Index: trunk/src/emx/include/386/builtin.h
===================================================================
--- trunk/src/emx/include/386/builtin.h	(revision 18)
+++ trunk/src/emx/include/386/builtin.h	(revision 18)
@@ -0,0 +1,90 @@
+/* 386/builtin.h (emx+gcc) */
+
+#ifndef _I386_BUILTIN_H
+#define _I386_BUILTIN_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+static __inline__ signed char __cxchg (__volatile__ signed char *p,
+                                       signed char v)
+{
+  __asm__ __volatile__ ("xchgb %0, %1" : "=m"(*p), "=r"(v) : "1"(v));
+  return v;
+}
+
+static __inline__ short __sxchg (__volatile__ short *p, short v)
+{
+  __asm__ __volatile__ ("xchgw %0, %1" : "=m"(*p), "=r"(v) : "1"(v));
+  return v;
+}
+
+static __inline__ int __lxchg (__volatile__ int *p, int v)
+{
+  __asm__ __volatile__ ("xchgl %0, %1" : "=m"(*p), "=r"(v) : "1"(v));
+  return v;
+}
+
+static __inline__ void __enable (void)
+{
+  __asm__ __volatile__ ("sti");
+}
+
+static __inline__ void __disable (void)
+{
+  __asm__ __volatile__ ("cli");
+}
+
+#define __ROTATE_FUN(F,I,T) \
+  static __inline__ T F (T value, int shift) \
+  { \
+    __asm__ (I " %b2, %0" : "=g"(value) : "0"(value), "c"(shift) : "cc"); \
+    return value; \
+  } \
+  static __inline__ T F##1 (T value) \
+  { \
+    __asm__ (I " $1, %0" : "=g"(value) : "0"(value) : "cc"); \
+    return value; \
+  }
+
+#define __ROTATE(V,S,F) ((__builtin_constant_p (S) && (int)(S) == 1) \
+                         ? F##1 (V) : F (V, S))
+
+__ROTATE_FUN (__crotr, "rorb", unsigned char)
+__ROTATE_FUN (__srotr, "rorw", unsigned short)
+__ROTATE_FUN (__lrotr, "rorl", unsigned long)
+
+__ROTATE_FUN (__crotl, "rolb", unsigned char)
+__ROTATE_FUN (__srotl, "rolw", unsigned short)
+__ROTATE_FUN (__lrotl, "roll", unsigned long)
+
+#define _crotr(V,S) __ROTATE (V, S, __crotr)
+#define _srotr(V,S) __ROTATE (V, S, __srotr)
+#define _lrotr(V,S) __ROTATE (V, S, __lrotr)
+#define _crotl(V,S) __ROTATE (V, S, __crotl)
+#define _srotl(V,S) __ROTATE (V, S, __srotl)
+#define _lrotl(V,S) __ROTATE (V, S, __lrotl)
+
+#define _rotr(V,S) _lrotr (V, S)
+#define _rotl(V,S) _lrotl (V, S)
+
+
+static __inline__ int __fls (int v)
+{
+  int r;
+
+  __asm__ __volatile__ ("bsrl %1, %0;"
+                        "jnz 1f;"
+                        "movl $-1, %0;"
+                        ".align 2, 0x90;"
+                        "1:"
+                        : "=r"(r) : "r"(v) : "cc");
+  return r + 1;
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _I386_BUILTIN_H */
Index: trunk/src/emx/include/386/endian.h
===================================================================
--- trunk/src/emx/include/386/endian.h	(revision 18)
+++ trunk/src/emx/include/386/endian.h	(revision 18)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1987, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)endian.h	7.8 (Berkeley) 4/3/91
+ *	$Id: endian.h,v 1.9 1994/02/12 07:23:49 cgd Exp $
+ */
+
+#ifndef _MACHINE_ENDIAN_H_
+#define _MACHINE_ENDIAN_H_
+
+/*
+ * Define the order of 32-bit words in 64-bit words.
+ */
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+
+
+#ifndef _POSIX_SOURCE
+/*
+ * Definitions for byte order, according to byte significance from low
+ * address to high.
+ */
+#define	LITTLE_ENDIAN	1234	/* LSB first: i386, vax */
+#define	BIG_ENDIAN	4321	/* MSB first: 68000, ibm, net */
+#define	PDP_ENDIAN	3412	/* LSB first in word, MSW first in long */
+
+#define	BYTE_ORDER	LITTLE_ENDIAN
+
+unsigned long   htonl(unsigned long);
+unsigned short  htons(unsigned short);
+unsigned long   ntohl(unsigned long);
+unsigned short  ntohs(unsigned short);
+
+#ifndef __EMX__
+
+#ifdef __GNUC__
+
+#if __GNUC__ >= 2
+
+#if defined(KERNEL) && ((defined(I486_CPU) || defined(I586_CPU)) && !defined(I386_CPU))
+#define __byte_swap_long(x) \
+({ register unsigned long __x = (x); \
+   asm ("bswap %1" \
+	: "=q" (__x) \
+	: "0" (__x)); \
+   __x; })
+#else
+#define __byte_swap_long(x) \
+({ register unsigned long __x = (x); \
+   asm ("xchgb %h1, %b1\n\trorl $16, %1\n\txchgb %h1, %b1" \
+	: "=q" (__x) \
+	: "0" (__x)); \
+   __x; })
+#endif	/* KERNEL && ... */
+#define __byte_swap_word(x) \
+({ register unsigned short __x = (x); \
+   asm ("xchgb %h1, %b1" \
+	: "=q" (__x) \
+	: "0" (__x)); \
+   __x; })
+
+#else	/* __GNUC__ >= 2 */
+
+#if defined(KERNEL) && ((defined(I486_CPU) || defined(I586_CPU)) && !defined(I386_CPU))
+#define __byte_swap_long(x) \
+({ register unsigned long __x = (x); \
+   asm ("bswap %1" \
+	: "=r" (__x) \
+	: "0" (__x)); \
+   __x; })
+#else
+#define __byte_swap_long(x) \
+({ register u_long __x = (x); \
+   asm ("rorw $8, %w1\n\trorl $16, %1\n\trorw $8, %w1" \
+	: "=r" (__x) \
+	: "0" (__x)); \
+   __x; })
+#endif	/* KERNEL && ... */
+#define __byte_swap_word(x) \
+({ register u_short __x = (x); \
+   asm ("rorw $8, %w1" \
+	: "=r" (__x) \
+	: "0" (__x)); \
+   __x; })
+
+#endif	/* __GNUC__ >= 2 */
+
+#define	ntohl(x)	__byte_swap_long(x)
+#define	ntohs(x)	__byte_swap_word(x)
+#define	htonl(x)	__byte_swap_long(x)
+#define	htons(x)	__byte_swap_word(x)
+
+#endif	/* __GNUC__ */
+
+#endif /* not __EMX__ */
+
+/*
+ * Macros for network/external number representation conversion.
+ */
+#define	NTOHL(x)	(x) = ntohl((u_long)x)
+#define	NTOHS(x)	(x) = ntohs((u_short)x)
+#define	HTONL(x)	(x) = htonl((u_long)x)
+#define	HTONS(x)	(x) = htons((u_short)x)
+
+#endif /* _POSIX_SOURCE */
+
+#endif /* _MACHINE_ENDIAN_H_ */
Index: trunk/src/emx/include/386/reg.h
===================================================================
--- trunk/src/emx/include/386/reg.h	(revision 18)
+++ trunk/src/emx/include/386/reg.h	(revision 18)
@@ -0,0 +1,27 @@
+/* 386/reg.h (emx+gcc) */
+
+#ifndef _I386_REG_H
+#define _I386_REG_H
+
+#define GS      0
+#define FS      1
+#define ES      2
+#define DS      3
+#define EDI     4
+#define ESI     5
+#define EBP     6
+#define ESP     7
+#define EBX     8
+#define EDX     9
+#define ECX    10
+#define EAX    11
+#define TRAPNO 12
+#define ERRCD  13
+#define EIP    14
+#define CS     15
+#define EFL    16
+#define UESP   17
+#define SS     18
+#define FP387  19   /* Floating point registers starting here */
+
+#endif /* not _I386_REG_H */
Index: trunk/src/emx/include/Attic/cpp/ACG.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/ACG.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/ACG.h	(revision 18)
@@ -0,0 +1,68 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _ACG_h
+#define _ACG_h 1 
+
+#include <RNG.h>
+#include <math.h>
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+//
+//	Additive number generator. This method is presented in Volume II
+//	of The Art of Computer Programming by Knuth. I've coded the algorithm
+//	and have added the extensions by Andres Nowatzyk of CMU to randomize
+//	the result of algorithm M a bit	by using an LCG & a spatial
+//	permutation table.
+//
+//	The version presented uses the same constants for the LCG that Andres
+//	uses (chosen by trial & error). The spatial permutation table is
+//	the same size (it's based on word size). This is for 32-bit words.
+//
+//	The ``auxillary table'' used by the LCG table varies in size, and
+//	is chosen to be the the smallest power of two which is larger than
+//	twice the size of the state table.
+//
+
+class ACG : public RNG {
+
+    _G_uint32_t initialSeed;	// used to reset generator
+    int initialTableEntry;
+
+    _G_uint32_t *state;
+    _G_uint32_t *auxState;
+    short stateSize;
+    short auxSize;
+    _G_uint32_t lcgRecurr;
+    short j;
+    short k;
+
+protected:
+
+public:
+    ACG(_G_uint32_t seed = 0, int size = 55);
+    virtual ~ACG();
+    //
+    // Return a long-words word of random bits
+    //
+    virtual _G_uint32_t asLong();
+    virtual void reset();
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/AllocRin.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/AllocRin.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/AllocRin.h	(revision 18)
@@ -0,0 +1,62 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1989 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _AllocRing_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _AllocRing_h 1
+
+
+/*
+  An AllocRing holds the last n malloc'ed strings, reallocating/reusing 
+  one only when the queue wraps around. It thus guarantees that the
+  last n allocations are intact. It is useful for things like I/O
+  formatting where reasonable restrictions may be made about the
+  number of allowable live allocations before auto-deletion.
+*/
+
+class AllocRing
+{
+
+  struct AllocQNode
+  {
+    void*  ptr;
+    int    sz;
+  };
+
+  AllocQNode* nodes;
+  int         n;
+  int         current;
+
+  int         find(void* p);
+
+public:
+
+              AllocRing(int max);
+             ~AllocRing();
+
+  void*       alloc(int size);
+  int         contains(void* ptr);
+  void        clear();
+  void        free(void* p);
+};
+
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Binomial.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Binomial.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Binomial.h	(revision 18)
@@ -0,0 +1,55 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _Binomial_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Binomial_h 1
+
+#include <Random.h>
+
+class Binomial: public Random {
+protected:
+    int pN;
+    double pU;
+public:
+    Binomial(int n, double u, RNG *gen);
+
+    int n();
+    int n(int xn);
+
+    double u();
+    double u(double xu);
+
+    virtual double operator()();
+
+};
+
+
+inline Binomial::Binomial(int n, double u, RNG *gen)
+: Random(gen){
+  pN = n; pU = u;
+}
+
+inline int Binomial::n() { return pN; }
+inline int Binomial::n(int xn) { int tmp = pN; pN = xn; return tmp; }
+
+inline double Binomial::u() { return pU; }
+inline double Binomial::u(double xu) { double tmp = pU; pU = xu; return tmp; }
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/BitSet.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/BitSet.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/BitSet.h	(revision 18)
@@ -0,0 +1,360 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _BitSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#define _BitSet_h 1
+
+#include <iostream.h>
+#include <limits.h>
+#include <bitprims.h>
+
+#undef OK
+
+#define BITSETBITS  (sizeof(_BS_word) * CHAR_BIT)
+
+struct BitSetRep
+{
+  unsigned short len;       // number of _BS_word in s
+  unsigned short sz;        // allocated slots
+  unsigned short virt;      // virtual 0 or 1
+  _BS_word  s[1];         // bits start here
+};
+
+extern BitSetRep*   BitSetalloc(BitSetRep*, const _BS_word*, 
+                                int, int, int);
+extern BitSetRep*   BitSetcopy(BitSetRep*, const BitSetRep*);
+extern BitSetRep*   BitSetresize(BitSetRep*, int);
+extern BitSetRep*   BitSetop(const BitSetRep*, const BitSetRep*, 
+                             BitSetRep*, char);
+extern BitSetRep*   BitSetcmpl(const BitSetRep*, BitSetRep*);
+extern BitSetRep    _nilBitSetRep;
+
+class BitSet;
+
+class BitSetBit
+{
+protected:
+  BitSet*            src;
+  unsigned long      pos;
+
+ public:
+                     BitSetBit(BitSet* v, int p);
+                     BitSetBit(const BitSetBit& b);
+                    ~BitSetBit();
+                     operator int() const;
+  int                operator = (int b);
+  int                operator = (const BitSetBit& b);
+};
+
+class BitSet
+{
+protected:
+  BitSetRep*          rep;
+
+  enum BS_op {
+    BS_and = (int) '&',
+    BS_or = (int) '|',
+    BS_xor = (int) '^',
+    BS_diff = (int) '-',
+    BS_inv = (int) '~'
+  };
+  BitSet(const BitSet& x, const BitSet& y, enum BS_op op)
+    { rep = BitSetop (x.rep, y.rep, NULL, (char) op);  }
+  BitSet(const BitSet& x, enum BS_op /* op */)
+    { rep = BitSetcmpl (x.rep, NULL); }
+
+public:
+
+// constructors
+                     BitSet();
+                     BitSet(const BitSet&);
+
+                    ~BitSet();
+
+  BitSet&            operator =  (const BitSet& y);
+
+// equality & subset tests
+
+  friend int         operator == (const BitSet& x, const BitSet& y);
+  friend int         operator != (const BitSet& x, const BitSet& y);
+  friend int         operator <  (const BitSet& x, const BitSet& y);
+  friend int         operator <= (const BitSet& x, const BitSet& y);
+  friend int         operator >  (const BitSet& x, const BitSet& y);
+  friend int         operator >= (const BitSet& x, const BitSet& y);
+  friend int	       lcompare(const BitSet& x, const BitSet& y);
+
+// operations on self
+
+  BitSet&            operator |= (const BitSet& y);
+  BitSet&            operator &= (const BitSet& y);
+  BitSet&            operator -= (const BitSet& y);
+  BitSet&            operator ^= (const BitSet& y);
+
+  void               complement();
+
+// functional operators
+
+  friend BitSet operator & (const BitSet& x, const BitSet& y);
+  friend BitSet operator | (const BitSet& x, const BitSet& y);
+  friend BitSet operator ^ (const BitSet& x, const BitSet& y);
+  friend BitSet operator - (const BitSet& x, const BitSet& y);
+  friend BitSet operator ~ (const BitSet& x);
+
+// individual bit manipulation
+
+  void               set(int pos);
+  void               set(int from, int to);
+  void               set(); // set all
+
+  void               clear(int pos);
+  void               clear(int from, int to);
+  void               clear(); // clear all
+
+  void               invert(int pos);
+  void               invert(int from, int to);
+
+  int                test(int pos) const;
+  int                test(int from, int to) const;
+
+  BitSetBit          operator [] (int i);
+  
+// iterators
+
+  int                first(int b = 1) const;
+  int                last(int b = 1) const;
+
+  int                next(int pos, int b = 1) const;
+  int                prev(int pos, int b = 1) const;
+  int                previous(int pos, int b = 1) const /* Obsolete synonym */
+    { return prev(pos, b); }
+
+// status
+
+  int                empty() const;
+  int                virtual_bit() const;
+  int                count(int b = 1) const;
+  
+// convertors & IO
+
+  friend BitSet      atoBitSet(const char* s, 
+                               char f='0', char t='1', char star='*');
+  // BitSettoa is deprecated; do not use in new programs.
+  friend const char* BitSettoa(const BitSet& x, 
+                               char f='0', char t='1', char star='*');
+
+  friend BitSet      shorttoBitSet(unsigned short w);
+  friend BitSet      longtoBitSet(unsigned long w);
+
+  friend ostream&    operator << (ostream& s, const BitSet& x);
+  void		     printon(ostream& s,
+			     char f='0', char t='1', char star='*') const;
+
+#ifndef __STRICT_ANSI__
+  // procedural versions of operators
+
+  // The first three of these are incompatible with ANSI C++ digraphs.
+  // In any case, it's not a great interface.
+  friend void        and(const BitSet& x, const BitSet& y, BitSet& r);
+  friend void        or(const BitSet& x, const BitSet& y, BitSet& r);
+  friend void        xor(const BitSet& x, const BitSet& y, BitSet& r);
+  friend void        diff(const BitSet& x, const BitSet& y, BitSet& r);
+  friend void        complement(const BitSet& x, BitSet& r);
+#endif
+
+// misc
+
+  void      error(const char* msg) const;
+  int                OK() const;
+};
+
+
+typedef BitSet BitSetTmp;
+
+// These are inlined regardless of optimization
+
+inline int BitSet_index(int l)
+{
+  return (unsigned)(l) / BITSETBITS;
+}
+
+inline int BitSet_pos(int l)
+{
+  return l & (BITSETBITS - 1);
+}
+
+inline BitSet::BitSet() : rep(&_nilBitSetRep) {}
+
+inline BitSet::BitSet(const BitSet& x) :rep(BitSetcopy(0, x.rep)) {}
+
+inline BitSet::~BitSet() { if (rep != &_nilBitSetRep) delete rep; }
+
+inline BitSet& BitSet::operator =  (const BitSet& y)
+{ 
+  rep = BitSetcopy(rep, y.rep);
+  return *this;
+}
+
+inline int operator != (const BitSet& x, const BitSet& y) { return !(x == y); }
+
+inline int operator >  (const BitSet& x, const BitSet& y) { return y < x; }
+
+inline int operator >= (const BitSet& x, const BitSet& y) { return y <= x; }
+
+#ifndef __STRICT_ANSI__
+inline void and(const BitSet& x, const BitSet& y, BitSet& r)
+{
+  r.rep =  BitSetop(x.rep, y.rep, r.rep, '&');
+}
+
+inline void or(const BitSet& x, const BitSet& y, BitSet& r)
+{
+  r.rep =  BitSetop(x.rep, y.rep, r.rep, '|');
+}
+
+inline void xor(const BitSet& x, const BitSet& y, BitSet& r)
+{
+  r.rep =  BitSetop(x.rep, y.rep, r.rep, '^');
+}
+
+inline void diff(const BitSet& x, const BitSet& y, BitSet& r)
+{
+  r.rep =  BitSetop(x.rep, y.rep, r.rep, '-');
+}
+
+inline void complement(const BitSet& x, BitSet& r)
+{
+  r.rep = BitSetcmpl(x.rep, r.rep);
+}
+#endif
+
+inline BitSet operator & (const BitSet& x, const BitSet& y) 
+{
+  return BitSet::BitSet(x, y, BitSet::BS_and);
+}
+
+inline BitSet operator | (const BitSet& x, const BitSet& y) 
+{
+  return BitSet::BitSet(x, y, BitSet::BS_or);
+}
+
+inline BitSet operator ^ (const BitSet& x, const BitSet& y) 
+{
+  return BitSet::BitSet(x, y, BitSet::BS_xor);
+}
+
+inline BitSet operator - (const BitSet& x, const BitSet& y) 
+{
+  return BitSet::BitSet(x, y, BitSet::BS_diff);
+}
+
+inline BitSet operator ~ (const BitSet& x) 
+{
+  return BitSet::BitSet(x, BitSet::BS_inv);
+}
+
+inline BitSet& BitSet::operator &= (const BitSet& y)
+{
+  rep =  BitSetop(rep, y.rep, rep, '&');
+  return *this;
+}
+
+inline BitSet& BitSet::operator |= (const BitSet& y)
+{
+  rep =  BitSetop(rep, y.rep, rep, '|');
+  return *this;
+}
+
+inline BitSet& BitSet::operator ^= (const BitSet& y)
+{
+  rep =  BitSetop(rep, y.rep, rep, '^');
+  return *this;
+}
+
+inline BitSet& BitSet::operator -= (const BitSet& y)
+{
+  rep =  BitSetop(rep, y.rep, rep, '-');
+  return *this;
+}
+
+
+inline void BitSet::complement()
+{
+  rep = BitSetcmpl(rep, rep);
+}
+
+inline int BitSet::virtual_bit() const
+{
+  return rep->virt;
+}
+
+inline int BitSet::first(int b) const
+{
+  return next(-1, b);
+}
+
+inline int BitSet::test(int p) const
+{
+  if (p < 0) error("Illegal bit index");
+  int index = BitSet_index(p);
+  return (index >= rep->len)? rep->virt : 
+         ((rep->s[index] & ((_BS_word)1 << BitSet_pos(p))) != 0);
+}
+
+
+inline void BitSet::set()
+{
+  rep = BitSetalloc(rep, 0, 0, 1, 0);
+}
+
+inline BitSetBit::BitSetBit(const BitSetBit& b) :src(b.src), pos(b.pos) {}
+
+inline BitSetBit::BitSetBit(BitSet* v, int p)
+{
+  src = v;  pos = p;
+}
+
+inline BitSetBit::~BitSetBit() {}
+
+inline BitSetBit::operator int() const
+{
+  return src->test(pos);
+}
+
+inline int BitSetBit::operator = (int b)
+{
+  if (b) src->set(pos); else src->clear(pos); return b;
+}
+
+inline int BitSetBit::operator = (const BitSetBit& b)
+{
+  int i = (int)b;
+  *this = i;
+  return i;
+}
+
+inline BitSetBit BitSet::operator [] (int i)
+{
+  if (i < 0) error("illegal bit index");
+  return BitSetBit(this, i);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/BitStrin.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/BitStrin.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/BitStrin.h	(revision 18)
@@ -0,0 +1,763 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _BitString_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#define _BitString_h 1
+
+#include <stream.h>
+#include <limits.h>
+
+#undef OK
+
+#include <bitprims.h>
+#define BITSTRBITS  _BS_BITS_PER_WORD
+
+struct BitStrRep
+{
+  unsigned int    len;          // length in bits
+  unsigned short  sz;           // allocated slots
+  _BS_word        s[1];         // bits start here
+};
+
+extern BitStrRep*  BStr_alloc(BitStrRep*, const _BS_word*, int, int,int);
+extern BitStrRep*  BStr_resize(BitStrRep*, int);
+extern BitStrRep*  BStr_copy(BitStrRep*, const BitStrRep*);
+extern BitStrRep*  cmpl(const BitStrRep*, BitStrRep*);
+extern BitStrRep*  and(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep*  or(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep*  xor(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep*  diff(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep*  cat(const BitStrRep*, const BitStrRep*, BitStrRep*);
+extern BitStrRep*  cat(const BitStrRep*, unsigned int, BitStrRep*);
+extern BitStrRep*  lshift(const BitStrRep*, int, BitStrRep*);
+
+
+class BitString;
+class BitPattern;
+
+class BitStrBit
+{
+protected:
+  BitString&        src;
+  unsigned int      pos;
+
+ public:
+                    BitStrBit(BitString& v, int p);
+                    BitStrBit(const BitStrBit& b);
+                   ~BitStrBit();
+                    operator unsigned int() const;
+  int               operator =  (unsigned int b);
+};
+
+class BitSubString
+{
+  friend class      BitString;
+  friend class      BitPattern;
+
+protected:
+
+  BitString&        S;
+  unsigned int      pos;
+  unsigned int      len;
+
+                    BitSubString(BitString& x, int p, int l);
+                    BitSubString(const BitSubString& x);
+public:
+                    ~BitSubString();
+
+  BitSubString&     operator =  (const BitString&);
+  BitSubString&     operator =  (const BitSubString&);
+
+  int               length() const;
+  int               empty() const;
+
+  int               OK() const;
+};
+
+class BitString
+{
+  friend class       BitSubString;
+  friend class       BitPattern;
+protected:
+  BitStrRep*         rep;
+
+  int                search(int, int, const _BS_word*, int, int) const;
+  int                match(int, int, int, const _BS_word*,int,int) const;
+  BitSubString       _substr(int first, int l);
+
+public:
+
+// constructors
+                     BitString();
+                     BitString(const BitString&);
+                     BitString(const BitSubString& y);
+
+                    ~BitString();
+
+  BitString&         operator =  (unsigned int bit);
+  BitString&         operator =  (const BitString& y);
+  BitString&         operator =  (const BitSubString& y);
+
+// equality & subset tests
+
+  friend int         operator == (const BitString&, const BitString&);
+  friend int         operator != (const BitString&, const BitString&);
+  friend int         operator <  (const BitString&, const BitString&);
+  friend int         operator <= (const BitString&, const BitString&);
+  friend int         operator >  (const BitString&, const BitString&);
+  friend int         operator >= (const BitString&, const BitString&);
+
+// procedural versions of operators
+
+
+  friend void        and(const BitString&, const BitString&, BitString&);
+  friend void        or(const BitString&, const BitString&, BitString&);
+  friend void        xor(const BitString&, const BitString&, BitString&);
+  friend void        diff(const BitString&, const BitString&, BitString&);
+  friend void        cat(const BitString&, const BitString&, BitString&);
+  friend void        cat(const BitString&, unsigned int, BitString&);
+  friend void        lshift(const BitString&, int, BitString&);
+  friend void        rshift(const BitString&, int, BitString&);
+
+  friend void        complement(const BitString&, BitString&);
+
+  friend int         lcompare(const BitString&, const BitString&); 
+
+// assignment-based operators
+// (constuctive versions decalred inline below
+
+  BitString&         operator |= (const BitString&);
+  BitString&         operator &= (const BitString&);
+  BitString&         operator -= (const BitString&);
+  BitString&         operator ^= (const BitString&);
+  BitString&         operator += (const BitString&);
+  BitString&         operator += (unsigned int b);
+  BitString&         operator <<=(int s);
+  BitString&         operator >>=(int s);
+
+  void               complement();
+
+// individual bit manipulation
+
+  void               set(int pos);
+  void               set(int from, int to);
+  void               set();
+
+  void               clear(int pos);
+  void               clear(int from, int to);
+  void               clear(); 
+
+  void               invert(int pos);
+  void               invert(int from, int to);
+
+  int                test(int pos) const;
+  int                test(int from, int to) const;
+
+  void               assign(int p, unsigned int bit);
+
+// indexing
+
+  BitStrBit          operator [] (int pos);
+
+// iterators
+
+  int                first(unsigned int bit = 1) const;
+  int                last(unsigned int b = 1) const;
+
+  int                next(int pos, unsigned int b = 1) const;
+  int                prev(int pos, unsigned int b = 1) const;
+  int                previous(int pos, unsigned int b = 1) const
+    { return prev(pos, b); } /* Obsolete synonym */
+
+// searching & matching
+
+  int                index(unsigned int bit, int startpos = 0) const ;      
+  int                index(const BitString&, int startpos = 0) const;
+  int                index(const BitSubString&, int startpos = 0) const;
+  int                index(const BitPattern&, int startpos = 0) const;
+
+  int                contains(const BitString&) const;
+  int                contains(const BitSubString&) const;
+  int                contains(const BitPattern&) const;
+
+  int                contains(const BitString&, int pos) const;
+  int                contains(const BitSubString&, int pos) const;
+  int                contains(const BitPattern&, int pos) const;
+
+  int                matches(const BitString&, int pos = 0) const;
+  int                matches(const BitSubString&, int pos = 0) const;
+  int                matches(const BitPattern&, int pos = 0) const;
+
+// BitSubString extraction
+
+  BitSubString       at(int pos, int len);
+  BitSubString       at(const BitString&, int startpos = 0); 
+  BitSubString       at(const BitSubString&, int startpos = 0); 
+  BitSubString       at(const BitPattern&, int startpos = 0); 
+
+  BitSubString       before(int pos);
+  BitSubString       before(const BitString&, int startpos = 0);
+  BitSubString       before(const BitSubString&, int startpos = 0);
+  BitSubString       before(const BitPattern&, int startpos = 0);
+
+  BitSubString       after(int pos);
+  BitSubString       after(const BitString&, int startpos = 0);
+  BitSubString       after(const BitSubString&, int startpos = 0);
+  BitSubString       after(const BitPattern&, int startpos = 0);
+
+// other friends & utilities
+
+  friend BitString   common_prefix(const BitString&, const BitString&, 
+                                   int pos = 0);
+  friend BitString   common_suffix(const BitString&, const BitString&, 
+                                   int pos = -1);
+  friend BitString   reverse(const BitString&);
+
+  void               right_trim(unsigned int bit);
+  void               left_trim(unsigned int bit);
+
+// status
+
+  int                empty() const ;
+  int                count(unsigned int bit = 1) const;
+  int                length() const;
+
+// convertors & IO
+
+  friend BitString   atoBitString(const char* s, char f='0', char t='1');
+  // BitStringtoa is deprecated; do not use in new programs!
+  friend const char* BitStringtoa(const BitString&, char f='0', char t='1');
+  void		     printon(ostream&, char f='0', char t='1') const;
+
+  friend BitString   shorttoBitString(unsigned short);
+  friend BitString   longtoBitString(unsigned long);
+
+  friend ostream&    operator << (ostream& s, const BitString&);
+
+// misc
+
+  void      error(const char* msg) const;
+
+// indirect friends
+
+  friend BitPattern  atoBitPattern(const char* s,
+                                  char f='0',char t='1',char x='X');
+  friend const char* BitPatterntoa(const BitPattern& p, 
+                                  char f='0',char t='1',char x='X');
+  int                OK() const;
+};
+
+
+class BitPattern
+{
+public:
+  BitString          pattern;
+  BitString          mask;
+
+                     BitPattern();
+                     BitPattern(const BitPattern&);
+                     BitPattern(const BitString& p, const BitString& m);
+
+                    ~BitPattern();
+
+  friend const char* BitPatterntoa(const BitPattern& p, 
+                                 char f/*='0'*/,char t/*='1'*/,char x/*='X'*/);
+  void		     printon(ostream&, char f='0',char t='1',char x='X') const;
+  friend BitPattern atoBitPattern(const char* s, char f,char t, char x);
+  friend ostream&   operator << (ostream& s, const BitPattern&);
+
+  int               search(const _BS_word*, int, int) const;
+  int               match(const _BS_word* xs, int, int, int) const;
+
+  int               OK() const;
+};
+
+BitString  operator & (const BitString& x, const BitString& y);
+BitString  operator | (const BitString& x, const BitString& y);
+BitString  operator ^ (const BitString& x, const BitString& y);
+BitString  operator << (const BitString& x, int y);
+BitString  operator >> (const BitString& x, int y);
+BitString  operator - (const BitString& x, const BitString& y);
+BitString  operator + (const BitString& x, const BitString& y);
+BitString  operator + (const BitString& x, unsigned int y);
+BitString  operator ~ (const BitString& x);
+int operator != (const BitString& x, const BitString& y);
+int operator>(const BitString& x, const BitString& y);
+int operator>=(const BitString& x, const BitString& y);
+
+extern BitStrRep    _nilBitStrRep;
+extern BitString    _nil_BitString;
+
+// primitive bit extraction
+
+// These must be inlined regardless of optimization.
+
+inline int BitStr_index(int l) { return (unsigned)(l) / BITSTRBITS; }
+
+inline int BitStr_pos(int l) { return l & (BITSTRBITS - 1); }
+
+
+// constructors & assignment
+
+inline BitString::BitString() :rep(&_nilBitStrRep) {}
+
+inline BitString::BitString(const BitString& x) :rep(BStr_copy(0, x.rep)) {}
+
+inline BitString::BitString(const BitSubString& y) 
+   :rep (BStr_alloc(0, y.S.rep->s, y.pos, y.pos+y.len, y.len)) {}
+
+inline BitString::~BitString()
+{ 
+  if (rep != &_nilBitStrRep) delete rep;
+}
+
+inline BitString shorttoBitString(unsigned short w) 
+{ 
+  BitString r;
+  _BS_word ww = w;
+#if _BS_BIGENDIAN
+  abort();
+#endif
+  r.rep = BStr_alloc(0, &ww, 0, 8 * sizeof(short), 8 * sizeof(short));
+  return r;
+}
+
+inline BitString longtoBitString(unsigned long w) 
+{ 
+  BitString r;
+#if 1
+  _BS_word u = w;
+  r.rep = BStr_alloc(0, &u, 0, BITSTRBITS, BITSTRBITS);
+#else
+  unsigned short u[2];
+  u[0] = w & ((unsigned short)(~(0)));
+  u[1] = w >> BITSTRBITS;
+  r.rep = BStr_alloc(0, &u[0], 0, 2*BITSTRBITS, 2*BITSTRBITS);
+#endif
+  return r;
+}
+
+inline BitString& BitString::operator =  (const BitString& y)
+{ 
+  rep = BStr_copy(rep, y.rep);
+  return *this;
+}
+
+inline BitString& BitString::operator = (unsigned int b)
+{ 
+  _BS_word bit = b;
+  rep = BStr_alloc(rep, &bit, 0, 1, 1);
+  return *this;
+}
+
+inline BitString&  BitString::operator=(const BitSubString&  y)
+{
+  rep = BStr_alloc(rep, y.S.rep->s, y.pos, y.pos+y.len, y.len);
+  return *this;
+}
+
+inline BitSubString::BitSubString(const BitSubString& x) 
+    :S(x.S), pos(x.pos), len(x.len) {}
+
+inline BitSubString::BitSubString(BitString& x, int p, int l)
+     : S(x), pos(p), len(l) {}
+
+inline BitSubString::~BitSubString() {}
+
+inline BitPattern::BitPattern(const BitString& p, const BitString& m)
+    :pattern(p), mask(m) {}
+
+inline BitPattern::BitPattern(const BitPattern& b)
+    :pattern(b.pattern), mask(b.mask) {}
+
+inline BitPattern::BitPattern() {}
+inline BitPattern::~BitPattern() {}
+
+
+// procedural versions of operators
+
+inline void and(const BitString& x, const BitString& y, BitString& r)
+{
+  r.rep = and(x.rep, y.rep, r.rep);
+}
+
+inline void or(const BitString& x, const BitString& y, BitString& r)
+{
+  r.rep = or(x.rep, y.rep, r.rep);
+}
+
+inline void xor(const BitString& x, const BitString& y, BitString& r)
+{
+  r.rep = xor(x.rep, y.rep, r.rep);
+}
+
+inline void diff(const BitString& x, const BitString& y, BitString& r)
+{
+  r.rep = diff(x.rep, y.rep, r.rep);
+}
+
+inline void cat(const BitString& x, const BitString& y, BitString& r)
+{
+  r.rep = cat(x.rep, y.rep, r.rep);
+}
+
+inline void cat(const BitString& x, unsigned int y, BitString& r)
+{
+  r.rep = cat(x.rep, y, r.rep);
+}
+
+inline void rshift(const BitString& x, int y, BitString& r)
+{
+  r.rep = lshift(x.rep, -y, r.rep);
+}
+
+inline void lshift(const BitString& x, int y, BitString& r)
+{
+  r.rep = lshift(x.rep, y, r.rep);
+}
+
+inline void complement(const BitString& x, BitString& r)
+{
+  r.rep = cmpl(x.rep, r.rep);
+}
+
+// operators
+
+
+inline BitString& BitString::operator &= (const BitString& y)
+{
+  and(*this, y, *this);
+  return *this;
+}
+
+
+inline BitString& BitString::operator |= (const BitString& y)
+{
+  or(*this, y, *this);
+  return *this;
+}
+
+inline BitString& BitString::operator ^= (const BitString& y)
+{
+  xor(*this, y, *this);
+  return *this;
+}
+
+inline BitString& BitString::operator <<= (int y)
+{
+  lshift(*this, y, *this);
+  return *this;
+}
+
+inline BitString& BitString::operator >>= (int y)
+{
+  rshift(*this, y, *this);
+  return *this;
+}
+
+inline BitString& BitString::operator -= (const BitString& y)
+{
+  diff(*this, y, *this);
+  return *this;
+}
+
+inline BitString& BitString::operator += (const BitString& y)
+{
+  cat(*this, y, *this);
+  return *this;
+}
+
+inline BitString& BitString::operator += (unsigned int y)
+{
+  cat(*this, y, *this);
+  return *this;
+}
+
+inline void BitString::complement()
+{
+  ::complement(*this, *this);
+}
+
+#if defined(__GNUG__) && !defined(_G_NO_NRV)
+
+inline BitString  operator & (const BitString& x, const BitString& y) return r
+{
+  and(x, y, r);
+}
+
+inline BitString  operator | (const BitString& x, const BitString& y) return r
+{
+  or(x, y, r);
+}
+
+inline BitString  operator ^ (const BitString& x, const BitString& y) return r
+{
+  xor(x, y, r);
+}
+
+inline BitString  operator << (const BitString& x, int y) return r
+{
+  lshift(x, y, r);
+}
+
+inline BitString  operator >> (const BitString& x, int y) return r
+{
+  rshift(x, y, r);
+}
+
+inline BitString  operator - (const BitString& x, const BitString& y) return r
+{
+  diff(x, y, r);
+}
+
+inline BitString  operator + (const BitString& x, const BitString& y) return r
+{
+  cat(x, y, r);
+}
+
+inline BitString  operator + (const BitString& x, unsigned int y) return r
+{
+  cat(x, y, r);
+}
+
+inline BitString  operator ~ (const BitString& x) return r
+{
+  complement(x, r);
+}
+
+#else /* NO_NRV */
+
+inline BitString  operator & (const BitString& x, const BitString& y) 
+{
+  BitString r; and(x, y, r); return r;
+}
+
+inline BitString  operator | (const BitString& x, const BitString& y) 
+{
+  BitString r; or(x, y, r); return r;
+}
+
+inline BitString  operator ^ (const BitString& x, const BitString& y) 
+{
+  BitString r; xor(x, y, r); return r;
+}
+
+inline BitString  operator << (const BitString& x, int y) 
+{
+  BitString r; lshift(x, y, r); return r;
+}
+
+inline BitString  operator >> (const BitString& x, int y) 
+{
+  BitString r; rshift(x, y, r); return r;
+}
+
+inline BitString  operator - (const BitString& x, const BitString& y) 
+{
+  BitString r; diff(x, y, r); return r;
+}
+
+inline BitString  operator + (const BitString& x, const BitString& y) 
+{
+  BitString r; cat(x, y, r); return r;
+}
+
+inline BitString  operator + (const BitString& x, unsigned int y) 
+{
+  BitString r; cat(x, y, r); return r;
+}
+
+inline BitString  operator ~ (const BitString& x) 
+{
+  BitString r; complement(x, r); return r;
+}
+
+#endif
+
+// status, matching
+
+inline int BitString::length() const
+{ 
+  return rep->len;
+}
+
+inline int BitString::empty() const
+{ 
+  return rep->len == 0;
+}
+
+inline int BitString::index(const BitString& y, int startpos) const
+{   
+  return search(startpos, rep->len, y.rep->s, 0, y.rep->len);
+}
+
+inline int BitString::index(const BitSubString& y, int startpos) const
+{   
+  return search(startpos, rep->len, y.S.rep->s, y.pos, y.pos+y.len);
+}
+
+inline int BitString::contains(const BitString& y) const
+{   
+  return search(0, rep->len, y.rep->s, 0, y.rep->len) >= 0;
+}
+
+inline int BitString::contains(const BitSubString& y) const
+{   
+  return search(0, rep->len, y.S.rep->s, y.pos, y.pos+y.len) >= 0;
+}
+
+inline int BitString::contains(const BitString& y, int p) const
+{
+  return match(p, rep->len, 0, y.rep->s, 0, y.rep->len);
+}
+
+inline int BitString::matches(const BitString& y, int p) const
+{
+  return match(p, rep->len, 1, y.rep->s, 0, y.rep->len);
+}
+
+inline int BitString::contains(const BitSubString& y, int p) const
+{
+  return match(p, rep->len, 0, y.S.rep->s, y.pos, y.pos+y.len);
+}
+
+inline int BitString::matches(const BitSubString& y, int p) const
+{
+  return match(p, rep->len, 1, y.S.rep->s, y.pos, y.pos+y.len);
+}
+
+inline int BitString::contains(const BitPattern& r) const
+{
+  return r.search(rep->s, 0, rep->len) >= 0;
+}
+
+inline int BitString::contains(const BitPattern& r, int p) const
+{
+  return r.match(rep->s, p, rep->len, 0);
+}
+
+inline int BitString::matches(const BitPattern& r, int p) const
+{
+  return r.match(rep->s, p, rep->len, 1);
+}
+
+inline int BitString::index(const BitPattern& r, int startpos) const
+{
+  return r.search(rep->s, startpos, rep->len);
+}
+
+inline  int BitSubString::length() const
+{ 
+  return len;
+}
+
+inline  int BitSubString::empty() const
+{ 
+  return len == 0;
+}
+
+inline int operator != (const BitString& x, const BitString& y)
+{
+  return !(x == y);
+}
+
+inline int operator>(const BitString& x, const BitString& y)
+{
+  return y < x;
+}
+
+inline int operator>=(const BitString& x, const BitString& y)
+{
+  return y <= x;
+}
+
+inline int BitString::first(unsigned int b) const
+{
+  return next(-1, b);
+}
+
+inline int BitString::last(unsigned int b) const
+{
+  return prev(rep->len, b);
+}
+
+inline int BitString::index(unsigned int bit, int startpos) const
+{
+  if (startpos >= 0)
+    return next(startpos - 1, bit);
+  else
+    return prev(rep->len + startpos + 1, bit);
+}
+
+inline void BitString::right_trim(unsigned int b) 
+{
+  int nb = (b == 0)? 1 : 0;
+  rep = BStr_resize(rep, prev(rep->len, nb) + 1);
+}
+
+inline void BitString::left_trim(unsigned int b)
+{
+  int nb = (b == 0)? 1 : 0;
+  int p = next(-1, nb);
+  rep = BStr_alloc(rep, rep->s, p, rep->len, rep->len - p);
+}
+
+inline int BitString::test(int i) const
+{
+  return ((unsigned)(i) >= rep->len)? 0 : 
+         ((rep->s[BitStr_index(i)] & (1 << (BitStr_pos(i)))) != 0);
+}
+
+
+// subscripting
+
+inline BitStrBit::BitStrBit(const BitStrBit& b) :src(b.src), pos(b.pos) {}
+
+inline BitStrBit::BitStrBit(BitString& v, int p) :src(v), pos(p) {}
+
+inline BitStrBit::~BitStrBit() {}
+
+inline BitStrBit::operator unsigned int() const
+{
+  return src.test(pos);
+}
+
+inline int BitStrBit::operator = (unsigned int b)
+{
+  src.assign(pos, b); return b;
+}
+
+inline BitStrBit BitString::operator [] (int i)
+{
+  if ((unsigned)(i) >= rep->len) error("illegal bit index");
+  return BitStrBit(*this, i);
+}
+
+inline BitSubString BitString::_substr(int first, int l)
+{
+  if (first < 0 || l <= 0 || (unsigned)(first + l) > rep->len)
+    return BitSubString(_nil_BitString, 0, 0) ;
+  else 
+    return BitSubString(*this, first, l);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Complx.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Complx.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Complx.h	(revision 18)
@@ -0,0 +1,10 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+#ifndef _Complex_h
+#define _Complex_h
+
+// Use the ANSI complex number template.
+#include <complex>
+typedef complex<double> Complex;
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/CursesW.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/CursesW.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/CursesW.h	(revision 18)
@@ -0,0 +1,603 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+/* 
+Copyright (C) 1989 Free Software Foundation
+    written by Eric Newton (newton@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _CursesWindow_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _CursesWindow_h
+
+#include   <_G_confi.h>
+
+#if defined(__bsdi__) || defined(__NetBSD__) || defined(__FreeBSD__)
+#define _begx begx
+#define _begy begy
+#define _maxx maxx
+#define _maxy maxy
+#endif
+
+#if _G_HAVE_CURSES
+// Even many system which mostly have C++-ready header files,
+// do not have C++-ready curses.h.
+extern "C" {
+#include   <curses.h>
+}
+
+/* SCO 3.2v4 curses.h includes term.h, which defines lines as a macro.
+   Undefine it here, because CursesWindow uses lines as a method.  */
+#undef lines
+
+// "Convert" macros to inlines, if needed.
+#ifdef addch
+inline int (addch)(char ch)  { return addch(ch); }
+#undef addch
+#endif
+#ifdef addstr
+/* The (char*) cast is to hack around missing const's */
+inline int (addstr)(const char * str)  { return addstr((char*)str); }
+#undef addstr
+#endif
+#ifdef clear
+inline int (clear)()  { return clear(); }
+#undef clear
+#endif
+#ifdef clearok
+inline int (clearok)(WINDOW* win, int bf)  { return clearok(win, bf); }
+#undef clearok
+#else
+extern "C" int clearok(WINDOW*, int);
+#endif
+#ifdef clrtobot
+inline int (clrtobot)()  { return clrtobot(); }
+#undef clrtobot
+#endif
+#ifdef clrtoeol
+inline int (clrtoeol)()  { return clrtoeol(); }
+#undef clrtoeol
+#endif
+#ifdef delch
+inline int (delch)()  { return delch(); }
+#undef delch
+#endif
+#ifdef deleteln
+inline int (deleteln)()  { return deleteln(); }
+#undef deleteln
+#endif
+#ifdef erase
+inline int (erase)()  { return erase(); }
+#undef erase
+#endif
+#ifdef flushok
+inline int (flushok)(WINDOW* _win, int _bf)  { return flushok(_win, _bf); }
+#undef flushok
+#else
+#define _no_flushok
+#endif
+#ifdef getch
+inline int (getch)()  { return getch(); }
+#undef getch
+#endif
+#ifdef getstr
+inline int (getstr)(char *_str)  { return getstr(_str); }
+#undef getstr
+#endif
+#ifdef getyx
+inline void (getyx)(WINDOW* win, int& y, int& x) { getyx(win, y, x); }
+#undef getyx
+#endif
+#ifdef inch
+inline int (inch)()  { return inch(); }
+#undef inch
+#endif
+#ifdef insch
+inline int (insch)(char c)  { return insch(c); }
+#undef insch
+#endif
+#ifdef insertln
+inline int (insertln)()  { return insertln(); }
+#undef insertln
+#endif
+#ifdef leaveok
+inline int (leaveok)(WINDOW* win, int bf)  { return leaveok(win, bf); }
+#undef leaveok
+#else
+extern "C" int leaveok(WINDOW* win, int bf);
+#endif
+#ifdef move
+inline int (move)(int x, int y)  { return move(x, y); }
+#undef move
+#endif
+#ifdef refresh
+inline int (rfresh)()  { return refresh(); }
+#undef refresh
+#endif
+#ifdef scrollok
+inline int (scrollok)(WINDOW* win, int bf)  { return scrollok(win, bf); }
+#undef scrollok
+#else
+#ifndef hpux
+extern "C" int scrollok(WINDOW*, int);
+#else
+extern "C" int scrollok(WINDOW*, char);
+#endif
+#endif
+#ifdef standend
+inline int (standend)()  { return standend(); }
+#undef standend
+#endif
+#ifdef standout
+inline int (standout)()  { return standout(); }
+#undef standout
+#endif
+#ifdef wstandend
+inline int (wstandend)(WINDOW *win)  { return wstandend(win); }
+#undef wstandend
+#endif
+#ifdef wstandout
+inline int (wstandout)(WINDOW *win)  { return wstandout(win); }
+#undef wstandout
+#endif
+#ifdef winch
+inline int (winch)(WINDOW* win) { return winch(win); }
+#undef winch
+#endif
+
+/* deal with conflicting macros in ncurses.h  which is SYSV based*/
+#ifdef box
+inline int _G_box(WINDOW* win, chtype v, chtype h) {return box(win, v, h); }
+#undef box
+inline int box(WINDOW* win, chtype v, chtype h) {return _G_box(win, v, h); }
+#endif
+#ifdef scroll
+inline int (scroll)(WINDOW* win) { return scroll(win); }
+#undef scroll
+#endif
+#ifdef touchwin
+inline int (touchwin)(WINDOW* win) { return touchwin(win); }
+#undef touchwin
+#endif
+
+#ifdef mvwaddch
+inline int (mvwaddch)(WINDOW *win, int y, int x, char ch)
+{ return mvwaddch(win, y, x, ch); }
+#undef mvwaddch
+#endif
+#ifdef mvwaddstr
+inline int (mvwaddstr)(WINDOW *win, int y, int x, const char * str)
+{ return mvwaddstr(win, y, x, (char*)str); }
+#undef mvwaddstr
+#endif
+#ifdef mvwdelch
+inline int (mvwdelch)(WINDOW *win, int y, int x) { return mvwdelch(win, y, x);}
+#undef mvwdelch
+#endif
+#ifdef mvwgetch
+inline int (mvwgetch)(WINDOW *win, int y, int x) { return mvwgetch(win, y, x);}
+#undef mvwgetch
+#endif
+#ifdef mvwgetstr
+inline int (mvwgetstr)(WINDOW *win, int y, int x, char *str)
+{return mvwgetstr(win,y,x, str);}
+#undef mvwgetstr
+#endif
+#ifdef mvwinch
+inline int (mvwinch)(WINDOW *win, int y, int x) { return mvwinch(win, y, x);}
+#undef mvwinch
+#endif
+#ifdef mvwinsch
+inline int (mvwinsch)(WINDOW *win, int y, int x, char c)
+{ return mvwinsch(win, y, x, c); }
+#undef mvwinsch
+#endif
+
+#ifdef mvaddch
+inline int (mvaddch)(int y, int x, char ch)
+{ return mvaddch(y, x, ch); }
+#undef mvaddch
+#endif
+#ifdef mvaddstr
+inline int (mvaddstr)(int y, int x, const char * str)
+{ return mvaddstr(y, x, (char*)str); }
+#undef mvaddstr
+#endif
+#ifdef mvdelch
+inline int (mvdelch)(int y, int x) { return mvdelch(y, x);}
+#undef mvdelch
+#endif
+#ifdef mvgetch
+inline int (mvgetch)(int y, int x) { return mvgetch(y, x);}
+#undef mvgetch
+#endif
+#ifdef mvgetstr
+inline int (mvgetstr)(int y, int x, char *str) {return mvgetstr(y, x, str);}
+#undef mvgetstr
+#endif
+#ifdef mvinch
+inline int (mvinch)(int y, int x) { return mvinch(y, x);}
+#undef mvinch
+#endif
+#ifdef mvinsch
+inline int (mvinsch)(int y, int x, char c)
+{ return mvinsch(y, x, c); }
+#undef mvinsch
+#endif
+
+/*
+ *
+ * C++ class for windows.
+ *
+ *
+ */
+
+class CursesWindow 
+{
+protected:
+  static int     count;           // count of all active windows:
+                                  //   We rely on the c++ promise that
+                                  //   all otherwise uninitialized
+                                  //   static class vars are set to 0
+
+  WINDOW *       w;               // the curses WINDOW
+
+  int            alloced;         // true if we own the WINDOW
+
+  CursesWindow*  par;             // parent, if subwindow
+  CursesWindow*  subwins;         // head of subwindows list
+  CursesWindow*  sib;             // next subwindow of parent
+
+  void           kill_subwindows(); // disable all subwindows
+
+public:
+                 CursesWindow(WINDOW* &window);   // useful only for stdscr
+
+                 CursesWindow(int lines,          // number of lines
+                              int cols,           // number of columns
+                              int begin_y,        // line origin
+                              int begin_x);       // col origin
+
+                 CursesWindow(CursesWindow& par,  // parent window
+                              int lines,          // number of lines
+                              int cols,           // number of columns
+                              int by,             // absolute or relative
+                              int bx,             //   origins:
+                              char absrel = 'a'); // if `a', by & bx are
+                                                  // absolute screen pos,
+                                                  // else if `r', they are
+                                                  // relative to par origin
+                ~CursesWindow();
+
+// terminal status
+  int            lines(); // number of lines on terminal, *not* window
+  int            cols();  // number of cols  on terminal, *not* window
+
+// window status
+  int            height(); // number of lines in this window
+  int            width();  // number of cols in this window
+  int            begx();   // smallest x coord in window
+  int            begy();   // smallest y coord in window
+  int            maxx();   // largest  x coord in window
+  int            maxy();   // largest  x coord in window
+
+// window positioning
+  int            move(int y, int x);
+
+// coordinate positioning
+  void           getyx(int& y, int& x);
+  int            mvcur(int sy, int ey, int sx, int ex);
+
+// input
+  int            getch();
+  int            getstr(char * str);
+  int            scanw(const char *, ...);
+
+// input + positioning
+  int            mvgetch(int y, int x);
+  int            mvgetstr(int y, int x, char * str);
+  int            mvscanw(int, int, const char*, ...);
+
+// output
+  int            addch(const char ch);
+  int            addstr(const char * str);
+  int            printw(const char * fmt, ...);
+  int            inch();
+  int            insch(char c);
+  int            insertln();
+
+// output + positioning
+  int            mvaddch(int y, int x, char ch);
+  int            mvaddstr(int y, int x, const char * str);
+  int            mvprintw(int y, int x, const char * fmt, ...);
+  int            mvinch(int y, int x);
+  int            mvinsch(int y, int x, char ch);
+
+// borders
+  int            box(char vert, char  hor);
+
+// erasure
+  int            erase();
+  int            clear();
+  int            clearok(int bf);
+  int            clrtobot();
+  int            clrtoeol();
+  int            delch();
+  int            mvdelch(int y, int x);
+  int            deleteln();
+
+// screen control
+  int            scroll();
+  int            scrollok(int bf);
+  int            touchwin();
+  int            refresh();
+  int            leaveok(int bf);
+#ifndef _no_flushok
+  int            flushok(int bf);
+#endif
+  int            standout();
+  int            standend();
+
+// multiple window control
+  int            overlay(CursesWindow &win);
+  int            overwrite(CursesWindow &win);
+
+
+// traversal support
+  CursesWindow*  child();
+  CursesWindow*  sibling();
+  CursesWindow*  parent();
+};
+
+
+inline int CursesWindow::begx()
+{
+  return w->_begx;
+}
+
+inline int CursesWindow::begy()
+{
+  return w->_begy;
+}
+
+inline int CursesWindow::maxx()
+{
+  return w->_maxx;
+}
+
+inline int CursesWindow::maxy()
+{
+  return w->_maxy;
+}
+
+inline int CursesWindow::height()
+{
+  return maxy() - begy() + 1;
+}
+
+inline int CursesWindow::width()
+{
+  return maxx() - begx() + 1;
+}
+
+inline int CursesWindow::box(char vert, char  hor)    
+{
+  return ::box(w, vert, hor); 
+}
+
+inline int CursesWindow::overlay(CursesWindow &win)         
+{
+  return ::overlay(w, win.w); 
+}
+
+inline int CursesWindow::overwrite(CursesWindow &win)       
+{
+  return ::overwrite(w, win.w); 
+}
+
+inline int CursesWindow::scroll()                     
+{
+  return ::scroll(w); 
+}
+
+
+inline int CursesWindow::touchwin()                   
+{
+  return ::touchwin(w); 
+}
+
+inline int CursesWindow::addch(const char ch)         
+{
+  return ::waddch(w, ch); 
+}
+
+inline int CursesWindow::addstr(const char * str)     
+{
+  // The (char*) cast is to hack around prototypes in curses.h that
+  // have const missing in the parameter lists.  [E.g. SVR4]
+  return ::waddstr(w, (char*)str); 
+}
+
+inline int CursesWindow::clear()                      
+{
+  return ::wclear(w); 
+}
+
+inline int CursesWindow::clrtobot()                   
+{
+  return ::wclrtobot(w); 
+}
+
+inline int CursesWindow::clrtoeol()                   
+{
+  return ::wclrtoeol(w); 
+}
+
+inline int CursesWindow::delch()                      
+{
+  return ::wdelch(w); 
+}
+
+inline int CursesWindow::deleteln()                   
+{
+  return ::wdeleteln(w); 
+}
+
+inline int CursesWindow::erase()                      
+{
+  return ::werase(w); 
+}
+
+inline int CursesWindow::getch()                      
+{
+  return ::wgetch(w); 
+}
+
+inline int CursesWindow::getstr(char * str)           
+{
+  return ::wgetstr(w, str); 
+}
+
+inline int CursesWindow::inch()                       
+{
+  return winch(w); 
+}
+
+inline int CursesWindow::insch(char c)               
+{
+  return ::winsch(w, c); 
+}
+
+inline int CursesWindow::insertln()                   
+{
+  return ::winsertln(w); 
+}
+
+inline int CursesWindow::move(int y, int x)           
+{
+  return ::wmove(w, y, x); 
+}
+
+
+inline int CursesWindow::mvcur(int sy, int ey, int sx, int ex)
+{
+  return ::mvcur(sy, ey, sx,ex);
+}
+
+inline int CursesWindow::mvaddch(int y, int x, char ch)
+{
+  return (::wmove(w, y, x)==ERR) ? ERR : ::waddch(w, ch);
+}
+
+inline int CursesWindow::mvgetch(int y, int x)
+{
+  return (::wmove(w, y, x)==ERR) ? ERR : ::wgetch(w);
+}
+
+inline int CursesWindow::mvaddstr(int y, int x, const char * str)
+{
+  return (::wmove(w, y, x)==ERR) ? ERR : ::waddstr(w, (char*)str);
+}
+
+inline int CursesWindow::mvgetstr(int y, int x, char * str)
+{
+  return (::wmove(w, y, x)==ERR) ? ERR : ::wgetstr(w, str);
+}
+
+inline int CursesWindow::mvinch(int y, int x)
+{
+  return (::wmove(w, y, x)==ERR) ? ERR : ::winch(w);
+}
+
+inline int CursesWindow::mvdelch(int y, int x)
+{
+  return (::wmove(w, y, x)==ERR) ? ERR : ::wdelch(w);
+}
+
+inline int CursesWindow::mvinsch(int y, int x, char ch)
+{
+  return (::wmove(w, y, x)==ERR) ? ERR : ::winsch(w, ch);
+}
+
+inline int CursesWindow::refresh()                   
+{
+  return ::wrefresh(w); 
+}
+
+inline int CursesWindow::clearok(int bf)             
+{
+  return ::clearok(w,bf); 
+}
+
+inline int CursesWindow::leaveok(int bf)             
+{
+  return ::leaveok(w,bf); 
+}
+
+inline int CursesWindow::scrollok(int bf)            
+{
+  return ::scrollok(w,bf); 
+}
+
+#ifndef _no_flushok
+inline int CursesWindow::flushok(int bf)            
+{
+  return ::flushok(w, bf); 
+}
+#endif
+
+inline void CursesWindow::getyx(int& y, int& x)       
+{
+  ::getyx(w, y, x); 
+}
+
+inline int CursesWindow::standout()                   
+{
+  return ::wstandout(w); 
+}
+
+inline int CursesWindow::standend()                   
+{
+  return ::wstandend(w); 
+}
+
+inline int CursesWindow::lines()                      
+{
+  return LINES; 
+}
+
+inline int CursesWindow::cols()                       
+{
+  return COLS; 
+}
+
+inline CursesWindow* CursesWindow::child()
+{
+  return subwins;
+}
+
+inline CursesWindow* CursesWindow::parent()
+{
+  return par;
+}
+
+inline CursesWindow* CursesWindow::sibling()
+{
+  return sib;
+}
+
+#endif /* _G_HAVE_CURSES */
+#endif
Index: trunk/src/emx/include/Attic/cpp/DLList.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/DLList.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/DLList.h	(revision 18)
@@ -0,0 +1,139 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _DLList_h
+#ifdef __GNUG__
+//#pragma interface
+#endif
+#define _DLList_h 1
+
+#undef OK
+
+#include <Pix.h>
+
+struct BaseDLNode {
+    BaseDLNode *bk;
+    BaseDLNode *fd;
+    void *item() {return (void*)(this+1);} //Return ((DLNode<T>*)this)->hd
+};
+
+template<class T>
+class DLNode : public BaseDLNode
+{
+  public:
+    T hd;
+    DLNode() { }
+    DLNode(const T& h, DLNode* p = 0, DLNode* n = 0)
+        : hd(h) { bk = p; fd = n; }
+    ~DLNode() { }
+};
+
+class BaseDLList {
+  protected:
+    BaseDLNode *h;
+
+    BaseDLList() { h = 0; }
+    void copy(const BaseDLList&);
+    BaseDLList& operator= (const BaseDLList& a);
+    virtual void delete_node(BaseDLNode*node) = 0;
+    virtual BaseDLNode* copy_node(const void* datum) = 0;
+    virtual void copy_item(void *dst, void *src) = 0;
+    virtual ~BaseDLList() { }
+
+    Pix                   prepend(const void*);
+    Pix                   append(const void*);
+    Pix ins_after(Pix p, const void *datum);
+    Pix ins_before(Pix p, const void *datum);
+    void remove_front(void *dst);
+    void remove_rear(void *dst);
+    void join(BaseDLList&);
+
+  public:
+    int                   empty() const { return h == 0; }
+    int                   length() const;
+    void                  clear();
+    void                  error(const char* msg) const;
+    int                   owns(Pix p) const;
+    int                   OK() const;
+    void                  del(Pix& p, int dir = 1);
+    void                  del_after(Pix& p);
+    void                  del_front();
+    void                  del_rear();
+};
+
+template <class T>
+class DLList : public BaseDLList {
+    //friend class          <T>DLListTrav;
+
+    virtual void delete_node(BaseDLNode *node) { delete (DLNode<T>*)node; }
+    virtual BaseDLNode* copy_node(const void *datum)
+	{ return new DLNode<T>(*(const T*)datum); }
+    virtual void copy_item(void *dst, void *src) { *(T*)dst = *(T*)src; }
+
+  public:
+    DLList() : BaseDLList() { }
+    DLList(const DLList<T>& a) : BaseDLList() { copy(a); }
+
+    DLList<T>&            operator = (const DLList<T>& a)
+	{ BaseDLList::operator=((const BaseDLList&) a); return *this; }
+    virtual ~DLList() { clear(); }
+
+    Pix prepend(const T& item) {return BaseDLList::prepend(&item);}
+    Pix append(const T& item) {return BaseDLList::append(&item);}
+
+    void join(DLList<T>& a) { BaseDLList::join(a); }
+
+    T& front() {
+	if (h == 0) error("front: empty list");
+	return ((DLNode<T>*)h)->hd; }
+    T& rear() {
+	if (h == 0) error("rear: empty list");
+	return ((DLNode<T>*)h->bk)->hd;
+    }
+    const T& front() const {
+	if (h == 0) error("front: empty list");
+	return ((DLNode<T>*)h)->hd; }
+    const T& rear() const {
+	if (h == 0) error("rear: empty list");
+	return ((DLNode<T>*)h->bk)->hd;
+    }
+    T remove_front() { T dst; BaseDLList::remove_front(&dst); return dst; }
+    T remove_rear() { T dst; BaseDLList::remove_rear(&dst); return dst; }
+
+    T&                  operator () (Pix p) {
+	if (p == 0) error("null Pix");
+	return ((DLNode<T>*)p)->hd;
+    }
+    const T&              operator () (Pix p) const {
+	if (p == 0) error("null Pix");
+	return ((DLNode<T>*)p)->hd;
+    }
+    Pix                   first() const { return Pix(h); }
+    Pix                   last()  const { return (h == 0) ? 0 : Pix(h->bk); }
+    void                  next(Pix& p) const
+	{ p = (p == 0 || p == h->bk)? 0 : Pix(((DLNode<T>*)p)->fd); }
+    void                  prev(Pix& p) const
+	{ p = (p == 0 || p == h)? 0 : Pix(((DLNode<T>*)p)->bk); }
+    Pix ins_after(Pix p, const T& item)
+      {return BaseDLList::ins_after(p, &item); }
+    Pix ins_before(Pix p, const T& item)
+      {return BaseDLList::ins_before(p, &item);}
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/DiscUnif.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/DiscUnif.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/DiscUnif.h	(revision 18)
@@ -0,0 +1,72 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _DiscreteUniform_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _DiscreteUniform_h 1
+
+#include <Random.h>
+
+//
+//	The interval [lo..hi)
+// 
+
+class DiscreteUniform: public Random {
+    long pLow;
+    long pHigh;
+    double delta;
+public:
+    DiscreteUniform(long low, long high, RNG *gen);
+
+    long low();
+    long low(long x);
+    long high();
+    long high(long x);
+
+    virtual double operator()();
+};
+
+
+inline DiscreteUniform::DiscreteUniform(long low, long high, RNG *gen)
+: Random(gen)
+{
+    pLow = (low < high) ? low : high;
+    pHigh = (low < high) ? high : low;
+    delta = (pHigh - pLow) + 1;
+}
+
+inline long DiscreteUniform::low() { return pLow; }
+
+inline long DiscreteUniform::low(long x) {
+  long tmp = pLow;
+  pLow = x;
+  delta = (pHigh - pLow) + 1;
+  return tmp;
+}
+
+inline long DiscreteUniform::high() { return pHigh; }
+
+inline long DiscreteUniform::high(long x) {
+  long tmp = pHigh;
+  pHigh = x;
+  delta = (pHigh - pLow) + 1;
+  return tmp;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Erlang.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Erlang.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Erlang.h	(revision 18)
@@ -0,0 +1,68 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _Erlang_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Erlang_h 1 
+
+#include <Random.h>
+
+class Erlang: public Random {
+protected:
+    double pMean;
+    double pVariance;
+    int k;
+    double a;
+    void setState();
+public:
+    Erlang(double mean, double variance, RNG *gen);
+
+    double mean();
+    double mean(double x);
+    double variance();
+    double variance(double x);
+
+    virtual double operator()();
+
+};
+
+
+inline void Erlang::setState() {
+  k = int( (pMean * pMean ) / pVariance + 0.5 );
+  k = (k > 0) ? k : 1;
+  a = k / pMean;
+}
+
+inline Erlang::Erlang(double mean, double variance, RNG *gen) : Random(gen)
+{
+  pMean = mean; pVariance = variance;
+  setState();
+}
+
+inline double Erlang::mean() { return pMean; }
+inline double Erlang::mean(double x) {
+  double tmp = pMean; pMean = x; setState(); return tmp;
+};
+
+inline double Erlang::variance() { return pVariance; }
+inline double Erlang::variance(double x) {
+  double tmp = pVariance; pVariance = x; setState(); return tmp;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Fix.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Fix.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Fix.h	(revision 18)
@@ -0,0 +1,523 @@
+// -*- C++ -*-
+// Fix.h : variable length fixed point data type 
+//
+
+#ifndef _Fix_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Fix_h 1
+
+#include <stream.h>
+#include <std.h>
+#include <stddef.h>
+#include <Integer.h>
+#include <builtin.h>
+
+class Fix
+{
+  struct Rep                    // internal Fix representation
+  {
+    _G_uint16_t len;		// length in bits
+    _G_uint16_t siz;		// allocated storage
+    _G_int16_t  ref;		// reference count
+    _G_uint16_t s[1];		// start of ushort array represention
+  };
+
+public:
+
+  typedef void (*PEH)(Rep*);
+
+private:
+
+  Rep*		  rep;
+
+		  Fix(Rep*);
+                  Fix(int, const Rep*);
+
+  void		  unique();
+
+  static const _G_uint16_t min_length =     1;
+  static const _G_uint16_t max_length = 65535;
+  static const double min_value  =  -1.0;
+  static const double max_value  =   1.0;
+
+  static _G_uint16_t   default_length;
+  static int 	  default_print_width;
+  static Rep	  Rep_0;
+  static Rep 	  Rep_m1;
+  static Rep 	  Rep_quotient_bump;
+
+  // internal class functions
+  static void	  mask(Rep*);
+  static int      compare(const Rep*, const Rep* = &Rep_0);
+
+  static Rep*	  new_Fix(_G_uint16_t);
+  static Rep*	  new_Fix(_G_uint16_t, const Rep*);
+  static Rep*	  new_Fix(_G_uint16_t, double);
+
+  static Rep*	  copy(const Rep*, Rep*);
+  static Rep*	  negate(const Rep*, Rep* = NULL);
+  static Rep*	  add(const Rep*, const Rep*, Rep* = NULL);
+  static Rep*	  subtract(const Rep*, const Rep*, Rep* = NULL);
+  static Rep*	  multiply(const Rep*, const Rep*, Rep* = NULL);
+  static Rep*	  multiply(const Rep*, int, Rep* = NULL);
+  static Rep*	  divide(const Rep*, const Rep*, Rep* = NULL,
+			 Rep* = NULL);
+  static Rep*	  shift(const Rep*, int, Rep* = NULL);
+
+  static one_arg_error_handler_t error_handler;
+  static one_arg_error_handler_t range_error_handler;
+
+  static PEH overflow_handler;
+
+public:
+		  Fix();
+                  Fix(const Fix&);
+		  Fix(double);
+                  Fix(int);
+                  Fix(_G_uint16_t);
+                  Fix(int, const Fix&);
+                  Fix(int, double);
+
+                  ~Fix();
+
+  Fix             operator =  (const Fix&);
+  Fix             operator =  (double);
+
+  friend int      operator == (const Fix&, const Fix&);
+  friend int      operator != (const Fix&, const Fix&);
+
+  friend int      operator <  (const Fix&, const Fix&);
+  friend int      operator <= (const Fix&, const Fix&);
+  friend int      operator >  (const Fix&, const Fix&);
+  friend int      operator >= (const Fix&, const Fix&);
+
+  Fix&            operator +  ();
+  Fix             operator -  ();
+
+  friend Fix      operator +  (const Fix&, const Fix&);
+  friend Fix      operator -  (const Fix&, const Fix&);
+  friend Fix      operator *  (const Fix&, const Fix&);
+  friend Fix      operator /  (const Fix&, const Fix&);
+
+  friend Fix      operator *  (const Fix&, int);
+  friend Fix      operator *  (int, const Fix&);
+  friend Fix      operator %  (const Fix&, int);
+  friend Fix      operator << (const Fix&, int);
+  friend Fix      operator >> (const Fix&, int);
+
+#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
+  friend Fix     operator <? (const Fix&, const Fix&); // min
+  friend Fix     operator >? (const Fix&, const Fix&); // max
+#endif
+
+  Fix            operator += (const Fix&);
+  Fix            operator -= (const Fix&);
+  Fix            operator *= (const Fix&);
+  Fix            operator /= (const Fix&);
+
+  Fix            operator *= (int);
+  Fix            operator %= (int);
+  Fix            operator <<=(int);
+  Fix            operator >>=(int);
+
+  friend char*    Ftoa(const Fix&, int width = default_print_width);
+  void		  printon(ostream&, int width = default_print_width) const;
+  friend Fix      atoF(const char*, int len = default_length);
+  
+  friend istream& operator >> (istream&, Fix&);
+  friend ostream& operator << (ostream&, const Fix&);
+
+  // built-in functions
+  friend Fix      abs(Fix);             // absolute value
+  friend int      sgn(const Fix&);	// -1, 0, +1
+  friend Integer  mantissa(const Fix&);	// integer representation
+  friend double   value(const Fix&);	// double value
+  friend int      length(const Fix&);	// field length
+  friend void	  show(const Fix&);	// show contents
+
+  // error handlers
+  static void     error(const char* msg); // error handler
+  static void     range_error(const char* msg);	// range error handler
+
+  static one_arg_error_handler_t set_error_handler(one_arg_error_handler_t f);
+  static one_arg_error_handler_t
+    set_range_error_handler(one_arg_error_handler_t f);
+
+  static void	  default_error_handler (const char *);
+  static void	  default_range_error_handler (const char *);
+
+  // non-operator versions for user
+  friend void	  negate(const Fix& x, Fix& r);
+  friend void	  add(const Fix& x, const Fix& y, Fix& r);
+  friend void	  subtract(const Fix& x, const Fix& y, Fix& r);
+  friend void	  multiply(const Fix& x, const Fix& y, Fix& r);
+  friend void	  divide(const Fix& x, const Fix& y, Fix& q, Fix& r);
+  friend void	  shift(const Fix& x, int y, Fix& r);
+
+  // overflow handlers
+  static void overflow_saturate(Fix::Rep*);
+  static void overflow_wrap(Fix::Rep*);
+  static void overflow_warning_saturate(Fix::Rep*);
+  static void overflow_warning(Fix::Rep*);
+  static void overflow_error(Fix::Rep*);
+
+  static PEH set_overflow_handler(PEH);
+
+  static int set_default_length(int);
+};
+
+// function definitions
+
+inline void
+Fix::unique()
+{
+  if ( rep->ref > 1 )
+  {
+    rep->ref--;
+    rep = new_Fix(rep->len,rep);
+  }
+}
+
+inline void
+Fix::mask (Fix::Rep* x)
+{
+  int n = x->len & 0x0f;
+  if ( n )
+    x->s[x->siz - 1] &= 0xffff0000 >> n; 
+}
+
+inline Fix::Rep*
+Fix::copy(const Fix::Rep* from, Fix::Rep* to)
+{
+  _G_uint16_t *ts = to->s;
+  const _G_uint16_t *fs = from->s;
+  int ilim = to->siz < from->siz ? to->siz : from->siz;
+  int i;
+  for ( i=0; i < ilim; i++ )
+    *ts++ = *fs++;
+  for ( ; i < to->siz; i++ )
+    *ts++ = 0;
+  mask(to);
+  return to;
+}
+
+inline
+Fix::Fix(Rep* f)
+{
+  rep = f;
+}
+
+inline
+Fix::Fix()
+{
+  rep = new_Fix(default_length);
+}
+
+inline
+Fix::Fix(int len)
+{
+  if ( len < min_length || len > max_length )
+    error("illegal length in declaration");
+  rep = new_Fix((_G_uint16_t) len);
+}
+
+inline
+Fix::Fix(_G_uint16_t len)
+{
+  if ( len < min_length || len > max_length )
+    error("illegal length in declaration");
+  rep = new_Fix(len);
+}
+
+inline
+Fix::Fix(double d)
+{
+  rep = new_Fix(default_length,d);
+}
+
+inline
+Fix::Fix(const Fix&  y)
+{
+  rep = y.rep; rep->ref++;
+}
+
+inline
+Fix::Fix(int len, const Fix&  y)
+{
+  if ( len < Fix::min_length || len > Fix::max_length )
+    error("illegal length in declaration");
+  rep = new_Fix((_G_uint16_t) len,y.rep);
+}
+
+inline
+Fix::Fix(int len, const Rep* fr)
+{
+  if ( len < Fix::min_length || len > Fix::max_length )
+    error("illegal length in declaration");
+  rep = new_Fix((_G_uint16_t) len,fr);
+}
+
+inline
+Fix::Fix(int len, double d)
+{
+  if ( len < Fix::min_length || len > Fix::max_length )
+    error("illegal length in declaration");
+  rep = new_Fix((_G_uint16_t) len,d);
+}
+
+inline
+Fix::~Fix()
+{
+  if ( --rep->ref <= 0 ) delete rep;
+}
+
+inline Fix
+Fix::operator = (const Fix&  y)
+{
+  if ( rep->len == y.rep->len ) {
+    ++y.rep->ref;
+    if ( --rep->ref <= 0 ) delete rep;
+    rep = y.rep; 
+  }
+  else {
+    unique();
+    copy(y.rep,rep);
+  }
+  return *this;
+}
+
+inline Fix
+Fix::operator = (double d)
+{
+  int oldlen = rep->len;
+  if ( --rep->ref <= 0 ) delete rep;
+  rep = new_Fix(oldlen,d);
+  return *this;
+}
+
+inline int
+operator == (const Fix&  x, const Fix&  y)
+{
+  return Fix::compare(x.rep, y.rep) == 0; 
+}
+
+inline int
+operator != (const Fix&  x, const Fix&  y)
+{
+  return Fix::compare(x.rep, y.rep) != 0; 
+}
+
+inline int
+operator <  (const Fix&  x, const Fix&  y)
+{
+  return Fix::compare(x.rep, y.rep) <  0; 
+}
+
+inline int
+operator <= (const Fix&  x, const Fix&  y)
+{
+  return Fix::compare(x.rep, y.rep) <= 0; 
+}
+
+inline int
+operator >  (const Fix&  x, const Fix&  y)
+{
+  return Fix::compare(x.rep, y.rep) >  0; 
+}
+
+inline int
+operator >= (const Fix&  x, const Fix&  y)
+{
+  return Fix::compare(x.rep, y.rep) >= 0; 
+}
+
+inline Fix&
+Fix::operator +  ()
+{
+  return *this;
+}
+
+inline Fix
+Fix::operator -  ()
+{
+  Rep* r = negate(rep); return r;
+}
+
+inline Fix
+operator +  (const Fix& x, const Fix& y)
+{
+  Fix::Rep* r = Fix::add(x.rep, y.rep); return r;
+}
+
+inline Fix
+operator -  (const Fix& x, const Fix& y)
+{
+  Fix::Rep* r = Fix::subtract(x.rep, y.rep); return r;
+}
+
+inline Fix
+operator *  (const Fix& x, const Fix& y)
+{
+  Fix::Rep* r = Fix::multiply(x.rep, y.rep); return r;
+}
+
+inline Fix
+operator *  (const Fix& x, int y)
+{
+  Fix::Rep* r = Fix::multiply(x.rep, y); return r;
+}
+
+inline Fix
+operator *  (int y, const Fix& x)
+{
+  Fix::Rep* r = Fix::multiply(x.rep, y); return r;
+}
+
+inline Fix
+operator / (const Fix& x, const Fix& y)
+{
+  Fix::Rep* r = Fix::divide(x.rep, y.rep); return r;
+}
+
+inline Fix
+Fix::operator += (const Fix& y)
+{
+  unique(); Fix::add(rep, y.rep, rep); return *this;
+}
+
+inline Fix
+Fix::operator -= (const Fix& y)
+{
+  unique(); Fix::subtract(rep, y.rep, rep); return *this;
+}
+
+inline Fix
+Fix::operator *= (const Fix& y)
+{
+  unique(); Fix::multiply(rep, y.rep, rep); return *this;
+}
+
+inline Fix
+Fix::operator *= (int y)
+{
+  unique(); Fix::multiply(rep, y, rep); return *this;
+}
+
+inline Fix
+Fix::operator /= (const Fix& y)
+{
+  unique(); Fix::divide(rep, y.rep, rep); return *this;
+}
+
+inline Fix
+operator % (const Fix& x, int y)
+{
+  Fix r((int) x.rep->len + y, x); return r;
+}
+
+inline Fix
+operator << (const Fix&  x, int y)
+{
+  Fix::Rep* rep = Fix::shift(x.rep, y); return rep;
+}
+
+inline Fix
+operator >> (const Fix&  x, int y)
+{  
+  Fix::Rep* rep = Fix::shift(x.rep, -y); return rep;
+}
+
+inline Fix
+Fix::operator <<= (int y)
+{
+  unique(); Fix::shift(rep, y, rep); return *this;
+}
+
+inline Fix
+Fix::operator >>= (int y)
+{
+  unique(); Fix::shift(rep, -y, rep); return *this;
+}
+
+#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
+inline Fix
+operator <? (const Fix& x, const Fix& y)
+{
+  if ( Fix::compare(x.rep, y.rep) <= 0 ) return x; else return y;
+}
+
+inline Fix
+operator >? (const Fix& x, const Fix& y)
+{
+  if ( Fix::compare(x.rep, y.rep) >= 0 ) return x; else return y;
+}
+#endif
+
+inline Fix
+abs(Fix  x)
+{
+  Fix::Rep* r = (Fix::compare(x.rep) >= 0 ? Fix::new_Fix(x.rep->len,x.rep) :
+		 Fix::negate(x.rep));
+  return r;
+}
+
+inline int
+sgn(const Fix& x)
+{
+  int a = Fix::compare(x.rep);
+  return a == 0 ? 0 : (a > 0 ? 1 : -1);
+}
+
+inline int
+length(const Fix& x)
+{
+  return x.rep->len;
+}
+
+inline ostream&
+operator << (ostream& s, const Fix& y)
+{
+  if (s.opfx())
+    y.printon(s);
+  return s;
+}
+
+inline void
+negate (const Fix& x, Fix& r)
+{
+  Fix::negate(x.rep, r.rep);
+}
+
+inline void
+add (const Fix& x, const Fix& y, Fix& r)
+{
+  Fix::add(x.rep, y.rep, r.rep);
+}
+
+inline void
+subtract (const Fix& x, const Fix& y, Fix& r)
+{
+  Fix::subtract(x.rep, y.rep, r.rep);
+}
+
+inline void
+multiply (const Fix& x, const Fix& y, Fix& r)
+{
+  Fix::multiply(x.rep, y.rep, r.rep);
+}
+
+inline void
+divide (const Fix& x, const Fix& y, Fix& q, Fix& r)
+{
+  Fix::divide(x.rep, y.rep, q.rep, r.rep);
+}
+
+inline void
+shift (const Fix& x, int y, Fix& r)
+{
+  Fix::shift(x.rep, y, r.rep);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Fix16.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Fix16.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Fix16.h	(revision 18)
@@ -0,0 +1,648 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu)
+    adapted for libg++ by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _Fix16_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Fix16_h 1
+
+#include <stream.h>
+#include <std.h>
+
+// constant definitions
+
+#define Fix16_fs 	((double)((unsigned)(1 << 15)))
+
+#define Fix16_msb	(1 << 15)
+#define Fix16_m_max	((1 << 15) - 1)
+#define Fix16_m_min	((short)(1 << 15))
+
+#define Fix16_mult	Fix16_fs
+#define Fix16_div	(1./Fix16_fs)
+#define Fix16_max	(1. - .5/Fix16_fs)
+#define Fix16_min	(-1.)
+
+
+#define Fix32_fs 	((double)((_G_uint32_t)(1 << 31)))
+
+#define Fix32_msb	((_G_uint32_t)(1 << 31))
+#define Fix32_m_max	((_G_int32_t)((1 << 31) - 1))
+#define Fix32_m_min	((_G_int32_t)(1 << 31))
+
+#define Fix32_mult	Fix32_fs
+#define Fix32_div	(1./Fix32_fs)
+#define Fix32_max	(1. - .5/Fix32_fs)
+#define Fix32_min	(-1.)
+
+
+//
+// Fix16    class: 16-bit Fixed point data type
+//
+//	consists of a 16-bit mantissa (sign bit & 15 data bits).
+//
+
+class Fix16 
+{ 
+  friend class          Fix32;
+
+  short                 m;
+
+  short                 round(double d);
+  short                 assign(double d);
+                        Fix16(short i);
+                        Fix16(int i);
+
+         operator       double() const;
+
+
+public:
+                        Fix16();
+                        Fix16(const Fix16&  f);
+                        Fix16(double d);
+                        Fix16(const Fix32& f);
+
+                        ~Fix16();
+
+  Fix16&                operator=(const Fix16&  f);
+  Fix16&                operator=(double d);
+  Fix16&                operator=(const Fix32& f);
+
+  friend short&         mantissa(Fix16&  f);
+  friend const short&   mantissa(const Fix16&  f);
+  friend double         value(const Fix16&  f);
+
+  Fix16                 operator +  () const;
+  Fix16                 operator -  () const;
+
+  friend Fix16          operator +  (const Fix16&  f, const Fix16&  g);
+  friend Fix16          operator -  (const Fix16&  f, const Fix16&  g);
+  friend Fix32          operator *  (const Fix16&  f, const Fix16&  g);
+  friend Fix16          operator /  (const Fix16&  f, const Fix16&  g);
+  friend Fix16          operator << (const Fix16&  f, int b);
+  friend Fix16          operator >> (const Fix16&  f, int b);
+
+  Fix16&                operator += (const Fix16&  f);
+  Fix16&                operator -= (const Fix16&  f);
+  Fix16&                operator *= (const Fix16& );
+  Fix16&                operator /= (const Fix16&  f);
+  
+  Fix16&                operator <<=(int b);
+  Fix16&                operator >>=(int b);
+
+  friend int            operator == (const Fix16&  f, const Fix16&  g);
+  friend int            operator != (const Fix16&  f, const Fix16&  g);
+  friend int            operator >= (const Fix16&  f, const Fix16&  g);
+  friend int            operator <= (const Fix16&  f, const Fix16&  g);
+  friend int            operator >  (const Fix16&  f, const Fix16&  g);
+  friend int            operator <  (const Fix16&  f, const Fix16&  g);
+
+  friend istream&       operator >> (istream& s, Fix16&  f);
+  friend ostream&       operator << (ostream& s, const Fix16&  f);
+
+  void                  overflow(short&) const;
+  void                  range_error(short&) const;
+
+  friend Fix16          operator *  (const Fix16&  f, int g);
+  friend Fix16          operator *  (int g, const Fix16&  f);
+  Fix16&                operator *= (int g);
+};
+
+ 
+//
+// Fix32 class: 32-bit Fixed point data type
+//
+//	consists of a 32-bit mantissa (sign bit & 31 data bits).
+//
+
+class Fix32 
+{ 
+  friend class         Fix16;
+
+  _G_int32_t           m;
+
+  _G_int32_t           round(double d);
+  _G_int32_t           assign(double d);
+
+                       Fix32(_G_int32_t i);
+                       operator double() const;
+
+
+public:
+                       Fix32();
+                       Fix32(const Fix32& f);
+                       Fix32(const Fix16&  f);
+                       Fix32(double d);
+                       ~Fix32();
+
+  Fix32&               operator =  (const Fix32& f);
+  Fix32&               operator =  (const Fix16&  f);
+  Fix32&               operator =  (double d);
+
+  friend _G_int32_t&         mantissa(Fix32& f);
+  friend const _G_int32_t&   mantissa(const Fix32& f);
+  friend double        value(const Fix32& f);
+
+  Fix32                operator +  () const;
+  Fix32                operator -  () const;
+
+  friend Fix32         operator +  (const Fix32& f, const Fix32& g);
+  friend Fix32         operator -  (const Fix32& f, const Fix32& g);
+  friend Fix32         operator *  (const Fix32& f, const Fix32& g);
+  friend Fix32         operator /  (const Fix32& f, const Fix32& g);
+  friend Fix32         operator << (const Fix32& f, int b);
+  friend Fix32         operator >> (const Fix32& f, int b);
+
+  friend Fix32         operator *  (const Fix16&  f, const Fix16&  g);
+
+  Fix32&               operator += (const Fix32& f);
+  Fix32&               operator -= (const Fix32& f);
+  Fix32&               operator *= (const Fix32& f);
+  Fix32&               operator /= (const Fix32& f);
+  Fix32&               operator <<=(int b);
+  Fix32&               operator >>=(int b);
+
+  friend int           operator == (const Fix32& f, const Fix32& g);
+  friend int           operator != (const Fix32& f, const Fix32& g);
+  friend int           operator >= (const Fix32& f, const Fix32& g);
+  friend int           operator <= (const Fix32& f, const Fix32& g);
+  friend int           operator >  (const Fix32& f, const Fix32& g);
+  friend int           operator <  (const Fix32& f, const Fix32& g);
+
+  friend istream&      operator >> (istream& s, Fix32& f);
+  friend ostream&      operator << (ostream& s, const Fix32& f);
+
+  void                 overflow(_G_int32_t& i) const;
+  void                 range_error(_G_int32_t& i) const;
+
+  friend Fix32          operator *  (const Fix32&  f, int g);
+  friend Fix32          operator *  (int g, const Fix32&  f);
+  Fix32&                operator *= (int g);
+};
+
+// active error handler declarations
+
+typedef void (*Fix16_peh)(short&);
+typedef void (*Fix32_peh)(_G_int32_t&);
+
+extern Fix16_peh Fix16_overflow_handler;
+extern Fix32_peh Fix32_overflow_handler;
+
+extern Fix16_peh Fix16_range_error_handler;
+extern Fix32_peh Fix32_range_error_handler;
+
+#if defined(SHORT_NAMES) || defined(VMS)
+#define	set_overflow_handler	sohndl
+#define set_range_error_handler	srnghdl
+#endif
+
+
+// error handler declarations
+
+extern Fix16_peh set_Fix16_overflow_handler(Fix16_peh);
+extern Fix32_peh set_Fix32_overflow_handler(Fix32_peh);
+extern void set_overflow_handler(Fix16_peh, Fix32_peh);
+
+extern Fix16_peh set_Fix16_range_error_handler(Fix16_peh);
+extern Fix32_peh set_Fix32_range_error_handler(Fix32_peh);
+extern void set_range_error_handler(Fix16_peh, Fix32_peh);
+
+extern void
+  Fix16_ignore(short&),
+  Fix16_overflow_saturate(short&),
+  Fix16_overflow_warning_saturate(short&),
+  Fix16_warning(short&),
+  Fix16_abort(short&);
+
+extern void
+  Fix32_ignore(_G_int32_t&),
+  Fix32_overflow_saturate(_G_int32_t&),
+  Fix32_overflow_warning_saturate(_G_int32_t&),
+  Fix32_warning(_G_int32_t&),
+  Fix32_abort(_G_int32_t&);
+
+
+inline Fix16::~Fix16() {}
+
+inline Fix32::~Fix32() {}
+
+inline short Fix16::round(double d)
+{ 
+  return short( (d >= 0)? d + 0.5 : d - 0.5); 
+}
+
+inline Fix16::Fix16(short i)		
+{ 
+  m = i; 
+}
+
+inline Fix16::Fix16(int i)	    
+{ 
+  m = i; 
+}
+
+inline Fix16::operator double() const 
+{ 
+  return  Fix16_div * m; 
+}
+
+inline Fix16::Fix16()     			
+{ 
+  m = 0; 
+}
+
+inline Fix16::Fix16(const Fix16&  f)		
+{ 
+  m = f.m; 
+}
+
+inline Fix16::Fix16(double d)		
+{
+  m = assign(d);
+}
+
+
+inline Fix16&  Fix16::operator=(const Fix16&  f)	
+{ 
+  m = f.m; 
+  return *this; 
+}
+
+inline Fix16&  Fix16::operator=(double d) 
+{ 
+  m = assign(d); 
+  return *this; 
+}
+
+
+inline Fix32::Fix32()			    
+{ 
+  m = 0;
+}
+
+inline Fix32::Fix32(_G_int32_t i)		
+{ 
+  m = i;
+}
+
+inline Fix32:: operator double() const		
+{ 
+  return Fix32_div * m;
+}
+
+
+inline Fix32::Fix32(const Fix32& f)		
+{ 
+  m = f.m;
+}
+
+inline Fix32::Fix32(const Fix16&  f)    
+{ 
+  m = _G_int32_t(f.m) << 16;
+}
+
+inline Fix32::Fix32(double d)		
+{ 
+  m = assign(d);
+}
+
+inline Fix16::Fix16(const Fix32& f)		
+{ 
+  m = f.m >> 16; 
+}
+
+
+inline Fix16&  Fix16::operator=(const Fix32& f)
+{ 
+  m = f.m >> 16; 
+  return *this; 
+}
+
+inline Fix32& Fix32::operator=(const Fix32& f)	
+{ 
+  m = f.m;
+  return *this; 
+}
+
+inline Fix32& Fix32::operator=(const Fix16&  f)	
+{ 
+  m = _G_int32_t(f.m) << 16;
+  return *this;
+}
+
+inline Fix32& Fix32::operator=(double d)	
+{ 
+  m = assign(d);
+  return *this; 
+}
+
+inline short& mantissa(Fix16&  f)	
+{ 
+  return f.m; 
+}
+
+inline const short& mantissa(const Fix16&  f)	
+{ 
+  return f.m; 
+}
+
+inline double value(const Fix16&  f)		
+{ 
+  return double(f); 
+}
+
+inline Fix16 Fix16::operator+() const		
+{ 
+  return m; 
+}
+
+inline Fix16 Fix16::operator-() const	
+{ 
+  return -m; 
+}
+
+inline Fix16 operator+(const Fix16&  f, const Fix16&  g) 
+{
+  short sum = f.m + g.m;
+  if ( (f.m ^ sum) & (g.m ^ sum) & Fix16_msb )
+    f.overflow(sum);
+  return sum;
+}
+
+inline Fix16 operator-(const Fix16&  f, const Fix16&  g) 
+{
+  short sum = f.m - g.m;
+  if ( (f.m ^ sum) & (-g.m ^ sum) & Fix16_msb )
+    f.overflow(sum);
+  return sum;
+}
+
+inline Fix32 operator*(const Fix16&  f, const Fix16&  g)
+{ 
+  return Fix32( _G_int32_t( _G_int32_t(f.m) * _G_int32_t(g.m) << 1)); 
+}
+
+inline Fix16 operator<<(const Fix16& a, int b) 	
+{ 
+  return a.m << b; 
+}
+
+inline Fix16 operator>>(const Fix16& a, int b) 	
+{ 
+  return a.m >> b; 
+}
+
+inline  Fix16&  Fix16:: operator+=(const Fix16&  f)
+{ 
+  return *this = *this + f; 
+}
+
+inline Fix16&  Fix16:: operator-=(const Fix16&  f) 	
+{ 
+  return *this = *this - f; 
+}
+
+inline Fix16& Fix16::operator*=(const Fix16& f) 	
+{ 
+  return *this = *this * f; 
+}
+
+inline Fix16&  Fix16:: operator/=(const Fix16&  f) 	
+{ 
+  return *this = *this / f; 
+}
+
+inline Fix16&  Fix16:: operator<<=(int b)	
+{ 
+  return *this = *this << b;
+}
+
+inline Fix16&  Fix16:: operator>>=(int b)	
+{ 
+  return *this = *this >> b;
+}
+
+inline int operator==(const Fix16&  f, const Fix16&  g)	
+{ 
+  return f.m == g.m;
+}
+
+inline int operator!=(const Fix16&  f, const Fix16&  g)	
+{ 
+  return f.m != g.m;
+}
+
+inline int operator>=(const Fix16&  f, const Fix16&  g)	
+{ 
+  return f.m >= g.m;
+}
+
+inline int operator<=(const Fix16&  f, const Fix16&  g)	
+{ 
+  return f.m <= g.m;
+}
+
+inline int operator>(const Fix16&  f, const Fix16&  g)	
+{ 
+  return f.m > g.m;
+}
+
+inline int operator<(const Fix16&  f, const Fix16&  g)	
+{ 
+  return f.m < g.m;
+}
+
+inline istream&  operator>>(istream& s, Fix16&  f)
+{ 
+  double d;
+  s >> d; 
+  f = d; 
+  return s; 
+}
+
+inline ostream&  operator<<(ostream& s, const Fix16&  f)
+{ 
+  return s << double(f);
+}
+
+
+inline Fix16 operator*(const Fix16&  f, int g)
+{
+  return Fix16(short(f.m * g));
+}
+
+inline Fix16 operator*(int g, const Fix16&  f)
+{
+  return f * g;
+}
+
+
+inline Fix16& Fix16::operator*=(int g)
+{
+  return *this = *this * g;
+}
+
+inline _G_int32_t Fix32::round(double d)
+{ 
+  return _G_int32_t( (d >= 0)? d + 0.5 : d - 0.5);
+}
+
+inline _G_int32_t& mantissa(Fix32& f)	
+{ 
+  return f.m;
+}
+
+inline const _G_int32_t& mantissa(const Fix32& f)	
+{ 
+  return f.m;
+}
+
+inline double value(const Fix32& f)		
+{ 
+  return double(f);
+}
+
+inline Fix32 Fix32::operator+() const
+{ 
+  return m;
+}
+
+inline Fix32 Fix32::operator-() const		
+{ 
+  return -m;
+}
+
+inline Fix32 operator+(const Fix32& f, const Fix32& g) 
+{
+  _G_int32_t sum = f.m + g.m;
+  if ( (f.m ^ sum) & (g.m ^ sum) & Fix32_msb )
+    f.overflow(sum);
+  return sum;
+}
+
+inline Fix32 operator-(const Fix32& f, const Fix32& g) 
+{
+  _G_int32_t sum = f.m - g.m;
+  if ( (f.m ^ sum) & (-g.m ^ sum) & Fix32_msb )
+    f.overflow(sum);
+  return sum;
+}
+
+inline Fix32 operator<<(const Fix32& a, int b) 	
+{ 
+  return a.m << b;
+}
+
+inline Fix32 operator>>(const Fix32& a, int b) 	
+{ 
+  return a.m >> b;
+}
+
+inline Fix32& Fix32::operator+=(const Fix32& f) 	
+{ 
+  return *this = *this + f;
+}
+
+inline Fix32& Fix32::operator-=(const Fix32& f) 	
+{ 
+  return *this = *this - f;
+}
+
+inline Fix32& Fix32::operator*=(const Fix32& f) 	
+{ 
+  return *this = *this * f;
+}
+
+inline Fix32& Fix32::operator/=(const Fix32& f) 	
+{ 
+  return *this = *this / f;
+}
+
+
+inline Fix32& Fix32::operator<<=(int b)	
+{ 
+  return *this = *this << b;
+}
+
+inline Fix32& Fix32::operator>>=(int b)	
+{ 
+  return *this = *this >> b;
+}
+
+inline int operator==(const Fix32& f, const Fix32& g)	
+{ 
+  return f.m == g.m;
+}
+
+inline int operator!=(const Fix32& f, const Fix32& g)	
+{ 
+  return f.m != g.m;
+}
+
+inline int operator>=(const Fix32& f, const Fix32& g)	
+{ 
+  return f.m >= g.m;
+}
+
+inline int operator<=(const Fix32& f, const Fix32& g)	
+{ 
+  return f.m <= g.m;
+}
+
+inline int operator>(const Fix32& f, const Fix32& g)	
+{ 
+  return f.m > g.m;
+}
+
+inline int operator<(const Fix32& f, const Fix32& g)	
+{ 
+  return f.m < g.m;
+}
+
+inline istream& operator>>(istream& s, Fix32& f)
+{ 
+  double d;
+  s >> d; 
+  f = d; 
+  return s; 
+}
+
+inline ostream& operator<<(ostream& s, const Fix32& f)
+{ 
+  return s << double(f);
+}
+
+inline Fix32 operator*(const Fix32&  f, int g)
+{
+  return Fix32(_G_int32_t(f.m * g));
+}
+
+inline Fix32 operator*(int g, const Fix32&  f)
+{
+  return f * g;
+}
+
+
+
+inline Fix32& Fix32::operator*=(int g)
+{
+  return *this = *this * g;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Fix24.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Fix24.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Fix24.h	(revision 18)
@@ -0,0 +1,597 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu)
+    adapted for libg++ by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _Fix24_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Fix24_h 1
+
+#include <stream.h>
+#include <std.h>
+
+// extra type definitions 
+
+typedef struct {
+  _G_int32_t		u;
+  _G_uint32_t		l;
+} twolongs;
+
+// constant definitions
+
+static const int
+  Fix24_shift = 31;
+		  
+static const double
+  Fix24_fs = 2147483648.,		// 2^Fix24_shift
+  Fix24_mult = Fix24_fs,
+  Fix24_div = 1./Fix24_fs,
+  Fix24_max = 1. - .5/Fix24_fs,
+  Fix24_min = -1.;
+	  
+static const _G_uint32_t
+  Fix24_msb = 0x80000000L,
+  Fix24_lsb = 0x00000100L,
+  Fix24_m_max = 0x7fffff00L,
+  Fix24_m_min = 0x80000000L;
+
+static const double
+  Fix48_fs = 36028797018963968.,	// 2^(24+Fix24_shift)
+  Fix48_max = 1. - .5/Fix48_fs,
+  Fix48_min = -1.,
+  Fix48_div_u = 1./Fix24_fs,
+  Fix48_div_l = 1./Fix48_fs;
+   
+static const twolongs
+  Fix48_msb = { 0x80000000L, 0L },
+  Fix48_lsb = { 0L, 0x00000100L },
+  Fix48_m_max = { 0x7fffff00L, 0xffffff00L },
+  Fix48_m_min = { 0x80000000L, 0L };
+		  
+//
+// Fix24    class: 24-bit Fixed point data type
+//
+//	consists of a 24-bit mantissa (sign bit & 23 data bits).
+//
+
+class Fix24 
+{ 
+  friend class          Fix48;
+
+  _G_int32_t            m;
+
+  _G_int32_t            assign(double d);
+         operator       double() const;
+                        Fix24(long i);
+                        Fix24(int i);
+
+
+public:
+                        Fix24();
+                        Fix24(const Fix24&  f);
+                        Fix24(double d);
+                        Fix24(const Fix48& f);
+
+                        ~Fix24();
+
+  Fix24&                operator=(const Fix24&  f);
+  Fix24&                operator=(double d);
+  Fix24&                operator=(const Fix48& f);
+
+  friend _G_int32_t&    mantissa(Fix24&  f);
+  friend const _G_int32_t&    mantissa(const Fix24&  f);
+  friend double         value(const Fix24&  f);
+
+  Fix24                 operator +  () const;
+  Fix24                 operator -  () const;
+
+  friend Fix24          operator +  (const Fix24&  f, const Fix24&  g);
+  friend Fix24          operator -  (const Fix24&  f, const Fix24&  g);
+  friend Fix48          operator *  (const Fix24&  f, const Fix24&  g);
+  friend Fix24          operator *  (const Fix24&  f, int     g);
+  friend Fix24          operator *  (int     g, const Fix24&  f);
+  friend Fix24          operator /  (const Fix24&  f, const Fix24&  g);
+  friend Fix24          operator << (const Fix24&  f, int b);
+  friend Fix24          operator >> (const Fix24&  f, int b);
+
+  Fix24&                operator += (const Fix24&  f);
+  Fix24&                operator -= (const Fix24&  f);
+  Fix24&                operator *= (const Fix24&  f);
+  Fix24&                operator *= (int     b);
+  Fix24&                operator /= (const Fix24&  f);
+
+  Fix24&                operator <<=(int b);
+  Fix24&                operator >>=(int b);
+
+  friend int            operator == (const Fix24&  f, const Fix24&  g);
+  friend int            operator != (const Fix24&  f, const Fix24&  g);
+  friend int            operator >= (const Fix24&  f, const Fix24&  g);
+  friend int            operator <= (const Fix24&  f, const Fix24&  g);
+  friend int            operator >  (const Fix24&  f, const Fix24&  g);
+  friend int            operator <  (const Fix24&  f, const Fix24&  g);
+
+  friend istream&       operator >> (istream& s, Fix24&  f);
+  friend ostream&       operator << (ostream& s, const Fix24&  f);
+
+  void                  overflow(_G_int32_t&) const;
+  void                  range_error(_G_int32_t&) const;
+};
+
+ 
+//
+// Fix48 class: 48-bit Fixed point data type
+//
+//	consists of a 48-bit mantissa (sign bit & 47 data bits).
+//
+
+class Fix48 
+{ 
+  friend class         Fix24;
+
+  twolongs             m;
+
+  twolongs             assign(double d);
+         operator      double() const;
+                       Fix48(twolongs i);
+
+public:
+                       Fix48();
+                       Fix48(const Fix48& f);
+                       Fix48(const Fix24&  f);
+                       Fix48(double d);
+                       ~Fix48();
+
+  Fix48&               operator =  (const Fix48& f);
+  Fix48&               operator =  (const Fix24&  f);
+  Fix48&               operator =  (double d);
+
+  friend twolongs&     mantissa(Fix48& f);
+  friend const twolongs&  mantissa(const Fix48& f);
+  friend double        value(const Fix48& f);
+
+  Fix48                operator +  () const;
+  Fix48                operator -  () const;
+
+  friend Fix48         operator +  (const Fix48& f, const Fix48& g);
+  friend Fix48         operator -  (const Fix48& f, const Fix48& g);
+  friend Fix48         operator *  (const Fix48& f, int    g);
+  friend Fix48         operator *  (int    g, const Fix48& f);
+  friend Fix48         operator << (const Fix48& f, int b);
+  friend Fix48         operator >> (const Fix48& f, int b);
+
+  friend Fix48         operator *  (const Fix24&  f, const Fix24&  g);
+
+  Fix48&               operator += (const Fix48& f);
+  Fix48&               operator -= (const Fix48& f);
+  Fix48&               operator *= (int    b);
+  Fix48&               operator <<=(int b);
+  Fix48&               operator >>=(int b);
+
+  friend int           operator == (const Fix48& f, const Fix48& g);
+  friend int           operator != (const Fix48& f, const Fix48& g);
+  friend int           operator >= (const Fix48& f, const Fix48& g);
+  friend int           operator <= (const Fix48& f, const Fix48& g);
+  friend int           operator >  (const Fix48& f, const Fix48& g);
+  friend int           operator <  (const Fix48& f, const Fix48& g);
+
+  friend istream&      operator >> (istream& s, Fix48& f);
+  friend ostream&      operator << (ostream& s, const Fix48& f);
+
+  void                 overflow(twolongs& i) const;
+  void                 range_error(twolongs& i) const;
+};
+
+
+// active error handler declarations
+
+typedef void (*Fix24_peh)(_G_int32_t&);
+typedef void (*Fix48_peh)(twolongs&);
+
+extern Fix24_peh Fix24_overflow_handler;
+extern Fix48_peh Fix48_overflow_handler;
+
+extern Fix24_peh Fix24_range_error_handler;
+extern Fix48_peh Fix48_range_error_handler;
+
+
+// error handler declarations
+
+#if defined(SHORT_NAMES) || defined(VMS)
+#define	set_overflow_handler	sohndl
+#define set_range_error_handler	srnghdl
+#endif
+
+extern Fix24_peh set_Fix24_overflow_handler(Fix24_peh);
+extern Fix48_peh set_Fix48_overflow_handler(Fix48_peh);
+extern void set_overflow_handler(Fix24_peh, Fix48_peh);
+
+extern Fix24_peh set_Fix24_range_error_handler(Fix24_peh);
+extern Fix48_peh set_Fix48_range_error_handler(Fix48_peh);
+extern void set_range_error_handler(Fix24_peh, Fix48_peh);
+
+extern void
+  Fix24_ignore(_G_int32_t&),
+  Fix24_overflow_saturate(_G_int32_t&),
+  Fix24_overflow_warning_saturate(_G_int32_t&),
+  Fix24_warning(_G_int32_t&),
+  Fix24_abort(_G_int32_t&);
+
+extern void
+  Fix48_ignore(twolongs&),
+  Fix48_overflow_saturate(twolongs&),
+  Fix48_overflow_warning_saturate(twolongs&),
+  Fix48_warning(twolongs&),
+  Fix48_abort(twolongs&);
+
+
+inline Fix24::~Fix24() {}
+
+inline Fix48::~Fix48() {}
+
+inline Fix24::Fix24(long i)		
+{ 
+  m = i; 
+}
+
+inline Fix24::Fix24(int i)	    
+{ 
+  m = i; 
+}
+
+inline Fix24::operator double() const
+{ 
+  return  Fix24_div * m; 
+}
+
+inline Fix24::Fix24()     			
+{ 
+  m = 0; 
+}
+
+inline Fix24::Fix24(const Fix24&  f)		
+{ 
+  m = f.m; 
+}
+
+inline Fix24::Fix24(double d)		
+{
+  m = assign(d);
+}
+
+inline Fix24::Fix24(const Fix48& f)		
+{ 
+  m = f.m.u;
+}
+
+inline Fix24&  Fix24::operator=(const Fix24&  f)	
+{ 
+  m = f.m; 
+  return *this; 
+}
+
+inline Fix24&  Fix24::operator=(double d) 
+{ 
+  m = assign(d); 
+  return *this; 
+}
+
+inline Fix24&  Fix24::operator=(const Fix48& f)
+{ 
+  m = f.m.u;
+  return *this; 
+}
+
+inline _G_int32_t& mantissa(Fix24&  f)
+{ 
+  return f.m; 
+}
+
+inline const _G_int32_t& mantissa(const Fix24&  f)
+{ 
+  return f.m; 
+}
+
+inline double value(const Fix24&  f)
+{ 
+  return double(f); 
+}
+
+inline Fix24 Fix24::operator+() const		
+{ 
+  return m; 
+}
+
+inline Fix24 Fix24::operator-() const
+{ 
+  return -m; 
+}
+
+inline Fix24 operator+(const Fix24&  f, const Fix24&  g) 
+{
+  _G_int32_t sum = f.m + g.m;
+  if ( (f.m ^ sum) & (g.m ^ sum) & Fix24_msb )
+    f.overflow(sum);
+  return sum;
+}
+
+inline Fix24 operator-(const Fix24&  f, const Fix24&  g) 
+{
+  _G_int32_t sum = f.m - g.m;
+  if ( (f.m ^ sum) & (-g.m ^ sum) & Fix24_msb )
+    f.overflow(sum);
+  return sum;
+}
+
+inline Fix24 operator*(const Fix24& a, int b) 	
+{ 
+  return a.m * b; 
+}
+
+inline Fix24 operator*(int b, const Fix24& a) 	
+{ 
+  return a * b; 
+}
+
+inline Fix24 operator<<(const Fix24& a, int b) 	
+{ 
+  return a.m << b; 
+}
+
+inline Fix24 operator>>(const Fix24& a, int b) 	
+{ 
+  return (a.m >> b) & ~0xff;
+}
+
+inline  Fix24&  Fix24:: operator+=(const Fix24&  f)
+{
+  return *this = *this + f;
+}
+
+inline Fix24&  Fix24:: operator-=(const Fix24&  f) 	
+{ 
+  return *this = *this - f; 
+}
+
+inline Fix24& Fix24::operator*=(const Fix24& f) 	
+{ 
+  return *this = *this * f; 
+}
+
+inline Fix24&  Fix24:: operator/=(const Fix24&  f) 	
+{ 
+  return *this = *this / f; 
+}
+
+inline Fix24&  Fix24:: operator<<=(int b)	
+{ 
+  return *this = *this << b;
+}
+
+inline Fix24&  Fix24:: operator>>=(int b)	
+{ 
+  return *this = *this >> b;
+}
+
+inline Fix24& Fix24::operator*=(int b)
+{ 
+  return *this = *this * b; 
+}
+
+inline int operator==(const Fix24&  f, const Fix24&  g)	
+{ 
+  return f.m == g.m;
+}
+
+inline int operator!=(const Fix24&  f, const Fix24&  g)	
+{ 
+  return f.m != g.m;
+}
+
+inline int operator>=(const Fix24&  f, const Fix24&  g)	
+{ 
+  return f.m >= g.m;
+}
+
+inline int operator<=(const Fix24&  f, const Fix24&  g)	
+{ 
+  return f.m <= g.m;
+}
+
+inline int operator>(const Fix24&  f, const Fix24&  g)	
+{ 
+  return f.m > g.m;
+}
+
+inline int operator<(const Fix24&  f, const Fix24&  g)	
+{ 
+  return f.m < g.m;
+}
+
+inline istream&  operator>>(istream& s, Fix24&  f)
+{ 
+  double d;
+  s >> d; 
+  f = d; 
+  return s; 
+}
+
+inline ostream&  operator<<(ostream& s, const Fix24&  f)
+{ 
+  return s << double(f);
+}
+
+inline Fix48::Fix48(twolongs i)		
+{ 
+  m = i;
+}
+
+inline Fix48:: operator double() const
+{ 
+/*
+ * Note: can't simply do Fix48_div_u * m.u + Fix48_div_l * m.l, because
+ * m.u is signed and m.l is unsigned.
+ */
+  return (m.u >= 0)? Fix48_div_u * m.u + Fix48_div_l * m.l :
+      (Fix48_div_u * ((_G_uint32_t)(m.u & 0xffffff00)) 
+	  + Fix48_div_l * m.l) - 2;
+}
+
+inline Fix48::Fix48()			    
+{ 
+  m.u = 0;
+  m.l = 0;
+}
+
+inline Fix48::Fix48(const Fix48& f)		
+{ 
+  m = f.m;
+}
+
+inline Fix48::Fix48(const Fix24&  f)    
+{ 
+  m.u = f.m;
+  m.l = 0;
+}
+
+inline Fix48::Fix48(double d)		
+{ 
+  m = assign(d);
+}
+
+inline Fix48& Fix48::operator=(const Fix48& f)	
+{ 
+  m = f.m;
+  return *this; 
+}
+
+inline Fix48& Fix48::operator=(const Fix24&  f)	
+{ 
+  m.u = f.m;
+  m.l = 0;
+  return *this;
+}
+
+inline Fix48& Fix48::operator=(double d)	
+{ 
+  m = assign(d);
+  return *this; 
+}
+
+inline twolongs& mantissa(Fix48& f)	
+{ 
+  return f.m;
+}
+
+inline const twolongs& mantissa(const Fix48& f)	
+{ 
+  return f.m;
+}
+
+inline double value(const Fix48& f)
+{ 
+  return double(f);
+}
+
+inline Fix48 Fix48::operator+() const		
+{ 
+  return m;
+}
+
+inline Fix48 Fix48::operator-() const
+{ 
+  twolongs n;
+  n.l = -m.l;
+  n.u = ~m.u + ((n.l ^ m.l) & Fix24_msb ? 0 : Fix24_lsb);
+  return Fix48(n);
+}
+
+inline Fix48 operator*(int b, const Fix48& a) 	
+{ 
+  return a * b; 
+}
+
+inline Fix48& Fix48::operator+=(const Fix48& f) 	
+{ 
+  return *this = *this + f;
+}
+
+inline Fix48& Fix48::operator-=(const Fix48& f) 	
+{ 
+  return *this = *this - f;
+}
+
+inline Fix48& Fix48::operator*=(int b)	
+{ 
+  return *this = *this * b;
+}
+
+inline Fix48& Fix48::operator<<=(int b)	
+{ 
+  return *this = *this << b;
+}
+
+inline Fix48& Fix48::operator>>=(int b)	
+{ 
+  return *this = *this >> b;
+}
+
+inline int operator==(const Fix48& f, const Fix48& g)	
+{ 
+  return f.m.u == g.m.u && f.m.l == g.m.l;
+}
+
+inline int operator!=(const Fix48& f, const Fix48& g)	
+{ 
+  return f.m.u != g.m.u || f.m.l != g.m.l;
+}
+
+inline int operator>=(const Fix48& f, const Fix48& g)	
+{ 
+  return f.m.u >= g.m.u || (f.m.u == g.m.u && f.m.l >= g.m.l);
+}
+
+inline int operator<=(const Fix48& f, const Fix48& g)	
+{ 
+  return f.m.u <= g.m.u || (f.m.u == g.m.u && f.m.l <= g.m.l);
+}
+
+inline int operator>(const Fix48& f, const Fix48& g)	
+{ 
+  return f.m.u > g.m.u || (f.m.u == g.m.u && f.m.l > g.m.l);
+}
+
+inline int operator<(const Fix48& f, const Fix48& g)	
+{ 
+  return f.m.u < g.m.u || (f.m.u == g.m.u && f.m.l < g.m.l);
+}
+
+inline istream& operator>>(istream& s, Fix48& f)
+{ 
+  double d;
+  s >> d; 
+  f = d; 
+  return s; 
+}
+
+inline ostream& operator<<(ostream& s, const Fix48& f)
+{ 
+  return s << double(f);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Geom.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Geom.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Geom.h	(revision 18)
@@ -0,0 +1,52 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _Geometric_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Geometric_h 
+
+#include <Random.h>
+
+class Geometric: public Random {
+protected:
+    double pMean;
+public:
+    Geometric(double mean, RNG *gen);
+
+    double mean();
+    double mean(double x);
+
+    virtual double operator()();
+
+};
+
+
+inline Geometric::Geometric(double mean, RNG *gen) : Random(gen)
+{
+  pMean = mean;
+}
+
+
+inline double Geometric::mean() { return pMean; }
+inline double Geometric::mean(double x) {
+  double tmp = pMean; pMean = x; return tmp;
+}
+
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/GetOpt.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/GetOpt.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/GetOpt.h	(revision 18)
@@ -0,0 +1,130 @@
+/* Getopt for GNU. 
+   Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+   (Modified by Douglas C. Schmidt for use with GNU G++.)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of `argv' so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable _POSIX_OPTION_ORDER disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#ifndef GetOpt_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define GetOpt_h 1
+
+#include <std.h>
+#include <stdio.h>
+
+class GetOpt
+{
+private:
+  /* The next char to be scanned in the option-element
+     in which the last option character we returned was found.
+     This allows us to pick up the scan where we left off.
+        
+     If this is zero, or a null string, it means resume the scan
+     by advancing to the next ARGV-element.  */
+  
+  static char *nextchar;
+  
+  
+  /* Describe how to deal with options that follow non-option ARGV-elements.
+    
+    UNSPECIFIED means the caller did not specify anything;
+    the default is then REQUIRE_ORDER if the environment variable
+    _OPTIONS_FIRST is defined, PERMUTE otherwise.
+      
+    REQUIRE_ORDER means don't recognize them as options.
+    Stop option processing when the first non-option is seen.
+    This is what Unix does.
+            
+    PERMUTE is the default.  We permute the contents of `argv' as we scan,
+    so that eventually all the options are at the end.  This allows options
+    to be given in any order, even with programs that were not written to
+    expect this.
+        
+    RETURN_IN_ORDER is an option available to programs that were written
+    to expect options and other ARGV-elements in any order and that care about
+    the ordering of the two.  We describe each non-option ARGV-element
+    as if it were the argument of an option with character code zero.
+    Using `-' as the first character of the list of option characters
+    requests this mode of operation.
+                    
+    The special argument `--' forces an end of option-scanning regardless
+    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+    `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+  
+   enum OrderingEnum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER };
+   OrderingEnum ordering;
+
+  /* Handle permutation of arguments.  */
+  
+  /* Describe the part of ARGV that contains non-options that have
+     been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+     `last_nonopt' is the index after the last of them.  */
+  
+  static int first_nonopt;
+  static int last_nonopt;
+  
+  void exchange (char **argv);
+public:
+  /* For communication from `getopt' to the caller.
+     When `getopt' finds an option that takes an argument,
+     the argument value is returned here.
+     Also, when `ordering' is RETURN_IN_ORDER,
+     each non-option ARGV-element is returned here.  */
+  
+  char *optarg;
+  
+  /* Index in ARGV of the next element to be scanned.
+     This is used for communication to and from the caller
+     and for communication between successive calls to `getopt'.
+     On entry to `getopt', zero means this is the first call; initialize.
+          
+     When `getopt' returns EOF, this is the index of the first of the
+     non-option elements that the caller should itself scan.
+              
+     Otherwise, `optind' communicates from one call to the next
+     how much of ARGV has been scanned so far.  */
+  
+  int optind;
+
+  /* Callers store zero here to inhibit the error message
+     for unrecognized options.  */
+  
+  int opterr;
+  
+  int    nargc;
+  char **nargv;
+  const char  *noptstring;
+  
+  GetOpt (int argc, char **argv, const char *optstring);
+  int operator () (void);
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/HypGeom.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/HypGeom.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/HypGeom.h	(revision 18)
@@ -0,0 +1,70 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _HyperGeometric_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _HyperGeometric_h 
+
+#include <Random.h>
+
+class HyperGeometric: public Random {
+protected:
+    double pMean;
+    double pVariance;
+    double pP;
+    void setState();
+
+public:
+    HyperGeometric(double mean, double variance, RNG *gen);
+
+    double mean();
+    double mean(double x);
+    double variance();
+    double variance(double x);
+
+    virtual double operator()();
+};
+
+
+inline void HyperGeometric::setState() {
+  double z = pVariance / (pMean * pMean);
+  pP = 0.5 * (1.0 - sqrt((z - 1.0) / ( z + 1.0 )));
+}
+
+inline HyperGeometric::HyperGeometric(double mean, double variance, RNG *gen)
+: Random(gen) {
+  pMean = mean; pVariance = variance;
+  setState();
+}
+
+inline double HyperGeometric::mean() { return pMean; };
+
+inline double HyperGeometric::mean(double x) {
+  double t = pMean; pMean = x;
+  setState(); return t;
+}
+
+inline double HyperGeometric::variance() { return pVariance; }
+
+inline double HyperGeometric::variance(double x) {
+  double t = pVariance; pVariance = x;
+  setState(); return t;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Incremen.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Incremen.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Incremen.h	(revision 18)
@@ -0,0 +1,12 @@
+#ifndef Incremental_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define Incremental_h
+#define DECLARE_INIT_FUNCTION(USER_INIT_FUNCTION) \
+static void USER_INIT_FUNCTION (); extern void (*_initfn)(); \
+static struct xyzzy { xyzzy () {_initfn = USER_INIT_FUNCTION;}; \
+~xyzzy () {};} __2xyzzy;
+#else
+#error Incremental.h was not the first file included in this module
+#endif
Index: trunk/src/emx/include/Attic/cpp/Integer.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Integer.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Integer.h	(revision 18)
@@ -0,0 +1,1134 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _Integer_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Integer_h 1
+
+#include <iostream.h>
+
+#undef OK
+
+struct IntRep                    // internal Integer representations
+{
+  unsigned short  len;          // current length
+  unsigned short  sz;           // allocated space (0 means static).
+  short           sgn;          // 1 means >= 0; 0 means < 0 
+  unsigned short  s[1];         // represented as ushort array starting here
+};
+
+// True if REP is staticly (or manually) allocated,
+// and should not be deleted by an Integer destructor.
+#define STATIC_IntRep(rep) ((rep)->sz==0)
+
+extern IntRep*  Ialloc(IntRep*, const unsigned short *, int, int, int);
+extern IntRep*  Icalloc(IntRep*, int);
+extern IntRep*  Icopy_ulong(IntRep*, unsigned long);
+extern IntRep*  Icopy_long(IntRep*, long);
+extern IntRep*  Icopy(IntRep*, const IntRep*);
+extern IntRep*  Iresize(IntRep*, int);
+extern IntRep*  add(const IntRep*, int, const IntRep*, int, IntRep*);
+extern IntRep*  add(const IntRep*, int, long, IntRep*);
+extern IntRep*  multiply(const IntRep*, const IntRep*, IntRep*);
+extern IntRep*  multiply(const IntRep*, long, IntRep*);
+extern IntRep*  lshift(const IntRep*, long, IntRep*);
+extern IntRep*  lshift(const IntRep*, const IntRep*, int, IntRep*);
+extern IntRep*  bitop(const IntRep*, const IntRep*, IntRep*, char);
+extern IntRep*  bitop(const IntRep*, long, IntRep*, char);
+extern IntRep*  power(const IntRep*, long, IntRep*);
+extern IntRep*  div(const IntRep*, const IntRep*, IntRep*);
+extern IntRep*  mod(const IntRep*, const IntRep*, IntRep*);
+extern IntRep*  div(const IntRep*, long, IntRep*);
+extern IntRep*  mod(const IntRep*, long, IntRep*);
+extern IntRep*  compl(const IntRep*, IntRep*);
+extern IntRep*  abs(const IntRep*, IntRep*);
+extern IntRep*  negate(const IntRep*, IntRep*);
+extern IntRep*  pow(const IntRep*, long);
+extern IntRep*  gcd(const IntRep*, const IntRep* y);
+extern int      compare(const IntRep*, const IntRep*);
+extern int      compare(const IntRep*, long);
+extern int      ucompare(const IntRep*, const IntRep*);
+extern int      ucompare(const IntRep*, long);
+extern char*    Itoa(const IntRep* x, int base = 10, int width = 0);
+extern char*    cvtItoa(const IntRep* x, char* fmt, int& fmtlen, int base,
+                        int showbase, int width, int align_right, 
+                        char fillchar, char Xcase, int showpos);
+extern IntRep*  atoIntRep(const char* s, int base = 10);
+extern long     Itolong(const IntRep*);
+extern int      Iislong(const IntRep*);
+extern long     lg(const IntRep*);
+
+extern IntRep _ZeroRep, _OneRep, _MinusOneRep;
+
+class Integer
+{
+protected:
+  IntRep*         rep;
+public:
+                  Integer();
+                  Integer(int);
+                  Integer(long);
+                  Integer(unsigned long);
+                  Integer(IntRep*);
+                  Integer(const Integer&);
+
+                  ~Integer();
+  Integer&        operator =  (const Integer&);
+  Integer&        operator =  (long);
+
+// unary operations to self
+
+  Integer&        operator ++ ();
+  Integer&        operator -- ();
+  void            negate();          // negate in-place
+  void            abs();             // absolute-value in-place
+  void            complement();      // bitwise complement in-place
+
+// assignment-based operations
+
+  Integer&        operator += (const Integer&);
+  Integer&        operator -= (const Integer&);
+  Integer&        operator *= (const Integer&);
+  Integer&        operator /= (const Integer&);
+  Integer&        operator %= (const Integer&);
+  Integer&        operator <<=(const Integer&);
+  Integer&        operator >>=(const Integer&);
+  Integer&        operator &= (const Integer&);
+  Integer&        operator |= (const Integer&);
+  Integer&        operator ^= (const Integer&);
+
+  Integer&        operator += (long);
+  Integer&        operator -= (long);
+  Integer&        operator *= (long);
+  Integer&        operator /= (long);
+  Integer&        operator %= (long);
+  Integer&        operator <<=(long);
+  Integer&        operator >>=(long);
+  Integer&        operator &= (long);
+  Integer&        operator |= (long);
+  Integer&        operator ^= (long);
+
+// (constructive binary operations are inlined below)
+
+#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
+  friend Integer operator <? (const Integer& x, const Integer& y); // min
+  friend Integer operator >? (const Integer& x, const Integer& y); // max
+#endif
+
+// builtin Integer functions that must be friends
+
+  friend long     lg (const Integer&); // floor log base 2 of abs(x)
+  friend double   ratio(const Integer& x, const Integer& y);
+                  // return x/y as a double
+
+  friend Integer  gcd(const Integer&, const Integer&);
+  friend int      even(const Integer&); // true if even
+  friend int      odd(const Integer&); // true if odd
+  friend int      sign(const Integer&); // returns -1, 0, +1
+
+  friend void     (setbit)(Integer& x, long b);   // set b'th bit of x
+  friend void     clearbit(Integer& x, long b); // clear b'th bit
+  friend int      testbit(const Integer& x, long b);  // return b'th bit
+
+// procedural versions of operators
+
+  friend void     abs(const Integer& x, Integer& dest);
+  friend void     negate(const Integer& x, Integer& dest);
+  friend void     complement(const Integer& x, Integer& dest);
+
+  friend int      compare(const Integer&, const Integer&);  
+  friend int      ucompare(const Integer&, const Integer&); 
+  friend void     add(const Integer& x, const Integer& y, Integer& dest);
+  friend void     sub(const Integer& x, const Integer& y, Integer& dest);
+  friend void     mul(const Integer& x, const Integer& y, Integer& dest);
+  friend void     div(const Integer& x, const Integer& y, Integer& dest);
+  friend void     mod(const Integer& x, const Integer& y, Integer& dest);
+  friend void     divide(const Integer& x, const Integer& y, 
+                         Integer& q, Integer& r);
+#ifndef __STRICT_ANSI__
+  friend void     and(const Integer& x, const Integer& y, Integer& dest);
+  friend void     or(const Integer& x, const Integer& y, Integer& dest);
+  friend void     xor(const Integer& x, const Integer& y, Integer& dest); 
+#endif
+  friend void     lshift(const Integer& x, const Integer& y, Integer& dest);
+  friend void     rshift(const Integer& x, const Integer& y, Integer& dest);
+  friend void     pow(const Integer& x, const Integer& y, Integer& dest);
+
+  friend int      compare(const Integer&, long);  
+  friend int      ucompare(const Integer&, long); 
+  friend void     add(const Integer& x, long y, Integer& dest);
+  friend void     sub(const Integer& x, long y, Integer& dest);
+  friend void     mul(const Integer& x, long y, Integer& dest);
+  friend void     div(const Integer& x, long y, Integer& dest);
+  friend void     mod(const Integer& x, long y, Integer& dest);
+  friend void     divide(const Integer& x, long y, Integer& q, long& r);
+#ifndef __STRICT_ANSI__
+  friend void     and(const Integer& x, long y, Integer& dest);
+  friend void     or(const Integer& x, long y, Integer& dest);
+  friend void     xor(const Integer& x, long y, Integer& dest);
+#endif
+  friend void     lshift(const Integer& x, long y, Integer& dest);
+  friend void     rshift(const Integer& x, long y, Integer& dest);
+  friend void     pow(const Integer& x, long y, Integer& dest);
+
+  friend int      compare(long, const Integer&);  
+  friend int      ucompare(long, const Integer&); 
+  friend void     add(long x, const Integer& y, Integer& dest);
+  friend void     sub(long x, const Integer& y, Integer& dest);
+  friend void     mul(long x, const Integer& y, Integer& dest);
+#ifndef __STRICT_ANSI__
+  friend void     and(long x, const Integer& y, Integer& dest);
+  friend void     or(long x, const Integer& y, Integer& dest);
+  friend void     xor(long x, const Integer& y, Integer& dest);
+#endif
+
+  friend Integer  operator &  (const Integer&, const Integer&);
+  friend Integer  operator &  (const Integer&, long);
+  friend Integer  operator &  (long, const Integer&);
+  friend Integer  operator |  (const Integer&, const Integer&);
+  friend Integer  operator |  (const Integer&, long);
+  friend Integer  operator |  (long, const Integer&);
+  friend Integer  operator ^  (const Integer&, const Integer&);
+  friend Integer  operator ^  (const Integer&, long);
+  friend Integer  operator ^  (long, const Integer&);
+
+// coercion & conversion
+
+  int             fits_in_long() const { return Iislong(rep); }
+  int             fits_in_double() const;
+
+  long		  as_long() const { return Itolong(rep); }
+  double	  as_double() const;
+
+  friend char*    Itoa(const Integer& x, int base = 10, int width = 0);
+  friend Integer  atoI(const char* s, int base = 10);
+  void		  printon(ostream& s, int base = 10, int width = 0) const;
+  
+  friend istream& operator >> (istream& s, Integer& y);
+  friend ostream& operator << (ostream& s, const Integer& y);
+
+// error detection
+
+  int             initialized() const;
+  void   error(const char* msg) const;
+  int             OK() const;  
+};
+
+
+//  (These are declared inline)
+
+  int      operator == (const Integer&, const Integer&);
+  int      operator == (const Integer&, long);
+  int      operator != (const Integer&, const Integer&);
+  int      operator != (const Integer&, long);
+  int      operator <  (const Integer&, const Integer&);
+  int      operator <  (const Integer&, long);
+  int      operator <= (const Integer&, const Integer&);
+  int      operator <= (const Integer&, long);
+  int      operator >  (const Integer&, const Integer&);
+  int      operator >  (const Integer&, long);
+  int      operator >= (const Integer&, const Integer&);
+  int      operator >= (const Integer&, long);
+  Integer  operator -  (const Integer&);
+  Integer  operator ~  (const Integer&);
+  Integer  operator +  (const Integer&, const Integer&);
+  Integer  operator +  (const Integer&, long);
+  Integer  operator +  (long, const Integer&);
+  Integer  operator -  (const Integer&, const Integer&);
+  Integer  operator -  (const Integer&, long);
+  Integer  operator -  (long, const Integer&);
+  Integer  operator *  (const Integer&, const Integer&);
+  Integer  operator *  (const Integer&, long);
+  Integer  operator *  (long, const Integer&);
+  Integer  operator /  (const Integer&, const Integer&);
+  Integer  operator /  (const Integer&, long);
+  Integer  operator %  (const Integer&, const Integer&);
+  Integer  operator %  (const Integer&, long);
+  Integer  operator << (const Integer&, const Integer&);
+  Integer  operator << (const Integer&, long);
+  Integer  operator >> (const Integer&, const Integer&);
+  Integer  operator >> (const Integer&, long);
+
+  Integer  abs(const Integer&); // absolute value
+  Integer  sqr(const Integer&); // square
+
+  Integer  pow(const Integer& x, const Integer& y);
+  Integer  pow(const Integer& x, long y);
+  Integer  Ipow(long x, long y); // x to the y as Integer 
+
+
+extern char*    dec(const Integer& x, int width = 0);
+extern char*    oct(const Integer& x, int width = 0);
+extern char*    hex(const Integer& x, int width = 0);
+extern Integer  sqrt(const Integer&); // floor of square root
+extern Integer  lcm(const Integer& x, const Integer& y); // least common mult
+
+
+typedef Integer IntTmp; // for backward compatibility
+
+inline Integer::Integer() :rep(&_ZeroRep) {}
+
+inline Integer::Integer(IntRep* r) :rep(r) {}
+
+inline Integer::Integer(int y) :rep(Icopy_long(0, (long)y)) {}
+
+inline Integer::Integer(long y) :rep(Icopy_long(0, y)) {}
+
+inline Integer::Integer(unsigned long y) :rep(Icopy_ulong(0, y)) {}
+
+inline Integer::Integer(const Integer&  y) :rep(Icopy(0, y.rep)) {}
+
+inline Integer::~Integer() { if (rep && !STATIC_IntRep(rep)) delete rep; }
+
+inline Integer&  Integer::operator = (const Integer&  y)
+{
+  rep = Icopy(rep, y.rep);
+  return *this;
+}
+
+inline Integer& Integer::operator = (long y)
+{
+  rep = Icopy_long(rep, y);
+  return *this;
+}
+
+inline int Integer::initialized() const
+{
+  return rep != 0;
+}
+
+// procedural versions
+
+inline int compare(const Integer& x, const Integer& y)
+{
+  return compare(x.rep, y.rep);
+}
+
+inline int ucompare(const Integer& x, const Integer& y)
+{
+  return ucompare(x.rep, y.rep);
+}
+
+inline int compare(const Integer& x, long y)
+{
+  return compare(x.rep, y);
+}
+
+inline int ucompare(const Integer& x, long y)
+{
+  return ucompare(x.rep, y);
+}
+
+inline int compare(long x, const Integer& y)
+{
+  return -compare(y.rep, x);
+}
+
+inline int ucompare(long x, const Integer& y)
+{
+  return -ucompare(y.rep, x);
+}
+
+inline void  add(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = add(x.rep, 0, y.rep, 0, dest.rep);
+}
+
+inline void  sub(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = add(x.rep, 0, y.rep, 1, dest.rep);
+}
+
+inline void  mul(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = multiply(x.rep, y.rep, dest.rep);
+}
+
+inline void  div(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = div(x.rep, y.rep, dest.rep);
+}
+
+inline void  mod(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = mod(x.rep, y.rep, dest.rep);
+}
+
+#ifndef __STRICT_ANSI__
+inline void  and(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = bitop(x.rep, y.rep, dest.rep, '&');
+}
+
+inline void  or(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = bitop(x.rep, y.rep, dest.rep, '|');
+}
+
+inline void  xor(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = bitop(x.rep, y.rep, dest.rep, '^');
+}
+#endif
+
+inline void  lshift(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = lshift(x.rep, y.rep, 0, dest.rep);
+}
+
+inline void  rshift(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = lshift(x.rep, y.rep, 1, dest.rep);
+}
+
+inline void  pow(const Integer& x, const Integer& y, Integer& dest)
+{
+  dest.rep = power(x.rep, Itolong(y.rep), dest.rep); // not incorrect
+}
+
+inline void  add(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = add(x.rep, 0, y, dest.rep);
+}
+
+inline void  sub(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = add(x.rep, 0, -y, dest.rep);
+}
+
+inline void  mul(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = multiply(x.rep, y, dest.rep);
+}
+
+inline void  div(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = div(x.rep, y, dest.rep);
+}
+
+inline void  mod(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = mod(x.rep, y, dest.rep);
+}
+
+#ifndef __STRICT_ANSI__
+inline void  and(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = bitop(x.rep, y, dest.rep, '&');
+}
+
+inline void  or(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = bitop(x.rep, y, dest.rep, '|');
+}
+
+inline void  xor(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = bitop(x.rep, y, dest.rep, '^');
+}
+#endif
+
+inline void  lshift(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = lshift(x.rep, y, dest.rep);
+}
+
+inline void  rshift(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = lshift(x.rep, -y, dest.rep);
+}
+
+inline void  pow(const Integer& x, long y, Integer& dest)
+{
+  dest.rep = power(x.rep, y, dest.rep);
+}
+
+inline void abs(const Integer& x, Integer& dest)
+{
+  dest.rep = abs(x.rep, dest.rep);
+}
+
+inline void negate(const Integer& x, Integer& dest)
+{
+  dest.rep = negate(x.rep, dest.rep);
+}
+
+inline void complement(const Integer& x, Integer& dest)
+{
+  dest.rep = compl(x.rep, dest.rep);
+}
+
+inline void  add(long x, const Integer& y, Integer& dest)
+{
+  dest.rep = add(y.rep, 0, x, dest.rep);
+}
+
+inline void  sub(long x, const Integer& y, Integer& dest)
+{
+  dest.rep = add(y.rep, 1, x, dest.rep);
+}
+
+inline void  mul(long x, const Integer& y, Integer& dest)
+{
+  dest.rep = multiply(y.rep, x, dest.rep);
+}
+
+#ifndef __STRICT_ANSI__
+inline void  and(long x, const Integer& y, Integer& dest)
+{
+  dest.rep = bitop(y.rep, x, dest.rep, '&');
+}
+
+inline void  or(long x, const Integer& y, Integer& dest)
+{
+  dest.rep = bitop(y.rep, x, dest.rep, '|');
+}
+
+inline void  xor(long x, const Integer& y, Integer& dest)
+{
+  dest.rep = bitop(y.rep, x, dest.rep, '^');
+}
+#endif
+
+
+// operator versions
+
+inline int operator == (const Integer&  x, const Integer&  y)
+{
+  return compare(x, y) == 0; 
+}
+
+inline int operator == (const Integer&  x, long y)
+{
+  return compare(x, y) == 0; 
+}
+
+inline int operator != (const Integer&  x, const Integer&  y)
+{
+  return compare(x, y) != 0; 
+}
+
+inline int operator != (const Integer&  x, long y)
+{
+  return compare(x, y) != 0; 
+}
+
+inline int operator <  (const Integer&  x, const Integer&  y)
+{
+  return compare(x, y) <  0; 
+}
+
+inline int operator <  (const Integer&  x, long y)
+{
+  return compare(x, y) <  0; 
+}
+
+inline int operator <= (const Integer&  x, const Integer&  y)
+{
+  return compare(x, y) <= 0; 
+}
+
+inline int operator <= (const Integer&  x, long y)
+{
+  return compare(x, y) <= 0; 
+}
+
+inline int operator >  (const Integer&  x, const Integer&  y)
+{
+  return compare(x, y) >  0; 
+}
+
+inline int operator >  (const Integer&  x, long y)
+{
+  return compare(x, y) >  0; 
+}
+
+inline int operator >= (const Integer&  x, const Integer&  y)
+{
+  return compare(x, y) >= 0; 
+}
+
+inline int operator >= (const Integer&  x, long y)
+{
+  return compare(x, y) >= 0; 
+}
+
+
+inline Integer&  Integer::operator += (const Integer& y)
+{
+  add(*this, y, *this);
+  return *this;
+}
+
+inline Integer&  Integer::operator += (long y)
+{
+  add(*this, y, *this);
+  return *this;
+}
+
+inline Integer& Integer::operator ++ ()
+{
+  add(*this, 1, *this);
+  return *this;
+}
+
+
+inline Integer& Integer::operator -= (const Integer& y)
+{
+  sub(*this, y, *this);
+  return *this;
+}
+
+inline Integer& Integer::operator -= (long y)
+{
+  sub(*this, y, *this);
+  return *this;
+}
+
+inline Integer& Integer::operator -- ()
+{
+  add(*this, -1, *this);
+  return *this;
+}
+
+
+
+inline Integer& Integer::operator *= (const Integer& y)
+{
+  mul(*this, y, *this);
+  return *this;
+}
+
+inline Integer& Integer::operator *= (long y)
+{
+  mul(*this, y, *this);
+  return *this;
+}
+
+
+inline Integer& Integer::operator &= (const Integer& y)
+{
+  rep = bitop(rep, y.rep, rep, '&');
+  return *this;
+}
+
+inline Integer& Integer::operator &= (long y)
+{
+  rep = bitop(rep, y, rep, '&');
+  return *this;
+}
+
+inline Integer& Integer::operator |= (const Integer& y)
+{
+  rep = bitop(rep, y.rep, rep, '|');
+  return *this;
+}
+
+inline Integer& Integer::operator |= (long y)
+{
+  rep = bitop(rep, y, rep, '|');
+  return *this;
+}
+
+
+inline Integer& Integer::operator ^= (const Integer& y)
+{
+  rep = bitop(rep, y.rep, rep, '^');
+  return *this;
+}
+
+inline Integer& Integer::operator ^= (long y)
+{
+  rep = bitop(rep, y, rep, '^');
+  return *this;
+}
+
+
+
+inline Integer& Integer::operator /= (const Integer& y)
+{
+  div(*this, y, *this);
+  return *this;
+}
+
+inline Integer& Integer::operator /= (long y)
+{
+  div(*this, y, *this);
+  return *this;
+}
+
+
+inline Integer& Integer::operator <<= (const Integer&  y)
+{
+  lshift(*this, y, *this);
+  return *this;
+}
+
+inline Integer& Integer::operator <<= (long  y)
+{
+  lshift(*this, y, *this);
+  return *this;
+}
+
+
+inline Integer& Integer::operator >>= (const Integer&  y)
+{
+  rshift(*this, y, *this);
+  return *this;
+}
+
+inline Integer& Integer::operator >>= (long y)
+{
+  rshift(*this, y, *this);
+  return *this;
+}
+
+#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
+inline Integer operator <? (const Integer& x, const Integer& y)
+{
+  return (compare(x.rep, y.rep) <= 0) ? x : y;
+}
+
+inline Integer operator >? (const Integer& x, const Integer& y)
+{
+  return (compare(x.rep, y.rep) >= 0)?  x : y;
+}
+#endif
+
+
+inline void Integer::abs()
+{
+  ::abs(*this, *this);
+}
+
+inline void Integer::negate()
+{
+  ::negate(*this, *this);
+}
+
+
+inline void Integer::complement()
+{
+  ::complement(*this, *this);
+}
+
+
+inline int sign(const Integer& x)
+{
+  return (x.rep->len == 0) ? 0 : ( (x.rep->sgn == 1) ? 1 : -1 );
+}
+
+inline int even(const Integer& y)
+{
+  return y.rep->len == 0 || !(y.rep->s[0] & 1);
+}
+
+inline int odd(const Integer& y)
+{
+  return y.rep->len > 0 && (y.rep->s[0] & 1);
+}
+
+inline char* Itoa(const Integer& y, int base, int width)
+{
+  return Itoa(y.rep, base, width);
+}
+
+
+
+inline long lg(const Integer& x) 
+{
+  return lg(x.rep);
+}
+
+// constructive operations 
+
+#if defined(__GNUG__) && !defined(_G_NO_NRV)
+
+inline Integer  operator +  (const Integer& x, const Integer& y) return r
+{
+  add(x, y, r);
+}
+
+inline Integer  operator +  (const Integer& x, long y) return r
+{
+  add(x, y, r);
+}
+
+inline Integer  operator +  (long  x, const Integer& y) return r
+{
+  add(x, y, r);
+}
+
+inline Integer  operator -  (const Integer& x, const Integer& y) return r
+{
+  sub(x, y, r);
+}
+
+inline Integer  operator -  (const Integer& x, long y) return r
+{
+  sub(x, y, r);
+}
+
+inline Integer  operator -  (long  x, const Integer& y) return r
+{
+  sub(x, y, r);
+}
+
+inline Integer  operator *  (const Integer& x, const Integer& y) return r
+{
+  mul(x, y, r);
+}
+
+inline Integer  operator *  (const Integer& x, long y) return r
+{
+  mul(x, y, r);
+}
+
+inline Integer  operator *  (long  x, const Integer& y) return r
+{
+  mul(x, y, r);
+}
+
+inline Integer sqr(const Integer& x) return r
+{
+  mul(x, x, r);
+}
+
+inline Integer  operator &  (const Integer& x, const Integer& y) return r
+{
+  r.rep = bitop(x.rep, y.rep, r.rep, '&');
+}
+
+inline Integer  operator &  (const Integer& x, long y) return r
+{
+  r.rep = bitop(x.rep, y, r.rep, '&');
+}
+
+inline Integer  operator &  (long  x, const Integer& y) return r
+{
+  r.rep = bitop(y.rep, x, r.rep, '&');
+}
+
+inline Integer  operator |  (const Integer& x, const Integer& y) return r
+{
+  r.rep = bitop(x.rep, y.rep, r.rep, '|');
+}
+
+inline Integer  operator |  (const Integer& x, long y) return r
+{
+  r.rep = bitop(x.rep, y, r.rep, '|');
+}
+
+inline Integer  operator |  (long  x, const Integer& y) return r
+{
+  r.rep = bitop(y.rep, x, r.rep, '|');
+}
+
+inline Integer  operator ^  (const Integer& x, const Integer& y) return r
+{
+  r.rep = bitop(x.rep, y.rep, r.rep, '^');
+}
+
+inline Integer  operator ^  (const Integer& x, long y) return r
+{
+  r.rep = bitop (x.rep, y, r.rep, '^');
+}
+
+inline Integer  operator ^  (long  x, const Integer& y) return r
+{
+  r.rep = bitop (y.rep, x, r.rep, '^');
+}
+
+inline Integer  operator /  (const Integer& x, const Integer& y) return r
+{
+  div(x, y, r);
+}
+
+inline Integer operator /  (const Integer& x, long y) return r
+{
+  div(x, y, r);
+}
+
+inline Integer operator %  (const Integer& x, const Integer& y) return r
+{
+  mod(x, y, r);
+}
+
+inline Integer operator %  (const Integer& x, long y) return r
+{
+  mod(x, y, r);
+}
+
+inline Integer operator <<  (const Integer& x, const Integer& y) return r
+{
+  lshift(x, y, r);
+}
+
+inline Integer operator <<  (const Integer& x, long y) return r
+{
+  lshift(x, y, r);
+}
+
+inline Integer operator >>  (const Integer& x, const Integer& y) return r;
+{
+  rshift(x, y, r);
+}
+
+inline Integer operator >>  (const Integer& x, long y) return r
+{
+  rshift(x, y, r);
+}
+
+inline Integer pow(const Integer& x, long y) return r
+{
+  pow(x, y, r);
+}
+
+inline Integer Ipow(long x, long y) return r(x)
+{
+  pow(r, y, r);
+}
+
+inline Integer pow(const Integer& x, const Integer& y) return r
+{
+  pow(x, y, r);
+}
+
+
+
+inline Integer abs(const Integer& x) return r
+{
+  abs(x, r);
+}
+
+inline Integer operator - (const Integer& x) return r
+{
+  negate(x, r);
+}
+
+inline Integer operator ~ (const Integer& x) return r
+{
+  complement(x, r);
+}
+
+inline Integer  atoI(const char* s, int base) return r
+{
+  r.rep = atoIntRep(s, base);
+}
+
+inline Integer  gcd(const Integer& x, const Integer& y) return r
+{
+  r.rep = gcd(x.rep, y.rep);
+}
+
+#else /* NO_NRV */
+
+inline Integer  operator +  (const Integer& x, const Integer& y) 
+{
+  Integer r; add(x, y, r); return r;
+}
+
+inline Integer  operator +  (const Integer& x, long y) 
+{
+  Integer r; add(x, y, r); return r;
+}
+
+inline Integer  operator +  (long  x, const Integer& y) 
+{
+  Integer r; add(x, y, r); return r;
+}
+
+inline Integer  operator -  (const Integer& x, const Integer& y) 
+{
+  Integer r; sub(x, y, r); return r;
+}
+
+inline Integer  operator -  (const Integer& x, long y) 
+{
+  Integer r; sub(x, y, r); return r;
+}
+
+inline Integer  operator -  (long  x, const Integer& y) 
+{
+  Integer r; sub(x, y, r); return r;
+}
+
+inline Integer  operator *  (const Integer& x, const Integer& y) 
+{
+  Integer r; mul(x, y, r); return r;
+}
+
+inline Integer  operator *  (const Integer& x, long y) 
+{
+  Integer r; mul(x, y, r); return r;
+}
+
+inline Integer  operator *  (long  x, const Integer& y) 
+{
+  Integer r; mul(x, y, r); return r;
+}
+
+inline Integer sqr(const Integer& x) 
+{
+  Integer r; mul(x, x, r); return r;
+}
+
+inline Integer  operator &  (const Integer& x, const Integer& y) 
+{
+  Integer r; and(x, y, r); return r;
+}
+
+inline Integer  operator &  (const Integer& x, long y) 
+{
+  Integer r; and(x, y, r); return r;
+}
+
+inline Integer  operator &  (long  x, const Integer& y) 
+{
+  Integer r; and(x, y, r); return r;
+}
+
+inline Integer  operator |  (const Integer& x, const Integer& y) 
+{
+  Integer r; or(x, y, r); return r;
+}
+
+inline Integer  operator |  (const Integer& x, long y) 
+{
+  Integer r; or(x, y, r); return r;
+}
+
+inline Integer  operator |  (long  x, const Integer& y) 
+{
+  Integer r; or(x, y, r); return r;
+}
+
+inline Integer  operator ^  (const Integer& x, const Integer& y) 
+{
+  Integer r; r.rep = bitop(x.rep, y.rep, r.rep, '^'); return r;
+}
+
+inline Integer  operator ^  (const Integer& x, long y) 
+{
+  Integer r; r.rep = bitop(x.rep, y, r.rep, '^'); return r;
+}
+
+inline Integer  operator ^  (long  x, const Integer& y) 
+{
+  Integer r; r.rep = bitop(y.rep, x, r.rep, '^'); return r;
+}
+
+inline Integer  operator /  (const Integer& x, const Integer& y) 
+{
+  Integer r; div(x, y, r); return r;
+}
+
+inline Integer operator /  (const Integer& x, long y) 
+{
+  Integer r; div(x, y, r); return r;
+}
+
+inline Integer operator %  (const Integer& x, const Integer& y) 
+{
+  Integer r; mod(x, y, r); return r;
+}
+
+inline Integer operator %  (const Integer& x, long y) 
+{
+  Integer r; mod(x, y, r); return r;
+}
+
+inline Integer operator <<  (const Integer& x, const Integer& y) 
+{
+  Integer r; lshift(x, y, r); return r;
+}
+
+inline Integer operator <<  (const Integer& x, long y) 
+{
+  Integer r; lshift(x, y, r); return r;
+}
+
+inline Integer operator >>  (const Integer& x, const Integer& y) 
+{
+  Integer r; rshift(x, y, r); return r;
+}
+
+inline Integer operator >>  (const Integer& x, long y) 
+{
+  Integer r; rshift(x, y, r); return r;
+}
+
+inline Integer pow(const Integer& x, long y) 
+{
+  Integer r; pow(x, y, r); return r;
+}
+
+inline Integer Ipow(long x, long y) 
+{
+  Integer r(x); pow(r, y, r); return r;
+}
+
+inline Integer pow(const Integer& x, const Integer& y) 
+{
+  Integer r; pow(x, y, r); return r;
+}
+
+
+
+inline Integer abs(const Integer& x) 
+{
+  Integer r; abs(x, r); return r;
+}
+
+inline Integer operator - (const Integer& x) 
+{
+  Integer r; negate(x, r); return r;
+}
+
+inline Integer operator ~ (const Integer& x) 
+{
+  Integer r; complement(x, r); return r;
+}
+
+inline Integer  atoI(const char* s, int base) 
+{
+  Integer r; r.rep = atoIntRep(s, base); return r;
+}
+
+inline Integer  gcd(const Integer& x, const Integer& y) 
+{
+  Integer r; r.rep = gcd(x.rep, y.rep); return r;
+}
+
+#endif  /* NO_NRV */
+
+inline Integer& Integer::operator %= (const Integer& y)
+{
+  *this = *this % y; // mod(*this, y, *this) doesn't work.
+  return *this;
+}
+
+inline Integer& Integer::operator %= (long y)
+{
+  *this = *this % y; // mod(*this, y, *this) doesn't work.
+  return *this;
+}
+#endif /* !_Integer_h */
Index: trunk/src/emx/include/Attic/cpp/LogNorm.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/LogNorm.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/LogNorm.h	(revision 18)
@@ -0,0 +1,78 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _LogNormal_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _LogNormal_h 
+
+#include <Normal.h>
+
+class LogNormal: public Normal {
+protected:
+    double logMean;
+    double logVariance;
+    void setState();
+public:
+    LogNormal(double mean, double variance, RNG *gen);
+    double mean();
+    double mean(double x);
+    double variance();
+    double variance(double x);
+    virtual double operator()();
+};
+
+
+inline void LogNormal::setState()
+{
+    double m2 = logMean * logMean;
+    pMean = log(m2 / sqrt(logVariance + m2) );
+// from ch@heike.informatik.uni-dortmund.de:
+// (was   pVariance = log((sqrt(logVariance + m2)/m2 )); )
+    pStdDev = sqrt(log((logVariance + m2)/m2 )); 
+}
+
+inline LogNormal::LogNormal(double mean, double variance, RNG *gen)
+    : Normal(mean, variance, gen)
+{
+    logMean = mean;
+    logVariance = variance;
+    setState();
+}
+
+inline double LogNormal::mean() {
+    return logMean;
+}
+
+inline double LogNormal::mean(double x)
+{
+    double t=logMean; logMean = x; setState();
+    return t;
+}
+
+inline double LogNormal::variance() {
+    return logVariance;
+}
+
+inline double LogNormal::variance(double x)
+{
+    double t=logVariance; logVariance = x; setState();
+    return t;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/MLCG.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/MLCG.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/MLCG.h	(revision 18)
@@ -0,0 +1,87 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _MLCG_h
+#define _MLCG_h 1 
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <RNG.h>
+#include <math.h>
+
+//
+//	Multiplicative Linear Conguential Generator
+//
+
+class MLCG : public RNG {
+    _G_int32_t initialSeedOne;
+    _G_int32_t initialSeedTwo;
+    _G_int32_t seedOne;
+    _G_int32_t seedTwo;
+
+protected:
+
+public:
+    MLCG(_G_int32_t seed1 = 0, _G_int32_t seed2 = 1);
+    //
+    // Return a long-words word of random bits
+    //
+    virtual _G_uint32_t asLong();
+    virtual void reset();
+    _G_int32_t seed1();
+    void seed1(_G_int32_t);
+    _G_int32_t seed2();
+    void seed2(_G_int32_t);
+    void reseed(_G_int32_t, _G_int32_t);
+};
+
+inline _G_int32_t
+MLCG::seed1()
+{
+    return(seedOne);
+}
+
+inline void
+MLCG::seed1(_G_int32_t s)
+{
+    initialSeedOne = s;
+    reset();
+}
+
+inline _G_int32_t
+MLCG::seed2()
+{
+    return(seedTwo);
+}
+
+inline void
+MLCG::seed2(_G_int32_t s)
+{
+    initialSeedTwo = s;
+    reset();
+}
+
+inline void
+MLCG::reseed(_G_int32_t s1, _G_int32_t s2)
+{
+    initialSeedOne = s1;
+    initialSeedTwo = s2;
+    reset();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/NegExp.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/NegExp.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/NegExp.h	(revision 18)
@@ -0,0 +1,55 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _NegativeExpntl_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _NegativeExpntl_h 1
+
+
+//
+//	Negative Exponential Random Numbers
+//
+// 
+
+#include <Random.h>
+
+class NegativeExpntl: public Random {
+protected:
+    double pMean;
+public:
+    NegativeExpntl(double xmean, RNG *gen);
+    double mean();
+    double mean(double x);
+
+    virtual double operator()();
+};
+
+
+inline NegativeExpntl::NegativeExpntl(double xmean, RNG *gen)
+: Random(gen) {
+  pMean = xmean;
+}
+
+inline double NegativeExpntl::mean() { return pMean; }
+inline double NegativeExpntl::mean(double x) {
+  double t = pMean; pMean = x;
+  return t;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Normal.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Normal.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Normal.h	(revision 18)
@@ -0,0 +1,66 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _Normal_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Normal_h 
+
+#include <Random.h>
+
+class Normal: public Random {
+    char haveCachedNormal;
+    double cachedNormal;
+
+protected:
+    double pMean;
+    double pVariance;
+    double pStdDev;
+    
+public:
+    Normal(double xmean, double xvariance, RNG *gen);
+    double mean();
+    double mean(double x);
+    double variance();
+    double variance(double x);
+    virtual double operator()();
+};
+
+
+inline Normal::Normal(double xmean, double xvariance, RNG *gen)
+: Random(gen) {
+  pMean = xmean;
+  pVariance = xvariance;
+  pStdDev = sqrt(pVariance);
+  haveCachedNormal = 0;
+}
+
+inline double Normal::mean() { return pMean; };
+inline double Normal::mean(double x) {
+  double t=pMean; pMean = x;
+  return t;
+}
+
+inline double Normal::variance() { return pVariance; }
+inline double Normal::variance(double x) {
+  double t=pVariance; pVariance = x;
+  pStdDev = sqrt(pVariance);
+  return t;
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Obstack.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Obstack.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Obstack.h	(revision 18)
@@ -0,0 +1,218 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _Obstack_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Obstack_h 1
+
+#include <std.h>
+
+#undef OK
+
+class Obstack
+{
+  struct _obstack_chunk
+  {
+    char*           limit;
+    _obstack_chunk* prev;
+    char            contents[4];
+  };
+
+protected:
+  long	          chunksize;
+  _obstack_chunk* chunk;
+  char*	          objectbase;
+  char*	          nextfree;
+  char*	          chunklimit;
+  int             alignmentmask;
+
+  void  _free(void* obj);
+  void  newchunk(int size);
+
+public:
+        Obstack(int size = 4080, int alignment = 4); // 4080=4096-mallocslop
+
+        ~Obstack();
+
+  void* base();
+  void* next_free();
+  int   alignment_mask();
+  int   chunk_size();
+  int   size();
+  int   room();
+  int   contains(void* p);      // does Obstack hold pointer p?
+
+  void  grow(const void* data, int size);
+  void  grow(const void* data, int size, char terminator);
+  void  grow(const char* s);
+  void  grow(char c);
+  void  grow_fast(char c);
+  void  blank(int size);
+  void  blank_fast(int size);
+
+  void* finish();
+  void* finish(char terminator);
+
+  void* copy(const void* data, int size);
+  void* copy(const void* data, int size, char terminator);
+  void* copy(const char* s);
+  void* copy(char c);
+  void* alloc(int size);
+
+  void  free(void* obj);
+  void  shrink(int size = 1); // suggested by ken@cs.rochester.edu
+
+  int   OK();                   // rep invariant
+};
+
+
+inline Obstack::~Obstack()
+{
+  _free(0); 
+}
+
+inline void* Obstack::base()
+{
+  return objectbase; 
+}
+
+inline void* Obstack::next_free()
+{
+  return nextfree; 
+}
+
+inline int Obstack::alignment_mask()
+{
+  return alignmentmask; 
+}
+
+inline int Obstack::chunk_size()
+{
+  return chunksize; 
+}
+
+inline int Obstack::size()
+{
+  return nextfree - objectbase; 
+}
+
+inline int Obstack::room()
+{
+  return chunklimit - nextfree; 
+}
+
+inline void Obstack:: grow(const void* data, int size)
+{
+  if (nextfree+size > chunklimit) 
+    newchunk(size);
+  memcpy(nextfree, data, size);
+  nextfree += size; 
+}
+
+inline void Obstack:: grow(const void* data, int size, char terminator)
+{
+  if (nextfree+size+1 > chunklimit) 
+    newchunk(size+1);
+  memcpy(nextfree, data, size);
+  nextfree += size; 
+  *(nextfree)++ = terminator; 
+}
+
+inline void Obstack:: grow(const char* s)
+{
+  grow((const void*)s, strlen(s), 0); 
+}
+
+inline void Obstack:: grow(char c)
+{
+  if (nextfree+1 > chunklimit) 
+    newchunk(1); 
+  *(nextfree)++ = c; 
+}
+
+inline void Obstack:: blank(int size)
+{
+  if (nextfree+size > chunklimit) 
+    newchunk(size);
+  nextfree += size; 
+}
+
+inline void* Obstack::finish(char terminator)
+{
+  grow(terminator); 
+  return finish(); 
+}
+
+inline void* Obstack::copy(const void* data, int size)
+{
+  grow (data, size);
+  return finish(); 
+}
+
+inline void* Obstack::copy(const void* data, int size, char terminator)
+{
+  grow(data, size, terminator); 
+  return finish(); 
+}
+
+inline void* Obstack::copy(const char* s)
+{
+  grow((const void*)s, strlen(s), 0); 
+  return finish(); 
+}
+
+inline void* Obstack::copy(char c)
+{
+  grow(c);
+  return finish(); 
+}
+
+inline void* Obstack::alloc(int size)
+{
+  blank(size);
+  return finish(); 
+}
+
+inline void Obstack:: free(void* obj)     
+{
+  if (obj >= (void*)chunk && obj<(void*)chunklimit)
+    nextfree = objectbase = (char *) obj;
+  else 
+    _free(obj); 
+}
+
+inline void Obstack:: grow_fast(char c)
+{
+  *(nextfree)++ = c; 
+}
+
+inline void Obstack:: blank_fast(int size)
+{
+  nextfree += size; 
+}
+
+inline void Obstack:: shrink(int size) // from ken@cs.rochester.edu
+{
+  if (nextfree >= objectbase + size)
+    nextfree -= size;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Pix.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Pix.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Pix.h	(revision 18)
@@ -0,0 +1,5 @@
+
+#ifndef _Pix_h
+#define _Pix_h 1
+typedef void* Pix;
+#endif
Index: trunk/src/emx/include/Attic/cpp/PlotFile.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/PlotFile.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/PlotFile.h	(revision 18)
@@ -0,0 +1,89 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/* 
+  a very simple implementation of a class to output unix "plot"
+  format plotter files. See corresponding unix man pages for
+  more details. 
+
+  written by Doug Lea (dl@rocky.oswego.edu)
+  converted to use iostream library by Per Bothner (bothner@cygnus.com)
+*/
+
+#ifndef _PlotFile_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _PlotFile_h
+
+#include <fstream.h>
+
+/*   
+   Some plot libraries have the `box' command to draw boxes. Some don't.
+   `box' is included here via moves & lines to allow both possiblilties.
+*/
+
+extern "C++" {
+class PlotFile : public ofstream
+{
+protected:
+  PlotFile& cmd(char c);
+  PlotFile& operator << (const int x);
+  PlotFile& operator << (const char *s);
+  
+public:
+  
+  PlotFile() : ofstream() { }
+  PlotFile(int fd) : ofstream(fd) { }
+  PlotFile(const char *name, int mode=ios::out, int prot=0664)
+      : ofstream(name, mode, prot) { }
+  
+//  PlotFile& remove() { ofstream::remove(); return *this; }
+  
+//  int           filedesc() { return ofstream::filedesc(); }
+//  const char*   name() { return File::name(); }
+//  void          setname(const char* newname) { File::setname(newname); }
+//  int           iocount() { return File::iocount(); }
+  
+  PlotFile& arc(const int xi, const int yi,
+                const int x0, const int y0,
+                const int x1, const int y1);
+  PlotFile& box(const int x0, const int y0,
+                const int x1, const int y1);
+  PlotFile& circle(const int x, const int y, const int r);
+  PlotFile& cont(const int xi, const int yi);
+  PlotFile& dot(const int xi, const int yi, const int dx,
+                int n, const int* pat);
+  PlotFile& erase(); 
+  PlotFile& label(const char* s);
+  PlotFile& line(const int x0, const int y0,
+                 const int x1, const int y1);
+  PlotFile& linemod(const char* s);
+  PlotFile& move(const int xi, const int yi);
+  PlotFile& point(const int xi, const int yi);
+  PlotFile& space(const int x0, const int y0,
+                  const int x1, const int y1);
+};
+} // extern "C++"
+#endif
Index: trunk/src/emx/include/Attic/cpp/Poisson.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Poisson.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Poisson.h	(revision 18)
@@ -0,0 +1,51 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _Poisson_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Poisson_h 
+
+#include <Random.h>
+
+class Poisson: public Random {
+protected:
+    double pMean;
+public:
+    Poisson(double mean, RNG *gen);
+
+    double mean();
+    double mean(double x);
+
+    virtual double operator()();
+};
+
+
+inline Poisson::Poisson(double mean, RNG *gen)
+: Random(gen) {
+  pMean = mean;
+}
+
+inline double Poisson::mean() { return pMean; }
+inline double Poisson::mean(double x) {
+  double t = pMean;
+  pMean = x;
+  return t;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/RNG.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/RNG.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/RNG.h	(revision 18)
@@ -0,0 +1,58 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _RNG_h
+#define _RNG_h 1
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <assert.h>
+#include <math.h>
+#include <_G_confi.h>
+
+union PrivateRNGSingleType {		   	// used to access floats as unsigneds
+    float s;
+    _G_uint32_t u;
+};
+
+union PrivateRNGDoubleType {		   	// used to access doubles as unsigneds
+    double d;
+    _G_uint32_t u[2];
+};
+
+//
+// Base class for Random Number Generators. See ACG and MLCG for instances.
+//
+class RNG {
+    static PrivateRNGSingleType singleMantissa;	// mantissa bit vector
+    static PrivateRNGDoubleType doubleMantissa;	// mantissa bit vector
+public:
+    RNG();
+    //
+    // Return a long-words word of random bits
+    //
+    virtual _G_uint32_t asLong() = 0;
+    virtual void reset() = 0;
+    //
+    // Return random bits converted to either a float or a double
+    //
+    float asFloat();
+    double asDouble();
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Random.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Random.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Random.h	(revision 18)
@@ -0,0 +1,54 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _Random_h
+#define _Random_h 1
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <math.h>
+#include <RNG.h>
+
+class Random {
+protected:
+    RNG *pGenerator;
+public:
+    Random(RNG *generator);
+    virtual double operator()() = 0;
+
+    RNG *generator();
+    void generator(RNG *p);
+};
+
+
+inline Random::Random(RNG *gen)
+{
+    pGenerator = gen;
+}
+
+inline RNG *Random::generator()
+{
+    return(pGenerator);
+}
+
+inline void Random::generator(RNG *p)
+{
+    pGenerator = p;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Rational.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Rational.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Rational.h	(revision 18)
@@ -0,0 +1,290 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _Rational_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Rational_h 1
+
+#include <Integer.h>
+#include <math.h>
+
+#undef OK
+
+class Rational
+{
+protected:
+  Integer          num;
+  Integer          den;
+
+  void             normalize();
+
+public:
+                   Rational();
+                   Rational(double);
+                   Rational(int n);
+                   Rational(long n);
+                   Rational(int n, int d);
+                   Rational(long n, long d);
+                   Rational(long n, unsigned long d);
+                   Rational(unsigned long n, long d);
+                   Rational(unsigned long n, unsigned long d);
+                   Rational(const Integer& n);
+                   Rational(const Integer& n, const Integer& d);
+                   Rational(const Rational&);
+
+                  ~Rational();
+
+  Rational&        operator =  (const Rational& y);
+
+  friend int       operator == (const Rational& x, const Rational& y);
+  friend int       operator != (const Rational& x, const Rational& y);
+  friend int       operator <  (const Rational& x, const Rational& y);
+  friend int       operator <= (const Rational& x, const Rational& y);
+  friend int       operator >  (const Rational& x, const Rational& y);
+  friend int       operator >= (const Rational& x, const Rational& y);
+
+  friend Rational  operator +  (const Rational& x, const Rational& y);
+  friend Rational  operator -  (const Rational& x, const Rational& y);
+  friend Rational  operator *  (const Rational& x, const Rational& y);
+  friend Rational  operator /  (const Rational& x, const Rational& y);
+
+  Rational&        operator += (const Rational& y);
+  Rational&        operator -= (const Rational& y);
+  Rational&        operator *= (const Rational& y);
+  Rational&        operator /= (const Rational& y);
+
+#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
+  friend Rational  operator <? (const Rational& x, const Rational& y); // min
+  friend Rational  operator >? (const Rational& x, const Rational& y); // max
+#endif
+
+  friend Rational  operator - (const Rational& x);
+
+
+// builtin Rational functions
+
+
+  void             negate();                      // x = -x
+  void             invert();                      // x = 1/x
+
+  friend int       sign(const Rational& x);             // -1, 0, or +1
+  friend Rational  abs(const Rational& x);              // absolute value
+  friend Rational  sqr(const Rational& x);              // square
+  friend Rational  pow(const Rational& x, long y);
+  friend Rational  pow(const Rational& x, const Integer& y);
+  const Integer&   numerator() const;
+  const Integer&   denominator() const;
+
+// coercion & conversion
+
+                   operator double() const;
+  friend Integer   floor(const Rational& x);
+  friend Integer   ceil(const Rational& x);
+  friend Integer   trunc(const Rational& x);
+  friend Integer   round(const Rational& x);
+
+  friend istream&  operator >> (istream& s, Rational& y);
+  friend ostream&  operator << (ostream& s, const Rational& y);
+
+  int		   fits_in_float() const;
+  int		   fits_in_double() const;
+
+// procedural versions of operators
+
+  friend int       compare(const Rational& x, const Rational& y);
+  friend void      add(const Rational& x, const Rational& y, Rational& dest);
+  friend void      sub(const Rational& x, const Rational& y, Rational& dest);
+  friend void      mul(const Rational& x, const Rational& y, Rational& dest);
+  friend void      div(const Rational& x, const Rational& y, Rational& dest);
+
+// error detection
+
+  void    error(const char* msg) const;
+  int              OK() const;
+
+};
+
+typedef Rational RatTmp; // backwards compatibility
+
+inline Rational::Rational() : num(&_ZeroRep), den(&_OneRep) {}
+inline Rational::~Rational() {}
+
+inline Rational::Rational(const Rational& y) :num(y.num), den(y.den) {}
+
+inline Rational::Rational(const Integer& n) :num(n), den(&_OneRep) {}
+
+inline Rational::Rational(const Integer& n, const Integer& d) :num(n),den(d)
+{
+  normalize();
+}
+
+inline Rational::Rational(long n) :num(n), den(&_OneRep) { }
+
+inline Rational::Rational(int n) :num(n), den(&_OneRep) { }
+
+inline Rational::Rational(long n, long d) :num(n), den(d) { normalize(); }
+inline Rational::Rational(int n, int d) :num(n), den(d) { normalize(); }
+inline Rational::Rational(long n, unsigned long d) :num(n), den(d)
+{
+  normalize();
+}
+inline Rational::Rational(unsigned long n, long d) :num(n), den(d)
+{
+  normalize();
+}
+inline Rational::Rational(unsigned long n, unsigned long d) :num(n), den(d)
+{
+  normalize();
+}
+
+inline Rational& Rational::operator =  (const Rational& y)
+{
+  num = y.num;  den = y.den;
+  return *this;
+}
+
+inline int operator == (const Rational& x, const Rational& y)
+{
+  return compare(x.num, y.num) == 0 && compare(x.den, y.den) == 0;
+}
+
+inline int operator != (const Rational& x, const Rational& y)
+{
+  return compare(x.num, y.num) != 0 || compare(x.den, y.den) != 0;
+}
+
+inline int operator <  (const Rational& x, const Rational& y)
+{
+  return compare(x, y) <  0; 
+}
+
+inline int operator <= (const Rational& x, const Rational& y)
+{
+  return compare(x, y) <= 0; 
+}
+
+inline int operator >  (const Rational& x, const Rational& y)
+{
+  return compare(x, y) >  0; 
+}
+
+inline int operator >= (const Rational& x, const Rational& y)
+{
+  return compare(x, y) >= 0; 
+}
+
+inline int sign(const Rational& x)
+{
+  return sign(x.num);
+}
+
+inline void Rational::negate()
+{
+  num.negate();
+}
+
+
+inline Rational& Rational::operator += (const Rational& y) 
+{
+  add(*this, y, *this);
+  return *this;
+}
+
+inline Rational& Rational::operator -= (const Rational& y) 
+{
+  sub(*this, y, *this);
+  return *this;
+}
+
+inline Rational& Rational::operator *= (const Rational& y) 
+{
+  mul(*this, y, *this);
+  return *this;
+}
+
+inline Rational& Rational::operator /= (const Rational& y) 
+{
+  div(*this, y, *this);
+  return *this;
+}
+
+inline const Integer& Rational::numerator() const { return num; }
+inline const Integer& Rational::denominator() const { return den; }
+inline Rational::operator double() const { return ratio(num, den); }
+
+#if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
+inline Rational operator <? (const Rational& x, const Rational& y)
+{
+  if (compare(x, y) <= 0) return x; else return y;
+}
+
+inline Rational operator >? (const Rational& x, const Rational& y)
+{
+  if (compare(x, y) >= 0) return x; else return y;
+}
+#endif
+
+#if defined(__GNUG__) && !defined(_G_NO_NRV)
+
+inline Rational operator + (const Rational& x, const Rational& y) return r
+{
+  add(x, y, r);
+}
+
+inline Rational operator - (const Rational& x, const Rational& y) return r
+{
+  sub(x, y, r);
+}
+
+inline Rational operator * (const Rational& x, const Rational& y) return r
+{
+  mul(x, y, r);
+}
+
+inline Rational operator / (const Rational& x, const Rational& y) return r
+{
+  div(x, y, r);
+}
+
+#else /* NO_NRV */
+
+inline Rational operator + (const Rational& x, const Rational& y) 
+{
+  Rational r; add(x, y, r); return r;
+}
+
+inline Rational operator - (const Rational& x, const Rational& y)
+{
+  Rational r; sub(x, y, r); return r;
+}
+
+inline Rational operator * (const Rational& x, const Rational& y)
+{
+  Rational r; mul(x, y, r); return r;
+}
+
+inline Rational operator / (const Rational& x, const Rational& y)
+{
+  Rational r; div(x, y, r); return r;
+}
+#endif
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Regx.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Regx.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Regx.h	(revision 18)
@@ -0,0 +1,78 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _Regex_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Regex_h 1
+
+#undef OK
+
+#if defined(SHORT_NAMES) || defined(VMS)
+#define re_compile_pattern	recmppat
+#define re_pattern_buffer	repatbuf
+#define re_registers		reregs
+#endif
+
+struct re_pattern_buffer;       // defined elsewhere
+struct re_registers;
+
+class Regex
+{
+private:
+
+                     Regex(const Regex&) {}  // no X(X&)
+  void               operator = (const Regex&) {} // no assignment
+
+protected:
+  re_pattern_buffer* buf;
+  re_registers*      reg;
+
+public:
+                     Regex(const char* t, 
+                           int fast = 0, 
+                           int bufsize = 40, 
+                           const char* transtable = 0);
+
+                    ~Regex();
+
+  int                match(const char* s, int len, int pos = 0) const;
+  int                search(const char* s, int len, 
+                            int& matchlen, int startpos = 0) const;
+  int                match_info(int& start, int& length, int nth = 0) const;
+
+  int                OK() const;  // representation invariant
+};
+
+// some built in regular expressions
+
+extern const Regex RXwhite;          // = "[ \n\t\r\v\f]+"
+extern const Regex RXint;            // = "-?[0-9]+"
+extern const Regex RXdouble;         // = "-?\\(\\([0-9]+\\.[0-9]*\\)\\|
+                                     //    \\([0-9]+\\)\\|\\(\\.[0-9]+\\)\\)
+                                     //    \\([eE][---+]?[0-9]+\\)?"
+extern const Regex RXalpha;          // = "[A-Za-z]+"
+extern const Regex RXlowercase;      // = "[a-z]+"
+extern const Regex RXuppercase;      // = "[A-Z]+"
+extern const Regex RXalphanum;       // = "[0-9A-Za-z]+"
+extern const Regex RXidentifier;     // = "[A-Za-z_][A-Za-z0-9_]*"
+
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/RndInt.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/RndInt.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/RndInt.h	(revision 18)
@@ -0,0 +1,176 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1990 Free Software Foundation
+    adapted from a submission from John Reidl <riedl@cs.purdue.edu>
+
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY.  No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing.  Refer to the GNU CC General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+GNU CC, but only under the conditions described in the
+GNU CC General Public License.   A copy of this license is
+supposed to have been given to you along with GNU CC so you
+can know your rights and responsibilities.  It should be in a
+file named COPYING.  Among other things, the copyright notice
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _RandomInteger_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _RandomInteger_h 1
+
+// RandomInteger uses a random number generator to generate an integer
+// in a specified range.  By default the range is 0..1.  Since in my
+// experience random numbers are often needed for a wide variety of
+// ranges in the same program, this generator accepts a new low or high value
+// as an argument to the asLong and operator() methods to temporarily 
+// override stored values
+
+#include <math.h>
+#include <RNG.h>
+
+class RandomInteger 
+{
+ protected:
+  RNG *pGenerator;
+  long pLow;
+  long pHigh;
+
+  long _asLong(long, long);
+
+ public:
+
+       RandomInteger(long low, long high, RNG *gen);
+       RandomInteger(long high, RNG *gen);
+       RandomInteger(RNG *gen);
+
+// read params
+
+  long low() const;
+  long high() const;
+  RNG* generator() const;
+
+// change params
+
+  long low(long x);
+  long high(long x);
+  RNG* generator(RNG *gen);
+
+// get a random number
+
+  long asLong();
+  long operator()(); // synonym for asLong
+  int  asInt();      // (possibly) truncate as int
+
+// override params for one shot
+
+  long asLong(long high);
+  long asLong(long low, long high);
+
+  long operator () (long high);  // synonyms
+  long operator () (long low, long high);
+
+};
+
+
+inline RandomInteger::RandomInteger(long low, long high, RNG *gen) 
+     : pGenerator(gen),
+       pLow((low < high) ? low : high),
+       pHigh((low < high) ? high : low)
+       
+{}
+
+inline RandomInteger::RandomInteger(long high, RNG *gen) 
+     : pGenerator(gen),
+       pLow((0 < high) ? 0 : high),
+       pHigh((0 < high) ? high : 0)
+{}
+  
+
+inline RandomInteger::RandomInteger(RNG *gen) 
+     : pGenerator(gen),
+       pLow(0),
+       pHigh(1)
+{}
+
+inline RNG* RandomInteger::generator() const { return pGenerator;}
+inline long RandomInteger::low() const       { return pLow; }
+inline long RandomInteger::high() const      { return pHigh; }
+
+inline RNG* RandomInteger::generator(RNG *gen) 
+{
+  RNG *tmp = pGenerator; pGenerator = gen;  return tmp;
+}
+
+inline long RandomInteger::low(long x)  
+{
+  long tmp = pLow;  pLow = x;  return tmp;
+}
+
+inline long RandomInteger:: high(long x) 
+{
+  long tmp = pHigh; pHigh = x; return tmp;
+}
+
+inline long RandomInteger:: _asLong(long low, long high)
+{	
+  return (pGenerator->asLong() % (high-low+1)) + low;
+}
+
+
+inline long RandomInteger:: asLong() 
+{
+  return _asLong(pLow, pHigh);
+}
+
+inline long RandomInteger:: asLong(long high)
+{
+  return _asLong(pLow, high);
+}
+
+inline long RandomInteger:: asLong(long low, long high)
+{
+  return _asLong(low, high);
+}
+
+inline long RandomInteger:: operator () () 
+{
+  return _asLong(pLow, pHigh);
+}
+
+inline long RandomInteger:: operator () (long high)
+{
+  return _asLong(pLow, high);
+}
+
+inline long RandomInteger:: operator () (long low, long high)
+{
+  return _asLong(low, high);
+}
+
+
+
+
+inline int RandomInteger:: asInt() 
+{
+  return int(asLong());
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/SFile.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/SFile.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/SFile.h	(revision 18)
@@ -0,0 +1,55 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1988, 1992, 1993 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#ifndef _SFile_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _SFile_h 1
+
+#include <fstream.h>
+
+extern "C++" {
+class SFile: public fstream
+{
+  protected:
+    int       sz;                   // unit size for structured binary IO
+
+public:
+    SFile() : fstream() { }
+    SFile(int fd, int size);
+    SFile(const char *name, int size, int mode, int prot=0664);
+    void open(const char *name, int size, int mode, int prot=0664);
+    
+    int       size() { return sz; }
+    int       setsize(int s) { int old = sz; sz = s; return old; }
+    
+    SFile&    get(void* x);
+    SFile&    put(void* x);
+    SFile&    operator[](long i);
+};
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/SLList.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/SLList.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/SLList.h	(revision 18)
@@ -0,0 +1,129 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988, 1992 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _SLList_h
+#ifdef __GNUG__
+//#pragma interface
+#endif
+#define _SLList_h 1
+
+#undef OK
+
+#include <Pix.h>
+
+struct BaseSLNode
+{
+   union {
+     struct BaseSLNode *tl;
+     double dummy;  /* To force correct alignment */
+   };
+   void *item() {return (void*)(this+1);} // Return ((SLNode<T>*)this)->hd
+};
+
+template<class T>
+class SLNode : public BaseSLNode
+{
+  public:
+    T                    hd; // Data part of node
+                         SLNode() { }
+                         SLNode(const T& h, SLNode* t = 0)
+			     : hd(h) { tl = t; }
+                         ~SLNode() { }
+};
+
+extern int __SLListLength(BaseSLNode *ptr);
+
+class BaseSLList {
+  protected:
+    BaseSLNode *last;
+    virtual void delete_node(BaseSLNode*node) = 0;
+    virtual BaseSLNode* copy_node(const void* datum) = 0;
+    virtual void copy_item(void *dst, void *src) = 0;
+    virtual ~BaseSLList() { }
+    BaseSLList() { last = 0; }
+    void copy(const BaseSLList&);
+    BaseSLList& operator = (const BaseSLList& a);
+    Pix ins_after(Pix p, const void *datum);
+    Pix prepend(const void *datum);
+    Pix append(const void *datum);
+    int remove_front(void *dst, int signal_error = 0);
+    void join(BaseSLList&);
+  public:
+    int length() const;
+    int empty() const { return last == 0; }
+    void clear();
+    Pix                   prepend(BaseSLNode*);
+    Pix                   append(BaseSLNode*);
+    int                   OK() const;
+    void                  error(const char* msg) const;
+    void                  del_after(Pix p);
+    int                   owns(Pix p) const;
+    void                  del_front();
+};
+
+template <class T>
+class SLList : public BaseSLList
+{
+  private:
+    virtual void delete_node(BaseSLNode *node) { delete (SLNode<T>*)node; }
+    virtual BaseSLNode* copy_node(const void *datum)
+	{ return new SLNode<T>(*(const T*)datum); }
+    virtual void copy_item(void *dst, void *src) { *(T*)dst = *(T*)src; }
+
+public:
+    SLList() : BaseSLList() { }
+    SLList(const SLList<T>& a) : BaseSLList() { copy(a); }
+    SLList<T>&            operator = (const SLList<T>& a)
+	{ BaseSLList::operator=((const BaseSLList&) a); return *this; }
+    virtual ~SLList() { clear(); }
+
+    Pix prepend(const T& item) {return BaseSLList::prepend(&item);}
+    Pix append(const T& item) {return BaseSLList::append(&item);}
+    Pix prepend(SLNode<T>* node) {return BaseSLList::prepend(node);}
+    Pix append(SLNode<T>* node) {return BaseSLList::append(node);}
+
+    T& operator () (Pix p) {
+	if (p == 0) error("null Pix");
+	return ((SLNode<T>*)(p))->hd; }
+    const T& operator () (Pix p) const {
+	if (p == 0) error("null Pix");
+	return ((SLNode<T>*)(p))->hd; }
+    inline Pix first() const { return (last == 0) ? 0 : Pix(last->tl); }
+    void next(Pix& p) const
+	{ p = (p == 0 || p == last) ? 0 : Pix(((SLNode<T>*)(p))->tl); }
+    Pix ins_after(Pix p, const T& item)
+      { return BaseSLList::ins_after(p, &item); }
+    void join(SLList<T>& a) { BaseSLList::join(a); }
+    
+    T& front() {
+	if (last == 0) error("front: empty list");
+	return ((SLNode<T>*)last->tl)->hd; }
+    T& rear() {
+	if (last == 0) error("rear: empty list");
+	return ((SLNode<T>*)last)->hd; }
+    const T& front() const {
+	if (last == 0) error("front: empty list");
+	return ((SLNode<T>*)last->tl)->hd; }
+    const T& rear() const {
+	if (last == 0) error("rear: empty list");
+	return ((SLNode<T>*)last)->hd; }
+    int remove_front(T& x) { return BaseSLList::remove_front(&x); }
+    T remove_front() { T dst; BaseSLList::remove_front(&dst, 1); return dst; }
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/SmplHist.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/SmplHist.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/SmplHist.h	(revision 18)
@@ -0,0 +1,72 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SampleHistogram_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define SampleHistogram_h 1
+
+#include <iostream.h>
+#include <SmplStat.h>
+
+extern const int SampleHistogramMinimum;
+extern const int SampleHistogramMaximum;
+
+class SampleHistogram : public SampleStatistic 
+{
+protected:
+    short howManyBuckets;
+    int *bucketCount;
+    double *bucketLimit;
+
+public:
+    
+    SampleHistogram(double low, double hi, double bucketWidth = -1.0);
+
+    ~SampleHistogram();
+
+    virtual void reset();
+    virtual void operator+=(double);
+
+    int similarSamples(double);
+
+    int buckets();
+
+    double bucketThreshold(int i);
+    int inBucket(int i);
+    void printBuckets(ostream&);
+
+};
+
+
+inline int SampleHistogram:: buckets() { return(howManyBuckets); };
+
+inline double SampleHistogram:: bucketThreshold(int i) {
+    if (i < 0 || i >= howManyBuckets)
+        error("invalid bucket access");
+    return(bucketLimit[i]);
+}
+
+inline int SampleHistogram:: inBucket(int i) {
+    if (i < 0 || i >= howManyBuckets)
+        error("invalid bucket access");
+    return(bucketCount[i]);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/SmplStat.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/SmplStat.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/SmplStat.h	(revision 18)
@@ -0,0 +1,69 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef SampleStatistic_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define SampleStatistic_h 1
+
+#include <builtin.h>
+
+#undef min
+#undef max
+
+class SampleStatistic {
+protected:
+    int	n;
+    double x;
+    double x2;
+    double minValue, maxValue;
+
+    public :
+
+    SampleStatistic();
+    inline virtual ~SampleStatistic();
+    virtual void reset(); 
+
+    virtual void operator+=(double);
+    int  samples();
+    double mean();
+    double stdDev();
+    double var();
+    double min();
+    double max();
+    double confidence(int p_percentage);
+    double confidence(double p_value);
+
+    void            error(const char* msg);
+};
+
+// error handlers
+
+extern  void default_SampleStatistic_error_handler(const char*);
+extern  one_arg_error_handler_t SampleStatistic_error_handler;
+
+extern  one_arg_error_handler_t 
+        set_SampleStatistic_error_handler(one_arg_error_handler_t f);
+
+inline SampleStatistic:: SampleStatistic(){ reset();}
+inline int SampleStatistic::  samples() {return(n);}
+inline double SampleStatistic:: min() {return(minValue);}
+inline double SampleStatistic:: max() {return(maxValue);}
+inline SampleStatistic::~SampleStatistic() {}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Strng.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Strng.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Strng.h	(revision 18)
@@ -0,0 +1,1284 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* Changed for emx by Eberhard Mattes -- Oct 1998
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _String_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _String_h 1
+
+#include <iostream.h>
+#include <Regx.h>
+
+#undef OK
+
+struct StrRep                     // internal String representations
+{
+  unsigned short    len;         // string length 
+  unsigned short    sz;          // allocated space
+  char              s[1];        // the string starts here 
+                                 // (at least 1 char for trailing null)
+                                 // allocated & expanded via non-public fcts
+};
+
+// primitive ops on StrReps -- nearly all String fns go through these.
+
+StrRep*     Salloc(StrRep*, const char*, int, int);
+StrRep*     Scopy(StrRep*, const StrRep*);
+StrRep*     Scat(StrRep*, const char*, int, const char*, int);
+StrRep*     Scat(StrRep*, const char*, int,const char*,int, const char*,int);
+StrRep*     Sprepend(StrRep*, const char*, int);
+StrRep*     Sreverse(const StrRep*, StrRep*);
+StrRep*     Supcase(const StrRep*, StrRep*);
+StrRep*     Sdowncase(const StrRep*, StrRep*);
+StrRep*     Scapitalize(const StrRep*, StrRep*);
+
+// These classes need to be defined in the order given
+
+class String;
+class SubString;
+
+class SubString
+{
+  friend class      String;
+protected:
+
+  String&           S;        // The String I'm a substring of
+  unsigned short    pos;      // starting position in S's rep
+  unsigned short    len;      // length of substring
+
+  void              assign(const StrRep*, const char*, int = -1);
+                    SubString(String& x, int p, int l);
+                    SubString(const SubString& x);
+
+public:
+
+// Note there are no public constructors. SubStrings are always
+// created via String operations
+
+                   ~SubString();
+
+  SubString&        operator =  (const String&     y);
+  SubString&        operator =  (const SubString&  y);
+  SubString&        operator =  (const char* t);
+  SubString&        operator =  (char        c);
+
+// return 1 if target appears anywhere in SubString; else 0
+
+  int               contains(char        c) const;
+  int               contains(const String&     y) const;
+  int               contains(const SubString&  y) const;
+  int               contains(const char* t) const;
+  int               contains(const Regex&       r) const;
+
+// return 1 if target matches entire SubString
+
+  int               matches(const Regex&  r) const;
+
+// IO 
+
+  friend ostream&   operator<<(ostream& s, const SubString& x);
+
+// status
+
+  unsigned int      length() const;
+  int               empty() const;
+  const char*       chars() const;
+
+  int               OK() const; 
+
+};
+
+
+class String
+{
+  friend class      SubString;
+
+protected:
+  StrRep*           rep;   // Strings are pointers to their representations
+
+// some helper functions
+
+  int               search(int, int, const char*, int = -1) const;
+  int               search(int, int, char) const;
+  int               match(int, int, int, const char*, int = -1) const;
+  int               _gsub(const char*, int, const char* ,int);
+  int               _gsub(const Regex&, const char*, int);
+  SubString         _substr(int, int);
+
+public:
+
+// constructors & assignment
+
+                    String();
+                    String(const String& x);
+                    String(const SubString&  x);
+                    String(const char* t);
+                    String(const char* t, int len);
+                    String(char c);
+
+                    ~String();
+
+  String&           operator =  (const String&     y);
+  String&           operator =  (const char* y);
+  String&           operator =  (char        c);
+  String&           operator =  (const SubString&  y);
+
+// concatenation
+
+  String&           operator += (const String&     y); 
+  String&           operator += (const SubString&  y);
+  String&           operator += (const char* t);
+  String&           operator += (char        c);
+
+  void              prepend(const String&     y); 
+  void              prepend(const SubString&  y);
+  void              prepend(const char* t);
+  void              prepend(char        c);
+
+
+// procedural versions:
+// concatenate first 2 args, store result in last arg
+
+  friend inline void     cat(const String&, const String&, String&);
+  friend inline void     cat(const String&, const SubString&, String&);
+  friend inline void     cat(const String&, const char*, String&);
+  friend inline void     cat(const String&, char, String&);
+
+  friend inline void     cat(const SubString&, const String&, String&);
+  friend inline void     cat(const SubString&, const SubString&, String&);
+  friend inline void     cat(const SubString&, const char*, String&);
+  friend inline void     cat(const SubString&, char, String&);
+
+  friend inline void     cat(const char*, const String&, String&);
+  friend inline void     cat(const char*, const SubString&, String&);
+  friend inline void     cat(const char*, const char*, String&);
+  friend inline void     cat(const char*, char, String&);
+
+// double concatenation, by request. (yes, there are too many versions, 
+// but if one is supported, then the others should be too...)
+// Concatenate first 3 args, store in last arg
+
+  friend inline void     cat(const String&,const String&, const String&,String&);
+  friend inline void     cat(const String&,const String&,const SubString&,String&);
+  friend inline void     cat(const String&,const String&, const char*, String&);
+  friend inline void     cat(const String&,const String&, char, String&);
+  friend inline void     cat(const String&,const SubString&,const String&,String&);
+  inline friend void     cat(const String&,const SubString&,const SubString&,String&);
+  friend inline void     cat(const String&,const SubString&, const char*, String&);
+  friend inline void     cat(const String&,const SubString&, char, String&);
+  friend inline void     cat(const String&,const char*, const String&,    String&);
+  friend inline void     cat(const String&,const char*, const SubString&, String&);
+  friend inline void     cat(const String&,const char*, const char*, String&);
+  friend inline void     cat(const String&,const char*, char, String&);
+
+  friend inline void     cat(const char*, const String&, const String&,String&);
+  friend inline void     cat(const char*,const String&,const SubString&,String&);
+  friend inline void     cat(const char*,const String&, const char*, String&);
+  friend inline void     cat(const char*,const String&, char, String&);
+  friend inline void     cat(const char*,const SubString&,const String&,String&);
+  friend inline void     cat(const char*,const SubString&,const SubString&,String&);
+  friend inline void     cat(const char*,const SubString&, const char*, String&);
+  friend inline void     cat(const char*,const SubString&, char, String&);
+  friend inline void     cat(const char*,const char*, const String&,    String&);
+  friend inline void     cat(const char*,const char*, const SubString&, String&);
+  friend inline void     cat(const char*,const char*, const char*, String&);
+  friend inline void     cat(const char*,const char*, char, String&);
+
+
+// searching & matching
+
+// return position of target in string or -1 for failure
+
+  int               index(char        c, int startpos = 0) const;      
+  int               index(const String&     y, int startpos = 0) const;      
+  int               index(const SubString&  y, int startpos = 0) const;      
+  int               index(const char* t, int startpos = 0) const;  
+  int               index(const Regex&      r, int startpos = 0) const;       
+
+// return 1 if target appears anyhere in String; else 0
+
+  int               contains(char        c) const;
+  int               contains(const String&     y) const;
+  int               contains(const SubString&  y) const;
+  int               contains(const char* t) const;
+  int               contains(const Regex&      r) const;
+
+// return 1 if target appears anywhere after position pos 
+// (or before, if pos is negative) in String; else 0
+
+  int               contains(char        c, int pos) const;
+  int               contains(const String&     y, int pos) const;
+  int               contains(const SubString&  y, int pos) const;
+  int               contains(const char* t, int pos) const;
+  int               contains(const Regex&      r, int pos) const;
+
+// return 1 if target appears at position pos in String; else 0
+
+  int               matches(char        c, int pos = 0) const;
+  int               matches(const String&     y, int pos = 0) const;
+  int               matches(const SubString&  y, int pos = 0) const;
+  int               matches(const char* t, int pos = 0) const;
+  int               matches(const Regex&      r, int pos = 0) const;
+
+//  return number of occurences of target in String
+
+  int               freq(char        c) const; 
+  int               freq(const String&     y) const;
+  int               freq(const SubString&  y) const;
+  int               freq(const char* t) const;
+
+// SubString extraction
+
+// Note that you can't take a substring of a const String, since
+// this leaves open the possiblility of indirectly modifying the
+// String through the SubString
+
+  SubString         at(int         pos, int len);
+  SubString         operator () (int         pos, int len); // synonym for at
+
+  SubString         at(const String&     x, int startpos = 0); 
+  SubString         at(const SubString&  x, int startpos = 0); 
+  SubString         at(const char* t, int startpos = 0);
+  SubString         at(char        c, int startpos = 0);
+  SubString         at(const Regex&      r, int startpos = 0); 
+
+  SubString         before(int          pos);
+  SubString         before(const String&      x, int startpos = 0);
+  SubString         before(const SubString&   x, int startpos = 0);
+  SubString         before(const char*  t, int startpos = 0);
+  SubString         before(char         c, int startpos = 0);
+  SubString         before(const Regex&       r, int startpos = 0);
+
+  SubString         through(int          pos);
+  SubString         through(const String&      x, int startpos = 0);
+  SubString         through(const SubString&   x, int startpos = 0);
+  SubString         through(const char*  t, int startpos = 0);
+  SubString         through(char         c, int startpos = 0);
+  SubString         through(const Regex&       r, int startpos = 0);
+
+  SubString         from(int          pos);
+  SubString         from(const String&      x, int startpos = 0);
+  SubString         from(const SubString&   x, int startpos = 0);
+  SubString         from(const char*  t, int startpos = 0);
+  SubString         from(char         c, int startpos = 0);
+  SubString         from(const Regex&       r, int startpos = 0);
+
+  SubString         after(int         pos);
+  SubString         after(const String&     x, int startpos = 0);
+  SubString         after(const SubString&  x, int startpos = 0);
+  SubString         after(const char* t, int startpos = 0);
+  SubString         after(char        c, int startpos = 0);
+  SubString         after(const Regex&      r, int startpos = 0);
+
+
+// deletion
+
+// delete len chars starting at pos
+  void              del(int         pos, int len);
+
+// delete the first occurrence of target after startpos
+
+  void              del(const String&     y, int startpos = 0);
+  void              del(const SubString&  y, int startpos = 0);
+  void              del(const char* t, int startpos = 0);
+  void              del(char        c, int startpos = 0);
+  void              del(const Regex&      r, int startpos = 0);
+
+// global substitution: substitute all occurrences of pat with repl
+
+  int               gsub(const String&     pat, const String&     repl);
+  int               gsub(const SubString&  pat, const String&     repl);
+  int               gsub(const char* pat, const String&     repl);
+  int               gsub(const char* pat, const char* repl);
+  int               gsub(const Regex&      pat, const String&     repl);
+
+// friends & utilities
+
+// split string into array res at separators; return number of elements
+
+  friend int        split(const String& x, String res[], int maxn, 
+                          const String& sep);
+  friend int        split(const String& x, String res[], int maxn, 
+                          const Regex&  sep);
+
+  friend String     common_prefix(const String& x, const String& y, 
+                                  int startpos = 0);
+  friend String     common_suffix(const String& x, const String& y, 
+                                  int startpos = -1);
+  friend String     replicate(char        c, int n);
+  friend String     replicate(const String&     y, int n);
+  friend String     join(String src[], int n, const String& sep);
+
+// simple builtin transformations
+
+  friend inline String     reverse(const String& x);
+  friend inline String     upcase(const String& x);
+  friend inline String     downcase(const String& x);
+  friend inline String     capitalize(const String& x);
+
+// in-place versions of above
+
+  void              reverse();
+  void              upcase();
+  void              downcase();
+  void              capitalize();
+
+// element extraction
+
+  char&             operator [] (int i);
+  const char&       operator [] (int i) const;
+  char              elem(int i) const;
+  char              firstchar() const;
+  char              lastchar() const;
+
+// conversion
+
+                    operator const char*() const;
+  const char*       chars() const;
+
+
+// IO
+
+  friend inline ostream&   operator<<(ostream& s, const String& x);
+  friend ostream&   operator<<(ostream& s, const SubString& x);
+  friend istream&   operator>>(istream& s, String& x);
+
+  friend int        readline(istream& s, String& x, 
+                             char terminator = '\n',
+                             int discard_terminator = 1);
+
+// status
+
+  unsigned int      length() const;
+  int               empty() const;
+
+// preallocate some space for String
+  void              alloc(int newsize);
+
+// report current allocation (not length!)
+
+  int               allocation() const;
+
+
+  void     error(const char* msg) const;
+
+  int               OK() const;
+};
+
+typedef String StrTmp; // for backward compatibility
+
+// other externs
+
+int        compare(const String&    x, const String&     y);
+int        compare(const String&    x, const SubString&  y);
+int        compare(const String&    x, const char* y);
+int        compare(const SubString& x, const String&     y);
+int        compare(const SubString& x, const SubString&  y);
+int        compare(const SubString& x, const char* y);
+int        fcompare(const String&   x, const String&     y); // ignore case
+
+extern StrRep  _nilStrRep;
+extern String _nilString;
+
+// status reports, needed before defining other things
+
+inline unsigned int String::length() const {  return rep->len; }
+inline int         String::empty() const { return rep->len == 0; }
+inline const char* String::chars() const { return &(rep->s[0]); }
+inline int         String::allocation() const { return rep->sz; }
+
+inline unsigned int SubString::length() const { return len; }
+inline int         SubString::empty() const { return len == 0; }
+inline const char* SubString::chars() const { return &(S.rep->s[pos]); }
+
+
+// constructors
+
+inline String::String() 
+  : rep(&_nilStrRep) {}
+inline String::String(const String& x) 
+  : rep(Scopy(0, x.rep)) {}
+inline String::String(const char* t) 
+  : rep(Salloc(0, t, -1, -1)) {}
+inline String::String(const char* t, int tlen)
+  : rep(Salloc(0, t, tlen, tlen)) {}
+inline String::String(const SubString& y)
+  : rep(Salloc(0, y.chars(), y.length(), y.length())) {}
+inline String::String(char c) 
+  : rep(Salloc(0, &c, 1, 1)) {}
+
+inline String::~String() { if (rep != &_nilStrRep) delete rep; }
+
+inline SubString::SubString(const SubString& x)
+  :S(x.S), pos(x.pos), len(x.len) {}
+inline SubString::SubString(String& x, int first, int l)
+  :S(x), pos(first), len(l) {}
+
+inline SubString::~SubString() {}
+
+// assignment
+
+inline String& String::operator =  (const String& y)
+{ 
+  rep = Scopy(rep, y.rep);
+  return *this;
+}
+
+inline String& String::operator=(const char* t)
+{
+  rep = Salloc(rep, t, -1, -1);
+  return *this;
+}
+
+inline String& String::operator=(const SubString&  y)
+{
+  rep = Salloc(rep, y.chars(), y.length(), y.length());
+  return *this;
+}
+
+inline String& String::operator=(char c)
+{
+  rep = Salloc(rep, &c, 1, 1);
+  return *this;
+}
+
+
+inline SubString& SubString::operator = (const char* ys)
+{
+  assign(0, ys);
+  return *this;
+}
+
+inline SubString& SubString::operator = (char ch)
+{
+  assign(0, &ch, 1);
+  return *this;
+}
+
+inline SubString& SubString::operator = (const String& y)
+{
+  assign(y.rep, y.chars(), y.length());
+  return *this;
+}
+
+inline SubString& SubString::operator = (const SubString& y)
+{
+  assign(y.S.rep, y.chars(), y.length());
+  return *this;
+}
+
+// Zillions of cats...
+
+inline void cat(const String& x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const String& x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const String& x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
+}
+
+inline void cat(const String& x, char y, String& r)
+{
+  r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
+}
+
+inline void cat(const SubString& x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const SubString& x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const SubString& x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
+}
+
+inline void cat(const SubString& x, char y, String& r)
+{
+  r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
+}
+
+inline void cat(const char* x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
+}
+
+inline void cat(const char* x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
+}
+
+inline void cat(const char* x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, x, -1, y, -1);
+}
+
+inline void cat(const char* x, char y, String& r)
+{
+  r.rep = Scat(r.rep, x, -1, &y, 1);
+}
+
+inline void cat(const String& a, const String& x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const String& a, const String& x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const String& a, const String& x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
+}
+
+inline void cat(const String& a, const String& x, char y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
+}
+
+inline void cat(const String& a, const SubString& x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const String& a, const SubString& x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const String& a, const SubString& x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
+}
+
+inline void cat(const String& a, const SubString& x, char y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
+}
+
+inline void cat(const String& a, const char* x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
+}
+
+inline void cat(const String& a, const char* x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
+}
+
+inline void cat(const String& a, const char* x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1);
+}
+
+inline void cat(const String& a, const char* x, char y, String& r)
+{
+  r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1);
+}
+
+
+inline void cat(const char* a, const String& x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const char* a, const String& x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const char* a, const String& x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
+}
+
+inline void cat(const char* a, const String& x, char y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
+}
+
+inline void cat(const char* a, const SubString& x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const char* a, const SubString& x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
+}
+
+inline void cat(const char* a, const SubString& x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
+}
+
+inline void cat(const char* a, const SubString& x, char y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
+}
+
+inline void cat(const char* a, const char* x, const String& y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
+}
+
+inline void cat(const char* a, const char* x, const SubString& y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
+}
+
+inline void cat(const char* a, const char* x, const char* y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x, -1, y, -1);
+}
+
+inline void cat(const char* a, const char* x, char y, String& r)
+{
+  r.rep = Scat(r.rep, a, -1, x, -1, &y, 1);
+}
+
+
+// operator versions
+
+inline String& String::operator +=(const String& y)
+{
+  cat(*this, y, *this);
+  return *this;
+}
+
+inline String& String::operator +=(const SubString& y)
+{
+  cat(*this, y, *this);
+  return *this;
+}
+
+inline String& String::operator += (const char* y)
+{
+  cat(*this, y, *this);
+  return *this;
+}
+
+inline String& String:: operator +=(char y)
+{
+  cat(*this, y, *this);
+  return *this;
+}
+
+// constructive concatenation
+
+#if defined(__GNUG__) && !defined(_G_NO_NRV)
+
+inline String operator + (const String& x, const String& y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const String& x, const SubString& y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const String& x, const char* y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const String& x, char y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const SubString& x, const String& y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const SubString& x, const SubString& y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const SubString& x, const char* y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const SubString& x, char y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const char* x, const String& y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String operator + (const char* x, const SubString& y) return r;
+{
+  cat(x, y, r);
+}
+
+inline String reverse(const String& x) return r;
+{
+  r.rep = Sreverse(x.rep, r.rep);
+}
+
+inline String upcase(const String& x) return r;
+{
+  r.rep = Supcase(x.rep, r.rep);
+}
+
+inline String downcase(const String& x) return r;
+{
+  r.rep = Sdowncase(x.rep, r.rep);
+}
+
+inline String capitalize(const String& x) return r;
+{
+  r.rep = Scapitalize(x.rep, r.rep);
+}
+
+#else /* NO_NRV */
+
+inline String operator + (const String& x, const String& y)
+{
+  String r;  cat(x, y, r);  return r;
+}
+
+inline String operator + (const String& x, const SubString& y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String operator + (const String& x, const char* y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String operator + (const String& x, char y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String operator + (const SubString& x, const String& y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String operator + (const SubString& x, const SubString& y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String operator + (const SubString& x, const char* y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String operator + (const SubString& x, char y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String operator + (const char* x, const String& y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String operator + (const char* x, const SubString& y) 
+{
+  String r; cat(x, y, r); return r;
+}
+
+inline String reverse(const String& x) 
+{
+  String r; r.rep = Sreverse(x.rep, r.rep); return r;
+}
+
+inline String upcase(const String& x) 
+{
+  String r; r.rep = Supcase(x.rep, r.rep); return r;
+}
+
+inline String downcase(const String& x) 
+{
+  String r; r.rep = Sdowncase(x.rep, r.rep); return r;
+}
+
+inline String capitalize(const String& x) 
+{
+  String r; r.rep = Scapitalize(x.rep, r.rep); return r;
+}
+
+#endif
+
+// prepend
+
+inline void String::prepend(const String& y)
+{
+  rep = Sprepend(rep, y.chars(), y.length());
+}
+
+inline void String::prepend(const char* y)
+{
+  rep = Sprepend(rep, y, -1); 
+}
+
+inline void String::prepend(char y)
+{
+  rep = Sprepend(rep, &y, 1); 
+}
+
+inline void String::prepend(const SubString& y)
+{
+  rep = Sprepend(rep, y.chars(), y.length());
+}
+
+// misc transformations
+
+
+inline void String::reverse()
+{
+  rep = Sreverse(rep, rep);
+}
+
+
+inline void String::upcase()
+{
+  rep = Supcase(rep, rep);
+}
+
+
+inline void String::downcase()
+{
+  rep = Sdowncase(rep, rep);
+}
+
+
+inline void String::capitalize()
+{
+  rep = Scapitalize(rep, rep);
+}
+
+// element extraction
+
+inline char&  String::operator [] (int i) 
+{ 
+  if (((unsigned)i) >= length()) error("invalid index");
+  return rep->s[i];
+}
+
+inline const char&  String::operator [] (int i) const
+{ 
+  if (((unsigned)i) >= length()) error("invalid index");
+  return rep->s[i];
+}
+
+inline char  String::elem (int i) const
+{ 
+  if (((unsigned)i) >= length()) error("invalid index");
+  return rep->s[i];
+}
+
+inline char  String::firstchar() const
+{ 
+  return elem(0);
+}
+
+inline char  String::lastchar() const
+{ 
+  return elem(length() - 1);
+}
+
+// searching
+
+inline int String::index(char c, int startpos) const
+{
+  return search(startpos, length(), c);
+}
+
+inline int String::index(const char* t, int startpos) const
+{   
+  return search(startpos, length(), t);
+}
+
+inline int String::index(const String& y, int startpos) const
+{   
+  return search(startpos, length(), y.chars(), y.length());
+}
+
+inline int String::index(const SubString& y, int startpos) const
+{   
+  return search(startpos, length(), y.chars(), y.length());
+}
+
+inline int String::index(const Regex& r, int startpos) const
+{
+  int unused;  return r.search(chars(), length(), unused, startpos);
+}
+
+inline int String::contains(char c) const
+{
+  return search(0, length(), c) >= 0;
+}
+
+inline int String::contains(const char* t) const
+{   
+  return search(0, length(), t) >= 0;
+}
+
+inline int String::contains(const String& y) const
+{   
+  return search(0, length(), y.chars(), y.length()) >= 0;
+}
+
+inline int String::contains(const SubString& y) const
+{   
+  return search(0, length(), y.chars(), y.length()) >= 0;
+}
+
+inline int String::contains(char c, int p) const
+{
+  return match(p, length(), 0, &c, 1) >= 0;
+}
+
+inline int String::contains(const char* t, int p) const
+{
+  return match(p, length(), 0, t) >= 0;
+}
+
+inline int String::contains(const String& y, int p) const
+{
+  return match(p, length(), 0, y.chars(), y.length()) >= 0;
+}
+
+inline int String::contains(const SubString& y, int p) const
+{
+  return match(p, length(), 0, y.chars(), y.length()) >= 0;
+}
+
+inline int String::contains(const Regex& r) const
+{
+  int unused;  return r.search(chars(), length(), unused, 0) >= 0;
+}
+
+inline int String::contains(const Regex& r, int p) const
+{
+  return r.match(chars(), length(), p) >= 0;
+}
+
+
+inline int String::matches(const SubString& y, int p) const
+{
+  return match(p, length(), 1, y.chars(), y.length()) >= 0;
+}
+
+inline int String::matches(const String& y, int p) const
+{
+  return match(p, length(), 1, y.chars(), y.length()) >= 0;
+}
+
+inline int String::matches(const char* t, int p) const
+{
+  return match(p, length(), 1, t) >= 0;
+}
+
+inline int String::matches(char c, int p) const
+{
+  return match(p, length(), 1, &c, 1) >= 0;
+}
+
+inline int String::matches(const Regex& r, int p) const
+{
+  int l = (p < 0)? -p : length() - p;
+  return r.match(chars(), length(), p) == l;
+}
+
+
+inline int SubString::contains(const char* t) const
+{   
+  return S.search(pos, pos+len, t) >= 0;
+}
+
+inline int SubString::contains(const String& y) const
+{   
+  return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
+}
+
+inline int SubString::contains(const SubString&  y) const
+{   
+  return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
+}
+
+inline int SubString::contains(char c) const
+{
+  return S.search(pos, pos+len, c) >= 0;
+}
+
+inline int SubString::contains(const Regex& r) const
+{
+  int unused;  return r.search(chars(), len, unused, 0) >= 0;
+}
+
+inline int SubString::matches(const Regex& r) const
+{
+  return r.match(chars(), len, 0) == len;
+}
+
+
+inline int String::gsub(const String& pat, const String& r)
+{
+  return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
+}
+
+inline int String::gsub(const SubString&  pat, const String& r)
+{
+  return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
+}
+
+inline int String::gsub(const Regex& pat, const String& r)
+{
+  return _gsub(pat, r.chars(), r.length());
+}
+
+inline int String::gsub(const char* pat, const String& r)
+{
+  return _gsub(pat, -1, r.chars(), r.length());
+}
+
+inline int String::gsub(const char* pat, const char* r)
+{
+  return _gsub(pat, -1, r, -1);
+}
+
+
+
+inline  ostream& operator<<(ostream& s, const String& x)
+{
+   s << x.chars(); return s;
+}
+
+// a zillion comparison operators
+
+inline int operator==(const String& x, const String& y) 
+{
+  return compare(x, y) == 0; 
+}
+
+inline int operator!=(const String& x, const String& y)
+{
+  return compare(x, y) != 0; 
+}
+
+inline int operator>(const String& x, const String& y)
+{
+  return compare(x, y) > 0; 
+}
+
+inline int operator>=(const String& x, const String& y)
+{
+  return compare(x, y) >= 0; 
+}
+
+inline int operator<(const String& x, const String& y)
+{
+  return compare(x, y) < 0; 
+}
+
+inline int operator<=(const String& x, const String& y)
+{
+  return compare(x, y) <= 0; 
+}
+
+inline int operator==(const String& x, const SubString&  y) 
+{
+  return compare(x, y) == 0; 
+}
+
+inline int operator!=(const String& x, const SubString&  y)
+{
+  return compare(x, y) != 0; 
+}
+
+inline int operator>(const String& x, const SubString&  y)      
+{
+  return compare(x, y) > 0; 
+}
+
+inline int operator>=(const String& x, const SubString&  y)
+{
+  return compare(x, y) >= 0; 
+}
+
+inline int operator<(const String& x, const SubString&  y) 
+{
+  return compare(x, y) < 0; 
+}
+
+inline int operator<=(const String& x, const SubString&  y)
+{
+  return compare(x, y) <= 0; 
+}
+
+inline int operator==(const String& x, const char* t) 
+{
+  return compare(x, t) == 0; 
+}
+
+inline int operator!=(const String& x, const char* t) 
+{
+  return compare(x, t) != 0; 
+}
+
+inline int operator>(const String& x, const char* t)  
+{
+  return compare(x, t) > 0; 
+}
+
+inline int operator>=(const String& x, const char* t) 
+{
+  return compare(x, t) >= 0; 
+}
+
+inline int operator<(const String& x, const char* t)  
+{
+  return compare(x, t) < 0; 
+}
+
+inline int operator<=(const String& x, const char* t) 
+{
+  return compare(x, t) <= 0; 
+}
+
+inline int operator==(const SubString& x, const String& y) 
+{
+  return compare(y, x) == 0; 
+}
+
+inline int operator!=(const SubString& x, const String& y)
+{
+  return compare(y, x) != 0;
+}
+
+inline int operator>(const SubString& x, const String& y)      
+{
+  return compare(y, x) < 0;
+}
+
+inline int operator>=(const SubString& x, const String& y)     
+{
+  return compare(y, x) <= 0;
+}
+
+inline int operator<(const SubString& x, const String& y)      
+{
+  return compare(y, x) > 0;
+}
+
+inline int operator<=(const SubString& x, const String& y)     
+{
+  return compare(y, x) >= 0;
+}
+
+inline int operator==(const SubString& x, const SubString&  y) 
+{
+  return compare(x, y) == 0; 
+}
+
+inline int operator!=(const SubString& x, const SubString&  y)
+{
+  return compare(x, y) != 0;
+}
+
+inline int operator>(const SubString& x, const SubString&  y)      
+{
+  return compare(x, y) > 0;
+}
+
+inline int operator>=(const SubString& x, const SubString&  y)
+{
+  return compare(x, y) >= 0;
+}
+
+inline int operator<(const SubString& x, const SubString&  y) 
+{
+  return compare(x, y) < 0;
+}
+
+inline int operator<=(const SubString& x, const SubString&  y)
+{
+  return compare(x, y) <= 0;
+}
+
+inline int operator==(const SubString& x, const char* t) 
+{
+  return compare(x, t) == 0; 
+}
+
+inline int operator!=(const SubString& x, const char* t) 
+{
+  return compare(x, t) != 0;
+}
+
+inline int operator>(const SubString& x, const char* t)  
+{
+  return compare(x, t) > 0; 
+}
+
+inline int operator>=(const SubString& x, const char* t) 
+{
+  return compare(x, t) >= 0; 
+}
+
+inline int operator<(const SubString& x, const char* t)  
+{
+  return compare(x, t) < 0; 
+}
+
+inline int operator<=(const SubString& x, const char* t) 
+{
+  return compare(x, t) <= 0; 
+}
+
+
+// a helper needed by at, before, etc.
+
+inline SubString String::_substr(int first, int l)
+{
+  if (first < 0 || (unsigned)(first + l) > length() )
+    return SubString(_nilString, 0, 0) ;
+  else 
+    return SubString(*this, first, l);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Uniform.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Uniform.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Uniform.h	(revision 18)
@@ -0,0 +1,71 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _Uniform_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Uniform_h 1
+
+#include <Random.h>
+
+//
+//	The interval [lo..hi]
+// 
+
+class Uniform: public Random {
+    double pLow;
+    double pHigh;
+    double delta;
+public:
+    Uniform(double low, double high, RNG *gen);
+
+    double low();
+    double low(double x);
+    double high();
+    double high(double x);
+
+    virtual double operator()();
+};
+
+
+inline Uniform::Uniform(double low, double high, RNG *gen) : Random(gen)
+{
+    pLow = (low < high) ? low : high;
+    pHigh = (low < high) ? high : low;
+    delta = pHigh - pLow;
+}
+
+inline double Uniform::low() { return pLow; }
+
+inline double Uniform::low(double x) {
+  double tmp = pLow;
+  pLow = x;
+  delta = pHigh - pLow;
+  return tmp;
+}
+
+inline double Uniform::high() { return pHigh; }
+
+inline double Uniform::high(double x) {
+  double tmp = pHigh;
+  pHigh = x;
+  delta = pHigh - pLow;
+  return tmp;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/Weibull.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/Weibull.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/Weibull.h	(revision 18)
@@ -0,0 +1,74 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef _Weibull_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _Weibull_h 
+
+#include <Random.h>
+
+class Weibull: public Random {
+protected:
+    double pAlpha;
+    double pInvAlpha;
+    double pBeta;
+
+    void setState();
+    
+public:
+    Weibull(double alpha, double beta, RNG *gen);
+
+    double alpha();
+    double alpha(double x);
+
+    double beta();
+    double beta(double x);
+
+    virtual double operator()();
+};
+
+
+inline void Weibull::setState() {
+  pInvAlpha = 1.0 / pAlpha;
+}
+    
+inline Weibull::Weibull(double alpha, double beta,  RNG *gen) : Random(gen)
+{
+  pAlpha = alpha;
+  pBeta = beta;
+  setState();
+}
+
+inline double Weibull::alpha() { return pAlpha; }
+
+inline double Weibull::alpha(double x) {
+  double tmp = pAlpha;
+  pAlpha = x;
+  setState();
+  return tmp;
+}
+
+inline double Weibull::beta() { return pBeta; };
+inline double Weibull::beta(double x) {
+  double tmp = pBeta;
+  pBeta = x;
+  return tmp;
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/_G_confi.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/_G_confi.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/_G_confi.h	(revision 18)
@@ -0,0 +1,90 @@
+/* AUTOMATICALLY GENERATED; DO NOT EDIT! */ 
+#ifndef _G_config_h
+#define _G_config_h
+#define _G_LIB_VERSION "8.1.1.1"
+#define _G_NAMES_HAVE_UNDERSCORE 1
+#define _G_VTABLE_LABEL_HAS_LENGTH 1
+#define _G_VTABLE_LABEL_PREFIX "__vt$"
+#define _G_VTABLE_LABEL_PREFIX_ID __vt$
+#define _G_HAVE_ST_BLKSIZE 0
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+typedef          int   _G_int8_t __attribute__((__mode__(__QI__)));
+typedef unsigned int  _G_uint8_t __attribute__((__mode__(__QI__)));
+typedef          int  _G_int16_t __attribute__((__mode__(__HI__)));
+typedef unsigned int _G_uint16_t __attribute__((__mode__(__HI__)));
+typedef          int  _G_int32_t __attribute__((__mode__(__SI__)));
+typedef unsigned int _G_uint32_t __attribute__((__mode__(__SI__)));
+typedef          int  _G_int64_t __attribute__((__mode__(__DI__)));
+typedef unsigned int _G_uint64_t __attribute__((__mode__(__DI__)));
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 8
+__extension__ typedef long long _G_llong;
+__extension__ typedef unsigned long long _G_ullong;
+#endif
+#else
+typedef  short /* deduced */  _G_int16_t;
+typedef unsigned short /* deduced */ _G_uint16_t;
+typedef  long /* deduced */  _G_int32_t;
+typedef unsigned long /* deduced */ _G_uint32_t;
+#endif
+
+typedef long _G_clock_t;
+typedef int _G_dev_t;
+typedef long _G_fpos_t;
+typedef int _G_gid_t;
+typedef int _G_ino_t;
+typedef int _G_mode_t;
+typedef int _G_nlink_t;
+typedef long _G_off_t;
+typedef int _G_pid_t;
+#ifndef __PTRDIFF_TYPE__
+#define __PTRDIFF_TYPE__ long
+#endif
+typedef __PTRDIFF_TYPE__ _G_ptrdiff_t;
+typedef unsigned long _G_sigset_t;
+#ifndef __SIZE_TYPE__
+#define __SIZE_TYPE__ unsigned long
+#endif
+typedef __SIZE_TYPE__ _G_size_t;
+typedef unsigned long _G_time_t;
+typedef int _G_uid_t;
+typedef unsigned short _G_wchar_t;
+
+#define _G_BUFSIZ 5120
+#define _G_FOPEN_MAX 14
+#define _G_FILENAME_MAX 260
+#if defined (__cplusplus) || defined (__STDC__)
+#define _G_ARGS(ARGLIST) ARGLIST
+#else
+#define _G_ARGS(ARGLIST) ()
+#endif
+#if !defined (__GNUG__) || defined (__STRICT_ANSI__)
+#define _G_NO_NRV
+#endif
+#if !defined (__GNUG__)
+#define _G_NO_EXTERN_TEMPLATES
+#endif
+typedef int _G_ssize_t;
+typedef int /* default */ _G_wint_t;
+typedef char * _G_va_list;
+#define _G_signal_return_type void
+#define _G_sprintf_return_type int
+#define _G_HAVE_ATEXIT 1
+#define _G_HAVE_SYS_RESOURCE 0
+#define _G_HAVE_SYS_TIMES 1
+#define _G_HAVE_SYS_SOCKET 1
+#define _G_HAVE_SYS_CDEFS 0     /* Don't require bsddev.zip */
+#define _G_HAVE_SYS_WAIT 1
+#define _G_HAVE_UNISTD 1
+#define _G_HAVE_DIRENT 1
+#define _G_HAVE_CURSES 1
+#define _G_MATH_H_INLINES 0
+#define _G_HAVE_BOOL 1
+#define _G_HAVE_PRINTF_FP 0
+#define _G_HAVE_LONG_DOUBLE_IO 0
+#if 0
+#undef NULL
+#define __need_NULL
+#include <stddef.h>
+#endif
+#endif /* !_G_config_h */
Index: trunk/src/emx/include/Attic/cpp/algo.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/algo.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/algo.h	(revision 18)
@@ -0,0 +1,114 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_ALGO_H
+#define __SGI_STL_ALGO_H
+
+#include <algobase.h>
+#include <tempbuf.h>
+#include <stl_algo.h>
+#include <stl_nume.h>
+
+#ifdef __STL_USE_NAMESPACES
+
+// Names from <stl_algo.h>
+using __STD::for_each; 
+using __STD::find; 
+using __STD::find_if; 
+using __STD::adjacent_find; 
+using __STD::count; 
+using __STD::count_if; 
+using __STD::search; 
+using __STD::search_n; 
+using __STD::swap_ranges; 
+using __STD::transform; 
+using __STD::replace; 
+using __STD::replace_if; 
+using __STD::replace_copy; 
+using __STD::replace_copy_if; 
+using __STD::generate; 
+using __STD::generate_n; 
+using __STD::remove; 
+using __STD::remove_if; 
+using __STD::remove_copy; 
+using __STD::remove_copy_if; 
+using __STD::unique; 
+using __STD::unique_copy; 
+using __STD::reverse; 
+using __STD::reverse_copy; 
+using __STD::rotate; 
+using __STD::rotate_copy; 
+using __STD::random_shuffle; 
+using __STD::random_sample; 
+using __STD::random_sample_n; 
+using __STD::partition; 
+using __STD::stable_partition; 
+using __STD::sort; 
+using __STD::stable_sort; 
+using __STD::partial_sort; 
+using __STD::partial_sort_copy; 
+using __STD::nth_element; 
+using __STD::lower_bound; 
+using __STD::upper_bound; 
+using __STD::equal_range; 
+using __STD::binary_search; 
+using __STD::merge; 
+using __STD::inplace_merge; 
+using __STD::includes; 
+using __STD::set_union; 
+using __STD::set_intersection; 
+using __STD::set_difference; 
+using __STD::set_symmetric_difference; 
+using __STD::min_element; 
+using __STD::max_element; 
+using __STD::next_permutation; 
+using __STD::prev_permutation; 
+using __STD::find_first_of; 
+using __STD::find_end; 
+using __STD::is_sorted; 
+using __STD::is_heap; 
+
+// Names from stl_heap.h
+using __STD::push_heap;
+using __STD::pop_heap;
+using __STD::make_heap;
+using __STD::sort_heap;
+
+// Names from <stl_numeric.h>
+using __STD::accumulate; 
+using __STD::inner_product; 
+using __STD::partial_sum; 
+using __STD::adjacent_difference; 
+using __STD::power; 
+using __STD::iota; 
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_ALGO_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/algobase.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/algobase.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/algobase.h	(revision 18)
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_ALGOBASE_H
+#define __SGI_STL_ALGOBASE_H
+
+#ifndef __SGI_STL_PAIR_H
+#include <pair.h>
+#endif
+#ifndef __SGI_STL_ITERATOR_H
+#include <iterator.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_ALGOBASE_H
+#include <stl_algb.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_UNINITIALIZED_H
+#include <stl_unin.h>
+#endif
+
+#ifdef __STL_USE_NAMESPACES
+
+// Names from stl_algobase.h
+using __STD::iter_swap; 
+using __STD::swap; 
+using __STD::min; 
+using __STD::max; 
+using __STD::copy; 
+using __STD::copy_backward; 
+using __STD::copy_n; 
+using __STD::fill; 
+using __STD::fill_n; 
+using __STD::mismatch; 
+using __STD::equal; 
+using __STD::lexicographical_compare; 
+using __STD::lexicographical_compare_3way; 
+
+// Names from stl_uninitialized.h
+using __STD::uninitialized_copy;
+using __STD::uninitialized_copy_n;
+using __STD::uninitialized_fill;
+using __STD::uninitialized_fill_n;
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_ALGOBASE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/algorith
===================================================================
--- trunk/src/emx/include/Attic/cpp/algorith	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/algorith	(revision 18)
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_ALGORITHM
+#define __SGI_STL_ALGORITHM
+
+#include <stl_algb.h>
+#include <stl_cons.h>
+#include <stl_temp.h>
+#include <stl_algo.h>
+
+#endif /* __SGI_STL_ALGORITHM */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/alloc.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/alloc.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/alloc.h	(revision 18)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996-1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_ALLOC_H
+#define __SGI_STL_ALLOC_H
+
+#ifndef __STL_CONFIG_H
+#include <stl_conf.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_ALLOC_H
+#include <stl_allo.h>
+#endif
+
+#ifdef __STL_USE_NAMESPACES
+
+using __STD::__malloc_alloc_template; 
+using __STD::malloc_alloc; 
+using __STD::simple_alloc; 
+using __STD::debug_alloc; 
+using __STD::__default_alloc_template; 
+using __STD::alloc; 
+using __STD::single_client_alloc; 
+#ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
+using __STD::__malloc_alloc_oom_handler; 
+#endif /* __STL_STATIC_TEMPLATE_MEMBER_BUG */
+
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_ALLOC_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/bitdo1.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/bitdo1.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/bitdo1.h	(revision 18)
@@ -0,0 +1,32 @@
+#ifndef ONES
+#define ONES  ((_BS_word)(~0L))
+#endif
+  register int nwords;
+  register _BS_word mask;
+  if (offset == 0)
+    ;
+  else if (offset + length >= _BS_BITS_PER_WORD)
+    {
+      mask = ONES _BS_RIGHT offset;
+      DOIT(*ptr++, mask);
+      length -= _BS_BITS_PER_WORD - offset;
+    }
+  else
+    {
+      mask = (ONES _BS_RIGHT (_BS_BITS_PER_WORD - length))
+	_BS_LEFT (_BS_BITS_PER_WORD - length - offset);
+      DOIT(*ptr, mask);
+      goto done;
+    }
+  nwords = _BS_INDEX(length);
+  while (--nwords >= 0)
+   {
+     DOIT(*ptr++, ONES);
+   }
+  length = _BS_POS (length);
+  if (length)
+    {
+      mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length);
+      DOIT(*ptr, mask);
+    }
+ done: ;
Index: trunk/src/emx/include/Attic/cpp/bitdo2.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/bitdo2.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/bitdo2.h	(revision 18)
@@ -0,0 +1,184 @@
+#ifndef ONES
+#define ONES  ((_BS_word)(~0L))
+#endif
+
+#ifndef DOIT_SOLID
+#ifdef DOIT
+#define DOIT_SOLID(dst, src) DOIT(dst, src, (_BS_word)(~0))
+#else
+#define DOIT_SOLID(dst, src) (dst) = (COMBINE(dst, src))
+#endif
+#endif
+
+#ifndef DOIT
+#define DOIT(dst, src, mask) \
+  (dst) = ((COMBINE(dst, src)) & (mask)) | ((dst) & ~(mask))
+#endif
+
+  _BS_word word0, mask;
+  int shift0, shift1;
+
+  if (length == 0)
+    goto done;
+
+  shift0 = srcbit - dstbit;
+
+  /* First handle the case that only one destination word is touched. */
+  if (length + dstbit <= _BS_BITS_PER_WORD)
+    {
+      _BS_word mask
+	= (ONES _BS_LEFT (_BS_BITS_PER_WORD - length)) _BS_RIGHT dstbit;
+      _BS_word word0 = *psrc++;
+      if (shift0 <= 0)  /* dstbit >= srcbit */
+        {
+	  word0 = word0 _BS_RIGHT (-shift0);
+	}
+      else
+	{
+	  word0 = word0 _BS_LEFT shift0;
+	  if (length + srcbit > _BS_BITS_PER_WORD)
+	    word0 = word0 | (*psrc _BS_RIGHT (_BS_BITS_PER_WORD - shift0));
+	}
+      DOIT(*pdst, word0, mask);
+      goto done;
+    }
+
+  /* Next optimize the case that the source and destination are aligned. */
+  if (shift0 == 0)
+    {
+      _BS_word mask;
+      if (psrc > pdst)
+        {
+	  if (srcbit)
+	    {
+	      mask = ONES _BS_RIGHT srcbit;
+	      DOIT(*pdst, *psrc, mask);
+	      pdst++; psrc++;
+	      length -= _BS_BITS_PER_WORD - srcbit;
+	    }
+	  for (; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
+	    {
+	      DOIT_SOLID(*pdst, *psrc);
+	      pdst++;  psrc++;
+	    }
+	  if (length)
+	    {
+	      mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length);
+	      DOIT(*pdst, *psrc, mask);
+	    }
+        }
+      else if (psrc < pdst)
+        {
+	  _BS_size_t span = srcbit + length;
+	  pdst += span / (_BS_size_t)_BS_BITS_PER_WORD;
+	  psrc += span / (_BS_size_t)_BS_BITS_PER_WORD;
+	  span %= (_BS_size_t)_BS_BITS_PER_WORD;
+	  if (span)
+	    {
+	      mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - span);
+	      DOIT(*pdst, *psrc, mask);
+	      length -= span;
+	    }
+	  pdst--;  psrc--;
+	  for (; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
+	    {
+	      DOIT_SOLID(*pdst, *psrc);
+	      pdst--;  psrc--;
+	    }
+	  if (srcbit)
+	    {
+	      mask = ONES _BS_RIGHT srcbit;
+	      DOIT(*pdst, *psrc, mask);
+	    }
+	}
+      /* else if (psrc == pdst) --nothing to do--; */
+      goto done;
+    }
+
+  /* Now we assume shift!=0, and more than on destination word is changed. */
+  if (psrc >= pdst) /* Do the updates in forward direction. */
+    {
+      _BS_word word0 = *psrc++;
+      _BS_word mask = ONES _BS_RIGHT dstbit;
+      if (shift0 > 0)
+        {
+	  _BS_word word1 = *psrc++;
+	  shift1 = _BS_BITS_PER_WORD - shift0;
+	  DOIT(*pdst, (word0 _BS_LEFT shift0) | (word1 _BS_RIGHT shift1), mask);
+	  word0 = word1;
+        }
+      else /* dstbit > srcbit */
+        {
+	  shift1 = -shift0;
+	  shift0 += _BS_BITS_PER_WORD;
+	  DOIT(*pdst, word0 _BS_RIGHT shift1, mask);
+      }
+      pdst++;
+      length -= _BS_BITS_PER_WORD - dstbit;
+
+      for ( ; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
+        {
+	  register _BS_word word1 = *psrc++;
+	  DOIT_SOLID(*pdst,
+		     (word0 _BS_LEFT shift0) | (word1 _BS_RIGHT shift1));
+	  pdst++;
+	  word0 = word1;
+        }
+      if (length > 0)
+        {
+	  _BS_size_t mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length);
+	  word0 = word0 _BS_LEFT shift0;
+	  if (length > shift1)
+	    word0 = word0 | (*psrc _BS_RIGHT shift1) ;
+	  DOIT (*pdst, word0, mask);
+        }
+    }
+  else /* Do the updates in backward direction. */
+    {
+      _BS_word word0;
+
+      /* Make (psrc, srcbit) and (pdst, dstbit) point to *last* bit. */
+      psrc += (srcbit + length  - 1) / _BS_BITS_PER_WORD;
+      srcbit = (srcbit + length - 1) % _BS_BITS_PER_WORD;
+      pdst += (dstbit + length - 1) / _BS_BITS_PER_WORD;
+      dstbit = (dstbit + length - 1) % _BS_BITS_PER_WORD;
+
+      shift0 = srcbit - dstbit;
+
+      word0 = *psrc--;
+      mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - 1 - dstbit);
+      if (shift0 < 0)
+        {
+	  _BS_word word1 = *psrc--;
+	  shift1 = -shift0;
+	  shift0 += _BS_BITS_PER_WORD;
+	  DOIT (*pdst, (word0 _BS_RIGHT shift1) | (word1 _BS_LEFT shift0),
+		mask);
+	  word0 = word1;
+        }
+      else
+        {
+	  shift1 = _BS_BITS_PER_WORD - shift0;
+	  DOIT(*pdst, word0 _BS_LEFT shift0, mask);
+      }
+      pdst--;
+      length -= dstbit + 1;
+
+      for ( ; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
+        {
+	  register _BS_word word1 = *psrc--;
+	  DOIT_SOLID(*pdst,
+		     (word0 _BS_RIGHT shift1) | (word1 _BS_LEFT shift0));
+	  pdst--;
+	  word0 = word1;
+        }
+      if (length > 0)
+        {
+	  _BS_size_t mask = ONES _BS_RIGHT (_BS_BITS_PER_WORD - length);
+	  word0 = word0 _BS_RIGHT shift1;
+	  if (length > shift0)
+	    word0 = word0 | (*psrc _BS_LEFT shift0) ;
+	  DOIT (*pdst, word0, mask);
+        }
+    }
+ done: ;
Index: trunk/src/emx/include/Attic/cpp/bitprims.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/bitprims.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/bitprims.h	(revision 18)
@@ -0,0 +1,125 @@
+#ifndef _BS_PRIMS
+#define _BS_PRIMS
+
+/* A bitstring is an array of _BS_word. */
+typedef unsigned long _BS_word;
+
+#define _BS_CHAR_BIT 8
+#define _BS_BITS_PER_WORD (_BS_CHAR_BIT*sizeof(_BS_word))
+#define _BS_WORDS_NEEDED(NBITS) ((NBITS+_BS_BITS_PER_WORD-1)/_BS_BITS_PER_WORD)
+
+/* For now, we number the bits in a _BS_word in little-endian order.
+   Later, might use machine order. */
+#ifdef CHILL_LIB
+#ifndef BITS_BIG_ENDIAN
+#include "config.h"
+#endif
+#define _BS_BIGENDIAN BITS_BIG_ENDIAN
+#else
+#define _BS_BIGENDIAN 0
+#endif
+
+/* By "left" we mean where bit number 0 is.
+   Hence, so left shift is << if we're numbering the bits in big-endian oder,
+   and >> if we're numbering the bits in little-endian order.
+   Currently, we always use little-endian order.
+   Later, we might use machine-endian order. */
+#if _BS_BIGENDIAN
+#define _BS_LEFT <<
+#define _BS_RIGHT >>
+#else
+#define _BS_LEFT >>
+#define _BS_RIGHT <<
+#endif
+
+#if _BS_BIGENDIAN
+#define _BS_BITMASK(BITNO) ((_BS_word)1 << (_BS_BITS_PER_WORD - 1 - (BITNO)))
+#else
+#define _BS_BITMASK(BITNO) ((_BS_word)1 << (BITNO))
+#endif
+
+/* Given a PTR which may not be aligned on a _BS_word boundary,
+   set NEW_PTR to point to (the beginning of) the corresponding _BS_word.
+   Adjust the bit-offset OFFSET to compensate for the difference. */
+#define _BS_ADJUST_ALIGNED(NEW_PTR, PTR, OFFSET) \
+  ( (NEW_PTR) = (_BS_word*)(((char*)(PTR)-(char*)0) & ~(sizeof(_BS_word)-1)), \
+    (OFFSET) += (char*)(PTR) - (char*)(NEW_PTR) )
+
+/* Given a bit pointer (PTR, OFFSET) normalize it so that
+   OFFSET < _BS_BITS_PER_WORD. */
+#define _BS_NORMALIZE(PTR, OFFSET) \
+{ _BS_size_t __tmp_ind = _BS_INDEX (OFFSET); \
+  (PTR) += __tmp_ind; \
+  (OFFSET) -= __tmp_ind * _BS_BITS_PER_WORD; }
+
+#define _BS_INDEX(I) ((unsigned)(I) / _BS_BITS_PER_WORD)
+#define _BS_POS(I) ((I) & (_BS_BITS_PER_WORD -1 ))
+
+#ifndef _BS_size_t
+#if __GNUC__ > 1
+#define _BS_size_t __SIZE_TYPE__
+#else
+#define _BS_size_t unsigned long
+#endif
+#endif
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif /*!__P*/
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+#if !defined(__STDC__) && !defined(void)
+#define void int
+#endif
+
+/* The 16 2-operand raster-ops:
+   These match the correspodning GX codes in X11. */
+enum _BS_alu {
+  _BS_alu_clear        =  0 /* 0 */,
+  _BS_alu_and          =  1 /* src & dst */,
+  _BS_alu_andReverse   =  2 /* src & ~dst */,
+  _BS_alu_copy         =  3 /* src */,
+  _BS_alu_andInverted  =  4 /* ~src & dst */,
+  _BS_alu_noop         =  5 /* dst */,
+  _BS_alu_xor          =  6 /* src ^ dst */,
+  _BS_alu_or           =  7 /* src | dst */,
+  _BS_alu_nor          =  8 /* ~src & ~dst */,
+  _BS_alu_equiv        =  9 /* ~(src ^ dst) */,
+  _BS_alu_invert       = 10 /* ~dst */,
+  _BS_alu_orReverse    = 11 /* src | ~dst */,
+  _BS_alu_copyInverted = 12 /* ~src */,
+  _BS_alu_orInverted   = 13 /* ~src | dst */,
+  _BS_alu_nand         = 14 /* ~src | d~st */,
+  _BS_alu_set          = 15 /* ~src | dst */
+};
+#define _BS
+#define _BS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void _BS_and __P((_BS_word*,int, const _BS_word*, int, _BS_size_t));
+extern void _BS_blt __P((enum _BS_alu,
+			     _BS_word*,int, const _BS_word*,int, _BS_size_t));
+extern void _BS_copy __P((_BS_word*,int, const _BS_word*,int, _BS_size_t));
+#define _BS_copy_0(DS, SS, LENGTH) _BS_copy(DS, 0, SS, 0, LENGTH)
+extern int _BS_count __P((const _BS_word*, int, _BS_size_t));
+extern int _BS_any __P((const _BS_word*, int, _BS_size_t));
+extern void _BS_clear __P((_BS_word*, int, _BS_size_t));
+extern void _BS_set __P((_BS_word*, int, _BS_size_t));
+extern void _BS_invert __P((_BS_word*, int, _BS_size_t));
+int _BS_lcompare_0 __P((const _BS_word*, _BS_size_t,
+			const _BS_word*, _BS_size_t));
+extern void _BS_xor __P((_BS_word*,int, const _BS_word*,int, _BS_size_t));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_BS_PRIMS */
Index: trunk/src/emx/include/Attic/cpp/bool.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/bool.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/bool.h	(revision 18)
@@ -0,0 +1,24 @@
+// Defining TRUE and FALSE is usually a Bad Idea,
+// because you will probably be inconsistent with anyone
+// else who had the same clever idea.
+// Therefore:  DON'T USE THIS FILE.
+
+#ifndef _bool_h
+#define _bool_h 1
+
+#include   <_G_confi.h>
+
+#if _G_HAVE_BOOL
+#undef TRUE
+#undef FALSE
+#define TRUE true
+#define FALSE false
+#else
+#undef FALSE
+#undef TRUE
+#undef true
+#undef false
+enum bool { FALSE = 0, false = 0, TRUE = 1, true = 1 };
+#endif
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/builtin.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/builtin.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/builtin.h	(revision 18)
@@ -0,0 +1,125 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+/* 
+Copyright (C) 1988, 1992 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+  arithmetic, etc. functions on built in types
+*/
+
+
+#ifndef _builtin_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _builtin_h 1
+
+#include <stddef.h>
+#include <std.h>
+#include <cmath>
+
+#ifndef __GNUC__
+#define __attribute__(x)
+#endif
+
+typedef void (*one_arg_error_handler_t)(const char*);
+typedef void (*two_arg_error_handler_t)(const char*, const char*);
+
+long         gcd(long, long);
+long         lg(unsigned long); 
+double       pow(double, long);
+long         pow(long, long);
+
+extern "C" double       start_timer();
+extern "C" double       return_elapsed_time(double last_time = 0.0);
+
+char*        dtoa(double x, char cvt = 'g', int width = 0, int prec = 6);
+
+unsigned int hashpjw(const char*);
+unsigned int multiplicativehash(int);
+unsigned int foldhash(double);
+
+extern void default_one_arg_error_handler(const char*) __attribute__ ((noreturn));
+extern void default_two_arg_error_handler(const char*, const char*) __attribute__ ((noreturn));
+
+extern two_arg_error_handler_t lib_error_handler;
+
+extern two_arg_error_handler_t 
+       set_lib_error_handler(two_arg_error_handler_t f);
+
+
+#if !defined(IV)
+
+inline short abs(short arg) 
+{
+  return (arg < 0)? -arg : arg;
+}
+
+inline int sign(long arg)
+{
+  return (arg == 0) ? 0 : ( (arg > 0) ? 1 : -1 );
+}
+
+inline int sign(double arg)
+{
+  return (arg == 0.0) ? 0 : ( (arg > 0.0) ? 1 : -1 );
+}
+
+inline long sqr(long arg)
+{
+  return arg * arg;
+}
+
+#if ! _G_MATH_H_INLINES /* hpux and SCO define this in math.h */
+inline double sqr(double arg)
+{
+  return arg * arg;
+}
+#endif
+
+inline int even(long arg)
+{
+  return !(arg & 1);
+}
+
+inline int odd(long arg)
+{
+  return (arg & 1);
+}
+
+inline long lcm(long x, long y)
+{
+  return x / gcd(x, y) * y;
+}
+
+inline void (setbit)(long& x, long b)
+{
+  x |= (1 << b);
+}
+
+inline void clearbit(long& x, long b)
+{
+  x &= ~(1 << b);
+}
+
+inline int testbit(long x, long b)
+{
+  return ((x & (1 << b)) != 0);
+}
+
+#endif
+#endif
Index: trunk/src/emx/include/Attic/cpp/builtinb.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/builtinb.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/builtinb.h	(revision 18)
@@ -0,0 +1,68 @@
+/* 
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#ifndef _BUILTINBUF_H
+#define _BUILTINBUF_H
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include <streambu.h>
+
+#if !_IO_UNIFIED_JUMPTABLES
+// A builtinbuf a a streambuf where all the virtual operations
+// call the _IO_jump_t table.
+
+extern "C++" {
+class builtinbuf : public streambuf {
+  friend ios;
+  virtual int overflow(int);
+  virtual int underflow();
+  virtual streamsize xsgetn(char *, streamsize);
+  virtual streamsize xsputn(const char *, streamsize);
+  virtual streambuf* setbuf(char*, int);
+  virtual int doallocate();
+  virtual ~builtinbuf();
+  virtual int sync();
+
+  virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
+  virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out);
+  virtual int pbackfail(int c);
+  virtual streamsize sys_read(char* buf, streamsize size);
+  virtual streampos sys_seek(streamoff, _seek_dir);
+  virtual streamsize sys_write(const char*, streamsize);
+  virtual int sys_stat(void*); // Actually, a (struct stat*)
+  virtual int sys_close();
+#if 0
+  virtual int get_column();
+  virtual int set_column(int);
+#endif
+ private:
+  builtinbuf() { }
+};
+} // extern "C++"
+#endif
+
+#endif /* _BUILTINBUF_H */
Index: trunk/src/emx/include/Attic/cpp/bvector.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/bvector.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/bvector.h	(revision 18)
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_BVECTOR_H
+#define __SGI_STL_BVECTOR_H
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+#include <vector.h>
+#else
+#include <algobase.h>
+#include <alloc.h>
+#endif 
+
+#include <stl_bvec.h>
+
+#ifdef __STL_USE_NAMESPACES
+
+using __STD::bit_vector;
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_BVECTOR_H */
+
+// Local Variables:
+// mode:C++
+// End:
+
+
Index: trunk/src/emx/include/Attic/cpp/cassert
===================================================================
--- trunk/src/emx/include/Attic/cpp/cassert	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cassert	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CASSERT__
+#define __CASSERT__
+#include <assert.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cctype
===================================================================
--- trunk/src/emx/include/Attic/cpp/cctype	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cctype	(revision 18)
@@ -0,0 +1,7 @@
+// The -*- C++ -*- character type header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CCTYPE__
+#define __CCTYPE__
+#include <ctype.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cerrno
===================================================================
--- trunk/src/emx/include/Attic/cpp/cerrno	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cerrno	(revision 18)
@@ -0,0 +1,7 @@
+// The -*- C++ -*- error number header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CERRNO__
+#define __CERRNO__
+#include <errno.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cfloat
===================================================================
--- trunk/src/emx/include/Attic/cpp/cfloat	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cfloat	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CFLOAT__
+#define __CFLOAT__
+#include <float.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/ciso646
===================================================================
--- trunk/src/emx/include/Attic/cpp/ciso646	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/ciso646	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CISO646__
+#define __CISO646__
+#include <iso646.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/climits
===================================================================
--- trunk/src/emx/include/Attic/cpp/climits	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/climits	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CLIMITS__
+#define __CLIMITS__
+#include <limits.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/clocale
===================================================================
--- trunk/src/emx/include/Attic/cpp/clocale	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/clocale	(revision 18)
@@ -0,0 +1,7 @@
+// The -*- C++ -*- locale support header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CLOCALE__
+#define __CLOCALE__
+#include <locale.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cmath
===================================================================
--- trunk/src/emx/include/Attic/cpp/cmath	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cmath	(revision 18)
@@ -0,0 +1,76 @@
+// The -*- C++ -*- math functions header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CMATH__
+#define __CMATH__
+#include <_G_confi.h>
+#include <math.h>
+
+#ifdef __GNUG__
+#pragma interface "cmath"
+#endif
+
+extern "C++" {
+#if 0
+float acos (float);
+float asin (float);
+float atan (float);
+float atan2(float, float);
+float ceil (float);
+float cos  (float);
+float cosh (float);
+float exp  (float);
+float fabs (float);
+float floor(float);
+float fmod (float, float);
+float frexp(float, int*);
+float modf (float, float*);
+float ldexp(float, int);
+float log  (float);
+float log10(float);
+float pow  (float, float);
+float pow  (float, int);
+float sin  (float);
+float sinh (float);
+float sqrt (float);
+float tan  (float);
+float tanh (float);
+#endif
+
+inline float  abs (float  x) { return fabs (x); }
+#if ! _G_MATH_H_INLINES /* hpux and SCO define this in math.h */
+inline double abs (double x) { return fabs (x); }
+#endif
+
+#if 0
+double pow(double, int);
+
+long double acos (long double);
+long double asin (long double);
+long double atan (long double);
+long double atan2(long double, long double);
+long double ceil (long double);
+long double cos  (long double);
+long double cosh (long double);
+long double exp  (long double);
+long double fabs (long double);
+long double floor(long double);
+long double frexp(long double, int*);
+long double fmod (long double, long double);
+long double frexp(long double, int*);
+long double log  (long double);
+long double log10(long double);
+long double modf (long double, long double*);
+long double pow  (long double, long double);
+long double pow  (long double, int);
+long double sin  (long double);
+long double sinh (long double);
+long double sqrt (long double);
+long double tan  (long double);
+long double tanh (long double);
+#endif
+inline long double abs (long double x) { return fabs (x); }
+
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/compare.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/compare.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/compare.h	(revision 18)
@@ -0,0 +1,91 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _compare_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _compare_h 1
+
+#include <builtin.h>
+
+int compare(int a, int b);
+int compare(short a, short b);
+int compare(unsigned long a, unsigned long b);
+int compare(unsigned int a, unsigned int b);
+int compare(unsigned short a, unsigned short b);
+int compare(unsigned char a, unsigned char b);
+int compare(signed char a, signed char b);
+int compare(float a, float b);
+int compare(double a, double b);
+int compare(const char* a, const char* b);
+
+
+inline int compare(int a, int b)
+{
+  return a - b;
+}
+
+inline int compare(short a, short b)
+{
+  return a - b;
+}
+
+
+inline int compare(signed char a, signed char b)
+{
+  return a - b;
+}
+
+inline int compare(unsigned long a, unsigned long b)
+{
+  return (a < b)? -1 : (a > b)? 1 : 0;
+}
+
+inline int compare(unsigned int a, unsigned int b)
+{
+  return (a < b)? -1 : (a > b)? 1 : 0;
+}
+
+inline int compare(unsigned short a, unsigned short b)
+{
+  return (a < b)? -1 : (a > b)? 1 : 0;
+}
+
+inline int compare(unsigned char a, unsigned char b)
+{
+  return (a < b)? -1 : (a > b)? 1 : 0;
+}
+
+inline int compare(float a, float b)
+{
+  return (a < b)? -1 : (a > b)? 1 : 0;
+}
+
+inline int compare(double a, double b)
+{
+  return (a < b)? -1 : (a > b)? 1 : 0;
+}
+
+inline int compare(const char* a, const char* b)
+{
+  return strcmp(a,b);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/complex
===================================================================
--- trunk/src/emx/include/Attic/cpp/complex	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/complex	(revision 18)
@@ -0,0 +1,18 @@
+// Main header for the -*- C++ -*- complex number classes.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __COMPLEX__
+#define __COMPLEX__
+
+#include <std/complext.h>
+
+extern "C++" {
+#define __STD_COMPLEX
+
+// ANSI complex types
+typedef complex<float> float_complex;
+typedef complex<double> double_complex;
+typedef complex<long double> long_double_complex;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/complex.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/complex.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/complex.h	(revision 18)
@@ -0,0 +1,6 @@
+// -*- C++ -*- backward compatiblity header.
+// Copyright (C) 1994 Free Software Foundation
+
+#ifndef __COMPLEX_H__
+#include <complex>
+#endif
Index: trunk/src/emx/include/Attic/cpp/csetjmp
===================================================================
--- trunk/src/emx/include/Attic/cpp/csetjmp	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/csetjmp	(revision 18)
@@ -0,0 +1,8 @@
+// The -*- C++ -*- setjmp/longjmp header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CSETJMP__
+#define __CSETJMP__
+#include <setjmp.h>
+#endif
+
Index: trunk/src/emx/include/Attic/cpp/csignal
===================================================================
--- trunk/src/emx/include/Attic/cpp/csignal	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/csignal	(revision 18)
@@ -0,0 +1,7 @@
+// The -*- C++ -*- signal handling header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CSIGNAL__
+#define __CSIGNAL__
+#include <signal.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cstdarg
===================================================================
--- trunk/src/emx/include/Attic/cpp/cstdarg	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cstdarg	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CSTDARG__
+#define __CSTDARG__
+#include <stdarg.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cstddef
===================================================================
--- trunk/src/emx/include/Attic/cpp/cstddef	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cstddef	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CSTDDEF__
+#define __CSTDDEF__
+#include <stddef.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cstdio
===================================================================
--- trunk/src/emx/include/Attic/cpp/cstdio	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cstdio	(revision 18)
@@ -0,0 +1,7 @@
+// The -*- C++ -*- standard I/O header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CSTDIO__
+#define __CSTDIO__
+#include <stdio.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cstdlib
===================================================================
--- trunk/src/emx/include/Attic/cpp/cstdlib	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cstdlib	(revision 18)
@@ -0,0 +1,23 @@
+// The -*- C++ -*- standard library header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CSTDLIB__
+#define __CSTDLIB__
+#include <stdlib.h>
+
+#ifdef __GNUG__
+#pragma interface "cstdlib"
+#endif
+
+extern "C++" {
+
+#if _G_HAS_LABS
+inline long   abs(long x)		{ return labs (x); }
+#else
+inline long   abs(long x)		{ return x >= 0 ? x : -x; }
+#endif
+//inline ldiv_t div(long x, long y)	{ return ldiv (x, y); }
+
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/cstring
===================================================================
--- trunk/src/emx/include/Attic/cpp/cstring	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cstring	(revision 18)
@@ -0,0 +1,96 @@
+// The -*- C++ -*- null-terminated string header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CSTRING__
+#define __CSTRING__
+
+#include <string.h>
+
+#if 0 // Let's not bother with this just yet.
+#include <cstddef>
+
+#ifdef __GNUG__
+#pragma interface "cstring"
+#endif
+
+// The ANSI C prototypes for these functions have a const argument type and
+// non-const return type, so we can't use them.
+
+extern "C++" {
+extern inline const char *
+_G_strchr (const char *s, int c)
+{
+  return strchr (s, c);
+}
+
+extern inline char *
+_G_strchr (char *s, int c)
+{
+  return const_cast<char *> (strchr (s, c));
+}
+
+extern inline const char *
+_G_strpbrk (const char *s1, const char *s2)
+{
+  return strpbrk (s1, s2);
+}
+
+extern inline char *
+_G_strpbrk (char *s1, const char *s2)
+{
+  return const_cast<char *> (strpbrk (s1, s2));
+}
+
+extern inline const char *
+_G_strrchr (const char *s, int c)
+{
+  return strrchr (s, c);
+}
+
+extern inline char *
+_G_strrchr (char *s, int c)
+{
+  return const_cast<char *> (strrchr (s, c));
+}
+
+extern inline const char *
+_G_strstr (const char *s1, const char *s2)
+{
+  return strstr (s1, s2);
+}
+
+extern inline char *
+_G_strstr (char *s1, const char *s2)
+{
+  return const_cast<char *> (strstr (s1, s2));
+}
+
+extern inline const void *
+_G_memchr (const void *s, int c, size_t n)
+{
+  return memchr (s, c, n);
+}
+
+extern inline void *
+_G_memchr (void *s, int c, size_t n)
+{
+  return const_cast<void *> (memchr (s, c, n));
+}
+} // extern "C++"
+
+// Lose any vendor macros for these functions.
+#undef strchr
+#undef strpbrk
+#undef strrchr
+#undef strstr
+#undef memchr
+
+// Ewww, namespace pollution.  Anyone have a better idea?
+#define strchr  _G_strchr
+#define strpbrk _G_strpbrk
+#define strrchr _G_strrchr
+#define strstr  _G_strstr
+#define memchr  _G_memchr
+#endif // 0
+
+#endif // !defined (__CSTRING__)
Index: trunk/src/emx/include/Attic/cpp/ctime
===================================================================
--- trunk/src/emx/include/Attic/cpp/ctime	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/ctime	(revision 18)
@@ -0,0 +1,7 @@
+// The -*- C++ -*- time header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CTIME__
+#define __CTIME__
+#include <time.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cwchar
===================================================================
--- trunk/src/emx/include/Attic/cpp/cwchar	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cwchar	(revision 18)
@@ -0,0 +1,7 @@
+// The -*- C++ -*- wide character header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CWCHAR__
+#define __CWCHAR__
+#include <wchar.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/cwctype
===================================================================
--- trunk/src/emx/include/Attic/cpp/cwctype	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/cwctype	(revision 18)
@@ -0,0 +1,7 @@
+// The -*- C++ -*- wide character type header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __CWCTYPE__
+#define __CWCTYPE__
+#include <wctype.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/defalloc.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/defalloc.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/defalloc.h	(revision 18)
@@ -0,0 +1,86 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+// Inclusion of this file is DEPRECATED.  This is the original HP
+// default allocator.  It is provided only for backward compatibility.
+// 
+// DO NOT USE THIS FILE unless you have an old container implementation
+// that requires an allocator with the HP-style interface.  SGI STL
+// uses a different allocator interface.  SGI-style allocators are not
+// parametrized with respect to the object type; they traffic in void *
+// pointers.  This file is not included by any other SGI STL header.
+
+#ifndef DEFALLOC_H
+#define DEFALLOC_H
+
+#include <new.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <iostream.h>
+#include <algobase.h>
+
+
+template <class T>
+inline T* allocate(ptrdiff_t size, T*) {
+    set_new_handler(0);
+    T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
+    if (tmp == 0) {
+	cerr << "out of memory" << endl; 
+	exit(1);
+    }
+    return tmp;
+}
+
+
+template <class T>
+inline void deallocate(T* buffer) {
+    ::operator delete(buffer);
+}
+
+template <class T>
+class allocator {
+public:
+    typedef T value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef T& reference;
+    typedef const T& const_reference;
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    pointer allocate(size_type n) { 
+	return ::allocate((difference_type)n, (pointer)0);
+    }
+    void deallocate(pointer p) { ::deallocate(p); }
+    pointer address(reference x) { return (pointer)&x; }
+    const_pointer const_address(const_reference x) { 
+	return (const_pointer)&x; 
+    }
+    size_type init_page_size() { 
+	return max(size_type(1), size_type(4096/sizeof(T))); 
+    }
+    size_type max_size() const { 
+	return max(size_type(1), size_type(UINT_MAX/sizeof(T))); 
+    }
+};
+
+class allocator<void> {
+public:
+    typedef void* pointer;
+};
+
+
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/deque
===================================================================
--- trunk/src/emx/include/Attic/cpp/deque	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/deque	(revision 18)
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_DEQUE
+#define __SGI_STL_DEQUE
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_unin.h>
+#include <stl_dequ.h>
+
+#endif /* __SGI_STL_DEQUE */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/deque.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/deque.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/deque.h	(revision 18)
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_DEQUE_H
+#define __SGI_STL_DEQUE_H
+
+#include <algobase.h>
+#include <alloc.h>
+#include <stl_dequ.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::deque;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_DEQUE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/editbuf.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/editbuf.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/editbuf.h	(revision 18)
@@ -0,0 +1,185 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License.
+
+Written by Per Bothner (bothner@cygnus.com). */
+
+#ifndef _EDITBUF_H
+#define _EDITBUF_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+#include <stdio.h>
+#include <fstream.h>
+
+extern "C++" {
+typedef unsigned long mark_pointer;
+// At some point, it might be nice to parameterize this code
+// in terms of buf_char.
+typedef /*unsigned*/ char buf_char;
+
+// Logical pos from start of buffer (does not count gap).
+typedef long buf_index;
+			
+// Pos from start of buffer, possibly including gap_size.
+typedef long buf_offset; 
+
+#if 0
+struct buf_cookie {
+    FILE *file;
+    struct edit_string *str;
+    struct buf_cookie *next;
+    buf_index tell();
+};
+#endif
+
+struct edit_buffer;
+struct edit_mark;
+
+// A edit_string is defined as the region between the 'start' and 'end' marks.
+// Normally (always?) 'start->insert_before()' should be false,
+// and 'end->insert_before()' should be true.
+
+struct edit_string {
+    struct edit_buffer *buffer; // buffer that 'start' and 'end' belong to
+    struct edit_mark *start, *end;
+    int length() const; // count of buf_chars currently in string
+    edit_string(struct edit_buffer *b,
+		      struct edit_mark *ms, struct edit_mark *me)
+	{ buffer = b; start = ms; end = me; }
+/* Make a fresh, contiguous copy of the data in STR.
+   Assign length of STR to *LENP.
+   (Output has extra NUL at out[*LENP].) */
+    buf_char *copy_bytes(int *lenp) const;
+//    FILE *open_file(char *mode);
+    void assign(struct edit_string *src); // copy bytes from src to this
+};
+
+struct edit_streambuf : public streambuf {
+    friend edit_buffer;
+    edit_string *str;
+    edit_streambuf* next; // Chain of edit_streambuf's for a edit_buffer.
+    short _mode;
+    edit_streambuf(edit_string* bstr, int mode);
+    ~edit_streambuf();
+    virtual int underflow();
+    virtual int overflow(int c = EOF);
+    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
+    void flush_to_buffer();
+    void flush_to_buffer(edit_buffer* buffer);
+    int _inserting;
+    int inserting() { return _inserting; }
+    void inserting(int i) { _inserting = i; }
+//    int delete_chars(int count, char* cut_buf); Not implemented.
+    int truncate();
+    int is_reading() { return gptr() != NULL; }
+    buf_char* current() { return is_reading() ? gptr() : pptr(); }
+    void set_current(char *p, int is_reading);
+  protected:
+    void disconnect_gap_from_file(edit_buffer* buffer);
+};
+
+// A 'edit_mark' indicates a position in a buffer.
+// It is "attached" the text (rather than the offset).
+// There are two kinds of mark, which have different behavior
+// when text is inserted at the mark:
+// If 'insert_before()' is true the mark will be adjusted to be
+// *after* the new text.
+
+struct edit_mark {
+    struct edit_mark *chain;
+    mark_pointer _pos;
+    inline int insert_before() { return _pos & 1; }
+    inline unsigned long index_in_buffer(struct edit_buffer *)
+	{ return _pos >> 1; }
+    inline buf_char *ptr(struct edit_buffer *buf);
+    buf_index tell();
+    edit_mark() { }
+    edit_mark(struct edit_string *str, long delta);
+    edit_buffer *buffer();
+    ~edit_mark();
+};
+
+// A 'edit_buffer' consists of a sequence of buf_chars (the data),
+// a list of edit_marks pointing into the data, and a list of FILEs
+// also pointing into the data.
+// A 'edit_buffer' coerced to a edit_string is the string of
+// all the buf_chars in the buffer.
+
+// This implementation uses a conventional buffer gap (as in Emacs).
+// The gap start is defined by de-referencing a (buf_char**).
+// This is because sometimes a FILE is inserting into the buffer,
+// so rather than having each putc adjust the gap, we use indirection
+// to have the gap be defined as the write pointer of the FILE.
+// (This assumes that putc adjusts a pointer (as in GNU's libc), not an index.)
+
+struct edit_buffer {
+    buf_char *data; /* == emacs buffer_text.p1+1 */
+    buf_char *_gap_start;
+    edit_streambuf* _writer; // If non-NULL, currently writing stream
+    inline buf_char *gap_start()
+	{ return _writer ? _writer->pptr() : _gap_start; }
+    buf_offset __gap_end_pos; // size of part 1 + size of gap
+    /* int gap; implicit: buf_size - size1 - size2 */
+    int buf_size;
+    struct edit_streambuf *files;
+    struct edit_mark start_mark;
+    struct edit_mark end_mark;
+    edit_buffer();
+    inline buf_offset gap_end_pos() { return __gap_end_pos; }
+    inline struct edit_mark *start_marker() { return &start_mark; }
+    inline struct edit_mark *end_marker() { return &end_mark; }
+/* these should be protected, ultimately */
+    buf_index tell(edit_mark*);
+    buf_index tell(buf_char*);
+    inline buf_char *gap_end() { return data + gap_end_pos(); }
+    inline int gap_size() { return gap_end() - gap_start(); }
+    inline int size1() { return gap_start() - data; }
+    inline int size2() { return buf_size - gap_end_pos(); }
+    inline struct edit_mark * mark_list() { return &start_mark; }
+    void make_gap (buf_offset);
+    void move_gap (buf_offset pos);
+    void move_gap (buf_char *pos) { move_gap(pos - data); }
+    void gap_left (int pos);
+    void gap_right (int pos);
+    void adjust_markers(mark_pointer low, mark_pointer high,
+			int amount, buf_char *old_data);
+    void delete_range(buf_index from, buf_index to);
+    void delete_range(struct edit_mark *start, struct edit_mark *end);
+};
+
+extern buf_char * bstr_copy(struct edit_string *str, int *lenp);
+
+// Convert a edit_mark to a (buf_char*)
+
+inline buf_char *edit_mark::ptr(struct edit_buffer *buf)
+	{ return buf->data + index_in_buffer(buf); }
+
+inline void edit_streambuf::flush_to_buffer()
+{
+    edit_buffer* buffer = str->buffer;
+    if (buffer->_writer == this) flush_to_buffer(buffer);
+}
+} // extern "C++"
+#endif /* !_EDITBUF_H*/
+
Index: trunk/src/emx/include/Attic/cpp/exceptio
===================================================================
--- trunk/src/emx/include/Attic/cpp/exceptio	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/exceptio	(revision 18)
@@ -0,0 +1,42 @@
+// Exception Handling support header for -*- C++ -*-
+// Copyright (C) 1995, 1996 Free Software Foundation
+
+#ifndef __EXCEPTION__
+#define __EXCEPTION__
+
+#pragma interface "exception"
+
+extern "C++" {
+
+#if 0
+namespace std {
+#endif
+
+class exception {
+public:
+  exception () { }
+  virtual ~exception () { }
+  virtual const char* what () const;
+};
+
+class bad_exception : public exception {
+public:
+  bad_exception () { }
+  virtual ~bad_exception () { }
+};
+
+typedef void (*terminate_handler) ();
+typedef void (*unexpected_handler) ();
+
+terminate_handler set_terminate (terminate_handler);
+void terminate (void);
+unexpected_handler set_unexpected (unexpected_handler);
+void unexpected (void);
+bool uncaught_exception ();
+} // extern "C++"
+
+#if 0
+} // namespace std
+#endif
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/floatio.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/floatio.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/floatio.h	(revision 18)
@@ -0,0 +1,51 @@
+/* 
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *	%W% (Berkeley) %G%
+ */
+
+/*
+ * Floating point scanf/printf (input/output) definitions.
+ */
+
+/* 11-bit exponent (VAX G floating point) is 308 decimal digits */
+#define	MAXEXP		308
+/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
+#define	MAXFRACT	39
Index: trunk/src/emx/include/Attic/cpp/fstream
===================================================================
--- trunk/src/emx/include/Attic/cpp/fstream	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/fstream	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __FSTREAM__
+#define __FSTREAM__
+#include <fstream.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/fstream.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/fstream.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/fstream.h	(revision 18)
@@ -0,0 +1,92 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#ifndef _FSTREAM_H
+#define _FSTREAM_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+#include <iostream.h>
+
+extern "C++" {
+class fstreambase : virtual public ios {
+#ifdef _IO_NEW_STREAMS
+    mutable filebuf __my_fb; // mutable so rdbuf() can be const
+#endif
+    void __fb_init ();
+  public:
+    fstreambase();
+    fstreambase(int fd);
+    fstreambase(int fd, char *p, int l); /* Deprecated */
+    fstreambase(const char *name, int mode, int prot=0664);
+    void close();
+#ifdef _IO_NEW_STREAMS
+    filebuf* rdbuf() const { return &__my_fb; }
+#else
+    filebuf* rdbuf() const { return (filebuf*) ios::rdbuf(); }
+#endif
+    void open(const char *name, int mode, int prot=0664);
+    int is_open() const { return rdbuf()->is_open(); }
+    void setbuf(char *ptr, int len) { rdbuf()->setbuf(ptr, len); }
+    void attach(int fd);
+#ifdef _STREAM_COMPAT
+    int filedesc() { return rdbuf()->fd(); }
+    fstreambase& raw() { rdbuf()->setbuf(NULL, 0); return *this; }
+#endif
+};
+
+class ifstream : public fstreambase, public istream {
+  public:
+    ifstream() : fstreambase() { }
+    ifstream(int fd) : fstreambase(fd) { }
+    ifstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/
+    ifstream(const char *name, int mode=ios::in, int prot=0664)
+	: fstreambase(name, mode, prot) { }
+    void open(const char *name, int mode=ios::in, int prot=0664)
+	{ fstreambase::open(name, mode, prot); }
+};
+
+class ofstream : public fstreambase, public ostream {
+  public:
+    ofstream() : fstreambase() { }
+    ofstream(int fd) : fstreambase(fd) { }
+    ofstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/
+    ofstream(const char *name, int mode=ios::out, int prot=0664)
+	: fstreambase(name, mode, prot) { }
+    void open(const char *name, int mode=ios::out, int prot=0664)
+	{ fstreambase::open(name, mode, prot); }
+};
+
+class fstream : public fstreambase, public iostream {
+  public:
+    fstream() : fstreambase() { }
+    fstream(int fd) : fstreambase(fd) { }
+    fstream(const char *name, int mode, int prot=0664)
+	: fstreambase(name, mode, prot) { }
+    fstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/
+    void open(const char *name, int mode, int prot=0664)
+	{ fstreambase::open(name, mode, prot); }
+};
+} // extern "C++"
+#endif /*!_FSTREAM_H*/
Index: trunk/src/emx/include/Attic/cpp/function
===================================================================
--- trunk/src/emx/include/Attic/cpp/function	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/function	(revision 18)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __SGI_STL_FUNCTIONAL
+#define __SGI_STL_FUNCTIONAL
+
+#include <stl_conf.h>
+#include <stddef.h>
+#include <stl_func.h>
+
+#endif /* __SGI_STL_FUNCTIONAL */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/function.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/function.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/function.h	(revision 18)
@@ -0,0 +1,118 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_FUNCTION_H
+#define __SGI_STL_FUNCTION_H
+
+#ifndef __STL_CONFIG_H
+#include <stl_conf.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_RELOPS
+#include <stl_relo.h>
+#endif
+#include <stddef.h>
+#ifndef __SGI_STL_INTERNAL_FUNCTION_H
+#include <stl_func.h>
+#endif
+
+#ifdef __STL_USE_NAMESPACE_FOR_RELOPS
+
+// Names from stl_relops.h
+using __STD_RELOPS::operator!=;
+using __STD_RELOPS::operator>;
+using __STD_RELOPS::operator<=;
+using __STD_RELOPS::operator>=;
+
+#endif /* __STL_USE_NAMESPACE_FOR_RELOPS */
+
+#ifdef __STL_USE_NAMESPACES
+
+// Names from stl_function.h
+using __STD::unary_function; 
+using __STD::binary_function; 
+using __STD::plus; 
+using __STD::minus; 
+using __STD::multiplies; 
+using __STD::divides; 
+using __STD::identity_element; 
+using __STD::modulus; 
+using __STD::negate; 
+using __STD::equal_to; 
+using __STD::not_equal_to; 
+using __STD::greater; 
+using __STD::less; 
+using __STD::greater_equal; 
+using __STD::less_equal; 
+using __STD::logical_and; 
+using __STD::logical_or; 
+using __STD::logical_not; 
+using __STD::unary_negate; 
+using __STD::binary_negate; 
+using __STD::not1; 
+using __STD::not2; 
+using __STD::binder1st; 
+using __STD::binder2nd; 
+using __STD::bind1st; 
+using __STD::bind2nd; 
+using __STD::unary_compose; 
+using __STD::binary_compose; 
+using __STD::compose1; 
+using __STD::compose2; 
+using __STD::pointer_to_unary_function; 
+using __STD::pointer_to_binary_function; 
+using __STD::ptr_fun; 
+using __STD::identity; 
+using __STD::select1st; 
+using __STD::select2nd; 
+using __STD::project1st; 
+using __STD::project2nd; 
+using __STD::constant_void_fun; 
+using __STD::constant_unary_fun; 
+using __STD::constant_binary_fun; 
+using __STD::constant0; 
+using __STD::constant1; 
+using __STD::constant2; 
+using __STD::subtractive_rng; 
+using __STD::mem_fun_t; 
+using __STD::const_mem_fun_t; 
+using __STD::mem_fun_ref_t; 
+using __STD::const_mem_fun_ref_t; 
+using __STD::mem_fun1_t; 
+using __STD::const_mem_fun1_t; 
+using __STD::mem_fun1_ref_t; 
+using __STD::const_mem_fun1_ref_t; 
+using __STD::mem_fun; 
+using __STD::mem_fun_ref; 
+using __STD::mem_fun1; 
+using __STD::mem_fun1_ref; 
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_FUNCTION_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/gen/AVLMap.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/AVLMap.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/AVLMap.ccP	(revision 18)
@@ -0,0 +1,614 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.<C>.AVLMap.h"
+
+
+/*
+ constants & inlines for maintaining balance & thread status in tree nodes
+*/
+
+#define AVLBALANCEMASK    3
+#define AVLBALANCED       0
+#define AVLLEFTHEAVY      1
+#define AVLRIGHTHEAVY     2
+
+#define LTHREADBIT        4
+#define RTHREADBIT        8
+
+
+static inline int bf(<T><C>AVLNode* t)
+{
+  return t->stat & AVLBALANCEMASK;
+}
+
+static inline void set_bf(<T><C>AVLNode* t, int b)
+{
+  t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK);
+}
+
+
+static inline int rthread(<T><C>AVLNode* t)
+{
+  return t->stat & RTHREADBIT;
+}
+
+static inline void set_rthread(<T><C>AVLNode* t, int b)
+{
+  if (b)
+    t->stat |= RTHREADBIT;
+  else
+    t->stat &= ~RTHREADBIT;
+}
+
+static inline int lthread(<T><C>AVLNode* t)
+{
+  return t->stat & LTHREADBIT;
+}
+
+static inline void set_lthread(<T><C>AVLNode* t, int b)
+{
+  if (b)
+    t->stat |= LTHREADBIT;
+  else
+    t->stat &= ~LTHREADBIT;
+}
+
+/*
+ traversal primitives
+*/
+
+
+<T><C>AVLNode* <T><C>AVLMap::leftmost()
+{
+  <T><C>AVLNode* t = root;
+  if (t != 0) while (t->lt != 0) t = t->lt;
+  return t;
+}
+
+<T><C>AVLNode* <T><C>AVLMap::rightmost()
+{
+  <T><C>AVLNode* t = root;
+  if (t != 0) while (t->rt != 0) t = t->rt;
+  return t;
+}
+
+<T><C>AVLNode* <T><C>AVLMap::succ(<T><C>AVLNode* t)
+{
+  <T><C>AVLNode* r = t->rt;
+  if (!rthread(t)) while (!lthread(r)) r = r->lt;
+  return r;
+}
+
+<T><C>AVLNode* <T><C>AVLMap::pred(<T><C>AVLNode* t)
+{
+  <T><C>AVLNode* l = t->lt;
+  if (!lthread(t)) while (!rthread(l)) l = l->rt;
+  return l;
+}
+
+
+Pix <T><C>AVLMap::seek(<T&> key)
+{
+  <T><C>AVLNode* t = root;
+  if (t == 0)
+    return 0;
+  for (;;)
+  {
+    int cmp = <T>CMP(key, t->item);
+    if (cmp == 0)
+      return Pix(t);
+    else if (cmp < 0)
+    {
+      if (lthread(t))
+        return 0;
+      else
+        t = t->lt;
+    }
+    else if (rthread(t))
+      return 0;
+    else
+      t = t->rt;
+  }
+}
+
+
+/*
+ The combination of threads and AVL bits make adding & deleting
+ interesting, but very awkward.
+
+ We use the following statics to avoid passing them around recursively
+*/
+
+static int _need_rebalancing;   // to send back balance info from rec. calls
+static <T>*   _target_item;     // add/del_item target
+static <T><C>AVLNode* _found_node; // returned added/deleted node
+static int    _already_found;   // for deletion subcases
+
+
+void <T><C>AVLMap:: _add(<T><C>AVLNode*& t)
+{
+  int cmp = <T>CMP(*_target_item, t->item);
+  if (cmp == 0)
+  {
+    _found_node = t;
+    return;
+  }
+  else if (cmp < 0)
+  {
+    if (lthread(t))
+    {
+      ++count;
+      _found_node = new <T><C>AVLNode(*_target_item, def);
+      set_lthread(_found_node, 1);
+      set_rthread(_found_node, 1);
+      _found_node->lt = t->lt;
+      _found_node->rt = t;
+      t->lt = _found_node;
+      set_lthread(t, 0);
+      _need_rebalancing = 1;
+    }
+    else
+      _add(t->lt);
+    if (_need_rebalancing)
+    {
+      switch(bf(t))
+      {
+      case AVLRIGHTHEAVY:
+        set_bf(t, AVLBALANCED);
+        _need_rebalancing = 0;
+        return;
+      case AVLBALANCED:
+        set_bf(t, AVLLEFTHEAVY);
+        return;
+      case AVLLEFTHEAVY:
+	{
+        <T><C>AVLNode* l = t->lt;
+        if (bf(l) == AVLLEFTHEAVY)
+        {
+          if (rthread(l))
+            t->lt = l;
+          else
+            t->lt = l->rt;
+          set_lthread(t, rthread(l));
+          l->rt = t;
+          set_rthread(l, 0);
+          set_bf(t, AVLBALANCED);
+          set_bf(l, AVLBALANCED);
+          t = l;
+          _need_rebalancing = 0;
+        }
+        else
+        {
+          <T><C>AVLNode* r = l->rt;
+          set_rthread(l, lthread(r));
+          if (lthread(r))
+            l->rt = r;
+          else
+            l->rt = r->lt;
+          r->lt = l;
+          set_lthread(r, 0);
+          set_lthread(t, rthread(r));
+          if (rthread(r))
+            t->lt = r;
+          else
+            t->lt = r->rt;
+          r->rt = t;
+          set_rthread(r, 0);
+          if (bf(r) == AVLLEFTHEAVY)
+            set_bf(t, AVLRIGHTHEAVY);
+          else
+            set_bf(t, AVLBALANCED);
+          if (bf(r) == AVLRIGHTHEAVY)
+            set_bf(l, AVLLEFTHEAVY);
+          else
+            set_bf(l, AVLBALANCED);
+          set_bf(r, AVLBALANCED);
+          t = r;
+          _need_rebalancing = 0;
+          return;
+        }
+	}
+      }
+    }
+  }
+  else
+  {
+    if (rthread(t))
+    {
+      ++count;
+      _found_node = new <T><C>AVLNode(*_target_item, def);
+      set_rthread(t, 0);
+      set_lthread(_found_node, 1);
+      set_rthread(_found_node, 1);
+      _found_node->lt = t;
+      _found_node->rt = t->rt;
+      t->rt = _found_node;
+      _need_rebalancing = 1;
+    }
+    else
+      _add(t->rt);
+    if (_need_rebalancing)
+    {
+      switch(bf(t))
+      {
+      case AVLLEFTHEAVY:
+        set_bf(t, AVLBALANCED);
+        _need_rebalancing = 0;
+        return;
+      case AVLBALANCED:
+        set_bf(t, AVLRIGHTHEAVY);
+        return;
+      case AVLRIGHTHEAVY:
+	{
+        <T><C>AVLNode* r = t->rt;
+        if (bf(r) == AVLRIGHTHEAVY)
+        {
+          if (lthread(r))
+            t->rt = r;
+          else
+            t->rt = r->lt;
+          set_rthread(t, lthread(r));
+          r->lt = t;
+          set_lthread(r, 0);
+          set_bf(t, AVLBALANCED);
+          set_bf(r, AVLBALANCED);
+          t = r;
+          _need_rebalancing = 0;
+        }
+        else
+        {
+          <T><C>AVLNode* l = r->lt;
+          set_lthread(r, rthread(l));
+          if (rthread(l))
+            r->lt = l;
+          else
+            r->lt = l->rt;
+          l->rt = r;
+          set_rthread(l, 0);
+          set_rthread(t, lthread(l));
+          if (lthread(l))
+            t->rt = l;
+          else
+            t->rt = l->lt;
+          l->lt = t;
+          set_lthread(l, 0);
+          if (bf(l) == AVLRIGHTHEAVY)
+            set_bf(t, AVLLEFTHEAVY);
+          else
+            set_bf(t, AVLBALANCED);
+          if (bf(l) == AVLLEFTHEAVY)
+            set_bf(r, AVLRIGHTHEAVY);
+          else
+            set_bf(r, AVLBALANCED);
+          set_bf(l, AVLBALANCED);
+          t = l;
+          _need_rebalancing = 0;
+          return;
+        }
+	}
+      }
+    }
+  }
+}
+
+    
+<C>& <T><C>AVLMap::operator [] (<T&> item)
+{
+  if (root == 0)
+  {
+    ++count;
+    root = new <T><C>AVLNode(item, def);
+    set_rthread(root, 1);
+    set_lthread(root, 1);
+    return root->cont;
+  }
+  else
+  {
+    _target_item = &item;
+    _need_rebalancing = 0;
+    _add(root);
+    return _found_node->cont;
+  }
+}
+
+
+void <T><C>AVLMap::_del(<T><C>AVLNode* par, <T><C>AVLNode*& t)
+{
+  int comp;
+  if (_already_found)
+  {
+    if (rthread(t))
+      comp = 0;
+    else
+      comp = 1;
+  }
+  else 
+    comp = <T>CMP(*_target_item, t->item);
+  if (comp == 0)
+  {
+    if (lthread(t) && rthread(t))
+    {
+      _found_node = t;
+      if (t == par->lt)
+      {
+        set_lthread(par, 1);
+        par->lt = t->lt;
+      }
+      else
+      {
+        set_rthread(par, 1);
+        par->rt = t->rt;
+      }
+      _need_rebalancing = 1;
+      return;
+    }
+    else if (lthread(t))
+    {
+      _found_node = t;
+      <T><C>AVLNode* s = succ(t);
+      if (s != 0 && lthread(s))
+        s->lt = t->lt;
+      t = t->rt;
+      _need_rebalancing = 1;
+      return;
+    }
+    else if (rthread(t))
+    {
+      _found_node = t;
+      <T><C>AVLNode* p = pred(t);
+      if (p != 0 && rthread(p))
+        p->rt = t->rt;
+      t = t->lt;
+      _need_rebalancing = 1;
+      return;
+    }
+    else                        // replace item & find someone deletable
+    {
+      <T><C>AVLNode* p = pred(t);
+      t->item = p->item;
+      t->cont = p->cont;
+      _already_found = 1;
+      comp = -1;                // fall through below to left
+    }
+  }
+
+  if (comp < 0)
+  {
+    if (lthread(t))
+      return;
+    _del(t, t->lt);
+    if (!_need_rebalancing)
+      return;
+    switch (bf(t))
+    {
+    case AVLLEFTHEAVY:
+      set_bf(t, AVLBALANCED);
+      return;
+    case AVLBALANCED:
+      set_bf(t, AVLRIGHTHEAVY);
+      _need_rebalancing = 0;
+      return;
+    case AVLRIGHTHEAVY:
+      {
+      <T><C>AVLNode* r = t->rt;
+      switch (bf(r))
+      {
+      case AVLBALANCED:
+        if (lthread(r))
+          t->rt = r;
+        else
+          t->rt = r->lt;
+        set_rthread(t, lthread(r));
+        r->lt = t;
+        set_lthread(r, 0);
+        set_bf(t, AVLRIGHTHEAVY);
+        set_bf(r, AVLLEFTHEAVY);
+        _need_rebalancing = 0;
+        t = r;
+        return;
+      case AVLRIGHTHEAVY:
+        if (lthread(r))
+          t->rt = r;
+        else
+          t->rt = r->lt;
+        set_rthread(t, lthread(r));
+        r->lt = t;
+        set_lthread(r, 0);
+        set_bf(t, AVLBALANCED);
+        set_bf(r, AVLBALANCED);
+        t = r;
+        return;
+      case AVLLEFTHEAVY:
+	{
+        <T><C>AVLNode* l = r->lt;
+        set_lthread(r, rthread(l));
+        if (rthread(l))
+          r->lt = l;
+        else
+          r->lt = l->rt;
+        l->rt = r;
+        set_rthread(l, 0);
+        set_rthread(t, lthread(l));
+        if (lthread(l))
+          t->rt = l;
+        else
+          t->rt = l->lt;
+        l->lt = t;
+        set_lthread(l, 0);
+        if (bf(l) == AVLRIGHTHEAVY)
+          set_bf(t, AVLLEFTHEAVY);
+        else
+          set_bf(t, AVLBALANCED);
+        if (bf(l) == AVLLEFTHEAVY)
+          set_bf(r, AVLRIGHTHEAVY);
+        else
+          set_bf(r, AVLBALANCED);
+        set_bf(l, AVLBALANCED);
+        t = l;
+        return;
+	}
+      }
+    }
+    }
+  }
+  else
+  {
+    if (rthread(t))
+      return;
+    _del(t, t->rt);
+    if (!_need_rebalancing)
+      return;
+    switch (bf(t))
+    {
+    case AVLRIGHTHEAVY:
+      set_bf(t, AVLBALANCED);
+      return;
+    case AVLBALANCED:
+      set_bf(t, AVLLEFTHEAVY);
+      _need_rebalancing = 0;
+      return;
+    case AVLLEFTHEAVY:
+      {
+      <T><C>AVLNode* l = t->lt;
+      switch (bf(l))
+      {
+      case AVLBALANCED:
+        if (rthread(l))
+          t->lt = l;
+        else
+          t->lt = l->rt;
+        set_lthread(t, rthread(l));
+        l->rt = t;
+        set_rthread(l, 0);
+        set_bf(t, AVLLEFTHEAVY);
+        set_bf(l, AVLRIGHTHEAVY);
+        _need_rebalancing = 0;
+        t = l;
+        return;
+      case AVLLEFTHEAVY:
+        if (rthread(l))
+          t->lt = l;
+        else
+          t->lt = l->rt;
+        set_lthread(t, rthread(l));
+        l->rt = t;
+        set_rthread(l, 0);
+        set_bf(t, AVLBALANCED);
+        set_bf(l, AVLBALANCED);
+        t = l;
+        return;
+      case AVLRIGHTHEAVY:
+	{
+        <T><C>AVLNode* r = l->rt;
+        set_rthread(l, lthread(r));
+        if (lthread(r))
+          l->rt = r;
+        else
+          l->rt = r->lt;
+        r->lt = l;
+        set_lthread(r, 0);
+        set_lthread(t, rthread(r));
+        if (rthread(r))
+          t->lt = r;
+        else
+          t->lt = r->rt;
+        r->rt = t;
+        set_rthread(r, 0);
+        if (bf(r) == AVLLEFTHEAVY)
+          set_bf(t, AVLRIGHTHEAVY);
+        else
+          set_bf(t, AVLBALANCED);
+        if (bf(r) == AVLRIGHTHEAVY)
+          set_bf(l, AVLLEFTHEAVY);
+        else
+          set_bf(l, AVLBALANCED);
+        set_bf(r, AVLBALANCED);
+        t = r;
+        return;
+	}
+      }
+      }
+    }
+  }
+}
+
+        
+
+void <T><C>AVLMap::del(<T&> item)
+{
+  if (root == 0) return;
+  _need_rebalancing = 0;
+  _already_found = 0;
+  _found_node = 0;
+  _target_item = &item;
+  _del(root, root);
+  if (_found_node)
+  {
+    delete(_found_node);
+    if (--count == 0)
+      root = 0;
+  }
+}
+
+void <T><C>AVLMap::_kill(<T><C>AVLNode* t)
+{
+  if (t != 0)
+  {
+    if (!lthread(t)) _kill(t->lt);
+    if (!rthread(t)) _kill(t->rt);
+    delete t;
+  }
+}
+
+
+<T><C>AVLMap::<T><C>AVLMap(<T><C>AVLMap& b) :<T><C>Map(b.def)
+{
+  root = 0;
+  count = 0;
+  for (Pix i = b.first(); i != 0; b.next(i)) 
+    (*this)[b.key(i)] = b.contents(i);
+}
+
+
+int <T><C>AVLMap::OK()
+{
+  int v = 1;
+  if (root == 0) 
+    v = count == 0;
+  else
+  {
+    int n = 1;
+    <T><C>AVLNode* trail = leftmost();
+    <T><C>AVLNode* t = succ(trail);
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/AVLMap.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/AVLMap.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/AVLMap.hP	(revision 18)
@@ -0,0 +1,141 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T><C>AVLMap_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T><C>AVLMap_h 1
+
+#include "<T>.<C>.Map.h"
+
+struct <T><C>AVLNode
+{
+  <T><C>AVLNode*      lt;
+  <T><C>AVLNode*      rt;
+  <T>                 item;
+  <C>                 cont;
+  char                stat;
+                      <T><C>AVLNode(<T&> h, <C&> c, 
+                                    <T><C>AVLNode* l=0, <T><C>AVLNode* r=0);
+                      ~<T><C>AVLNode();
+};
+
+inline <T><C>AVLNode::<T><C>AVLNode(<T&> h, <C&> c, 
+                                    <T><C>AVLNode* l, <T><C>AVLNode* r)
+     :lt(l), rt(r), item(h), cont(c), stat(0) {}
+
+inline <T><C>AVLNode::~<T><C>AVLNode() {}
+
+typedef <T><C>AVLNode* <T><C>AVLNodePtr;
+
+
+class <T><C>AVLMap : public <T><C>Map
+{
+protected:
+  <T><C>AVLNode*   root;
+
+  <T><C>AVLNode*   leftmost();
+  <T><C>AVLNode*   rightmost();
+  <T><C>AVLNode*   pred(<T><C>AVLNode* t);
+  <T><C>AVLNode*   succ(<T><C>AVLNode* t);
+  void            _kill(<T><C>AVLNode* t);
+  void            _add(<T><C>AVLNode*& t);
+  void            _del(<T><C>AVLNode* p, <T><C>AVLNode*& t);
+
+public:
+                <T><C>AVLMap(<C&> dflt);
+                <T><C>AVLMap(<T><C>AVLMap& a);
+  inline               ~<T><C>AVLMap();
+
+  <C>&          operator [] (<T&> key);
+
+  void          del(<T&> key);
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          key(Pix i);
+  inline <C>&          contents(Pix i);
+
+  Pix           seek(<T&> key);
+  inline int           contains(<T&> key);
+
+  inline void          clear(); 
+
+  Pix           last();
+  void          prev(Pix& i);
+
+  int           OK();
+};
+
+inline <T><C>AVLMap::~<T><C>AVLMap()
+{
+  _kill(root);
+}
+
+inline <T><C>AVLMap::<T><C>AVLMap(<C&> dflt) :<T><C>Map(dflt)
+{
+  root = 0;
+}
+
+inline Pix <T><C>AVLMap::first()
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T><C>AVLMap::last()
+{
+  return Pix(rightmost());
+}
+
+inline void <T><C>AVLMap::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T><C>AVLNode*)i));
+}
+
+inline void <T><C>AVLMap::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T><C>AVLNode*)i));
+}
+
+inline <T>& <T><C>AVLMap::key(Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T><C>AVLNode*)i)->item;
+}
+
+inline <C>& <T><C>AVLMap::contents(Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T><C>AVLNode*)i)->cont;
+}
+
+inline void <T><C>AVLMap::clear()
+{
+  _kill(root);
+  count = 0;
+  root = 0;
+}
+
+inline int <T><C>AVLMap::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/AVLSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/AVLSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/AVLSet.ccP	(revision 18)
@@ -0,0 +1,892 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.AVLSet.h"
+#include <stdlib.h>
+
+
+/*
+ constants & inlines for maintaining balance & thread status in tree nodes
+*/
+
+#define AVLBALANCEMASK    3
+#define AVLBALANCED       0
+#define AVLLEFTHEAVY      1
+#define AVLRIGHTHEAVY     2
+
+#define LTHREADBIT        4
+#define RTHREADBIT        8
+
+
+static inline int bf(<T>AVLNode* t)
+{
+  return t->stat & AVLBALANCEMASK;
+}
+
+static inline void set_bf(<T>AVLNode* t, int b)
+{
+  t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK);
+}
+
+
+static inline int rthread(<T>AVLNode* t)
+{
+  return t->stat & RTHREADBIT;
+}
+
+static inline void set_rthread(<T>AVLNode* t, int b)
+{
+  if (b)
+    t->stat |= RTHREADBIT;
+  else
+    t->stat &= ~RTHREADBIT;
+}
+
+static inline int lthread(<T>AVLNode* t)
+{
+  return t->stat & LTHREADBIT;
+}
+
+static inline void set_lthread(<T>AVLNode* t, int b)
+{
+  if (b)
+    t->stat |= LTHREADBIT;
+  else
+    t->stat &= ~LTHREADBIT;
+}
+
+/*
+ traversal primitives
+*/
+
+
+<T>AVLNode* <T>AVLSet::leftmost()
+{
+  <T>AVLNode* t = root;
+  if (t != 0) while (t->lt != 0) t = t->lt;
+  return t;
+}
+
+<T>AVLNode* <T>AVLSet::rightmost()
+{
+  <T>AVLNode* t = root;
+  if (t != 0) while (t->rt != 0) t = t->rt;
+  return t;
+}
+
+<T>AVLNode* <T>AVLSet::succ(<T>AVLNode* t)
+{
+  <T>AVLNode* r = t->rt;
+  if (!rthread(t)) while (!lthread(r)) r = r->lt;
+  return r;
+}
+
+<T>AVLNode* <T>AVLSet::pred(<T>AVLNode* t)
+{
+  <T>AVLNode* l = t->lt;
+  if (!lthread(t)) while (!rthread(l)) l = l->rt;
+  return l;
+}
+
+
+Pix <T>AVLSet::seek(<T&> key)
+{
+  <T>AVLNode* t = root;
+  if (t == 0)
+    return 0;
+  for (;;)
+  {
+    int cmp = <T>CMP(key, t->item);
+    if (cmp == 0)
+      return Pix(t);
+    else if (cmp < 0)
+    {
+      if (lthread(t))
+        return 0;
+      else
+        t = t->lt;
+    }
+    else if (rthread(t))
+      return 0;
+    else
+      t = t->rt;
+  }
+}
+
+
+/*
+ The combination of threads and AVL bits make adding & deleting
+ interesting, but very awkward.
+
+ We use the following statics to avoid passing them around recursively
+*/
+
+static int _need_rebalancing;   // to send back balance info from rec. calls
+static <T>*   _target_item;     // add/del_item target
+static <T>AVLNode* _found_node; // returned added/deleted node
+static int    _already_found;   // for deletion subcases
+
+static <T>AVLNode** _hold_nodes;       // used for rebuilding trees
+static int  _max_hold_index;              // # elements-1 in _hold_nodes
+
+
+void <T>AVLSet:: _add(<T>AVLNode*& t)
+{
+  int cmp = <T>CMP(*_target_item, t->item);
+  if (cmp == 0)
+  {
+    _found_node = t;
+    return;
+  }
+  else if (cmp < 0)
+  {
+    if (lthread(t))
+    {
+      ++count;
+      _found_node = new <T>AVLNode(*_target_item);
+      set_lthread(_found_node, 1);
+      set_rthread(_found_node, 1);
+      _found_node->lt = t->lt;
+      _found_node->rt = t;
+      t->lt = _found_node;
+      set_lthread(t, 0);
+      _need_rebalancing = 1;
+    }
+    else
+      _add(t->lt);
+    if (_need_rebalancing)
+    {
+      switch(bf(t))
+      {
+      case AVLRIGHTHEAVY:
+        set_bf(t, AVLBALANCED);
+        _need_rebalancing = 0;
+        return;
+      case AVLBALANCED:
+        set_bf(t, AVLLEFTHEAVY);
+        return;
+      case AVLLEFTHEAVY:
+	{
+        <T>AVLNode* l = t->lt;
+        if (bf(l) == AVLLEFTHEAVY)
+        {
+          if (rthread(l))
+            t->lt = l;
+          else
+            t->lt = l->rt;
+          set_lthread(t, rthread(l));
+          l->rt = t;
+          set_rthread(l, 0);
+          set_bf(t, AVLBALANCED);
+          set_bf(l, AVLBALANCED);
+          t = l;
+          _need_rebalancing = 0;
+        }
+        else
+        {
+          <T>AVLNode* r = l->rt;
+          set_rthread(l, lthread(r));
+          if (lthread(r))
+            l->rt = r;
+          else
+            l->rt = r->lt;
+          r->lt = l;
+          set_lthread(r, 0);
+          set_lthread(t, rthread(r));
+          if (rthread(r))
+            t->lt = r;
+          else
+            t->lt = r->rt;
+          r->rt = t;
+          set_rthread(r, 0);
+          if (bf(r) == AVLLEFTHEAVY)
+            set_bf(t, AVLRIGHTHEAVY);
+          else
+            set_bf(t, AVLBALANCED);
+          if (bf(r) == AVLRIGHTHEAVY)
+            set_bf(l, AVLLEFTHEAVY);
+          else
+            set_bf(l, AVLBALANCED);
+          set_bf(r, AVLBALANCED);
+          t = r;
+          _need_rebalancing = 0;
+          return;
+        }
+	}
+      }
+    }
+  }
+  else
+  {
+    if (rthread(t))
+    {
+      ++count;
+      _found_node = new <T>AVLNode(*_target_item);
+      set_rthread(t, 0);
+      set_lthread(_found_node, 1);
+      set_rthread(_found_node, 1);
+      _found_node->lt = t;
+      _found_node->rt = t->rt;
+      t->rt = _found_node;
+      _need_rebalancing = 1;
+    }
+    else
+      _add(t->rt);
+    if (_need_rebalancing)
+    {
+      switch(bf(t))
+      {
+      case AVLLEFTHEAVY:
+        set_bf(t, AVLBALANCED);
+        _need_rebalancing = 0;
+        return;
+      case AVLBALANCED:
+        set_bf(t, AVLRIGHTHEAVY);
+        return;
+      case AVLRIGHTHEAVY:
+	{
+        <T>AVLNode* r = t->rt;
+        if (bf(r) == AVLRIGHTHEAVY)
+        {
+          if (lthread(r))
+            t->rt = r;
+          else
+            t->rt = r->lt;
+          set_rthread(t, lthread(r));
+          r->lt = t;
+          set_lthread(r, 0);
+          set_bf(t, AVLBALANCED);
+          set_bf(r, AVLBALANCED);
+          t = r;
+          _need_rebalancing = 0;
+        }
+        else
+        {
+          <T>AVLNode* l = r->lt;
+          set_lthread(r, rthread(l));
+          if (rthread(l))
+            r->lt = l;
+          else
+            r->lt = l->rt;
+          l->rt = r;
+          set_rthread(l, 0);
+          set_rthread(t, lthread(l));
+          if (lthread(l))
+            t->rt = l;
+          else
+            t->rt = l->lt;
+          l->lt = t;
+          set_lthread(l, 0);
+          if (bf(l) == AVLRIGHTHEAVY)
+            set_bf(t, AVLLEFTHEAVY);
+          else
+            set_bf(t, AVLBALANCED);
+          if (bf(l) == AVLLEFTHEAVY)
+            set_bf(r, AVLRIGHTHEAVY);
+          else
+            set_bf(r, AVLBALANCED);
+          set_bf(l, AVLBALANCED);
+          t = l;
+          _need_rebalancing = 0;
+          return;
+        }
+	}
+      }
+    }
+  }
+}
+
+    
+Pix <T>AVLSet::add(<T&> item)
+{
+  if (root == 0)
+  {
+    ++count;
+    root = new <T>AVLNode(item);
+    set_rthread(root, 1);
+    set_lthread(root, 1);
+    return Pix(root);
+  }
+  else
+  {
+    _target_item = &item;
+    _need_rebalancing = 0;
+    _add(root);
+    return Pix(_found_node);
+  }
+}
+
+
+void <T>AVLSet::_del(<T>AVLNode* par, <T>AVLNode*& t)
+{
+  int comp;
+  if (_already_found)
+  {
+    if (rthread(t))
+      comp = 0;
+    else
+      comp = 1;
+  }
+  else 
+    comp = <T>CMP(*_target_item, t->item);
+  if (comp == 0)
+  {
+    if (lthread(t) && rthread(t))
+    {
+      _found_node = t;
+      if (t == par->lt)
+      {
+        set_lthread(par, 1);
+        par->lt = t->lt;
+      }
+      else
+      {
+        set_rthread(par, 1);
+        par->rt = t->rt;
+      }
+      _need_rebalancing = 1;
+      return;
+    }
+    else if (lthread(t))
+    {
+      _found_node = t;
+      <T>AVLNode* s = succ(t);
+      if (s != 0 && lthread(s))
+        s->lt = t->lt;
+      t = t->rt;
+      _need_rebalancing = 1;
+      return;
+    }
+    else if (rthread(t))
+    {
+      _found_node = t;
+      <T>AVLNode* p = pred(t);
+      if (p != 0 && rthread(p))
+        p->rt = t->rt;
+      t = t->lt;
+      _need_rebalancing = 1;
+      return;
+    }
+    else                        // replace item & find someone deletable
+    {
+      <T>AVLNode* p = pred(t);
+      t->item = p->item;
+      _already_found = 1;
+      comp = -1;                // fall through below to left
+    }
+  }
+
+  if (comp < 0)
+  {
+    if (lthread(t))
+      return;
+    _del(t, t->lt);
+    if (!_need_rebalancing)
+      return;
+    switch (bf(t))
+    {
+    case AVLLEFTHEAVY:
+      set_bf(t, AVLBALANCED);
+      return;
+    case AVLBALANCED:
+      set_bf(t, AVLRIGHTHEAVY);
+      _need_rebalancing = 0;
+      return;
+    case AVLRIGHTHEAVY:
+      {
+      <T>AVLNode* r = t->rt;
+      switch (bf(r))
+      {
+      case AVLBALANCED:
+        if (lthread(r))
+          t->rt = r;
+        else
+          t->rt = r->lt;
+        set_rthread(t, lthread(r));
+        r->lt = t;
+        set_lthread(r, 0);
+        set_bf(t, AVLRIGHTHEAVY);
+        set_bf(r, AVLLEFTHEAVY);
+        _need_rebalancing = 0;
+        t = r;
+        return;
+      case AVLRIGHTHEAVY:
+        if (lthread(r))
+          t->rt = r;
+        else
+          t->rt = r->lt;
+        set_rthread(t, lthread(r));
+        r->lt = t;
+        set_lthread(r, 0);
+        set_bf(t, AVLBALANCED);
+        set_bf(r, AVLBALANCED);
+        t = r;
+        return;
+      case AVLLEFTHEAVY:
+	{
+        <T>AVLNode* l = r->lt;
+        set_lthread(r, rthread(l));
+        if (rthread(l))
+          r->lt = l;
+        else
+          r->lt = l->rt;
+        l->rt = r;
+        set_rthread(l, 0);
+        set_rthread(t, lthread(l));
+        if (lthread(l))
+          t->rt = l;
+        else
+          t->rt = l->lt;
+        l->lt = t;
+        set_lthread(l, 0);
+        if (bf(l) == AVLRIGHTHEAVY)
+          set_bf(t, AVLLEFTHEAVY);
+        else
+          set_bf(t, AVLBALANCED);
+        if (bf(l) == AVLLEFTHEAVY)
+          set_bf(r, AVLRIGHTHEAVY);
+        else
+          set_bf(r, AVLBALANCED);
+        set_bf(l, AVLBALANCED);
+        t = l;
+        return;
+	}
+      }
+    }
+    }
+  }
+  else
+  {
+    if (rthread(t))
+      return;
+    _del(t, t->rt);
+    if (!_need_rebalancing)
+      return;
+    switch (bf(t))
+    {
+    case AVLRIGHTHEAVY:
+      set_bf(t, AVLBALANCED);
+      return;
+    case AVLBALANCED:
+      set_bf(t, AVLLEFTHEAVY);
+      _need_rebalancing = 0;
+      return;
+    case AVLLEFTHEAVY:
+      {
+      <T>AVLNode* l = t->lt;
+      switch (bf(l))
+      {
+      case AVLBALANCED:
+        if (rthread(l))
+          t->lt = l;
+        else
+          t->lt = l->rt;
+        set_lthread(t, rthread(l));
+        l->rt = t;
+        set_rthread(l, 0);
+        set_bf(t, AVLLEFTHEAVY);
+        set_bf(l, AVLRIGHTHEAVY);
+        _need_rebalancing = 0;
+        t = l;
+        return;
+      case AVLLEFTHEAVY:
+        if (rthread(l))
+          t->lt = l;
+        else
+          t->lt = l->rt;
+        set_lthread(t, rthread(l));
+        l->rt = t;
+        set_rthread(l, 0);
+        set_bf(t, AVLBALANCED);
+        set_bf(l, AVLBALANCED);
+        t = l;
+        return;
+      case AVLRIGHTHEAVY:
+	{
+        <T>AVLNode* r = l->rt;
+        set_rthread(l, lthread(r));
+        if (lthread(r))
+          l->rt = r;
+        else
+          l->rt = r->lt;
+        r->lt = l;
+        set_lthread(r, 0);
+        set_lthread(t, rthread(r));
+        if (rthread(r))
+          t->lt = r;
+        else
+          t->lt = r->rt;
+        r->rt = t;
+        set_rthread(r, 0);
+        if (bf(r) == AVLLEFTHEAVY)
+          set_bf(t, AVLRIGHTHEAVY);
+        else
+          set_bf(t, AVLBALANCED);
+        if (bf(r) == AVLRIGHTHEAVY)
+          set_bf(l, AVLLEFTHEAVY);
+        else
+          set_bf(l, AVLBALANCED);
+        set_bf(r, AVLBALANCED);
+        t = r;
+        return;
+	}
+      }
+      }
+    }
+  }
+}
+
+        
+
+void <T>AVLSet::del(<T&> item)
+{
+  if (root == 0) return;
+  _need_rebalancing = 0;
+  _already_found = 0;
+  _found_node = 0;
+  _target_item = &item;
+  _del(root, root);
+  if (_found_node)
+  {
+    delete(_found_node);
+    if (--count == 0)
+      root = 0;
+  }
+}
+
+// build an ordered array of pointers to tree nodes back into a tree
+// we know that at least one element exists
+
+static <T>AVLNode* _do_treeify(int lo, int hi, int& h)
+{
+  int lh, rh;
+  int mid = (lo + hi) / 2;
+  <T>AVLNode* t = _hold_nodes[mid];
+  if (lo > mid - 1)
+  {
+    set_lthread(t, 1);
+    if (mid == 0)
+      t->lt = 0;
+    else
+      t->lt = _hold_nodes[mid-1];
+    lh = 0;
+  }
+  else
+  {
+    set_lthread(t, 0);
+    t->lt = _do_treeify(lo, mid-1, lh);
+  }
+  if (hi < mid + 1)
+  {
+    set_rthread(t, 1);
+    if (mid == _max_hold_index)
+      t->rt = 0;
+    else
+      t->rt = _hold_nodes[mid+1];
+    rh = 0;
+  }
+  else 
+  {
+    set_rthread(t, 0);
+    t->rt = _do_treeify(mid+1, hi, rh);
+  }
+  if (lh == rh)
+  {
+    set_bf(t, AVLBALANCED);
+    h = lh + 1;
+  }
+  else if (lh == rh - 1)
+  {
+    set_bf(t, AVLRIGHTHEAVY);
+    h = rh + 1;
+  }
+  else if (rh == lh - 1)
+  {
+    set_bf(t, AVLLEFTHEAVY);
+    h = lh + 1;
+  }
+  else                          // can't happen
+    abort();
+
+  return t;
+}
+
+static <T>AVLNode* _treeify(int n)
+{
+  <T>AVLNode* t;
+  if (n == 0)
+    t = 0;
+  else
+  {
+    int b;
+    _max_hold_index = n-1;
+    t = _do_treeify(0, _max_hold_index, b);
+  }
+  delete _hold_nodes;
+  return t;
+}
+
+
+void <T>AVLSet::_kill(<T>AVLNode* t)
+{
+  if (t != 0)
+  {
+    if (!lthread(t)) _kill(t->lt);
+    if (!rthread(t)) _kill(t->rt);
+    delete t;
+  }
+}
+
+
+<T>AVLSet::<T>AVLSet(<T>AVLSet& b)
+{
+  if ((count = b.count) == 0)
+  {
+    root = 0;
+  }
+  else
+  {
+    _hold_nodes = new <T>AVLNodePtr [count];
+    <T>AVLNode* t = b.leftmost();
+    int i = 0;
+    while (t != 0)
+    {
+      _hold_nodes[i++] = new <T>AVLNode(t->item);
+      t = b.succ(t);
+    }
+    root = _treeify(count);
+  }
+}
+
+
+int <T>AVLSet::operator == (<T>AVLSet& y)
+{
+  if (count != y.count)
+    return 0;
+  else
+  {
+    <T>AVLNode* t = leftmost();
+    <T>AVLNode* u = y.leftmost();
+    for (;;)
+    {
+      if (t == 0)
+        return 1;
+      else if (!(<T>EQ(t->item, u->item)))
+        return 0;
+      else
+      {
+        t = succ(t);
+        u = y.succ(u);
+      }
+    }
+  }
+}
+
+int <T>AVLSet::operator <= (<T>AVLSet& y)
+{
+  if (count > y.count)
+    return 0;
+  else
+  {
+    <T>AVLNode* t = leftmost();
+    <T>AVLNode* u = y.leftmost();
+    for (;;)
+    {
+      if (t == 0)
+        return 1;
+      else if (u == 0)
+        return 0;
+      int cmp = <T>CMP(t->item, u->item);
+      if (cmp == 0)
+      {
+        t = succ(t);
+        u = y.succ(u);
+      }
+      else if (cmp < 0)
+        return 0;
+      else
+        u = y.succ(u);
+    }
+  }
+}
+
+void <T>AVLSet::operator |=(<T>AVLSet& y)
+{
+  <T>AVLNode* t = leftmost();
+  <T>AVLNode* u = y.leftmost();
+  int rsize = count + y.count;
+  _hold_nodes = new <T>AVLNodePtr [rsize];
+  int k = 0;
+  for (;;)
+  {
+    if (t == 0)
+    {
+      while (u != 0)
+      {
+        _hold_nodes[k++] = new <T>AVLNode(u->item);
+        u = y.succ(u);
+      }
+      break;
+    }
+    else if (u == 0)
+    {
+      while (t != 0)
+      {
+        _hold_nodes[k++] = t;
+        t = succ(t);
+      }
+      break;
+    }
+    int cmp = <T>CMP(t->item, u->item);
+    if (cmp == 0)
+    {
+      _hold_nodes[k++] = t;
+      t = succ(t);
+      u = y.succ(u);
+    }
+    else if (cmp < 0)
+    {
+      _hold_nodes[k++] = t;
+      t = succ(t);
+    }
+    else
+    {
+      _hold_nodes[k++] = new <T>AVLNode(u->item);
+      u = y.succ(u);
+    }
+  }
+  root = _treeify(k);
+  count = k;
+}
+
+void <T>AVLSet::operator &= (<T>AVLSet& y)
+{
+  <T>AVLNode* t = leftmost();
+  <T>AVLNode* u = y.leftmost();
+  int rsize = (count < y.count)? count : y.count;
+  _hold_nodes = new <T>AVLNodePtr [rsize];
+  int k = 0;
+  for (;;)
+  {
+    if (t == 0)
+      break;
+    if (u == 0)
+    {
+      while (t != 0)
+      {
+        <T>AVLNode* tmp = succ(t);
+        delete t;
+        t = tmp;
+      }
+      break;
+    }
+    int cmp = <T>CMP(t->item, u->item);
+    if (cmp == 0)
+    {
+      _hold_nodes[k++] = t;
+      t = succ(t);
+      u = y.succ(u);
+    }
+    else if (cmp < 0)
+    {
+      <T>AVLNode* tmp = succ(t);
+      delete t;
+      t = tmp;
+    }
+    else
+      u = y.succ(u);
+  }
+  root = _treeify(k);
+  count = k;
+}
+
+
+void <T>AVLSet::operator -=(<T>AVLSet& y)
+{
+  <T>AVLNode* t = leftmost();
+  <T>AVLNode* u = y.leftmost();
+  int rsize = count;
+  _hold_nodes = new <T>AVLNodePtr [rsize];
+  int k = 0;
+  for (;;)
+  {
+    if (t == 0)
+      break;
+    else if (u == 0)
+    {
+      while (t != 0)
+      {
+        _hold_nodes[k++] = t;
+        t = succ(t);
+      }
+      break;
+    }
+    int cmp = <T>CMP(t->item, u->item);
+    if (cmp == 0)
+    {
+      <T>AVLNode* tmp = succ(t);
+      delete t;
+      t = tmp;
+      u = y.succ(u);
+    }
+    else if (cmp < 0)
+    {
+      _hold_nodes[k++] = t;
+      t = succ(t);
+    }
+    else
+      u = y.succ(u);
+  }
+  root = _treeify(k);
+  count = k;
+}
+
+int <T>AVLSet::owns(Pix i)
+{
+  if (i == 0) return 0;
+  for (<T>AVLNode* t = leftmost(); t != 0; t = succ(t)) 
+    if (Pix(t) == i) return 1;
+  return 0;
+}
+
+int <T>AVLSet::OK()
+{
+  int v = 1;
+  if (root == 0) 
+    v = count == 0;
+  else
+  {
+    int n = 1;
+    <T>AVLNode* trail = leftmost();
+    <T>AVLNode* t = succ(trail);
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/AVLSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/AVLSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/AVLSet.hP	(revision 18)
@@ -0,0 +1,152 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>AVL_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>AVL_h 1
+
+#include "<T>.Set.h"
+
+struct <T>AVLNode
+{
+  <T>AVLNode*         lt;
+  <T>AVLNode*         rt;
+  <T>                 item;
+  char                stat;
+                      <T>AVLNode(<T&> h, <T>AVLNode* l=0, <T>AVLNode* r=0);
+                      ~<T>AVLNode();
+};
+
+inline <T>AVLNode::<T>AVLNode(<T&> h, <T>AVLNode* l, <T>AVLNode* r)
+:lt(l), rt(r), item(h), stat(0) {}
+
+inline <T>AVLNode::~<T>AVLNode() {}
+
+typedef <T>AVLNode* <T>AVLNodePtr;
+
+
+class <T>AVLSet : public <T>Set
+{
+protected:
+  <T>AVLNode*   root;
+
+                <T>AVLSet(<T>AVLNode* p, int l);
+
+  <T>AVLNode*   leftmost();
+  <T>AVLNode*   rightmost();
+  <T>AVLNode*   pred(<T>AVLNode* t);
+  <T>AVLNode*   succ(<T>AVLNode* t);
+  void          _kill(<T>AVLNode* t);
+  void          _add(<T>AVLNode*& t);
+  void          _del(<T>AVLNode* p, <T>AVLNode*& t);
+
+public:
+                <T>AVLSet();
+                <T>AVLSet(<T>AVLSet& a);
+  inline               ~<T>AVLSet();
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  inline int           contains(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  int           owns(Pix i);
+  Pix           seek(<T&> item);
+
+  Pix           last();
+  void          prev(Pix& i);
+
+  void          operator |= (<T>AVLSet& b);
+  void          operator -= (<T>AVLSet& b);
+  void          operator &= (<T>AVLSet& b);
+
+  int           operator == (<T>AVLSet& b);
+  int           operator != (<T>AVLSet& b);
+  int           operator <= (<T>AVLSet& b); 
+
+  int           OK();
+};
+
+inline <T>AVLSet::~<T>AVLSet()
+{
+  _kill(root);
+}
+
+inline <T>AVLSet::<T>AVLSet()
+{
+  root = 0;
+  count = 0;
+}
+
+inline <T>AVLSet::<T>AVLSet(<T>AVLNode* p, int l)
+{
+  root = p;
+  count = l;
+}
+
+inline int <T>AVLSet::operator != (<T>AVLSet& b)
+{
+  return ! ((*this) == b);
+}
+
+inline Pix <T>AVLSet::first()
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T>AVLSet::last()
+{
+  return Pix(rightmost());
+}
+
+inline void <T>AVLSet::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T>AVLNode*)i));
+}
+
+inline void <T>AVLSet::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T>AVLNode*)i));
+}
+
+inline <T>& <T>AVLSet::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T>AVLNode*)i)->item;
+}
+
+inline void <T>AVLSet::clear()
+{
+  _kill(root);
+  count = 0;
+  root = 0;
+}
+
+inline int <T>AVLSet::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/AVec.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/AVec.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/AVec.ccP	(revision 18)
@@ -0,0 +1,397 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include <builtin.h>
+#include "<T>.AVec.h"
+
+/*
+ The following brought to you by the department of redundancy department
+*/
+
+<T>AVec& <T>AVec::operator = (const <T>AVec& v)
+{
+  if (len != 0 && len != v.capacity())
+    error("nonconformant vectors.");
+  if (len == 0)
+    s = new <T> [len = v.capacity()];
+  if (s != v.vec())
+  {
+    for (int i = 0; i < len; ++i)
+      s[i] = v.vec()[i];
+  }
+  return *this;
+}
+
+<T>AVec& <T>AVec::operator = (<T&> f)
+{
+  for (int i = 0; i < len; ++i) s[i] = f;
+  return *this;
+}
+
+
+<T>AVec concat(<T>AVec & a, <T>AVec & b)
+{
+  int newl = a.capacity() + b.capacity();
+  <T>* news = new <T> [newl];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  while (t < top) *p++ = *t++;
+  top = &(b.vec()[b.capacity()]);
+  t = b.vec();
+  while (t < top) *p++ = *t++;
+  return <T>AVec(newl, news);
+}
+
+
+<T>AVec combine(<T>Combiner f, <T>AVec& a, <T>AVec& b)
+{
+  int newl = (a.capacity() < b.capacity())? a.capacity() : b.capacity();
+  <T>* news = new <T> [newl];
+  <T>* p = news;
+  <T>* top = &(a.vec()[newl]);
+  <T>* t = a.vec();
+  <T>* u = b.vec();
+  while (t < top) *p++ = (*f)(*t++, *u++);
+  return <T>AVec(newl, news);
+}
+
+<T>AVec reverse(<T>AVec& a)
+{
+  <T>* news = new <T> [a.capacity()];
+  if (a.capacity() != 0)
+  {
+    <T>* lo = news;
+    <T>* hi = &(news[a.capacity() - 1]);
+    while (lo < hi)
+    {
+      <T> tmp = *lo;
+      *lo++ = *hi;
+      *hi-- = tmp;
+    }
+  }
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec map(<T>Mapper f, <T>AVec& a)
+{
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  while(t < top) *p++ = (*f)(*t++);
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec <T>AVec::at(int from, int n)
+{
+  int to;
+  if (n < 0)
+  {
+    n = len - from;
+    to = len - 1;
+  }
+  else
+    to = from + n - 1;
+  if ((unsigned)from > (unsigned)to)
+    range_error();
+  <T>* news = new <T> [n];
+  <T>* p = news;
+  <T>* t = &(s[from]);
+  <T>* top = &(s[to]);
+  while (t <= top) *p++ = *t++;
+  return <T>AVec(n, news);
+}
+
+<T>AVec merge(<T>AVec & a, <T>AVec & b, <T>Comparator f)
+{
+  int newl = a.capacity() + b.capacity();
+  <T>* news = new <T> [newl];
+  <T>* p = news;
+  <T>* topa = &(a.vec()[a.capacity()]);
+  <T>* as = a.vec();
+  <T>* topb = &(b.vec()[b.capacity()]);
+  <T>* bs = b.vec();
+
+  for (;;)
+  {
+    if (as >= topa)
+    {
+      while (bs < topb) *p++ = *bs++;
+      break;
+    }
+    else if (bs >= topb)
+    {
+      while (as < topa) *p++ = *as++;
+      break;
+    }
+    else if ((*f)(*as, *bs) <= 0)
+      *p++ = *as++;
+    else
+      *p++ = *bs++;
+  }
+  return <T>AVec(newl, news);
+}
+
+<T>AVec operator + (<T>AVec& a, <T>AVec& b)
+{
+  a.check_len(b.capacity());
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  <T>* u = b.vec();
+  while (t < top) *p++ = *t++ + *u++;
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec operator - (<T>AVec& a, <T>AVec& b)
+{
+  a.check_len(b.capacity());
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  <T>* u = b.vec();
+  while (t < top) *p++ = *t++ - *u++;
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec  product (<T>AVec& a, <T>AVec& b)
+{
+  a.check_len(b.capacity());
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  <T>* u = b.vec();
+  while (t < top) *p++ = *t++ * *u++;
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec quotient(<T>AVec& a, <T>AVec& b)
+{
+  a.check_len(b.capacity());
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  <T>* u = b.vec();
+  while (t < top) *p++ = *t++ / *u++;
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec operator + (<T>AVec& a, <T&> b)
+{
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  while (t < top) *p++ = *t++ + b;
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec operator - (<T>AVec& a, <T&> b)
+{
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  while (t < top) *p++ = *t++ - b;
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec operator * (<T>AVec& a, <T&> b)
+{
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  while (t < top) *p++ = *t++ * b;
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec operator / (<T>AVec& a, <T&> b)
+{
+  <T>* news = new <T> [a.capacity()];
+  <T>* p = news;
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  while (t < top) *p++ = *t++ / b;
+  return <T>AVec(a.capacity(), news);
+}
+
+<T>AVec <T>AVec::operator - ()
+{
+  <T>* news = new <T> [len];
+  <T>* p = news;
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *p++ = -(*t++);
+  return <T>AVec(len, news);
+}
+
+<T>AVec& <T>AVec::operator += (<T>AVec& b)
+{
+  check_len(b.capacity());
+  <T>* u = b.vec();
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ += *u++;
+  return *this;
+}
+
+<T>AVec& <T>AVec::operator -= (<T>AVec& b)
+{
+  check_len(b.capacity());
+  <T>* u = b.vec();
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ -= *u++;
+  return *this;
+}
+
+<T>AVec& <T>AVec::product(<T>AVec& b)
+{
+  check_len(b.capacity());
+  <T>* u = b.vec();
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ *= *u++;
+  return *this;
+}
+
+<T>AVec& <T>AVec::quotient(<T>AVec& b)
+{
+  check_len(b.capacity());
+  <T>* u = b.vec();
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ /= *u++;
+  return *this;
+}
+
+<T>AVec& <T>AVec::operator += (<T&> b)
+{
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ += b;
+  return *this;
+}
+
+<T>AVec& <T>AVec::operator -= (<T&> b)
+{
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ -= b;
+  return *this;
+}
+
+<T>AVec& <T>AVec::operator *= (<T&> b)
+{
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ *= b;
+  return *this;
+}
+
+<T>AVec& <T>AVec::operator /= (<T&> b)
+{
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ /= b;
+  return *this;
+}
+
+<T> <T>AVec::max()
+{
+  if (len == 0)
+    return 0;
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  <T> res = *t++;
+  for (; t < top; ++t) if (*t > res) res = *t;
+  return res;
+}
+
+int <T>AVec::max_index()
+{
+  if (len == 0)
+    return -1;
+  int ind = 0;
+  for (int i = 1; i < len; ++i)
+    if (s[i] > s[ind])
+      ind = i;
+  return ind;
+}
+
+<T> <T>AVec::min()
+{
+  if (len == 0)
+    return 0;
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  <T> res = *t++;
+  for (; t < top; ++t) if (*t < res) res = *t;
+  return res;
+}
+
+int <T>AVec::min_index()
+{
+  if (len == 0)
+    return -1;
+  int ind = 0;
+  for (int i = 1; i < len; ++i)
+    if (s[i] < s[ind])
+      ind = i;
+  return ind;
+}
+
+<T> <T>AVec::sum()
+{
+  <T> res = 0;
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) res += *t++;
+  return res;
+}
+
+
+<T> <T>AVec::sumsq()
+{
+  <T> res = 0;
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  for (; t < top; ++t) res += *t * *t;
+  return res;
+}
+
+<T> operator * (<T>AVec& a, <T>AVec& b)
+{
+  a.check_len(b.capacity());
+  <T>* top = &(a.vec()[a.capacity()]);
+  <T>* t = a.vec();
+  <T>* u = b.vec();
+  <T> res = 0;
+  while (t < top) res += *t++ * *u++;
+  return res;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/AVec.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/AVec.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/AVec.hP	(revision 18)
@@ -0,0 +1,118 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>AVec_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>AVec_h 1
+
+#include "<T>.Vec.h"
+
+class <T>AVec : public <T>Vec
+{
+protected:
+  void                  check_len(int l);
+  <T>*                  vec();
+  const <T>*		vec() const;
+                        <T>AVec(int l, <T>* d);
+  public:
+                        <T>AVec ();
+                        <T>AVec (int l);
+                        <T>AVec (int l, <T&> fill_value);
+                        <T>AVec (const <T>AVec&);
+                        ~<T>AVec ();
+
+  <T>AVec&              operator =  (const <T>AVec& a);
+  <T>AVec&              operator =  (<T&> fill_value);
+
+// vector by scalar -> vector operations
+
+  friend <T>AVec        operator +  (<T>AVec& a, <T&> b);
+  friend <T>AVec        operator -  (<T>AVec& a, <T&> b);
+  friend <T>AVec        operator *  (<T>AVec& a, <T&> b);
+  friend <T>AVec        operator /  (<T>AVec& a, <T&> b);
+
+  <T>AVec&              operator += (<T&> b);
+  <T>AVec&              operator -= (<T&> b);
+  <T>AVec&              operator *= (<T&> b);
+  <T>AVec&              operator /= (<T&> b);
+
+// vector by vector -> vector operations
+
+  friend <T>AVec        operator +  (<T>AVec& a, <T>AVec& b);
+  friend <T>AVec        operator -  (<T>AVec& a, <T>AVec& b);
+  <T>AVec&              operator += (<T>AVec& b);
+  <T>AVec&              operator -= (<T>AVec& b);
+
+  <T>AVec               operator - ();
+
+  friend <T>AVec        product(<T>AVec& a, <T>AVec& b);
+  <T>AVec&              product(<T>AVec& b);
+  friend <T>AVec        quotient(<T>AVec& a, <T>AVec& b);
+  <T>AVec&              quotient(<T>AVec& b);
+
+// vector -> scalar operations
+
+  friend <T>            operator * (<T>AVec& a, <T>AVec& b);
+
+  <T>                   sum();
+  <T>                   min();
+  <T>                   max();
+  <T>                   sumsq();
+
+// indexing
+
+  int                   min_index();
+  int                   max_index();
+
+// redundant but necesssary
+  friend <T>AVec        concat(<T>AVec& a, <T>AVec& b);
+  friend <T>AVec        map(<T>Mapper f, <T>AVec& a);
+  friend <T>AVec        merge(<T>AVec& a, <T>AVec& b, <T>Comparator f);
+  friend <T>AVec        combine(<T>Combiner f, <T>AVec& a, <T>AVec& b);
+  friend <T>AVec        reverse(<T>AVec& a);
+  <T>AVec               at(int from = 0, int n = -1);
+};
+
+inline <T>AVec::<T>AVec() {}
+inline <T>AVec::<T>AVec(int l) :<T>Vec(l) {}
+inline <T>AVec::<T>AVec(int l, <T&> fill_value) : <T>Vec (l, fill_value) {}
+inline <T>AVec::<T>AVec(const <T>AVec& v) :<T>Vec(v) {}
+inline <T>AVec::<T>AVec(int l, <T>* d) :<T>Vec(l, d) {}
+inline <T>AVec::~<T>AVec() {}
+
+
+inline <T>* <T>AVec::vec()
+{
+  return s;
+}
+
+inline const <T>* <T>AVec::vec() const
+{
+  return s;
+}
+
+inline void <T>AVec::check_len(int l)
+{
+  if (l != len)
+    error("nonconformant vectors.");
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/BSTSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/BSTSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/BSTSet.ccP	(revision 18)
@@ -0,0 +1,377 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.BSTSet.h"
+
+
+/*
+ traversal primitives
+*/
+
+
+<T>BSTNode* <T>BSTSet::leftmost()
+{
+  <T>BSTNode* t = root;
+  if (t != 0) while (t->lt != 0) t = t->lt;
+  return t;
+}
+
+<T>BSTNode* <T>BSTSet::rightmost()
+{
+  <T>BSTNode* t = root;
+  if (t != 0) while (t->rt != 0) t = t->rt;
+  return t;
+}
+
+<T>BSTNode* <T>BSTSet::succ(<T>BSTNode* t)
+{
+  if (t == 0)
+    return 0;
+  if (t->rt != 0)
+  {
+    t = t->rt;
+    while (t->lt != 0) t = t->lt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->lt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+<T>BSTNode* <T>BSTSet::pred(<T>BSTNode* t)
+{
+  if (t == 0)
+    return 0;
+  else if (t->lt != 0)
+  {
+    t = t->lt;
+    while (t->rt != 0) t = t->rt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->rt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+
+Pix <T>BSTSet::seek(<T&> key)
+{
+  <T>BSTNode* t = root;
+  for (;;)
+  {
+    if (t == 0)
+      return 0;
+    int comp = <T>CMP(key, t->item);
+    if (comp == 0)
+      return Pix(t);
+    else if (comp < 0)
+      t = t->lt;
+    else
+      t = t->rt;
+  }
+}
+
+
+Pix <T>BSTSet::add(<T&> item)
+{
+  if (root == 0)
+  {
+    ++count;
+    root = new <T>BSTNode(item);
+    return Pix(root);
+  }
+
+  <T>BSTNode* t = root;
+  <T>BSTNode* p = root;
+  for (;;)
+  {
+    int comp = <T>CMP(t->item, item);
+    if (comp == 0)
+      return Pix(t);
+    else if (comp > 0)
+      t = t->lt;
+    else
+      t = t->rt;
+    if (t == 0)
+    {
+      ++count;
+      t = new <T>BSTNode(item);
+      if (comp > 0)
+        p->lt = t;
+      else
+        p->rt = t;
+      t->par = p;
+      return Pix(t);
+    }
+    p = t;
+  }
+}
+
+
+void <T>BSTSet::del(<T&> key)
+{
+  <T>BSTNode* t = root;
+  <T>BSTNode* p = root;
+  int comp;
+  for (;;)
+  {
+    if (t == 0)
+      return;
+    comp = <T>CMP(key, t->item);
+    if (comp == 0)
+    {
+      --count;
+      <T>BSTNode* repl;
+      if (t->lt == 0)
+        repl = t->rt;
+      else if (t->rt == 0)
+        repl = t->lt;
+      else
+      {
+        <T>BSTNode* prepl = t;
+        repl = t->lt;
+        while (repl->rt != 0)
+        {
+          prepl = repl;
+          repl = repl->rt;
+        }
+        if (prepl != t)
+        {
+          prepl->rt = repl->lt;
+          if (prepl->rt != 0) prepl->rt->par = prepl;
+          repl->lt = t->lt;
+          if (repl->lt != 0) repl->lt->par = repl;
+        }
+        repl->rt = t->rt;
+        if (repl->rt != 0) repl->rt->par = repl;
+      }
+      if (t == root)
+      {
+        root = repl;
+        if (repl != 0) repl->par = 0;
+      }
+      else
+      {
+        if (t == p->lt)
+          p->lt = repl;
+        else
+          p->rt = repl;
+        if (repl != 0) repl->par = p;
+      }
+      delete t;
+      return;
+    }
+    p = t;
+    if (comp < 0)
+      t = t->lt;
+    else
+      t = t->rt;
+  }
+}
+
+
+void <T>BSTSet::_kill(<T>BSTNode* t)
+{
+  if (t != 0)
+  {
+    _kill(t->lt);
+    _kill(t->rt);
+    delete t;
+  }
+}
+
+<T>BSTNode* <T>BSTSet::_copy(<T>BSTNode* t)
+{
+  if (t == 0)
+    return 0;
+  else
+  {
+    <T>BSTNode* u = new <T>BSTNode(t->item, _copy(t->lt), _copy(t->rt));
+    if (u->lt != 0) u->lt->par = u;
+    if (u->rt != 0) u->rt->par = u;
+    return u;
+  }
+}
+
+
+int <T>BSTSet::operator == (<T>BSTSet& y)
+{
+  if (count != y.count)
+    return 0;
+  else
+  {
+    <T>BSTNode* t = leftmost();
+    <T>BSTNode* u = y.leftmost();
+    for (;;)
+    {
+      if (t == 0)
+        return 1;
+      else if (!<T>EQ(t->item, u->item))
+        return 0;
+      else
+      {
+        t = succ(t);
+        u = y.succ(u);
+      }
+    }
+  }
+}
+
+int <T>BSTSet::operator <= (<T>BSTSet& y)
+{
+  if (count > y.count)
+    return 0;
+  else
+  {
+    <T>BSTNode* t = leftmost();
+    <T>BSTNode* u = y.leftmost();
+    for (;;)
+    {
+      if (t == 0)
+        return 1;
+      else if (u == 0)
+        return 0;
+      int cmp = <T>CMP(t->item, u->item);
+      if (cmp == 0)
+      {
+        t = succ(t);
+        u = y.succ(u);
+      }
+      else if (cmp < 0)
+        return 0;
+      else
+        u = y.succ(u);
+    }
+  }
+}
+
+
+// linear-time, zero space overhead binary tree rebalancing from
+// Stout & Warren, ``Tree rebalancing in linear space and time''
+// CACM, Sept, 1986, p902.
+
+
+void <T>BSTSet::balance()
+{
+  if (count <= 2) return; // don't bother -- 
+                          // also we assume non-null root, below
+
+  // make re-attaching the root easy via trickery
+
+  struct _fake_node { _fake_node *lt, *rt, *par; } fake_root;
+
+  fake_root.rt = (_fake_node*)root; 
+  fake_root.par = 0;
+  <T>BSTNode* pseudo_root = (<T>BSTNode*)&fake_root;
+
+  // phase 1: tree-to-vine
+
+  <T>BSTNode* vine_tail = pseudo_root;
+  <T>BSTNode* remainder = root;
+
+  while (remainder != 0)
+  {
+    if (remainder->lt == 0)
+    {
+      vine_tail = remainder;
+      remainder = remainder->rt;
+    }
+    else
+    {
+      <T>BSTNode* tmp = remainder->lt;
+      remainder->lt = tmp->rt;
+      if (remainder->lt != 0) remainder->lt->par = remainder;
+      tmp->rt = remainder;
+      remainder->par = tmp;
+      vine_tail->rt = remainder = tmp;
+    }
+  }
+
+  // phase 2: vine-to-tree
+  
+  // Uses the slightly simpler version adapted from
+  // Day ``Balancing a binary tree'' Computer Journal, Nov. 1976,
+  // since it's not generally important whether the `stray' leaves are
+  // on the left or on the right.
+
+  unsigned int spines = count - 1;
+  while (spines > 1)
+  {
+    int compressions = spines >> 1; // compress every other node
+    spines -= compressions + 1;     // halve for next time
+
+    <T>BSTNode* scanner = pseudo_root;
+    while (compressions-- > 0)
+    {
+      <T>BSTNode* child = scanner->rt;
+      <T>BSTNode* grandchild = child->rt;
+      scanner->rt = grandchild;
+      grandchild->par = scanner;
+      child->rt = grandchild->lt;
+      if (child->rt != 0) child->rt->par = child;
+      grandchild->lt = child;
+      child->par = grandchild;
+      scanner = grandchild;
+    }
+  }
+
+  root = pseudo_root->rt;
+  root->par = 0;
+}
+
+
+int <T>BSTSet::OK()
+{
+  int v = 1;
+  if (root == 0) 
+    v = count == 0;
+  else
+  {
+    int n = 1;
+    <T>BSTNode* trail = leftmost();
+    <T>BSTNode* t = succ(trail);
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/BSTSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/BSTSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/BSTSet.hP	(revision 18)
@@ -0,0 +1,152 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>BSTSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>BSTSet_h 1
+
+#include "<T>.Set.h"
+
+#ifndef _<T>BSTNode
+#define _<T>BSTNode 1
+
+struct <T>BSTNode
+{
+  <T>BSTNode*         lt;
+  <T>BSTNode*         rt;
+  <T>BSTNode*         par;
+  <T>                 item;
+                      <T>BSTNode(<T&> h, <T>BSTNode* l=0, <T>BSTNode* r=0,
+                                 <T>BSTNode* p = 0);
+                      ~<T>BSTNode();
+};
+
+inline <T>BSTNode::<T>BSTNode(<T&> h, <T>BSTNode* l, <T>BSTNode* r,
+                              <T>BSTNode* p)
+:lt(l), rt(r), par(p), item(h)  {}
+
+inline <T>BSTNode::~<T>BSTNode() {}
+
+typedef <T>BSTNode* <T>BSTNodePtr;
+
+#endif
+
+class <T>BSTSet : public <T>Set
+{
+protected:
+  <T>BSTNode*      root;
+
+  <T>BSTNode*     leftmost();
+  <T>BSTNode*     rightmost();
+  <T>BSTNode*     pred(<T>BSTNode* t);
+  <T>BSTNode*     succ(<T>BSTNode* t);
+  void            _kill(<T>BSTNode* t);
+  <T>BSTNode*     _copy(<T>BSTNode* t);
+
+public:
+                   <T>BSTSet();
+                   <T>BSTSet(<T>BSTSet& a);
+  inline                  ~<T>BSTSet();
+
+  Pix             add(<T&> item);
+  void            del(<T&> item);
+  inline int             contains(<T&> item);
+
+  inline void            clear();
+
+  inline Pix             first();
+  inline void            next(Pix& i);
+  inline <T>&            operator () (Pix i);
+  Pix             seek(<T&> item);
+
+  Pix             last();
+  void            prev(Pix& i);
+
+  int             operator == (<T>BSTSet& b);
+  int             operator != (<T>BSTSet& b);
+  int             operator <= (<T>BSTSet& b); 
+
+  void            balance();
+  int             OK();
+};
+
+inline <T>BSTSet::~<T>BSTSet()
+{
+  _kill(root);
+}
+
+inline <T>BSTSet::<T>BSTSet()
+{
+  root = 0;
+  count = 0;
+}
+
+
+inline <T>BSTSet::<T>BSTSet(<T>BSTSet& a)
+{
+  count = a.count;
+  root = _copy(a.root);
+}
+
+inline int <T>BSTSet::operator != (<T>BSTSet& b)
+{
+  return ! (*this == b);
+}
+
+inline Pix <T>BSTSet::first()
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T>BSTSet::last()
+{
+  return Pix(rightmost());
+}
+
+inline void <T>BSTSet::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T>BSTNode*)i));
+}
+
+inline void <T>BSTSet::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T>BSTNode*)i));
+}
+
+inline <T>& <T>BSTSet::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T>BSTNode*)i)->item;
+}
+
+inline void <T>BSTSet::clear()
+{
+  _kill(root);
+  count = 0;
+  root = 0;
+}
+
+inline int <T>BSTSet::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/Bag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Bag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Bag.ccP	(revision 18)
@@ -0,0 +1,74 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <builtin.h>
+#include "<T>.Bag.h"
+
+// error handling
+
+void <T>Bag::error(const char* msg)
+{
+  (*lib_error_handler)("Bag", msg);
+}
+
+
+Pix <T>Bag::seek(<T&> item, Pix i)
+{
+  if (i == 0) 
+    i = first();
+  else
+    next(i);
+  for (;i != 0 && (!(<T>EQ((*this)(i), item))); next(i));
+  return i;
+}
+
+int <T>Bag::owns(Pix p)
+{
+  if (p == 0) return 0;
+  for (Pix i = first(); i != 0; next(i)) if (i == p) return 1;
+  return 0;
+}
+
+void <T>Bag::remove(<T&> item)
+{
+  int i = nof(item);
+  while (i-- > 0) del(item);
+}
+
+
+int <T>Bag::nof(<T&> item)
+{
+  int n = 0;
+  for (Pix p = first(); p; next(p)) if (<T>EQ((*this)(p), item)) ++n;
+  return n;
+}
+
+void <T>Bag::clear()
+{
+  Pix i = first(); 
+  while (i != 0)
+  {
+    del((*this)(i));
+    i = first();
+  }
+}
+
+
Index: trunk/src/emx/include/Attic/cpp/gen/Bag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Bag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Bag.hP	(revision 18)
@@ -0,0 +1,79 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>Bag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>Bag_h 1
+
+#include <Pix.h>
+#include "<T>.defs.h"
+
+class <T>Bag
+{
+protected:
+  int                   count;
+
+public:
+  inline virtual              ~<T>Bag();
+
+  int                   length();                // current number of items
+  int                   empty();
+
+  virtual Pix           add(<T&> item) = 0;      // add item; return Pix
+
+  virtual void          del(<T&> item) = 0;      // delete 1 occurrence of item
+#undef remove
+  virtual void          remove(<T&> item);       // delete all occurrences
+  virtual void          clear();                 // delete all items
+
+  inline virtual int           contains(<T&> item);     // is item in Bag?
+  virtual int           nof(<T&> item);          // how many in Bag?
+
+  virtual Pix           first() = 0;             // Pix of first item or 0
+  virtual void          next(Pix& i) = 0;        // advance to next or 0
+
+  virtual <T>&          operator () (Pix i) = 0; // access item at i
+
+  virtual Pix           seek(<T&> item, Pix from=0); // Pix of next occurrence
+  virtual int           owns(Pix i);             // is i a valid Pix  ?
+
+  void                  error(const char* msg);
+  virtual int           OK() = 0;                // rep invariant
+};
+
+inline <T>Bag::~<T>Bag() {}
+
+inline int <T>Bag::length()
+{
+  return count;
+}
+
+inline int <T>Bag::empty()
+{
+  return count == 0;
+}
+
+inline int <T>Bag::contains(<T&> item)
+{
+  return seek(item) != 0;
+}
+ 
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/CHBag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/CHBag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/CHBag.ccP	(revision 18)
@@ -0,0 +1,210 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.CHBag.h"
+
+// The nodes are linked together serially via a version
+// of a trick used in some vtables: odd pointers are
+// actually links to the next table entry. 
+// Not terrible, but not wonderful either
+
+static inline int goodCHptr(<T>CHNode* t)
+{
+  return ((((unsigned)t) & 1) == 0);
+}
+
+static inline <T>CHNode* index_to_CHptr(int i)
+{
+  return (<T>CHNode*)((i << 1) + 1);
+}
+
+static inline int CHptr_to_index(<T>CHNode* t)
+{
+  return ( ((unsigned) t) >> 1);
+}
+
+<T>CHBag::<T>CHBag(unsigned int sz)
+{
+  tab = (<T>CHNode**)(new <T>CHNodePtr[size = sz]);
+  for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1);
+  count = 0;
+}
+
+<T>CHBag::<T>CHBag(<T>CHBag& a)
+{
+  tab = (<T>CHNode**)(new <T>CHNodePtr[size = a.size]);
+  for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1);
+  count = 0;
+  for (Pix p = a.first(); p; a.next(p)) add(a(p));
+}
+
+
+Pix <T>CHBag::seek(<T&> key, Pix i)
+{
+  <T>CHNode* p = (<T>CHNode*)i;
+  if (p == 0 || !<T>EQ(p->hd, key))
+  {
+    unsigned int h = <T>HASH(key) % size;
+    for (<T>CHNode* t = tab[h]; goodCHptr(t); t = t->tl)
+      if (<T>EQ(key, t->hd))
+        return Pix(t);
+  }
+  else
+  {
+    for (p = p->tl; goodCHptr(p); p = p->tl) 
+      if (<T>EQ(p->hd, key))
+        return Pix(p);
+  }
+  return 0;
+}
+
+int <T>CHBag::nof(<T&> key)
+{
+  int n = 0;
+  unsigned int h = <T>HASH(key) % size;
+  for (<T>CHNode* t = tab[h]; goodCHptr(t); t = t->tl) 
+    if (<T>EQ(key, t->hd)) ++n;
+  return n;
+}
+
+
+Pix <T>CHBag::add(<T&> item)
+{
+  unsigned int h = <T>HASH(item) % size;
+  <T>CHNode* t = new <T>CHNode(item);
+  t->tl = tab[h];
+  tab[h] = t;
+  ++count;
+  return Pix(t);
+}
+
+void <T>CHBag::del(<T&> key)
+{
+  unsigned int h = <T>HASH(key) % size;
+
+  <T>CHNode* t = tab[h]; 
+  <T>CHNode* trail = t;
+  while (goodCHptr(t))
+  {
+    if (<T>EQ(key, t->hd))
+    {
+      if (trail == t)
+        tab[h] = t->tl;
+      else
+        trail->tl = t->tl;
+      delete t;
+      --count;
+      return;
+    }
+    trail = t;
+    t = t->tl;
+  }
+}
+
+void <T>CHBag::remove(<T&> key)
+{
+  unsigned int h = <T>HASH(key) % size;
+
+  <T>CHNode* t = tab[h]; 
+  <T>CHNode* trail = t;
+  while (goodCHptr(t))
+  {
+    if (<T>EQ(key, t->hd))
+    {
+      --count;
+      if (trail == t)
+      {
+        tab[h] = t->tl;
+        delete t;
+        t = trail = tab[h];
+      }
+      else
+      {
+        trail->tl = t->tl;
+        delete t;
+        t = trail->tl;
+      }
+    }
+    else
+    {
+      trail = t;
+      t = t->tl;
+    }
+  }
+}
+
+
+void <T>CHBag::clear()
+{
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    <T>CHNode* p = tab[i];
+    tab[i] = index_to_CHptr(i+1);
+    while (goodCHptr(p))
+    {
+      <T>CHNode* nxt = p->tl;
+      delete(p);
+      p = nxt;
+    }
+  }
+  count = 0;
+}
+
+Pix <T>CHBag::first()
+{
+  for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]);
+  return 0;
+}
+
+void <T>CHBag::next(Pix& p)
+{
+  if (p == 0) return;
+  <T>CHNode* t = ((<T>CHNode*)p)->tl;
+  if (goodCHptr(t))
+    p = Pix(t);
+  else
+  {
+    for (unsigned int i = CHptr_to_index(t); i < size; ++i) 
+    {
+      if (goodCHptr(tab[i]))
+      {
+        p =  Pix(tab[i]);
+        return;
+      }
+    }
+    p = 0;
+  }
+}
+
+int <T>CHBag::OK()
+{
+  int v = tab != 0;
+  int n = 0;
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    <T>CHNode* p;
+    for (p = tab[i]; goodCHptr(p); p = p->tl) ++n;
+    v &= CHptr_to_index(p) == i + 1;
+  }
+  v &= count == n;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/CHBag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/CHBag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/CHBag.hP	(revision 18)
@@ -0,0 +1,76 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>CHBag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>CHBag_h 1
+
+#include "<T>.Bag.h"
+
+
+#include "<T>.CHNode.h"
+
+class <T>CHBag : public <T>Bag
+{
+protected:
+  <T>CHNode**   tab;
+  unsigned int  size;
+
+public:
+                <T>CHBag(unsigned int sz = DEFAULT_INITIAL_CAPACITY);
+                <T>CHBag(<T>CHBag& a);
+  inline               ~<T>CHBag();
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  void          remove(<T&>item);
+  int           nof(<T&> item);
+  inline int           contains(<T&> item);
+
+  void          clear();
+
+  Pix           first();
+  void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  Pix           seek(<T&> item, Pix from = 0);
+
+  int           OK();
+};
+
+
+inline <T>CHBag::~<T>CHBag()
+{
+  clear();
+  delete tab;
+}
+
+inline int <T>CHBag::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+inline <T>& <T>CHBag::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T>CHNode*)i)->hd;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/CHMap.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/CHMap.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/CHMap.ccP	(revision 18)
@@ -0,0 +1,168 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.<C>.CHMap.h"
+
+// The nodes are linked together serially via a version
+// of a trick used in some vtables: odd pointers are
+// actually links to the next table entry. 
+// Not terrible, but not wonderful either
+
+static inline int goodCHptr(<T><C>CHNode* t)
+{
+  return ((((unsigned)t) & 1) == 0);
+}
+
+static inline <T><C>CHNode* index_to_CHptr(int i)
+{
+  return (<T><C>CHNode*)((i << 1) + 1);
+}
+
+static inline int CHptr_to_index(<T><C>CHNode* t)
+{
+  return ( ((unsigned) t) >> 1);
+}
+
+<T><C>CHMap::<T><C>CHMap(<C&> dflt, unsigned int sz)
+     :<T><C>Map(dflt)
+{
+  tab = (<T><C>CHNode**)(new <T><C>CHNodePtr[size = sz]);
+  for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1);
+  count = 0;
+}
+
+<T><C>CHMap::<T><C>CHMap(<T><C>CHMap& a) :<T><C>Map(a.def)
+{
+  tab = (<T><C>CHNode**)(new <T><C>CHNodePtr[size = a.size]);
+  for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1);
+  count = 0;
+  for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p);
+}
+
+
+Pix <T><C>CHMap::seek(<T&> key)
+{
+  unsigned int h = <T>HASH(key) % size;
+
+  for (<T><C>CHNode* t = tab[h]; goodCHptr(t); t = t->tl)
+    if (<T>EQ(key, t->hd))
+      return Pix(t);
+
+  return 0;
+}
+
+
+<C>& <T><C>CHMap::operator [](<T&> item)
+{
+  unsigned int h = <T>HASH(item) % size;
+  <T><C>CHNode* t;
+
+  for (t = tab[h]; goodCHptr(t); t = t->tl)
+    if (<T>EQ(item, t->hd))
+      return t->cont;
+
+  t = new <T><C>CHNode(item, def, tab[h]);
+  tab[h] = t;
+  ++count;
+  return t->cont;
+}
+
+
+void <T><C>CHMap::del(<T&> key)
+{
+  unsigned int h = <T>HASH(key) % size;
+
+  <T><C>CHNode* t = tab[h]; 
+  <T><C>CHNode* trail = t;
+  while (goodCHptr(t))
+  {
+    if (<T>EQ(key, t->hd))
+    {
+      if (trail == t)
+        tab[h] = t->tl;
+      else
+        trail->tl = t->tl;
+      delete t;
+      --count;
+      return;
+    }
+    trail = t;
+    t = t->tl;
+  }
+}
+
+
+void <T><C>CHMap::clear()
+{
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    <T><C>CHNode* p = tab[i];
+    tab[i] = index_to_CHptr(i+1);
+    while (goodCHptr(p))
+    {
+      <T><C>CHNode* nxt = p->tl;
+      delete(p);
+      p = nxt;
+    }
+  }
+  count = 0;
+}
+
+Pix <T><C>CHMap::first()
+{
+  for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]);
+  return 0;
+}
+
+void <T><C>CHMap::next(Pix& p)
+{
+  <T><C>CHNode* t = ((<T><C>CHNode*)p)->tl;
+  if (goodCHptr(t))
+    p = Pix(t);
+  else
+  {
+    for (unsigned int i = CHptr_to_index(t); i < size; ++i) 
+    {
+      if (goodCHptr(tab[i]))
+      {
+        p =  Pix(tab[i]);
+        return;
+      }
+    }
+    p = 0;
+  }
+}
+
+
+int <T><C>CHMap::OK()
+{
+  int v = tab != 0;
+  int n = 0;
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    <T><C>CHNode* p;
+    for (p = tab[i]; goodCHptr(p); p = p->tl) ++n;
+    v &= CHptr_to_index(p) == i + 1;
+  }
+  v &= count == n;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/CHMap.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/CHMap.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/CHMap.hP	(revision 18)
@@ -0,0 +1,104 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T><C>CHMap_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T><C>CHMap_h 1
+
+#include "<T>.<C>.Map.h"
+
+#ifndef _<T><C>CHNode_h
+#define _<T><C>CHNode_h 1
+
+struct <T><C>CHNode
+{
+  <T><C>CHNode*      tl;
+  <T>                hd;
+  <C>                cont;
+                     <T><C>CHNode();
+                     <T><C>CHNode(<T&> h, <C&> c, <T><C>CHNode* t = 0);
+                     ~<T><C>CHNode();
+};
+
+inline <T><C>CHNode::<T><C>CHNode() {}
+
+inline <T><C>CHNode::<T><C>CHNode(<T&> h, <C&> c, <T><C>CHNode* t)
+     : tl(t), hd(h), cont(c) {}
+
+inline <T><C>CHNode::~<T><C>CHNode() {}
+
+typedef <T><C>CHNode* <T><C>CHNodePtr;
+
+#endif
+
+
+class <T><C>CHMap : public <T><C>Map
+{
+protected:
+  <T><C>CHNode** tab;
+  unsigned int   size;
+
+public:
+                <T><C>CHMap(<C&> dflt,unsigned int sz=DEFAULT_INITIAL_CAPACITY);
+                <T><C>CHMap(<T><C>CHMap& a);
+  inline               ~<T><C>CHMap();
+
+  <C>&          operator [] (<T&> key);
+
+  void          del(<T&> key);
+
+  Pix           first();
+  void          next(Pix& i);
+  inline <T>&          key(Pix i);
+  inline <C>&          contents(Pix i);
+
+  Pix           seek(<T&> key);
+  inline int           contains(<T&> key);
+
+  void          clear(); 
+  int           OK();
+};
+
+
+inline <T><C>CHMap::~<T><C>CHMap()
+{
+  clear();
+  delete tab;
+}
+
+inline int <T><C>CHMap::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+inline <T>& <T><C>CHMap::key(Pix p)
+{
+  if (p == 0) error("null Pix");
+  return ((<T><C>CHNode*)p)->hd;
+}
+
+inline <C>& <T><C>CHMap::contents(Pix p)
+{
+  if (p == 0) error("null Pix");
+  return ((<T><C>CHNode*)p)->cont;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/CHNode.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/CHNode.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/CHNode.ccP	(revision 18)
@@ -0,0 +1,21 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1992 Free Software Foundation
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.CHNode.h"
Index: trunk/src/emx/include/Attic/cpp/gen/CHNode.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/CHNode.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/CHNode.hP	(revision 18)
@@ -0,0 +1,43 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988, 1982 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>CHNode_h
+#define _<T>CHNode_h 1
+#ifdef __GNUG__
+#pragma interface
+#endif
+#include "<T>.defs.h"
+
+struct <T>CHNode
+{
+  <T>CHNode*         tl;
+  <T>                hd;
+                     <T>CHNode();
+                     <T>CHNode(<T&> h, <T>CHNode* t = 0);
+                     ~<T>CHNode();
+};
+
+inline <T>CHNode::<T>CHNode() {}
+
+inline <T>CHNode::<T>CHNode(<T&> h, <T>CHNode* t) :tl(t), hd(h) {}
+
+inline <T>CHNode::~<T>CHNode() {}
+
+typedef <T>CHNode* <T>CHNodePtr;
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/CHSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/CHSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/CHSet.ccP	(revision 18)
@@ -0,0 +1,273 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.CHSet.h"
+
+// A CHSet is implemented as an array (tab) of buckets, each of which
+// contains a pointer to a list of <T>CHNodes.  Each node contains a
+// pointer to the next node in the list, and a pointer to the <T>.
+// The end of the list is marked by a next node pointer which is odd
+// when considered as an integer (least significant bit = 1).  The
+// assumption is that CHNodes will all begin on even addresses.  If
+// the odd pointer is right-shifted by one bit, it becomes the index
+// within the tab array of the next bucket (that is, bucket i has
+// next bucket pointer 2*(i+1)+1).
+
+// The bucket pointers are initialized by the constructor and
+// used to support the next(Pix&) method.
+
+// This implementation is not portable to machines with different
+// pointer and integer sizes, or on which CHNodes might be aligned on
+// odd byte boundaries, but allows the same pointer to be used for
+// chaining within a bucket and to the next bucket.
+
+
+static inline int goodCHptr(<T>CHNode* t)
+{
+  return ((((unsigned)t) & 1) == 0);
+}
+
+static inline <T>CHNode* index_to_CHptr(int i)
+{
+  return (<T>CHNode*)((i << 1) + 1);
+}
+
+static inline int CHptr_to_index(<T>CHNode* t)
+{
+  return ( ((unsigned) t) >> 1);
+}
+
+<T>CHSet::<T>CHSet(unsigned int sz)
+{
+  tab = (<T>CHNode**)(new <T>CHNodePtr[size = sz]);
+  for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1);
+  count = 0;
+}
+
+<T>CHSet::<T>CHSet(<T>CHSet& a)
+{
+  tab = (<T>CHNode**)(new <T>CHNodePtr[size = a.size]);
+  for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1);
+  count = 0;
+  for (Pix p = a.first(); p; a.next(p)) add(a(p));
+}
+
+
+Pix <T>CHSet::seek(<T&> key)
+{
+  unsigned int h = <T>HASH(key) % size;
+
+  for (<T>CHNode* t = tab[h]; goodCHptr(t); t = t->tl)
+    if (<T>EQ(key, t->hd))
+      return Pix(t);
+
+  return 0;
+}
+
+
+Pix <T>CHSet::add(<T&> item)
+{
+  unsigned int h = <T>HASH(item) % size;
+  <T>CHNode* t;
+
+  for (t = tab[h]; goodCHptr(t); t = t->tl)
+    if (<T>EQ(item, t->hd))
+      return Pix(t);
+
+  ++count;
+  t = new <T>CHNode(item, tab[h]);
+  tab[h] = t;
+  return Pix(t);
+}
+
+
+void <T>CHSet::del(<T&> key)
+{
+  unsigned int h = <T>HASH(key) % size;
+
+  <T>CHNode* t = tab[h]; 
+  <T>CHNode* trail = t;
+  while (goodCHptr(t))
+  {
+    if (<T>EQ(key, t->hd))
+    {
+      if (trail == t)
+        tab[h] = t->tl;
+      else
+        trail->tl = t->tl;
+      delete t;
+      --count;
+      return;
+    }
+    trail = t;
+    t = t->tl;
+  }
+}
+
+
+void <T>CHSet::clear()
+{
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    <T>CHNode* p = tab[i];
+    tab[i] = index_to_CHptr(i+1);
+    while (goodCHptr(p))
+    {
+      <T>CHNode* nxt = p->tl;
+      delete(p);
+      p = nxt;
+    }
+  }
+  count = 0;
+}
+
+Pix <T>CHSet::first()
+{
+  for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]);
+  return 0;
+}
+
+void <T>CHSet::next(Pix& p)
+{
+  if (p == 0) return;
+  <T>CHNode* t = ((<T>CHNode*)p)->tl;
+  if (goodCHptr(t))
+    p = Pix(t);
+  else
+  {
+    for (unsigned int i = CHptr_to_index(t); i < size; ++i) 
+    {
+      if (goodCHptr(tab[i]))
+      {
+        p =  Pix(tab[i]);
+        return;
+      }
+    }
+    p = 0;
+  }
+}
+
+int <T>CHSet::operator == (<T>CHSet& b)
+{
+  if (count != b.count)
+    return 0;
+  else
+  {
+    <T>CHNode* p;
+    for (unsigned int i = 0; i < size; ++i)
+      for (p = tab[i]; goodCHptr(p); p = p->tl)
+        if (b.seek(p->hd) == 0)
+          return 0;
+    for (unsigned int i = 0; i < b.size; ++i)
+      for (p = b.tab[i]; goodCHptr(p); p = p->tl)
+        if (seek(p->hd) == 0)
+          return 0;
+    return 1;
+  }
+}
+
+int <T>CHSet::operator <= (<T>CHSet& b)
+{
+  if (count > b.count)
+    return 0;
+  else
+  {
+    for (unsigned int i = 0; i < size; ++i)
+      for (<T>CHNode* p = tab[i]; goodCHptr(p); p = p->tl)
+        if (b.seek(p->hd) == 0)
+          return 0;
+    return 1;
+  }
+}
+
+void <T>CHSet::operator |= (<T>CHSet& b)
+{
+  if (&b == this || b.count == 0)
+    return;
+  for (unsigned int i = 0; i < b.size; ++i)
+    for (<T>CHNode* p = b.tab[i]; goodCHptr(p); p = p->tl)
+      add(p->hd);
+}
+
+void <T>CHSet::operator &= (<T>CHSet& b)
+{
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    <T>CHNode* t = tab[i]; 
+    <T>CHNode* trail = t;
+    while (goodCHptr(t))
+    {
+      <T>CHNode* nxt = t->tl;
+      if (b.seek(t->hd) == 0)
+      {
+        if (trail == tab[i])
+          trail = tab[i] = nxt;
+        else
+          trail->tl = nxt;
+        delete t;
+        --count;
+      }
+      else
+        trail = t;
+      t = nxt;
+    }
+  }
+}
+
+void <T>CHSet::operator -= (<T>CHSet& b)
+{
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    <T>CHNode* t = tab[i]; 
+    <T>CHNode* trail = t;
+    while (goodCHptr(t))
+    {
+      <T>CHNode* nxt = t->tl;
+      if (b.seek(t->hd) != 0)
+      {
+        if (trail == tab[i])
+          trail = tab[i] = nxt;
+        else
+          trail->tl = nxt;
+        delete t;
+        --count;
+      }
+      else
+        trail = t;
+      t = nxt;
+    }
+  }
+}
+
+int <T>CHSet::OK()
+{
+  int v = tab != 0;
+  int n = 0;
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    <T>CHNode* p;
+    for (p = tab[i]; goodCHptr(p); p = p->tl) ++n;
+    v &= CHptr_to_index(p) == i + 1;
+  }
+  v &= count == n;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/CHSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/CHSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/CHSet.hP	(revision 18)
@@ -0,0 +1,84 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>CHSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>CHSet_h 1
+
+#include "<T>.Set.h"
+#include "<T>.CHNode.h"
+
+class <T>CHSet : public <T>Set
+{
+protected:
+  <T>CHNode**   tab;
+  unsigned int  size;
+
+public:
+                <T>CHSet(unsigned int sz = DEFAULT_INITIAL_CAPACITY);
+                <T>CHSet(<T>CHSet& a);
+  inline               ~<T>CHSet();
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  inline int           contains(<T&> item);
+
+  void          clear();
+
+  Pix           first();
+  void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  Pix           seek(<T&> item);
+
+  void          operator |= (<T>CHSet& b);
+  void          operator -= (<T>CHSet& b);
+  void          operator &= (<T>CHSet& b);
+
+  int           operator == (<T>CHSet& b);
+  int           operator != (<T>CHSet& b);
+  int           operator <= (<T>CHSet& b); 
+
+  int           OK();
+};
+
+inline <T>CHSet::~<T>CHSet()
+{
+  clear();
+  delete tab;
+}
+
+inline int <T>CHSet::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+inline <T>& <T>CHSet::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T>CHNode*)i)->hd;
+}
+
+inline int <T>CHSet::operator != (<T>CHSet& b)
+{
+  return ! ((*this) == b);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/DLDeque.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/DLDeque.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/DLDeque.ccP	(revision 18)
@@ -0,0 +1,4 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.DLDeque.h"
Index: trunk/src/emx/include/Attic/cpp/gen/DLDeque.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/DLDeque.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/DLDeque.hP	(revision 18)
@@ -0,0 +1,130 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>DLDeque_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>DLDeque_h
+
+#include "<T>.DLList.h"
+#include "<T>.Deque.h"
+
+class <T>DLDeque : public <T>Deque
+{
+  <T>DLList    p;
+
+public:
+               <T>DLDeque();
+               <T>DLDeque(const <T>DLDeque& d);
+  inline              ~<T>DLDeque();
+
+  void          operator = (const <T>DLDeque&);
+
+  inline void          push(<T&> item); // insert at front
+  inline void          enq(<T&> item);  // insert at rear
+
+  inline <T>&          front();
+  inline <T>&          rear();
+
+  inline <T>           deq();
+  inline void          del_front();
+  inline void          del_rear();               
+
+  inline void          clear();
+  inline int           empty();
+  inline int           full();
+  inline int           length();
+               
+  inline int           OK();
+};
+
+
+inline <T>DLDeque::<T>DLDeque() : p() {}
+inline <T>DLDeque::<T>DLDeque(const <T>DLDeque& d) : p(d.p) {}
+
+inline <T>DLDeque::~<T>DLDeque() {}
+
+inline void <T>DLDeque::push(<T&>item)
+{
+  p.prepend(item);
+}
+
+inline void <T>DLDeque::enq(<T&>item)
+{
+  p.append(item);
+}
+
+inline <T> <T>DLDeque::deq()
+{
+  return p.remove_front();
+}
+
+inline <T>& <T>DLDeque::front()
+{
+  return p.front();
+}
+
+inline <T>& <T>DLDeque::rear()
+{
+  return p.rear();
+}
+
+inline void <T>DLDeque::del_front()
+{
+  p.del_front();
+}
+
+inline void <T>DLDeque::del_rear()
+{
+  p.del_rear();
+}
+
+inline void <T>DLDeque::operator =(const <T>DLDeque& s)
+{
+  p.operator = (s.p);
+}
+
+
+inline int <T>DLDeque::empty()
+{
+  return p.empty();
+}
+
+inline int <T>DLDeque::full()
+{
+  return 0;
+}
+
+inline int <T>DLDeque::length()
+{
+  return p.length();
+}
+
+inline int <T>DLDeque::OK()
+{
+  return p.OK();
+}
+
+inline void <T>DLDeque::clear()
+{
+  p.clear();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/DLList.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/DLList.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/DLList.ccP	(revision 18)
@@ -0,0 +1,339 @@
+// This may look like C code, but it is really -*- C++ -*-
+// WARNING: This file is obsolete.  Use ../DLList.cc, if you can.
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <limits.h>
+#include <stream.h>
+#include <builtin.h>
+#include "<T>.DLList.h"
+
+// error handling
+
+
+
+void <T>DLList::error(const char* msg)
+{
+  (*lib_error_handler)("DLList", msg);
+}
+
+int <T>DLList::length()
+{
+  int l = 0;
+  <T>DLListNode* t = h;
+  if (t != 0) do { ++l; t = t->fd; } while (t != h);
+  return l;
+}
+
+<T>DLList::<T>DLList(const <T>DLList& a)
+{
+  if (a.h == 0)
+    h = 0;
+  else
+  {
+    <T>DLListNode* p = a.h;
+    <T>DLListNode* t = new <T>DLListNode(p->hd);
+    h = t;
+    p = p->fd;
+    while (p != a.h)
+    {
+      <T>DLListNode* n = new <T>DLListNode(p->hd);
+      t->fd = n;
+      n->bk = t;
+      t = n;
+        p = p->fd;
+    }
+    t->fd = h;
+    h->bk = t;
+    return;
+  }
+}
+
+<T>DLList& <T>DLList::operator = (const <T>DLList& a)
+{
+  if (h != a.h)
+  {
+    clear();
+    if (a.h != 0)
+    {
+      <T>DLListNode* p = a.h;
+      <T>DLListNode* t = new <T>DLListNode(p->hd);
+      h = t;
+      p = p->fd;
+      while (p != a.h)
+      {
+        <T>DLListNode* n = new <T>DLListNode(p->hd);
+        t->fd = n;
+        n->bk = t;
+        t = n;
+        p = p->fd;
+      }
+      t->fd = h;
+      h->bk = t;
+    }
+  }
+  return *this;
+}
+
+void <T>DLList::clear()
+{
+  if (h == 0)
+    return;
+
+  <T>DLListNode* p = h->fd;
+  h->fd = 0;
+  h = 0;
+
+  while (p != 0)
+  {
+    <T>DLListNode* nxt = p->fd;
+    delete(p);
+    p = nxt;
+  }
+}
+
+
+Pix <T>DLList::prepend(<T&> item)
+{
+  <T>DLListNode* t = new <T>DLListNode(item);
+  if (h == 0)
+    t->fd = t->bk = h = t;
+  else
+  {
+    t->fd = h;
+    t->bk = h->bk;
+    h->bk->fd = t;
+    h->bk = t;
+    h = t;
+  }
+  return Pix(t);
+}
+
+Pix <T>DLList::append(<T&> item)
+{
+  <T>DLListNode* t = new <T>DLListNode(item);
+  if (h == 0)
+    t->fd = t->bk = h = t;
+  else
+  {
+    t->bk = h->bk;
+    t->bk->fd = t;
+    t->fd = h;
+    h->bk = t;
+  }
+  return Pix(t);
+}
+
+Pix <T>DLList::ins_after(Pix p, <T&> item)
+{
+  if (p == 0) return prepend(item);
+  <T>DLListNode* u = (<T>DLListNode*) p;
+  <T>DLListNode* t = new <T>DLListNode(item, u, u->fd);
+  u->fd->bk = t;
+  u->fd = t;
+  return Pix(t);
+}
+
+Pix <T>DLList::ins_before(Pix p, <T&> item)
+{
+  if (p == 0) error("null Pix");
+  <T>DLListNode* u = (<T>DLListNode*) p;
+  <T>DLListNode* t = new <T>DLListNode(item, u->bk, u);
+  u->bk->fd = t;
+  u->bk = t;
+  if (u == h) h = t;
+  return Pix(t);
+}
+
+void <T>DLList::join(<T>DLList& b)
+{
+  <T>DLListNode* t = b.h;
+  b.h = 0;
+  if (h == 0)
+    h = t;
+  else if (t != 0)
+  {
+    <T>DLListNode* l = t->bk;
+    h->bk->fd = t;
+    t->bk = h->bk;
+    h->bk = l;
+    l->fd = h;
+  }
+}
+
+int <T>DLList::owns(Pix p)
+{
+  <T>DLListNode* t = h;
+  if (t != 0 && p != 0)
+  {
+    do
+    {
+      if (Pix(t) == p) return 1;
+      t = t->fd;
+    } while (t != h);
+  }
+  return 0;
+}
+
+void <T>DLList::del(Pix& p, int dir)
+{
+  if (p == 0) error("null Pix");
+  <T>DLListNode* t = (<T>DLListNode*) p;
+  if (t->fd == t)
+  {
+    h = 0;
+    p = 0;
+  }
+  else
+  {
+    if (dir < 0)
+    {
+      if (t == h)
+        p = 0;
+      else
+        p = Pix(t->bk);
+    }
+    else
+    {
+      if (t == h->bk)
+        p = 0;
+      else
+        p = Pix(t->fd);
+    }
+    t->bk->fd = t->fd;
+    t->fd->bk = t->bk;
+    if (t == h) h = t->fd;
+  }
+  delete t;
+}
+
+void <T>DLList::del_after(Pix& p)
+{
+  if (p == 0)
+  {
+    del_front();
+    return;
+  }
+
+  <T>DLListNode* b = (<T>DLListNode*) p;
+  <T>DLListNode* t = b->fd;
+
+  if (b == t)
+  {
+    h = 0;
+    p = 0;
+  }
+  else
+  {
+    t->bk->fd = t->fd;
+    t->fd->bk = t->bk;
+    if (t == h) h = t->fd;
+  }
+  delete t;
+}
+
+<T> <T>DLList::remove_front()
+{
+  if (h == 0)
+    error("remove_front of empty list");
+  <T>DLListNode* t = h;
+  <T> res = t->hd;
+  if (h->fd == h)
+    h = 0;
+  else
+  {
+    h->fd->bk = h->bk;
+    h->bk->fd = h->fd;
+    h = h->fd;
+  }
+  delete t;
+  return res;
+}
+
+
+void <T>DLList::del_front()
+{
+  if (h == 0)
+    error("del_front of empty list");
+  <T>DLListNode* t = h;
+  if (h->fd == h)
+    h = 0;
+  else
+  {
+    h->fd->bk = h->bk;
+    h->bk->fd = h->fd;
+    h = h->fd;
+  }
+  delete t;
+}
+
+<T> <T>DLList::remove_rear()
+{
+  if (h == 0)
+    error("remove_rear of empty list");
+  <T>DLListNode* t = h->bk;
+  <T> res = t->hd;
+  if (h->fd == h)
+    h = 0;
+  else
+  {
+    t->fd->bk = t->bk;
+    t->bk->fd = t->fd;
+  }
+  delete t;
+  return res;
+}
+
+
+void <T>DLList::del_rear()
+{
+  if (h == 0)
+    error("del_rear of empty list");
+  <T>DLListNode* t = h->bk;
+  if (h->fd == h)
+    h = 0;
+  else
+  {
+    t->fd->bk = t->bk;
+    t->bk->fd = t->fd;
+  }
+  delete t;
+}
+
+
+int <T>DLList::OK()
+{
+  int v = 1;
+  if (h != 0)
+  {
+    <T>DLListNode* t = h;
+    long count = LONG_MAX;      // Lots of chances to find h!
+    do
+    {
+      count--;
+      v &= t->bk->fd == t;
+      v &= t->fd->bk == t;
+      t = t->fd;
+    } while (v && count > 0 && t != h);
+    v &= count > 0;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/DLList.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/DLList.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/DLList.hP	(revision 18)
@@ -0,0 +1,157 @@
+// This may look like C code, but it is really -*- C++ -*-
+// WARNING: This file is obsolete.  Use ../DLList.h, if you can.
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>DLList_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>DLList_h 1
+
+#include <Pix.h>
+#include "<T>.defs.h"
+
+#ifndef _<T>DLListNode_h
+#define _<T>DLListNode_h 1
+
+struct <T>DLListNode
+{
+  <T>DLListNode*         bk;
+  <T>DLListNode*         fd;
+  <T>                    hd;
+                         <T>DLListNode();
+                         <T>DLListNode(const <T&> h, 
+                                       <T>DLListNode* p = 0,
+                                       <T>DLListNode* n = 0);
+                         ~<T>DLListNode();
+};
+
+inline <T>DLListNode::<T>DLListNode() {}
+
+inline <T>DLListNode::<T>DLListNode(const <T&> h, <T>DLListNode* p,
+                                    <T>DLListNode* n)
+  :bk(p), fd(n), hd(h) {}
+
+inline <T>DLListNode::~<T>DLListNode() {}
+
+typedef <T>DLListNode* <T>DLListNodePtr;
+
+#endif
+
+class <T>DLList
+{
+  friend class          <T>DLListTrav;
+
+  <T>DLListNode*        h;
+
+public:
+                        <T>DLList();
+                        <T>DLList(const <T>DLList& a);
+                        ~<T>DLList();
+
+  <T>DLList&            operator = (const <T>DLList& a);
+
+  int                   empty();
+  int                   length();
+
+  void                  clear();
+
+  Pix                   prepend(<T&> item);
+  Pix                   append(<T&> item);
+  void                  join(<T>DLList&);
+
+  <T>&                  front();
+  <T>                   remove_front();
+  void                  del_front();
+
+  <T>&                  rear();
+  <T>                   remove_rear();
+  void                  del_rear();
+
+  <T>&                  operator () (Pix p);
+  Pix                   first();
+  Pix                   last();
+  void                  next(Pix& p);
+  void                  prev(Pix& p);
+  int                   owns(Pix p);
+  Pix                   ins_after(Pix p, <T&> item);
+  Pix                   ins_before(Pix p, <T&> item);
+  void                  del(Pix& p, int dir = 1);
+  void                  del_after(Pix& p);
+
+  void                  error(const char* msg);
+  int                   OK();
+};
+
+
+inline <T>DLList::~<T>DLList()
+{
+  clear();
+}
+
+inline <T>DLList::<T>DLList()
+{
+  h = 0;
+}
+
+inline int <T>DLList::empty()
+{
+  return h == 0;
+}
+
+
+inline void <T>DLList::next(Pix& p)
+{
+  p = (p == 0 || p == h->bk)? 0 : Pix(((<T>DLListNode*)p)->fd);
+}
+
+inline void <T>DLList::prev(Pix& p)
+{
+  p = (p == 0 || p == h)? 0 : Pix(((<T>DLListNode*)p)->bk);
+}
+
+inline Pix <T>DLList::first()
+{
+  return Pix(h);
+}
+
+inline Pix <T>DLList::last()
+{
+  return (h == 0)? 0 : Pix(h->bk);
+}
+
+inline <T>& <T>DLList::operator () (Pix p)
+{
+  if (p == 0) error("null Pix");
+  return ((<T>DLListNode*)p)->hd;
+}
+
+inline <T>& <T>DLList::front()
+{
+  if (h == 0) error("front: empty list");
+  return h->hd;
+}
+
+inline <T>& <T>DLList::rear()
+{
+  if (h == 0) error("rear: empty list");
+  return h->bk->hd;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/Deque.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Deque.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Deque.ccP	(revision 18)
@@ -0,0 +1,11 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.Deque.h"
+
+<T>Deque::~<T>Deque() {}
+
+void <T>Deque::error(const char* msg)
+{
+  (*lib_error_handler)("Deque", msg);
+}
Index: trunk/src/emx/include/Attic/cpp/gen/Deque.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Deque.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Deque.hP	(revision 18)
@@ -0,0 +1,57 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>Deque_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>Deque_h
+
+#include <builtin.h>
+
+#include "<T>.defs.h"
+
+class <T>Deque
+{
+public:
+                        <T>Deque() { }
+  virtual              ~<T>Deque();
+
+  virtual void          push(<T&> item) = 0; // insert at front
+  virtual void          enq(<T&> item) = 0;  // insert at rear
+
+  virtual <T>&          front() = 0;
+  virtual <T>&          rear() = 0;
+
+  virtual <T>           deq() = 0;
+  virtual void          del_front() = 0;
+  virtual void          del_rear() = 0;               
+
+  virtual int           empty() = 0;
+  virtual int           full() = 0;
+  virtual int           length() = 0;
+  virtual void          clear() = 0;
+  
+  virtual int           OK() = 0;
+
+  void                  error(const char*);
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/FPQueue.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/FPQueue.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/FPQueue.ccP	(revision 18)
@@ -0,0 +1,4 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.FPQueue.h"
Index: trunk/src/emx/include/Attic/cpp/gen/FPQueue.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/FPQueue.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/FPQueue.hP	(revision 18)
@@ -0,0 +1,112 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>FPQueue_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>FPQueue_h
+
+#include "<T>.FPlex.h"
+#include "<T>.Queue.h"
+
+class <T>FPQueue : public <T>Queue
+{
+  <T>FPlex     p;
+
+public:
+               <T>FPQueue(int chunksize = DEFAULT_INITIAL_CAPACITY);
+               <T>FPQueue(const <T>FPQueue& q);
+               ~<T>FPQueue();
+
+  void          operator = (const <T>FPQueue&);
+
+  void          enq(<T&> item);
+  <T>           deq();
+  <T>&          front();
+  void          del_front();
+
+  void          clear();
+  int           empty();
+  int           full();
+  int           length();
+               
+  int           OK();
+};
+
+inline <T>FPQueue::<T>FPQueue(int chunksize) : p(chunksize) {}
+inline <T>FPQueue::<T>FPQueue(const <T>FPQueue& q) : p(q.p) {}
+
+inline <T>FPQueue::~<T>FPQueue() {}
+
+inline void <T>FPQueue::enq(<T&>item)
+{
+  p.add_high(item);
+}
+
+inline <T> <T>FPQueue::deq()
+{
+  <T> res = p.low_element();
+  p.del_low();
+  return res;
+}
+
+inline <T>& <T>FPQueue::front()
+{
+  return p.low_element();
+}
+
+
+inline void <T>FPQueue::del_front()
+{
+  p.del_low();
+}
+
+inline void <T>FPQueue::operator =(const <T>FPQueue& s)
+{
+  p = s.p;
+}
+
+inline int <T>FPQueue::empty()
+{
+  return p.empty();
+}
+
+inline int <T>FPQueue::full()
+{
+  return p.full();
+}
+
+inline int <T>FPQueue::length()
+{
+  return p.length();
+}
+
+inline int <T>FPQueue::OK()
+{
+  return p.OK();
+}
+
+inline void <T>FPQueue::clear()
+{
+  p.clear();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/FPStack.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/FPStack.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/FPStack.ccP	(revision 18)
@@ -0,0 +1,4 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.FPStack.h"
Index: trunk/src/emx/include/Attic/cpp/gen/FPStack.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/FPStack.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/FPStack.hP	(revision 18)
@@ -0,0 +1,114 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>FPStack_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>FPStack_h
+
+#include "<T>.FPlex.h"
+#include "<T>.Stack.h"
+
+class <T>FPStack : public <T>Stack
+{
+  <T>FPlex      p;
+
+public:
+                <T>FPStack(int chunksize = DEFAULT_INITIAL_CAPACITY);
+                <T>FPStack(const <T>FPStack& s);
+                ~<T>FPStack();
+
+  void          operator = (const <T>FPStack&);
+
+  void          push(<T&> item);
+  <T>           pop();
+  <T>&          top();               
+  void          del_top();
+
+  int           empty();
+  int           full();
+  int           length();
+
+  void          clear();
+
+  int           OK();
+
+};
+
+
+inline <T>FPStack::<T>FPStack(int chunksize) : p(chunksize) {}
+inline <T>FPStack::<T>FPStack(const <T>FPStack& s) : p(s.p) {}
+
+inline <T>FPStack::~<T>FPStack() {}
+
+inline void <T>FPStack::push(<T&>item)
+{
+  p.add_high(item);
+}
+
+inline <T> <T>FPStack::pop()
+{
+  <T> res = p.high_element();
+  p.del_high();
+  return res;
+}
+
+inline <T>& <T>FPStack::top()
+{
+  return p.high_element();
+}
+
+inline void <T>FPStack::del_top()
+{
+  p.del_high();
+}
+
+inline void <T>FPStack::operator =(const <T>FPStack& s)
+{
+  p = s.p;
+}
+
+inline int <T>FPStack::empty() 
+{
+  return p.empty();
+}
+
+inline int <T>FPStack::full() 
+{
+  return p.full();
+}
+
+inline int <T>FPStack::length() 
+{
+  return p.length();
+}
+
+inline int <T>FPStack::OK() 
+{
+  return p.OK();
+}
+
+inline void <T>FPStack::clear() 
+{
+  p.clear();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/FPlex.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/FPlex.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/FPlex.ccP	(revision 18)
@@ -0,0 +1,167 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.FPlex.h"
+
+
+<T>FPlex:: <T>FPlex()
+{
+  lo = fnc = 0;
+  csize = DEFAULT_INITIAL_CAPACITY;
+  <T>* data = new <T>[csize];
+  hd = new <T>IChunk(data,  lo, lo, fnc, csize);
+}
+
+<T>FPlex:: <T>FPlex(int maxsize)
+{
+  if (maxsize == 0) error("invalid constructor specification");
+  lo = fnc = 0;
+  if (maxsize > 0)
+  {
+    csize = maxsize;
+    <T>* data = new <T>[csize];
+    hd = new <T>IChunk(data,  lo, lo, fnc, csize);
+  }
+  else
+  {
+    csize = -maxsize;
+    <T>* data = new <T>[csize];
+    hd = new <T>IChunk(data,  maxsize, lo, fnc, fnc);
+  }
+}
+
+
+<T>FPlex:: <T>FPlex(int l, int maxsize)
+{
+  if (maxsize == 0) error("invalid constructor specification");
+  lo = fnc = l;
+  if (maxsize > 0)
+  {
+    csize = maxsize;
+    <T>* data = new <T>[csize];
+    hd = new <T>IChunk(data,  lo, lo, fnc, csize+lo);
+  }
+  else
+  {
+    csize = -maxsize;
+    <T>* data = new <T>[csize];
+    hd = new <T>IChunk(data,  maxsize+lo, lo, fnc, fnc);
+  }
+}
+
+<T>FPlex:: <T>FPlex(int l, int hi, const <T&> initval, int maxsize)
+{
+  lo = l;
+  fnc = hi + 1;
+  if (maxsize >= 0)
+  {
+    csize = maxsize;
+    if (csize < fnc - lo)
+      csize = fnc - lo;
+    <T>* data = new <T>[csize];
+    hd = new <T>IChunk(data,  lo, lo, fnc, csize);
+  }
+  else
+  {
+    csize = -maxsize;
+    if (csize < fnc - lo)
+      csize = fnc - lo;
+    <T>* data = new <T>[csize];
+    hd = new <T>IChunk(data,  -csize, lo, fnc, fnc);
+  }
+  fill(initval);
+}
+
+<T>FPlex::<T>FPlex(const <T>FPlex& a)
+{
+  lo = a.lo;
+  fnc = a.fnc;
+  csize = fnc - lo;
+  if (csize < a.csize) csize = a.csize;
+  <T>* data = new <T> [csize];
+  hd = new <T>IChunk(data,  lo, lo, fnc, lo+csize);
+  for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
+}
+
+void <T>FPlex::operator= (const <T>FPlex& a)
+{
+  if (&a != this)
+  {
+    del_chunk(hd);
+    lo = a.lo;
+    fnc = a.fnc;
+    csize = fnc - lo;
+    if (csize < a.csize) csize = a.csize;
+    <T>* data = new <T> [csize];
+    hd = new <T>IChunk(data,  lo, lo, fnc, lo+csize);
+    for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
+  }
+}
+
+
+void <T>FPlex::reverse()
+{
+  <T> tmp;
+  int l = lo;
+  int h = fnc - 1;
+  while (l < h)
+  {
+    tmp = (*this)[l];
+    (*this)[l] = (*this)[h];
+    (*this)[h] = tmp;
+    next(l);
+    prev(h);
+  }
+}
+
+void <T>FPlex::fill(const <T&> x)
+{
+  for (int i = lo; i < fnc; ++i) (*this)[i] = x;
+}
+
+void <T>FPlex::fill(const <T&> x, int lo, int hi)
+{
+  for (int i = lo; i <= hi; ++i) (*this)[i] = x;
+}
+
+void <T>FPlex::clear()
+{
+  if (fnc != lo)
+  {
+    hd->clear(lo);
+    fnc = lo;
+  }
+}
+
+int <T>FPlex::OK () const
+{
+  int v = hd != 0;                    // hd exists
+  v &= hd-><T>IChunk::OK();           // and is OK
+  v &= fnc - lo <= hd->size();        // and has enough space
+  v &= lo <= fnc;                     // plex indices consistent
+  v &= lo == hd->low_index();         // and match those 
+  v &= fnc == hd->fence_index();      //   of chunk
+  v &= one_chunk();                   // and only one chunk
+  if (!v) error("invariant failure");
+  return v;
+}
+
Index: trunk/src/emx/include/Attic/cpp/gen/FPlex.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/FPlex.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/FPlex.hP	(revision 18)
@@ -0,0 +1,253 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>FPlex_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>FPlex_h 1
+
+#include "<T>.Plex.h"
+
+class <T>FPlex : public <T>Plex
+{
+public:
+                   <T>FPlex();                 // set low = 0;
+                                               // fence = 0;
+                                               // csize = default
+
+                   <T>FPlex(int maxsize);      // low = 0; 
+                                               // fence = 0;
+                                               // csize = maxsize
+
+                   <T>FPlex(int lo,            // low = lo; 
+                            int maxsize);      // fence=lo
+                                               // csize = maxsize
+
+                   <T>FPlex(int lo,            // low = lo
+                            int hi,            // fence = hi+1
+                            const <T&> initval,// fill with initval,
+                            int maxsize = 0);  // csize = maxsize
+                                               // or fence - lo if 0
+
+                   <T>FPlex(const <T>FPlex&);   // X(X&)
+
+  inline                  ~<T>FPlex();
+
+  void             operator= (const <T>FPlex&);
+
+// virtuals
+
+  inline <T>&             high_element ();
+  inline <T>&             low_element ();
+
+  inline const <T>&       high_element () const;
+  inline const <T>&       low_element () const;
+
+  inline Pix              first() const;
+  inline Pix              last() const;
+  inline void             prev(Pix& ptr) const;
+  inline void             next(Pix& ptr) const;
+  inline int              owns(Pix p) const;
+  inline <T>&             operator () (Pix p);
+  inline const <T>&       operator () (Pix p) const;
+
+  inline int              low() const; 
+  inline int              high() const;
+  inline int              valid(int idx) const;
+  inline void             prev(int& idx) const;
+  inline void             next(int& x) const;
+  inline <T>&             operator [] (int index);
+  inline const <T>&       operator [] (int index) const;
+    
+  inline int              Pix_to_index(Pix p) const;
+  inline Pix              index_to_Pix(int idx) const;    
+
+  inline int              can_add_high() const;
+  inline int              can_add_low() const;
+  inline int              full() const;
+
+  inline int              add_high(const <T&> elem);
+  inline int              del_high ();
+  inline int              add_low (const <T&> elem);
+  inline int              del_low ();
+
+  void             fill(const <T&> x);
+  void             fill(const <T&> x, int from, int to);
+  void             clear();
+  void             reverse();
+
+  int              OK () const; 
+};
+
+
+inline  int <T>FPlex::valid (int idx) const
+{
+  return idx >= lo && idx < fnc;
+}
+
+inline int <T>FPlex::low() const
+{
+  return lo;
+}
+
+inline int <T>FPlex::high() const
+{
+  return fnc - 1;
+}
+
+inline Pix  <T>FPlex::first() const
+{
+  return (Pix)(hd-><T>IChunk::first_pointer());
+}
+
+inline void  <T>FPlex::prev(Pix&  p) const
+{
+  p = Pix(hd-><T>IChunk::pred((<T>*) p));
+}
+
+inline void  <T>FPlex::next(Pix&  p) const
+{
+  p =  Pix(hd-><T>IChunk::succ((<T>*) p));
+}
+
+inline Pix <T>FPlex::last() const
+{
+  return Pix(hd-><T>IChunk::last_pointer());
+}
+
+inline  int <T>FPlex::full () const
+{
+  return fnc - lo == csize;
+}
+
+inline void <T>FPlex::prev(int& idx) const
+{
+  --idx;
+}
+
+inline void <T>FPlex::next(int& idx) const
+{
+  ++idx;
+}
+
+inline <T>& <T>FPlex:: operator [] (int idx)
+{
+  if (idx < lo || idx >= fnc) index_error();
+  return *(hd->pointer_to(idx));
+}
+
+inline <T>& <T>FPlex:: operator () (Pix p)
+{
+  return *((<T>*)p);
+}
+
+inline  <T>& <T>FPlex::low_element ()
+{
+  if (empty()) index_error();
+  return *(hd->pointer_to(lo));
+}
+
+inline  <T>& <T>FPlex::high_element ()
+{
+  if (empty()) index_error();
+  return *(hd->pointer_to(fnc - 1));
+}
+
+inline const <T>& <T>FPlex:: operator [] (int idx) const
+{
+  if (idx < lo || idx >= fnc) index_error();
+  return *(hd->pointer_to(idx));
+}
+
+inline const <T>& <T>FPlex:: operator () (Pix p) const
+{
+  return *((const <T>*)p);
+}
+
+inline const <T>& <T>FPlex::low_element () const
+{
+  if (empty()) index_error();
+  return *(hd->pointer_to(lo));
+}
+
+inline const  <T>& <T>FPlex::high_element () const
+{
+  if (empty()) index_error();
+  return *(hd->pointer_to(fnc - 1));
+}
+
+inline int <T>FPlex::can_add_high() const
+{
+  return hd->can_grow_high();
+}
+
+inline int <T>FPlex::can_add_low() const
+{
+  return hd->can_grow_low();
+}
+
+inline int <T>FPlex::add_high(const <T&> elem)
+{
+  if (!can_add_high()) full_error();
+  *((hd-><T>IChunk::grow_high())) = elem;
+  return fnc++;
+}
+
+inline  int <T>FPlex::del_high ()
+{
+  if (empty()) empty_error();
+  hd-><T>IChunk::shrink_high();
+  return --fnc - 1;
+}
+
+inline  int <T>FPlex::add_low (const <T&> elem)
+{
+  if (!can_add_low()) full_error();
+  *((hd-><T>IChunk::grow_low())) = elem;
+  return --lo;
+}
+
+inline  int <T>FPlex::del_low ()
+{
+  if (empty()) empty_error();
+  hd-><T>IChunk::shrink_low();
+  return ++lo;
+}
+
+inline  int <T>FPlex::owns (Pix p) const
+{
+  return hd->actual_pointer((<T>*)p);
+}
+
+inline  int <T>FPlex::Pix_to_index(Pix p) const
+{
+  if (!hd->actual_pointer((const <T>*)p)) index_error();
+  return hd->index_of((const <T>*)p);
+}
+
+inline  Pix <T>FPlex::index_to_Pix(int idx) const
+{
+  if (idx < lo || idx >= fnc) index_error();
+  return Pix(hd->pointer_to(idx));
+}
+
+inline <T>FPlex::~<T>FPlex() {}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/List.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/List.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/List.ccP	(revision 18)
@@ -0,0 +1,972 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <builtin.h>
+#include "<T>.List.h"
+
+<T>ListNode Nil<T>ListNode;
+
+class init_Nil<T>ListNode
+{
+public:
+  init_Nil<T>ListNode() 
+  {
+    Nil<T>ListNode.tl = &Nil<T>ListNode;
+    Nil<T>ListNode.ref = -1;
+  }
+};
+
+static init_Nil<T>ListNode Nil<T>ListNode_initializer;
+
+<T>List& <T>List::operator = (const <T>List& a)
+{
+  reference(a.P);
+  dereference(P);
+  P = a.P;
+  return *this;
+}
+
+<T> <T>List::pop()
+{
+  <T> res = P->hd;
+  <T>ListNode* tail = P->tl;
+  reference(tail);
+  dereference(P);
+  P = tail;
+  return res;
+}
+
+void <T>List::set_tail(<T>List& a)
+{
+  reference(a.P);
+  dereference(P->tl);
+  P->tl = a.P;
+}
+
+<T>List <T>List::nth(int n)
+{
+  <T>ListNode* p;
+  for ( p = P; n-- > 0; p = p->tl);
+  reference(p);
+  return <T>List(p);
+}
+
+<T>List <T>List::last()
+{
+  <T>ListNode* p = P;
+  if (p != &Nil<T>ListNode) while (p->tl != &Nil<T>ListNode) p = p->tl;
+  reference(p);
+  return <T>List(p);
+}
+
+void <T>List::append(<T>List& l)
+{
+  <T>ListNode* p = P;
+  <T>ListNode* a = l.P;
+  reference(a);
+  if (p != &Nil<T>ListNode)
+  {
+    while (p->tl != &Nil<T>ListNode) p = p->tl;
+    p->tl = a;
+  }
+  else
+    P = a;
+}
+
+int <T>List::length()
+{
+  int l = 0;
+  for (<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl) ++l;
+  return l;
+}
+
+<T>&  <T>List::operator [] (int n)
+{
+  <T>ListNode* p;
+  for ( p = P; n-- > 0; p = p->tl);
+  return (p->hd);
+}
+
+int operator == (const <T>List& x, const <T>List& y)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* b = y.P;
+  
+  for (;;)
+  {
+    if (a == &Nil<T>ListNode)
+      return b == &Nil<T>ListNode;
+    else if (b == &Nil<T>ListNode)
+      return 0;
+    else if (<T>EQ(a->hd, b->hd))
+    {
+      a = a->tl;
+      b = b->tl;
+    }
+    else
+      return 0;
+  }
+}
+
+
+void <T>List::apply(<T>Procedure f)
+{
+  for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl)
+    (*f)((p->hd));
+}
+
+void <T>List::subst(<T&> old, <T&> repl)
+{
+  for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl)
+    if (<T>EQ(p->hd, old))
+      p->hd = repl;
+}
+
+<T> <T>List::reduce(<T>Combiner f, <T&> base)
+{
+  <T> r = base;
+  for(<T>ListNode* p = P; p != &Nil<T>ListNode; p = p->tl)
+    r = (*f)(r, (p->hd));
+  return r;
+}
+
+int <T>List::position(<T&> targ)
+{
+  int l = 0;
+  <T>ListNode* p = P;
+  for (;;)
+  {
+    if (p == &Nil<T>ListNode)
+      return -1;
+    else if (<T>EQ(p->hd, targ))
+      return l;
+    else
+    {
+      ++l;
+      p = p->tl;
+    }
+  }
+}
+
+int <T>List::contains(<T&> targ)
+{
+  <T>ListNode* p = P;
+  for (;;)
+  {
+    if (p == &Nil<T>ListNode)
+      return 0;
+    else if (<T>EQ(p->hd, targ))
+      return 1;
+    else
+      p = p->tl;
+  }
+}
+
+<T>List <T>List::find(<T&> targ)
+{
+  <T>ListNode* p = P;
+  while (p != &Nil<T>ListNode && !<T>EQ(p->hd, targ))
+    p=p->tl;
+  reference(p);
+  return <T>List(p);
+}
+
+Pix <T>List::seek(<T&> targ) const
+{
+  const <T>ListNode* p = P; 
+  for (;;)
+  {
+    if (p == &Nil<T>ListNode)
+      return 0;
+    else if (<T>EQ(p->hd, targ))
+      return Pix(p);
+    else
+      p = p->tl;
+  }
+}
+
+int <T>List::owns(Pix i)
+{
+  <T>ListNode* p = P; 
+  for (;;)
+  {
+    if (p == &Nil<T>ListNode)
+      return 0;
+    else if (Pix(p) == i)
+      return 1;
+    else
+      p = p->tl;
+  }
+}
+
+<T>List <T>List::find(<T>List& target)
+{
+  <T>ListNode* targ = target.P;
+  if (targ == &Nil<T>ListNode)
+    return <T>List(targ);
+
+  <T>ListNode* p = P;
+  while (p != &Nil<T>ListNode)
+  {
+    if (<T>EQ(p->hd, targ->hd))
+    {
+      <T>ListNode* a = p->tl;
+      <T>ListNode* t = targ->tl;
+      for(;;)
+      {
+        if (t == &Nil<T>ListNode)
+        {
+          reference(p);
+          return <T>List(p);
+        }
+        else if (a == &Nil<T>ListNode || !<T>EQ(a->hd, t->hd))
+          break;
+        else
+        {
+          a = a->tl;
+          t = t->tl;
+        }
+      }
+    }
+    p = p->tl;
+  }
+  return <T>List(&Nil<T>ListNode);
+}
+
+int <T>List::contains(<T>List& target)
+{
+  <T>ListNode* targ = target.P;
+  if (targ == &Nil<T>ListNode)
+    return 0;
+
+  <T>ListNode* p = P;
+  while (p != &Nil<T>ListNode)
+  {
+    if (<T>EQ(p->hd, targ->hd))
+    {
+      <T>ListNode* a = p->tl;
+      <T>ListNode* t = targ->tl;
+      for(;;)
+      {
+        if (t == &Nil<T>ListNode)
+          return 1;
+        else if (a == &Nil<T>ListNode || !<T>EQ(a->hd, t->hd))
+          break;
+        else
+        {
+          a = a->tl;
+          t = t->tl;
+        }
+      }
+    }
+    p = p->tl;
+  }
+  return 0;
+}
+
+void <T>List::del(<T&> targ)
+{
+  <T>ListNode* h = P;
+  // Former bug: targ can be a reference to a element in this list
+  // So do not dereference a element if targ is the element,
+  // until targ is no longer needed, as dereferencing it may destroy it.
+  <T>ListNode* to_be_dereferenced = 0;
+
+  for (;;)
+  {
+    if (h == &Nil<T>ListNode)
+    {
+      P = h;
+      if (to_be_dereferenced)
+	dereference(to_be_dereferenced);
+      return;
+    }
+    else if (<T>EQ(h->hd, targ))
+    {
+      <T>ListNode* nxt = h->tl;
+      reference(nxt);
+      if ((&targ == &h->hd) && (to_be_dereferenced == 0))
+	to_be_dereferenced = h;
+      else
+        dereference(h);
+      h = nxt;
+    }
+    else
+      break;
+  }
+
+  <T>ListNode* trail = h;
+  <T>ListNode* p = h->tl;
+  while (p != &Nil<T>ListNode)
+  {
+    if (<T>EQ(p->hd, targ))
+    {
+      <T>ListNode* nxt = p->tl;
+      reference(nxt);
+      if ((&targ == &p->hd) && (to_be_dereferenced == 0))
+	to_be_dereferenced = p;
+      else
+        dereference(p);
+      trail->tl = nxt;
+      p = nxt;
+    }
+    else
+    {
+      trail = p;
+      p = p->tl;
+    }
+  }
+  P = h;
+  if (to_be_dereferenced)
+    dereference(to_be_dereferenced);
+}
+
+void <T>List::del(<T>Predicate f)
+{
+  <T>ListNode* h = P;
+  for (;;)
+  {
+    if (h == &Nil<T>ListNode)
+    {
+      P = h;
+      return;
+    }
+    else if ((*f)(h->hd))
+    {
+      <T>ListNode* nxt = h->tl;
+      reference(nxt);
+      dereference(h);
+      h = nxt;
+    }
+    else
+      break;
+  }
+
+  <T>ListNode* trail = h;
+  <T>ListNode* p = h->tl;
+  while (p != &Nil<T>ListNode)
+  {
+    if ((*f)(p->hd))
+    {
+      <T>ListNode* nxt = p->tl;
+      reference(nxt);
+      dereference(p);
+      trail->tl = nxt;
+      p = nxt;
+    }
+    else
+    {
+      trail = p;
+      p = p->tl;
+    }
+  }
+  P = h;
+}
+
+void <T>List::select(<T>Predicate f)
+{
+  <T>ListNode* h = P;
+  for (;;)
+  {
+    if (h == &Nil<T>ListNode)
+    {
+      P = h;
+      return;
+    }
+    else if (!(*f)(h->hd))
+    {
+      <T>ListNode* nxt = h->tl;
+      reference(nxt);
+      dereference(h);
+      h = nxt;
+    }
+    else
+      break;
+  }
+  <T>ListNode* trail = h;
+  <T>ListNode* p = h->tl;
+  while (p != &Nil<T>ListNode)
+  {
+    if (!(*f)(p->hd))
+    {
+      <T>ListNode* nxt = p->tl;
+      reference(nxt);
+      dereference(p);
+      trail->tl = nxt;
+      p = nxt;
+    }
+    else
+    {
+      trail = p;
+      p = p->tl;
+    }
+  }
+  P = h;
+}
+
+void <T>List::reverse()
+{
+  <T>ListNode* l = &Nil<T>ListNode;
+  <T>ListNode* p = P; 
+  while (p != &Nil<T>ListNode)
+  {
+    <T>ListNode* nxt = p->tl;
+    p->tl = l;
+    l = p;
+    p = nxt;
+  }
+  P = l;
+}
+
+
+<T>List copy(const <T>List& x)
+{
+  const <T>ListNode* a = x.P;
+  if (a == &Nil<T>ListNode)
+    return <T>List(&Nil<T>ListNode);
+  else
+  {
+    <T>ListNode* h = new<T>ListNode(a->hd);
+    <T>ListNode* trail = h;
+    for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+    {
+      <T>ListNode* n = new<T>ListNode(a->hd);
+      trail->tl = n;
+      trail = n;
+    }
+    trail->tl = &Nil<T>ListNode;
+    return <T>List(h);
+  }
+}
+
+
+<T>List subst(<T&> old, <T&> repl, <T>List& x)
+{
+  <T>ListNode* a = x.P;
+  if (a == &Nil<T>ListNode)
+    return <T>List(a);
+  else
+  {
+    <T>ListNode* h = new <T>ListNode;
+    h->ref = 1;
+    if (<T>EQ(a->hd, old))
+      h->hd = repl;
+    else
+      h->hd = a->hd;
+    <T>ListNode* trail = h;
+    for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+    {
+      <T>ListNode* n = new <T>ListNode;
+      n->ref = 1;
+      if (<T>EQ(a->hd, old))
+        n->hd = repl;
+      else
+        n->hd = a->hd;
+      trail->tl = n;
+      trail = n;
+    }
+    trail->tl = &Nil<T>ListNode;
+    return <T>List(h);
+  }
+}
+
+<T>List combine(<T>Combiner f, <T>List& x, <T>List& y)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* b = y.P;
+  if (a == &Nil<T>ListNode || b == &Nil<T>ListNode)
+    return <T>List(&Nil<T>ListNode);
+  else
+  {
+    <T>ListNode* h = new<T>ListNode((*f)(a->hd, b->hd));
+    <T>ListNode* trail = h;
+    a = a->tl;
+    b = b->tl;
+    while (a != &Nil<T>ListNode && b != &Nil<T>ListNode)
+    {
+      <T>ListNode* n = new<T>ListNode((*f)(a->hd, b->hd));
+      trail->tl = n;
+      trail = n;
+      a = a->tl;
+      b = b->tl;
+    }
+    trail->tl = &Nil<T>ListNode;
+    return <T>List(h);
+  }
+}
+
+<T>List reverse(<T>List& x)
+{
+  <T>ListNode* a = x.P;
+  if (a == &Nil<T>ListNode)
+    return <T>List(a);
+  else
+  {
+    <T>ListNode* l = new<T>ListNode(a->hd);
+    l->tl = &Nil<T>ListNode;
+    for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+    {
+      <T>ListNode* n = new<T>ListNode(a->hd);
+      n->tl = l;
+      l = n;
+    }
+    return <T>List(l);
+  }
+}
+
+<T>List append(<T>List& x, <T>List& y)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* b = y.P;
+  reference(b);
+  if (a != &Nil<T>ListNode)
+  {
+    <T>ListNode* h = new<T>ListNode(a->hd);
+    <T>ListNode* trail = h;
+    for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+    {
+      <T>ListNode* n = new<T>ListNode(a->hd);
+      trail->tl = n;
+      trail = n;
+    }
+    trail->tl = b;
+    return <T>List(h);
+  }
+  else
+    return <T>List(b);
+}
+
+void <T>List::prepend(<T>List& y)
+{
+  <T>ListNode* b = y.P;
+  if (b != &Nil<T>ListNode)
+  {
+    <T>ListNode* h = new<T>ListNode(b->hd);
+    <T>ListNode* trail = h;
+    for(b = b->tl; b != &Nil<T>ListNode; b = b->tl)
+    {
+      <T>ListNode* n = new<T>ListNode(b->hd);
+      trail->tl = n;
+      trail = n;
+    }
+    trail->tl = P;
+    P = h;
+  }
+}
+
+<T>List concat(<T>List& x, <T>List& y)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* b = y.P;
+  if (a != &Nil<T>ListNode)
+  {
+    <T>ListNode* h = new<T>ListNode(a->hd);
+    <T>ListNode* trail = h;
+    for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+    {
+      <T>ListNode* n = new<T>ListNode(a->hd);
+      trail->tl = n;
+      trail = n;
+    };
+    for(;b != &Nil<T>ListNode; b = b->tl)
+    {
+      <T>ListNode* n = new<T>ListNode(b->hd);
+      trail->tl = n;
+      trail = n;
+    }
+    trail->tl = &Nil<T>ListNode;
+    return <T>List(h);
+  }
+  else if (b != &Nil<T>ListNode)
+  {
+    <T>ListNode* h = new<T>ListNode(b->hd);
+    <T>ListNode* trail = h;
+    for(b = b->tl; b != &Nil<T>ListNode; b = b->tl)
+    {
+      <T>ListNode* n = new<T>ListNode(b->hd);
+      trail->tl = n;
+      trail = n;
+    }
+    trail->tl = &Nil<T>ListNode;
+    return <T>List(h);
+  }
+  else
+    return <T>List(&Nil<T>ListNode);
+}
+
+<T>List select(<T>Predicate f, <T>List& x)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* h = &Nil<T>ListNode;
+  while (a != &Nil<T>ListNode)
+  {
+    if ((*f)(a->hd))
+    {
+      h = new<T>ListNode(a->hd);
+      <T>ListNode* trail = h;
+      for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+      {
+        if ((*f)(a->hd))
+        {
+          <T>ListNode* n = new<T>ListNode(a->hd);
+          trail->tl = n;
+          trail = n;
+        }
+      }
+      trail->tl = &Nil<T>ListNode;
+      break;
+    }
+    else
+      a = a->tl;
+  }
+  return <T>List(h);
+}
+
+<T>List remove(<T>Predicate f, <T>List& x)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* h = &Nil<T>ListNode;
+  while (a != &Nil<T>ListNode)
+  {
+    if (!(*f)(a->hd))
+    {
+      h = new<T>ListNode(a->hd);
+      <T>ListNode* trail = h;
+      for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+      {
+        if (!(*f)(a->hd))
+        {
+          <T>ListNode* n = new<T>ListNode(a->hd);
+          trail->tl = n;
+          trail = n;
+        }
+      }
+      trail->tl = &Nil<T>ListNode;
+      break;
+    }
+    else
+      a = a->tl;
+  }
+  return <T>List(h);
+}
+
+<T>List remove(<T&> targ, <T>List& x)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* h = &Nil<T>ListNode;
+  while (a != &Nil<T>ListNode)
+  {
+    if (!(<T>EQ(a->hd, targ)))
+    {
+      h = new<T>ListNode(a->hd);
+      <T>ListNode* trail = h;
+      for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+      {
+        if (!<T>EQ(a->hd, targ))
+        {
+          <T>ListNode* n = new<T>ListNode(a->hd);
+          trail->tl = n;
+          trail = n;
+        }
+      }
+      trail->tl = &Nil<T>ListNode;
+      break;
+    }
+    else
+      a = a->tl;
+  }
+  return <T>List(h);
+}
+
+<T>List map(<T>Mapper f, <T>List& x)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* h = &Nil<T>ListNode;
+  if (a != &Nil<T>ListNode)
+  {
+    h = new<T>ListNode((*f)(a->hd));
+    <T>ListNode* trail = h;
+    for(a = a->tl; a != &Nil<T>ListNode; a = a->tl)
+    {
+      <T>ListNode* n = new<T>ListNode((*f)(a->hd));
+      trail->tl = n;
+      trail = n;
+    }
+    trail->tl = &Nil<T>ListNode;
+  }
+  return <T>List(h);
+}
+
+
+<T>List merge(<T>List& x, <T>List& y, <T>Comparator f)
+{
+  <T>ListNode* a = x.P;
+  <T>ListNode* b = y.P;
+
+  if (a == &Nil<T>ListNode)
+  {
+    if (b == &Nil<T>ListNode)
+      return <T>List(&Nil<T>ListNode);
+    else
+      return copy(y);
+  }
+  else if (b == &Nil<T>ListNode)
+    return copy(x);
+
+  <T>ListNode* h = new <T>ListNode;
+  h->ref = 1;
+  if ((*f)(a->hd, b->hd) <= 0)
+  {
+    h->hd = a->hd;
+    a = a->tl;
+  }
+  else
+  {
+    h->hd = b->hd;
+    b = b->tl;
+  }
+
+  <T>ListNode* r = h;
+
+  for(;;)
+  {
+    if (a == &Nil<T>ListNode)
+    {
+      while (b != &Nil<T>ListNode)
+      {
+        <T>ListNode* n = new <T>ListNode;
+        n->ref = 1;
+        n->hd = b->hd;
+        r->tl = n;
+        r = n;
+        b = b->tl;
+      }
+      r->tl = &Nil<T>ListNode;
+      return <T>List(h);
+    }
+    else if (b == &Nil<T>ListNode)
+    {
+      while (a != &Nil<T>ListNode)
+      {
+        <T>ListNode* n = new <T>ListNode;
+        n->ref = 1;
+        n->hd = a->hd;
+        r->tl = n;
+        r = n;
+        a = a->tl;
+      }
+      r->tl = &Nil<T>ListNode;
+      return <T>List(h);
+    }
+    else if ((*f)(a->hd, b->hd) <= 0)
+    {
+      <T>ListNode* n = new <T>ListNode;
+      n->ref = 1;
+      n->hd = a->hd;
+      r->tl = n;
+      r = n;
+      a = a->tl;
+    }
+    else
+    {
+      <T>ListNode* n = new <T>ListNode;
+      n->ref = 1;
+      n->hd = b->hd;
+      r->tl = n;
+      r = n;
+      b = b->tl;
+    }
+  }
+}
+
+void <T>List::sort(<T>Comparator f)
+{
+  // strategy: place runs in queue, merge runs until done
+  // This is often very fast
+
+  if (P == &Nil<T>ListNode || P->tl == &Nil<T>ListNode)
+    return;
+
+  int qlen = 250;   // guess a good queue size, realloc if necessary
+
+  <T>ListNode** queue = (<T>ListNode**)malloc(qlen * sizeof(<T>ListNode*));
+
+  <T>ListNode* h = P;
+  <T>ListNode* a = h;
+  <T>ListNode* b = a->tl;
+  int qin = 0;
+
+  while (b != &Nil<T>ListNode)
+  {
+    if ((*f)(a->hd, b->hd) > 0)
+    {
+      if (h == a)               // minor optimization: ensure runlen >= 2
+      {
+        h = b;
+        a->tl = b->tl;
+        b->tl = a;
+        b = a->tl;
+      }
+      else
+      {
+        if (qin >= qlen)
+        {
+          qlen *= 2;
+          queue = (<T>ListNode**)realloc(queue, qlen * sizeof(<T>ListNode*));
+        }
+        queue[qin++] = h;
+        a->tl = &Nil<T>ListNode;
+        h = a = b;
+        b = b->tl;
+      }
+    }
+    else
+    {
+      a = b;
+      b = b->tl;
+    }
+  }
+
+  int count = qin;
+  queue[qin] = h;
+  if (++qin >= qlen) qin = 0;
+  int qout = 0;
+
+  while (count-- > 0)
+  {
+    a = queue[qout];
+    if (++qout >= qlen) qout = 0;
+    b = queue[qout];
+    if (++qout >= qlen) qout = 0;
+
+    if ((*f)(a->hd, b->hd) <= 0)
+    {
+      h = a;
+      a = a->tl;
+    }
+    else
+    {
+      h = b;
+      b = b->tl;
+    }
+    queue[qin] = h;
+    if (++qin >= qlen) qin = 0;
+
+    for (;;)
+    {
+      if (a == &Nil<T>ListNode)
+      {
+        h->tl = b;
+        break;
+      }
+      else if (b == &Nil<T>ListNode)
+      {
+        h->tl = a;
+        break;
+      }
+      else if ((*f)(a->hd, b->hd) <= 0)
+      {
+        h->tl = a;
+        h = a;
+        a = a->tl;
+      }
+      else
+      {
+        h->tl = b;
+        h = b;
+        b = b->tl;
+      }
+    }
+  }
+  P = queue[qout];
+  free(queue);
+}
+    
+int <T>List::list_length()
+{
+  <T>ListNode* fast = P;
+  if (fast == &Nil<T>ListNode)
+    return 0;
+
+  <T>ListNode* slow = fast->tl;
+  if (slow == &Nil<T>ListNode)
+    return 1;
+
+  fast = slow->tl;
+  int n = 2;
+
+  for (;;)
+  {
+    if (fast == &Nil<T>ListNode)
+      return n;
+    else if (fast->tl == &Nil<T>ListNode)
+      return n+1;
+    else if (fast == slow)
+      return -1;
+    else
+    {
+      n += 2;
+      fast = fast->tl->tl;
+      slow = slow->tl;
+    }
+  }
+}
+
+void <T>List::error(const char* msg)
+{
+  (*lib_error_handler)("List", msg);
+}
+
+int <T>List::OK()
+{
+  int v = P != 0;               // have a node
+  // check that all nodes OK, even if circular:
+
+  <T>ListNode* fast = P;
+  if (fast != &Nil<T>ListNode)
+  {
+    v &= fast->ref != 0;
+    <T>ListNode* slow = fast->tl;
+    v &= slow->ref != 0;
+    if (v && slow != &Nil<T>ListNode)
+    {
+      fast = slow->tl;
+      v &= fast->ref != 0;
+      while (v)
+      {
+        if (fast == &Nil<T>ListNode)
+          break;
+        else if (fast->tl == &Nil<T>ListNode)
+          break;
+        else if (fast == slow)
+          break;
+        else
+        {
+          v &= fast->ref != 0 && slow->ref != 0;
+          fast = fast->tl->tl;
+          slow = slow->tl;
+        }
+      }
+    }
+  }
+  if (!v) error ("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/List.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/List.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/List.hP	(revision 18)
@@ -0,0 +1,279 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>List_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>List_h 1
+
+#include <Pix.h>
+#include "<T>.defs.h"
+
+#ifndef _<T>_typedefs
+#define _<T>_typedefs 1
+typedef void (*<T>Procedure)(<T&>);
+typedef <T>  (*<T>Mapper)(<T&>);
+typedef <T>  (*<T>Combiner)(<T&>, <T&>);
+typedef int  (*<T>Predicate)(<T&>);
+typedef int  (*<T>Comparator)(<T&>, <T&>);
+#endif
+
+struct <T>ListNode
+{
+  <T>ListNode*          tl;
+  short                 ref;
+  <T>                   hd;
+};
+
+extern <T>ListNode Nil<T>ListNode;
+
+class <T>List
+{
+protected:
+  <T>ListNode*          P;
+
+                        <T>List(<T>ListNode* p);
+public:
+                        <T>List();
+                        <T>List(<T&> head);
+                        <T>List(<T&> head, const <T>List& tl);
+                        <T>List(const <T>List& a);
+                        <T>List(Pix p);
+                        ~<T>List();
+
+  <T>List&              operator = (const <T>List& a);
+
+  int                   null();
+  int                   valid();
+                        operator const void* ();
+  int                   operator ! ();
+
+  int                   length();
+  int                   list_length();
+
+  <T>&                  get();
+  <T>&                  head();
+  <T>&                  operator [] (int n);
+
+  <T>List               nth(int n);
+  <T>List               tail();
+  <T>List               last();
+
+  <T>List               find(<T&> targ);
+  <T>List               find(<T>List& targ);
+  int                   contains(<T&> targ);
+  int                   contains(<T>List& targ);
+  int                   position(<T&> targ);
+
+  friend <T>List        copy(const <T>List& a);
+  friend <T>List        concat(<T>List& a, <T>List& b);
+  friend <T>List        append(<T>List& a, <T>List& b);
+  friend <T>List        map(<T>Mapper f, <T>List& a);
+  friend <T>List        merge(<T>List& a, <T>List& b, <T>Comparator f);
+  friend <T>List        combine(<T>Combiner f, <T>List& a, <T>List& b);
+  friend <T>List        reverse(<T>List& a);
+  friend <T>List        select(<T>Predicate f, <T>List& a);        
+#undef remove
+  friend <T>List        remove(<T&> targ, <T>List& a);
+  friend <T>List        remove(<T>Predicate f, <T>List& a);
+  friend <T>List        subst(<T&> old, <T&> repl, <T>List& a);
+
+  void                  push(<T&> x);
+  <T>                   pop();
+
+  void                  set_tail(<T>List& p);
+  void                  append(<T>List& p);
+  void                  prepend(<T>List& p);
+  void                  del(<T&> targ);
+  void                  del(<T>Predicate f);
+  void                  select(<T>Predicate f);
+  void                  subst(<T&> old, <T&> repl);
+  void                  reverse();
+  void                  sort(<T>Comparator f);
+
+  void                  apply(<T>Procedure f);
+  <T>                   reduce(<T>Combiner f, <T&> base);
+
+  friend int            operator == (const <T>List& a, const <T>List& b);
+  friend inline int     operator != (const <T>List& a, const <T>List& b);
+
+  Pix                   first();
+  void                  next(Pix& p);
+  Pix                   seek(<T&> item) const;
+  <T>&                  operator () (Pix p);
+  const <T>&            operator () (Pix p) const;
+  int                   owns(Pix p);
+
+  void                  error(const char*);
+  int                   OK();
+};
+
+
+inline void reference(<T>ListNode* p)
+{
+  if (p->ref >= 0) ++p->ref;
+}
+
+inline void dereference(<T>ListNode* p)
+{
+  while (p->ref > 0 && --p->ref == 0)
+  {
+    <T>ListNode* n = p->tl;
+    delete(p);
+    p = n;
+  }
+}
+
+
+inline <T>ListNode* new<T>ListNode(const <T&> h)
+{
+  <T>ListNode* p = new <T>ListNode;
+  p->ref = 1;
+  p->hd = h;
+  return p;
+}
+
+inline <T>ListNode* new<T>ListNode(<T&> h, <T>ListNode* t)
+{
+  <T>ListNode* p = new <T>ListNode;
+  p->ref = 1;
+  p->hd = h;
+  p->tl = t;
+  return p;
+}
+
+
+inline <T>List::~<T>List()
+{
+  dereference(P);
+}
+
+inline <T>List::<T>List()
+{
+  P = &Nil<T>ListNode;
+}
+
+inline <T>List::<T>List(<T>ListNode* p)
+{
+  P = p;
+}
+
+inline <T>List::<T>List(<T&> head)
+{
+  P = new<T>ListNode(head);
+  P->tl = &Nil<T>ListNode;
+}
+
+inline <T>List::<T>List(<T&> head, const <T>List& tl)
+{
+  P = new<T>ListNode(head, tl.P);
+  reference(P->tl);
+}
+
+inline <T>List::<T>List(const <T>List& a)
+{
+  reference(a.P);
+  P = a.P;
+}
+
+
+inline <T>& <T>List::get()
+{
+  return P->hd;
+}
+
+inline <T>& <T>List::head()
+{
+  return P->hd;
+}
+
+
+inline <T>List <T>List::tail()
+{
+  reference(P->tl);
+  return <T>List(P->tl);
+}
+
+
+
+inline int <T>List::null()
+{
+  return P == &Nil<T>ListNode;
+}
+
+inline int <T>List::valid()
+{
+  return P != &Nil<T>ListNode;
+}
+
+inline <T>List::operator const void* ()
+{
+  return (P == &Nil<T>ListNode)? 0 : this;
+}
+
+inline int <T>List::operator ! ()
+{
+  return (P == &Nil<T>ListNode);
+}
+
+
+inline void <T>List::push(<T&> head)
+{
+  <T>ListNode* oldp = P;
+  P = new<T>ListNode(head, oldp);
+}
+
+
+inline int operator != (const <T>List& x, const <T>List& y)
+{
+  return !(x == y);
+}
+
+inline Pix <T>List::first()
+{
+  return (P == &Nil<T>ListNode)? 0 : Pix(P);
+}
+
+inline <T>& <T>List::operator () (Pix p)
+{
+  return ((<T>ListNode*)p)->hd;
+}
+
+inline const <T>& <T>List::operator () (Pix p) const
+{
+  return ((const <T>ListNode*)p)->hd;
+}
+
+inline void <T>List::next(Pix& p)
+{
+  if (p != 0)
+  {
+    p = Pix(((<T>ListNode*)p)->tl);
+    if (p == &Nil<T>ListNode) p = 0;
+  }
+}
+
+inline <T>List::<T>List(Pix p)
+{
+  P = (<T>ListNode*)p;
+  reference(P);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/MPlex.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/MPlex.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/MPlex.ccP	(revision 18)
@@ -0,0 +1,848 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.MPlex.h"
+
+// <T>MChunk support
+
+
+<T>MChunk::<T>MChunk(<T>*    d,      
+               int      baseidx,
+               int      lowidx, 
+               int      fenceidx,
+               int      topidx)
+     : <T>IChunk(d, baseidx, lowidx, fenceidx, topidx)
+{
+  unused = fence - low;
+  unsigned msize = (top - base)/_MAP_BITS + 1;
+  map = (unsigned long *) (new long[msize]);
+  memset((void*)map, 0, msize * sizeof(long));
+}
+
+void <T>MChunk:: shrink_high ()
+{
+  if (fence <= low) empty_error();
+  --fence;
+  if (!valid(fence)) 
+    --unused;
+  else
+    free(fence);
+  reset_high();
+}
+
+void <T>MChunk:: shrink_low ()
+{
+  if (fence <= low) empty_error();
+  if (!valid(low)) 
+    --unused;
+  else
+    free(low);
+  ++low;
+  reset_low();
+}
+
+void <T>MChunk::clear(int lo)
+{
+  int s = top - base;
+  low = base = fence = lo;
+  top = base + s;
+  unused = 0;
+  memset((void*)map, 0, ((top - base)/_MAP_BITS + 1) * sizeof(long));
+}
+
+void <T>MChunk::cleardown(int hi)
+{
+  int s = top - base;
+  low = top = fence = hi;
+  base = top - s;
+  unused = 0;
+  memset((void*)map, 0, ((top - base)/_MAP_BITS + 1) * sizeof(long));
+}
+
+int <T>MChunk::del(int idx)
+{
+  if (idx < low || idx >= fence) index_error();
+  int v = valid(idx);
+  if (v)
+  {
+    free(idx);
+    ++unused;
+  }
+  return v;
+}
+
+
+int <T>MChunk::undel(int idx)
+{
+  if (idx < low || idx >= fence) index_error();
+  int v = valid(idx);
+  if (!v)
+  {
+    mark(idx);
+    --unused;
+  }
+  return v;
+}
+
+int <T>MChunk::unused_index() const
+{
+  if (unused_indices() == 0) index_error();
+  int slot;
+  if (low == base)              // can traverse 32 slots at a time
+  {
+    int blk = 0;
+    while (map[blk] == ~0UL) ++blk;
+    slot = blk * _MAP_BITS + base;
+  }
+  else
+    slot = low;
+
+  while(valid(slot)) ++slot;
+  return slot;
+}
+
+int <T>MChunk::first_index() const
+{
+  if (empty()) return fence;
+  int slot;
+  if (low == base)
+  {
+    int blk = 0;
+    while (map[blk] == 0) ++blk;
+    slot = blk * _MAP_BITS + base;
+  }
+  else
+    slot = low;
+
+  while(!valid(slot)) ++slot;
+  return slot;
+}
+
+int <T>MChunk::last_index() const
+{
+  if (empty()) return low - 1;
+  int slot;
+  if (top == fence)
+  {
+    int blk = (top - base) / _MAP_BITS;
+    while (map[blk] == 0) --blk;
+    slot = blk * _MAP_BITS + base + _MAP_BITS - 1;
+  }
+  else
+    slot = fence - 1;
+
+  while(!valid(slot)) --slot;
+  return slot;
+}
+
+
+int <T>MChunk:: OK() const
+{
+  int v = data != 0;             // have some data
+  v &= map != 0;                 // and a map
+  v &= base <= low;              // ok, index-wise
+  v &= low <= fence;
+  v &= fence <= top;
+
+  v &=  ((<T>MChunk*)(nxt->prev())) == this;      // and links are OK
+  v &=  ((<T>MChunk*)(prv->next())) == this;
+
+  int bitcount = 0;              // and unused count correct
+  for (int i = low; i < fence; ++i) if (!valid(i)) ++bitcount;
+  v &= unused == bitcount;
+  
+  if (!v) error("invariant failure");
+  return(v);
+}
+
+<T>* <T>MChunk::succ(<T>* p) const
+{
+  int i = ((int) p - (int) data) / sizeof(<T>) + base + 1;
+  if (p == 0 || i < low) return 0;
+  while (i < fence && !valid(i)) ++i;
+  if (i >= fence) return 0;
+  return pointer_to(i);
+}
+
+<T>* <T>MChunk::pred(<T>* p) const
+{
+  int i = ((int) p - (int) data) / sizeof(<T>) + base - 1;
+  if (p == 0 || i >= fence) return 0;
+  while (i >= low && !valid(i)) --i;
+  if (i < low) return 0;
+  return pointer_to(i);
+}
+
+<T>* <T>MChunk::first_pointer() const
+{
+  if (empty()) return 0;
+  int slot;
+  if (low == base)
+  {
+    int blk = 0;
+    while (map[blk] == 0) ++blk;
+    slot = blk * _MAP_BITS + base;
+  }
+  else
+    slot = low;
+
+  while(!valid(slot)) ++slot;
+  return pointer_to(slot);
+}
+
+<T>* <T>MChunk::last_pointer() const
+{
+  if (empty()) return 0;
+  int slot;
+  if (top == fence)
+  {
+    int blk = (top - base) / _MAP_BITS;
+    while (map[blk] == 0) --blk;
+    slot = blk * _MAP_BITS + base + _MAP_BITS - 1;
+  }
+  else
+    slot = fence - 1;
+
+  while(!valid(slot)) --slot;
+  return pointer_to(slot);
+}
+
+<T>MPlex:: <T>MPlex()
+{
+  unused = 0;
+  lo = fnc = 0;
+  csize = DEFAULT_INITIAL_CAPACITY;
+  <T>* data = new <T>[csize];
+  hd = ch = new <T>MChunk(data,  lo, lo, fnc, lo+csize);
+}
+
+<T>MPlex:: <T>MPlex(int chunksize)
+{
+  if (chunksize == 0) error("invalid constructor specification");
+  unused = 0;
+  lo = fnc = 0;
+  if (chunksize > 0)
+  {
+    csize = chunksize;
+    <T>* data = new <T>[csize];
+    hd = ch = new <T>MChunk(data,  lo, lo, fnc, csize);
+  }
+  else
+  {
+    csize = -chunksize;
+    <T>* data = new <T>[csize];
+    hd = ch = new <T>MChunk(data,  chunksize, lo, fnc, fnc);
+  }
+}
+
+
+<T>MPlex:: <T>MPlex(int l, int chunksize)
+{
+  if (chunksize == 0) error("invalid constructor specification");
+  unused = 0;
+  lo = fnc = l;
+  if (chunksize > 0)
+  {
+    csize = chunksize;
+    <T>* data = new <T>[csize];
+    hd = ch = new <T>MChunk(data,  lo, lo, fnc, csize+lo);
+  }
+  else
+  {
+    csize = -chunksize;
+    <T>* data = new <T>[csize];
+    hd = ch = new <T>MChunk(data,  chunksize+lo, lo, fnc, fnc);
+  }
+}
+
+
+void <T>MPlex::make_initial_chunks(int up)
+{
+  int need = fnc - lo;
+  hd = 0;
+  if (up)
+  {
+    int l = lo;
+    do
+    {
+      int sz;
+      if (need >= csize)
+        sz = csize;
+      else
+        sz = need;
+      <T>* data = new <T> [csize];
+      <T>MChunk* h = new <T>MChunk(data,  l, l, l+sz, l+csize);
+      if (hd != 0)
+        h->link_to_next(hd);
+      else
+        hd = h;
+      l += sz;
+      need -= sz;
+    } while (need > 0);
+  }
+  else
+  {
+    int hi = fnc;
+    do
+    {
+      int sz;
+      if (need >= csize)
+        sz = csize;
+      else
+        sz = need;
+      <T>* data = new <T> [csize];
+      <T>MChunk* h = new <T>MChunk(data,  hi-csize, hi-sz, hi, hi);
+      if (hd != 0)
+        h->link_to_next(hd);
+      hd = h;
+      hi -= sz;
+      need -= sz;
+    } while (need > 0);
+  }
+  ch = (<T>MChunk*) hd;
+}
+
+<T>MPlex:: <T>MPlex(int l, int hi, const <T&> initval, int chunksize)
+{
+  lo = l;
+  fnc = hi + 1;
+  if (chunksize == 0)
+  {
+    csize = fnc - l;
+    make_initial_chunks(1);
+  }
+  else if (chunksize < 0)
+  {
+    csize = -chunksize;
+    make_initial_chunks(0);
+  }
+  else
+  {
+    csize = chunksize;
+    make_initial_chunks(1);
+  }
+  unused = fnc - lo;
+  for (int i=lo; i<fnc; ++i)
+    undel_index(i);
+  fill(initval);
+}
+
+<T>MPlex::<T>MPlex(const <T>MPlex& a)
+{
+  lo = a.lo;
+  fnc = a.fnc;
+  csize = a.csize;
+  unused = fnc - lo;
+  hd = 0;
+  const <T>IChunk* p = a.hd;
+  do
+  {
+    <T>* data = new <T> [p->size()];
+    <T>MChunk* h = new <T>MChunk(data,  p->base_index(),
+                          p->low_index(), p->fence_index(), p->top_index());
+    if (hd != 0)
+      h->link_to_next(hd);
+    else
+      hd = h;
+    p = p->next();
+  } while (p != a.hd);
+  ch = (<T>MChunk*) hd;
+  for (int i = a.low(); i < a.fence(); a.next(i)) 
+  {
+    undel_index(i);
+    (*this)[i] = a[i];
+  }
+}
+
+void <T>MPlex::operator= (const <T>MPlex& a)
+{
+  if (&a != this)
+  {
+    invalidate();
+    lo = a.lo;
+    fnc = a.fnc;
+    csize = a.csize;
+    unused = fnc - lo;
+    hd = 0;
+    const <T>IChunk* p = a.hd;
+    do
+    {
+      <T>* data = new <T> [p->size()];
+      <T>MChunk* h = new <T>MChunk(data,  p->base_index(),
+                                   p->low_index(), p->fence_index(), 
+                                   p->top_index());
+      if (hd != 0)
+        h->link_to_next(hd);
+      else
+        hd = h;
+      p = p->next();
+    } while (p != a.hd);
+    ch = (<T>MChunk*) hd;
+    for (int i = a.low(); i < a.fence(); a.next(i)) 
+    {
+      undel_index(i);
+      (*this)[i] = a[i];
+    }
+  }
+}
+
+int <T>MPlex::valid(int idx) const
+{
+  const <T>MChunk* tail = (<T>MChunk*)tl();
+  const <T>MChunk* t = ch;
+  while (idx >= t->fence_index())
+  {
+    if (t == tail)  return 0; 
+    t = ((<T>MChunk*)(t->next()));
+  }
+  while (idx < t->low_index())
+  {
+    if (t == (<T>MChunk*)(hd)) return 0; 
+    t = ((<T>MChunk*)(t->prev()));
+  }
+  set_cache(t);
+  return t-><T>MChunk::valid_index(idx);
+}
+
+void <T>MPlex::cache(int idx) const
+{
+  const <T>MChunk* tail = (<T>MChunk*)tl();
+  const <T>MChunk* t = ch;
+  while (idx >= t->fence_index())
+  {
+    if (t == tail) index_error();
+    t = ((<T>MChunk*)(t->next()));
+  }
+  while (idx < t->low_index())
+  {
+    if (t == (<T>MChunk*)hd) index_error();
+    t = ((<T>MChunk*)(t->prev()));
+  }
+  if (!t-><T>MChunk::valid_index(idx)) index_error();
+  set_cache(t);
+}
+
+void <T>MPlex::cache(const <T>* p) const
+{
+  const <T>MChunk* old = ch;
+  const <T>MChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = ((<T>MChunk*)(t->next()));
+    if (t == old) index_error();
+  }
+  if (!t-><T>MChunk::valid_pointer(p)) index_error();
+  set_cache(t);
+}
+
+int <T>MPlex::owns(Pix px) const
+{
+  <T>* p = (<T>*)px;
+  const <T>MChunk* old = ch;
+  const <T>MChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = ((<T>MChunk*)(t->next()));
+    if (t == old)  return 0; 
+  }
+  set_cache(t);
+  return t-><T>MChunk::valid_pointer(p);
+}
+
+int <T>MPlex::add_high(const <T&> elem)
+{
+  <T>MChunk* t = ((<T>MChunk*) tl());
+
+  if (!t->can_grow_high())
+  {
+    <T>* data = new <T> [csize];
+    t = (new <T>MChunk(data, fnc,fnc,fnc,fnc+csize));
+    t->link_to_prev(tl());
+  }
+
+  *((t-><T>MChunk::grow_high())) = elem;
+  set_cache(t);
+  return fnc++;
+}
+
+int <T>MPlex::add_low (const <T&> elem)
+{
+  <T>MChunk* t = ((<T>MChunk*) hd);
+  if (!t->can_grow_low())
+  {
+    <T>* data = new <T> [csize];
+    hd = new <T>MChunk(data,  lo-csize, lo, lo, lo);
+    hd->link_to_next(t);
+    t = ((<T>MChunk*) hd);
+  }
+
+  *((t-><T>MChunk::grow_low())) = elem;
+  set_cache(t);
+  return --lo;
+}
+
+void <T>MPlex::adjust_bounds()
+{
+  <T>MChunk* t = ((<T>MChunk*) tl());
+
+  // clean up tail
+
+  t->reset_high();
+  while (t-><T>MChunk::empty() && !one_chunk())
+  {
+    <T>MChunk* pred = (<T>MChunk*)(t->prev());
+    del_chunk(t);
+    pred->reset_high();
+    t = (pred);
+  }
+  if (one_chunk())
+    t->reset_high();
+
+  int oldfnc = fnc;
+  fnc = t->fence_index();
+  unused -= oldfnc - fnc;
+
+  // and head..
+  t = ((<T>MChunk*) hd);
+  t->reset_low();
+  while (t-><T>MChunk::empty() && !one_chunk())
+  {
+    hd = (<T>MChunk*)(t->next());
+    del_chunk(t);
+    t = ((<T>MChunk*) hd);
+    t->reset_low();
+  }
+
+  int oldlo = lo;
+  lo = t->low_index();
+  unused -= lo - oldlo;
+
+
+  set_cache(t);
+}
+
+int <T>MPlex::del_high ()
+{
+  if (empty()) empty_error();
+  <T>MChunk* t = ((<T>MChunk*) tl());
+  while (t-><T>MChunk::empty() && !one_chunk()) // possible stragglers
+  {
+    <T>MChunk* pred = (<T>MChunk*)(t->prev());
+    del_chunk(t);
+    pred->reset_high();
+    t = (pred);
+  }
+  t-><T>MChunk::shrink_high();
+  while (t-><T>MChunk::empty() && !one_chunk())
+  {
+    <T>MChunk* pred = (<T>MChunk*)(t->prev());
+    del_chunk(t);
+    pred->reset_high();
+    t = (pred);
+  }
+  int oldfnc = fnc;
+  fnc = t->fence_index();
+  unused -= oldfnc - fnc - 1;
+  set_cache(t);
+  return fnc - 1;
+}
+
+int <T>MPlex::del_low ()
+{
+  if (empty()) empty_error();
+  <T>MChunk* t = ((<T>MChunk*) hd);
+  while (t-><T>MChunk::empty() && !one_chunk())
+  {
+    hd = (<T>MChunk*)(t->next());
+    del_chunk(t);
+    t = ((<T>MChunk*) hd);
+    t->reset_low();
+  }
+  t-><T>MChunk::shrink_low();
+  while (t-><T>MChunk::empty() && !one_chunk())
+  {
+    hd = (<T>MChunk*)(t->next());
+    del_chunk(t);
+    t = ((<T>MChunk*) hd);
+    t->reset_low();
+  }
+  int oldlo = lo;
+  lo = t->low_index();
+  unused -= lo - oldlo - 1;
+  set_cache(t);
+  return lo;
+}
+
+int <T>MPlex::add(const <T&> elem)
+{
+  if (unused == 0) 
+    return add_high(elem);
+
+  <T>MChunk* t;
+  for (t = ch; 
+       t->unused_indices() == 0; 
+       t = (<T>MChunk*)(t->prev()))
+    ;
+
+  int i =  t->unused_index();
+  set_cache(t);
+  undel_index(i);
+  (*this)[i] = elem;
+  return i;
+}
+
+int <T>MPlex::unused_index() const
+{
+  if (unused == 0) index_error();
+
+  <T>MChunk* t;
+  for (t = ch; 
+       t->unused_indices() == 0; 
+       t = (<T>MChunk*)(t->prev()))
+    ;
+
+  set_cache(t);
+  return t->unused_index();
+}
+
+Pix <T>MPlex::unused_Pix() const
+{
+  if (unused == 0) return 0;
+
+  <T>MChunk* t;
+  for (t = ch; 
+       t->unused_indices() == 0; 
+       t = (<T>MChunk*)(t->prev()))
+    ;
+
+  set_cache(t);
+  return t->pointer_to(t->unused_index()); 
+}
+
+int <T>MPlex::del_index(int idx)
+{
+  if (idx < lo || idx >= fnc) index_error();
+  if (<T>MPlex::valid(idx))
+  {
+    ++unused;
+    ch-><T>MChunk::del(idx);
+    return 1;
+  }
+  else
+    return 0;
+}
+
+int <T>MPlex::dopred(int idx) const
+{
+
+  if (idx >= fnc) idx = fnc;
+  if (idx <= lo) return lo - 1;
+
+  const <T>MChunk* t = ch;
+  
+  while (idx > t->fence_index())
+  {
+    t = ((<T>MChunk*)(t->next()));
+  }
+  while (idx <= t->low_index())
+  {
+    t = ((<T>MChunk*)(t->prev()));
+  }
+  int i = t-><T>MChunk::pred(idx);
+  while (i < t->low_index() && i >= lo)
+  {
+    t = ((<T>MChunk*)(t->prev()));
+    i = t-><T>MChunk::last_index();
+  }
+  set_cache(t);
+  return i;
+}
+
+
+int <T>MPlex::dosucc(int idx) const
+{
+  if (idx < lo) idx = lo;
+  if (idx >= fnc - 1) return fnc;
+
+  const <T>MChunk* t = ch;
+  while (idx >= t->fence_index())
+  {
+    t = ((<T>MChunk*)(t->next()));
+  }
+  while (idx < t->low_index())
+  {
+    t = ((<T>MChunk*)(t->prev()));
+  }
+  int i = t-><T>MChunk::succ(idx);
+  while (i >= t->fence_index() && i < fnc)
+  {
+    t = (<T>MChunk*)(t->next());
+    i = t-><T>MChunk::first_index();
+  }
+  set_cache(t);
+  return i;
+}
+
+void <T>MPlex::prev(Pix& i) const
+{
+  if (i == 0) return;
+
+  <T>* p = (<T>*) i;
+  const <T>MChunk* old = ch;
+  const <T>MChunk* t = ch;
+
+  while (!t->actual_pointer(p))
+  {
+    t = ((<T>MChunk*)(t->prev()));
+    if (t == old) 
+    { 
+      i = 0; 
+      return; 
+    }
+  }
+  <T>* q = t-><T>MChunk::pred(p);
+  while (q == 0 && t != (<T>MChunk*)hd)
+  {
+    t = ((<T>MChunk*)(t->prev()));
+    q = t-><T>MChunk::last_pointer();
+  }
+
+  i = Pix(q); 
+  set_cache(t);
+  return; 
+}
+
+void <T>MPlex::next(Pix& i) const
+{
+  if (i == 0) return;
+
+  <T>* p = (<T>*) i;
+  const <T>MChunk* tail = (<T>MChunk*)(tl());
+  const <T>MChunk* old = ch;
+  const <T>MChunk* t = ch;
+
+  while (!t->actual_pointer(p))
+  {
+    t = ((<T>MChunk*)(t->next()));
+    if (t == old) 
+    { 
+      i = 0; 
+      return; 
+    }
+  }
+  <T>* q = t-><T>MChunk::succ(p);
+  while  (q == 0 && t != tail)
+  {
+    t = ((<T>MChunk*)(t->next()));
+    q = t-><T>MChunk::first_pointer();
+  }
+
+  i = Pix(q); 
+  set_cache(t);
+  return; 
+}
+
+    
+void <T>MPlex::undel_index(int idx)
+{
+  if (idx < lo || idx >= fnc) index_error();
+
+  <T>MChunk* t = ch;
+  while (idx >= t->fence_index())
+  {
+    t = ((<T>MChunk*)(t->next()));
+  }
+  while (idx < t->low_index())
+  {
+    t = ((<T>MChunk*)(t->prev()));
+  }
+  int was_present = t-><T>MChunk::undel(idx);
+  if (!was_present) 
+  {
+    --unused;
+  }
+  set_cache(t);
+  return;
+}
+
+void <T>MPlex::clear()
+{
+  if (fnc != lo)
+  {
+    <T>MChunk* t = ((<T>MChunk*)tl());
+    while (t != hd)
+    {
+      <T>MChunk* prv = (<T>MChunk*)(t->prev());
+      del_chunk(t);
+      t = prv;
+    }
+    t-><T>MChunk::clear(lo);
+    set_cache(t);
+    fnc = lo;
+    unused = 0;
+  }
+}
+
+int <T>MPlex::OK () const
+{
+  int v = hd != 0;                    // at least one chunk
+
+  int found_ch = 0;                   // to make sure ch is in list;
+
+  int count = 0;                      // to count unused slots
+
+  const <T>MChunk* t = (<T>MChunk*)(hd);
+
+  int gap = t->low_index() - lo;
+  v &= gap == 0;                      // hd lo not less than lo.
+  count += gap;
+
+  for (;;)
+  {
+    if (t == ch) ++found_ch;
+    v &= t-><T>MChunk::OK();             // each chunk is OK
+    count += t->unused_indices();
+    if (t == (<T>MChunk*)(tl()))
+      break;
+    else                              // and has indices less than succ
+    {
+      gap = t->next()->base_index() - t->top_index();
+      v &= gap == 0;
+      count += gap;
+
+      if (t != (<T>MChunk*)hd)                  // internal chunks can't grow
+        v &= !t->can_grow_low() && !t->can_grow_high();
+
+      t = (const <T>MChunk*)(t->next());
+    }
+  }
+  gap = fnc - t->fence_index();
+  v &= gap == 0;
+  count += gap;
+
+  v &= count == unused;              // chunk counts agree with plex
+
+  v &= found_ch == 1;
+  if (!v) error("invariant failure");
+  return v;
+}
+
Index: trunk/src/emx/include/Attic/cpp/gen/MPlex.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/MPlex.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/MPlex.hP	(revision 18)
@@ -0,0 +1,414 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>MPlex_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>MPlex_h 1
+
+
+#include "<T>.Plex.h"
+
+
+// Number of bits per long, used in MChunk bit map operations
+
+#define _MAP_BITS  32
+
+
+class <T>MChunk : public <T>IChunk
+{
+protected:
+
+  unsigned long* map;          // bitmap of slots
+  int            unused;       // number of unused internal slots 
+
+  inline void           mark(int);    // bitmap operations
+  inline void           free(int);
+  inline int            valid(int) const;
+
+public:
+
+                 <T>MChunk(<T>*    d,        // ptr to array of elements
+                        int      base_idx, // initial indices
+                        int      low_idx,  // & initially clear map
+                        int      fence_idx,
+                        int      top_idx);
+
+  inline                ~<T>MChunk();
+
+// virtuals
+
+  int            first_index() const;
+  int            last_index() const;
+  inline int            succ(int idx) const;
+  inline int            pred(int idx) const;
+  <T>*           first_pointer() const;                 
+  <T>*           last_pointer() const;                 
+  <T>*           succ(<T>*) const;                 
+  <T>*           pred(<T>*) const; 
+  inline int            empty() const;
+  inline int            full() const;
+  inline int            valid_index(int i) const;
+  inline int            valid_pointer(const <T>* p) const;
+  inline <T>*           grow_high ();
+  inline <T>*           grow_low ();  
+  void           shrink_high ();
+  void           shrink_low ();     
+  void           clear(int);
+  void           cleardown(int);
+  int            OK() const;
+
+// extensions
+
+  int            unused_indices() const;   // how many free slot in low..fence?
+
+  int            unused_index() const;     // return index of free slot
+
+  int            del(int i);         // delete data indexed by i
+                                     // return true if was present
+  int            undel(int idx);     // un-delete data indexed by i
+                                     // return true if already present
+
+  void           reset_low();        // reset low = lowest valid index; 
+  void           reset_high();       // same for high
+
+};
+
+
+class <T>MPlex: public <T>Plex
+{
+  <T>MChunk*       ch;          // cached chunk
+  int              unused;      // # of free slots between low & fence
+
+  void             make_initial_chunks(int up = 1);
+  void             cache(int idx) const;
+  void             cache(const <T>* p) const;
+  int              dopred(int) const;
+  int              dosucc(int) const;
+
+  void             set_cache(const <T>MChunk* t) const; // logically, 
+                                               // not physically const
+
+public:
+                   <T>MPlex();                 // set low = 0;
+                                               // fence = 0;
+                                               // csize = default
+
+                   <T>MPlex(int ch_size);      // low = 0; 
+                                               // fence = 0;
+                                               // csize = ch_size
+
+                   <T>MPlex(int lo,            // low = lo; 
+                            int ch_size);      // fence=lo
+                                               // csize = ch_size
+
+                   <T>MPlex(int lo,            // low = lo
+                            int hi,            // fence = hi+1
+                            const <T&> initval,// fill with initval,
+                            int ch_size = 0);  // csize= ch_size
+                                               // or fence-lo if 0
+
+                   <T>MPlex(const <T>MPlex&);
+
+  void             operator= (const <T>MPlex&);
+
+// virtuals 
+
+  inline <T>&             high_element ();
+  inline <T>&             low_element ();
+  inline const <T>&       high_element () const;
+  inline const <T>&       low_element () const;
+
+  inline Pix              first() const;
+  inline Pix              last() const ;
+  void             prev(Pix& ptr) const;
+  void             next(Pix& ptr) const;
+  int              owns(Pix p) const;
+  inline <T>&             operator () (Pix p);
+  inline const <T>&       operator () (Pix p) const;
+
+  inline int              low() const; 
+  inline int              high() const;
+  int              valid(int idx) const;
+  inline void             prev(int& idx) const;
+  inline void             next(int& x) const;
+  inline <T>&             operator [] (int index);
+  inline const <T>&       operator [] (int index) const;
+    
+  inline int              Pix_to_index(Pix p) const;
+  inline Pix              index_to_Pix(int idx) const;
+
+  inline int              can_add_high() const;
+  inline int              can_add_low() const;
+  inline int              full() const;
+
+  int              add_high(const <T&> elem);
+  int              del_high ();
+  int              add_low (const <T&> elem);
+  int              del_low ();
+  void             clear();
+
+  int              OK () const; 
+
+// extensions
+
+  int              count() const;             // # valid elements
+  int              available() const;         // # deleted elements
+
+  int              unused_index()const;       // return index of a deleted elem
+  Pix              unused_Pix() const;        // return Pix of a deleted elem
+
+  int              del_index(int idx);        // logically delete at idx;
+                                              // return true if was present
+  int              del_Pix(Pix p);            // delete at p
+
+  void             undel_index(int idx);      // undelete at idx;
+  void             undel_Pix(Pix p);          // undelete at p;
+
+  void             adjust_bounds();           // reset lo, hi to lowest &
+                                              // highest valid indices
+
+  int              add(const <T&> elem);      // add anywhere
+};
+
+
+inline <T>MChunk:: ~<T>MChunk()
+{
+  delete [] map;
+}
+
+inline void <T>MChunk::mark(int idx)
+{
+  unsigned int i = idx - base;
+  map[i / _MAP_BITS] |= 1 << (i & (_MAP_BITS - 1));
+}
+
+inline void <T>MChunk::free(int idx)
+{
+  unsigned int i = idx - base;
+  map[i / _MAP_BITS] &= ~(1 << (i & (_MAP_BITS - 1)));
+}
+
+inline int <T>MChunk::valid(int idx) const
+{
+  unsigned int i = idx - base;
+  return map[i / _MAP_BITS] & (1 << (i & (_MAP_BITS - 1)));
+}
+
+inline  int <T>MChunk:: valid_index(int i) const
+{
+  return i >= low && i < fence && valid(i);
+}
+
+inline  int  <T>MChunk:: valid_pointer(const <T>* p) const
+{
+  int i = ((int)p - (int)data) / sizeof(<T>);
+  return i >= 0 && i < (fence - base) &&
+    (map[(unsigned)i / _MAP_BITS] & (1 << (i & (_MAP_BITS - 1))));
+}
+
+inline int <T>MChunk::empty() const
+{
+  return  fence - low - unused == 0;
+}
+
+inline int <T>MChunk::full() const
+{
+  return  unused + (top - fence) + (low - base) == 0;
+}
+
+inline int <T>MChunk::succ(int idx) const
+{
+  int i = (idx < low)? low : idx + 1;
+  while (i < fence && !valid(i)) ++i;
+  return i;
+}
+
+inline int <T>MChunk::pred(int idx) const
+{
+  int i = (idx > fence)? (fence - 1) : idx - 1;
+  while (i >= low && !valid(i)) --i;
+  return i;
+}
+
+inline int <T>MChunk::unused_indices() const
+{
+  return unused;
+}
+
+inline <T>*   <T>MChunk:: grow_high ()
+{
+  if (!can_grow_high()) full_error();
+  mark(fence);
+  return &(data[fence++ - base]);
+}
+
+inline <T>*   <T>MChunk:: grow_low ()
+{
+  if (!can_grow_low()) full_error();
+  mark(--low);
+  return &(data[low - base]);
+}
+
+inline void <T>MChunk::reset_low()
+{
+  while (low < fence && !valid(low))
+  {
+    --unused;
+    ++low;
+  }
+}
+
+inline void <T>MChunk::reset_high()
+{
+  while (fence > low && !valid(fence - 1))
+  {
+    --unused;
+    --fence;
+  }
+}
+
+inline  int <T>MPlex::full () const
+{
+  return 0;
+}
+
+inline int <T>MPlex::can_add_high() const
+{
+  return 1;
+}
+
+inline int <T>MPlex::can_add_low() const
+{
+  return 1;
+}
+
+inline int <T>MPlex::available() const
+{
+  return unused;
+}
+
+inline int <T>MPlex::count() const
+{
+  return fnc - lo - unused;
+}
+
+inline void <T>MPlex::set_cache(const <T>MChunk* t) const
+{
+  ((<T>MPlex*)(this))->ch = (<T>MChunk*)t;
+}
+
+inline <T>& <T>MPlex:: operator [] (int idx)
+{
+  if (!ch-><T>MChunk::valid_index(idx)) cache(idx);
+  return * (ch->pointer_to(idx));
+}
+
+inline const <T>& <T>MPlex:: operator [] (int idx) const
+{
+  if (!ch-><T>MChunk::valid_index(idx)) cache(idx);
+  return * ((const <T>*)(ch->pointer_to(idx)));
+}
+
+inline  int <T>MPlex::Pix_to_index(Pix p) const
+{
+  if (!ch-><T>MChunk::valid_pointer((<T>*)p)) cache((<T>*)p);
+  return ch->index_of((<T>*)p);
+}
+
+inline int <T>MPlex::high() const
+{
+  return (((const <T>MChunk*)tl())-><T>MChunk::valid_index(fnc-1)) ? 
+    fnc-1 : dopred(fnc-1);
+}
+
+inline int <T>MPlex::low() const
+{
+  return (((const <T>MChunk*)hd)-><T>MChunk::valid_index(lo))? lo : dosucc(lo);
+}
+
+inline  <T>& <T>MPlex::low_element ()
+{
+  return (*this)[low()];
+}
+
+inline const <T>& <T>MPlex::low_element () const
+{
+  return (*this)[low()];
+}
+
+inline  <T>& <T>MPlex::high_element ()
+{
+  return (*this)[high()];
+}
+
+inline const <T>& <T>MPlex::high_element () const
+{
+  return (*this)[high()];
+}
+
+inline  Pix <T>MPlex::index_to_Pix(int idx) const
+{
+  if (!ch-><T>MChunk::valid_index(idx)) cache(idx);
+  return Pix(ch->pointer_to(idx));
+}
+
+inline void <T>MPlex::next(int& idx) const
+{
+  idx = (ch-><T>MChunk::valid_index(idx+1))? idx+1 : dosucc(idx);
+}
+
+inline void <T>MPlex::prev(int& idx) const
+{
+  idx = (ch-><T>MChunk::valid_index(idx-1))? idx-1 : dopred(idx);
+}
+
+inline Pix <T>MPlex::first() const
+{
+  return index_to_Pix(low());
+}
+
+inline Pix <T>MPlex::last() const
+{
+  return index_to_Pix(high());
+}
+
+
+inline void <T>MPlex::undel_Pix(Pix p)
+{
+  undel_index(Pix_to_index(p));
+}
+
+inline int <T>MPlex::del_Pix(Pix p)
+{
+  return del_index(Pix_to_index(p));
+}
+
+inline <T>& <T>MPlex:: operator () (Pix p)
+{
+  return *((<T>*)p);
+}
+
+inline const <T>& <T>MPlex:: operator () (Pix p) const
+{
+  return *((const <T>*)p);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/Map.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Map.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Map.ccP	(revision 18)
@@ -0,0 +1,59 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <builtin.h>
+#include "<T>.<C>.Map.h"
+
+
+Pix <T><C>Map::seek(<T&> item)
+{
+  Pix i;
+  for (i = first(); i != 0 && !(<T>EQ(key(i), item)); next(i));
+  return i;
+}
+
+int <T><C>Map::owns(Pix idx)
+{
+  if (idx == 0) return 0;
+  for (Pix i = first(); i; next(i)) if (i == idx) return 1;
+  return 0;
+}
+
+void <T><C>Map::clear()
+{
+  Pix i = first(); 
+  while (i != 0)
+  {
+    del(key(i));
+    i = first();
+  }
+}
+
+int <T><C>Map::contains (<T&> item)
+{
+  return seek(item) != 0;
+}
+
+
+void <T><C>Map::error(const char* msg)
+{
+  (*lib_error_handler)("Map", msg);
+}
Index: trunk/src/emx/include/Attic/cpp/gen/Map.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Map.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Map.hP	(revision 18)
@@ -0,0 +1,87 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T><C>Map_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T><C>Map_h 1
+
+#include <Pix.h>
+#include "<T>.defs.h"
+
+class <T><C>Map
+{
+protected:
+  int                   count;
+  <C>                   def;
+
+public:
+                        <T><C>Map(<C&> dflt);
+  inline virtual              ~<T><C>Map();
+
+  int                   length() const; // current number of items
+  int                   empty() const;
+
+  virtual int           contains(<T&> key);      // is key mapped?
+
+  virtual void          clear();                 // delete all items
+
+  virtual <C>&          operator [] (<T&> key) = 0; // access contents by key
+
+  virtual void          del(<T&> key) = 0;       // delete entry
+
+  virtual Pix           first() = 0;             // Pix of first item or 0
+  virtual void          next(Pix& i) = 0;        // advance to next or 0
+  virtual <T>&          key(Pix i) = 0;          // access key at i
+  virtual <C>&          contents(Pix i) = 0;     // access contents at i
+
+  virtual int           owns(Pix i);             // is i a valid Pix  ?
+  virtual Pix           seek(<T&> key);          // Pix of key
+
+  <C>&                  dflt();                  // access default val
+
+  void                  error(const char* msg);
+  virtual int           OK() = 0;                // rep invariant
+};
+
+
+inline <T><C>Map::~<T><C>Map() {}
+
+inline int <T><C>Map::length() const
+{
+  return count;
+}
+
+inline int <T><C>Map::empty() const
+{
+  return count == 0;
+}
+
+inline <C>& <T><C>Map::dflt()
+{
+  return def;
+}
+
+inline <T><C>Map::<T><C>Map(<C&> dflt) :def(dflt)
+{
+  count = 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/OSLBag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/OSLBag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/OSLBag.ccP	(revision 18)
@@ -0,0 +1,196 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.OSLBag.h"
+
+
+Pix <T>OSLBag::seek(<T&> item, Pix i)
+{
+  if (i == 0) i = p.first(); else next(i);
+  for (; i != 0; p.next(i))
+  {
+    int cmp = <T>CMP(item, p(i));
+    if (cmp == 0)
+      return i;
+    else if (cmp < 0)
+      return 0;
+  }
+  return 0;
+}
+
+int <T>OSLBag::nof(<T&> item)
+{
+  int n = 0;
+  for (Pix i = p.first(); i != 0; p.next(i))
+  {
+    int cmp = <T>CMP(item, p(i));
+    if (cmp == 0)
+      ++n;
+    else if (cmp < 0)
+      break;
+  }
+  return n;
+}
+
+Pix <T>OSLBag::add(<T&> item)
+{
+  Pix i = p.first();
+  if (i == 0) 
+  {
+    ++count;
+    return p.prepend(item);
+  }
+  int cmp = <T>CMP(item, p(i));
+  if (cmp <= 0)
+  {
+    ++count;
+    return p.prepend(item);
+  }
+  else
+  {
+    Pix trail = i;
+    p.next(i);
+    for (;;)
+    {
+      if (i == 0)
+      {
+        ++count;
+        return p.append(item);
+      }
+      cmp = <T>CMP(item, p(i));
+      if (cmp <= 0)
+      {
+        ++count;
+        return p.ins_after(trail, item);
+      }
+      else
+      {
+        trail = i;
+        p.next(i);
+      }
+    }
+  }
+}
+
+void <T>OSLBag::del(<T&> item)
+{
+  Pix i = p.first();
+  if (i == 0)
+    return;
+  int cmp = <T>CMP(item, p(i));
+  if (cmp < 0)
+    return;
+  else if (cmp == 0)
+  {
+    --count;
+    p.del_front();
+  }
+  else
+  {
+    Pix trail = i;
+    p.next(i);
+    while (i != 0)
+    {
+      cmp = <T>CMP(item, p(i));
+      if (cmp < 0)
+        return;
+      else if (cmp == 0)
+      {
+        --count;
+        p.del_after(trail);
+        return;
+      }
+      else
+      {
+        trail = i;
+        p.next(i);
+      }
+    }
+  }
+}
+
+void <T>OSLBag::remove(<T&> item)
+{
+  Pix i = p.first();
+  if (i == 0)
+    return;
+  int cmp = <T>CMP(item, p(i));
+  if (cmp < 0)
+    return;
+  else if (cmp == 0)
+  {
+    do
+    {
+      --count;
+      p.del_front();
+      i = p.first();
+    } while (i != 0 && <T>EQ(item, p(i)));
+  }
+  else
+  {
+    Pix trail = i;
+    p.next(i);
+    while (i != 0)
+    {
+      cmp = <T>CMP(item, p(i));
+      if (cmp < 0)
+        return;
+      else if (cmp == 0)
+      {
+        do
+        {
+          --count;
+          p.del_after(trail);
+          i = trail;
+          next(i);
+        } while (i != 0 && <T>EQ(item, p(i)));
+        return;
+      }
+      else
+      {
+        trail = i;
+        p.next(i);
+      }
+    }
+  }
+}
+        
+int <T>OSLBag::OK()
+{
+  int v = p.OK();
+  v &= count == p.length();
+  Pix trail = p.first();
+  if (trail == 0)
+    v &= count == 0;
+  else
+  {
+    Pix i = trail; next(i);
+    while (i != 0)
+    {
+      v &= <T>CMP(p(trail), p(i)) <= 0;
+      trail = i;
+      next(i);
+    }
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
+ 
Index: trunk/src/emx/include/Attic/cpp/gen/OSLBag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/OSLBag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/OSLBag.hP	(revision 18)
@@ -0,0 +1,91 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>OSLBag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>OSLBag_h 1
+
+#include "<T>.Bag.h"
+#include "<T>.SLList.h"
+
+class <T>OSLBag : public <T>Bag
+{
+protected:
+  <T>SLList     p;
+
+public:
+                <T>OSLBag();
+                <T>OSLBag(const <T>OSLBag&);
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  void          remove(<T&>item);
+
+  inline int           contains(<T&> item);
+  int           nof(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item, Pix from = 0);
+
+  int           OK();
+};
+
+
+inline <T>OSLBag::<T>OSLBag() : p() { count = 0; }
+
+inline <T>OSLBag::<T>OSLBag(const <T>OSLBag& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>OSLBag::first()
+{
+  return p.first();
+}
+
+inline void <T>OSLBag::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>OSLBag::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline void <T>OSLBag::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>OSLBag::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+inline int <T>OSLBag::contains(<T&> item)
+{
+  return seek(item) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/OSLSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/OSLSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/OSLSet.ccP	(revision 18)
@@ -0,0 +1,321 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.OSLSet.h"
+
+
+Pix <T>OSLSet::seek(<T&> item)
+{
+  for (Pix i = p.first(); i != 0; p.next(i))
+  {
+    int cmp = <T>CMP(item, p(i));
+    if (cmp == 0)
+      return i;
+    else if (cmp < 0)
+      return 0;
+  }
+  return 0;
+}
+
+Pix <T>OSLSet::add(<T&> item)
+{
+  Pix i = p.first();
+  if (i == 0) 
+  {
+    ++count;
+    return p.prepend(item);
+  }
+  int cmp = <T>CMP(item, p(i));
+  if (cmp == 0)
+    return i;
+  else if (cmp < 0)
+  {
+    ++count;
+    return p.prepend(item);
+  }
+  else
+  {
+    Pix trail = i;
+    p.next(i);
+    for (;;)
+    {
+      if (i == 0)
+      {
+        ++count;
+        return p.append(item);
+      }
+      cmp = <T>CMP(item, p(i));
+      if (cmp == 0)
+        return i;
+      else if (cmp < 0)
+      {
+        ++count;
+        return p.ins_after(trail, item);
+      }
+      else
+      {
+        trail = i;
+        p.next(i);
+      }
+    }
+  }
+}
+
+void <T>OSLSet::del(<T&> item)
+{
+  Pix i = p.first();
+  if (i == 0)
+    return;
+  int cmp = <T>CMP(item, p(i));
+  if (cmp < 0)
+    return;
+  else if (cmp == 0)
+  {
+    --count;
+    p.del_front();
+  }
+  else
+  {
+    Pix trail = i;
+    p.next(i);
+    while (i != 0)
+    {
+      cmp = <T>CMP(item, p(i));
+      if (cmp < 0)
+        return;
+      else if (cmp == 0)
+      {
+        --count;
+        p.del_after(trail);
+        return;
+      }
+      else
+      {
+        trail = i;
+        p.next(i);
+      }
+    }
+  }
+}
+        
+
+int <T>OSLSet::operator <= (<T>OSLSet& b)
+{
+  if (count > b.count) return 0;
+  Pix i = first();
+  Pix j = b.first();
+  for (;;)
+  {
+    if (i == 0)
+      return 1;
+    else if (j == 0)
+      return 0;
+    int cmp = <T>CMP(p(i), b.p(j));
+    if (cmp == 0)
+    {
+      next(i); b.next(j);
+    }
+    else if (cmp < 0)
+      return 0;
+    else
+      b.next(j);
+  }
+}
+
+int <T>OSLSet::operator == (<T>OSLSet& b)
+{
+  if (count != b.count) return 0;
+  if (count == 0) return 1;
+  Pix i = p.first();
+  Pix j = b.p.first();
+  while (i != 0)
+  {
+    if (!<T>EQ(p(i),b.p(j))) return 0;
+    next(i);
+    b.next(j);
+  }
+  return 1;
+}
+
+
+void <T>OSLSet::operator |= (<T>OSLSet& b)
+{
+  if (&b == this || b.count == 0)
+    return;
+  else
+  {
+    Pix j = b.p.first();
+    Pix i = p.first();
+    Pix trail = 0;
+    for (;;)
+    {
+      if (j == 0)
+        return;
+      else if (i == 0)
+      {
+        for (; j != 0; b.next(j))
+        {
+          ++count;
+          p.append(b.p(j));
+        }
+        return;
+      }
+      int cmp = <T>CMP(p(i), b.p(j));
+      if (cmp <= 0)
+      {
+        if (cmp == 0) b.next(j);
+        trail = i;
+        next(i);
+      }
+      else
+      {
+        ++count;
+        if (trail == 0)
+          trail = p.prepend(b.p(j));
+        else
+          trail = p.ins_after(trail, b.p(j));
+        b.next(j);
+      }
+    }
+  }
+}
+
+
+void <T>OSLSet::operator -= (<T>OSLSet& b)
+{
+  if (&b == this)
+    clear();
+  else if (count != 0 && b.count != 0)
+  {
+    Pix i = p.first();
+    Pix j = b.p.first();
+    Pix trail = 0;
+    for (;;)
+    {
+      if (j == 0 || i == 0)
+        return;
+      int cmp = <T>CMP(p(i), b.p(j));
+      if (cmp == 0)
+      {
+        --count;
+        b.next(j);
+        if (trail == 0)
+        {
+          p.del_front();
+          i = p.first();
+        }
+        else
+        {
+          next(i);
+          p.del_after(trail);
+        }
+      }
+      else if (cmp < 0)
+      {
+        trail = i;
+        next(i);
+      }
+      else
+        b.next(j);
+    }
+  }
+}
+
+void <T>OSLSet::operator &= (<T>OSLSet& b)
+{
+  if (b.count == 0)
+    clear();
+  else if (&b != this && count != 0)
+  {
+    Pix i = p.first();
+    Pix j = b.p.first();
+    Pix trail = 0;
+    for (;;)
+    {
+      if (i == 0)
+        return;
+      else if (j == 0)
+      {
+        if (trail == 0)
+        {
+          p.clear();
+          count = 0;
+        }
+        else
+        {
+          while (i != 0)
+          {
+            --count;
+            next(i);
+            p.del_after(trail);
+          }
+        }
+        return;
+      }
+      int cmp = <T>CMP(p(i), b.p(j));
+
+      if (cmp == 0)
+      {
+        trail = i;
+        next(i);
+        b.next(j);
+      }
+      else if (cmp < 0)
+      {
+        --count;
+        if (trail == 0)
+        {
+          p.del_front();
+          i = p.first();
+        }
+        else
+        {
+          next(i);
+          p.del_after(trail);
+        }
+      }
+      else
+        b.next(j);
+    }
+  }
+}
+
+
+int <T>OSLSet::OK()
+{
+  int v = p.OK();
+  v &= count == p.length();
+  Pix trail = p.first();
+  if (trail == 0)
+    v &= count == 0;
+  else
+  {
+    Pix i = trail; next(i);
+    while (i != 0)
+    {
+      v &= <T>CMP(p(trail), p(i)) < 0;
+      trail = i;
+      next(i);
+    }
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/OSLSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/OSLSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/OSLSet.hP	(revision 18)
@@ -0,0 +1,101 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>OSLSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>OSLSet_h 1
+
+#include "<T>.Set.h"
+#include "<T>.SLList.h"
+
+class <T>OSLSet : public <T>Set
+{
+protected:
+  <T>SLList     p;
+
+public:
+                <T>OSLSet();
+                <T>OSLSet(const <T>OSLSet&);
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  inline int           contains(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item);
+
+  void          operator |= (<T>OSLSet& b);
+  void          operator -= (<T>OSLSet& b);
+  void          operator &= (<T>OSLSet& b);
+
+  int           operator == (<T>OSLSet& b);
+  int           operator != (<T>OSLSet& b);
+  int           operator <= (<T>OSLSet& b); 
+
+  int           OK();
+};
+
+
+inline <T>OSLSet::<T>OSLSet() : p() { count = 0; }
+
+inline <T>OSLSet::<T>OSLSet(const <T>OSLSet& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>OSLSet::first()
+{
+  return p.first();
+}
+
+inline void <T>OSLSet::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>OSLSet::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline void <T>OSLSet::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>OSLSet::contains (<T&> item)
+{
+  return seek(item) != 0;
+}
+
+inline int <T>OSLSet::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+inline int <T>OSLSet::operator != (<T>OSLSet& b)
+{
+  return !(*this == b);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/OXPBag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/OXPBag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/OXPBag.ccP	(revision 18)
@@ -0,0 +1,221 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.OXPBag.h"
+
+
+Pix <T>OXPBag::seek(<T&> item, Pix i)
+{
+  if (i == 0)
+  {
+    int l = p.low();
+    int h = p.high();
+    while (l <= h)
+    {
+      int mid = (l + h) / 2;
+      int cmp = <T>CMP(item, p[mid]);
+      if (cmp == 0)
+      {
+        while (mid > p.low() && <T>EQ(item, p[mid - 1])) --mid;
+        return p.index_to_Pix(mid);
+      }
+      else if (cmp < 0)
+        h = mid - 1;
+      else
+        l = mid + 1;
+    }
+    return 0;
+  }
+  int cmp = <T>CMP(item, p(i));
+  if (cmp == 0)
+  {
+    next(i);
+    return (<T>EQ(item, p(i)))? i : 0;
+  }
+  else if (cmp < 0)
+  {
+    int ind = p.Pix_to_index(i);
+    int l = ind;
+    int h = p.high();
+    while (l <= h)
+    {
+      int mid = (l + h) / 2;
+      cmp = <T>CMP(item, p[mid]);
+      if (cmp == 0)
+      {
+        while (mid > ind && <T>EQ(item, p[mid - 1])) --mid;
+        return p.index_to_Pix(mid);
+      }
+      else if (cmp < 0)
+        h = mid - 1;
+      else
+        l = mid + 1;
+    }
+    return 0;
+  }
+  else
+    return 0;
+}
+
+int <T>OXPBag::nof(<T&> item)
+{
+  int l = p.low();
+  int h = p.high();
+  while (l <= h)
+  {
+    int mid = (l + h) / 2;
+    int cmp = <T>CMP(item, p[mid]);
+    if (cmp == 0)
+    {
+      l = h = mid;
+      while (l > p.low() && <T>EQ(item, p[l - 1])) --l;
+      while (h < p.high() && <T>EQ(item, p[h + 1])) ++h;
+      return h - l + 1;
+    }
+    else if (cmp < 0)
+      h = mid - 1;
+    else
+      l = mid + 1;
+  }
+  return 0;
+}
+
+Pix <T>OXPBag::add(<T&> item)
+{
+  if (count == 0) 
+  {
+    ++count;
+    return p.index_to_Pix(p.add_high(item));
+  }
+  int l = p.low();
+  int h = p.high();
+  while (l <= h)
+  {
+    int mid = (l + h) / 2;
+    int cmp = <T>CMP(item, p[mid]);
+    if (cmp == 0)
+    {
+      l = mid;
+      break;
+    }
+    else if (cmp < 0)
+      h = mid - 1;
+    else
+      l = mid + 1;
+  }
+  // add on whichever side is shortest
+  ++count;
+  if (l == p.fence())
+    return p.index_to_Pix(p.add_high(item));
+  else if (l == p.low())
+    return p.index_to_Pix(p.add_low(item));
+  else 
+  {
+    if (p.high() - l < l - p.low())
+    {
+      h = p.add_high(p.high_element());
+      for (int i = h - 1; i > l; --i) p[i] = p[i-1];
+    }
+    else
+    {
+      --l;
+      h = p.add_low(p.low_element());
+      for (int i = h + 1; i < l; ++i) p[i] = p[i+1];
+    }
+    p[l] = item;
+    return p.index_to_Pix(l);
+  }
+}
+
+void <T>OXPBag::del(<T&> item)
+{
+  int l = p.low();
+  int h = p.high();
+  while (l <= h)
+  {
+    int mid = (l + h) / 2;
+    int cmp = <T>CMP(item, p[mid]);
+    if (cmp == 0)
+    {
+      --count;
+      if (p.high() - mid < mid - p.low())
+      {
+        for (int i = mid; i < p.high(); ++i) p[i] = p[i+1];
+        p.del_high();
+      }
+      else
+      {
+        for (int i = mid; i > p.low(); --i) p[i] = p[i-1];
+        p.del_low();
+      }
+      return;
+    }
+    else if (cmp < 0)
+      h = mid - 1;
+    else
+      l = mid + 1;
+  }
+}
+
+void <T>OXPBag::remove(<T&> item)
+{
+  int l = p.low();
+  int h = p.high();
+  while (l <= h)
+  {
+    int mid = (l + h) / 2;
+    int cmp = <T>CMP(item, p[mid]);
+    if (cmp == 0)
+    {
+      l = h = mid;
+      while (l > p.low() && <T>EQ(item, p[l - 1])) --l;
+      while (h < p.high() && <T>EQ(item, p[h + 1])) ++h;
+      int n = h - l + 1;
+      count -= n;
+      if (p.high() - h < l - p.low())
+      {
+        h = p.high() - n;
+        for (int i = l; i <= h; ++i) p[i] = p[i+n];
+        while (n-- > 0) p.del_high();
+      }
+      else
+      {
+        l = p.low() + n;
+        for (int i = h; i >= l; --i) p[i] = p[i-n];
+        while (n-- > 0) p.del_low();
+      }
+      return;
+    }
+    else if (cmp < 0)
+      h = mid - 1;
+    else
+      l = mid + 1;
+  }
+}
+
+int <T>OXPBag::OK()
+{
+  int v = p.OK();
+  v &= count == p.length();
+  for (int i = p.low(); i < p.high(); ++i) v &= <T>CMP(p[i], p[i+1]) <= 0;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/OXPBag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/OXPBag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/OXPBag.hP	(revision 18)
@@ -0,0 +1,73 @@
+#ifndef _<T>OXPBag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>OXPBag_h 1
+
+#include "<T>.Bag.h"
+#include "<T>.XPlex.h"
+
+class <T>OXPBag : public <T>Bag
+{
+protected:
+  <T>XPlex       p;
+
+public:
+                <T>OXPBag(int chunksize = DEFAULT_INITIAL_CAPACITY);
+                <T>OXPBag(const <T>OXPBag&);
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+#undef remove
+  void          remove(<T&>item);
+  int           nof(<T&> item);
+  inline int           contains(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item, Pix from = 0);
+
+  int           OK();
+};
+
+
+inline <T>OXPBag::<T>OXPBag(int chunksize) 
+     : p(chunksize) { count = 0; }
+
+inline <T>OXPBag::<T>OXPBag(const <T>OXPBag& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>OXPBag::first()
+{
+  return p.first();
+}
+
+inline void <T>OXPBag::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>OXPBag::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline void <T>OXPBag::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>OXPBag::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+inline int <T>OXPBag::contains(<T&> item)
+{
+  return seek(item) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/OXPSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/OXPSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/OXPSet.ccP	(revision 18)
@@ -0,0 +1,280 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.OXPSet.h"
+
+
+Pix <T>OXPSet::seek(<T&> item)
+{
+  int l = p.low();
+  int h = p.high();
+  while (l <= h)
+  {
+    int mid = (l + h) / 2;
+    int cmp = <T>CMP(item, p[mid]);
+    if (cmp == 0)
+      return p.index_to_Pix(mid);
+    else if (cmp < 0)
+      h = mid - 1;
+    else
+      l = mid + 1;
+  }
+  return 0;
+}
+
+Pix <T>OXPSet::add(<T&> item)
+{
+  if (count == 0) 
+  {
+    ++count;
+    return p.index_to_Pix(p.add_high(item));
+  }
+  int l = p.low();
+  int h = p.high();
+  while (l <= h)
+  {
+    int mid = (l + h) / 2;
+    int cmp = <T>CMP(item, p[mid]);
+    if (cmp == 0)
+      return p.index_to_Pix(mid);
+    else if (cmp < 0)
+        h = mid - 1;
+    else
+      l = mid + 1;
+  }
+  // add on whichever side is shortest
+  ++count;
+  if (l == p.fence())
+    return p.index_to_Pix(p.add_high(item));
+  else if (l == p.low())
+    return p.index_to_Pix(p.add_low(item));
+  else 
+  {
+    if (p.fence() - l < l - p.low())
+    {
+      h = p.add_high(p.high_element());
+      for (int i = h - 1; i > l; --i) p[i] = p[i-1];
+    }
+    else
+    {
+      --l;
+      h = p.add_low(p.low_element());
+      for (int i = h + 1; i < l; ++i) p[i] = p[i+1];
+    }
+    p[l] = item;
+    return p.index_to_Pix(l);
+  }
+}
+
+void <T>OXPSet::del(<T&> item)
+{
+  int l = p.low();
+  int h = p.high();
+  while (l <= h)
+  {
+    int mid = (l + h) / 2;
+    int cmp = <T>CMP(item, p[mid]);
+    if (cmp == 0)
+    {
+      --count;
+      if (p.high() - mid < mid - p.low())
+      {
+        for (int i = mid; i < p.high(); ++i) p[i] = p[i+1];
+        p.del_high();
+      }
+      else
+      {
+        for (int i = mid; i > p.low(); --i) p[i] = p[i-1];
+        p.del_low();
+      }
+      return;
+    }
+    else if (cmp < 0)
+      h = mid - 1;
+    else
+      l = mid + 1;
+  }
+}
+
+int <T>OXPSet::operator <= (<T>OXPSet& b)
+{
+  if (count > b.count) return 0;
+  int i = p.low();
+  int j = b.p.low();
+  for (;;)
+  {
+    if (i >= p.fence())
+      return 1;
+    else if (j >= b.p.fence()) 
+      return 0;
+    int cmp = <T>CMP(p[i], b.p[j]);
+    if (cmp == 0)
+    {
+      ++i; ++j;
+    }
+    else if (cmp < 0)
+      return 0;
+    else
+      ++j;
+  }
+}
+
+int <T>OXPSet::operator == (<T>OXPSet& b)
+{
+  int n = count;
+  if (n != b.count) return 0;
+  if (n == 0) return 1;
+  int i = p.low();
+  int j = b.p.low();
+  while (n-- > 0) if (!<T>EQ(p[i++], b.p[j++])) return 0;
+  return 1;
+}
+
+
+void <T>OXPSet::operator |= (<T>OXPSet& b)
+{
+  if (&b == this || b.count == 0)
+    return;
+  else if (b.count <= 2) // small b -- just add
+    for (Pix i = b.first(); i; b.next(i)) add(b(i));
+  else
+  {
+    // strategy: merge into top of p, simultaneously killing old bottom
+    int oldfence = p.fence();
+    int i = p.low();
+    int j = b.p.low();
+    for (;;)
+    {
+      if (i == oldfence)
+      {
+        while (j < b.p.fence()) p.add_high(b.p[j++]);
+        break;
+      }
+      else if (j == b.p.fence())
+      {
+        while (i++ < oldfence) 
+        {
+          p.add_high(p.low_element());
+          p.del_low();
+        }
+        break;
+      }
+      int cmp = <T>CMP(p[i], b.p[j]);
+      if (cmp <= 0)
+      {
+        ++i;
+        if (cmp == 0)  ++j;
+        p.add_high(p.low_element());
+        p.del_low();
+      }
+      else
+        p.add_high(b.p[j++]);
+    }
+    count = p.length();
+  }
+}
+
+
+
+void <T>OXPSet::operator -= (<T>OXPSet& b)
+{
+  if (&b == this)
+    clear();
+  else if (count != 0 && b.count != 0)
+  {
+    int i = p.low();
+    int k = i;
+    int j = b.p.low();
+    int oldfence = p.fence();
+    for (;;)
+    {
+      if (i >= oldfence)
+        break;
+      else if (j >= b.p.fence())
+      {
+        if (k != i)
+          while (i < oldfence) p[k++] = p[i++];
+        else
+          k = oldfence;
+        break;
+      }
+      int cmp = <T>CMP(p[i], b.p[j]);
+      if (cmp == 0)
+      {
+        ++i; ++j;
+      }
+      else if (cmp < 0)
+      {
+        if (k != i) p[k] = p[i];
+        ++i; ++k;
+      }
+      else
+        j++;
+    }
+    while (k++ < oldfence)
+    {
+      --count;
+      p.del_high();
+    }
+  }
+}
+
+void <T>OXPSet::operator &= (<T>OXPSet& b)
+{
+  if (b.count == 0)
+    clear();
+  else if (&b != this && count != 0)
+  {
+    int i = p.low();
+    int k = i;
+    int j = b.p.low();
+    int oldfence = p.fence();
+    for (;;)
+    {
+      if (i >= oldfence || j >= b.p.fence())
+        break;
+      int cmp = <T>CMP(p[i], b.p[j]);
+      if (cmp == 0)
+      {
+        if (k != i) p[k] = p[i];
+        ++i; ++k; ++j;
+      }
+      else if (cmp < 0)
+        ++i;
+      else
+        ++j;
+    }
+    while (k++ < oldfence)
+    {
+      --count;
+      p.del_high();
+    }
+  }
+}
+
+int <T>OXPSet::OK()
+{
+  int v = p.OK();
+  v &= count == p.length();
+  for (int i = p.low(); i < p.high(); ++i) v &= <T>CMP(p[i], p[i+1]) < 0;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/OXPSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/OXPSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/OXPSet.hP	(revision 18)
@@ -0,0 +1,102 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>OXPSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>OXPSet_h 1
+
+#include "<T>.Set.h"
+#include "<T>.XPlex.h"
+
+class <T>OXPSet : public <T>Set
+{
+protected:
+  <T>XPlex       p;
+
+public:
+                <T>OXPSet(int chunksize = DEFAULT_INITIAL_CAPACITY);
+                <T>OXPSet(const <T>OXPSet&);
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  inline int           contains(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item);
+
+  void          operator |= (<T>OXPSet& b);
+  void          operator -= (<T>OXPSet& b);
+  void          operator &= (<T>OXPSet& b);
+
+  int           operator == (<T>OXPSet& b);
+  int           operator != (<T>OXPSet& b);
+  int           operator <= (<T>OXPSet& b); 
+
+  int           OK();
+};
+
+
+inline <T>OXPSet::<T>OXPSet(int chunksize) 
+     : p(chunksize) { count = 0; }
+
+inline <T>OXPSet::<T>OXPSet(const <T>OXPSet& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>OXPSet::first()
+{
+  return p.first();
+}
+
+inline void <T>OXPSet::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>OXPSet::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline void <T>OXPSet::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>OXPSet::contains (<T&> item)
+{
+  return seek(item) != 0;
+}
+
+inline int <T>OXPSet::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+inline int <T>OXPSet::operator != (<T>OXPSet& b)
+{
+  return !(*this == b);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/PHPQ.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/PHPQ.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/PHPQ.ccP	(revision 18)
@@ -0,0 +1,339 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+    adapted for libg++ by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <limits.h>
+#include "<T>.PHPQ.h"
+
+//
+//	This defines a Pairing Heap structure
+//
+//	See ``The Pairing Heap: A New Form of Self-Adjusting Heap''
+//	Fredman, Segdewick et al,
+//	Algorithmica (1986) 1:111-129
+//
+//	In particular, this implements the pairing heap using the circular
+//	list.
+//
+//
+
+<T>PHPQ::<T>PHPQ(int sz)
+{
+  storage = 0;
+  root = 0;
+  count = 0;
+  size = 0;
+  prealloc(sz);
+}
+
+<T>PHPQ::<T>PHPQ(<T>PHPQ& a)
+{
+  storage = 0;
+  root  = 0;
+  count = 0;
+  size = 0;
+  prealloc(a.size);
+  for (Pix i = a.first(); i != 0; a.next(i)) enq(a(i));
+}
+
+
+void <T>PHPQ::prealloc(int newsize)
+{
+  ++newsize; // leave a spot for freelist
+  if (size != 0)
+  {
+    int news = size;
+    while (news <= newsize) news = (news * 3) / 2;
+    newsize = news;
+  }
+  // see if indices are OK
+  <T>PHPQNode test;
+  test.sibling = 0;
+  test.sibling = ~test.sibling;
+  if ((unsigned long)newsize > (unsigned long)(test.sibling))
+    error("storage size exceeds index range");
+
+  if (storage == 0)
+  {
+    storage = new <T>PHPQNode[size = newsize];
+    for (int i = 0; i < size; ++i) 
+    {
+      storage[i].sibling = i + 1;
+      storage[i].valid = 0;
+    }
+    storage[size-1].sibling = 0;
+  }
+  else
+  {
+    <T>PHPQNode* newstor = new <T>PHPQNode[newsize];
+    for (int i = 1; i < size; ++i)
+      newstor[i] = storage[i];
+    delete [] storage;
+    storage = newstor;
+    for (int i = size; i < newsize; ++i) 
+    {
+      storage[i].sibling = i + 1;
+      storage[i].valid = 0;
+    }
+    storage[newsize-1].sibling = 0;
+    storage[0].sibling = size;
+    size = newsize;
+  }
+}
+
+
+void <T>PHPQ::clear()
+{
+  for (int i = 0; i < size; ++i) 
+  {
+    storage[i].sibling = i + 1;
+    storage[i].valid = 0;
+  }
+  storage[size-1].sibling = 0;
+  root = 0;
+  count = 0;
+}
+
+Pix <T>PHPQ::enq(<T&> item)
+{
+  ++count;
+  if (storage[0].sibling == 0)
+    prealloc(count);
+
+  int cell = storage[0].sibling;
+  storage[0].sibling = storage[cell].sibling;
+  storage[cell].sibling = 0;
+  storage[cell].children = 0;
+  storage[cell].item = item;
+  storage[cell].valid = 1;
+  
+  if (root == 0) 
+  {
+    root = cell;
+    return Pix(root);
+  }
+  else 
+  {
+    int parent;
+    int child;
+    
+    if (<T>LE(storage[root].item, storage[cell].item))
+    {
+      parent = root; child = cell;
+    } 
+    else 
+    {
+      parent = cell; child = root;
+    }
+    int popsKid = storage[parent].children;
+    
+    if (popsKid == 0) 
+    {
+      storage[parent].children = child;
+      storage[child].sibling = child;
+    } 
+    else 
+    {
+      int temp = storage[popsKid].sibling;
+      storage[popsKid].sibling = child;
+      storage[child].sibling = temp;
+      storage[parent].children = child;
+    }
+    root = parent;
+    return Pix(cell);
+  }
+}
+
+//
+//	Item removal is the most complicated routine.
+//
+//	We remove the root (should there be one) and then select a new
+//	root. The siblings of the root are in a circular list. We continue
+//	to pair elements in this list until there is a single element.
+//	This element will be the new root.
+
+void <T>PHPQ::del_front()
+{
+  int valid = 0;
+  do 
+  {
+    if (root == 0) return;
+	if ((valid = storage[root].valid))
+      --count;
+    storage[root].valid = 0;
+	int child = storage[root].children;
+    storage[root].sibling = storage[0].sibling;
+    storage[0].sibling = root;
+
+	if (child == 0)
+    {
+      root = 0;
+      return;
+    }
+    else 
+    {
+      while(storage[child].sibling != child) 
+      {
+		// We have at least two kids, but we may only have
+		// two kids. So, oneChild != child, but it is possible
+		// that twoChild == child.
+        
+		int oneChild = storage[child].sibling;
+		int twoChild = storage[oneChild].sibling;
+
+		// Remove the two from the sibling list
+
+		storage[child].sibling = storage[twoChild].sibling;
+		storage[oneChild].sibling = 0;
+		storage[twoChild].sibling = 0;
+		
+        int bestChild;
+        int worstChild;
+    
+        if (<T>LE(storage[oneChild].item, storage[twoChild].item))
+        {
+          bestChild = oneChild; worstChild = twoChild;
+        } 
+        else 
+        {
+          bestChild = twoChild; worstChild = oneChild;
+        }
+        int popsKid = storage[bestChild].children;
+        
+        if (popsKid == 0) 
+        {
+          storage[bestChild].children = worstChild;
+          storage[worstChild].sibling = worstChild;
+        } 
+        else 
+        {
+          int temp = storage[popsKid].sibling;
+          storage[popsKid].sibling = worstChild;
+          storage[worstChild].sibling = temp;
+          storage[bestChild].children = worstChild;
+        }
+		if (twoChild == child) 
+        {
+          // We have reduced the two to one, so we'll be exiting.
+          child = bestChild;
+          storage[child].sibling = child;
+        } 
+        else 
+        {
+          // We've removed two siblings, now we need to insert
+          // the better of the two
+          storage[bestChild].sibling = storage[child].sibling;
+          storage[child].sibling = bestChild;
+          child = storage[bestChild].sibling;
+		}
+      }
+      root = child;
+	}
+  } while ( !valid );
+}
+
+void <T>PHPQ::del(Pix p) 
+{
+  if (p == 0) error("null Pix");
+  int i = int(p);
+  if (storage[i].valid)
+  {
+    if (i == root)
+      del_front();
+    else
+    {
+      storage[i].valid = 0;
+      --count;
+    }
+  }
+}
+
+
+Pix <T>PHPQ::seek(<T&> key)
+{
+  for (int i = 1; i < size; ++i)
+    if (storage[i].valid && <T>EQ(storage[i].item, key))
+      return Pix(i);
+  return 0;
+}
+
+Pix <T>PHPQ::first()
+{
+  for (int i = 1; i < size; ++i)
+    if (storage[i].valid)
+      return Pix(i);
+  return 0;
+}
+
+
+void <T>PHPQ::next(Pix& p)
+{
+  if (p == 0) return;
+  for (int i = int(p)+1; i < size; ++i)
+    if (storage[i].valid)
+    {
+      p = Pix(i); 
+      return;
+    }
+  p = 0;
+}
+
+int <T>PHPQ::OK()
+{
+  int v = storage != 0;
+  int n = 0;
+  for (int i = 0; i < size; ++i) if (storage[i].valid) ++n;
+  v &= n == count;
+  v &= check_sibling_list(root);
+  int ct = INT_MAX;
+  n = 0;
+  int f = storage[0].sibling;
+  while (f != 0 && ct-- > 0)
+  {
+    f = storage[f].sibling;
+    ++n;
+  }
+  v &= ct > 0;
+  v &= n <= size - count;
+  if (!v) error("invariant failure");
+  return v;
+}
+
+
+int <T>PHPQ::check_sibling_list(int t)
+{
+  if (t != 0)
+  {
+    int s = t;
+    long ct = LONG_MAX;      // Lots of chances to find self!
+    do 
+    {
+      if (storage[s].valid && !check_sibling_list(storage[s].children))
+        return 0;
+      s = storage[s].sibling;
+    } while (ct-- > 0 && s != t && s != 0);
+    if (ct <= 0) return 0;
+  }
+  return 1;
+}
+
+
Index: trunk/src/emx/include/Attic/cpp/gen/PHPQ.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/PHPQ.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/PHPQ.hP	(revision 18)
@@ -0,0 +1,108 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Dirk Grunwald (grunwald@cs.uiuc.edu)
+    adapted for libg++ by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef <T>PHPQ_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define <T>PHPQ_h 1
+
+#include "<T>.PQ.h"
+
+#ifndef <T>PHPQIndex
+#define <T>PHPQIndex unsigned short
+#endif
+
+struct <T>PHPQNode
+{
+  <T>PHPQIndex   sibling;
+  <T>PHPQIndex   children;
+  <T>            item;
+  char           valid;
+};
+
+
+class <T>PHPQ : public <T>PQ
+{
+  <T>PHPQNode*  storage;        // table -- freelist in storage[0].sibling
+  int           root;
+  int           size;
+
+  void          prealloc(int);
+  int           check_sibling_list(int);
+
+public:
+
+                <T>PHPQ(int sz = DEFAULT_INITIAL_CAPACITY);
+                <T>PHPQ(<T>PHPQ&);
+  inline               ~<T>PHPQ();
+
+  Pix           enq(<T&> item);
+  inline <T>           deq(); 
+
+  inline <T>&          front();
+  void          del_front();
+
+  inline int           contains(<T&> item);
+
+  void          clear(); 
+
+  Pix           first(); 
+  void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  void          del(Pix i);
+  Pix           seek(<T&> item);
+
+  int           OK();                    // rep invariant
+};
+
+
+inline <T>PHPQ::~<T>PHPQ()
+{
+  delete [] storage;
+}
+
+
+inline <T> <T>PHPQ::deq()
+{
+  if (count == 0) error("deq of empty PQ");
+  <T> x = storage[root].item;
+  del_front();
+  return x;
+}
+
+
+inline <T>& <T>PHPQ::front()
+{
+  if (count == 0) error("front of empty PQ");
+  return storage[root].item;
+}
+
+inline int <T>PHPQ::contains(<T&> item)
+{
+  return seek(item) != 0;
+}
+
+inline <T>& <T>PHPQ::operator() (Pix p)
+{
+  if (p == 0) error("null Pix");
+  return storage[int(p)].item;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/PQ.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/PQ.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/PQ.ccP	(revision 18)
@@ -0,0 +1,63 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <builtin.h>
+#include "<T>.PQ.h"
+
+
+
+<T> <T>PQ::deq()
+{
+  <T> x = front();
+  del_front();
+  return x;
+}
+
+Pix <T>PQ::seek(<T&> item)
+{
+  Pix i;
+  for (i = first(); i != 0 && !(<T>EQ((*this)(i), item)); next(i));
+  return i;
+}
+
+int <T>PQ::owns(Pix idx)
+{
+  if (idx == 0) return 0;
+  for (Pix i = first(); i; next(i)) if (i == idx) return 1;
+  return 0;
+}
+
+void <T>PQ::clear()
+{
+  while (count != 0) del_front();
+}
+
+int <T>PQ::contains (<T&> item)
+{
+  return seek(item) != 0;
+}
+
+
+void <T>PQ::error(const char* msg)
+{
+  (*lib_error_handler)("PQ", msg);
+}
+
Index: trunk/src/emx/include/Attic/cpp/gen/PQ.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/PQ.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/PQ.hP	(revision 18)
@@ -0,0 +1,78 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>PQ_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>PQ_h 1
+
+#include <Pix.h>
+#include "<T>.defs.h"
+
+class <T>PQ
+{
+protected:
+
+  int                   count;
+
+public:
+                        <T>PQ();
+  inline virtual              ~<T>PQ();
+
+  int                   length();                // current number of items
+  int                   empty();
+
+  virtual Pix           enq(<T&> item) = 0;      // add item; return Pix
+  virtual <T>           deq();                   // return & remove min
+
+  virtual <T>&          front() = 0;             // access min item
+  virtual void          del_front() = 0;         // delete min item
+
+  virtual int           contains(<T&> item);     // is item in PQ?
+
+  virtual void          clear();                 // delete all items
+
+  virtual Pix           first() = 0;             // Pix of first item or 0
+  virtual void          next(Pix& i) = 0;        // advance to next or 0
+  virtual <T>&          operator () (Pix i) = 0; // access item at i
+  virtual void          del(Pix i) = 0;          // delete item at i
+  virtual int           owns(Pix i);             // is i a valid Pix  ?
+  virtual Pix           seek(<T&> item);         // Pix of item
+
+  void                  error(const char* msg);
+  virtual int           OK() = 0;                // rep invariant
+};
+
+
+inline <T>PQ::<T>PQ() :count(0) {}
+
+inline <T>PQ::~<T>PQ() {}
+
+inline int <T>PQ::length()
+{
+  return count;
+}
+
+inline int <T>PQ::empty()
+{
+  return count == 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/PSList.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/PSList.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/PSList.hP	(revision 18)
@@ -0,0 +1,32 @@
+/*  : Light weight list: This will simply reuse code from a VoidP List, which 
+was genclassed from the SLList libg++ class. The classes generated from this file
+will all be derived classes from class VoidSLList or intSLList. Note that class SLList does not 
+offer all the functionality of List classes, such as sharing of sub-lists.
+However, no additional code is needed at all and no .cc file is generated. So it costs nothing
+to use these type-safe lists. Only member functions needing type casting are re-defined  */
+
+
+#ifndef _<T>SList_h
+#define _<T>SList_h 1
+
+#include "VoidP.SLList.h"
+#include "<T>.defs.h"
+
+class <T>SList : public VoidPSLList
+{
+public:
+  <T>SList() {}
+  <T>SList(<T>SList& a) : (a) {}
+  ~<T>SList() {}
+
+  <T>SList& operator = (<T>SList& a) {
+    return (<T>SList&) VoidPSLList::operator= (a); }
+
+  <T>& operator () (Pix p) { return (<T>&) (VoidPSLList::operator() (p)); }
+  <T>& front() { return (<T>&) VoidPSLList::front(); }
+  <T>& rear()  { return (<T>&) VoidPSLList::rear(); }
+  <T> remove_front() { return (<T>) VoidPSLList::remove_front(); }
+
+};
+
+#endif /* conditional include */
Index: trunk/src/emx/include/Attic/cpp/gen/PVec.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/PVec.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/PVec.hP	(revision 18)
@@ -0,0 +1,79 @@
+/*  : light weight Vector: This will simply reuse code from  */
+/* a VoidP Vec, which was genclassed from the Vec libg++ class.     */
+/* The classes generated from this file will all be derived classes */
+/* from class VoidVec or intVec.  No .cc file is generated.  So     */
+/* it costs nothing to use these type-safe Vectors. Only member     */
+/* functions needing type casting are re-defined.                   */
+/*  */
+
+#ifndef _<T>Vec_h
+#define _<T>Vec_h 1
+
+#include "VoidP.Vec.h"
+#include "<T>.defs.h"
+
+
+#ifndef _<T>_typedefs
+#define _<T>_typedefs 1
+typedef void (*<T>Procedure)(<T> );
+typedef <T>  (*<T>Mapper)(<T> );
+typedef <T>  (*<T>Combiner)(<T> , <T> );
+typedef int  (*<T>Predicate)(<T> );
+typedef int  (*<T>Comparator)(<T> , <T> );
+#endif
+
+class <T>Vec : public VoidPVec
+{
+protected:
+  <T>Vec(int l, <T>* d) : (l, (VoidP*) d) {};
+public:
+  <T>Vec() {};
+  <T>Vec(int l) : (l) {};
+  <T>Vec(int l, <T&> fill_value) : (l, fill_value) {};
+  <T>Vec(<T>Vec& v) : (v) {};
+  <T>Vec(VoidPVec& v) {fake_copy(v, s, len);}
+  ~<T>Vec() {};
+
+  <T>Vec& operator = (<T>Vec& a)
+           {return (<T>Vec&) VoidPVec::operator= (a);}
+  <T>Vec  at(int from, int n) {return (<T>Vec) VoidPVec::at(from, n);}
+
+  <T>&    operator [] (int n) {return (<T>&)VoidPVec::operator[] (n);}
+  <T>&    elem(int n) {return (<T>&)VoidPVec::elem(n);}
+
+  friend <T>Vec   concat(<T>Vec& a, <T>Vec& b);
+  friend <T>Vec   map(<T>Mapper f, <T>Vec & a);
+  friend <T>Vec   merge(<T>Vec & a, <T>Vec & b, <T>Comparator f);
+  friend <T>Vec   combine(<T>Combiner f, <T>Vec & a, <T>Vec & b);
+  friend <T>Vec   reverse(<T>Vec& a);
+
+  void sort(<T>Comparator f);
+  void apply(<T>Procedure f);
+  <T> reduce(<T>Combiner f, <T> base);
+};
+
+inline <T>Vec concat(<T>Vec& a, <T>Vec& b)
+{return (<T>Vec)concat((VoidPVec&)a, (VoidPVec&)b);}
+
+inline <T>Vec   map(<T>Mapper f, <T>Vec & a) {
+  return (<T>Vec)map((VoidPMapper)f, (VoidPVec&)a); }
+
+inline <T>Vec   merge(<T>Vec & a, <T>Vec & b, <T>Comparator f) {
+  return (<T>Vec)merge((VoidPVec&)a, (VoidPVec&)b, (VoidPComparator)f); }
+
+inline <T>Vec   combine(<T>Combiner f, <T>Vec & a, <T>Vec & b) {
+  return (<T>Vec)combine((VoidPCombiner)f, (VoidPVec&)a, (VoidPVec&)b); }
+
+inline <T>Vec reverse(<T>Vec& a) {
+  return (<T>Vec)reverse((VoidPVec&)a);}
+
+inline void <T>Vec::sort(<T>Comparator f) {
+  VoidPVec::sort((VoidPComparator) f); }
+
+inline void <T>Vec::apply(<T>Procedure f) {
+  VoidPVec::apply((VoidPProcedure) f); }
+
+inline <T> <T>Vec::reduce(<T>Combiner f, <T> base) {
+  return (<T>)VoidPVec::reduce((VoidPCombiner)f, base);}
+
+#endif /* conditional include */
Index: trunk/src/emx/include/Attic/cpp/gen/Plex.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Plex.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Plex.ccP	(revision 18)
@@ -0,0 +1,222 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include <builtin.h>
+#include "<T>.Plex.h"
+
+// IChunk support
+
+void <T>IChunk::error(const char* msg) const
+{
+  (*lib_error_handler)("<T>IChunk", msg);
+}
+
+void <T>IChunk::index_error() const
+{
+  error("attempt to use invalid index");
+}
+
+void <T>IChunk::empty_error() const
+{
+  error("invalid use of empty chunk");
+}
+
+void <T>IChunk::full_error() const
+{
+  error("attempt to extend chunk beyond bounds");
+}
+
+<T>IChunk:: ~<T>IChunk() {}
+
+<T>IChunk::<T>IChunk(<T>*     d,    
+                     int      baseidx,
+                     int      lowidx,
+                     int      fenceidx,
+                     int      topidx)
+{
+  if (d == 0 || baseidx > lowidx || lowidx > fenceidx || fenceidx > topidx)
+    error("inconsistent specification");
+  data = d;
+  base = baseidx;
+  low = lowidx;
+  fence = fenceidx;
+  top = topidx;
+  nxt = prv = this;
+}
+
+void <T>IChunk:: re_index(int lo)
+{
+  int delta = lo - low;
+  base += delta;
+  low += delta;
+  fence += delta;
+  top += delta;
+}
+
+
+void <T>IChunk::clear(int lo)
+{
+  int s = top - base;
+  low = base = fence = lo;
+  top = base + s;
+}
+
+void <T>IChunk::cleardown(int hi)
+{
+  int s = top - base;
+  low = top = fence = hi;
+  base = top - s;
+}
+
+int <T>IChunk:: OK() const
+{
+  int v = data != 0;             // have some data
+  v &= base <= low;              // ok, index-wise
+  v &= low <= fence;
+  v &= fence <= top;
+
+  v &=  nxt->prv == this;      // and links are OK
+  v &=  prv->nxt == this;
+  if (!v) error("invariant failure");
+  return(v);
+}
+
+
+// error handling
+
+
+void <T>Plex::error(const char* msg) const
+{
+  (*lib_error_handler)("Plex", msg);
+}
+
+void <T>Plex::index_error() const
+{
+  error("attempt to access invalid index");
+}
+
+void <T>Plex::empty_error() const
+{
+  error("attempted operation on empty plex");
+}
+
+void <T>Plex::full_error() const
+{
+  error("attempt to increase size of plex past limit");
+}
+
+// generic plex ops
+
+<T>Plex:: ~<T>Plex()
+{
+  invalidate();
+}  
+
+
+void <T>Plex::append (const <T>Plex& a)
+{
+  for (int i = a.low(); i < a.fence(); a.next(i)) add_high(a[i]);
+}
+
+void <T>Plex::prepend (const <T>Plex& a)
+{
+  for (int i = a.high(); i > a.ecnef(); a.prev(i)) add_low(a[i]);
+}
+
+void <T>Plex::reverse()
+{
+  <T> tmp;
+  int l = low();
+  int h = high();
+  while (l < h)
+  {
+    tmp = (*this)[l];
+    (*this)[l] = (*this)[h];
+    (*this)[h] = tmp;
+    next(l);
+    prev(h);
+  }
+}
+
+
+void <T>Plex::fill(const <T&> x)
+{
+  for (int i = lo; i < fnc; ++i) (*this)[i] = x;
+}
+
+void <T>Plex::fill(const <T&> x, int lo, int hi)
+{
+  for (int i = lo; i <= hi; ++i) (*this)[i] = x;
+}
+
+
+void <T>Plex::del_chunk(<T>IChunk* x)
+{
+  if (x != 0)
+  {
+    x->unlink();
+    <T>* data = (<T>*)(x->invalidate());
+    delete [] data;
+    delete x;
+  }
+}
+
+
+void <T>Plex::invalidate()
+{
+  <T>IChunk* t = hd;
+  if (t != 0)
+  {
+    <T>IChunk* tail = tl();
+    while (t != tail)
+    {
+      <T>IChunk* nxt = t->next();
+      del_chunk(t);
+      t = nxt;
+    } 
+    del_chunk(t);
+    hd = 0;
+  }
+}
+
+int <T>Plex::reset_low(int l)
+{
+  int old = lo;
+  int diff = l - lo;
+  if (diff != 0)
+  {
+    lo += diff;
+    fnc += diff;
+    <T>IChunk* t = hd;
+    do
+    {
+      t->re_index(t->low_index() + diff);
+      t = t->next();
+    } while (t != hd);
+  }
+  return old;
+}
+
+
+
+
Index: trunk/src/emx/include/Attic/cpp/gen/Plex.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Plex.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Plex.hP	(revision 18)
@@ -0,0 +1,494 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>Plex_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>Plex_h 1
+
+#include <std.h>
+#include <Pix.h>
+#include "<T>.defs.h"
+
+// Plexes are made out of <T>IChunks
+
+#include <stddef.h>
+
+class <T>IChunk
+{
+//public: // kludge until C++ `protected' policies settled
+protected:      
+
+  <T>*           data;           // data, from client
+
+  int            base;           // lowest possible index
+  int            low;            // lowest valid index
+  int            fence;          // highest valid index + 1
+  int            top;            // highest possible index + 1
+
+  <T>IChunk*     nxt;            // circular links
+  <T>IChunk*     prv;
+
+public:
+
+// constructors
+
+                 <T>IChunk(<T>*     d,       // ptr to array of elements
+                        int      base_idx, // initial indices
+                        int      low_idx,  
+                        int      fence_idx,
+                        int      top_idx);
+
+  virtual       ~<T>IChunk();
+
+// status reports
+
+  int            size() const;    // number of slots
+
+  inline virtual int    empty() const ;
+  inline virtual int    full() const ; 
+
+  int            can_grow_high () const ;  // there is space to add data
+  int            can_grow_low () const;        
+  
+  int            base_index() const;   // lowest possible index;
+  int            low_index() const;    // lowest actual index;
+  inline virtual int    first_index() const;  // lowest valid index or fence if none
+  inline virtual int    last_index() const;   // highest valid index or low-1 if none
+  int            fence_index() const;  // highest actual index + 1
+  int            top_index() const;    // highest possible index + 1
+
+// indexing conversion
+
+  int            possible_index(int i) const; // i between base and top
+  int            actual_index(int i) const;   // i between low and fence
+  inline virtual int    valid_index(int i) const;    // i not deleted (mainly for mchunks)
+
+  int            possible_pointer(const <T>* p) const; // same for ptr
+  int            actual_pointer(const <T>* p) const; 
+  inline virtual int    valid_pointer(const <T>* p) const; 
+
+  <T>*           pointer_to(int i) const ;   // pointer to data indexed by i
+                                      // caution: i is not checked for validity
+  int            index_of(const <T>* p) const; // index of data pointed to by p
+                                      // caution: p is not checked for validity
+
+  inline virtual int    succ(int idx) const;     // next valid index or fence if none
+  inline virtual int    pred(int idx) const;     // previous index or low - 1 if none
+
+  inline virtual <T>*   first_pointer() const;   // pointer to first valid pos or 0
+  inline virtual <T>*   last_pointer() const;    // pointer to first valid pos or 0
+  inline virtual <T>*   succ(<T>*  p) const;     // next pointer or 0
+  inline virtual <T>*   pred(<T>* p) const;     // previous pointer or 0
+
+// modification
+
+  inline virtual <T>*   grow_high ();      // return spot to add an element
+  inline virtual <T>*   grow_low ();  
+
+  inline virtual void   shrink_high ();    // logically delete top index
+  inline virtual void   shrink_low ();     
+
+  virtual void   clear(int lo);     // reset to empty ch with base = lo
+  virtual void   cleardown(int hi); // reset to empty ch with top = hi
+  void           re_index(int lo);  // re-index so lo is new low
+
+// chunk traversal
+
+  <T>IChunk*     next() const;
+  <T>IChunk*     prev() const;
+
+  void           link_to_prev(<T>IChunk* prev);
+  void           link_to_next(<T>IChunk* next);
+  void           unlink();
+
+// state checks
+
+  <T>*           invalidate();     // mark self as invalid; return data
+                                   // for possible deletion
+
+  virtual int    OK() const;             // representation invariant
+
+  void   error(const char*) const;
+  void   empty_error() const;
+  void   full_error() const;
+  void   index_error() const;
+};
+
+// <T>Plex is a partly `abstract' class: few of the virtuals
+// are implemented at the Plex level, only in the subclasses
+
+class <T>Plex
+{
+protected:      
+
+  <T>IChunk*       hd;          // a chunk holding the data
+  int              lo;          // lowest  index
+  int              fnc;         // highest index + 1
+  int              csize;       // size of the chunk
+
+  void             invalidate();              // mark so OK() is false
+  void             del_chunk(<T>IChunk*);        // delete a chunk
+
+  <T>IChunk*       tl() const;                // last chunk;
+  int              one_chunk() const;         // true if hd == tl()
+
+public:
+
+// constructors, etc.
+
+                    <T>Plex();                  // no-op
+
+  virtual           ~<T>Plex();
+
+  
+// Access functions 
+    
+  virtual <T>&      operator [] (int idx) = 0; // access by index;
+  virtual <T>&      operator () (Pix p) = 0;   // access by Pix;
+
+  virtual <T>&      high_element () = 0;      // access high element
+  virtual <T>&      low_element () = 0;       // access low element
+
+// read-only versions for const Plexes
+
+  virtual const <T>& operator [] (int idx) const = 0; // access by index;
+  virtual const <T>& operator () (Pix p) const = 0;   // access by Pix;
+
+  virtual const <T>& high_element () const = 0;      // access high element
+  virtual const <T>& low_element () const = 0;       // access low element
+
+
+// Index functions
+
+  virtual int       valid (int idx) const = 0;      // idx is an OK index
+
+  virtual int       low() const = 0;         // lowest index or fence if none
+  virtual int       high() const = 0;        // highest index or low-1 if none
+
+  int               ecnef() const;         // low limit index (low-1)
+  int               fence() const;         // high limit index (high+1)
+
+  virtual void      prev(int& idx) const= 0; // set idx to preceding index
+                                          // caution: pred may be out of bounds
+
+  virtual void      next(int& idx) const = 0;       // set to next index
+                                          // caution: succ may be out of bounds
+
+  virtual Pix       first() const = 0;        // Pix to low element or 0
+  virtual Pix       last() const = 0;         // Pix to high element or 0
+  virtual void      prev(Pix& pix) const = 0;  // preceding pix or 0
+  virtual void      next(Pix& pix) const = 0;  // next pix or 0
+  virtual int       owns(Pix p) const = 0;     // p is an OK Pix
+
+// index<->Pix 
+
+  virtual int       Pix_to_index(Pix p) const = 0;   // get index via Pix
+  virtual Pix       index_to_Pix(int idx) const = 0; // Pix via index
+
+// Growth
+
+  virtual int       add_high(const <T&> elem) =0;// add new element at high end
+                                                // return new high
+
+  virtual int       add_low(const <T&> elem) = 0;   // add new low element,
+                                                // return new low
+
+// Shrinkage
+
+  virtual int       del_high() = 0;           // remove the element at high end
+                                          // return new high
+  virtual int       del_low() = 0;        // delete low element, return new lo
+
+                                          // caution: del_low/high
+                                          // does not necessarily 
+                                          // immediately call <T>::~<T>
+
+
+// operations on multiple elements
+
+  virtual void      fill(const <T&> x);          // set all elements = x
+  virtual void      fill(const <T&> x, int from, int to); // fill from to to
+  virtual void      clear() = 0;                // reset to zero-sized Plex
+  virtual int       reset_low(int newlow); // change low index,return old
+  virtual void      reverse();                   // reverse in-place
+  virtual void      append(const <T>Plex& a);    // concatenate a copy
+  virtual void      prepend(const <T>Plex& a);   // prepend a copy
+
+// status
+
+  virtual int       can_add_high() const = 0;
+  virtual int       can_add_low() const = 0;
+  
+  int               length () const;       // number of slots
+
+  int               empty () const;        // is the plex empty?
+  virtual int       full() const = 0;      // it it full?
+
+  int               chunk_size() const;    // report chunk size;
+
+  virtual int       OK() const = 0;        // representation invariant
+
+  void		    error(const char* msg) const;
+  void		    index_error() const;
+  void		    empty_error() const;
+  void		    full_error() const;
+};
+
+
+// <T>IChunk ops
+
+inline int <T>IChunk:: size() const
+{
+  return top - base;
+}
+
+
+inline int <T>IChunk:: base_index() const
+{
+  return base;
+}
+
+inline  int <T>IChunk:: low_index() const
+{
+  return low;
+}
+
+inline  int  <T>IChunk:: fence_index() const
+{
+  return fence;
+}
+
+inline  int  <T>IChunk:: top_index() const
+{
+  return top;
+}
+
+inline  <T>* <T>IChunk:: pointer_to(int i) const
+{
+  return &(data[i-base]);
+}
+
+inline  int  <T>IChunk:: index_of(const <T>* p) const
+{
+  return ((int)p - (int)data) / sizeof(<T>) + base;
+}
+
+inline  int  <T>IChunk:: possible_index(int i) const
+{
+  return i >= base && i < top;
+}
+
+inline  int  <T>IChunk:: possible_pointer(const <T>* p) const
+{
+  return p >= data && p < &(data[top-base]);
+}
+
+inline  int  <T>IChunk:: actual_index(int i) const
+{
+  return i >= low && i < fence;
+}
+
+inline  int  <T>IChunk:: actual_pointer(const <T>* p) const
+{
+  return p >= data && p < &(data[fence-base]);
+}
+
+inline  int  <T>IChunk:: can_grow_high () const
+{
+  return fence < top;
+}
+
+inline  int  <T>IChunk:: can_grow_low () const
+{
+  return base < low;
+}
+
+inline  <T>* <T>IChunk:: invalidate()
+{
+  <T>* p = data;
+  data = 0;
+  return p;
+}
+
+
+inline <T>IChunk* <T>IChunk::prev() const
+{
+  return prv;
+}
+
+inline <T>IChunk* <T>IChunk::next() const
+{
+  return nxt;
+}
+
+inline void <T>IChunk::link_to_prev(<T>IChunk* prev)
+{
+  nxt = prev->nxt;
+  prv = prev;
+  nxt->prv = this;
+  prv->nxt = this;
+}
+
+inline void <T>IChunk::link_to_next(<T>IChunk* next)
+{
+  prv = next->prv;
+  nxt = next;
+  nxt->prv = this;
+  prv->nxt = this;
+}
+
+inline void <T>IChunk::unlink()
+{
+  <T>IChunk* n = nxt;
+  <T>IChunk* p = prv;
+  n->prv = p;
+  p->nxt = n;
+  prv = nxt = this;
+}
+
+inline  int <T>IChunk:: empty() const
+{
+  return low == fence;
+}
+
+inline  int  <T>IChunk:: full() const
+{
+  return top - base == fence - low;
+}
+
+inline int <T>IChunk:: first_index() const
+{
+  return (low == fence)? fence : low;
+}
+
+inline int <T>IChunk:: last_index() const
+{
+  return (low == fence)? low - 1 : fence - 1;
+}
+
+inline  int  <T>IChunk:: succ(int i) const
+{
+  return (i < low) ? low : i + 1;
+}
+
+inline  int  <T>IChunk:: pred(int i) const
+{
+  return (i > fence) ? (fence - 1) : i - 1;
+}
+
+inline  int  <T>IChunk:: valid_index(int i) const
+{
+  return i >= low && i < fence;
+}
+
+inline  int  <T>IChunk:: valid_pointer(const <T>* p) const
+{
+  return p >= &(data[low - base]) && p < &(data[fence - base]);
+}
+
+inline  <T>* <T>IChunk:: grow_high ()
+{
+  if (!can_grow_high()) full_error();
+  return &(data[fence++ - base]);
+}
+
+inline  <T>* <T>IChunk:: grow_low ()
+{
+  if (!can_grow_low()) full_error();
+  return &(data[--low - base]);
+}
+
+inline  void <T>IChunk:: shrink_high ()
+{
+  if (empty()) empty_error();
+  --fence;
+}
+
+inline  void <T>IChunk:: shrink_low ()
+{
+  if (empty()) empty_error();
+  ++low;
+}
+
+inline <T>* <T>IChunk::first_pointer() const
+{
+  return (low == fence)? 0 : &(data[low - base]);
+}
+
+inline <T>* <T>IChunk::last_pointer() const
+{
+  return (low == fence)? 0 : &(data[fence - base - 1]);
+}
+
+inline <T>* <T>IChunk::succ(<T>* p) const
+{
+  return ((p+1) <  &(data[low - base]) || (p+1) >= &(data[fence - base])) ? 
+    0 : (p+1);
+}
+
+inline <T>* <T>IChunk::pred(<T>* p) const
+{
+  return ((p-1) <  &(data[low - base]) || (p-1) >= &(data[fence - base])) ? 
+    0 : (p-1);
+}
+
+
+// generic Plex operations
+
+inline <T>Plex::<T>Plex() {}
+
+inline int <T>Plex::chunk_size() const
+{
+  return csize;
+}
+
+inline  int <T>Plex::ecnef () const
+{
+  return lo - 1;
+}
+
+
+inline  int <T>Plex::fence () const
+{
+  return fnc;
+}
+
+inline int <T>Plex::length () const
+{
+  return fnc - lo;
+}
+
+inline  int <T>Plex::empty () const
+{
+  return fnc == lo;
+}
+
+inline <T>IChunk* <T>Plex::tl() const
+{
+  return hd->prev();
+}
+
+inline int <T>Plex::one_chunk() const
+{
+  return hd == hd->prev();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/Queue.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Queue.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Queue.ccP	(revision 18)
@@ -0,0 +1,14 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.Queue.h"
+
+<T>Queue::~<T>Queue() {}
+
+
+// error handling
+
+void <T>Queue::error(const char* msg)
+{
+  (*lib_error_handler)("Queue", msg);
+}
Index: trunk/src/emx/include/Attic/cpp/gen/Queue.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Queue.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Queue.hP	(revision 18)
@@ -0,0 +1,51 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>Queue_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>Queue_h
+
+#include <builtin.h>
+
+#include "<T>.defs.h"
+
+class <T>Queue
+{
+public:
+                        <T>Queue() { }
+  virtual              ~<T>Queue();
+
+  virtual void          enq(<T&> item) = 0;
+  virtual <T>           deq() = 0;
+  virtual <T>&          front() = 0;
+  virtual void          del_front() = 0;
+
+  virtual void          clear() = 0;
+  virtual int           empty() = 0;
+  virtual int           full() = 0;
+  virtual int           length() = 0;
+
+  void                  error(const char*);
+  
+  virtual int           OK() = 0;
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/RAVLMap.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/RAVLMap.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/RAVLMap.ccP	(revision 18)
@@ -0,0 +1,690 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.<C>.RAVLMap.h"
+
+
+/*
+ constants & inlines for maintaining balance & thread status in tree nodes
+*/
+
+#define AVLBALANCEMASK    3
+#define AVLBALANCED       0
+#define AVLLEFTHEAVY      1
+#define AVLRIGHTHEAVY     2
+
+#define LTHREADBIT        4
+#define RTHREADBIT        8
+
+
+static inline int bf(<T><C>RAVLNode* t)
+{
+  return t->stat & AVLBALANCEMASK;
+}
+
+static inline void set_bf(<T><C>RAVLNode* t, int b)
+{
+  t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK);
+}
+
+
+static inline int rthread(<T><C>RAVLNode* t)
+{
+  return t->stat & RTHREADBIT;
+}
+
+static inline void set_rthread(<T><C>RAVLNode* t, int b)
+{
+  if (b)
+    t->stat |= RTHREADBIT;
+  else
+    t->stat &= ~RTHREADBIT;
+}
+
+static inline int lthread(<T><C>RAVLNode* t)
+{
+  return t->stat & LTHREADBIT;
+}
+
+static inline void set_lthread(<T><C>RAVLNode* t, int b)
+{
+  if (b)
+    t->stat |= LTHREADBIT;
+  else
+    t->stat &= ~LTHREADBIT;
+}
+
+/*
+ traversal primitives
+*/
+
+
+<T><C>RAVLNode* <T><C>RAVLMap::leftmost()
+{
+  <T><C>RAVLNode* t = root;
+  if (t != 0) while (t->lt != 0) t = t->lt;
+  return t;
+}
+
+<T><C>RAVLNode* <T><C>RAVLMap::rightmost()
+{
+  <T><C>RAVLNode* t = root;
+  if (t != 0) while (t->rt != 0) t = t->rt;
+  return t;
+}
+
+<T><C>RAVLNode* <T><C>RAVLMap::succ(<T><C>RAVLNode* t)
+{
+  <T><C>RAVLNode* r = t->rt;
+  if (!rthread(t)) while (!lthread(r)) r = r->lt;
+  return r;
+}
+
+<T><C>RAVLNode* <T><C>RAVLMap::pred(<T><C>RAVLNode* t)
+{
+  <T><C>RAVLNode* l = t->lt;
+  if (!lthread(t)) while (!rthread(l)) l = l->rt;
+  return l;
+}
+
+
+Pix <T><C>RAVLMap::seek(<T&> key)
+{
+  <T><C>RAVLNode* t = root;
+  if (t == 0)
+    return 0;
+  for (;;)
+  {
+    int cmp = <T>CMP(key, t->item);
+    if (cmp == 0)
+      return Pix(t);
+    else if (cmp < 0)
+    {
+      if (lthread(t))
+        return 0;
+      else
+        t = t->lt;
+    }
+    else if (rthread(t))
+      return 0;
+    else
+      t = t->rt;
+  }
+}
+
+
+int <T><C>RAVLMap::rankof(<T&> key)
+{
+  int r;
+  <T><C>RAVLNode* t = root;
+  if (t == 0)
+    return 0;
+  for (r=t->rank; t != 0; r+=t->rank)
+  {
+    int cmp = <T>CMP(key, t->item);
+    if (cmp == 0)
+      return r;
+    else if (cmp < 0)
+    {
+      if (lthread(t))
+        return 0;
+      else
+      {
+        r -= t->rank;  
+        t = t->lt;
+      }
+    }
+    else if (rthread(t))
+      return 0;
+    else
+    {
+      t = t->rt;
+    }
+  }
+  return 0;
+}
+
+Pix <T><C>RAVLMap::ranktoPix(int i)
+{
+  int r;
+  <T><C>RAVLNode* t = root;
+
+  if ((i<1)||(i>count))
+    return 0;
+  for (r=t->rank; r!=i; r+=t->rank)
+  {
+    if (r>i)
+    {
+      r -= t->rank;
+      t = t->lt;
+    }
+    else
+      t = t->rt;
+  }
+  return Pix(t);
+}
+
+/*
+ The combination of threads and AVL bits make adding & deleting
+ interesting, but very awkward.
+
+ We use the following statics to avoid passing them around recursively
+*/
+
+static int _need_rebalancing;   // to send back balance info from rec. calls
+static <T>*   _target_item;     // add/del_item target
+static <T><C>RAVLNode* _found_node; // returned added/deleted node
+static int    _already_found;   // for deletion subcases
+static int    _rank_changed;    // for rank computation
+
+
+void <T><C>RAVLMap:: _add(<T><C>RAVLNode*& t)
+{
+  int cmp = <T>CMP(*_target_item, t->item);
+  if (cmp == 0)
+  {
+    _found_node = t;
+    return;
+  }
+  else if (cmp < 0)
+  {
+    if (lthread(t))
+    {
+      ++count;
+      _found_node = new <T><C>RAVLNode(*_target_item, def);
+      set_lthread(_found_node, 1);
+      set_rthread(_found_node, 1);
+      _found_node->lt = t->lt;
+      _found_node->rt = t;
+      t->lt = _found_node;
+      set_lthread(t, 0);
+      _need_rebalancing = 1;
+      _rank_changed = 1;
+    }
+    else
+      _add(t->lt);
+    if (_rank_changed) ++t->rank;
+    if (_need_rebalancing)
+    {
+      switch(bf(t))
+      {
+      case AVLRIGHTHEAVY:
+        set_bf(t, AVLBALANCED);
+        _need_rebalancing = 0;
+        return;
+      case AVLBALANCED:
+        set_bf(t, AVLLEFTHEAVY);
+        return;
+      case AVLLEFTHEAVY:
+	{
+        <T><C>RAVLNode* l = t->lt;
+        if (bf(l) == AVLLEFTHEAVY)
+        {
+	  t->rank -= l->rank;
+          if (rthread(l))
+            t->lt = l;
+          else
+            t->lt = l->rt;
+          set_lthread(t, rthread(l));
+          l->rt = t;
+          set_rthread(l, 0);
+          set_bf(t, AVLBALANCED);
+          set_bf(l, AVLBALANCED);
+          t = l;
+          _need_rebalancing = 0;
+        }
+        else
+        {
+          <T><C>RAVLNode* r = l->rt;
+	  r->rank += l->rank;
+	  t->rank -= r->rank;
+          set_rthread(l, lthread(r));
+          if (lthread(r))
+            l->rt = r;
+          else
+            l->rt = r->lt;
+          r->lt = l;
+          set_lthread(r, 0);
+          set_lthread(t, rthread(r));
+          if (rthread(r))
+            t->lt = r;
+          else
+            t->lt = r->rt;
+          r->rt = t;
+          set_rthread(r, 0);
+          if (bf(r) == AVLLEFTHEAVY)
+            set_bf(t, AVLRIGHTHEAVY);
+          else
+            set_bf(t, AVLBALANCED);
+          if (bf(r) == AVLRIGHTHEAVY)
+            set_bf(l, AVLLEFTHEAVY);
+          else
+            set_bf(l, AVLBALANCED);
+          set_bf(r, AVLBALANCED);
+          t = r;
+          _need_rebalancing = 0;
+          return;
+        }
+	}
+      }
+    }
+  }
+  else
+  {
+    if (rthread(t))
+    {
+      ++count;
+      _found_node = new <T><C>RAVLNode(*_target_item, def);
+      set_rthread(t, 0);
+      set_lthread(_found_node, 1);
+      set_rthread(_found_node, 1);
+      _found_node->lt = t;
+      _found_node->rt = t->rt;
+      t->rt = _found_node;
+      _need_rebalancing = 1;
+      _rank_changed = 1;
+    }
+    else
+      _add(t->rt);
+    if (_need_rebalancing)
+    {
+      switch(bf(t))
+      {
+      case AVLLEFTHEAVY:
+        set_bf(t, AVLBALANCED);
+        _need_rebalancing = 0;
+        return;
+      case AVLBALANCED:
+        set_bf(t, AVLRIGHTHEAVY);
+        return;
+      case AVLRIGHTHEAVY:
+	{
+        <T><C>RAVLNode* r = t->rt;
+        if (bf(r) == AVLRIGHTHEAVY)
+        {
+	  r->rank += t->rank;
+          if (lthread(r))
+            t->rt = r;
+          else
+            t->rt = r->lt;
+          set_rthread(t, lthread(r));
+          r->lt = t;
+          set_lthread(r, 0);
+          set_bf(t, AVLBALANCED);
+          set_bf(r, AVLBALANCED);
+          t = r;
+          _need_rebalancing = 0;
+        }
+        else
+        {
+          <T><C>RAVLNode* l = r->lt;
+	  r->rank -= l->rank;
+	  l->rank += t->rank;
+          set_lthread(r, rthread(l));
+          if (rthread(l))
+            r->lt = l;
+          else
+            r->lt = l->rt;
+          l->rt = r;
+          set_rthread(l, 0);
+          set_rthread(t, lthread(l));
+          if (lthread(l))
+            t->rt = l;
+          else
+            t->rt = l->lt;
+          l->lt = t;
+          set_lthread(l, 0);
+          if (bf(l) == AVLRIGHTHEAVY)
+            set_bf(t, AVLLEFTHEAVY);
+          else
+            set_bf(t, AVLBALANCED);
+          if (bf(l) == AVLLEFTHEAVY)
+            set_bf(r, AVLRIGHTHEAVY);
+          else
+            set_bf(r, AVLBALANCED);
+          set_bf(l, AVLBALANCED);
+          t = l;
+          _need_rebalancing = 0;
+          return;
+        }
+	}
+      }
+    }
+  }
+}
+
+    
+<C>& <T><C>RAVLMap::operator [] (<T&> item)
+{
+  if (root == 0)
+  {
+    ++count;
+    root = new <T><C>RAVLNode(item, def);
+    set_rthread(root, 1);
+    set_lthread(root, 1);
+    return root->cont;
+  }
+  else
+  {
+    _target_item = &item;
+    _need_rebalancing = 0;
+    _rank_changed = 0;
+    _add(root);
+    return _found_node->cont;
+  }
+}
+
+
+void <T><C>RAVLMap::_del(<T><C>RAVLNode* par, <T><C>RAVLNode*& t)
+{
+  int comp;
+  if (_already_found)
+  {
+    if (rthread(t))
+      comp = 0;
+    else
+      comp = 1;
+  }
+  else 
+    comp = <T>CMP(*_target_item, t->item);
+  if (comp == 0)
+  {
+    if (lthread(t) && rthread(t))
+    {
+      _found_node = t;
+      if (t == par->lt)
+      {
+        set_lthread(par, 1);
+        par->lt = t->lt;
+      }
+      else
+      {
+        set_rthread(par, 1);
+        par->rt = t->rt;
+      }
+      _need_rebalancing = 1;
+      _rank_changed = 1;
+      return;
+    }
+    else if (lthread(t))
+    {
+      _found_node = t;
+      <T><C>RAVLNode* s = succ(t);
+      if (s != 0 && lthread(s))
+        s->lt = t->lt;
+      t = t->rt;
+      _need_rebalancing = 1;
+      _rank_changed = 1;
+      return;
+    }
+    else if (rthread(t))
+    {
+      _found_node = t;
+      <T><C>RAVLNode* p = pred(t);
+      if (p != 0 && rthread(p))
+        p->rt = t->rt;
+      t = t->lt;
+      _need_rebalancing = 1;
+      _rank_changed = 1;
+      return;
+    }
+    else                        // replace item & find someone deletable
+    {
+      <T><C>RAVLNode* p = pred(t);
+      t->item = p->item;
+      t->cont = p->cont;
+      _already_found = 1;
+      comp = -1;                // fall through below to left
+    }
+  }
+
+  if (comp < 0)
+  {
+    if (lthread(t))
+      return;
+    _del(t, t->lt);
+    if (_rank_changed) --t->rank;
+    if (!_need_rebalancing)
+      return;
+    switch (bf(t))
+    {
+    case AVLLEFTHEAVY:
+      set_bf(t, AVLBALANCED);
+      return;
+    case AVLBALANCED:
+      set_bf(t, AVLRIGHTHEAVY);
+      _need_rebalancing = 0;
+      return;
+    case AVLRIGHTHEAVY:
+      {
+      <T><C>RAVLNode* r = t->rt;
+      switch (bf(r))
+      {
+      case AVLBALANCED:
+	r->rank += t->rank;
+        if (lthread(r))
+          t->rt = r;
+        else
+          t->rt = r->lt;
+        set_rthread(t, lthread(r));
+        r->lt = t;
+        set_lthread(r, 0);
+        set_bf(t, AVLRIGHTHEAVY);
+        set_bf(r, AVLLEFTHEAVY);
+        _need_rebalancing = 0;
+        t = r;
+        return;
+      case AVLRIGHTHEAVY:
+	r->rank += t->rank;
+        if (lthread(r))
+          t->rt = r;
+        else
+          t->rt = r->lt;
+        set_rthread(t, lthread(r));
+        r->lt = t;
+        set_lthread(r, 0);
+        set_bf(t, AVLBALANCED);
+        set_bf(r, AVLBALANCED);
+        t = r;
+        return;
+      case AVLLEFTHEAVY:
+	{
+        <T><C>RAVLNode* l = r->lt;
+	r->rank -= l->rank;
+	l->rank += t->rank;
+        set_lthread(r, rthread(l));
+        if (rthread(l))
+          r->lt = l;
+        else
+          r->lt = l->rt;
+        l->rt = r;
+        set_rthread(l, 0);
+        set_rthread(t, lthread(l));
+        if (lthread(l))
+          t->rt = l;
+        else
+          t->rt = l->lt;
+        l->lt = t;
+        set_lthread(l, 0);
+        if (bf(l) == AVLRIGHTHEAVY)
+          set_bf(t, AVLLEFTHEAVY);
+        else
+          set_bf(t, AVLBALANCED);
+        if (bf(l) == AVLLEFTHEAVY)
+          set_bf(r, AVLRIGHTHEAVY);
+        else
+          set_bf(r, AVLBALANCED);
+        set_bf(l, AVLBALANCED);
+        t = l;
+        return;
+	}
+      }
+    }
+    }
+  }
+  else
+  {
+    if (rthread(t))
+      return;
+    _del(t, t->rt);
+    if (!_need_rebalancing)
+      return;
+    switch (bf(t))
+    {
+    case AVLRIGHTHEAVY:
+      set_bf(t, AVLBALANCED);
+      return;
+    case AVLBALANCED:
+      set_bf(t, AVLLEFTHEAVY);
+      _need_rebalancing = 0;
+      return;
+    case AVLLEFTHEAVY:
+      {
+      <T><C>RAVLNode* l = t->lt;
+      switch (bf(l))
+      {
+      case AVLBALANCED:
+	t->rank -= l->rank;
+        if (rthread(l))
+          t->lt = l;
+        else
+          t->lt = l->rt;
+        set_lthread(t, rthread(l));
+        l->rt = t;
+        set_rthread(l, 0);
+        set_bf(t, AVLLEFTHEAVY);
+        set_bf(l, AVLRIGHTHEAVY);
+        _need_rebalancing = 0;
+        t = l;
+        return;
+      case AVLLEFTHEAVY:
+	t->rank -= l->rank;
+        if (rthread(l))
+          t->lt = l;
+        else
+          t->lt = l->rt;
+        set_lthread(t, rthread(l));
+        l->rt = t;
+        set_rthread(l, 0);
+        set_bf(t, AVLBALANCED);
+        set_bf(l, AVLBALANCED);
+        t = l;
+        return;
+      case AVLRIGHTHEAVY:
+	{
+        <T><C>RAVLNode* r = l->rt;
+	r->rank += l->rank;
+	t->rank -= r->rank;
+        set_rthread(l, lthread(r));
+        if (lthread(r))
+          l->rt = r;
+        else
+          l->rt = r->lt;
+        r->lt = l;
+        set_lthread(r, 0);
+        set_lthread(t, rthread(r));
+        if (rthread(r))
+          t->lt = r;
+        else
+          t->lt = r->rt;
+        r->rt = t;
+        set_rthread(r, 0);
+        if (bf(r) == AVLLEFTHEAVY)
+          set_bf(t, AVLRIGHTHEAVY);
+        else
+          set_bf(t, AVLBALANCED);
+        if (bf(r) == AVLRIGHTHEAVY)
+          set_bf(l, AVLLEFTHEAVY);
+        else
+          set_bf(l, AVLBALANCED);
+        set_bf(r, AVLBALANCED);
+        t = r;
+        return;
+	}
+      }
+      }
+    }
+  }
+}
+
+
+void <T><C>RAVLMap::del(<T&> item)
+{
+  if (root == 0) return;
+  _need_rebalancing = 0;
+  _already_found = 0;
+  _found_node = 0;
+  _rank_changed = 0;
+  _target_item = &item;
+  _del(root, root);
+  if (_found_node)
+  {
+    delete(_found_node);
+    if (--count == 0)
+      root = 0;
+  }
+}
+
+void <T><C>RAVLMap::_kill(<T><C>RAVLNode* t)
+{
+  if (t != 0)
+  {
+    if (!lthread(t)) _kill(t->lt);
+    if (!rthread(t)) _kill(t->rt);
+    delete t;
+  }
+}
+
+
+<T><C>RAVLMap::<T><C>RAVLMap(<T><C>RAVLMap& b) :<T><C>Map(b.def)
+{
+  root = 0;
+  count = 0;
+  for (Pix i = b.first(); i != 0; b.next(i)) 
+    (*this)[b.key(i)] = b.contents(i);
+}
+
+
+int <T><C>RAVLMap::OK()
+{
+  int v = 1;
+  if (root == 0) 
+    v = count == 0;
+  else
+  {
+    int n = 1;
+    <T><C>RAVLNode* trail = leftmost();
+    v &= rankof(trail->item) == n;
+    <T><C>RAVLNode* t = succ(trail);
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      v &= rankof(t->item) == n;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/RAVLMap.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/RAVLMap.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/RAVLMap.hP	(revision 18)
@@ -0,0 +1,147 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu) 
+    ranking code from Paul Anderson (paul%lfcs.ed.ac.uk)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T><C>RAVLMap_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T><C>RAVLMap_h 1
+
+#include "<T>.<C>.Map.h"
+
+struct <T><C>RAVLNode
+{
+  <T><C>RAVLNode*      lt;
+  <T><C>RAVLNode*      rt;
+  <T>                 item;
+  <C>                 cont;
+  int                 rank;
+  char                stat;
+                      <T><C>RAVLNode(<T&> h, <C&> c, 
+                           <T><C>RAVLNode* l=0, <T><C>RAVLNode* r=0, int k=1);
+                      ~<T><C>RAVLNode();
+};
+
+inline <T><C>RAVLNode::<T><C>RAVLNode(<T&> h, <C&> c, 
+                           <T><C>RAVLNode* l, <T><C>RAVLNode* r, int k)
+     :lt(l), rt(r), item(h), cont(c), rank(k), stat(0) {}
+
+inline <T><C>RAVLNode::~<T><C>RAVLNode() {}
+
+typedef <T><C>RAVLNode* <T><C>RAVLNodePtr;
+
+
+class <T><C>RAVLMap : public <T><C>Map
+{
+protected:
+  <T><C>RAVLNode*   root;
+
+  <T><C>RAVLNode*   leftmost();
+  <T><C>RAVLNode*   rightmost();
+  <T><C>RAVLNode*   pred(<T><C>RAVLNode* t);
+  <T><C>RAVLNode*   succ(<T><C>RAVLNode* t);
+  void            _kill(<T><C>RAVLNode* t);
+  void            _add(<T><C>RAVLNode*& t);
+  void            _del(<T><C>RAVLNode* p, <T><C>RAVLNode*& t);
+
+public:
+                <T><C>RAVLMap(<C&> dflt);
+                <T><C>RAVLMap(<T><C>RAVLMap& a);
+  inline               ~<T><C>RAVLMap();
+
+  <C>&          operator [] (<T&> key);
+
+  void          del(<T&> key);
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          key(Pix i);
+  inline <C>&          contents(Pix i);
+
+  Pix           seek(<T&> key);
+  inline int           contains(<T&> key);
+
+  Pix           ranktoPix(int i);
+  int           rankof(<T&> key);
+
+  inline void          clear(); 
+
+  Pix           last();
+  void          prev(Pix& i);
+
+  int           OK();
+};
+
+inline <T><C>RAVLMap::~<T><C>RAVLMap()
+{
+  _kill(root);
+}
+
+inline <T><C>RAVLMap::<T><C>RAVLMap(<C&> dflt) :<T><C>Map(dflt)
+{
+  root = 0;
+}
+
+
+inline Pix <T><C>RAVLMap::first()
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T><C>RAVLMap::last()
+{
+  return Pix(rightmost());
+}
+
+inline void <T><C>RAVLMap::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T><C>RAVLNode*)i));
+}
+
+inline void <T><C>RAVLMap::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T><C>RAVLNode*)i));
+}
+
+inline <T>& <T><C>RAVLMap::key(Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T><C>RAVLNode*)i)->item;
+}
+
+inline <C>& <T><C>RAVLMap::contents(Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T><C>RAVLNode*)i)->cont;
+}
+
+inline void <T><C>RAVLMap::clear()
+{
+  _kill(root);
+  count = 0;
+  root = 0;
+}
+
+inline int <T><C>RAVLMap::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/RPlex.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/RPlex.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/RPlex.ccP	(revision 18)
@@ -0,0 +1,477 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.RPlex.h"
+
+typedef <T>IChunk* _<T>IChunk_ptr;
+
+<T>RPlex:: <T>RPlex()
+{
+  lo = fnc = 0;
+  csize = DEFAULT_INITIAL_CAPACITY;
+  <T>* data = new <T>[csize];
+  set_cache(new <T>IChunk(data,  lo, lo, fnc, lo+csize));
+  hd = ch;
+  maxch = MIN_NCHUNKS;
+  lch = maxch / 2;
+  fch = lch + 1;
+  base = ch->base_index() - lch * csize;
+  chunks = new _<T>IChunk_ptr[maxch];
+  chunks[lch] = ch;
+}
+
+<T>RPlex:: <T>RPlex(int chunksize)
+{
+  if (chunksize == 0) error("invalid constructor specification");
+  lo = fnc = 0;
+  if (chunksize > 0)
+  {
+    csize = chunksize;
+    <T>* data = new <T>[csize];
+    set_cache(new <T>IChunk(data,  lo, lo, fnc, csize+lo));
+    hd = ch;
+  }
+  else
+  {
+    csize = -chunksize;
+    <T>* data = new <T>[csize];
+    set_cache(new <T>IChunk(data,  chunksize+lo, lo, fnc, fnc));
+    hd = ch;
+  }
+  maxch = MIN_NCHUNKS;
+  lch = maxch / 2;
+  fch = lch + 1;
+  base = ch->base_index() - lch * csize;
+  chunks = new _<T>IChunk_ptr[maxch];
+  chunks[lch] = ch;
+}
+
+
+<T>RPlex:: <T>RPlex(int l, int chunksize)
+{
+  if (chunksize == 0) error("invalid constructor specification");
+  lo = fnc = l;
+  if (chunksize > 0)
+  {
+    csize = chunksize;
+    <T>* data = new <T>[csize];
+    set_cache(new <T>IChunk(data,  lo, lo, fnc, lo+csize));
+    hd = ch;
+  }
+  else
+  {
+    csize = -chunksize;
+    <T>* data = new <T>[csize];
+    set_cache(new <T>IChunk(data,  chunksize+lo, lo, fnc, fnc));
+    hd = ch;
+  }
+  maxch = MIN_NCHUNKS;
+  lch = maxch / 2;
+  fch = lch + 1;
+  base = ch->base_index() - lch * csize;
+  chunks = new _<T>IChunk_ptr[maxch];
+  chunks[lch] = ch;
+}
+
+void <T>RPlex::make_initial_chunks(int up)
+{
+  int count = 0;
+  int need = fnc - lo;
+  hd = 0;
+  if (up)
+  {
+    int l = lo;
+    do
+    {
+      ++count;
+      int sz;
+      if (need >= csize)
+        sz = csize;
+      else
+        sz = need;
+      <T>* data = new <T> [csize];
+      <T>IChunk* h = new <T>IChunk(data,  l, l, l+sz, l+csize);
+      if (hd != 0)
+        h->link_to_next(hd);
+      else
+        hd = h;
+      l += sz;
+      need -= sz;
+    } while (need > 0);
+  }
+  else
+  {
+    int hi = fnc;
+    do
+    {
+      ++count;
+      int sz;
+      if (need >= csize)
+        sz = csize;
+      else
+        sz = need;
+      <T>* data = new <T> [csize];
+      <T>IChunk* h = new <T>IChunk(data,  hi-csize, hi-sz, hi, hi);
+      if (hd != 0)
+        h->link_to_next(hd);
+      hd = h;
+      hi -= sz;
+      need -= sz;
+    } while (need > 0);
+  }
+  set_cache((<T>IChunk*)hd);
+  
+  maxch = MIN_NCHUNKS;
+  if (maxch < count * 2)
+    maxch = count * 2;
+  chunks = new _<T>IChunk_ptr[maxch];
+  lch = maxch / 3;
+  fch = lch + count;
+  base = ch->base_index() - csize * lch;
+  int k = lch;
+  do
+  {
+    chunks[k++] = ch;
+    set_cache(ch->next());
+  } while (ch != hd);
+}
+
+<T>RPlex:: <T>RPlex(int l, int hi, const <T&> initval, int chunksize)
+{
+  lo = l;
+  fnc = hi + 1;
+  if (chunksize == 0)
+  {
+    csize = fnc - l;
+    make_initial_chunks(1);
+  }
+  else if (chunksize < 0)
+  {
+    csize = -chunksize;
+    make_initial_chunks(0);
+  }
+  else
+  {
+    csize = chunksize;
+    make_initial_chunks(1);
+  }
+  fill(initval);
+}
+
+<T>RPlex::<T>RPlex(const <T>RPlex& a)
+{
+  lo = a.lo;
+  fnc = a.fnc;
+  csize = a.csize;
+  make_initial_chunks();
+  for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
+}
+
+void <T>RPlex::operator= (const <T>RPlex& a)
+{
+  if (&a != this)
+  {
+    invalidate();
+    lo = a.lo;
+    fnc = a.fnc;
+    csize = a.csize;
+    make_initial_chunks();
+    for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
+  }
+}
+
+
+void <T>RPlex::cache(const <T>* p) const
+{
+  const <T>IChunk* old = ch;
+  const <T>IChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = (t->next());
+    if (t == old) index_error();
+  }
+  set_cache(t);
+}
+
+int <T>RPlex::owns(Pix px) const
+{
+  <T>* p = (<T>*)px;
+  const <T>IChunk* old = ch;
+  const <T>IChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = (t->next());
+    if (t == old) return 0;
+  }
+  set_cache(t);
+  return 1;
+}
+
+
+<T>* <T>RPlex::dosucc(const <T>* p) const
+{
+  if (p == 0) return 0;
+  const <T>IChunk* old = ch;
+  const <T>IChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = (t->next());
+    if (t == old) return 0;
+  }
+  int i = t->index_of(p) + 1;
+  if (i >= fnc) return 0;
+  if (i >= t->fence_index()) t = (t->next());
+  set_cache(t);
+  return t->pointer_to(i);
+}
+
+<T>* <T>RPlex::dopred(const <T>* p) const
+{
+  if (p == 0) return 0;
+  const <T>IChunk* old = ch;
+  const <T>IChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = (t->prev());
+    if (t == old) return 0;
+  }
+  int i = t->index_of(p) - 1;
+  if (i < lo) return 0;
+  if (i < t->low_index()) t = (t->prev());
+  set_cache(t);
+  return (t->pointer_to(i));
+}
+
+int <T>RPlex::add_high(const <T&> elem)
+{
+  <T>IChunk* t = tl();
+  if (!t->can_grow_high())
+  {
+    if (t-><T>IChunk::empty() && one_chunk())
+    {
+      t->clear(fnc);
+      base = t->base_index() - lch * csize;
+    }
+    else
+    {
+      <T>* data = new <T> [csize];
+      t = (new <T>IChunk(data,  fnc, fnc, fnc,fnc+csize));
+      t->link_to_prev(tl());
+      if (fch == maxch)
+      {
+        maxch *= 2;
+        <T>IChunk** newch = new _<T>IChunk_ptr [maxch];
+        memcpy(newch, chunks, fch * sizeof(_<T>IChunk_ptr));
+        delete chunks;
+        chunks = newch;
+      }
+      chunks[fch++] = t;
+    }
+  }
+  *((t-><T>IChunk::grow_high())) = elem;
+  set_cache(t);
+  return fnc++;
+}
+
+int <T>RPlex::del_high ()
+{
+  if (empty()) empty_error();
+  <T>IChunk* t = tl();
+  if (t-><T>IChunk::empty()) // kill straggler first
+  {
+    <T>IChunk* pred = t->prev();
+    del_chunk(t);
+    t = (pred);
+    --fch;
+  }
+  t-><T>IChunk::shrink_high();
+  if (t-><T>IChunk::empty() && !one_chunk())
+  {
+    <T>IChunk* pred = t->prev();
+    del_chunk(t);
+    t = (pred);
+    --fch;
+  }
+  set_cache(t);
+  return --fnc - 1;
+}
+
+int <T>RPlex::add_low (const <T&> elem)
+{
+  <T>IChunk* t = hd;
+  if (!t->can_grow_low())
+  {
+    if (t-><T>IChunk::empty() && one_chunk())
+    {
+      t->cleardown(lo);
+      base = t->base_index() - lch * csize;
+    }
+    else
+    {
+      <T>* data = new <T> [csize];
+      hd = new <T>IChunk(data,  lo-csize, lo, lo, lo);
+      hd->link_to_next(t);
+      t = ( hd);
+      if (lch == 0)
+      {
+        lch = maxch;
+        fch += maxch;
+        maxch *= 2;
+        <T>IChunk** newch = new _<T>IChunk_ptr [maxch];
+        memcpy(&(newch[lch]), chunks, lch * sizeof(_<T>IChunk_ptr));
+        delete chunks;
+        chunks = newch;
+        base = t->base_index() - (lch - 1) * csize;
+      }
+      chunks[--lch] = t;
+    }
+  }
+  *((t-><T>IChunk::grow_low())) = elem;
+  set_cache(t);
+  return --lo;
+}
+
+
+int <T>RPlex::del_low ()
+{
+  if (empty()) empty_error();
+  <T>IChunk* t = hd;
+  if (t-><T>IChunk::empty())
+  {
+    hd = t->next();
+    del_chunk(t);
+    t = hd;
+    ++lch;
+  }
+  t-><T>IChunk::shrink_low();
+  if (t-><T>IChunk::empty() && !one_chunk())
+  {
+    hd = t->next();
+    del_chunk(t);
+    t = hd;
+    ++lch;
+  }
+  set_cache(t);
+  return ++lo;
+}
+
+void <T>RPlex::reverse()
+{
+  <T> tmp;
+  int l = lo;
+  int h = fnc - 1;
+  <T>IChunk* loch = hd;
+  <T>IChunk* hich = tl();
+  while (l < h)
+  {
+    <T>* lptr = loch->pointer_to(l);
+    <T>* hptr = hich->pointer_to(h);
+    tmp = *lptr;
+    *lptr = *hptr;
+    *hptr = tmp;
+    if (++l >= loch->fence_index()) loch = loch->next();
+    if (--h < hich->low_index()) hich = hich->prev();
+  }
+}
+
+void <T>RPlex::fill(const <T&> x)
+{
+  for (int i = lo; i < fnc; ++i) (*this)[i] = x;
+}
+
+void <T>RPlex::fill(const <T&> x, int lo, int hi)
+{
+  for (int i = lo; i <= hi; ++i) (*this)[i] = x;
+}
+
+
+void <T>RPlex::clear()
+{
+  for (int i = lch + 1; i < fch; ++i)
+    del_chunk(chunks[i]);
+  fch = lch + 1;
+  set_cache(chunks[lch]);
+  ch-><T>IChunk::clear(lo);
+  fnc = lo;
+}
+
+int <T>RPlex::reset_low(int l)
+{
+  int old = lo;
+  int diff = l - lo;
+  if (diff != 0)
+  {
+    lo += diff;
+    fnc += diff;
+    <T>IChunk* t = hd;
+    do
+    {
+      t->re_index(t->low_index() + diff);
+      t = t->next();
+    } while (t != hd);
+  }
+  base = hd->base_index() - lch * csize;
+  return old;
+}
+
+
+int <T>RPlex::OK () const
+{
+  int v = hd != 0 && ch != 0;         // at least one chunk
+
+  v &= fnc == tl()->fence_index();  // last chunk fnc == plex fnc
+  v &= lo == hd-><T>IChunk::low_index();    // first lo == plex lo
+
+  v &= base == hd->base_index() - lch * csize; // base is correct;
+  v &= lch < fch;
+  v &= fch <= maxch;                  // within allocation;
+
+// loop for others:
+
+  int k = lch;                        // to cross-check nch
+
+  int found_ch = 0;                   // to make sure ch is in list;
+  const <T>IChunk* t = (hd);
+  for (;;)
+  {
+    v &= chunks[k++] == t;             // each chunk is at proper index
+    if (t == ch) ++found_ch;
+    v &= t-><T>IChunk::OK();              // each chunk is OK
+    if (t == tl())
+      break;
+    else                              // and has indices contiguous to succ
+    {
+      v &= t->top_index() == t->next()->base_index();
+      if (t != hd)                  // internal chunks full
+      {
+        v &= !t->empty();
+        v &= !t->can_grow_low();
+        v &= !t->can_grow_high();
+      }
+      t = t->next();
+    }
+  }
+  v &= found_ch == 1;
+  v &= fch == k;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/RPlex.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/RPlex.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/RPlex.hP	(revision 18)
@@ -0,0 +1,257 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>RPlex_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>RPlex_h 1
+
+#include "<T>.Plex.h"
+
+// minimum number of chunks to index
+
+#ifndef MIN_NCHUNKS
+#define MIN_NCHUNKS  16
+#endif
+
+class <T>RPlex: public <T>Plex
+{
+  int              base;        // base index of lowest chunk
+  int              lch;         // index of lowest used chunk
+  int              fch;         // 1 + index of highest used chunk
+  int              maxch;       // max chunks in array
+  <T>IChunk**      chunks;      // array of chunks
+  <T>IChunk*       ch;          // cached chunk
+
+  void             make_initial_chunks(int up = 1);
+
+  void             cache(int idx) const;
+  void             cache(const <T>* p) const;
+  <T>*             dopred(const <T>* p) const;
+  <T>*             dosucc(const <T>* p) const;
+
+  inline void             set_cache(const <T>IChunk* t) const; // logically, 
+                                               // not physically const
+
+public:
+                   <T>RPlex();                 // set low = 0;
+                                               // fence = 0;
+                                               // csize = default
+
+                   <T>RPlex(int ch_size);      // low = 0; 
+                                               // fence = 0;
+                                               // csize = ch_size
+
+                   <T>RPlex(int lo,            // low = lo; 
+                            int ch_size);      // fence=lo
+                                               // csize = ch_size
+
+                   <T>RPlex(int lo,            // low = lo
+                            int hi,            // fence = hi+1
+                            const <T&> initval,// fill with initval,
+                            int ch_size = 0);  // csize= ch_size
+                                               // or fence-lo if 0
+
+                   <T>RPlex(const <T>RPlex&);
+
+  inline                  ~<T>RPlex();
+
+  void             operator= (const <T>RPlex&);
+
+// virtuals
+
+  inline <T>&             high_element ();
+  inline <T>&             low_element ();
+
+  inline const <T>&       high_element () const;
+  inline const <T>&       low_element () const;
+
+  inline Pix              first() const;
+  inline Pix              last() const;
+  inline void             prev(Pix& ptr) const;
+  inline void             next(Pix& ptr) const;
+  int              owns(Pix p) const;
+  inline <T>&             operator () (Pix p);
+  inline const <T>&       operator () (Pix p) const;
+
+  inline int              low() const; 
+  inline int              high() const;
+  inline int              valid(int idx) const;
+  inline void             prev(int& idx) const;
+  inline void             next(int& x) const;
+  inline <T>&             operator [] (int index);
+  inline const <T>&       operator [] (int index) const;
+    
+  inline int              Pix_to_index(Pix p) const;
+  inline Pix              index_to_Pix(int idx) const;    
+
+  inline int              can_add_high() const;
+  inline int              can_add_low() const;
+  inline int              full() const;
+
+  int              add_high(const <T&> elem);
+  int              del_high ();
+  int              add_low (const <T&> elem);
+  int              del_low ();
+
+  void             fill(const <T&> x);
+  void             fill(const <T&> x, int from, int to);
+  void             clear();
+  void             reverse();
+
+  int              reset_low(int newlow);
+    
+  int              OK () const; 
+};
+
+
+inline void <T>RPlex::prev(int& idx) const
+{
+  --idx;
+}
+
+inline void <T>RPlex::next(int& idx) const 
+{
+  ++idx;
+}
+
+inline  int <T>RPlex::full ()  const
+{
+  return 0;
+}
+
+inline int <T>RPlex::can_add_high() const
+{
+  return 1;
+}
+
+inline int <T>RPlex::can_add_low() const
+{
+  return 1;
+}
+
+inline  int <T>RPlex::valid (int idx) const
+{
+  return idx >= lo && idx < fnc;
+}
+
+inline int <T>RPlex::low() const
+{
+  return lo;
+}
+
+inline int <T>RPlex::high() const
+{
+  return fnc - 1;
+}
+
+inline void <T>RPlex::set_cache(const <T>IChunk* t) const
+{
+  ((<T>RPlex*)(this))->ch = (<T>IChunk*)t;
+}
+
+inline void <T>RPlex::cache(int idx) const
+{
+  if (idx < lo || idx >= fnc) index_error();
+  set_cache(chunks[(idx - base) / csize]);
+}  
+
+inline  <T>& <T>RPlex::low_element () 
+{
+  cache(lo); return *(ch->pointer_to(lo));
+}
+
+inline  <T>& <T>RPlex::high_element ()
+{
+  cache(fnc-1); return *(ch->pointer_to(fnc - 1));
+}
+
+inline const <T>& <T>RPlex::low_element () const
+{
+  cache(lo); return *((const <T>*)(ch->pointer_to(lo)));
+}
+
+inline const <T>& <T>RPlex::high_element () const
+{
+  cache(fnc-1); return *((const <T>*)(ch->pointer_to(fnc - 1)));
+}
+
+inline  int <T>RPlex::Pix_to_index(Pix px) const
+{
+  <T>* p = (<T>*)px;
+  if (!ch->actual_pointer(p)) cache(p);
+  return ch->index_of(p);
+}
+
+inline  Pix <T>RPlex::index_to_Pix(int idx) const
+{
+  if (!ch->actual_index(idx)) cache(idx);
+  return (Pix)(ch->pointer_to(idx));
+}
+
+inline Pix <T>RPlex::first() const
+{
+  return Pix(hd-><T>IChunk::first_pointer());
+}
+
+inline Pix <T>RPlex::last() const
+{
+  return Pix(tl()-><T>IChunk::last_pointer());
+}
+
+inline void <T>RPlex::prev(Pix& p) const
+{
+  Pix q = Pix(ch-><T>IChunk::pred((<T>*)p));
+  p = (q == 0)? Pix(dopred((<T>*)p)) : q;
+}
+
+inline void <T>RPlex::next(Pix& p) const
+{
+  Pix q = Pix(ch-><T>IChunk::succ((<T>*)p));
+  p = (q == 0)? Pix(dosucc((<T>*)p)) : q;
+}
+
+inline <T>& <T>RPlex:: operator () (Pix p)
+{
+  return *((<T>*)p);
+}
+
+
+inline <T>& <T>RPlex:: operator [] (int idx)
+{
+  cache(idx); return *(ch->pointer_to(idx));
+}
+
+inline const <T>& <T>RPlex:: operator () (Pix p) const
+{
+  return *((const <T>*)p);
+}
+
+inline const <T>& <T>RPlex:: operator [] (int idx) const
+{
+  cache(idx); return *((const <T>*)(ch->pointer_to(idx)));
+}
+
+inline <T>RPlex::~<T>RPlex()
+{
+  delete chunks;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SLBag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLBag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLBag.ccP	(revision 18)
@@ -0,0 +1,105 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.SLBag.h"
+
+int <T>SLBag::OK()
+{
+  int v = p.OK();
+  v &= count == p.length();
+  if (!v) error("invariant failure");
+  return v;
+}
+
+Pix <T>SLBag::seek(<T&> item, Pix i)
+{
+  if (i == 0) i = first(); else next(i);
+  for (; i != 0 && (!(<T>EQ(p(i), item))); p.next(i));
+  return i;
+}
+
+int <T>SLBag::nof(<T&> item)
+{
+  int n = 0;
+  for (Pix p = first(); p; next(p)) if (<T>EQ((*this)(p), item)) ++n;
+  return n;
+}
+
+
+void <T>SLBag::del(<T&> item)
+{
+  Pix i = p.first();
+  if (i == 0) 
+    return;
+  else if (<T>EQ(p(i), item))
+  {
+    --count;
+    p.del_front();
+  }
+  else
+  {
+    Pix trail = i;
+    p.next(i);
+    while (i != 0)
+    {
+      if (<T>EQ(p(i), item))
+      {
+        --count;
+        p.del_after(trail);
+        return;
+      }
+      trail = i;
+      p.next(i);
+    }
+  }
+}    
+
+void <T>SLBag::remove(<T&> item)
+{
+  Pix i = p.first();
+  while (i != 0 && <T>EQ(p(i), item))
+  {
+    --count;
+    p.del_front();
+    i = p.first();
+  }
+  if (i != 0)
+  {
+    Pix trail = i;
+    p.next(i);
+    while (i != 0)
+    {
+      if (<T>EQ(p(i), item))
+      {
+        --count;
+        p.del_after(trail);
+        i = trail;
+        p.next(i);
+      }
+      else
+      {
+        trail = i;
+        p.next(i);
+      }
+    }
+  }
+}    
+
Index: trunk/src/emx/include/Attic/cpp/gen/SLBag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLBag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLBag.hP	(revision 18)
@@ -0,0 +1,96 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>SLBag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SLBag_h 1
+
+#include "<T>.Bag.h"
+#include "<T>.SLList.h"
+
+class <T>SLBag : public <T>Bag
+{
+protected:
+  <T>SLList     p;
+
+public:
+                <T>SLBag();
+                <T>SLBag(const <T>SLBag&);
+
+  inline Pix           add(<T&> item);
+  void          del(<T&> item);
+  void          remove(<T&>item);
+  inline int           contains(<T&> item);
+  int           nof(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item, Pix from = 0);
+
+  int           OK();
+};
+
+
+inline <T>SLBag::<T>SLBag() : p() { count = 0; }
+
+inline <T>SLBag::<T>SLBag(const <T>SLBag& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>SLBag::first()
+{
+  return p.first();
+}
+
+inline void <T>SLBag::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>SLBag::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline void <T>SLBag::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>SLBag::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+inline Pix <T>SLBag::add(<T&> item)
+{
+  ++count;
+  return p.append(item);
+}
+
+inline int <T>SLBag::contains(<T&> item)
+{
+  return seek(item) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SLList.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLList.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLList.ccP	(revision 18)
@@ -0,0 +1,292 @@
+// This may look like C code, but it is really -*- C++ -*-
+// WARNING: This file is obsolete.  Use ../SLList.cc, if you can.
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <limits.h>
+#include <stream.h>
+#include <builtin.h>
+#include "<T>.SLList.h"
+
+void <T>SLList::error(const char* msg)
+{
+  (*lib_error_handler)("SLList", msg);
+}
+
+int <T>SLList::length()
+{
+  int l = 0;
+  <T>SLListNode* t = last;
+  if (t != 0) do { ++l; t = t->tl; } while (t != last);
+  return l;
+}
+
+<T>SLList::<T>SLList(const <T>SLList& a)
+{
+  if (a.last == 0)
+    last = 0;
+  else
+  {
+    <T>SLListNode* p = a.last->tl;
+    <T>SLListNode* h = new <T>SLListNode(p->hd);
+    last = h;
+    for (;;)
+    {
+      if (p == a.last)
+      {
+        last->tl = h;
+        return;
+      }
+      p = p->tl;
+      <T>SLListNode* n = new <T>SLListNode(p->hd);
+      last->tl = n;
+      last = n;
+    }
+  }
+}
+
+<T>SLList& <T>SLList::operator = (const <T>SLList& a)
+{
+  if (last != a.last)
+  {
+    clear();
+    if (a.last != 0)
+    {
+      <T>SLListNode* p = a.last->tl;
+      <T>SLListNode* h = new <T>SLListNode(p->hd);
+      last = h;
+      for (;;)
+      {
+        if (p == a.last)
+        {
+          last->tl = h;
+          break;
+        }
+        p = p->tl;
+        <T>SLListNode* n = new <T>SLListNode(p->hd);
+        last->tl = n;
+        last = n;
+      }
+    }
+  }
+  return *this;
+}
+
+void <T>SLList::clear()
+{
+  if (last == 0)
+    return;
+
+  <T>SLListNode* p = last->tl;
+  last->tl = 0;
+  last = 0;
+
+  while (p != 0)
+  {
+    <T>SLListNode* nxt = p->tl;
+    delete(p);
+    p = nxt;
+  }
+}
+
+
+Pix <T>SLList::prepend(<T&> item)
+{
+  <T>SLListNode* t = new <T>SLListNode(item);
+  if (last == 0)
+    t->tl = last = t;
+  else
+  {
+    t->tl = last->tl;
+    last->tl = t;
+  }
+  return Pix(t);
+}
+
+
+Pix <T>SLList::prepend(<T>SLListNode* t)
+{
+  if (t == 0) return 0;
+  if (last == 0)
+    t->tl = last = t;
+  else
+  {
+    t->tl = last->tl;
+    last->tl = t;
+  }
+  return Pix(t);
+}
+
+
+Pix <T>SLList::append(<T&> item)
+{
+  <T>SLListNode* t = new <T>SLListNode(item);
+  if (last == 0)
+    t->tl = last = t;
+  else
+  {
+    t->tl = last->tl;
+    last->tl = t;
+    last = t;
+  }
+  return Pix(t);
+}
+
+Pix <T>SLList::append(<T>SLListNode* t)
+{
+  if (t == 0) return 0;
+  if (last == 0)
+    t->tl = last = t;
+  else
+  {
+    t->tl = last->tl;
+    last->tl = t;
+    last = t;
+  }
+  return Pix(t);
+}
+
+void <T>SLList::join(<T>SLList& b)
+{
+  <T>SLListNode* t = b.last;
+  b.last = 0;
+  if (last == 0)
+    last = t;
+  else if (t != 0)
+  {
+    <T>SLListNode* f = last->tl;
+    last->tl = t->tl;
+    t->tl = f;
+    last = t;
+  }
+}
+
+Pix <T>SLList::ins_after(Pix p, <T&> item)
+{
+  <T>SLListNode* u = (<T>SLListNode*)p;
+  <T>SLListNode* t = new <T>SLListNode(item);
+  if (last == 0)
+    t->tl = last = t;
+  else if (u == 0) // ins_after 0 means prepend
+  {
+    t->tl = last->tl;
+    last->tl = t;
+  }
+  else
+  {
+    t->tl = u->tl;
+    u->tl = t;
+    if (u == last) 
+      last = t;
+  }
+  return Pix(t);
+}
+
+
+void <T>SLList::del_after(Pix p)
+{
+  <T>SLListNode* u = (<T>SLListNode*)p;
+  if (last == 0 || u == last) error("cannot del_after last");
+  if (u == 0) u = last; // del_after 0 means delete first
+  <T>SLListNode* t = u->tl;
+  if (u == t)
+    last = 0;
+  else
+  {
+    u->tl = t->tl;
+    if (last == t)
+      last = u;
+  }
+  delete t;
+}
+
+int <T>SLList::owns(Pix p)
+{
+  <T>SLListNode* t = last;
+  if (t != 0 && p != 0)
+  {
+    do
+    {
+      if (Pix(t) == p) return 1;
+      t = t->tl;
+    } while (t != last);
+  }
+  return 0;
+}
+
+<T> <T>SLList::remove_front()
+{
+  if (last == 0) error("remove_front of empty list");
+  <T>SLListNode* t = last->tl;
+  <T> res = t->hd;
+  if (t == last)
+    last = 0;
+  else
+    last->tl = t->tl;
+  delete t;
+  return res;
+}
+
+int <T>SLList::remove_front(<T>& x)
+{
+  if (last == 0)
+    return 0;
+  else
+  {
+    <T>SLListNode* t = last->tl;
+    x = t->hd;
+    if (t == last)
+      last = 0;
+    else
+      last->tl = t->tl;
+    delete t;
+    return 1;
+  }
+}
+
+
+void <T>SLList::del_front()
+{
+  if (last == 0) error("del_front of empty list");
+  <T>SLListNode* t = last->tl;
+  if (t == last)
+    last = 0;
+  else
+    last->tl = t->tl;
+  delete t;
+}
+
+int <T>SLList::OK()
+{
+  int v = 1;
+  if (last != 0)
+  {
+    <T>SLListNode* t = last;
+    long count = LONG_MAX;      // Lots of chances to find last!
+    do
+    {
+      count--;
+      t = t->tl;
+    } while (count > 0 && t != last);
+    v &= count > 0;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/SLList.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLList.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLList.hP	(revision 18)
@@ -0,0 +1,137 @@
+// This may look like C code, but it is really -*- C++ -*-
+// WARNING: This file is obsolete.  Use ../SLList.h, if you can.
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>SLList_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SLList_h 1
+
+#include <Pix.h>
+#include "<T>.defs.h"
+
+#ifndef _<T>SLListNode_h
+#define _<T>SLListNode_h 1
+
+struct <T>SLListNode
+{
+  <T>SLListNode*         tl;
+  <T>                    hd;
+                         <T>SLListNode() { }
+                         <T>SLListNode(const <T&> h, <T>SLListNode* t = 0);
+                         ~<T>SLListNode() { }
+};
+
+
+inline <T>SLListNode::<T>SLListNode(const <T&> h, <T>SLListNode* t)
+:tl(t), hd(h) {}
+
+typedef <T>SLListNode* <T>SLListNodePtr;
+
+#endif
+
+
+class <T>SLList
+{
+protected:
+  <T>SLListNode*        last;
+
+public:
+                        <T>SLList();
+                        <T>SLList(const <T>SLList& a);
+                        ~<T>SLList();
+
+  <T>SLList&            operator = (const <T>SLList& a);
+
+  int                   empty();
+  int                   length();
+
+  void                  clear();
+
+  Pix                   prepend(<T&> item);
+  Pix                   append(<T&> item);
+
+  void                  join(<T>SLList&);
+
+  Pix                   prepend(<T>SLListNode*);
+  Pix                   append(<T>SLListNode*);
+
+  <T>&                  operator () (Pix p);
+  Pix                   first();
+  void                  next(Pix& p);
+  int                   owns(Pix p);
+  Pix                   ins_after(Pix p, <T&> item);
+  void                  del_after(Pix p);
+
+  <T>&                  front();
+  <T>&                  rear();
+  <T>                   remove_front();
+  int                   remove_front(<T>& x);
+  void                  del_front();
+
+  void                  error(const char* msg);
+  int                   OK();
+};
+
+inline <T>SLList::~<T>SLList()
+{
+  clear();
+}
+
+inline <T>SLList::<T>SLList()
+{
+  last = 0;
+}
+
+inline int <T>SLList::empty()
+{
+  return last == 0;
+}
+
+
+inline Pix <T>SLList::first()
+{
+  return (last == 0)? 0 : Pix(last->tl);
+}
+
+inline void <T>SLList::next(Pix& p)
+{
+  p = (p == 0 || p == last)? 0 : Pix(((<T>SLListNode*)(p))->tl);
+}
+
+inline <T>& <T>SLList::operator () (Pix p)
+{
+  if (p == 0) error("null Pix");
+  return ((<T>SLListNode*)(p))->hd;
+}
+
+inline <T>& <T>SLList::front()
+{
+  if (last == 0) error("front: empty list");
+  return last->tl->hd;
+}
+
+inline <T>& <T>SLList::rear()
+{
+  if (last == 0) error("rear: empty list");
+  return last->hd;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SLQueue.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLQueue.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLQueue.ccP	(revision 18)
@@ -0,0 +1,4 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.SLQueue.h"
Index: trunk/src/emx/include/Attic/cpp/gen/SLQueue.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLQueue.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLQueue.hP	(revision 18)
@@ -0,0 +1,108 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>SLQueue_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SLQueue_h
+
+#include "<T>.SLList.h"
+#include "<T>.Queue.h"
+
+class <T>SLQueue : public <T>Queue
+{
+  <T>SLList    p;
+
+public:
+               <T>SLQueue();
+               <T>SLQueue(const <T>SLQueue& q);
+  inline              ~<T>SLQueue();
+
+  void          operator = (const <T>SLQueue&);
+
+  inline void          enq(<T&> item);
+  inline <T>           deq();
+  inline <T>&          front();
+  inline void          del_front();
+
+  inline void          clear();
+  inline int           empty();
+  inline int           full();
+  inline int           length();
+               
+  inline int           OK();
+};
+
+inline <T>SLQueue::<T>SLQueue() :p() {}
+inline <T>SLQueue::<T>SLQueue(const <T>SLQueue& q) : p(q.p) {}
+
+inline <T>SLQueue::~<T>SLQueue() {}
+
+inline void <T>SLQueue::enq(<T&>item)
+{
+  p.append(item);
+}
+
+inline <T> <T>SLQueue::deq()
+{
+  return p.remove_front();
+}
+
+inline <T>& <T>SLQueue::front()
+{
+  return p.front();
+}
+
+
+inline void <T>SLQueue::del_front()
+{
+  p.del_front();
+}
+
+inline void <T>SLQueue::operator =(const <T>SLQueue& s)
+{
+  p = s.p;
+}
+
+inline int <T>SLQueue::empty()
+{
+  return p.empty();
+}
+
+inline int <T>SLQueue::full()
+{
+  return 0;
+}
+
+inline int <T>SLQueue::length()
+{
+  return p.length();
+}
+
+inline int <T>SLQueue::OK()
+{
+  return p.OK();
+}
+
+inline void <T>SLQueue::clear()
+{
+  p.clear();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SLSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLSet.ccP	(revision 18)
@@ -0,0 +1,77 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.SLSet.h"
+
+int <T>SLSet::OK()
+{
+  int v = p.OK();
+  v &= count == p.length();
+  if (!v) error("invariant failure");
+  return v;
+}
+
+Pix <T>SLSet::seek(<T&> item)
+{
+  Pix i;
+  for (i = p.first(); i != 0 && !<T>EQ(p(i),item); p.next(i));
+  return i;
+}
+
+Pix <T>SLSet::add(<T&> item)
+{
+  Pix i = seek(item);
+  if (i == 0)
+  {
+    ++count;
+    i = p.append(item);
+  }
+  return i;
+}
+
+void <T>SLSet::del(<T&> item)
+{
+  Pix i = p.first();
+  if (i == 0)
+    return;
+  else if (<T>EQ(p(i), item))
+  {
+    --count;
+    p.del_front();
+  }
+  else
+  {
+    Pix trail = i;
+    p.next(i);
+    while (i != 0)
+    {
+      if (<T>EQ(p(i), item))
+      {
+        --count;
+        p.del_after(trail);
+        return;
+      }
+      trail = i;
+      p.next(i);
+    }
+  }
+}    
+
Index: trunk/src/emx/include/Attic/cpp/gen/SLSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLSet.hP	(revision 18)
@@ -0,0 +1,87 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>SLSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SLSet_h 1
+
+#include "<T>.Set.h"
+#include "<T>.SLList.h"
+
+class <T>SLSet : public <T>Set
+{
+protected:
+  <T>SLList     p;
+
+public:
+                <T>SLSet();
+                <T>SLSet(const <T>SLSet&);
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  inline int           contains(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item);
+
+  int           OK();
+};
+
+inline <T>SLSet::<T>SLSet() : p() { count = 0; }
+
+inline <T>SLSet::<T>SLSet(const <T>SLSet& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>SLSet::first()
+{
+  return p.first();
+}
+
+inline void <T>SLSet::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>SLSet::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline void <T>SLSet::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>SLSet::contains (<T&> item)
+{
+  return seek(item) != 0;
+}
+
+inline int <T>SLSet::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SLStack.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLStack.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLStack.ccP	(revision 18)
@@ -0,0 +1,4 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.SLStack.h"
Index: trunk/src/emx/include/Attic/cpp/gen/SLStack.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SLStack.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SLStack.hP	(revision 18)
@@ -0,0 +1,109 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>SLStack_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SLStack_h 1
+
+#include "<T>.SLList.h"
+#include "<T>.Stack.h"
+
+class <T>SLStack : public <T>Stack
+{
+  <T>SLList     p;
+
+public:
+                <T>SLStack();
+                <T>SLStack(const <T>SLStack& s);
+  inline               ~<T>SLStack();
+
+  void          operator = (const <T>SLStack&);
+
+  inline void          push(<T&> item);
+  inline <T>           pop();
+  inline <T>&          top();               
+  inline void          del_top();
+
+  inline int           empty();
+  inline int           full();
+  inline int           length();
+
+  inline void          clear();
+
+  inline int           OK();
+
+};
+
+inline <T>SLStack::<T>SLStack() :p() {}
+inline <T>SLStack::<T>SLStack(const <T>SLStack& a) : p(a.p) {}
+inline <T>SLStack::~<T>SLStack() {}
+
+inline void <T>SLStack::push(<T&> item)
+{
+  p.prepend(item);
+}
+
+inline <T> <T>SLStack::pop()
+{
+  return p.remove_front();
+}
+
+inline <T>& <T>SLStack::top()
+{
+  return p.front();
+}
+
+inline void <T>SLStack::del_top()
+{
+  p.del_front();
+}
+
+inline void <T>SLStack::operator =(const <T>SLStack& s)
+{
+  p = s.p;
+}
+
+inline int <T>SLStack::empty() 
+{
+  return p.empty();
+}
+
+inline int <T>SLStack::full() 
+{
+  return 0;
+}
+
+inline int <T>SLStack::length() 
+{
+  return p.length();
+}
+
+inline int <T>SLStack::OK() 
+{
+  return p.OK();
+}
+
+inline void <T>SLStack::clear() 
+{
+  p.clear();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/Set.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Set.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Set.ccP	(revision 18)
@@ -0,0 +1,117 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <builtin.h>
+#include "<T>.Set.h"
+
+
+Pix <T>Set::seek(<T&> item)
+{
+  Pix i;
+  for (i = first(); i != 0 && !(<T>EQ((*this)(i), item)); next(i));
+  return i;
+}
+
+int <T>Set::owns(Pix idx)
+{
+  if (idx == 0) return 0;
+  for (Pix i = first(); i; next(i)) if (i == idx) return 1;
+  return 0;
+}
+
+void <T>Set::clear()
+{
+  Pix i = first(); 
+  while (i != 0)
+  {
+    del((*this)(i));
+    i = first();
+  }
+}
+
+int <T>Set::contains (<T&> item)
+{
+  return seek(item) != 0;
+}
+
+int <T>Set::operator <= (<T>Set& b)
+{
+  if (count > b.count) return 0;
+  if (count == 0) return 1;
+  for (Pix i = first(); i; next(i)) if (b.seek((*this)(i)) == 0) return 0;
+  return 1;
+}
+
+int <T>Set::operator == (<T>Set& b)
+{
+  int n = count;
+  if (n != b.count) return 0;
+  if (n == 0) return 1;
+  Pix i = first();
+  Pix j = b.first();
+  while (n-- > 0)
+  {
+    if ((b.seek((*this)(i)) == 0) || (seek(b(j)) == 0)) return 0;
+    next(i);
+    b.next(j);
+  }
+  return 1;
+}
+
+int <T>Set::operator != (<T>Set& b)
+{
+  return !(*this == b);
+}
+
+void <T>Set::operator |= (<T>Set& b)
+{
+  if (&b != this)
+    for (Pix i = b.first(); i; b.next(i)) add(b(i));
+}
+
+void <T>Set::operator -= (<T>Set& b)
+{
+  if (&b == this)
+    clear();
+  else
+    for (Pix i = b.first(); i; b.next(i)) del(b(i));
+}
+
+
+void <T>Set::operator &= (<T>Set& b)
+{
+  if (&b != this)
+  {
+    Pix i = first();
+    Pix n = i;
+    while (i != 0)
+    {
+      next(n);
+      if (b.seek((*this)(i)) == 0) del((*this)(i));
+      i = n;
+    }
+  }
+}
+
+void <T>Set::error(const char* msg)
+{
+  (*lib_error_handler)("Set", msg);
+}
Index: trunk/src/emx/include/Attic/cpp/gen/Set.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Set.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Set.hP	(revision 18)
@@ -0,0 +1,78 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>Set_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>Set_h 1
+
+#include <Pix.h>
+#include "<T>.defs.h"
+
+class <T>Set
+{
+protected:
+
+  int                   count;
+
+public:
+  inline virtual              ~<T>Set();
+
+  int                   length();                // current number of items
+  int                   empty();
+
+  virtual Pix           add(<T&> item) = 0;      // add item; return Pix
+  virtual void          del(<T&> item) = 0;      // delete item
+  virtual int           contains(<T&> item);     // is item in set?
+
+  virtual void          clear();                 // delete all items
+
+  virtual Pix           first() = 0;             // Pix of first item or 0
+  virtual void          next(Pix& i) = 0;        // advance to next or 0
+  virtual <T>&          operator () (Pix i) = 0; // access item at i
+
+  virtual int           owns(Pix i);             // is i a valid Pix  ?
+  virtual Pix           seek(<T&> item);         // Pix of item
+
+  void                  operator |= (<T>Set& b); // add all items in b
+  void                  operator -= (<T>Set& b); // delete items also in b
+  void                  operator &= (<T>Set& b); // delete items not in b
+
+  int                   operator == (<T>Set& b);
+  int                   operator != (<T>Set& b);
+  int                   operator <= (<T>Set& b); 
+
+  void                  error(const char* msg);
+  virtual int           OK() = 0;                // rep invariant
+};
+
+inline <T>Set::~<T>Set() {}
+
+inline int <T>Set::length()
+{
+  return count;
+}
+
+inline int <T>Set::empty()
+{
+  return count == 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SkipBag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SkipBag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SkipBag.ccP	(revision 18)
@@ -0,0 +1,322 @@
+// This may look like C code, but it is really -*- C++ -*-
+
+/* 
+Copyright (C) 1991 Free Software Foundation
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * Bags implemented via William Pugh SkipList algorithms.
+ * CACM, June 1990, p 668-676.
+ *
+ */
+
+#include <stream.h>
+#include <time.h>
+#include "<T>.SkipBag.h"
+
+MLCG* <T>SkipBag::gen = 0;
+int <T>SkipBaginit::count = 0;
+
+static int countbits(long bits)
+{
+   int n = 0;
+   while(bits>>=1L) n++;
+   return n;
+}
+
+<T>SkipBag::<T>SkipBag(long size)
+: level(0),
+  header(new <T>SkipBagNode (countbits(size)+1)),
+  max_levels (countbits(size)+1),
+  random_bits(gen->asLong()),
+  randoms_left(BITS_IN_RANDOM / 2)
+{
+  <T>SkipBagNodePtr *buffer_start = header->forward;
+  <T>SkipBagNodePtr *trav = &header->forward[max_levels];
+  
+  count = 0;
+  while (trav > buffer_start)
+    *--trav = (<T>SkipBagNodePtr) header;
+}
+
+<T>SkipBag::<T>SkipBag(<T>SkipBag& b)
+: level (0),
+  header (new <T>SkipBagNode (b.max_levels)),
+  max_levels (b.max_levels),
+  random_bits (gen->asLong()),
+  randoms_left (BITS_IN_RANDOM / 2)
+{
+  <T>SkipBagNodePtr *buffer_start = header->forward;
+  <T>SkipBagNodePtr *trav = &header->forward[max_levels];
+  
+  count = 0;
+  
+   while (trav > buffer_start)
+     *--trav = (<T>SkipBagNodePtr)header;
+  
+  for (<T>SkipBagNodePtr t = b.leftmost(); t; t = b.succ(t))
+      add(t->item);
+}
+
+Pix <T>SkipBag::add (<T&> item)
+{
+  <T>SkipBagNodePtr *update = new <T>SkipBagNodePtr[max_levels+1];
+  <T>SkipBagNodePtr curr = (<T>SkipBagNodePtr) this->header;
+  int   l = level;
+  <T>SkipBagNodePtr temp;
+  
+  do
+  {
+    while ((temp = curr->forward[l])!=header &&
+	   <T>CMP(temp->item, item) < 0)
+      curr = temp;
+    update[l] = curr;
+  } 
+  while (--l >= 0);
+  
+  if ((l = random_level ()) > level)
+  {
+    l = ++level;
+    update[l] = (<T>SkipBagNodePtr)header;
+  };
+
+  temp = new <T>RealSkipBagNode (item, l);
+  <T>SkipBagNodePtr *temp_forward = temp->forward;
+  
+  do
+  {
+    <T>SkipBagNodePtr *curr_forward = update[l]->forward;
+    
+    temp_forward[l] = curr_forward[l];
+    curr_forward[l] = temp;
+  } 
+  while (--l >= 0);
+
+  count++;
+  delete update;
+  return Pix(temp);
+}
+
+void <T>SkipBag::del(<T&> key)
+{
+  
+  int   l = level;
+  int   curr_level = level;
+  <T>SkipBagNodePtr *update = new <T>SkipBagNodePtr[max_levels+1];
+  <T>SkipBagNodePtr curr = (<T>SkipBagNodePtr)header;
+  <T>SkipBagNodePtr temp;
+  
+  do
+  {
+    while ((temp = curr->forward[l])!=header
+	   && <T>CMP(temp->item,key) < 0)
+      curr = temp;
+    update[l] = curr;
+  } 
+  while (--l >= 0);
+  
+  if (<T>CMP(temp->item,key)==0)
+  {
+    <T>SkipBagNodePtr *temp_forward = temp->forward;
+    
+    for (l = 0;
+	 l <= curr_level && (curr = update[l])->forward[l] == temp;
+	 l++)
+      curr->forward[l] = temp_forward[l];
+    
+    delete temp;
+    
+    <T>SkipBagNodePtr *forward = header->forward;
+    
+    while (forward[curr_level]==header && curr_level > 0)
+      curr_level--;
+
+    level = curr_level;
+    count--;
+    delete update;
+    return;
+  }
+}
+
+<T>SkipBagNodePtr <T>SkipBag::rightmost()
+{
+  <T>SkipBagNodePtr temp;
+  <T>SkipBagNode*   curr = header;
+  int l = level;
+  
+  do
+    while ((temp = curr->forward[l])!=header)
+      curr = temp;
+  while (--l >= 0);
+  
+  return temp==header ? 0 : temp;
+}
+
+<T>SkipBagNodePtr <T>SkipBag::pred(<T>SkipBagNodePtr t)
+{
+  <T>SkipBagNodePtr temp, curr = (<T>SkipBagNodePtr) header;
+  int l = level;
+  
+  do
+    while ((temp = curr->forward[l])!=t)
+      curr = temp;
+  while (--l >= 0);
+  
+  return curr == header ? 0 : curr;
+}
+
+void <T>SkipBag::_kill()
+{
+  <T>SkipBagNode *p = this->header->forward[0];
+  
+  while (p != header)
+  {
+    <T>SkipBagNodePtr q = p->forward[0];
+    delete p;
+    p = q;
+  }
+}
+
+void <T>SkipBag::clear()
+{
+  <T>SkipBagNodePtr *buffer_start = header->forward;
+  <T>SkipBagNodePtr *trav = &header->forward[level+1];
+  _kill();
+  count = 0;
+    
+  while (trav > buffer_start)
+    *--trav = (<T>SkipBagNodePtr)header;
+}
+
+Pix <T>SkipBag::seek(<T&> key, Pix i)
+{
+  <T>SkipBagNodePtr temp;
+  <T>SkipBagNode *curr  = header;
+  int   l = level;
+  if (i)
+      curr = (<T>SkipBagNode *)i;
+  
+  do
+  {
+    while ((temp = curr->forward[l])!=header &&
+	   <T>CMP(temp->item, key) < 0)
+      curr = temp;
+  }
+  while (--l >= 0);
+  
+  if (<T>CMP(temp->item, key) != 0)
+    return 0;
+  else
+  {
+    return Pix(temp);
+  }
+}
+
+
+int <T>SkipBag::nof(<T&> item)
+{
+    int n = 0;
+    <T>SkipBagNodePtr t = (<T>SkipBagNodePtr)(seek(item));
+    if (t != 0)
+    {
+	do
+	{
+	    ++n;
+	    t = succ(t);
+	} while (t != 0 && <T>EQ(item, t->item));
+    }
+    return n;
+}
+
+void <T>SkipBag::remove(<T&> key)
+{
+    Pix t = seek(key);
+    while (t != 0)
+    {
+	del(key);
+	t = seek(key);
+    }
+}
+
+
+/*
+ * random function for probabilistic balancing
+ *
+ * Hardwired for p = .25.  Not too flexible,
+ * but fast.  Changing this would require a constructor
+ * that would accept a different value for p, etc.
+ * Perhaps someone else would like to implement this?
+ *
+ */
+int <T>SkipBag::random_level (void)
+{
+  int rlevel = 0;
+  int b;
+  
+  do
+  {
+    b = random_bits & 3L;
+    if (!b)
+      rlevel++;
+    random_bits >>= 2;
+    if (--randoms_left == 0)
+    {
+      random_bits = gen->asLong();
+      randoms_left = BITS_IN_RANDOM / 2;
+    };
+  } 
+  while (!b);
+  
+  return rlevel > max_levels ? max_levels : rlevel;
+}
+
+int <T>SkipBag::OK()
+{
+  int v = 1;
+  if (header == 0) 
+    v = 0;
+  else
+  {
+    int n = 0;
+    <T>SkipBagNodePtr trail = leftmost();
+    <T>SkipBagNodePtr t = 0;
+    if (trail) t = succ(trail);
+    if (t) n++;
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
+
+<T>SkipBaginit::<T>SkipBaginit()
+{
+    if (!count)
+	<T>SkipBag::gen = new MLCG(time(0));
+    count++;
+}
+
+<T>SkipBaginit::~<T>SkipBaginit()
+{
+    count--;
+    if (!count)
+	delete <T>SkipBag::gen;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/SkipBag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SkipBag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SkipBag.hP	(revision 18)
@@ -0,0 +1,171 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1991 Free Software Foundation
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * Bags implemented via William Pugh SkipList algorithms.
+ * CACM, June 1990, p 668-676.
+ *
+ */
+
+#ifndef _<T>SkipBag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SkipBag_h 1
+
+#include "<T>.Bag.h"
+
+#include <limits.h>
+#include <MLCG.h>
+
+class <T>SkipBag;
+class <T>RealSkipBagNode;
+
+class <T>SkipBagNode
+{
+friend class <T>SkipBag;
+  private:
+    <T>RealSkipBagNode * * forward;
+    <T>SkipBagNode(int size);
+};
+
+class <T>RealSkipBagNode : public <T>SkipBagNode
+{
+friend class <T>SkipBag;
+  private:
+    <T>             item;
+    <T>RealSkipBagNode(<T&> h, int size);
+};
+
+typedef <T>RealSkipBagNode* <T>SkipBagNodePtr;
+
+inline <T>SkipBagNode::<T>SkipBagNode(int size)
+: forward(new <T>SkipBagNodePtr[size+1])
+{
+}
+
+inline <T>RealSkipBagNode::<T>RealSkipBagNode(<T&> h, int size)
+: item(h),
+  <T>SkipBagNode(size)
+{
+}
+
+class <T>SkipBag : public <T>Bag
+{
+friend class <T>SkipBaginit;
+  protected:
+    <T>SkipBagNode*   header;
+    int               level;
+    int               max_levels;
+    int               randoms_left;
+    long              random_bits;
+    
+    static MLCG*      gen;
+    int               random_level(void);
+    
+    <T>SkipBagNodePtr leftmost(void);
+    <T>SkipBagNodePtr rightmost(void);
+    <T>SkipBagNodePtr pred(<T>SkipBagNodePtr t);
+    <T>SkipBagNodePtr succ(<T>SkipBagNodePtr t);
+    void              _kill(void);
+    
+  private:
+    enum { BITS_IN_RANDOM = LONGBITS-1 };
+    
+  public:
+    <T>SkipBag(long size=DEFAULT_INITIAL_CAPACITY);
+    <T>SkipBag(<T>SkipBag& a);
+    ~<T>SkipBag(void);
+    
+    Pix           add(<T&> i);
+    void          del(<T&> i);
+    void          remove(<T&>i);
+    int           nof(<T&> i);
+    int           contains(<T&> i);
+    
+    void          clear(void);
+    
+    Pix           first(void);
+    void          next(Pix& i);
+    <T>&          operator () (Pix i);
+    Pix           seek(<T&> i, Pix from = 0);
+    
+    Pix           last(void);
+    void          prev(Pix& i);
+    
+    int           OK(void);
+};
+
+inline <T>SkipBagNodePtr <T>SkipBag::leftmost(void)
+{
+    return header->forward[0];
+}
+
+inline <T>SkipBagNodePtr <T>SkipBag::succ(<T>SkipBagNodePtr t)
+{
+    <T>SkipBagNodePtr result = 0;
+    if (t->forward[0]!=header) result = t->forward[0];
+    return result;
+}
+
+inline Pix <T>SkipBag::first(void)
+{
+    return Pix(leftmost());
+}
+
+inline Pix <T>SkipBag::last(void)
+{
+    return Pix(rightmost());
+}
+
+inline void <T>SkipBag::next(Pix& i)
+{
+    if (i != 0) i = Pix(succ((<T>SkipBagNodePtr)i));
+}
+
+inline <T>& <T>SkipBag::operator () (Pix i)
+{
+    if (i == 0) error("null Pix");
+    return ((<T>SkipBagNodePtr)i)->item;
+}
+
+inline void <T>SkipBag::prev(Pix& i)
+{
+    if (i != 0) i = Pix(pred((<T>SkipBagNodePtr)i));
+}
+
+inline int <T>SkipBag::contains(<T&> key)
+{
+    return seek(key) != 0;
+}
+
+inline <T>SkipBag::~<T>SkipBag()
+{
+    _kill();
+    delete header;
+}
+
+static class <T>SkipBaginit
+{
+  public:
+    <T>SkipBaginit();
+    ~<T>SkipBaginit();
+  private:
+    static int count;
+} <T>skipBaginit;
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SkipMap.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SkipMap.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SkipMap.ccP	(revision 18)
@@ -0,0 +1,307 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1991 Free Software Foundation
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+#include <stream.h>
+#include <time.h>
+#include "<T>.<C>.SkipMap.h"
+
+/*
+ * Bags implemented via William Pugh SkipList algorithms.
+ * CACM, June 1990, p 668-676.
+ *
+ */
+
+MLCG* <T><C>SkipMap::gen = 0;
+int <T><C>SkipMapinit::count = 0;
+
+static int countbits(long bits)
+{
+  int n = 0;
+  while(bits>>=1) n++;
+  return n;
+}
+
+<T><C>SkipMap::<T><C>SkipMap(<C&> dflt, long size)
+: <T><C>Map(dflt),
+  level(0),
+  header(new <T><C>SkipMapNode (countbits(size)+1)),
+  max_levels (countbits(size)+1),
+  random_bits(gen->asLong()),
+  randoms_left(BITS_IN_RANDOM / 2)
+{
+  <T><C>SkipMapNodePtr *buffer_start = header->forward;
+  <T><C>SkipMapNodePtr *trav = &header->forward[max_levels];
+  
+  count = 0;
+  while (trav > buffer_start)
+    *--trav = (<T><C>SkipMapNodePtr) header;
+}
+
+<T><C>SkipMap::<T><C>SkipMap(<T><C>SkipMap& b)
+: <T><C>Map(b.def),
+  level (0),
+  header (new <T><C>SkipMapNode (b.max_levels)),
+  max_levels (b.max_levels),
+  random_bits (gen->asLong()),
+  randoms_left (BITS_IN_RANDOM / 2)
+{
+  <T><C>SkipMapNodePtr *buffer_start = header->forward;
+  <T><C>SkipMapNodePtr *trav = &header->forward[max_levels];
+  
+  count = 0;
+  
+   while (trav > buffer_start)
+     *--trav = (<T><C>SkipMapNodePtr)header;
+  
+  for (<T><C>SkipMapNodePtr t = b.leftmost(); t; t = b.succ(t))
+    (*this)[t->item] = t->cont;
+}
+
+<C>& <T><C>SkipMap::operator [] (<T&> item)
+{
+  <T><C>SkipMapNodePtr *update = new <T><C>SkipMapNodePtr[max_levels+1];
+  <T><C>SkipMapNodePtr curr =
+    (<T><C>SkipMapNodePtr) this->header;
+  int   l = level;
+  <T><C>SkipMapNodePtr temp;
+  
+  do
+  {
+    while ((temp = curr->forward[l])!=header &&
+	   <T>CMP(temp->item, item) < 0)
+      curr = temp;
+    update[l] = curr;
+  } 
+  while (--l >= 0);
+  
+  if (temp != header && <T>CMP(temp->item, item) == 0)
+  {
+      delete update;
+      return temp->cont;
+  }
+
+  if ((l = random_level ()) > level)
+  {
+    l = ++level;
+    update[l] = (<T><C>SkipMapNodePtr)header;
+  };
+
+  temp = new <T><C>RealSkipMapNode (item, def, l);
+  <T><C>SkipMapNodePtr *temp_forward = temp->forward;
+  
+  do
+  {
+    <T><C>SkipMapNodePtr *curr_forward = update[l]->forward;
+    
+    temp_forward[l] = curr_forward[l];
+    curr_forward[l] = temp;
+  } 
+  while (--l >= 0);
+
+  count++;
+  delete update;
+  return temp->cont;
+}
+
+void <T><C>SkipMap::del(<T&> key)
+{
+  
+  int   l = level;
+  int   curr_level = level;
+  <T><C>SkipMapNodePtr *update = new <T><C>SkipMapNodePtr[max_levels+1];
+  <T><C>SkipMapNodePtr curr = (<T><C>SkipMapNodePtr)header;
+  <T><C>SkipMapNodePtr temp;
+  
+  do
+  {
+    while ((temp = curr->forward[l])!=header
+	   && <T>CMP(temp->item,key) < 0)
+      curr = temp;
+    update[l] = curr;
+  } 
+  while (--l >= 0);
+  
+  if (<T>CMP(temp->item,key)==0)
+  {
+    <T><C>SkipMapNodePtr *temp_forward = temp->forward;
+    
+    for (l = 0;
+	 l <= curr_level && (curr = update[l])->forward[l] == temp;
+	 l++)
+      curr->forward[l] = temp_forward[l];
+    
+    delete temp;
+    
+    <T><C>SkipMapNodePtr *forward = header->forward;
+    
+    while (forward[curr_level]==header && curr_level > 0)
+      curr_level--;
+    
+    level = curr_level;
+    count--;
+    delete update;
+    return;
+  }
+}
+
+<T><C>SkipMapNodePtr <T><C>SkipMap::rightmost()
+{
+  <T><C>SkipMapNodePtr temp;
+  <T><C>SkipMapNode*   curr = header;
+  int l = level;
+  
+  do
+    while ((temp = curr->forward[l])!=header)
+      curr = temp;
+  while (--l >= 0);
+  
+  return temp==header ? 0 : temp;
+}
+
+<T><C>SkipMapNodePtr <T><C>SkipMap::pred(<T><C>SkipMapNodePtr t)
+{
+  <T><C>SkipMapNodePtr temp, curr = (<T><C>SkipMapNodePtr) header;
+  int l = level;
+  
+  do
+    while ((temp = curr->forward[l])!=t)
+      curr = temp;
+  while (--l >= 0);
+  
+  return curr == header ? 0 : curr;
+}
+
+void <T><C>SkipMap::_kill()
+{
+  <T><C>SkipMapNode *p = this->header->forward[0];
+  
+  while (p != header)
+  {
+    <T><C>SkipMapNodePtr q = p->forward[0];
+    delete p;
+    p = q;
+  }
+}
+
+void <T><C>SkipMap::clear()
+{
+  <T><C>SkipMapNodePtr *buffer_start = header->forward;
+  <T><C>SkipMapNodePtr *trav = &header->forward[level+1];
+  _kill();
+  count = 0;
+    
+  while (trav > buffer_start)
+    *--trav = (<T><C>SkipMapNodePtr)header;
+}
+
+Pix <T><C>SkipMap::seek(<T&> key)
+{
+  <T><C>SkipMapNodePtr temp;
+  <T><C>SkipMapNode *curr  = header;
+  int   l = level;
+    
+  do
+  {
+    while ((temp = curr->forward[l])!=header &&
+	   <T>CMP(temp->item, key) < 0)
+      curr = temp;
+  }
+  while (--l >= 0);
+  
+  if (<T>CMP(temp->item, key) != 0)
+    return 0;
+  else
+  {
+    return Pix(temp);
+  }
+}
+
+/*
+ * random function for probabilistic balancing
+ *
+ * Hardwired for p = .25.  Not too flexible,
+ * but fast.  Changing this would require a constructor
+ * that would accept a different value for p, etc.
+ * Perhaps someone else would like to implement this?
+ *
+ */
+int <T><C>SkipMap::random_level (void)
+{
+  int rlevel = 0;
+  int b;
+  
+  do
+  {
+    b = random_bits & 3L;
+    if (!b)
+      rlevel++;
+    random_bits >>= 2;
+    if (--randoms_left == 0)
+    {
+      random_bits = gen->asLong();
+      randoms_left = BITS_IN_RANDOM / 2;
+    };
+  } 
+  while (!b);
+  
+  return rlevel > max_levels ? max_levels : rlevel;
+}
+
+int <T><C>SkipMap::OK()
+{
+  int v = 1;
+  if (header == 0) 
+    v = 0;
+  else
+  {
+    int n = 0;
+    <T><C>SkipMapNodePtr trail = leftmost();
+    <T><C>SkipMapNodePtr t = 0;
+    if (trail) t = succ(trail);
+    if (t) n++;
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
+
+<T><C>SkipMapinit::<T><C>SkipMapinit()
+{
+    if (!count)
+	<T><C>SkipMap::gen = new MLCG(time(0));
+    count++;
+}
+
+<T><C>SkipMapinit::~<T><C>SkipMapinit()
+{
+    count--;
+    if (!count)
+	delete <T><C>SkipMap::gen;
+}
+
+	    
Index: trunk/src/emx/include/Attic/cpp/gen/SkipMap.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SkipMap.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SkipMap.hP	(revision 18)
@@ -0,0 +1,176 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1991 Free Software Foundation
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * Bags implemented via William Pugh SkipList algorithms.
+ * CACM, June 1990, p 668-676.
+ *
+ */
+
+#ifndef _<T><C>SkipMap_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T><C>SkipMap_h 1
+
+#include "<T>.<C>.Map.h"
+
+#include <limits.h>
+#include <MLCG.h>
+
+class <T><C>SkipMap;
+class <T><C>RealSkipMapNode;
+
+class <T><C>SkipMapNode
+{
+friend class <T><C>SkipMap;
+  private:
+    <T><C>RealSkipMapNode * * forward;
+  protected:
+    <T><C>SkipMapNode(int size);
+};
+
+class <T><C>RealSkipMapNode : public <T><C>SkipMapNode
+{
+friend class <T><C>SkipMap;
+  private:
+    <T>             item;
+    <C>             cont;
+    <T><C>RealSkipMapNode(<T&> h, <C&> i, int size);
+};
+
+typedef <T><C>RealSkipMapNode* <T><C>SkipMapNodePtr;
+
+inline <T><C>SkipMapNode::<T><C>SkipMapNode(int size)
+: forward(new <T><C>SkipMapNodePtr[size+1])
+{
+}
+
+inline <T><C>RealSkipMapNode::<T><C>RealSkipMapNode(<T&> h, <C&> i, int size)
+: item(h), cont(i),
+  <T><C>SkipMapNode(size)
+{
+}
+
+class <T><C>SkipMap : public <T><C>Map
+{
+friend class <T><C>SkipMapinit;
+  protected:
+    <T><C>SkipMapNode*   header;
+    int                  level;
+    int                  max_levels;
+    int                  randoms_left;
+    long                 random_bits;
+    
+    static MLCG*         gen;
+    int                  random_level(void);
+    
+    <T><C>SkipMapNodePtr leftmost();
+    <T><C>SkipMapNodePtr rightmost();
+    <T><C>SkipMapNodePtr pred(<T><C>SkipMapNodePtr t);
+    <T><C>SkipMapNodePtr succ(<T><C>SkipMapNodePtr t);
+    void                 _kill();
+  private:
+    enum { BITS_IN_RANDOM = LONGBITS-1 };
+    
+  public:
+    <T><C>SkipMap( <C&> dflt, long size=DEFAULT_INITIAL_CAPACITY);
+    <T><C>SkipMap(<T><C>SkipMap& a);
+    ~<T><C>SkipMap();
+    
+    <C>&          operator [] (<T&> key);
+    
+    void          del(<T&> key);
+    
+    Pix           first();
+    void          next(Pix& i);
+    <T>&          key(Pix i);
+    <C>&          contents(Pix i);
+    
+    Pix           seek(<T&> key);
+    int           contains(<T&> key);
+    void          clear(); 
+    
+    Pix           last();
+    void          prev(Pix& i);
+    
+    int           OK();
+};
+
+inline <T><C>SkipMap::~<T><C>SkipMap()
+{
+    _kill();
+    delete header;
+}
+
+inline <T><C>SkipMapNodePtr <T><C>SkipMap::leftmost()
+{
+    return header->forward[0]==header ? 0 : header->forward[0];
+}
+
+inline Pix <T><C>SkipMap::first()
+{
+    return Pix(leftmost());
+}
+
+inline Pix <T><C>SkipMap::last()
+{
+    return Pix(rightmost());
+}
+
+inline <T><C>SkipMapNodePtr <T><C>SkipMap::succ(<T><C>SkipMapNodePtr t)
+{
+    return t->forward[0]==header ? 0 : t->forward[0];
+}
+
+inline void <T><C>SkipMap::next(Pix& i)
+{
+    if (i != 0) i = Pix(succ((<T><C>SkipMapNodePtr)i));
+}
+
+inline void <T><C>SkipMap::prev(Pix& i)
+{
+    if (i != 0) i = Pix(pred((<T><C>SkipMapNodePtr)i));
+}
+
+inline <T>& <T><C>SkipMap::key (Pix i)
+{
+    if (i == 0) error("null Pix");
+    return ((<T><C>SkipMapNodePtr)i)->item;
+}
+
+inline <C>& <T><C>SkipMap::contents (Pix i)
+{
+    if (i == 0) error("null Pix");
+    return ((<T><C>SkipMapNodePtr)i)->cont;
+}
+
+inline int <T><C>SkipMap::contains(<T&> key)
+{
+    return seek(key) != 0;
+}
+
+static class <T><C>SkipMapinit
+{
+  public:
+    <T><C>SkipMapinit();
+    ~<T><C>SkipMapinit();
+  private:
+    static int count;
+} <T><C>skipMapinit;
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SkipSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SkipSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SkipSet.ccP	(revision 18)
@@ -0,0 +1,395 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1991 Free Software Foundation
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * Sets implemented via William Pugh SkipList algorithms.
+ * CACM, June 1990, p 668-676.
+ *
+ */
+
+#include <stream.h>
+#include <time.h>
+
+#include "<T>.SkipSet.h"
+
+MLCG* <T>SkipSet::gen = 0;
+int <T>SkipSetinit::count = 0;
+
+static int countbits(long bits)
+{
+   int n = 0;
+   while(bits>>=1L) n++;
+   return n;
+}
+
+<T>SkipSet::<T>SkipSet(long size)
+: level(0),
+  header(new <T>SkipSetNode (countbits(size)+1)),
+  max_levels (countbits(size)+1),
+  random_bits(gen->asLong()),
+  randoms_left(BITS_IN_RANDOM / 2)
+{
+  <T>SkipSetNodePtr *buffer_start = header->forward;
+  <T>SkipSetNodePtr *trav = &header->forward[max_levels];
+  
+  count = 0;
+  while (trav > buffer_start)
+    *--trav = (<T>SkipSetNodePtr) header;
+}
+
+<T>SkipSet::<T>SkipSet(<T>SkipSet& b)
+: level (0),
+  header (new <T>SkipSetNode (b.max_levels)),
+  max_levels (b.max_levels),
+  random_bits (gen->asLong()),
+  randoms_left (BITS_IN_RANDOM / 2)
+{
+  <T>SkipSetNodePtr *buffer_start = header->forward;
+  <T>SkipSetNodePtr *trav = &header->forward[max_levels];
+  
+  count = 0;
+  
+   while (trav > buffer_start)
+     *--trav = (<T>SkipSetNodePtr)header;
+  
+  for (<T>SkipSetNodePtr t = b.leftmost(); t; t = b.succ(t))
+      add(t->item);
+}
+
+/* relationals */
+
+int <T>SkipSet::operator == (<T>SkipSet& y)
+{
+  if (count != y.count)
+    return 0;
+  else
+  {
+    <T>SkipSetNodePtr t = leftmost();
+    <T>SkipSetNodePtr u = y.leftmost();
+    for (;;)
+    {
+      if (t == 0)
+        return 1;
+      else if (!<T>EQ(t->item, u->item))
+        return 0;
+      else
+      {
+        t = succ(t);
+        u = y.succ(u);
+      }
+    }
+  }
+}
+
+int <T>SkipSet::operator <= (<T>SkipSet& y)
+{
+  if (count > y.count)
+    return 0;
+  else
+  {
+    <T>SkipSetNodePtr t = leftmost();
+    <T>SkipSetNodePtr u = y.leftmost();
+    for (;;)
+    {
+      if (t == 0)
+        return 1;
+      else if (u == 0)
+        return 0;
+      int cmp = <T>CMP(t->item, u->item);
+      if (cmp == 0)
+      {
+        t = succ(t);
+        u = y.succ(u);
+      }
+      else if (cmp < 0)
+        return 0;
+      else
+        u = y.succ(u);
+    }
+  }
+}
+
+
+void <T>SkipSet::operator |=(<T>SkipSet& y)
+{
+  if (&y == this) return;
+  <T>SkipSetNodePtr u = y.leftmost();
+  while (u != 0)
+  {
+    add(u->item);
+    u = y.succ(u);
+  }
+}
+
+void <T>SkipSet::operator &= (<T>SkipSet& y)
+{
+  if (y.count == 0)
+    clear();
+  else if (&y != this && count != 0)
+  {
+    <T>SkipSetNodePtr t = leftmost();
+    while (t != 0)
+    {
+      <T>SkipSetNodePtr s = succ(t);
+      if (y.seek(t->item) == 0) del(t->item);
+      t = s;
+    }
+  }
+}
+
+
+void <T>SkipSet::operator -=(<T>SkipSet& y)
+{
+  if (&y == this)
+    clear();
+  else if (y.count != 0)
+  {
+    <T>SkipSetNodePtr t = leftmost();
+    while (t != 0)
+    {
+      <T>SkipSetNodePtr s = succ(t);
+      if (y.seek(t->item) != 0) del(t->item);
+      t = s;
+    }
+  }
+}
+
+Pix <T>SkipSet::add (<T&> i)
+{
+  <T>SkipSetNodePtr *update = new <T>SkipSetNodePtr[max_levels+1];
+  <T>SkipSetNodePtr curr = (<T>SkipSetNodePtr) this->header;
+  int   l = level;
+  <T>SkipSetNodePtr temp;
+  
+  do
+  {
+    while ((temp = curr->forward[l])!=header &&
+	   <T>CMP(temp->item, i) < 0)
+      curr = temp;
+    update[l] = curr;
+  } 
+  while (--l >= 0);
+  
+  if (temp != header && <T>CMP(temp->item, i) == 0)
+    return Pix(temp);
+
+  if ((l = random_level ()) > level)
+  {
+    l = ++level;
+    update[l] = (<T>SkipSetNodePtr)header;
+  };
+
+  temp = new <T>RealSkipSetNode (i, l);
+  <T>SkipSetNodePtr *temp_forward = temp->forward;
+  
+  do
+  {
+    <T>SkipSetNodePtr *curr_forward = update[l]->forward;
+    
+    temp_forward[l] = curr_forward[l];
+    curr_forward[l] = temp;
+  } 
+  while (--l >= 0);
+
+  count++;
+  delete update;
+  return Pix(temp);
+}
+
+void <T>SkipSet::del(<T&> key)
+{
+  
+  int   l = level;
+  int   curr_level = level;
+  <T>SkipSetNodePtr *update = new <T>SkipSetNodePtr[max_levels+1];
+  <T>SkipSetNodePtr curr = (<T>SkipSetNodePtr)header;
+  <T>SkipSetNodePtr temp;
+  
+  do
+  {
+    while ((temp = curr->forward[l])!=header
+	   && <T>CMP(temp->item,key) < 0)
+      curr = temp;
+    update[l] = curr;
+  } 
+  while (--l >= 0);
+  
+  if (<T>CMP(temp->item,key)==0)
+  {
+    <T>SkipSetNodePtr *temp_forward = temp->forward;
+    
+    for (l = 0;
+	 l <= curr_level && (curr = update[l])->forward[l] == temp;
+	 l++)
+      curr->forward[l] = temp_forward[l];
+    
+    delete temp;
+    
+    <T>SkipSetNodePtr *forward = header->forward;
+    
+    while (forward[curr_level]==header && curr_level > 0)
+      curr_level--;
+
+    level = curr_level;
+    count--;
+    delete update;
+    return;
+  }
+}
+
+<T>SkipSetNodePtr <T>SkipSet::rightmost()
+{
+  <T>SkipSetNodePtr temp;
+  <T>SkipSetNode*   curr = header;
+  int l = level;
+  
+  do
+    while ((temp = curr->forward[l])!=header)
+      curr = temp;
+  while (--l >= 0);
+  
+  return temp==header ? 0 : temp;
+}
+
+<T>SkipSetNodePtr <T>SkipSet::pred(<T>SkipSetNodePtr t)
+{
+  <T>SkipSetNodePtr temp, curr = (<T>SkipSetNodePtr) header;
+  int l = level;
+  
+  do
+    while ((temp = curr->forward[l])!=t)
+      curr = temp;
+  while (--l >= 0);
+  
+  return curr == header ? 0 : curr;
+}
+
+void <T>SkipSet::_kill()
+{
+  <T>SkipSetNode *p = this->header->forward[0];
+  
+  while (p != header)
+  {
+    <T>SkipSetNodePtr q = p->forward[0];
+    delete p;
+    p = q;
+  }
+}
+
+void <T>SkipSet::clear()
+{
+  <T>SkipSetNodePtr *buffer_start = header->forward;
+  <T>SkipSetNodePtr *trav = &header->forward[level+1];
+  _kill();
+  count = 0;
+    
+  while (trav > buffer_start)
+    *--trav = (<T>SkipSetNodePtr)header;
+}
+
+Pix <T>SkipSet::seek(<T&> key)
+{
+  <T>SkipSetNodePtr temp;
+  <T>SkipSetNode *curr  = header;
+  int   l = level;
+  
+  do
+  {
+    while ((temp = curr->forward[l])!=header &&
+	   <T>CMP(temp->item, key) < 0)
+      curr = temp;
+  }
+  while (--l >= 0);
+  
+  if (<T>CMP(temp->item, key) != 0)
+    return 0;
+  else
+  {
+    return Pix(temp);
+  }
+}
+
+
+/*
+ * random function for probabilistic balancing
+ *
+ * Hardwired for p = .25.  Not too flexible,
+ * but fast.  Changing this would require a constructor
+ * that would accept a different value for p, etc.
+ * Perhaps someone else would like to implement this?
+ *
+ */
+int <T>SkipSet::random_level (void)
+{
+  int rlevel = 0;
+  int b;
+  
+  do
+  {
+    b = random_bits & 3L;
+    if (!b)
+      rlevel++;
+    random_bits >>= 2;
+    if (--randoms_left == 0)
+    {
+      random_bits = gen->asLong();
+      randoms_left = BITS_IN_RANDOM / 2;
+    };
+  } 
+  while (!b);
+  
+  return rlevel > max_levels ? max_levels : rlevel;
+}
+
+int <T>SkipSet::OK()
+{
+  int v = 1;
+  if (header == 0) 
+    v = 0;
+  else
+  {
+    int n = 0;
+    <T>SkipSetNodePtr trail = leftmost();
+    <T>SkipSetNodePtr t = 0;
+    if (trail) t = succ(trail);
+    if (t) n++;
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
+
+<T>SkipSetinit::<T>SkipSetinit()
+{
+    if (!count)
+	<T>SkipSet::gen = new MLCG(time(0));
+    count++;
+}
+
+<T>SkipSetinit::~<T>SkipSetinit()
+{
+    count--;
+    if (!count)
+	delete <T>SkipSet::gen;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/SkipSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SkipSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SkipSet.hP	(revision 18)
@@ -0,0 +1,187 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1991 Free Software Foundation
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * Sets implemented via William Pugh SkipList algorithms.
+ * CACM, June 1990, p 668-676.
+ *
+ */
+
+#ifndef _<T>SkipSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SkipSet_h 1
+
+#include "<T>.Set.h"
+
+#include <limits.h>
+#include <MLCG.h>
+
+class <T>SkipSet;
+class <T>RealSkipSetNode;
+
+class <T>SkipSetNode
+{
+friend class <T>SkipSet;
+  private:
+    <T>RealSkipSetNode * * forward;
+    <T>SkipSetNode(int size);
+};
+
+class <T>RealSkipSetNode : public <T>SkipSetNode
+{
+friend class <T>SkipSet;
+  private:
+    <T>             item;
+    <T>RealSkipSetNode(<T&> h, int size);
+};
+
+typedef <T>RealSkipSetNode* <T>SkipSetNodePtr;
+
+inline <T>SkipSetNode::<T>SkipSetNode(int size)
+: forward(new <T>SkipSetNodePtr[size+1])
+{
+}
+
+inline <T>RealSkipSetNode::<T>RealSkipSetNode(<T&> h, int size)
+: item(h),
+  <T>SkipSetNode(size)
+{
+}
+
+class <T>SkipSet : public <T>Set
+{
+friend class <T>SkipSetinit;
+  protected:
+    <T>SkipSetNode*   header;
+    int               level;
+    int               max_levels;
+    int               randoms_left;
+    long              random_bits;
+    
+    static MLCG*      gen;
+    int               random_level(void);
+    
+    <T>SkipSetNodePtr leftmost(void);
+    <T>SkipSetNodePtr rightmost(void);
+    <T>SkipSetNodePtr pred(<T>SkipSetNodePtr t);
+    <T>SkipSetNodePtr succ(<T>SkipSetNodePtr t);
+    void              _kill(void);
+    
+  private:
+    enum { BITS_IN_RANDOM = LONGBITS-1 };
+  public:
+    <T>SkipSet(long size=DEFAULT_INITIAL_CAPACITY);
+    <T>SkipSet(<T>SkipSet& a);
+    ~<T>SkipSet();
+    
+    Pix             add(<T&> i);
+    void            del(<T&> i);
+    int             contains(<T&> i);
+    
+    void            clear(void);
+    
+    Pix             first(void);
+    void            next(Pix& i);
+    <T>&            operator () (Pix i);
+    Pix             seek(<T&> i);
+    
+    Pix             last(void);
+    void            prev(Pix& i);
+    
+    void            operator |= (<T>SkipSet& b);
+    void            operator -= (<T>SkipSet& b);
+    void            operator &= (<T>SkipSet& b);
+    
+    int             operator == (<T>SkipSet& b);
+    int             operator != (<T>SkipSet& b);
+    int             operator <= (<T>SkipSet& b); 
+    
+    int             OK(void);
+};
+
+/*
+ *  A little overkill on the inlines.
+ *
+ */
+
+inline <T>SkipSet::~<T>SkipSet(void)
+{
+  _kill();
+  delete header;
+}
+
+inline int <T>SkipSet::operator != (<T>SkipSet& b)
+{
+  return ! (*this == b);
+}
+
+inline <T>SkipSetNodePtr <T>SkipSet::leftmost(void)
+{
+  return header->forward[0];
+}
+
+inline <T>SkipSetNodePtr <T>SkipSet::succ(<T>SkipSetNodePtr t)
+{
+  <T>SkipSetNodePtr result = 0;
+  if (t->forward[0]!=header) result = t->forward[0];
+  return result;
+}
+
+inline Pix <T>SkipSet::first(void)
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T>SkipSet::last(void)
+{
+  return Pix(rightmost());
+}
+
+inline void <T>SkipSet::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T>SkipSetNodePtr)i));
+}
+
+inline void <T>SkipSet::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T>SkipSetNodePtr)i));
+}
+
+inline <T>& <T>SkipSet::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T>SkipSetNodePtr)i)->item;
+}
+
+
+inline int <T>SkipSet::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+static class <T>SkipSetinit
+{
+  public:
+    <T>SkipSetinit();
+    ~<T>SkipSetinit();
+  private:
+    static int count;
+} <T>skipSetinit;
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SplayBag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplayBag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplayBag.ccP	(revision 18)
@@ -0,0 +1,445 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.SplayBag.h"
+
+
+/* 
+
+ struct to simulate the special `null' node in the Sleater & Tarjan JACM 1985
+ splay tree algorithms
+
+ All routines use a version of their `simple top-down' splay alg. (p 669)
+
+*/
+
+struct _dummySplayNode
+{
+  <T>SplayNode*    lt;
+  <T>SplayNode*    rt;
+  <T>SplayNode*    par;
+} _dummy_null;
+
+
+/*
+ traversal primitives
+*/
+
+
+<T>SplayNode* <T>SplayBag::leftmost()
+{
+  <T>SplayNode* t = root;
+  if (t != 0) while (t->lt != 0) t = t->lt;
+  return t;
+}
+
+<T>SplayNode* <T>SplayBag::rightmost()
+{
+  <T>SplayNode* t = root;
+  if (t != 0) while (t->rt != 0) t = t->rt;
+  return t;
+}
+
+<T>SplayNode* <T>SplayBag::succ(<T>SplayNode* t)
+{
+  if (t == 0)
+    return 0;
+  if (t->rt != 0)
+  {
+    t = t->rt;
+    while (t->lt != 0) t = t->lt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->lt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+<T>SplayNode* <T>SplayBag::pred(<T>SplayNode* t)
+{
+  if (t == 0)
+    return 0;
+  else if (t->lt != 0)
+  {
+    t = t->lt;
+    while (t->rt != 0) t = t->rt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->rt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+
+
+Pix <T>SplayBag::seek(<T&> key, Pix i)
+{
+  if (root == 0) return 0;
+
+  <T>SplayNode* t = (<T>SplayNode*) i;
+  if (t != 0)
+  {
+    int cmp = <T>CMP(key, t->item);
+    if (cmp == 0)
+    {
+      t = succ(t);
+      if (t != 0 && <T>EQ(key, t->item))
+        return Pix(t);
+      else
+        return 0;
+    }
+    else if (cmp < 0)
+      return 0;
+  }
+
+  t = root;
+  int comp = <T>CMP(key, t->item);
+  if (comp == 0)
+    return Pix(t);
+
+  <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null);
+  <T>SplayNode* l = dummy;
+  <T>SplayNode* r = dummy;
+  dummy->rt = dummy->lt = dummy->par = 0;
+
+  while (comp != 0)
+  {
+    if (comp > 0)
+    {
+      <T>SplayNode* tr = t->rt;
+      if (tr == 0)
+        break;
+      else
+      {
+        comp = <T>CMP(key, tr->item);
+        if (comp <= 0 || tr->rt == 0)
+        {
+          l->rt = t; t->par = l;
+          l = t;
+          t = tr;
+          if (comp >= 0)
+            break;
+        }
+        else
+        {
+          if ((t->rt = tr->lt) != 0) t->rt->par = t;
+          tr->lt = t; t->par = tr;
+          l->rt = tr; tr->par = l;
+          l = tr;
+          t = tr->rt;
+          comp = <T>CMP(key, t->item);
+        }
+      }
+    }
+    else
+    {
+      <T>SplayNode* tl = t->lt;
+      if (tl == 0)
+        break;
+      else
+      {
+        comp = <T>CMP(key, tl->item);
+        if (comp >= 0 || tl->lt == 0)
+        {
+          r->lt = t; t->par = r;
+          r = t;
+          t = tl;
+          if (comp <= 0)
+            break;
+        }
+        else
+        {
+          if ((t->lt = tl->rt) != 0) t->lt->par = t;
+          tl->rt = t; t->par = tl;
+          r->lt = tl; tl->par = r;
+          r = tl;
+          t = tl->lt;
+          comp = <T>CMP(key, t->item);
+        }
+      }
+    }
+  }
+  if ((r->lt = t->rt) != 0) r->lt->par = r;
+  if ((l->rt = t->lt) != 0) l->rt->par = l;
+  if ((t->lt = dummy->rt) != 0) t->lt->par = t;
+  if ((t->rt = dummy->lt) != 0) t->rt->par = t;
+  t->par = 0;
+  root = t;
+  if (comp != 0)
+    return 0;
+  else
+  {
+    l = pred(t);
+    while (l != 0 && <T>EQ(l->item, key)) { t = l; l = pred(l); }
+    return Pix(t);
+  }
+}
+
+int <T>SplayBag::nof(<T&> item)
+{
+  int n = 0;
+  <T>SplayNode* t = (<T>SplayNode*)(seek(item));
+  if (t != 0)
+  {
+    do
+    {
+      ++n;
+      t = succ(t);
+    } while (t != 0 && <T>EQ(item, t->item));
+  }
+  return n;
+}
+
+Pix <T>SplayBag::add(<T&> item)
+{
+  ++count;
+  <T>SplayNode* newnode = new <T>SplayNode(item);
+  <T>SplayNode* t = root;
+  if (t == 0)
+  {
+    root = newnode;
+    return Pix(root);
+  }
+
+  int comp = <T>CMP(item, t->item);
+
+  <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null);
+  <T>SplayNode* l = dummy;
+  <T>SplayNode* r = dummy;
+  dummy->rt = dummy->lt = dummy->par = 0;
+  
+  int done = 0;
+  while (!done)
+  {
+    if (comp >= 0)
+    {
+      <T>SplayNode* tr = t->rt;
+      if (tr == 0)
+      {
+        tr = newnode;
+        comp = 0; done = 1;
+      }
+      else
+        comp = <T>CMP(item, tr->item);
+        
+      if (comp <= 0)
+      {
+        l->rt = t; t->par = l;
+        l = t;
+        t = tr;
+      }
+      else 
+      {
+        <T>SplayNode* trr = tr->rt;
+        if (trr == 0)
+        {
+          trr =  newnode;
+          comp = 0; done = 1;
+        }
+        else
+          comp = <T>CMP(item, trr->item);
+
+        if ((t->rt = tr->lt) != 0) t->rt->par = t;
+        tr->lt = t; t->par = tr;
+        l->rt = tr; tr->par = l;
+        l = tr;
+        t = trr;
+      }
+    }
+    else
+    {
+      <T>SplayNode* tl = t->lt;
+      if (tl == 0)
+      {
+        tl = newnode;
+        comp = 0; done = 1;
+      }
+      else
+        comp = <T>CMP(item, tl->item);
+
+      if (comp >= 0)
+      {
+        r->lt = t; t->par = r;
+        r = t;
+        t = tl;
+      }
+      else
+      {
+        <T>SplayNode* tll = tl->lt;
+        if (tll == 0)
+        {
+          tll = newnode;
+          comp = 0; done = 1;
+        }
+        else
+          comp = <T>CMP(item, tll->item);
+
+        if ((t->lt = tl->rt) != 0) t->lt->par = t;
+        tl->rt = t; t->par = tl;
+        r->lt = tl; tl->par = r;
+        r = tl;
+        t = tll;
+      }
+    }
+  }
+  if ((r->lt = t->rt) != 0) r->lt->par = r;
+  if ((l->rt = t->lt) != 0) l->rt->par = l;
+  if ((t->lt = dummy->rt) != 0) t->lt->par = t;
+  if ((t->rt = dummy->lt) != 0) t->rt->par = t;
+  t->par = 0;
+  root = t;
+  return Pix(root);
+}
+
+void <T>SplayBag::_del(<T>SplayNode* t)
+{
+  if (t == 0) return;
+
+  <T>SplayNode* p = t->par;
+
+  --count;
+  if (t->rt == 0)
+  {
+    if (t == root)
+    {
+      if ((root = t->lt) != 0) root->par = 0;
+    }
+    else if (t == p->lt)
+    {
+      if ((p->lt = t->lt) != 0) p->lt->par = p;
+    }
+    else
+      if ((p->rt = t->lt) != 0) p->rt->par = p;
+  }
+  else
+  {
+    <T>SplayNode* r = t->rt;
+    <T>SplayNode* l = r->lt;
+    for(;;)
+    {
+      if (l == 0)
+      {
+        if (t == root)
+        {
+          root = r;
+          r->par = 0;
+        }
+        else if (t == p->lt) 
+        {
+          p->lt = r;
+          r->par = p;
+        }
+        else
+        {
+          p->rt = r;
+          r->par = p;
+        }
+        if ((r->lt = t->lt) != 0) r->lt->par = r;
+        break;
+      }
+      else
+      {
+        if ((r->lt = l->rt) != 0) r->lt->par = r;
+        l->rt = r; r->par = l;
+        r = l;
+        l = l->lt;
+      }
+    }
+  }
+  delete t;
+}
+
+
+void <T>SplayBag::remove(<T&> key)
+{
+  <T>SplayNode* t = (<T>SplayNode*)(seek(key));
+  while (t != 0)
+  {
+    _del(t);
+    t = (<T>SplayNode*)(seek(key));
+  }
+}
+
+
+void <T>SplayBag::_kill(<T>SplayNode* t)
+{
+  if (t != 0)
+  {
+    _kill(t->lt);
+    _kill(t->rt);
+    delete t;
+  }
+}
+
+
+<T>SplayNode* <T>SplayBag::_copy(<T>SplayNode* t)
+{
+  if (t != 0)
+  {
+    <T>SplayNode* l = _copy(t->lt);
+    <T>SplayNode* r = _copy(t->rt);
+    <T>SplayNode* x = new <T>SplayNode(t->item, l, r);
+    if (l != 0) l->par = x;
+    if (r != 0) r->par = x;
+    return x;
+  }
+  else 
+    return 0;
+}
+
+int <T>SplayBag::OK()
+{
+  int v = 1;
+  if (root == 0) 
+    v = count == 0;
+  else
+  {
+    int n = 1;
+    <T>SplayNode* trail = leftmost();
+    <T>SplayNode* t = succ(trail);
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) <= 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
+
Index: trunk/src/emx/include/Attic/cpp/gen/SplayBag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplayBag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplayBag.hP	(revision 18)
@@ -0,0 +1,126 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988, 1982 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>SplayBag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SplayBag_h 1
+
+#include "<T>.Bag.h"
+#include "<T>.SplayNode.h"
+
+class <T>SplayBag : public <T>Bag
+{
+protected:
+  <T>SplayNode*   root;
+
+  <T>SplayNode*   leftmost();
+  <T>SplayNode*   rightmost();
+  <T>SplayNode*   pred(<T>SplayNode* t);
+  <T>SplayNode*   succ(<T>SplayNode* t);
+  void            _kill(<T>SplayNode* t);
+  <T>SplayNode*   _copy(<T>SplayNode* t);
+  void            _del(<T>SplayNode* t);
+
+public:
+                  <T>SplayBag();
+                  <T>SplayBag(<T>SplayBag& a);
+  inline                 ~<T>SplayBag();
+
+  Pix           add(<T&> item);
+  inline void          del(<T&> item);
+  void          remove(<T&>item);
+  int           nof(<T&> item);
+  inline int           contains(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  Pix           seek(<T&> item, Pix from = 0);
+
+  Pix           last();
+  void          prev(Pix& i);
+
+  int           OK();
+};
+
+
+inline <T>SplayBag::~<T>SplayBag()
+{
+  _kill(root);
+}
+
+inline <T>SplayBag::<T>SplayBag()
+{
+  root = 0;
+  count = 0;
+}
+
+inline <T>SplayBag::<T>SplayBag(<T>SplayBag& b)
+{
+  count = b.count;
+  root = _copy(b.root);
+}
+
+inline Pix <T>SplayBag::first()
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T>SplayBag::last()
+{
+  return Pix(rightmost());
+}
+
+inline void <T>SplayBag::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T>SplayNode*)i));
+}
+
+inline void <T>SplayBag::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T>SplayNode*)i));
+}
+
+inline <T>& <T>SplayBag::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T>SplayNode*)i)->item;
+}
+
+inline void <T>SplayBag::clear()
+{
+  _kill(root);
+  count = 0;
+  root = 0;
+}
+
+inline int <T>SplayBag::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+inline void <T>SplayBag::del(<T&> key)
+{
+  _del((<T>SplayNode*)(seek(key)));
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SplayMap.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplayMap.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplayMap.ccP	(revision 18)
@@ -0,0 +1,401 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.<C>.SplayMap.h"
+
+
+/* 
+
+ struct to simulate the special `null' node in the Sleater & Tarjan JACM 1985
+ splay tree algorithms
+
+ All routines use a version of their `simple top-down' splay alg. (p 669)
+
+*/
+
+struct _dummySplayNode
+{
+  <T><C>SplayNode*    lt;
+  <T><C>SplayNode*    rt;
+  <T><C>SplayNode*    par;
+} _dummy_null;
+
+
+/*
+ traversal primitives
+*/
+
+
+<T><C>SplayNode* <T><C>SplayMap::leftmost()
+{
+  <T><C>SplayNode* t = root;
+  if (t != 0) while (t->lt != 0) t = t->lt;
+  return t;
+}
+
+<T><C>SplayNode* <T><C>SplayMap::rightmost()
+{
+  <T><C>SplayNode* t = root;
+  if (t != 0) while (t->rt != 0) t = t->rt;
+  return t;
+}
+
+<T><C>SplayNode* <T><C>SplayMap::succ(<T><C>SplayNode* t)
+{
+  if (t == 0)
+    return 0;
+  if (t->rt != 0)
+  {
+    t = t->rt;
+    while (t->lt != 0) t = t->lt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->lt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+<T><C>SplayNode* <T><C>SplayMap::pred(<T><C>SplayNode* t)
+{
+  if (t == 0)
+    return 0;
+  else if (t->lt != 0)
+  {
+    t = t->lt;
+    while (t->rt != 0) t = t->rt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->rt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+
+Pix <T><C>SplayMap::seek(<T&> key)
+{
+  <T><C>SplayNode* t = root;
+  if (t == 0)
+    return 0;
+
+  int comp = <T>CMP(key, t->item);
+  if (comp == 0)
+    return Pix(t);
+
+  <T><C>SplayNode* dummy = (<T><C>SplayNode*)(&_dummy_null);
+  <T><C>SplayNode* l = dummy;
+  <T><C>SplayNode* r = dummy;
+  dummy->rt = dummy->lt = dummy->par = 0;
+
+  while (comp != 0)
+  {
+    if (comp > 0)
+    {
+      <T><C>SplayNode* tr = t->rt;
+      if (tr == 0)
+        break;
+      else
+      {
+        comp = <T>CMP(key, tr->item);
+        if (comp <= 0 || tr->rt == 0)
+        {
+          l->rt = t; t->par = l;
+          l = t;
+          t = tr;
+          if (comp >= 0)
+            break;
+        }
+        else
+        {
+          if ((t->rt = tr->lt) != 0) t->rt->par = t;
+          tr->lt = t; t->par = tr;
+          l->rt = tr; tr->par = l;
+          l = tr;
+          t = tr->rt;
+          comp = <T>CMP(key, t->item);
+        }
+      }
+    }
+    else
+    {
+      <T><C>SplayNode* tl = t->lt;
+      if (tl == 0)
+        break;
+      else
+      {
+        comp = <T>CMP(key, tl->item);
+        if (comp >= 0 || tl->lt == 0)
+        {
+          r->lt = t; t->par = r;
+          r = t;
+          t = tl;
+          if (comp <= 0)
+            break;
+        }
+        else
+        {
+          if ((t->lt = tl->rt) != 0) t->lt->par = t;
+          tl->rt = t; t->par = tl;
+          r->lt = tl; tl->par = r;
+          r = tl;
+          t = tl->lt;
+          comp = <T>CMP(key, t->item);
+        }
+      }
+    }
+  }
+  if ((r->lt = t->rt) != 0) r->lt->par = r;
+  if ((l->rt = t->lt) != 0) l->rt->par = l;
+  if ((t->lt = dummy->rt) != 0) t->lt->par = t;
+  if ((t->rt = dummy->lt) != 0) t->rt->par = t;
+  t->par = 0;
+  root = t;
+  return (comp == 0) ? Pix(t) : 0;
+}
+
+
+<C>& <T><C>SplayMap::operator [] (<T&> item)
+{
+  <T><C>SplayNode* t = root;
+  if (t == 0)
+  {
+    ++count;
+    root = new <T><C>SplayNode(item, def);
+    return root->cont;
+  }
+  int comp = <T>CMP(item, t->item);
+  if (comp == 0)
+    return t->cont;
+
+  <T><C>SplayNode* dummy = (<T><C>SplayNode*)(&_dummy_null);
+  <T><C>SplayNode* l = dummy;
+  <T><C>SplayNode* r = dummy;
+  dummy->rt = dummy->lt = dummy->par = 0;
+
+  while (comp != 0)
+  {
+    if (comp > 0)
+    {
+      <T><C>SplayNode* tr = t->rt;
+      if (tr == 0)
+      {
+        ++count;
+        tr = new <T><C>SplayNode(item, def);
+        comp = 0;
+      }
+      else
+        comp = <T>CMP(item, tr->item);
+        
+      if (comp <= 0)
+      {
+        l->rt = t; t->par = l;
+        l = t;
+        t = tr;
+      }
+      else 
+      {
+        <T><C>SplayNode* trr = tr->rt;
+        if (trr == 0)
+        {
+          ++count;
+          trr =  new <T><C>SplayNode(item, def);
+          comp = 0;
+        }
+        else
+          comp = <T>CMP(item, trr->item);
+
+        if ((t->rt = tr->lt) != 0) t->rt->par = t;
+        tr->lt = t; t->par = tr;
+        l->rt = tr; tr->par = l;
+        l = tr;
+        t = trr;
+      }
+    }
+    else
+    {
+      <T><C>SplayNode* tl = t->lt;
+      if (tl == 0)
+      {
+        ++count;
+        tl = new <T><C>SplayNode(item, def);
+        comp = 0;
+      }
+      else
+        comp = <T>CMP(item, tl->item);
+
+      if (comp >= 0)
+      {
+        r->lt = t; t->par = r;
+        r = t;
+        t = tl;
+      }
+      else
+      {
+        <T><C>SplayNode* tll = tl->lt;
+        if (tll == 0)
+        {
+          ++count;
+          tll = new <T><C>SplayNode(item, def);
+          comp = 0;
+        }
+        else
+          comp = <T>CMP(item, tll->item);
+
+        if ((t->lt = tl->rt) != 0) t->lt->par = t;
+        tl->rt = t; t->par = tl;
+        r->lt = tl; tl->par = r;
+        r = tl;
+        t = tll;
+      }
+    }
+  }
+  if ((r->lt = t->rt) != 0) r->lt->par = r;
+  if ((l->rt = t->lt) != 0) l->rt->par = l;
+  if ((t->lt = dummy->rt) != 0) t->lt->par = t;
+  if ((t->rt = dummy->lt) != 0) t->rt->par = t;
+  t->par = 0;
+  root = t;
+  return root->cont;
+}
+
+void <T><C>SplayMap::del(<T&> key)
+{
+  <T><C>SplayNode* t = (<T><C>SplayNode*)(seek(key));
+  if (t == 0) return;
+
+  <T><C>SplayNode* p = t->par;
+
+  --count;
+  if (t->rt == 0)
+  {
+    if (t == root)
+    {
+      if ((root = t->lt) != 0) root->par = 0;
+    }
+    else if (t == p->lt)
+    {
+      if ((p->lt = t->lt) != 0) p->lt->par = p;
+    }
+    else
+      if ((p->rt = t->lt) != 0) p->rt->par = p;
+  }
+  else
+  {
+    <T><C>SplayNode* r = t->rt;
+    <T><C>SplayNode* l = r->lt;
+    for(;;)
+    {
+      if (l == 0)
+      {
+        if (t == root)
+        {
+          root = r;
+          r->par = 0;
+        }
+        else if (t == p->lt) 
+        {
+          p->lt = r;
+          r->par = p;
+        }
+        else
+        {
+          p->rt = r;
+          r->par = p;
+        }
+        if ((r->lt = t->lt) != 0) r->lt->par = r;
+        break;
+      }
+      else
+      {
+        if ((r->lt = l->rt) != 0) r->lt->par = r;
+        l->rt = r; r->par = l;
+        r = l;
+        l = l->lt;
+      }
+    }
+  }
+  delete t;
+}
+
+
+void <T><C>SplayMap::_kill(<T><C>SplayNode* t)
+{
+  if (t != 0)
+  {
+    _kill(t->lt);
+    _kill(t->rt);
+    delete t;
+  }
+}
+
+
+<T><C>SplayNode* <T><C>SplayMap::_copy(<T><C>SplayNode* t)
+{
+  if (t != 0)
+  {
+    <T><C>SplayNode* l = _copy(t->lt);
+    <T><C>SplayNode* r = _copy(t->rt);
+    <T><C>SplayNode* x = new <T><C>SplayNode(t->item, t->cont, l, r);
+    if (l != 0) l->par = x;
+    if (r != 0) r->par = x;
+    return x;
+  }
+  else 
+    return 0;
+}
+
+
+int <T><C>SplayMap::OK()
+{
+  int v = 1;
+  if (root == 0) 
+    v = count == 0;
+  else
+  {
+    int n = 1;
+    <T><C>SplayNode* trail = leftmost();
+    <T><C>SplayNode* t = succ(trail);
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/SplayMap.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplayMap.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplayMap.hP	(revision 18)
@@ -0,0 +1,154 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T><C>SplayMap_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T><C>SplayMap_h 1
+
+#include "<T>.<C>.Map.h"
+
+#ifndef _<T><C>SplayNode
+#define _<T><C>SplayNode 1
+
+struct <T><C>SplayNode
+{
+  <T><C>SplayNode*   lt;
+  <T><C>SplayNode*   rt;
+  <T><C>SplayNode*   par;
+  <T>                item;
+  <C>                cont;
+                     <T><C>SplayNode(<T&> h, <C&> c, 
+                                     <T><C>SplayNode* l=0, 
+                                     <T><C>SplayNode* r=0);
+                  ~<T><C>SplayNode();
+};
+
+
+inline <T><C>SplayNode::<T><C>SplayNode(<T&> h, <C&> c, 
+                                        <T><C>SplayNode* l, 
+                                        <T><C>SplayNode* r)
+     :lt(l), rt(r), par(0), item(h), cont(c)  {}
+
+inline <T><C>SplayNode::~<T><C>SplayNode() {}
+
+typedef <T><C>SplayNode* <T><C>SplayNodePtr;
+
+#endif
+
+class <T><C>SplayMap : public <T><C>Map
+{
+protected:
+  <T><C>SplayNode*   root;
+
+  <T><C>SplayNode*   leftmost();
+  <T><C>SplayNode*   rightmost();
+  <T><C>SplayNode*   pred(<T><C>SplayNode* t);
+  <T><C>SplayNode*   succ(<T><C>SplayNode* t);
+  void               _kill(<T><C>SplayNode* t);
+  <T><C>SplayNode*   _copy(<T><C>SplayNode* t);
+
+public:
+               <T><C>SplayMap(<C&> dflt);
+               <T><C>SplayMap(<T><C>SplayMap& a);
+  inline              ~<T><C>SplayMap();
+
+  <C>&          operator [] (<T&> key);
+
+  void          del(<T&> key);
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          key(Pix i);
+  inline <C>&          contents(Pix i);
+
+  Pix           seek(<T&> key);
+  inline int           contains(<T&> key);
+
+  inline void          clear(); 
+
+  Pix           last();
+  void          prev(Pix& i);
+
+  int           OK();
+};
+
+
+inline <T><C>SplayMap::~<T><C>SplayMap()
+{
+  _kill(root);
+}
+
+inline <T><C>SplayMap::<T><C>SplayMap(<C&> dflt) :<T><C>Map(dflt)
+{
+  root = 0;
+}
+
+inline <T><C>SplayMap::<T><C>SplayMap(<T><C>SplayMap& b) :<T><C>Map(b.def)
+{
+  count = b.count;
+  root = _copy(b.root);
+}
+
+inline Pix <T><C>SplayMap::first()
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T><C>SplayMap::last()
+{
+  return Pix(rightmost());
+}
+
+inline void <T><C>SplayMap::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T><C>SplayNode*)i));
+}
+
+inline void <T><C>SplayMap::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T><C>SplayNode*)i));
+}
+
+inline <T>& <T><C>SplayMap::key (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T><C>SplayNode*)i)->item;
+}
+
+inline <C>& <T><C>SplayMap::contents (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T><C>SplayNode*)i)->cont;
+}
+
+inline void <T><C>SplayMap::clear()
+{
+  _kill(root);
+  count = 0;
+  root = 0;
+}
+
+inline int <T><C>SplayMap::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SplayNod.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplayNod.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplayNod.ccP	(revision 18)
@@ -0,0 +1,21 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1992 Free Software Foundation
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.SplayNode.h"
Index: trunk/src/emx/include/Attic/cpp/gen/SplayNod.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplayNod.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplayNod.hP	(revision 18)
@@ -0,0 +1,44 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988, 1982 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>SplayNode
+#define _<T>SplayNode 1
+#ifdef __GNUG__
+#pragma interface
+#endif
+#include "<T>.defs.h"
+
+struct <T>SplayNode
+{
+  <T>SplayNode*   lt;
+  <T>SplayNode*   rt;
+  <T>SplayNode*   par;
+  <T>             item;
+                  <T>SplayNode(<T&> h, <T>SplayNode* l=0, <T>SplayNode* r=0);
+                  ~<T>SplayNode();
+};
+
+
+inline <T>SplayNode::<T>SplayNode(<T&> h, <T>SplayNode* l, <T>SplayNode* r)
+:lt(l), rt(r), par(0), item(h) {}
+
+inline <T>SplayNode::~<T>SplayNode() {}
+
+typedef <T>SplayNode* <T>SplayNodePtr;
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SplayPQ.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplayPQ.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplayPQ.ccP	(revision 18)
@@ -0,0 +1,523 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.SplayPQ.h"
+
+
+/* 
+
+ struct to simulate the special `null' node in the Sleater & Tarjan JACM 1985
+ splay tree algorithms
+
+ All routines use a version of their `simple top-down' splay alg. (p 669)
+
+*/
+
+struct _dummySplayNode
+{
+  <T>SplayNode*    lt;
+  <T>SplayNode*    rt;
+  <T>SplayNode*    par;
+} _dummy_null;
+
+
+/*
+ traversal primitives
+*/
+
+
+<T>SplayNode* <T>SplayPQ::leftmost()
+{
+  <T>SplayNode* t = root;
+  if (t != 0) while (t->lt != 0) t = t->lt;
+  return t;
+}
+
+<T>SplayNode* <T>SplayPQ::rightmost()
+{
+  <T>SplayNode* t = root;
+  if (t != 0) while (t->rt != 0) t = t->rt;
+  return t;
+}
+
+<T>SplayNode* <T>SplayPQ::succ(<T>SplayNode* t)
+{
+  if (t == 0)
+    return 0;
+  if (t->rt != 0)
+  {
+    t = t->rt;
+    while (t->lt != 0) t = t->lt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->lt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+<T>SplayNode* <T>SplayPQ::pred(<T>SplayNode* t)
+{
+  if (t == 0)
+    return 0;
+  else if (t->lt != 0)
+  {
+    t = t->lt;
+    while (t->rt != 0) t = t->rt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->rt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+
+Pix <T>SplayPQ::seek(<T&> key)
+{
+  <T>SplayNode* t = root;
+  if (t == 0)
+    return 0;
+
+  int comp = <T>CMP(key, t->item);
+  if (comp == 0)
+    return Pix(t);
+
+  <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null);
+  <T>SplayNode* l = dummy;
+  <T>SplayNode* r = dummy;
+  dummy->rt = dummy->lt = dummy->par = 0;
+
+  while (comp != 0)
+  {
+    if (comp > 0)
+    {
+      <T>SplayNode* tr = t->rt;
+      if (tr == 0)
+        break;
+      else
+      {
+        comp = <T>CMP(key, tr->item);
+        if (comp <= 0 || tr->rt == 0)
+        {
+          l->rt = t; t->par = l;
+          l = t;
+          t = tr;
+          if (comp >= 0)
+            break;
+        }
+        else
+        {
+          if ((t->rt = tr->lt) != 0) t->rt->par = t;
+          tr->lt = t; t->par = tr;
+          l->rt = tr; tr->par = l;
+          l = tr;
+          t = tr->rt;
+          comp = <T>CMP(key, t->item);
+        }
+      }
+    }
+    else
+    {
+      <T>SplayNode* tl = t->lt;
+      if (tl == 0)
+        break;
+      else
+      {
+        comp = <T>CMP(key, tl->item);
+        if (comp >= 0 || tl->lt == 0)
+        {
+          r->lt = t; t->par = r;
+          r = t;
+          t = tl;
+          if (comp <= 0)
+            break;
+        }
+        else
+        {
+          if ((t->lt = tl->rt) != 0) t->lt->par = t;
+          tl->rt = t; t->par = tl;
+          r->lt = tl; tl->par = r;
+          r = tl;
+          t = tl->lt;
+          comp = <T>CMP(key, t->item);
+        }
+      }
+    }
+  }
+  if ((r->lt = t->rt) != 0) r->lt->par = r;
+  if ((l->rt = t->lt) != 0) l->rt->par = l;
+  if ((t->lt = dummy->rt) != 0) t->lt->par = t;
+  if ((t->rt = dummy->lt) != 0) t->rt->par = t;
+  t->par = 0;
+  root = t;
+  return (comp == 0) ? Pix(t) : 0;
+}
+
+
+Pix <T>SplayPQ::enq(<T&> item)
+{
+  ++count;
+  <T>SplayNode* newnode = new <T>SplayNode(item);
+  <T>SplayNode* t = root;
+  if (t == 0)
+  {
+    root = newnode;
+    return Pix(root);
+  }
+
+  int comp = <T>CMP(item, t->item);
+
+  <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null);
+  <T>SplayNode* l = dummy;
+  <T>SplayNode* r = dummy;
+  dummy->rt = dummy->lt = dummy->par = 0;
+  
+  int done = 0;
+  while (!done)
+  {
+    if (comp >= 0)
+    {
+      <T>SplayNode* tr = t->rt;
+      if (tr == 0)
+      {
+        tr = newnode;
+        comp = 0; done = 1;
+      }
+      else
+        comp = <T>CMP(item, tr->item);
+        
+      if (comp <= 0)
+      {
+        l->rt = t; t->par = l;
+        l = t;
+        t = tr;
+      }
+      else 
+      {
+        <T>SplayNode* trr = tr->rt;
+        if (trr == 0)
+        {
+          trr =  newnode;
+          comp = 0; done = 1;
+        }
+        else
+          comp = <T>CMP(item, trr->item);
+
+        if ((t->rt = tr->lt) != 0) t->rt->par = t;
+        tr->lt = t; t->par = tr;
+        l->rt = tr; tr->par = l;
+        l = tr;
+        t = trr;
+      }
+    }
+    else
+    {
+      <T>SplayNode* tl = t->lt;
+      if (tl == 0)
+      {
+        tl = newnode;
+        comp = 0; done = 1;
+      }
+      else
+        comp = <T>CMP(item, tl->item);
+
+      if (comp >= 0)
+      {
+        r->lt = t; t->par = r;
+        r = t;
+        t = tl;
+      }
+      else
+      {
+        <T>SplayNode* tll = tl->lt;
+        if (tll == 0)
+        {
+          tll = newnode;
+          comp = 0; done = 1;
+        }
+        else
+          comp = <T>CMP(item, tll->item);
+
+        if ((t->lt = tl->rt) != 0) t->lt->par = t;
+        tl->rt = t; t->par = tl;
+        r->lt = tl; tl->par = r;
+        r = tl;
+        t = tll;
+      }
+    }
+  }
+  if ((r->lt = t->rt) != 0) r->lt->par = r;
+  if ((l->rt = t->lt) != 0) l->rt->par = l;
+  if ((t->lt = dummy->rt) != 0) t->lt->par = t;
+  if ((t->rt = dummy->lt) != 0) t->rt->par = t;
+  t->par = 0;
+  root = t;
+  return Pix(root);
+}
+
+
+void <T>SplayPQ::del(Pix pix)
+{
+  <T>SplayNode* t = (<T>SplayNode*)pix;
+  if (t == 0) return;
+
+  <T>SplayNode* p = t->par;
+
+  --count;
+  if (t->rt == 0)
+  {
+    if (t == root)
+    {
+      if ((root = t->lt) != 0) root->par = 0;
+    }
+    else if (t == p->lt)
+    {
+      if ((p->lt = t->lt) != 0) p->lt->par = p;
+    }
+    else
+      if ((p->rt = t->lt) != 0) p->rt->par = p;
+  }
+  else
+  {
+    <T>SplayNode* r = t->rt;
+    <T>SplayNode* l = r->lt;
+    for(;;)
+    {
+      if (l == 0)
+      {
+        if (t == root)
+        {
+          root = r;
+          r->par = 0;
+        }
+        else if (t == p->lt) 
+        {
+          p->lt = r;
+          r->par = p;
+        }
+        else
+        {
+          p->rt = r;
+          r->par = p;
+        }
+        if ((r->lt = t->lt) != 0) r->lt->par = r;
+        break;
+      }
+      else
+      {
+        if ((r->lt = l->rt) != 0) r->lt->par = r;
+        l->rt = r; r->par = l;
+        r = l;
+        l = l->lt;
+      }
+    }
+  }
+  delete t;
+}
+
+<T>& <T>SplayPQ::front()
+{
+  if (root == 0)
+    error ("min: empty tree\n");
+//  else 
+  {
+    <T>SplayNode* t = root;
+    <T>SplayNode* l = root->lt;
+    for(;;)
+    {
+      if (l == 0)
+      {
+        root = t;
+        root->par = 0;
+        return root->item;
+      }
+      else
+      {
+        if ((t->lt = l->rt) != 0) t->lt->par = t;
+        l->rt = t; t->par = l;
+        t = l;
+        l = l->lt;
+      }
+    }
+  }
+}
+
+void <T>SplayPQ::del_front()
+{
+  if (root != 0)
+  {
+    --count;
+    <T>SplayNode* t = root;
+    <T>SplayNode* l = root->lt;
+    if (l == 0)
+    {
+      if ((root = t->rt) != 0) root->par = 0;
+      delete t;
+    }
+    else
+    {
+      for(;;)
+      {
+        <T>SplayNode* ll = l->lt;
+        if (ll == 0)
+        {
+          if ((t->lt = l->rt) != 0) t->lt->par = t;
+          delete l;
+          break;
+        }
+        else
+        {
+          <T>SplayNode* lll = ll->lt;
+          if (lll == 0)
+          {
+            if ((l->lt = ll->rt) != 0) l->lt->par = l;
+            delete ll;
+            break;
+          }
+          else
+          {
+            t->lt = ll; ll->par = t;
+            if ((l->lt = ll->rt) != 0) l->lt->par = l;
+            ll->rt = l; l->par = ll;
+            t = ll;
+            l = lll;
+          }
+        }
+      }
+    }
+  }
+}
+
+<T> <T>SplayPQ::deq()
+{
+  if (root == 0)
+    error("deq: empty tree");
+//  else
+  {
+    --count;
+    <T>SplayNode* t = root;
+    <T>SplayNode* l = root->lt;
+    if (l == 0)
+    {
+      if ((root = t->rt) != 0) root->par = 0;
+      <T> res = t->item;
+      delete t;
+      return res;
+    }
+    else
+    {
+      for(;;)
+      {
+        <T>SplayNode* ll = l->lt;
+        if (ll == 0)
+        {
+          if ((t->lt = l->rt) != 0) t->lt->par = t;
+          <T> res = l->item;
+          delete l;
+          return res;
+        }
+        else
+        {
+          <T>SplayNode* lll = ll->lt;
+          if (lll == 0)
+          {
+            if ((l->lt = ll->rt) != 0) l->lt->par = l;
+            <T> res = ll->item;
+            delete ll;
+            return res;
+          }
+          else
+          {
+            t->lt = ll; ll->par = t;
+            if ((l->lt = ll->rt) != 0) l->lt->par = l;
+            ll->rt = l; l->par = ll;
+            t = ll;
+            l = lll;
+          }
+        }
+      }
+    }
+  }
+}
+
+
+void <T>SplayPQ::_kill(<T>SplayNode* t)
+{
+  if (t != 0)
+  {
+    _kill(t->lt);
+    _kill(t->rt);
+    delete t;
+  }
+}
+
+
+<T>SplayNode* <T>SplayPQ::_copy(<T>SplayNode* t)
+{
+  if (t != 0)
+  {
+    <T>SplayNode* l = _copy(t->lt);
+    <T>SplayNode* r = _copy(t->rt);
+    <T>SplayNode* x = new <T>SplayNode(t->item, l, r);
+    if (l != 0) l->par = x;
+    if (r != 0) r->par = x;
+    return x;
+  }
+  else 
+    return 0;
+}
+
+int <T>SplayPQ::OK()
+{
+  int v = 1;
+  if (root == 0) 
+    v = count == 0;
+  else
+  {
+    int n = 1;
+    <T>SplayNode* trail = leftmost();
+    <T>SplayNode* t = succ(trail);
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/SplayPQ.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplayPQ.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplayPQ.hP	(revision 18)
@@ -0,0 +1,123 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>SplayPQ_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SplayPQ_h 1
+
+#include "<T>.PQ.h"
+#include "<T>.SplayNode.h"
+
+class <T>SplayPQ : public <T>PQ
+{
+protected:
+  <T>SplayNode*   root;
+
+  <T>SplayNode*   leftmost();
+  <T>SplayNode*   rightmost();
+  <T>SplayNode*   pred(<T>SplayNode* t);
+  <T>SplayNode*   succ(<T>SplayNode* t);
+  void            _kill(<T>SplayNode* t);
+  <T>SplayNode*   _copy(<T>SplayNode* t);
+
+public:
+                  <T>SplayPQ();
+                  <T>SplayPQ(<T>SplayPQ& a);
+  inline virtual       ~<T>SplayPQ();
+
+  Pix           enq(<T&> item);
+  <T>           deq(); 
+
+  <T>&          front();
+  void          del_front();
+
+  inline int           contains(<T&> item);
+
+  inline void          clear(); 
+
+  inline Pix           first(); 
+  Pix           last(); 
+  inline void          next(Pix& i);
+  void          prev(Pix& i);
+  inline <T>&          operator () (Pix i);
+  void          del(Pix i);
+  Pix           seek(<T&> item);
+
+  int           OK();                    // rep invariant
+};
+
+
+inline <T>SplayPQ::~<T>SplayPQ()
+{
+  _kill(root);
+}
+
+inline <T>SplayPQ::<T>SplayPQ()
+{
+  root = 0;
+  count = 0;
+}
+
+inline <T>SplayPQ::<T>SplayPQ(<T>SplayPQ& b)
+{
+  count = b.count;
+  root = _copy(b.root);
+}
+
+inline Pix <T>SplayPQ::first()
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T>SplayPQ::last()
+{
+  return Pix(rightmost());
+}
+
+inline void <T>SplayPQ::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T>SplayNode*)i));
+}
+
+inline void <T>SplayPQ::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T>SplayNode*)i));
+}
+
+inline <T>& <T>SplayPQ::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T>SplayNode*)i)->item;
+}
+
+inline void <T>SplayPQ::clear()
+{
+  _kill(root);
+  count = 0;
+  root = 0;
+}
+
+inline int <T>SplayPQ::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/SplaySet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplaySet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplaySet.ccP	(revision 18)
@@ -0,0 +1,499 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.SplaySet.h"
+
+
+/* 
+
+ struct to simulate the special `null' node in the Sleater & Tarjan JACM 1985
+ splay tree algorithms
+
+ All routines use a version of their `simple top-down' splay alg. (p 669)
+
+*/
+
+struct _dummySplayNode
+{
+  <T>SplayNode*    lt;
+  <T>SplayNode*    rt;
+  <T>SplayNode*    par;
+} _dummy_null;
+
+
+/*
+ traversal primitives
+*/
+
+
+<T>SplayNode* <T>SplaySet::leftmost()
+{
+  <T>SplayNode* t = root;
+  if (t != 0) while (t->lt != 0) t = t->lt;
+  return t;
+}
+
+<T>SplayNode* <T>SplaySet::rightmost()
+{
+  <T>SplayNode* t = root;
+  if (t != 0) while (t->rt != 0) t = t->rt;
+  return t;
+}
+
+<T>SplayNode* <T>SplaySet::succ(<T>SplayNode* t)
+{
+  if (t == 0)
+    return 0;
+  if (t->rt != 0)
+  {
+    t = t->rt;
+    while (t->lt != 0) t = t->lt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->lt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+<T>SplayNode* <T>SplaySet::pred(<T>SplayNode* t)
+{
+  if (t == 0)
+    return 0;
+  else if (t->lt != 0)
+  {
+    t = t->lt;
+    while (t->rt != 0) t = t->rt;
+    return t;
+  }
+  else
+  {
+    for (;;)
+    {
+      if (t->par == 0 || t == t->par->rt)
+        return t->par;
+      else
+        t = t->par;
+    }
+  }
+}
+
+
+Pix <T>SplaySet::seek(<T&> key)
+{
+  <T>SplayNode* t = root;
+  if (t == 0)
+    return 0;
+
+  int comp = <T>CMP(key, t->item);
+  if (comp == 0)
+    return Pix(t);
+
+  <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null);
+  <T>SplayNode* l = dummy;
+  <T>SplayNode* r = dummy;
+  dummy->rt = dummy->lt = dummy->par = 0;
+
+  while (comp != 0)
+  {
+    if (comp > 0)
+    {
+      <T>SplayNode* tr = t->rt;
+      if (tr == 0)
+        break;
+      else
+      {
+        comp = <T>CMP(key, tr->item);
+        if (comp <= 0 || tr->rt == 0)
+        {
+          l->rt = t; t->par = l;
+          l = t;
+          t = tr;
+          if (comp >= 0)
+            break;
+        }
+        else
+        {
+          if ((t->rt = tr->lt) != 0) t->rt->par = t;
+          tr->lt = t; t->par = tr;
+          l->rt = tr; tr->par = l;
+          l = tr;
+          t = tr->rt;
+          comp = <T>CMP(key, t->item);
+        }
+      }
+    }
+    else
+    {
+      <T>SplayNode* tl = t->lt;
+      if (tl == 0)
+        break;
+      else
+      {
+        comp = <T>CMP(key, tl->item);
+        if (comp >= 0 || tl->lt == 0)
+        {
+          r->lt = t; t->par = r;
+          r = t;
+          t = tl;
+          if (comp <= 0)
+            break;
+        }
+        else
+        {
+          if ((t->lt = tl->rt) != 0) t->lt->par = t;
+          tl->rt = t; t->par = tl;
+          r->lt = tl; tl->par = r;
+          r = tl;
+          t = tl->lt;
+          comp = <T>CMP(key, t->item);
+        }
+      }
+    }
+  }
+  if ((r->lt = t->rt) != 0) r->lt->par = r;
+  if ((l->rt = t->lt) != 0) l->rt->par = l;
+  if ((t->lt = dummy->rt) != 0) t->lt->par = t;
+  if ((t->rt = dummy->lt) != 0) t->rt->par = t;
+  t->par = 0;
+  root = t;
+  return (comp == 0) ? Pix(t) : 0;
+}
+
+
+
+Pix <T>SplaySet::add(<T&> item)
+{
+  <T>SplayNode* t = root;
+  if (t == 0)
+  {
+    ++count;
+    root = new <T>SplayNode(item);
+    return Pix(root);
+  }
+  int comp = <T>CMP(item, t->item);
+  if (comp == 0)
+    return Pix(t);
+
+  <T>SplayNode* dummy = (<T>SplayNode*)(&_dummy_null);
+  <T>SplayNode* l = dummy;
+  <T>SplayNode* r = dummy;
+  dummy->rt = dummy->lt = dummy->par = 0;
+
+  while (comp != 0)
+  {
+    if (comp > 0)
+    {
+      <T>SplayNode* tr = t->rt;
+      if (tr == 0)
+      {
+        ++count;
+        tr = new <T>SplayNode(item);
+        comp = 0;
+      }
+      else
+        comp = <T>CMP(item, tr->item);
+        
+      if (comp <= 0)
+      {
+        l->rt = t; t->par = l;
+        l = t;
+        t = tr;
+      }
+      else 
+      {
+        <T>SplayNode* trr = tr->rt;
+        if (trr == 0)
+        {
+          ++count;
+          trr =  new <T>SplayNode(item);
+          comp = 0;
+        }
+        else
+          comp = <T>CMP(item, trr->item);
+
+        if ((t->rt = tr->lt) != 0) t->rt->par = t;
+        tr->lt = t; t->par = tr;
+        l->rt = tr; tr->par = l;
+        l = tr;
+        t = trr;
+      }
+    }
+    else
+    {
+      <T>SplayNode* tl = t->lt;
+      if (tl == 0)
+      {
+        ++count;
+        tl = new <T>SplayNode(item);
+        comp = 0;
+      }
+      else
+        comp = <T>CMP(item, tl->item);
+
+      if (comp >= 0)
+      {
+        r->lt = t; t->par = r;
+        r = t;
+        t = tl;
+      }
+      else
+      {
+        <T>SplayNode* tll = tl->lt;
+        if (tll == 0)
+        {
+          ++count;
+          tll = new <T>SplayNode(item);
+          comp = 0;
+        }
+        else
+          comp = <T>CMP(item, tll->item);
+
+        if ((t->lt = tl->rt) != 0) t->lt->par = t;
+        tl->rt = t; t->par = tl;
+        r->lt = tl; tl->par = r;
+        r = tl;
+        t = tll;
+      }
+    }
+  }
+  if ((r->lt = t->rt) != 0) r->lt->par = r;
+  if ((l->rt = t->lt) != 0) l->rt->par = l;
+  if ((t->lt = dummy->rt) != 0) t->lt->par = t;
+  if ((t->rt = dummy->lt) != 0) t->rt->par = t;
+  t->par = 0;
+  root = t;
+  return Pix(root);
+}
+
+void <T>SplaySet::del(<T&> key)
+{
+  <T>SplayNode* t = (<T>SplayNode*)(seek(key));
+  if (t == 0) return;
+
+  <T>SplayNode* p = t->par;
+
+  --count;
+  if (t->rt == 0)
+  {
+    if (t == root)
+    {
+      if ((root = t->lt) != 0) root->par = 0;
+    }
+    else if (t == p->lt)
+    {
+      if ((p->lt = t->lt) != 0) p->lt->par = p;
+    }
+    else
+      if ((p->rt = t->lt) != 0) p->rt->par = p;
+  }
+  else
+  {
+    <T>SplayNode* r = t->rt;
+    <T>SplayNode* l = r->lt;
+    for(;;)
+    {
+      if (l == 0)
+      {
+        if (t == root)
+        {
+          root = r;
+          r->par = 0;
+        }
+        else if (t == p->lt) 
+        {
+          p->lt = r;
+          r->par = p;
+        }
+        else
+        {
+          p->rt = r;
+          r->par = p;
+        }
+        if ((r->lt = t->lt) != 0) r->lt->par = r;
+        break;
+      }
+      else
+      {
+        if ((r->lt = l->rt) != 0) r->lt->par = r;
+        l->rt = r; r->par = l;
+        r = l;
+        l = l->lt;
+      }
+    }
+  }
+  delete t;
+}
+
+
+void <T>SplaySet::_kill(<T>SplayNode* t)
+{
+  if (t != 0)
+  {
+    _kill(t->lt);
+    _kill(t->rt);
+    delete t;
+  }
+}
+
+
+<T>SplayNode* <T>SplaySet::_copy(<T>SplayNode* t)
+{
+  if (t != 0)
+  {
+    <T>SplayNode* l = _copy(t->lt);
+    <T>SplayNode* r = _copy(t->rt);
+    <T>SplayNode* x = new <T>SplayNode(t->item, l, r);
+    if (l != 0) l->par = x;
+    if (r != 0) r->par = x;
+    return x;
+  }
+  else 
+    return 0;
+}
+
+/* relationals */
+
+int <T>SplaySet::operator == (<T>SplaySet& y)
+{
+  if (count != y.count)
+    return 0;
+  else
+  {
+    <T>SplayNode* t = leftmost();
+    <T>SplayNode* u = y.leftmost();
+    for (;;)
+    {
+      if (t == 0)
+        return 1;
+      else if (!<T>EQ(t->item, u->item))
+        return 0;
+      else
+      {
+        t = succ(t);
+        u = y.succ(u);
+      }
+    }
+  }
+}
+
+int <T>SplaySet::operator <= (<T>SplaySet& y)
+{
+  if (count > y.count)
+    return 0;
+  else
+  {
+    <T>SplayNode* t = leftmost();
+    <T>SplayNode* u = y.leftmost();
+    for (;;)
+    {
+      if (t == 0)
+        return 1;
+      else if (u == 0)
+        return 0;
+      int cmp = <T>CMP(t->item, u->item);
+      if (cmp == 0)
+      {
+        t = succ(t);
+        u = y.succ(u);
+      }
+      else if (cmp < 0)
+        return 0;
+      else
+        u = y.succ(u);
+    }
+  }
+}
+
+
+void <T>SplaySet::operator |=(<T>SplaySet& y)
+{
+  if (&y == this) return;
+  <T>SplayNode* u = y.leftmost();
+  while (u != 0)
+  {
+    add(u->item);
+    u = y.succ(u);
+  }
+}
+
+void <T>SplaySet::operator &= (<T>SplaySet& y)
+{
+  if (y.count == 0)
+    clear();
+  else if (&y != this && count != 0)
+  {
+    <T>SplayNode* t = leftmost();
+    while (t != 0)
+    {
+      <T>SplayNode* s = succ(t);
+      if (y.seek(t->item) == 0) del(t->item);
+      t = s;
+    }
+  }
+}
+
+
+void <T>SplaySet::operator -=(<T>SplaySet& y)
+{
+  if (&y == this)
+    clear();
+  else if (y.count != 0)
+  {
+    <T>SplayNode* t = leftmost();
+    while (t != 0)
+    {
+      <T>SplayNode* s = succ(t);
+      if (y.seek(t->item) != 0) del(t->item);
+      t = s;
+    }
+  }
+}
+
+int <T>SplaySet::OK()
+{
+  int v = 1;
+  if (root == 0) 
+    v = count == 0;
+  else
+  {
+    int n = 1;
+    <T>SplayNode* trail = leftmost();
+    <T>SplayNode* t = succ(trail);
+    while (t != 0)
+    {
+      ++n;
+      v &= <T>CMP(trail->item, t->item) < 0;
+      trail = t;
+      t = succ(t);
+    }
+    v &= n == count;
+  }
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/SplaySet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/SplaySet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/SplaySet.hP	(revision 18)
@@ -0,0 +1,145 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>SplaySet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>SplaySet_h 1
+
+#include "<T>.Set.h"
+#include "<T>.SplayNode.h"
+
+class <T>SplaySet : public <T>Set
+{
+protected:
+  <T>SplayNode*   root;
+
+  <T>SplayNode*   leftmost();
+  <T>SplayNode*   rightmost();
+  <T>SplayNode*   pred(<T>SplayNode* t);
+  <T>SplayNode*   succ(<T>SplayNode* t);
+  void            _kill(<T>SplayNode* t);
+  <T>SplayNode*   _copy(<T>SplayNode* t);
+
+public:
+                  <T>SplaySet();
+                  <T>SplaySet(<T>SplaySet& a);
+  inline                 ~<T>SplaySet();
+
+  Pix             add(<T&> item);
+  void            del(<T&> item);
+  inline int             contains(<T&> item);
+
+  inline void            clear();
+
+  inline Pix             first();
+  inline void            next(Pix& i);
+  inline <T>&            operator () (Pix i);
+  Pix             seek(<T&> item);
+
+  Pix             last();
+  void            prev(Pix& i);
+
+  <T>SplaySet&    operator =  (const <T>SplaySet& b);
+  void            operator |= (<T>SplaySet& b);
+  void            operator -= (<T>SplaySet& b);
+  void            operator &= (<T>SplaySet& b);
+
+  int             operator == (<T>SplaySet& b);
+  int             operator != (<T>SplaySet& b);
+  int             operator <= (<T>SplaySet& b); 
+
+  int             OK();
+};
+
+
+inline <T>SplaySet::~<T>SplaySet()
+{
+  _kill(root);
+}
+
+inline <T>SplaySet::<T>SplaySet()
+{
+  root = 0;
+  count = 0;
+}
+
+inline <T>SplaySet::<T>SplaySet(<T>SplaySet& b)
+{
+  count = b.count;
+  root = _copy(b.root);
+}
+
+
+inline <T>SplaySet& <T>SplaySet::operator = (const <T>SplaySet& b)
+{
+  if (this != &b)
+    {
+      _kill (root);
+      count = b.count;
+      root = _copy (b.root);
+    }
+  return *this;
+}
+
+inline int <T>SplaySet::operator != (<T>SplaySet& b)
+{
+  return ! (*this == b);
+}
+
+inline Pix <T>SplaySet::first()
+{
+  return Pix(leftmost());
+}
+
+inline Pix <T>SplaySet::last()
+{
+  return Pix(rightmost());
+}
+
+inline void <T>SplaySet::next(Pix& i)
+{
+  if (i != 0) i = Pix(succ((<T>SplayNode*)i));
+}
+
+inline void <T>SplaySet::prev(Pix& i)
+{
+  if (i != 0) i = Pix(pred((<T>SplayNode*)i));
+}
+
+inline <T>& <T>SplaySet::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return ((<T>SplayNode*)i)->item;
+}
+
+inline void <T>SplaySet::clear()
+{
+  _kill(root);
+  count = 0;
+  root = 0;
+}
+
+inline int <T>SplaySet::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/Stack.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Stack.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Stack.ccP	(revision 18)
@@ -0,0 +1,11 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.Stack.h"
+
+<T>Stack::~<T>Stack() {}
+
+void <T>Stack::error(const char* msg)
+{
+  (*lib_error_handler)("Stack", msg);
+}
Index: trunk/src/emx/include/Attic/cpp/gen/Stack.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Stack.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Stack.hP	(revision 18)
@@ -0,0 +1,51 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>Stack_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>Stack_h
+
+#include <builtin.h>
+
+#include "<T>.defs.h"
+
+class <T>Stack
+{
+public:
+                        <T>Stack() { }
+  virtual              ~<T>Stack();
+
+  virtual void          push(<T&> item) = 0;
+  virtual <T>           pop() = 0;
+  virtual <T>&          top() = 0;               
+  virtual void          del_top() = 0;
+
+  virtual int           empty() = 0;
+  virtual int           full() = 0;
+  virtual int           length() = 0;
+
+  virtual void          clear() = 0;
+
+  void                  error(const char*);
+  virtual int           OK() = 0;
+};
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/VHBag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VHBag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VHBag.ccP	(revision 18)
@@ -0,0 +1,264 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.VHBag.h"
+
+/* codes for status fields */
+
+#define EMPTYCELL   0
+#define VALIDCELL   1
+#define DELETEDCELL 2
+
+
+<T>VHBag::<T>VHBag(unsigned int sz)
+{
+  tab = new <T>[size = sz];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+}
+ 
+<T>VHBag::<T>VHBag(<T>VHBag& a)
+{
+  tab = new <T>[size = a.size];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+  for (Pix p = a.first(); p; a.next(p)) add(a(p));
+}
+
+
+/* 
+ * hashing method: double hash based on high bits of hash fct,
+ * followed by linear probe. Can't do too much better if table
+ * sizes not constrained to be prime.
+*/
+
+
+static inline unsigned int doublehashinc(unsigned int h, unsigned int s)
+{
+  unsigned int dh =  ((h / s) % s);
+  return (dh > 1)? dh : 1;
+}
+
+Pix <T>VHBag::seek(<T&> key, Pix p)
+{
+  <T>* t = (<T>*) p;
+  if (t == 0 || !<T>EQ(*t, key))
+  {
+    unsigned int hashval = <T>HASH(key);
+    unsigned int h = hashval % size;
+    for (unsigned int i = 0; i <= size; ++i)
+    {
+      if (status[h] == EMPTYCELL)
+        return 0;
+      else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
+        return Pix(&tab[h]);
+      if (i == 0)
+        h = (h + doublehashinc(hashval, size)) % size;
+      else if (++h >= size)
+        h -= size;
+    }
+    return 0;
+  }
+  else
+  {
+    int seent = 0;
+    unsigned int hashval = <T>HASH(key);
+    unsigned int h = hashval % size;
+    for (unsigned int i = 0; i <= size; ++i)
+    {
+      if (status[h] == EMPTYCELL)
+        return 0;
+      else if (&tab[h] == t)
+        seent = 1;
+      else if (seent && status[h] == VALIDCELL && <T>EQ(key, tab[h]))
+        return Pix(&tab[h]);
+      if (i == 0)
+        h = (h + doublehashinc(hashval, size)) % size;
+      else if (++h >= size)
+        h -= size;
+    }
+    return 0;
+  }
+}
+
+int <T>VHBag::nof(<T&> item)
+{
+  int n = 0;
+  unsigned int hashval = <T>HASH(item);
+  unsigned int h = hashval % size;
+  unsigned int firsth = size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+      return n;
+    else if (h != firsth && status[h] == VALIDCELL && <T>EQ(item, tab[h]))
+    {
+      ++n;
+      if (firsth >= size)
+        firsth = h;
+    }
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+  return n;
+}
+
+
+Pix <T>VHBag::add(<T&> item)
+{
+  if (HASHTABLE_TOO_CROWDED(count, size))
+    resize();
+  unsigned int bestspot = size;
+  unsigned int hashval = <T>HASH(item);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+    {
+      if (bestspot >= size) bestspot = h;
+      tab[bestspot] = item;
+      status[bestspot] = VALIDCELL;
+      ++count;
+      return Pix(&tab[bestspot]);
+    }
+    else if (status[h] == DELETEDCELL)
+    {
+      if (bestspot >= size) bestspot = h;
+    }
+
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+  tab[bestspot] = item;
+  status[bestspot] = VALIDCELL;
+  ++count;
+  return Pix(&tab[bestspot]);
+}
+
+
+void <T>VHBag::del(<T&> key)
+{
+  unsigned int hashval = <T>HASH(key);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+      return;
+    else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
+    {
+      status[h] = DELETEDCELL;
+      --count;
+      return;
+    }
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+}
+
+void <T>VHBag::remove(<T&> key)
+{
+  unsigned int hashval = <T>HASH(key);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+      return;
+    else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
+    {
+      status[h] = DELETEDCELL;
+      --count;
+    }
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+}
+
+void <T>VHBag::clear()
+{
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+}
+
+void <T>VHBag::resize(unsigned int newsize)
+{
+  if (newsize <= count)
+  {
+    newsize = DEFAULT_INITIAL_CAPACITY;
+    while (HASHTABLE_TOO_CROWDED(count, newsize)) newsize <<= 1;
+  }
+  <T>* oldtab = tab;
+  char* oldstatus = status;
+  unsigned int oldsize = size;
+  tab = new <T>[size = newsize];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+  for (unsigned int i = 0; i < oldsize; ++i) if (oldstatus[i] == VALIDCELL) add(oldtab[i]);
+  delete [] oldtab;
+  delete oldstatus;
+}
+
+Pix <T>VHBag::first()
+{
+  for (unsigned int pos = 0; pos < size; ++pos)
+    if (status[pos] == VALIDCELL) return Pix(&tab[pos]);
+  return 0;
+}
+
+void <T>VHBag::next(Pix& i)
+{
+  if (i == 0) return;
+  unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1;
+  for (; pos < size; ++pos)
+    if (status[pos] == VALIDCELL)
+    {
+      i = Pix(&tab[pos]);
+      return;
+    }
+  i = 0;
+}
+
+  
+int <T>VHBag::OK()
+{
+  int v = tab != 0;
+  v &= status != 0;
+  int n = 0;
+  for (unsigned int i = 0; i < size; ++i) 
+  {
+    if (status[i] == VALIDCELL) ++n;
+    else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL)
+      v = 0;
+  }
+  v &= n == count;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/VHBag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VHBag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VHBag.hP	(revision 18)
@@ -0,0 +1,84 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>VHBag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>VHBag_h 1
+
+#include "<T>.Bag.h"
+
+
+class <T>VHBag : public <T>Bag
+{
+protected:
+  <T>*          tab;
+  char*         status;
+  unsigned int  size;
+
+public:
+                <T>VHBag(unsigned int sz = DEFAULT_INITIAL_CAPACITY);
+                <T>VHBag(<T>VHBag& a);
+  inline               ~<T>VHBag();
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  void          remove(<T&>item);
+  int           nof(<T&> item);
+  inline int           contains(<T&> item);
+
+  void          clear();
+
+  Pix           first();
+  void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  Pix           seek(<T&> item, Pix from = 0);
+
+  int           capacity();
+  void          resize(unsigned int newsize = 0);
+
+  int           OK();
+};
+
+
+inline <T>VHBag::~<T>VHBag()
+{
+  delete [] tab;
+  delete status;
+}
+
+
+inline int <T>VHBag::capacity()
+{
+  return size;
+}
+
+inline int <T>VHBag::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+inline <T>& <T>VHBag::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return *((<T>*)i);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/VHMap.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VHMap.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VHMap.ccP	(revision 18)
@@ -0,0 +1,210 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.<C>.VHMap.h"
+
+/* codes for status fields */
+
+#define EMPTYCELL   0
+#define VALIDCELL   1
+#define DELETEDCELL 2
+
+
+<T><C>VHMap::<T><C>VHMap(<C&> dflt, unsigned int sz)
+     :<T><C>Map(dflt)
+{
+  tab = new <T>[size = sz];
+  cont = new <C>[size];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+}
+
+<T><C>VHMap::<T><C>VHMap(<T><C>VHMap& a) : <T><C>Map(a.def)
+{
+  tab = new <T>[size = a.size];
+  cont = new <C>[size];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+  for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p);
+}
+
+
+/* 
+ * hashing method: double hash based on high bits of hash fct,
+ * followed by linear probe. Can't do too much better if table
+ * sizes not constrained to be prime.
+*/
+
+
+static inline unsigned int doublehashinc(unsigned int h, unsigned int s)
+{
+  unsigned int dh =  ((h / s) % s);
+  return (dh > 1)? dh : 1;
+}
+
+Pix <T><C>VHMap::seek(<T&> key)
+{
+  unsigned int hashval = <T>HASH(key);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+      return 0;
+    else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
+      return Pix(&tab[h]);
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+  return 0;
+}
+
+
+<C>& <T><C>VHMap::operator [](<T&> item)
+{
+  if (HASHTABLE_TOO_CROWDED(count, size))
+    resize();
+
+  unsigned int bestspot = size;
+  unsigned int hashval = <T>HASH(item);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+    {
+      ++count;
+      if (bestspot >= size) bestspot = h;
+      tab[bestspot] = item;
+      status[bestspot] = VALIDCELL;
+      cont[bestspot] = def;
+      return cont[bestspot];
+    }
+    else if (status[h] == DELETEDCELL)
+    {
+      if (bestspot >= size) bestspot = h;
+    }
+    else if (<T>EQ(tab[h],item))
+      return cont[h];
+
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+
+  ++count;
+  status[bestspot] = VALIDCELL;
+  tab[bestspot] = item;
+  cont[bestspot] = def;
+  return cont[bestspot];
+}
+
+
+void <T><C>VHMap::del(<T&> key)
+{
+  unsigned int hashval = <T>HASH(key);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+      return;
+    else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
+    {
+      status[h] = DELETEDCELL;
+      --count;
+      return;
+    }
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+}
+
+
+void <T><C>VHMap::clear()
+{
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+}
+
+void <T><C>VHMap::resize(unsigned int newsize)
+{
+  if (newsize <= count)
+  {
+    newsize = DEFAULT_INITIAL_CAPACITY;
+    while (HASHTABLE_TOO_CROWDED(count, newsize)) newsize <<= 1;
+  }
+  <T>* oldtab = tab;
+  <C>* oldcont = cont;
+  char* oldstatus = status;
+  unsigned int oldsize = size;
+  tab = new <T>[size = newsize];
+  cont = new <C>[size];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+  for (unsigned int i = 0; i < oldsize; ++i) 
+    if (oldstatus[i] == VALIDCELL) 
+      (*this)[oldtab[i]] = oldcont[i];
+  delete [] oldtab;
+  delete [] oldcont;
+  delete [] oldstatus;
+}
+
+Pix <T><C>VHMap::first()
+{
+  for (unsigned int pos = 0; pos < size; ++pos)
+    if (status[pos] == VALIDCELL) return Pix(&tab[pos]);
+  return 0;
+}
+
+void <T><C>VHMap::next(Pix& i)
+{
+  if (i == 0) return;
+  unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1;
+  for (; pos < size; ++pos)
+    if (status[pos] == VALIDCELL)
+    {
+      i = Pix(&tab[pos]);
+      return;
+    }
+  i = 0;
+}
+  
+
+int <T><C>VHMap::OK()
+{
+  int v = tab != 0;
+  v &= status != 0;
+  int n = 0;
+  for (unsigned int i = 0; i < size; ++i) 
+  {
+    if (status[i] == VALIDCELL) ++n;
+    else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL)
+      v = 0;
+  }
+  v &= n == count;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/VHMap.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VHMap.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VHMap.hP	(revision 18)
@@ -0,0 +1,84 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T><C>VHMap_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T><C>VHMap_h 1
+
+#include "<T>.<C>.Map.h"
+
+
+class <T><C>VHMap : public <T><C>Map
+{
+protected:
+  <T>*           tab;
+  <C>*           cont;
+  char*          status;
+  unsigned int   size;
+
+public:
+                <T><C>VHMap(<C&> dflt,unsigned int sz=DEFAULT_INITIAL_CAPACITY);
+                <T><C>VHMap(<T><C>VHMap& a);
+  inline               ~<T><C>VHMap();
+
+  <C>&          operator [] (<T&> key);
+
+  void          del(<T&> key);
+
+  Pix           first();
+  void          next(Pix& i);
+  inline <T>&          key(Pix i);
+  inline <C>&          contents(Pix i);
+
+  Pix           seek(<T&> key);
+  inline int           contains(<T&> key);
+
+  void          clear(); 
+  void          resize(unsigned int newsize = 0);
+
+  int           OK();
+};
+
+inline <T><C>VHMap::~<T><C>VHMap()
+{
+  delete [] tab;
+  delete [] cont;
+  delete [] status;
+}
+
+inline int <T><C>VHMap::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+inline <T>& <T><C>VHMap::key(Pix i)
+{
+  if (i == 0) error("null Pix");
+  return *((<T>*)i);
+}
+
+inline <C>& <T><C>VHMap::contents(Pix i)
+{
+  if (i == 0) error("null Pix");
+  return cont[((unsigned)(i) - (unsigned)(tab)) / sizeof(<T>)];
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/VHSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VHSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VHSet.ccP	(revision 18)
@@ -0,0 +1,263 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.VHSet.h"
+
+/* codes for status fields */
+
+#define EMPTYCELL   0
+#define VALIDCELL   1
+#define DELETEDCELL 2
+
+
+<T>VHSet::<T>VHSet(unsigned int sz)
+{
+  tab = new <T>[size = sz];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+}
+
+<T>VHSet::<T>VHSet(<T>VHSet& a)
+{
+  tab = new <T>[size = a.size];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+  for (Pix p = a.first(); p; a.next(p)) add(a(p));
+}
+
+
+/* 
+ * hashing method: double hash based on high bits of hash fct,
+ * followed by linear probe. Can't do too much better if table
+ * sizes not constrained to be prime.
+*/
+
+
+static inline unsigned int doublehashinc(unsigned int h, unsigned int s)
+{
+  unsigned int dh =  ((h / s) % s);
+  return (dh > 1)? dh : 1;
+}
+
+Pix <T>VHSet::seek(<T&> key)
+{
+  unsigned int hashval = <T>HASH(key);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+      return 0;
+    else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
+      return Pix(&tab[h]);
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+  return 0;
+}
+
+
+Pix <T>VHSet::add(<T&> item)
+{
+  if (HASHTABLE_TOO_CROWDED(count, size))
+    resize();
+
+  unsigned int bestspot = size;
+  unsigned int hashval = <T>HASH(item);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+    {
+      if (bestspot >= size) bestspot = h;
+      tab[bestspot] = item;
+      status[bestspot] = VALIDCELL;
+      ++count;
+      return Pix(&tab[bestspot]);
+    }
+    else if (status[h] == DELETEDCELL)
+    {
+      if (bestspot >= size) bestspot = h;
+    }
+    else if (<T>EQ(tab[h],item))
+      return Pix(&tab[h]);
+
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+  tab[bestspot] = item;
+  status[bestspot] = VALIDCELL;
+  ++count;
+  return Pix(&tab[bestspot]);
+
+}
+
+
+void <T>VHSet::del(<T&> key)
+{
+  unsigned int hashval = <T>HASH(key);
+  unsigned int h = hashval % size;
+  for (unsigned int i = 0; i <= size; ++i)
+  {
+    if (status[h] == EMPTYCELL)
+      return;
+    else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
+    {
+      status[h] = DELETEDCELL;
+      --count;
+      return;
+    }
+    if (i == 0)
+      h = (h + doublehashinc(hashval, size)) % size;
+    else if (++h >= size)
+      h -= size;
+  }
+}
+
+
+void <T>VHSet::clear()
+{
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+}
+
+void <T>VHSet::resize(unsigned int newsize)
+{
+  if (newsize <= count)
+  {
+    newsize = DEFAULT_INITIAL_CAPACITY;
+    while (HASHTABLE_TOO_CROWDED(count, newsize))  newsize <<= 1;
+  }
+  <T>* oldtab = tab;
+  char* oldstatus = status;
+  unsigned int oldsize = size;
+  tab = new <T>[size = newsize];
+  status = new char[size];
+  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = 0;
+  for (unsigned int i = 0; i < oldsize; ++i) if (oldstatus[i] == VALIDCELL) add(oldtab[i]);
+  delete [] oldtab;
+  delete oldstatus;
+}
+
+Pix <T>VHSet::first()
+{
+  for (unsigned int pos = 0; pos < size; ++pos)
+    if (status[pos] == VALIDCELL) return Pix(&tab[pos]);
+  return 0;
+}
+
+void <T>VHSet::next(Pix& i)
+{
+  if (i == 0) return;
+  unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1;
+  for (; pos < size; ++pos)
+    if (status[pos] == VALIDCELL)
+    {
+      i = Pix(&tab[pos]);
+      return;
+    }
+  i = 0;
+}
+  
+int <T>VHSet:: operator == (<T>VHSet& b)
+{
+  if (count != b.count)
+    return 0;
+  else
+  {
+    for (unsigned int i = 0; i < size; ++i)
+      if (status[i] == VALIDCELL && b.seek(tab[i]) == 0)
+          return 0;
+    for (unsigned int i = 0; i < b.size; ++i)
+      if (b.status[i] == VALIDCELL && seek(b.tab[i]) == 0)
+          return 0;
+    return 1;
+  }
+}
+
+int <T>VHSet::operator <= (<T>VHSet& b)
+{
+  if (count > b.count)
+    return 0;
+  else
+  {
+    for (unsigned int i = 0; i < size; ++i)
+      if (status[i] == VALIDCELL && b.seek(tab[i]) == 0)
+          return 0;
+    return 1;
+  }
+}
+
+void <T>VHSet::operator |= (<T>VHSet& b)
+{
+  if (&b == this || b.count == 0)
+    return;
+  for (unsigned int i = 0; i < b.size; ++i)
+    if (b.status[i] == VALIDCELL) add(b.tab[i]);
+}
+
+void <T>VHSet::operator &= (<T>VHSet& b)
+{
+  if (&b == this || count == 0)
+    return;
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    if (status[i] == VALIDCELL && b.seek(tab[i]) == 0)
+    {
+      status[i] = DELETEDCELL;
+      --count;
+    }
+  }
+}
+
+void <T>VHSet::operator -= (<T>VHSet& b)
+{
+  for (unsigned int i = 0; i < size; ++i)
+  {
+    if (status[i] == VALIDCELL && b.seek(tab[i]) != 0)
+    {
+      status[i] = DELETEDCELL;
+      --count;
+    }
+  }
+}
+
+int <T>VHSet::OK()
+{
+  int v = tab != 0;
+  v &= status != 0;
+  int n = 0;
+  for (unsigned int i = 0; i < size; ++i) 
+  {
+    if (status[i] == VALIDCELL) ++n;
+    else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL)
+      v = 0;
+  }
+  v &= n == count;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/VHSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VHSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VHSet.hP	(revision 18)
@@ -0,0 +1,96 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>VHSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>VHSet_h 1
+
+#include "<T>.Set.h"
+
+
+
+class <T>VHSet : public <T>Set
+{
+protected:
+  <T>*          tab;
+  char*         status;
+  unsigned int  size;
+
+public:
+                <T>VHSet(unsigned int sz = DEFAULT_INITIAL_CAPACITY);
+                <T>VHSet(<T>VHSet& a);
+  inline               ~<T>VHSet();
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  inline int           contains(<T&> item);
+
+  void          clear();
+
+  Pix           first();
+  void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  Pix           seek(<T&> item);
+
+  void          operator |= (<T>VHSet& b);
+  void          operator -= (<T>VHSet& b);
+  void          operator &= (<T>VHSet& b);
+
+  int           operator == (<T>VHSet& b);
+  int           operator != (<T>VHSet& b);
+  int           operator <= (<T>VHSet& b); 
+
+  int           capacity();
+  void          resize(unsigned int newsize = 0);
+
+  int           OK();
+};
+
+
+inline <T>VHSet::~<T>VHSet()
+{
+  delete [] tab;
+  delete status;
+}
+
+
+inline int <T>VHSet::capacity()
+{
+  return size;
+}
+
+inline int <T>VHSet::contains(<T&> key)
+{
+  return seek(key) != 0;
+}
+
+inline <T>& <T>VHSet::operator () (Pix i)
+{
+  if (i == 0) error("null Pix");
+  return *((<T>*)i);
+}
+
+inline int <T>VHSet::operator != (<T>VHSet& b)
+{
+  return ! ((*this) == b);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/VOHSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VOHSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VOHSet.ccP	(revision 18)
@@ -0,0 +1,305 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+     based on code by Doug Schmidt
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.VOHSet.h"
+
+
+/* codes for status fields */
+#define EMPTYCELL   0
+#define VALIDCELL   1
+#define DELETEDCELL 2
+
+
+<T>VOHSet::<T>VOHSet(int sz)
+{
+// The size of the hash table is always the smallest power of 2 >= the size
+// indicated by the user.  This allows several optimizations, including
+// the use of actual double hashing and elimination of the mod instruction.
+
+  size = 1;
+  while (size < sz) size <<= 1;
+  tab = new <T>[size];
+  status = new char[size];
+  for (int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = cnt = 0;
+}
+
+<T>VOHSet::<T>VOHSet(<T>VOHSet& a)
+{
+  tab = new <T>[size = a.size];
+  status = new char[size];
+  for (int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = cnt = 0;
+  for (Pix p = a.first(); p; a.next(p)) add(a(p));
+}
+
+Pix <T>VOHSet::seek(<T&> key)
+{
+// Uses ordered double hashing to perform a search of the table.
+// This greatly speeds up the average-case time for an unsuccessful search.
+
+  unsigned hashval = <T>HASH(key);
+
+  // We can avoid the mod operation since size is a power of 2.
+  unsigned h = hashval & (size - 1);
+
+  // The increment must be odd, since all odd numbers are relatively
+  // prime to a power of 2!!
+  unsigned inc = ((((hashval / size) << 1) + 1) & (size - 1));
+  
+  // There is always at least 1 empty cell, so this loop is guaranteed to halt!
+  while (status[h] != EMPTYCELL)
+  {
+    int cmp = <T>CMP (key, tab[h]);
+    if (cmp == 0)
+    {
+      if (status[h] == VALIDCELL)
+        return Pix(&tab[h]);
+      else
+        return 0;
+    }
+    else if (cmp < 0)
+      return 0;
+    else
+      h = ((h + inc) & (size - 1));
+  }
+  return 0;
+}
+
+// This adds an item if it doesn't already exist.  By performing the initial
+// comparison we assure that the table always contains at least 1 empty
+// spot.  This speeds up later searching by a constant factor.
+// The insertion algorithm uses ordered double hashing.  See Standish's
+// 1980 ``Data Structure's Techniques'' book for details.
+
+Pix <T>VOHSet::add(<T&> x)
+{
+  if (size <= cnt+1) 
+    resize();
+  
+  unsigned hashval = <T>HASH(x);
+  unsigned h = hashval & (size - 1);
+
+  if (status[h] != VALIDCELL)   // save some work if possible
+  {
+    if (status[h] == EMPTYCELL)
+      cnt++;
+    count++;
+    tab[h] = x;
+    status[h] = VALIDCELL; 
+    return Pix(&tab[h]);
+  }
+
+  <T> item = x;
+  Pix mypix = 0;
+  unsigned inc = ((((hashval / size) << 1) + 1) & (size - 1));
+
+  for (;;)
+  {
+    if (status[h] != VALIDCELL)
+    {
+      if (status[h] == EMPTYCELL)
+        cnt++;
+      count++;
+      tab[h] = item;
+      status[h] = VALIDCELL; 
+      return (mypix == 0)? Pix(&tab[h]) : mypix;
+    }
+    int cmp = <T>CMP(item, tab[h]);
+    if (cmp == 0)
+      return (mypix == 0)? Pix(&tab[h]) : mypix;
+    else if (cmp < 0)
+    {
+      <T> temp = tab[h];
+      tab[h] = item;
+      item = temp;
+      if (mypix == 0) mypix = Pix(&tab[h]);
+      hashval = <T>HASH(item);
+      h = hashval & (size - 1);
+      inc = ((((hashval / size) << 1) + 1) & (size - 1));
+    }
+    else
+      h = ((h + inc) & (size - 1));
+  }
+}
+
+
+void <T>VOHSet::del(<T&> key)
+{
+// This performs a deletion by marking the item's status field.
+// Note that we only decrease the count, *not* the cnt, since this
+// would cause trouble for subsequent steps in the algorithm.  See
+// Reingold and Hanson's ``Data Structure's'' book for a justification
+// of this approach.
+
+  unsigned hashval = <T>HASH(key);
+  unsigned h   = hashval & (size - 1);
+  unsigned inc = ((((hashval / size) << 1) + 1) & (size - 1));
+  
+  while (status[h] != EMPTYCELL)
+  {
+    int cmp = <T>CMP(key, tab[h]);
+    if (cmp > 0)
+      h = ((h + inc) & (size - 1));
+    else if (status[h] == VALIDCELL && cmp == 0)
+    {
+      status[h] = DELETEDCELL;
+      count--;
+      return;
+    }
+    else 
+      return;
+  }
+}
+
+void <T>VOHSet::clear()
+{
+  for (int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = cnt = 0;
+}
+
+void <T>VOHSet::resize(int newsize)
+{
+  if (newsize <= count)
+    newsize = count;
+  int s = 1;
+  while (s <= newsize) s <<= 1;
+  newsize = s;
+
+  <T>* oldtab = tab;
+  char* oldstatus = status;
+  int oldsize = size;
+  tab = new <T>[size = newsize];
+  status = new char[size];
+  for (int i = 0; i < size; ++i) status[i] = EMPTYCELL;
+  count = cnt = 0;
+  
+  for (int i = 0; i < oldsize; ++i) if (oldstatus[i] == VALIDCELL) add(oldtab[i]);
+  delete [] oldtab;
+  delete oldstatus;
+}
+
+Pix <T>VOHSet::first()
+{
+  for (int pos = 0; pos < size; ++pos)
+    if (status[pos] == VALIDCELL) return Pix(&tab[pos]);
+  return 0;
+}
+
+void <T>VOHSet::next(Pix& i)
+{
+  if (i == 0) return;
+  int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1;
+  for (; pos < size; ++pos)
+    if (status[pos] == VALIDCELL)
+    {
+      i = Pix(&tab[pos]);
+      return;
+    }
+  i = 0;
+}
+
+
+int <T>VOHSet:: operator == (<T>VOHSet& b)
+{
+  if (count != b.count)
+    return 0;
+  else
+  {
+    for (int i = 0; i < size; ++i)
+      if (status[i] == VALIDCELL && b.seek(tab[i]) == 0)
+          return 0;
+    for (int i = 0; i < b.size; ++i)
+      if (b.status[i] == VALIDCELL && seek(b.tab[i]) == 0)
+          return 0;
+    return 1;
+  }
+}
+
+int <T>VOHSet:: operator != (<T>VOHSet& b)
+{
+  return !(*this == b);
+}
+
+int <T>VOHSet::operator <= (<T>VOHSet& b)
+{
+  if (count > b.count)
+    return 0;
+  else
+  {
+    for (int i = 0; i < size; ++i)
+      if (status[i] == VALIDCELL && b.seek(tab[i]) == 0)
+          return 0;
+    return 1;
+  }
+}
+
+void <T>VOHSet::operator |= (<T>VOHSet& b)
+{
+  if (&b == this || b.count == 0)
+    return;
+  for (int i = 0; i < b.size; ++i)
+    if (b.status[i] == VALIDCELL) add(b.tab[i]);
+}
+
+void <T>VOHSet::operator &= (<T>VOHSet& b)
+{
+  if (&b == this || count == 0)
+    return;
+  for (int i = 0; i < size; ++i)
+  {
+    if (status[i] == VALIDCELL && b.seek(tab[i]) == 0)
+    {
+      status[i] = DELETEDCELL;
+      --count;
+    }
+  }
+}
+
+void <T>VOHSet::operator -= (<T>VOHSet& b)
+{
+  for (int i = 0; i < size; ++i)
+  {
+    if (status[i] == VALIDCELL && b.seek(tab[i]) != 0)
+    {
+      status[i] = DELETEDCELL;
+      --count;
+    }
+  }
+}
+
+int <T>VOHSet::OK()
+{
+  int v = tab != 0;
+  v &= status != 0;
+  int n = 0;
+  for (int i = 0; i < size; ++i) 
+  {
+    if (status[i] == VALIDCELL) ++n;
+    else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL)
+      v = 0;
+  }
+  v &= n == count;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/VOHSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VOHSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VOHSet.hP	(revision 18)
@@ -0,0 +1,88 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+     based on code by Doug Schmidt
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>VOHSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>VOHSet_h 1
+
+#include "<T>.Set.h"
+
+
+
+class <T>VOHSet : public <T>Set
+{
+  <T>*                  tab;
+  char*                 status;
+  int                   size;
+  int                   cnt; // keeps track of VALIDCELLs and DELETEDCELLs
+
+public:
+                        <T>VOHSet(int sz = DEFAULT_INITIAL_CAPACITY);
+                        <T>VOHSet(<T>VOHSet&);
+  inline                       ~<T>VOHSet();
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  inline int           contains(<T&> item);
+
+  void          clear();
+
+  Pix           first();
+  void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  Pix           seek(<T&> item);
+
+  void          operator |= (<T>VOHSet& b);
+  void          operator -= (<T>VOHSet& b);
+  void          operator &= (<T>VOHSet& b);
+
+  int           operator == (<T>VOHSet& b);
+  int           operator != (<T>VOHSet& b);
+  int           operator <= (<T>VOHSet& b); 
+
+  int           capacity();
+  void          resize(int newsize = 0);
+
+  int           OK();
+};
+
+
+inline <T>VOHSet::~<T>VOHSet()
+{
+  delete [] tab;
+  delete status;
+}
+
+
+inline int <T>VOHSet::contains(<T&>  key)
+{
+  return seek(key) != 0;
+}
+
+
+inline <T>& <T>VOHSet::operator () (Pix p)
+{
+  if (p == 0) error("null Pix");
+  return *((<T>*)p);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/VQueue.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VQueue.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VQueue.ccP	(revision 18)
@@ -0,0 +1,83 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.VQueue.h"
+
+<T>VQueue::<T>VQueue(<T>VQueue& b)
+:size(b.size), cnt(b.cnt), inp(b.inp), outp(b.outp), s(new <T> [b.size])
+{
+  int j = outp;
+  for (int i = 0; i < cnt; ++i)
+  {
+    s[j] = b.s[j];
+    if (++j == size) j = 0;
+  }
+}
+
+void <T>VQueue::operator = (<T>VQueue& b)
+{
+  if (&b == this) return;
+  if (size != b.size)
+  {
+    delete [] s;
+    s = new <T> [b.size];
+    size = b.size;
+  }
+  inp = b.inp; outp = b.outp; cnt = b.cnt;
+  int j = outp;
+  for (int i = 0; i < cnt; ++i)
+  {
+    s[j] = b.s[j];
+    if (++j == size) j = 0;
+  }
+}
+
+
+void <T>VQueue::resize(int newsz)
+{
+  if (newsz < cnt)
+    error("resize: new size too small");
+  <T>* news = new <T> [newsz];
+  int j = outp;
+  for (int i = 0; i < cnt; ++i)
+  {
+    news[i] = s[j];
+    if (++j == size) j = 0;
+  }
+  inp = cnt;
+  outp = 0;
+  delete [] s;
+  s = news;
+  size = newsz;
+}
+
+int <T>VQueue::OK()
+{
+  int v = s != 0;               // have space
+  v &= size >= 0;               // a legal size
+  v &= inp >= 0 && inp <= size; // pointers with bounds  
+  v &= outp >= 0 && outp <= size;
+  int c = (size + inp - outp) % size;
+  v &= cnt == size || cnt == c; // correct count
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/VQueue.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VQueue.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VQueue.hP	(revision 18)
@@ -0,0 +1,130 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>VQueue_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>VQueue_h 1
+
+#include "<T>.Queue.h"
+
+class <T>VQueue : public <T>Queue
+{
+protected:
+  int                   size;
+  int                   cnt;
+  int                   inp;
+  int                   outp;
+  <T>*                  s;
+
+public:
+
+                        <T>VQueue(int sz = DEFAULT_INITIAL_CAPACITY);
+                        <T>VQueue(<T>VQueue&);
+  inline                       ~<T>VQueue();
+
+  void                  operator = (<T>VQueue&);
+
+  inline void                  enq(<T&> item);
+  inline <T>                   deq();
+  inline <T>&                  front();
+  inline void                  del_front();
+
+  inline int                   length();
+  inline int                   empty();
+  inline int                   full();
+
+  int                   capacity();
+  void                  resize(int sz);
+  inline void                  clear();
+
+  int                   OK();
+};
+
+
+inline <T>VQueue::<T>VQueue(int sz)
+{
+  s = new <T> [size = sz];
+  cnt = inp = outp = 0;
+}
+
+inline <T>VQueue::~<T>VQueue()
+{
+  delete [] s;
+}
+
+inline void <T>VQueue::clear()
+{
+  inp = outp = 0;
+  cnt = 0;
+}
+
+inline int <T>VQueue::empty()
+{
+  return cnt <= 0;
+}
+
+inline int <T>VQueue::capacity()
+{
+  return size;
+}
+
+inline int <T>VQueue::full()
+{
+  return cnt >= size;
+}
+
+inline int <T>VQueue::length()
+{
+  return cnt;
+}
+
+inline void <T>VQueue::enq(<T&> item)
+{
+  if (cnt >= size) error("enq to full Queue.");
+  ++cnt;
+  s[inp] = item;
+  if (++inp == size) inp = 0;
+}
+
+inline <T> <T>VQueue::deq()
+{
+  if (cnt <= 0) error("deq from empty Queue.");
+  --cnt;
+  int i = outp;
+  if (++outp == size) outp = 0;
+  return s[i];
+}
+
+
+inline void <T>VQueue::del_front()
+{
+  if (cnt <= 0) error("delete from empty Queue.");
+  --cnt;
+  if (++outp == size) outp = 0;
+}
+
+inline <T>& <T>VQueue::front()
+{
+  if (empty()) error("top from empty Queue.");
+  return s[outp];
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/VStack.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VStack.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VStack.ccP	(revision 18)
@@ -0,0 +1,66 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include "<T>.VStack.h"
+
+// error handling
+
+
+<T>VStack::<T>VStack(<T>VStack& b)
+:size(b.size), ptr(b.ptr), s(new <T> [b.size])
+{
+  for (int i = 0; i < ptr; ++i) s[i] = b.s[i];
+}
+
+void <T>VStack::operator = (<T>VStack& b)
+{
+  if (&b == this) return;
+  if (size < b.ptr)
+  {
+    delete [] s;
+    s = new <T> [b.size];
+    size = b.size;
+  }
+  ptr = b.ptr;
+  for (int i = 0; i < ptr; ++i) s[i] = b.s[i];
+}
+
+
+void <T>VStack::resize(int newsz)
+{
+  if (newsz < ptr) error("resize: new size too small");
+  <T>* news = new <T> [newsz];
+  for (int i = 0; i < ptr; ++i) news[i] = s[i];
+  delete [] s;
+  s = news;
+  size = newsz;
+}
+
+int <T>VStack::OK()
+{
+  int v = s != 0;               // have space
+  v &= size >= 0;               // a legal size
+  v &= ptr <= size;             // ptr within bounds
+  v &= ptr >= 0;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/VStack.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/VStack.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/VStack.hP	(revision 18)
@@ -0,0 +1,120 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>VStack_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>VStack_h 1
+
+#include "<T>.Stack.h"
+
+class <T>VStack : public <T>Stack
+{
+protected:
+  int                   size;
+  int                   ptr;
+  <T>*                  s;
+
+public:
+
+                        <T>VStack(int sz = DEFAULT_INITIAL_CAPACITY);
+                        <T>VStack(<T>VStack&);
+  inline                       ~<T>VStack();
+
+  void                  operator = (<T>VStack&);
+  inline void                  push(<T&> item);
+  inline <T>                   pop();
+  inline <T>&                  top();
+  inline void                  del_top();
+
+  inline int                   length();
+  inline int                   empty();
+  inline int                   full();
+  inline void                  clear();
+
+  void                  resize(int sz);
+  int                   capacity();
+
+  int                   OK();
+};
+
+
+inline <T>VStack::<T>VStack(int sz)
+{
+  s = new <T> [size = sz];
+  ptr = 0;
+}
+
+inline <T>VStack::~<T>VStack()
+{
+  delete [] s;
+}
+
+inline void <T>VStack::clear()
+{
+  ptr = 0;
+}
+
+inline int <T>VStack::capacity()
+{
+  return size;
+}
+
+inline int <T>VStack::empty()
+{
+  return ptr == 0;
+}
+
+inline int <T>VStack::full()
+{
+  return ptr == size;
+}
+
+inline int <T>VStack::length()
+{
+  return ptr;
+}
+
+inline void <T>VStack::push(<T&> item)
+{
+  if (full()) error("push to full stack.");
+  s[ptr++] = item;
+}
+
+inline <T> <T>VStack::pop()
+{
+  if (empty()) error("pop from empty stack.");
+  return s[--ptr];
+}
+
+
+inline void <T>VStack::del_top()
+{
+  if (empty()) error("del_top from empty stack.");
+  --ptr;
+}
+
+inline <T>& <T>VStack::top()
+{
+  if (empty()) error("top from empty stack.");
+  return s[ptr-1];
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/Vec.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Vec.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Vec.ccP	(revision 18)
@@ -0,0 +1,478 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include <stream.h>
+#include <builtin.h>
+#include "<T>.Vec.h"
+
+// error handling
+
+
+void default_<T>Vec_error_handler(const char* msg)
+{
+  cerr << "Fatal <T>Vec error. " << msg << "\n";
+  exit(1);
+}
+
+one_arg_error_handler_t <T>Vec_error_handler = default_<T>Vec_error_handler;
+
+one_arg_error_handler_t set_<T>Vec_error_handler(one_arg_error_handler_t f)
+{
+  one_arg_error_handler_t old = <T>Vec_error_handler;
+  <T>Vec_error_handler = f;
+  return old;
+}
+
+void <T>Vec::error(const char* msg)
+{
+  (*<T>Vec_error_handler)(msg);
+}
+
+void <T>Vec::range_error()
+{
+  (*<T>Vec_error_handler)("Index out of range.");
+}
+
+<T>Vec::<T>Vec(const <T>Vec& v)
+{
+  s = new <T> [len = v.len];
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  const <T>* u = v.s;
+  while (t < top) *t++ = *u++;
+}
+
+<T>Vec::<T>Vec(int l, <T&> fill_value)
+{
+  s = new <T> [len = l];
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) *t++ = fill_value;
+}
+
+
+<T>Vec& <T>Vec::operator = (const <T>Vec& v)
+{
+  if (this != &v)
+  {
+    delete [] s;
+    s = new <T> [len = v.len];
+    <T>* top = &(s[len]);
+    <T>* t = s;
+    const <T>* u = v.s;
+    while (t < top) *t++ = *u++;
+  }
+  return *this;
+}
+
+void <T>Vec::apply(<T>Procedure f)
+{
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) (*f)(*t++);
+}
+
+// can't just realloc since there may be need for constructors/destructors
+void <T>Vec::resize(int newl)
+{
+  <T>* news = new <T> [newl];
+  <T>* p = news;
+  int minl = (len < newl)? len : newl;
+  <T>* top = &(s[minl]);
+  <T>* t = s;
+  while (t < top) *p++ = *t++;
+  delete [] s;
+  s = news;
+  len = newl;
+}
+
+<T>Vec concat(<T>Vec & a, <T>Vec & b)
+{
+  int newl = a.len + b.len;
+  <T>* news = new <T> [newl];
+  <T>* p = news;
+  <T>* top = &(a.s[a.len]);
+  <T>* t = a.s;
+  while (t < top) *p++ = *t++;
+  top = &(b.s[b.len]);
+  t = b.s;
+  while (t < top) *p++ = *t++;
+  return <T>Vec(newl, news);
+}
+
+
+<T>Vec combine(<T>Combiner f, <T>Vec& a, <T>Vec& b)
+{
+  int newl = (a.len < b.len)? a.len : b.len;
+  <T>* news = new <T> [newl];
+  <T>* p = news;
+  <T>* top = &(a.s[newl]);
+  <T>* t = a.s;
+  <T>* u = b.s;
+  while (t < top) *p++ = (*f)(*t++, *u++);
+  return <T>Vec(newl, news);
+}
+
+<T> <T>Vec::reduce(<T>Combiner f, <T&> base)
+{
+  <T> r = base;
+  <T>* top = &(s[len]);
+  <T>* t = s;
+  while (t < top) r = (*f)(r, *t++);
+  return r;
+}
+
+<T>Vec reverse(<T>Vec& a)
+{
+  <T>* news = new <T> [a.len];
+  if (a.len != 0)
+  {
+    <T>* lo = news;
+    <T>* hi = &(news[a.len - 1]);
+    while (lo < hi)
+    {
+      <T> tmp = *lo;
+      *lo++ = *hi;
+      *hi-- = tmp;
+    }
+  }
+  return <T>Vec(a.len, news);
+}
+
+void <T>Vec::reverse()
+{
+  if (len != 0)
+  {
+    <T>* lo = s;
+    <T>* hi = &(s[len - 1]);
+    while (lo < hi)
+    {
+      <T> tmp = *lo;
+      *lo++ = *hi;
+      *hi-- = tmp;
+    }
+  }
+}
+
+int <T>Vec::index(<T&> targ)
+{
+  for (int i = 0; i < len; ++i) if (<T>EQ(targ, s[i])) return i;
+  return -1;
+}
+
+<T>Vec map(<T>Mapper f, <T>Vec& a)
+{
+  <T>* news = new <T> [a.len];
+  <T>* p = news;
+  <T>* top = &(a.s[a.len]);
+  <T>* t = a.s;
+  while(t < top) *p++ = (*f)(*t++);
+  return <T>Vec(a.len, news);
+}
+
+int operator == (<T>Vec& a, <T>Vec& b)
+{
+  if (a.len != b.len)
+    return 0;
+  <T>* top = &(a.s[a.len]);
+  <T>* t = a.s;
+  <T>* u = b.s;
+  while (t < top) if (!(<T>EQ(*t++, *u++))) return 0;
+  return 1;
+}
+
+void <T>Vec::fill(<T&> val, int from, int n)
+{
+  int to;
+  if (n < 0)
+    to = len - 1;
+  else
+    to = from + n - 1;
+  if ((unsigned)from > (unsigned)to)
+    range_error();
+  <T>* t = &(s[from]);
+  <T>* top = &(s[to]);
+  while (t <= top) *t++ = val;
+}
+
+<T>Vec <T>Vec::at(int from, int n)
+{
+  int to;
+  if (n < 0)
+  {
+    n = len - from;
+    to = len - 1;
+  }
+  else
+    to = from + n - 1;
+  if ((unsigned)from > (unsigned)to)
+    range_error();
+  <T>* news = new <T> [n];
+  <T>* p = news;
+  <T>* t = &(s[from]);
+  <T>* top = &(s[to]);
+  while (t <= top) *p++ = *t++;
+  return <T>Vec(n, news);
+}
+
+<T>Vec merge(<T>Vec & a, <T>Vec & b, <T>Comparator f)
+{
+  int newl = a.len + b.len;
+  <T>* news = new <T> [newl];
+  <T>* p = news;
+  <T>* topa = &(a.s[a.len]);
+  <T>* as = a.s;
+  <T>* topb = &(b.s[b.len]);
+  <T>* bs = b.s;
+
+  for (;;)
+  {
+    if (as >= topa)
+    {
+      while (bs < topb) *p++ = *bs++;
+      break;
+    }
+    else if (bs >= topb)
+    {
+      while (as < topa) *p++ = *as++;
+      break;
+    }
+    else if ((*f)(*as, *bs) <= 0)
+      *p++ = *as++;
+    else
+      *p++ = *bs++;
+  }
+  return <T>Vec(newl, news);
+}
+
+static int gsort(<T>*, int, <T>Comparator);
+ 
+void <T>Vec::sort (<T>Comparator compar)
+{
+  gsort(s, len, compar);
+}
+
+
+// An adaptation of Schmidt's new quicksort
+
+static inline void SWAP(<T>* A, <T>* B)
+{
+  <T> tmp = *A; *A = *B; *B = tmp;
+}
+
+/* This should be replaced by a standard ANSI macro. */
+#define BYTES_PER_WORD 8
+#define BYTES_PER_LONG 4
+
+/* The next 4 #defines implement a very fast in-line stack abstraction. */
+
+#define STACK_SIZE (BYTES_PER_WORD * BYTES_PER_LONG)
+#define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0)
+#define POP(LOW,HIGH)  do {LOW = (--top)->lo;HIGH = top->hi;} while (0)
+#define STACK_NOT_EMPTY (stack < top)                
+
+/* Discontinue quicksort algorithm when partition gets below this size.
+   This particular magic number was chosen to work best on a Sun 4/260. */
+#define MAX_THRESH 4
+
+
+/* Order size using quicksort.  This implementation incorporates
+   four optimizations discussed in Sedgewick:
+   
+   1. Non-recursive, using an explicit stack of pointer that
+      store the next array partition to sort.  To save time, this
+      maximum amount of space required to store an array of
+      MAX_INT is allocated on the stack.  Assuming a 32-bit integer,
+      this needs only 32 * sizeof (stack_node) == 136 bits.  Pretty
+      cheap, actually.
+
+   2. Chose the pivot element using a median-of-three decision tree.
+      This reduces the probability of selecting a bad pivot value and 
+      eliminates certain extraneous comparisons.
+
+   3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
+      insertion sort to order the MAX_THRESH items within each partition.  
+      This is a big win, since insertion sort is faster for small, mostly
+      sorted array segements.
+   
+   4. The larger of the two sub-partitions is always pushed onto the
+      stack first, with the algorithm then concentrating on the
+      smaller partition.  This *guarantees* no more than log (n)
+      stack size is needed! */
+      
+static int gsort (<T> *base_ptr, int total_elems, <T>Comparator cmp)
+{
+/* Stack node declarations used to store unfulfilled partition obligations. */
+  struct stack_node {  <T> *lo;  <T> *hi; };
+  <T>   pivot_buffer;
+  int   max_thresh   = MAX_THRESH;
+
+  if (total_elems > MAX_THRESH)
+    {
+      <T>       *lo = base_ptr;
+      <T>       *hi = lo + (total_elems - 1);
+      <T>       *left_ptr;
+      <T>       *right_ptr;
+      stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
+      stack_node *top = stack;
+
+      for (;;)
+        {
+          {
+            <T> *pivot = &pivot_buffer;
+            {
+              /* Select median value from among LO, MID, and HI. Rearrange
+                 LO and HI so the three values are sorted. This lowers the 
+                 probability of picking a pathological pivot value and 
+                 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
+
+              <T> *mid = lo + ((hi - lo) >> 1);
+
+              if ((*cmp) (*mid, *lo) < 0)
+                SWAP (mid, lo);
+              if ((*cmp) (*hi, *mid) < 0)
+              {
+                SWAP (mid, hi);
+                if ((*cmp) (*mid, *lo) < 0)
+                  SWAP (mid, lo);
+              }
+              *pivot = *mid;
+              pivot = &pivot_buffer;
+            }
+            left_ptr  = lo + 1;
+            right_ptr = hi - 1; 
+
+            /* Here's the famous ``collapse the walls'' section of quicksort.  
+               Gotta like those tight inner loops!  They are the main reason 
+               that this algorithm runs much faster than others.
+
+	       [Yeah, but there is a function call in the inner loop,
+	       which makes the speed claim rather dubious.  --Per Bothner] */
+            do 
+              {
+                while ((*cmp) (*left_ptr, *pivot) < 0)
+                  left_ptr += 1;
+
+                while ((*cmp) (*pivot, *right_ptr) < 0)
+                  right_ptr -= 1;
+
+                if (left_ptr < right_ptr) 
+                  {
+                    SWAP (left_ptr, right_ptr);
+                    left_ptr += 1;
+                    right_ptr -= 1;
+                  }
+                else if (left_ptr == right_ptr) 
+                  {
+                    left_ptr += 1;
+                    right_ptr -= 1;
+                    break;
+                  }
+              } 
+            while (left_ptr <= right_ptr);
+
+          }
+
+          /* Set up pointers for next iteration.  First determine whether
+             left and right partitions are below the threshold size. If so, 
+             ignore one or both.  Otherwise, push the larger partition's
+             bounds on the stack and continue sorting the smaller one. */
+
+          if ((right_ptr - lo) <= max_thresh)
+            {
+              if ((hi - left_ptr) <= max_thresh)
+		{ /* Ignore both small partitions. */
+		  if (STACK_NOT_EMPTY)
+		    POP (lo, hi);
+		  else
+		    break;  /* No pending partitions - we're done. */
+		}
+              else              /* Ignore small left partition. */  
+                lo = left_ptr;
+            }
+          else if ((hi - left_ptr) <= max_thresh) /* Ignore small right partition. */
+            hi = right_ptr;
+          else if ((right_ptr - lo) > (hi - left_ptr)) /* Push larger left partition indices. */
+            {                   
+              PUSH (lo, right_ptr);
+              lo = left_ptr;
+            }
+          else                  /* Push larger right partition indices. */
+            {                   
+              PUSH (left_ptr, hi);
+              hi = right_ptr;
+            }
+        }
+    }
+
+  /* Once the BASE_PTR array is partially sorted by quicksort the rest
+     is completely sorted using insertion sort, since this is efficient 
+     for partitions below MAX_THRESH size. BASE_PTR points to the beginning 
+     of the array to sort, and END_PTR points at the very last element in
+     the array (*not* one beyond it!). */
+
+
+  {
+    <T> *end_ptr = base_ptr + 1 * (total_elems - 1);
+    <T> *run_ptr;
+    <T> *tmp_ptr = base_ptr;
+    <T> *thresh  = (end_ptr < (base_ptr + max_thresh))? 
+      end_ptr : (base_ptr + max_thresh);
+
+    /* Find smallest element in first threshold and place it at the
+       array's beginning.  This is the smallest array element,
+       and the operation speeds up insertion sort's inner loop. */
+
+    for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr += 1)
+      if ((*cmp) (*run_ptr, *tmp_ptr) < 0)
+        tmp_ptr = run_ptr;
+
+    if (tmp_ptr != base_ptr)
+      SWAP (tmp_ptr, base_ptr);
+
+    /* Insertion sort, running from left-hand-side up to `right-hand-side.' 
+       Pretty much straight out of the original GNU qsort routine. */
+
+    for (run_ptr = base_ptr + 1; (tmp_ptr = run_ptr += 1) <= end_ptr; )
+      {
+
+        while ((*cmp) (*run_ptr, *(tmp_ptr -= 1)) < 0)
+          ;
+
+        if ((tmp_ptr += 1) != run_ptr)
+          {
+            <T> *trav;
+
+            for (trav = run_ptr + 1; --trav >= run_ptr;)
+              {
+                <T> c = *trav;
+                <T> *hi, *lo;
+
+                for (hi = lo = trav; (lo -= 1) >= tmp_ptr; hi = lo)
+                  *hi = *lo;
+                *hi = c;
+              }
+          }
+
+      }
+  }
+  return 1;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/Vec.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/Vec.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/Vec.hP	(revision 18)
@@ -0,0 +1,135 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>Vec_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>Vec_h 1
+
+#include <builtin.h>
+#include "<T>.defs.h"
+
+#ifndef _<T>_typedefs
+#define _<T>_typedefs 1
+typedef void (*<T>Procedure)(<T&>);
+typedef <T>  (*<T>Mapper)(<T&>);
+typedef <T>  (*<T>Combiner)(<T&>, <T&>);
+typedef int  (*<T>Predicate)(<T&>);
+typedef int  (*<T>Comparator)(<T&>, <T&>);
+#endif
+
+
+class <T>Vec 
+{
+protected:      
+  int                   len;
+  <T>                   *s;                  
+
+                        <T>Vec(int l, <T>* d);
+public:
+                        <T>Vec ();
+                        <T>Vec (int l);
+                        <T>Vec (int l, <T&> fill_value);
+                        <T>Vec (const <T>Vec&);
+                        ~<T>Vec ();
+
+  <T>Vec &              operator = (const <T>Vec & a);
+  <T>Vec                at(int from = 0, int n = -1);
+
+  int                   capacity() const;
+  void                  resize(int newlen);                        
+
+  <T>&                  operator [] (int n);
+  <T>&                  elem(int n);
+
+  friend <T>Vec         concat(<T>Vec & a, <T>Vec & b);
+  friend <T>Vec         map(<T>Mapper f, <T>Vec & a);
+  friend <T>Vec         merge(<T>Vec & a, <T>Vec & b, <T>Comparator f);
+  friend <T>Vec         combine(<T>Combiner f, <T>Vec & a, <T>Vec & b);
+  friend <T>Vec         reverse(<T>Vec & a);
+
+  void                  reverse();
+  void                  sort(<T>Comparator f);
+  void                  fill(<T&> val, int from = 0, int n = -1);
+
+  void                  apply(<T>Procedure f);
+  <T>                   reduce(<T>Combiner f, <T&> base);
+  int                   index(<T&> targ);
+
+  friend int            operator == (<T>Vec& a, <T>Vec& b);
+  friend int            operator != (<T>Vec& a, <T>Vec& b);
+
+  void                  error(const char* msg);
+  void                  range_error();
+};
+
+extern void default_<T>Vec_error_handler(const char*);
+extern one_arg_error_handler_t <T>Vec_error_handler;
+
+extern one_arg_error_handler_t 
+        set_<T>Vec_error_handler(one_arg_error_handler_t f);
+
+
+inline <T>Vec::<T>Vec()
+{
+  len = 0; s = 0;
+}
+
+inline <T>Vec::<T>Vec(int l)
+{
+  s = new <T> [len = l];
+}
+
+
+inline <T>Vec::<T>Vec(int l, <T>* d) :len(l), s(d) {}
+
+
+inline <T>Vec::~<T>Vec()
+{
+  delete [] s;
+}
+
+
+inline <T>& <T>Vec::operator [] (int n)
+{
+  if ((unsigned)n >= (unsigned)len)
+    range_error();
+  return s[n];
+}
+
+inline <T>& <T>Vec::elem(int n)
+{
+  return s[n];
+}
+
+
+inline int <T>Vec::capacity() const
+{
+  return len;
+}
+
+
+
+inline int operator != (<T>Vec& a, <T>Vec& b)
+{
+  return !(a == b);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/XPBag.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPBag.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPBag.ccP	(revision 18)
@@ -0,0 +1,72 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.XPBag.h"
+
+int <T>XPBag::OK()
+{
+  int v = p.OK();
+  v &= count == p.length();
+  if (!v) error("invariant failure");
+  return v;
+}
+
+Pix <T>XPBag::seek(<T&> item, Pix i)
+{
+  if (i == 0) i = p.first(); else next(i);
+  for (; i != 0; p.next(i)) if (<T>EQ(p(i), item)) return i;
+  return 0;
+}
+
+int <T>XPBag::nof(<T&> item)
+{
+  int n = 0;
+  for (int i = p.low(); i < p.fence(); p.next(i)) if (<T>EQ(p[i], item)) ++n;
+  return n;
+}
+
+void <T>XPBag::del(<T&> item)
+{
+  for (int i = p.low(); i < p.fence(); p.next(i))
+  {
+    if (<T>EQ(p[i], item))
+    {
+      --count;
+      p[i] = p.low_element();
+      p.del_low();
+      return;
+    }
+  }
+}
+
+void <T>XPBag::remove(<T&> item)
+{
+  for (int i = p.low(); i < p.fence(); p.next(i))
+  {
+    if (<T>EQ(p[i], item))
+    {
+      --count;
+      p[i] = p.low_element();
+      p.del_low();
+    }
+  }
+}
+
Index: trunk/src/emx/include/Attic/cpp/gen/XPBag.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPBag.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPBag.hP	(revision 18)
@@ -0,0 +1,98 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>XPBag_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>XPBag_h 1
+
+#include "<T>.Bag.h"
+#include "<T>.XPlex.h"
+
+class <T>XPBag : public <T>Bag
+{
+protected:
+  <T>XPlex              p;
+
+public:
+                <T>XPBag(int chunksize = DEFAULT_INITIAL_CAPACITY);
+                <T>XPBag(const <T>XPBag&);
+
+  inline Pix           add(<T&> item);
+  void          del(<T&> item);
+#undef remove
+  void          remove(<T&>item);
+  int           nof(<T&> item);
+  inline int           contains(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item, Pix from = 0);
+
+  int           OK();
+};
+
+
+inline <T>XPBag::<T>XPBag(int chunksize) 
+     : p(chunksize) { count = 0; }
+
+inline <T>XPBag::<T>XPBag(const <T>XPBag& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>XPBag::first()
+{
+  return p.first();
+}
+
+inline void <T>XPBag::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>XPBag::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline void <T>XPBag::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>XPBag::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+inline Pix <T>XPBag::add(<T&> item)
+{
+  ++count;
+  return p.index_to_Pix(p.add_high(item));
+}
+
+inline int <T>XPBag::contains(<T&> item)
+{
+  return seek(item) != 0;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/XPDeque.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPDeque.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPDeque.ccP	(revision 18)
@@ -0,0 +1,4 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.XPDeque.h"
Index: trunk/src/emx/include/Attic/cpp/gen/XPDeque.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPDeque.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPDeque.hP	(revision 18)
@@ -0,0 +1,133 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>XPDeque_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>XPDeque_h
+
+#include "<T>.XPlex.h"
+#include "<T>.Deque.h"
+
+class <T>XPDeque : public <T>Deque
+{
+  <T>XPlex     p;
+
+public:
+               <T>XPDeque(int chunksize = DEFAULT_INITIAL_CAPACITY);
+               <T>XPDeque(const <T>XPDeque& d);
+  inline              ~<T>XPDeque();
+
+  void          operator = (const <T>XPDeque&);
+
+  inline void          push(<T&> item); // insert at front
+  inline void          enq(<T&> item);  // insert at rear
+
+  inline <T>&          front();
+  inline <T>&          rear();
+
+  inline <T>           deq();
+  inline void          del_front();
+  inline void          del_rear();               
+
+  inline void          clear();
+  inline int           empty();
+  inline int           full();
+  inline int           length();
+               
+  inline int           OK();
+};
+
+inline <T>XPDeque::<T>XPDeque(int chunksize) 
+     : p(chunksize) {}
+inline <T>XPDeque::<T>XPDeque(const <T>XPDeque& d) : p(d.p) {}
+
+inline <T>XPDeque::~<T>XPDeque() {}
+
+inline void <T>XPDeque::push(<T&>item)
+{
+  p.add_low(item);
+}
+
+inline void <T>XPDeque::enq(<T&>item)
+{
+  p.add_high(item);
+}
+
+inline <T> <T>XPDeque::deq()
+{
+  <T> res = p.low_element();
+  p.del_low();
+  return res;
+}
+
+inline <T>& <T>XPDeque::front()
+{
+  return p.low_element();
+}
+
+inline <T>& <T>XPDeque::rear()
+{
+  return p.high_element();
+}
+
+inline void <T>XPDeque::del_front()
+{
+  p.del_low();
+}
+
+inline void <T>XPDeque::del_rear()
+{
+  p.del_high();
+}
+
+inline void <T>XPDeque::operator =(const <T>XPDeque& s)
+{
+  p.operator = (s.p);
+}
+
+
+inline int <T>XPDeque::empty()
+{
+  return p.empty();
+}
+
+inline int <T>XPDeque::full()
+{
+  return p.full();
+}
+
+inline int <T>XPDeque::length()
+{
+  return p.length();
+}
+
+inline int <T>XPDeque::OK()
+{
+  return p.OK();
+}
+
+inline void <T>XPDeque::clear()
+{
+  p.clear();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/XPPQ.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPPQ.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPPQ.ccP	(revision 18)
@@ -0,0 +1,143 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.XPPQ.h"
+
+int <T>XPPQ::OK()
+{
+  int v = p.OK();
+  v &= p.low() == 1;
+  v &= count == p.length();
+  if (!v) error("invariant failure");
+  return v;
+}
+
+Pix <T>XPPQ::seek(<T&> item)
+{
+  for (int i = p.low(); i < p.fence(); p.next(i))
+    if (<T>EQ(p[i],item)) return p.index_to_Pix(i);
+  return 0;
+}
+
+// standard 2-ary heap ops
+// pointers are used a lot to avoid thrashing across chunks with plexes
+
+Pix <T>XPPQ::enq(<T&> item)
+{
+  p.add_high(item);
+  <T>* pk = &(p.high_element());
+  int par = ++count >> 1;
+  while (par != 0)
+  {
+    <T>* ppar = &(p[par]);
+    if (!(<T>LE(*ppar, item)))
+    {
+      *pk = *ppar;
+      pk = ppar;
+      par >>= 1;
+    }
+    else
+      break;
+  }
+  *pk = item;
+  return Pix(pk);
+}
+
+void <T>XPPQ::del_front()
+{
+  if (count == 0) error("empty PQ");
+  --count;
+  <T>* pk = &(p.low_element());
+  <T>* ph = &(p.high_element());
+  int child = 2;
+  while (child <= count)
+  {
+    <T>* pchild = &(p[child]);
+    if (child < count)
+    {
+      <T>* prchild = &(p[child+1]);
+      if (!(<T>LE(*pchild, *prchild)))
+      {
+        pchild = prchild;
+        ++child;
+      }
+    }
+    if (!(<T>LE(*ph, *pchild)))
+    {
+      *pk = *pchild;
+      pk = pchild;
+      child <<= 1;
+    }
+    else
+      break;
+  }
+  *pk = *ph;
+  p.del_high();
+}
+
+
+void <T>XPPQ::del(Pix i)
+{
+  if (i == 0) error("null Pix");
+  --count;
+  int k = p.Pix_to_index(i);
+  <T>* pk = &(p[k]);
+  <T>* ph = &(p.high_element());
+  int child = k << 1;
+  while (child <= count)
+  {
+    <T>* pchild = &(p[child]);
+    if (child < count)
+    {
+      <T>* prchild = &(p[child+1]);
+      if (!(<T>LE(*pchild, *prchild)))
+      {
+        pchild = prchild;
+        ++child;
+      }
+    }
+    if (!(<T>LE(*ph, *pchild)))
+    {
+      *pk = *pchild;
+      pk = pchild;
+      child <<= 1;
+    }
+    else
+      break;
+  }
+  int par = child >> 2;
+  while (par != 0)
+  {
+    <T>* ppar = &(p[par]);
+    if (!(<T>LE(*ppar, *ph)))
+    {
+      *pk = *ppar;
+      pk = ppar;
+      par >>= 1;
+    }
+    else
+      break;
+  }
+  *pk = *ph;
+  p.del_high();
+}
+
+
Index: trunk/src/emx/include/Attic/cpp/gen/XPPQ.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPPQ.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPPQ.hP	(revision 18)
@@ -0,0 +1,105 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>XPPQ_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>XPPQ_h 1
+
+#include "<T>.PQ.h"
+#include "<T>.XPlex.h"
+
+class <T>XPPQ : public <T>PQ
+{
+protected:
+  <T>XPlex              p;
+
+public:
+                <T>XPPQ(int chunksize = DEFAULT_INITIAL_CAPACITY);
+                <T>XPPQ(const <T>XPPQ&);
+
+  Pix           enq(<T&> item);
+  inline <T>           deq(); 
+
+  inline <T>&          front();
+  void          del_front();
+
+  inline int           contains(<T&> item);
+
+  inline void          clear(); 
+
+  inline Pix           first(); 
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  void          del(Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item);
+
+  int           OK();                    // rep invariant
+};
+
+inline <T>XPPQ::<T>XPPQ(int chunksize) 
+     : p(1, chunksize) { count = 0; }
+
+inline <T>XPPQ::<T>XPPQ(const <T>XPPQ& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>XPPQ::first()
+{
+  return p.first();
+}
+
+inline void <T>XPPQ::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>XPPQ::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline <T>& <T>XPPQ::front ()
+{
+  return p.low_element();
+}
+
+inline <T> <T>XPPQ::deq ()
+{
+  <T> x = p.low_element();
+  del_front();
+  return x;
+}
+
+inline void <T>XPPQ::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>XPPQ::contains (<T&> item)
+{
+  return seek(item) != 0;
+}
+
+inline int <T>XPPQ::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/XPQueue.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPQueue.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPQueue.ccP	(revision 18)
@@ -0,0 +1,4 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.XPQueue.h"
Index: trunk/src/emx/include/Attic/cpp/gen/XPQueue.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPQueue.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPQueue.hP	(revision 18)
@@ -0,0 +1,114 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>XPQueue_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>XPQueue_h
+
+#include "<T>.XPlex.h"
+#include "<T>.Queue.h"
+
+class <T>XPQueue : public <T>Queue
+{
+protected:
+  <T>XPlex     p;
+
+public:
+               <T>XPQueue(int chunksize = DEFAULT_INITIAL_CAPACITY);
+               <T>XPQueue(const <T>XPQueue& q);
+  inline              ~<T>XPQueue();
+
+  void          operator = (const <T>XPQueue&);
+
+  inline void          enq(<T&> item);
+  inline <T>           deq();
+  inline <T>&          front();
+  inline void          del_front();
+
+  inline void          clear();
+  inline int           empty();
+  inline int           full();
+  inline int           length();
+               
+  inline int           OK();
+};
+
+inline <T>XPQueue::<T>XPQueue(int chunksize) 
+     : p(chunksize) {}
+inline <T>XPQueue::<T>XPQueue(const <T>XPQueue& q) : p(q.p) {}
+
+inline <T>XPQueue::~<T>XPQueue() {}
+
+inline void <T>XPQueue::enq(<T&>item)
+{
+  p.add_high(item);
+}
+
+inline <T> <T>XPQueue::deq()
+{
+  <T> res = p.low_element();
+  p.del_low();
+  return res;
+}
+
+inline <T>& <T>XPQueue::front()
+{
+  return p.low_element();
+}
+
+
+inline void <T>XPQueue::del_front()
+{
+  p.del_low();
+}
+
+inline void <T>XPQueue::operator =(const <T>XPQueue& s)
+{
+  p.operator = (s.p);
+}
+
+inline int <T>XPQueue::empty()
+{
+  return p.empty();
+}
+
+inline int <T>XPQueue::full()
+{
+  return p.full();
+}
+
+inline int <T>XPQueue::length()
+{
+  return p.length();
+}
+
+inline int <T>XPQueue::OK()
+{
+  return p.OK();
+}
+
+inline void <T>XPQueue::clear()
+{
+  p.clear();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/XPSet.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPSet.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPSet.ccP	(revision 18)
@@ -0,0 +1,63 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.XPSet.h"
+
+int <T>XPSet::OK()
+{
+  int v = p.OK();
+  v &= count == p.length();
+  if (!v) error("invariant failure");
+  return v;
+}
+
+Pix <T>XPSet::seek(<T&> item)
+{
+  for (int i = p.low(); i < p.fence(); p.next(i))
+    if (<T>EQ(p[i],item)) return p.index_to_Pix(i);
+  return 0;
+}
+
+Pix <T>XPSet::add(<T&> item)
+{
+  Pix i = seek(item);
+  if (i == 0)
+  {
+    ++count;
+    i = p.index_to_Pix(p.add_high(item));
+  }
+  return i;
+}
+
+void <T>XPSet::del(<T&> item)
+{
+  for (int i = p.low(); i < p.fence(); p.next(i))
+  {
+    if (<T>EQ(p[i], item))
+    {
+      --count;
+      p[i] = p.low_element();
+      p.del_low();
+      return;
+    }
+  }
+}
+
Index: trunk/src/emx/include/Attic/cpp/gen/XPSet.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPSet.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPSet.hP	(revision 18)
@@ -0,0 +1,89 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>XPSet_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>XPSet_h 1
+
+#include "<T>.Set.h"
+#include "<T>.XPlex.h"
+
+class <T>XPSet : public <T>Set
+{
+protected:
+  <T>XPlex              p;
+
+public:
+                <T>XPSet(int chunksize = DEFAULT_INITIAL_CAPACITY);
+                <T>XPSet(const <T>XPSet&);
+
+  Pix           add(<T&> item);
+  void          del(<T&> item);
+  inline int           contains(<T&> item);
+
+  inline void          clear();
+
+  inline Pix           first();
+  inline void          next(Pix& i);
+  inline <T>&          operator () (Pix i);
+  inline int           owns(Pix i);
+  Pix           seek(<T&> item);
+
+  int           OK();
+};
+
+
+inline <T>XPSet::<T>XPSet(int chunksize) 
+     : p(chunksize) { count = 0; }
+
+inline <T>XPSet::<T>XPSet(const <T>XPSet& s) : p(s.p) { count = s.count; }
+
+inline Pix <T>XPSet::first()
+{
+  return p.first();
+}
+
+inline void <T>XPSet::next(Pix  & idx)
+{
+  p.next(idx);
+}
+
+inline <T>& <T>XPSet::operator ()(Pix   idx)
+{
+  return p(idx);
+}
+
+inline void <T>XPSet::clear()
+{
+  count = 0;  p.clear();
+}
+
+inline int <T>XPSet::contains (<T&> item)
+{
+  return seek(item) != 0;
+}
+
+inline int <T>XPSet::owns (Pix   idx)
+{
+  return p.owns(idx);
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/XPStack.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPStack.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPStack.ccP	(revision 18)
@@ -0,0 +1,4 @@
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.XPStack.h"
Index: trunk/src/emx/include/Attic/cpp/gen/XPStack.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPStack.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPStack.hP	(revision 18)
@@ -0,0 +1,115 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>XPStack_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>XPStack_h
+
+#include "<T>.XPlex.h"
+#include "<T>.Stack.h"
+
+class <T>XPStack : public <T>Stack
+{
+  <T>XPlex      p;
+
+public:
+                <T>XPStack(int chunksize = DEFAULT_INITIAL_CAPACITY);
+                <T>XPStack(const <T>XPStack& s);
+  inline               ~<T>XPStack();
+
+  void          operator = (const <T>XPStack&);
+
+  inline void          push(<T&> item);
+  inline <T>           pop();
+  inline <T>&          top();               
+  inline void          del_top();
+
+  inline int           empty();
+  inline int           full();
+  inline int           length();
+
+  inline void          clear();
+
+  inline int           OK();
+
+};
+
+
+inline <T>XPStack::<T>XPStack(int chunksize) 
+     : p(chunksize) {}
+inline <T>XPStack::<T>XPStack(const <T>XPStack& s) : p(s.p) {}
+
+inline <T>XPStack::~<T>XPStack() {}
+
+inline void <T>XPStack::push(<T&>item)
+{
+  p.add_high(item);
+}
+
+inline <T> <T>XPStack::pop()
+{
+  <T> res = p.high_element();
+  p.del_high();
+  return res;
+}
+
+inline <T>& <T>XPStack::top()
+{
+  return p.high_element();
+}
+
+inline void <T>XPStack::del_top()
+{
+  p.del_high();
+}
+
+inline void <T>XPStack::operator =(const <T>XPStack& s)
+{
+  p.operator = (s.p);
+}
+
+inline int <T>XPStack::empty() 
+{
+  return p.empty();
+}
+
+inline int <T>XPStack::full() 
+{
+  return p.full();
+}
+
+inline int <T>XPStack::length() 
+{
+  return p.length();
+}
+
+inline int <T>XPStack::OK() 
+{
+  return p.OK();
+}
+
+inline void <T>XPStack::clear() 
+{
+  p.clear();
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/XPlex.ccP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPlex.ccP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPlex.ccP	(revision 18)
@@ -0,0 +1,397 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "<T>.XPlex.h"
+
+
+<T>XPlex:: <T>XPlex()
+{
+  lo = fnc = 0;
+  csize = DEFAULT_INITIAL_CAPACITY;
+  <T>* data = new <T>[csize];
+  set_cache(new <T>IChunk(data,  lo, lo, fnc, lo+csize));
+  hd = ch;
+}
+
+<T>XPlex:: <T>XPlex(int chunksize)
+{
+  if (chunksize == 0) error("invalid constructor specification");
+  lo = fnc = 0;
+  if (chunksize > 0)
+  {
+    csize = chunksize;
+    <T>* data = new <T>[csize];
+    set_cache(new <T>IChunk(data,  lo, lo, fnc, csize));
+    hd = ch;
+  }
+  else
+  {
+    csize = -chunksize;
+    <T>* data = new <T>[csize];
+    set_cache(new <T>IChunk(data,  chunksize, lo, fnc, fnc));
+    hd = ch;
+  }
+}
+
+
+<T>XPlex:: <T>XPlex(int l, int chunksize)
+{
+  if (chunksize == 0) error("invalid constructor specification");
+  lo = fnc = l;
+  if (chunksize > 0)
+  {
+    csize = chunksize;
+    <T>* data = new <T>[csize];
+    set_cache(new <T>IChunk(data,  lo, lo, fnc, csize+lo));
+    hd = ch;
+  }
+  else
+  {
+    csize = -chunksize;
+    <T>* data = new <T>[csize];
+    set_cache(new <T>IChunk(data,  chunksize+lo, lo, fnc, fnc));
+    hd = ch;
+  }
+}
+
+void <T>XPlex::make_initial_chunks(int up)
+{
+  int need = fnc - lo;
+  hd = 0;
+  if (up)
+  {
+    int l = lo;
+    do
+    {
+      int sz;
+      if (need >= csize)
+        sz = csize;
+      else
+        sz = need;
+      <T>* data = new <T> [csize];
+      <T>IChunk* h = new <T>IChunk(data,  l, l, l+sz, l+csize);
+      if (hd != 0)
+        h->link_to_next(hd);
+      else
+        hd = h;
+      l += sz;
+      need -= sz;
+    } while (need > 0);
+  }
+  else
+  {
+    int hi = fnc;
+    do
+    {
+      int sz;
+      if (need >= csize)
+        sz = csize;
+      else
+        sz = need;
+      <T>* data = new <T> [csize];
+      <T>IChunk* h = new <T>IChunk(data,  hi-csize, hi-sz, hi, hi);
+      if (hd != 0)
+        h->link_to_next(hd);
+      hd = h;
+      hi -= sz;
+      need -= sz;
+    } while (need > 0);
+  }
+  set_cache(hd);
+}
+
+<T>XPlex:: <T>XPlex(int l, int hi, const <T&> initval, int chunksize)
+{
+  lo = l;
+  fnc = hi + 1;
+  if (chunksize == 0)
+  {
+    csize = fnc - l;
+    make_initial_chunks(1);
+  }
+  else if (chunksize < 0)
+  {
+    csize = -chunksize;
+    make_initial_chunks(0);
+  }
+  else
+  {
+    csize = chunksize;
+    make_initial_chunks(1);
+  }
+  fill(initval);
+}
+
+<T>XPlex::<T>XPlex(const <T>XPlex& a)
+{
+  lo = a.lo;
+  fnc = a.fnc;
+  csize = a.csize;
+  make_initial_chunks();
+  for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
+}
+
+void <T>XPlex::operator= (const <T>XPlex& a)
+{
+  if (&a != this)
+  {
+    invalidate();
+    lo = a.lo;
+    fnc = a.fnc;
+    csize = a.csize;
+    make_initial_chunks();
+    for (int i = a.low(); i < a.fence(); a.next(i)) (*this)[i] = a[i];
+  }
+}
+
+
+void <T>XPlex::cache(int idx) const
+{
+  const <T>IChunk* tail = tl();
+  const <T>IChunk* t = ch;
+  while (idx >= t->fence_index())
+  {
+    if (t == tail) index_error();
+    t = (t->next());
+  }
+  while (idx < t->low_index())
+  {
+    if (t == hd) index_error();
+    t = (t->prev());
+  }
+  set_cache(t);
+}
+
+
+void <T>XPlex::cache(const <T>* p) const
+{
+  const <T>IChunk* old = ch;
+  const <T>IChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = (t->next());
+    if (t == old) index_error();
+  }
+  set_cache(t);
+}
+
+int <T>XPlex::owns(Pix px) const
+{
+  <T>* p = (<T>*)px;
+  const <T>IChunk* old = ch;
+  const <T>IChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = (t->next());
+    if (t == old) { set_cache(t); return 0; }
+  }
+  set_cache(t);
+  return 1;
+}
+
+
+<T>* <T>XPlex::dosucc(const <T>* p) const
+{
+  if (p == 0) return 0;
+  const <T>IChunk* old = ch;
+  const <T>IChunk* t = ch;
+ 
+  while (!t->actual_pointer(p))
+  {
+    t = (t->next());
+    if (t == old)  return 0;
+  }
+  int i = t->index_of(p) + 1;
+  if (i >= fnc) return 0;
+  if (i >= t->fence_index()) t = (t->next());
+  set_cache(t);
+  return (t->pointer_to(i));
+}
+
+<T>* <T>XPlex::dopred(const <T>* p) const
+{
+  if (p == 0) return 0;
+  const <T>IChunk* old = ch;
+  const <T>IChunk* t = ch;
+  while (!t->actual_pointer(p))
+  {
+    t = (t->prev());
+    if (t == old) return 0;
+  }
+  int i = t->index_of(p) - 1;
+  if (i < lo) return 0;
+  if (i < t->low_index()) t = (t->prev());
+  set_cache(t);
+  return (t->pointer_to(i));
+}
+
+
+int <T>XPlex::add_high(const <T&> elem)
+{
+  <T>IChunk* t = tl();
+  if (!t->can_grow_high())
+  {
+    if (t-><T>IChunk::empty() && one_chunk())
+      t->clear(fnc);
+    else
+    {
+      <T>* data = new <T> [csize];
+      t = (new <T>IChunk(data,  fnc, fnc, fnc,fnc+csize));
+      t->link_to_prev(tl());
+    }
+  }
+  *((t-><T>IChunk::grow_high())) = elem;
+  set_cache(t);
+  return fnc++;
+}
+
+int <T>XPlex::del_high ()
+{
+  if (empty()) empty_error();
+  <T>IChunk* t = tl();
+  t-><T>IChunk::shrink_high();
+  if (t-><T>IChunk::empty() && !one_chunk())
+  {
+    <T>IChunk* pred = t->prev();
+    del_chunk(t);
+    t = pred;
+  }
+  set_cache(t);
+  return --fnc - 1;
+}
+
+int <T>XPlex::add_low (const <T&> elem)
+{
+  <T>IChunk* t = hd;
+  if (!t->can_grow_low())
+  {
+    if (t-><T>IChunk::empty() && one_chunk())
+      t->cleardown(lo);
+    else
+    {
+      <T>* data = new <T> [csize];
+      hd = new <T>IChunk(data,  lo-csize, lo, lo, lo);
+      hd->link_to_next(t);
+      t = hd;
+    }
+  }
+  *((t-><T>IChunk::grow_low())) = elem;
+  set_cache(t);
+  return --lo;
+}
+
+
+int <T>XPlex::del_low ()
+{
+  if (empty()) empty_error();
+  <T>IChunk* t = hd;
+  t-><T>IChunk::shrink_low();
+  if (t-><T>IChunk::empty() && !one_chunk())
+  {
+    hd = t->next();
+    del_chunk(t);
+    t = hd;
+  }
+  set_cache(t);
+  return ++lo;
+}
+
+void <T>XPlex::reverse()
+{
+  <T> tmp;
+  int l = lo;
+  int h = fnc - 1;
+  <T>IChunk* loch = hd;
+  <T>IChunk* hich = tl();
+  while (l < h)
+  {
+    <T>* lptr = loch->pointer_to(l);
+    <T>* hptr = hich->pointer_to(h);
+    tmp = *lptr;
+    *lptr = *hptr;
+    *hptr = tmp;
+    if (++l >= loch->fence_index()) loch = loch->next();
+    if (--h < hich->low_index()) hich = hich->prev();
+  }
+}
+
+void <T>XPlex::fill(const <T&> x)
+{
+  for (int i = lo; i < fnc; ++i) (*this)[i] = x;
+}
+
+void <T>XPlex::fill(const <T&> x, int l, int hi)
+{
+  for (int i = l; i <= hi; ++i) (*this)[i] = x;
+}
+
+
+void <T>XPlex::clear()
+{
+  if (fnc != lo)
+  {
+    <T>IChunk* t = tl();
+    while (t != hd)
+    {
+      <T>IChunk* prv = t->prev();
+      del_chunk(t);
+      t = prv;
+    }
+    t-><T>IChunk::clear(lo);
+    set_cache(t);
+    fnc = lo;
+  }
+}
+
+
+int <T>XPlex::OK () const
+{
+  int v = hd != 0 && ch != 0;     // at least one chunk
+
+  v &= fnc == tl()->fence_index();// last chunk fence == plex fence
+  v &= lo == ((hd))-><T>IChunk::low_index();    // first lo == plex lo
+
+// loop for others:
+  int found_ch = 0;                   // to make sure ch is in list;
+  const <T>IChunk* t = (hd);
+  for (;;)
+  {
+    if (t == ch) ++found_ch;
+    v &= t-><T>IChunk::OK();              // each chunk is OK
+    if (t == tl())
+      break;
+    else                              // and has indices contiguous to succ
+    {
+      v &= t->top_index() == t->next()->base_index();
+      if (t != hd)                  // internal chunks full
+      {
+        v &= !t->empty();
+        v &= !t->can_grow_low();
+        v &= !t->can_grow_high();
+      }
+      t = t->next();
+    }
+  }
+  v &= found_ch == 1;
+  if (!v) error("invariant failure");
+  return v;
+}
Index: trunk/src/emx/include/Attic/cpp/gen/XPlex.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/XPlex.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/XPlex.hP	(revision 18)
@@ -0,0 +1,238 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+    based on code by Marc Shapiro (shapiro@sor.inria.fr)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _<T>XPlex_h
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _<T>XPlex_h 1
+
+#include "<T>.Plex.h"
+
+class <T>XPlex: public <T>Plex
+{
+  <T>IChunk*       ch;           // cached chunk
+
+  void             make_initial_chunks(int up = 1);
+
+  void             cache(int idx) const;
+  void             cache(const <T>* p) const;
+
+  <T>*             dopred(const <T>* p) const;
+  <T>*             dosucc(const <T>* p) const;
+
+  inline void             set_cache(const <T>IChunk* t) const; // logically, 
+                                               // not physically const
+public:
+                   <T>XPlex();                 // set low = 0;
+                                               // fence = 0;
+                                               // csize = default
+
+                   <T>XPlex(int ch_size);      // low = 0; 
+                                               // fence = 0;
+                                               // csize = ch_size
+
+                   <T>XPlex(int lo,            // low = lo; 
+                            int ch_size);      // fence=lo
+                                               // csize = ch_size
+
+                   <T>XPlex(int lo,            // low = lo
+                            int hi,            // fence = hi+1
+                            const <T&> initval,// fill with initval,
+                            int ch_size = 0);  // csize= ch_size
+                                               // or fence-lo if 0
+
+                   <T>XPlex(const <T>XPlex&);
+  
+  void             operator= (const <T>XPlex&);
+
+// virtuals
+
+
+  inline <T>&             high_element ();
+  inline <T>&             low_element ();
+
+  inline const <T>&       high_element () const;
+  inline const <T>&       low_element () const;
+
+  inline Pix              first() const;
+  inline Pix              last() const;
+  inline void             prev(Pix& ptr) const;
+  inline void             next(Pix& ptr) const;
+  int              owns(Pix p) const;
+  inline <T>&             operator () (Pix p);
+  inline const <T>&       operator () (Pix p) const;
+
+  inline int              low() const; 
+  inline int              high() const;
+  inline int              valid(int idx) const;
+  inline void             prev(int& idx) const;
+  inline void             next(int& x) const;
+  inline <T>&             operator [] (int index);
+  inline const <T>&       operator [] (int index) const;
+    
+  inline int              Pix_to_index(Pix p) const;
+  inline Pix              index_to_Pix(int idx) const;    
+
+  inline int              can_add_high() const;
+  inline int              can_add_low() const;
+  inline int              full() const;
+
+  int              add_high(const <T&> elem);
+  int              del_high ();
+  int              add_low (const <T&> elem);
+  int              del_low ();
+
+  void             fill(const <T&> x);
+  void             fill(const <T&> x, int from, int to);
+  void             clear();
+  void             reverse();
+    
+  int              OK () const; 
+
+};
+
+
+inline void <T>XPlex::prev(int& idx) const
+{
+  --idx;
+}
+
+inline void <T>XPlex::next(int& idx) const
+{
+  ++idx;
+}
+
+inline  int <T>XPlex::full () const
+{
+  return 0;
+}
+
+inline int <T>XPlex::can_add_high() const
+{
+  return 1;
+}
+
+inline int <T>XPlex::can_add_low() const
+{
+  return 1;
+}
+
+inline  int <T>XPlex::valid (int idx) const
+{
+  return idx >= lo && idx < fnc;
+}
+
+inline int <T>XPlex::low() const
+{
+  return lo;
+}
+
+inline int <T>XPlex::high() const
+{
+  return fnc - 1;
+}
+
+inline <T>& <T>XPlex:: operator [] (int idx)
+{
+  if (!ch->actual_index(idx)) cache(idx);
+  return *(ch->pointer_to(idx));
+}
+
+inline const <T>& <T>XPlex:: operator [] (int idx) const
+{
+  if (!ch->actual_index(idx)) cache(idx);
+  return *((const <T>*)(ch->pointer_to(idx)));
+}
+
+inline  <T>& <T>XPlex::low_element ()
+{
+  if (empty()) index_error();
+  return *(hd->pointer_to(lo));
+}
+
+inline  const <T>& <T>XPlex::low_element () const
+{
+  if (empty()) index_error();
+  return *((const <T>*)(hd->pointer_to(lo)));
+}
+
+inline  <T>& <T>XPlex::high_element ()
+{
+  if (empty()) index_error();
+  return *(tl()->pointer_to(fnc - 1));
+}
+
+inline const <T>& <T>XPlex::high_element () const
+{
+  if (empty()) index_error();
+  return *((const <T>*)(tl()->pointer_to(fnc - 1)));
+}
+
+inline  int <T>XPlex::Pix_to_index(Pix px) const
+{
+  <T>* p = (<T>*)px;
+  if (!ch->actual_pointer(p)) cache(p);
+  return ch->index_of(p);
+}
+
+inline  Pix <T>XPlex::index_to_Pix(int idx) const
+{
+  if (!ch->actual_index(idx)) cache(idx);
+  return (Pix)(ch->pointer_to(idx));
+}
+
+inline Pix <T>XPlex::first() const
+{
+  return Pix(hd-><T>IChunk::first_pointer());
+}
+
+inline Pix <T>XPlex::last() const
+{
+  return Pix(tl()-><T>IChunk::last_pointer());
+}
+
+inline void <T>XPlex::prev(Pix& p) const
+{
+  Pix q = Pix(ch-><T>IChunk::pred((<T>*) p));
+  p = (q == 0)? Pix(dopred((const <T>*) p)) : q;
+}
+
+inline void <T>XPlex::next(Pix& p) const
+{
+  Pix q = Pix(ch-><T>IChunk::succ((<T>*) p));
+  p = (q == 0)? Pix(dosucc((const <T>*)p)) : q;
+}
+
+inline <T>& <T>XPlex:: operator () (Pix p)
+{
+  return *((<T>*)p);
+}
+
+inline const <T>& <T>XPlex:: operator () (Pix p) const
+{
+  return *((const <T>*)p);
+}
+
+inline void <T>XPlex::set_cache(const <T>IChunk* t) const
+{
+  ((<T>XPlex*)(this))->ch = (<T>IChunk*)t;
+}
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/defs.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/defs.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/defs.hP	(revision 18)
@@ -0,0 +1,57 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef _<T>defs_h
+#define _<T>defs_h 1
+
+
+// equality operator
+#ifndef <T>EQ
+#define <T>EQ(a, b)  ((a) == (b))
+#endif
+
+// less-than-or-equal
+#ifndef <T>LE
+#define <T>LE(a, b)  ((a) <= (b))
+#endif
+
+// comparison : less-than -> < 0; equal -> 0; greater-than -> > 0
+#ifndef <T>CMP
+#define <T>CMP(a, b) ( ((a) <= (b))? (((a) == (b))? 0 : -1) : 1 )
+#endif
+
+// hash function
+#ifndef <T>HASH
+extern unsigned int hash(<T&>);
+#define <T>HASH(x)  hash(x)
+#endif
+
+// initial capacity for structures requiring one
+
+#ifndef DEFAULT_INITIAL_CAPACITY
+#define DEFAULT_INITIAL_CAPACITY 100
+#endif
+
+// HASHTABLE_TOO_CROWDED(COUNT, SIZE) is true iff a hash table with COUNT
+// elements and SIZE slots is too full, and should be resized.
+// This is so if available space is less than 1/8.
+
+#define HASHTABLE_TOO_CROWDED(COUNT, SIZE) ((SIZE) - ((SIZE) >> 3) <= (COUNT))
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/gen/intSList.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/intSList.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/intSList.hP	(revision 18)
@@ -0,0 +1,33 @@
+/*  : Light weight List: This will simply reuse code from a int List, which 
+was genclassed from the SLList libg++ class. The classes generated from this file
+will all be derived classes from class VoidSLList or intSLList. Note that class SLList does not 
+offer all the functionality of List classes, such as sharing of sub-Lists.
+However, no additional code is needed at all and no .cc file is generated. So it costs nothing
+to use these type-safe Lists. Only member functions needing type casting are re-defined  */
+
+
+#ifndef _<T>SList_h
+#define _<T>SList_h 1
+
+#include "int.SLList.h"
+#include "<T>.defs.h"
+
+class <T>SList : public intSLList
+{
+public:
+  <T>SList() {}
+  <T>SList(<T>SList& a) : (a) {}
+  ~<T>SList() {}
+
+  <T>SList& operator = (<T>SList& a) {
+    return (<T>SList&) intSLList::operator= (a); }
+
+  <T>& operator () (Pix p) { return (<T>&) (intSLList::operator() (p)); }
+  <T>& front() { return (<T>&) intSLList::front(); }
+  <T>& rear()  { return (<T>&) intSLList::rear(); }
+  <T> remove_front() { return (<T>) intSLList::remove_front(); }
+
+};
+
+#endif /* conditional include */
+
Index: trunk/src/emx/include/Attic/cpp/gen/intVec.hP
===================================================================
--- trunk/src/emx/include/Attic/cpp/gen/intVec.hP	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/gen/intVec.hP	(revision 18)
@@ -0,0 +1,80 @@
+/*  : light weight Vector: This will simply reuse code from  */
+/* a int Vec, which was genclassed from the Vec libg++ class.     */
+/* The classes generated from this file will all be derived classes */
+/* from class VoidVec or intVec.  No .cc file is generated.  So     */
+/* it costs nothing to use these type-safe Vectors. Only member     */
+/* functions needing type casting are re-defined.                   */
+/*  */
+
+#ifndef _<T>Vec_h
+#define _<T>Vec_h 1
+
+#include "int.Vec.h"
+#include "<T>.defs.h"
+
+
+#ifndef _<T>_typedefs
+#define _<T>_typedefs 1
+typedef void (*<T>Procedure)(<T> );
+typedef <T>  (*<T>Mapper)(<T> );
+typedef <T>  (*<T>Combiner)(<T> , <T> );
+typedef int  (*<T>Predicate)(<T> );
+typedef int  (*<T>Comparator)(<T> , <T> );
+#endif
+
+class <T>Vec : public intVec
+{
+protected:
+  <T>Vec(int l, <T>* d) : (l, (int*) d) {};
+public:
+  <T>Vec() {};
+  <T>Vec(int l) : (l) {};
+  <T>Vec(int l, <T&> fill_value) : (l, fill_value) {};
+  <T>Vec(<T>Vec& v) : (v) {};
+  <T>Vec(intVec& v) {fake_copy(v, s, len);}
+  ~<T>Vec() {};
+
+  <T>Vec& operator = (<T>Vec& a)
+           {return (<T>Vec&) intVec::operator= (a);}
+  <T>Vec  at(int from, int n) {return (<T>Vec) intVec::at(from, n);}
+
+  <T>&    operator [] (int n) {return (<T>&)intVec::operator[] (n);}
+  <T>&    elem(int n) {return (<T>&)intVec::elem(n);}
+
+  friend <T>Vec   concat(<T>Vec& a, <T>Vec& b);
+  friend <T>Vec   map(<T>Mapper f, <T>Vec & a);
+  friend <T>Vec   merge(<T>Vec & a, <T>Vec & b, <T>Comparator f);
+  friend <T>Vec   combine(<T>Combiner f, <T>Vec & a, <T>Vec & b);
+  friend <T>Vec   reverse(<T>Vec& a);
+
+  void sort(<T>Comparator f);
+  void apply(<T>Procedure f);
+  <T> reduce(<T>Combiner f, <T> base);
+};
+
+inline <T>Vec concat(<T>Vec& a, <T>Vec& b)
+{return (<T>Vec)concat((intVec&)a, (intVec&)b);}
+
+inline <T>Vec   map(<T>Mapper f, <T>Vec & a) {
+  return (<T>Vec)map((intMapper)f, (intVec&)a); }
+
+inline <T>Vec   merge(<T>Vec & a, <T>Vec & b, <T>Comparator f) {
+  return (<T>Vec)merge((intVec&)a, (intVec&)b, (intComparator)f); }
+
+inline <T>Vec   combine(<T>Combiner f, <T>Vec & a, <T>Vec & b) {
+  return (<T>Vec)combine((intCombiner)f, (intVec&)a, (intVec&)b); }
+
+inline <T>Vec reverse(<T>Vec& a) {
+  return (<T>Vec)reverse((intVec&)a);}
+
+inline void <T>Vec::sort(<T>Comparator f) {
+  intVec::sort((intComparator) f); }
+
+inline void <T>Vec::apply(<T>Procedure f) {
+  intVec::apply((intProcedure) f); }
+
+inline <T> <T>Vec::reduce(<T>Combiner f, <T> base) {
+  return (<T>)intVec::reduce((intCombiner)f, base);}
+
+#endif /* conditional include */
+
Index: trunk/src/emx/include/Attic/cpp/generic.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/generic.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/generic.h	(revision 18)
@@ -0,0 +1,54 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef generic_h
+#define generic_h 1
+
+/*
+ *	See the CPP manual, argument prescan section for explanation
+ */
+
+#define name2(a,b) gEnErIc2(a,b)
+#define gEnErIc2(a,b) a ## b
+
+#define name3(a,b,c) gEnErIc3(a,b,c)
+#define gEnErIc3(a,b,c) a ## b ## c
+
+#define name4(a,b,c,d) gEnErIc4(a,b,c,d)
+#define gEnErIc4(a,b,c,d) a ## b ## c ## d
+
+#define GENERIC_STRING(a) gEnErIcStRiNg(a)
+#define gEnErIcStRiNg(a) #a
+
+#define declare(clas,t)        name2(clas,declare)(t)
+#define declare2(clas,t1,t2)   name2(clas,declare2)(t1,t2)
+
+#define implement(clas,t)      name2(clas,implement)(t)
+#define implement2(clas,t1,t2) name2(clas,implement2)(t1,t2)
+
+//extern genericerror(int,char*);
+typedef int (*GPT)(int,char*);
+
+#define set_handler(gen,type,x) name4(set_,type,gen,_handler)(x)
+
+#define errorhandler(gen,type)  name3(type,gen,handler)
+
+#define callerror(gen,type,a,b) (*errorhandler(gen,type))(a,b)
+
+
+#endif /* generic_h */
Index: trunk/src/emx/include/Attic/cpp/getpages.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/getpages.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/getpages.h	(revision 18)
@@ -0,0 +1,27 @@
+#if defined(BSD) || defined(DGUX)
+#ifndef BSD4_1
+#define HAVE_GETPAGESIZE
+#endif
+#endif
+ 
+#ifndef HAVE_GETPAGESIZE
+ 
+#include <sys/param.h>
+
+#ifdef EXEC_PAGESIZE
+#define getpagesize() EXEC_PAGESIZE
+#else
+#ifdef NBPG
+#define getpagesize() NBPG * CLSIZE
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* no CLSIZE */
+#else /* no NBPG */
+#ifdef NBPC
+#define getpagesize() NBPC
+#endif /* NBPC */
+#endif /* no NBPG */
+#endif /* no EXEC_PAGESIZE */
+
+#endif /* not HAVE_GETPAGESIZE */
+
Index: trunk/src/emx/include/Attic/cpp/hash_map
===================================================================
--- trunk/src/emx/include/Attic/cpp/hash_map	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/hash_map	(revision 18)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __SGI_STL_HASH_MAP
+#define __SGI_STL_HASH_MAP
+
+#ifndef __SGI_STL_INTERNAL_HASHTABLE_H
+#include <stl_htab.h>
+#endif 
+
+#include <stl_hmap.h>
+
+#endif /* __SGI_STL_HASH_MAP */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/hash_map.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/hash_map.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/hash_map.h	(revision 18)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __SGI_STL_HASH_MAP_H
+#define __SGI_STL_HASH_MAP_H
+
+#ifndef __SGI_STL_INTERNAL_HASHTABLE_H
+#include <stl_htab.h>
+#endif 
+
+#include <stl_hmap.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::hash;
+using __STD::hashtable;
+using __STD::hash_map;
+using __STD::hash_multimap;
+#endif /* __STL_USE_NAMESPACES */
+
+
+#endif /* __SGI_STL_HASH_MAP_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/hash_set
===================================================================
--- trunk/src/emx/include/Attic/cpp/hash_set	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/hash_set	(revision 18)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __SGI_STL_HASH_SET
+#define __SGI_STL_HASH_SET
+
+#ifndef __SGI_STL_INTERNAL_HASHTABLE_H
+#include <stl_htab.h>
+#endif 
+
+#include <stl_hset.h>
+
+#endif /* __SGI_STL_HASH_SET */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/hash_set.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/hash_set.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/hash_set.h	(revision 18)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __SGI_STL_HASH_SET_H
+#define __SGI_STL_HASH_SET_H
+
+#ifndef __SGI_STL_INTERNAL_HASHTABLE_H
+#include <stl_htab.h>
+#endif 
+
+#include <stl_hset.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::hash;
+using __STD::hashtable;
+using __STD::hash_set;
+using __STD::hash_multiset;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_HASH_SET_H */
Index: trunk/src/emx/include/Attic/cpp/hashtabl.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/hashtabl.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/hashtabl.h	(revision 18)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_HASHTABLE_H
+#define __SGI_STL_HASHTABLE_H
+
+#include <stl_htab.h>
+#include <algo.h>
+#include <alloc.h>
+#include <vector.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::hash;
+using __STD::hashtable;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_HASHTABLE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/heap.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/heap.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/heap.h	(revision 18)
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_HEAP_H
+#define __SGI_STL_HEAP_H
+
+#include <stl_conf.h>
+#include <stl_heap.h>
+
+#ifdef __STL_USE_NAMESPACES
+
+using __STD::push_heap;
+using __STD::pop_heap;
+using __STD::make_heap;
+using __STD::sort_heap;
+
+#endif /* __STL_USE_NAMESPACES */
+
+
+#endif /* __SGI_STL_HEAP_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/indstrea.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/indstrea.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/indstrea.h	(revision 18)
@@ -0,0 +1,77 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License.
+
+Written by Per Bothner (bothner@cygnus.com). */
+
+#ifndef _INDSTREAM_H
+#define _INDSTREAM_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <iostream.h>
+
+extern "C++" {
+// An indirectbuf is one that forwards all of its I/O requests
+// to another streambuf.
+// All get-related requests are sent to get_stream().
+// All put-related requests are sent to put_stream().
+
+// An indirectbuf can be used to implement Common Lisp
+// synonym-streams and two-way-streams.
+//
+// class synonymbuf : public indirectbuf {
+//    Symbol *sym;
+//    synonymbuf(Symbol *s) { sym = s; }
+//    virtual streambuf *lookup_stream(int mode) {
+//        return coerce_to_streambuf(lookup_value(sym)); }
+// };
+
+class indirectbuf : public streambuf {
+  protected:
+    streambuf *_get_stream;  // Optional cache for get_stream().
+    streambuf *_put_stream;  // Optional cache for put_stream().
+    int _delete_flags;
+  public:
+    streambuf *get_stream()
+	{ return _get_stream ? _get_stream : lookup_stream(ios::in); }
+    streambuf *put_stream()
+	{ return _put_stream ? _put_stream : lookup_stream(ios::out); }
+    virtual streambuf *lookup_stream(int/*mode*/) { return NULL; } // ERROR!
+    indirectbuf(streambuf *get=NULL, streambuf *put=NULL, int delete_mode=0);
+    virtual ~indirectbuf();
+    virtual streamsize xsputn(const char* s, streamsize n);
+    virtual streamsize xsgetn(char* s, streamsize n);
+    virtual int underflow();
+    virtual int uflow();
+    virtual int overflow(int c = EOF);
+    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
+    virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out);
+    virtual int sync();
+    virtual int pbackfail(int c);
+};
+} // extern "C++"
+
+#endif /* !_INDSTREAM_H */
Index: trunk/src/emx/include/Attic/cpp/iolibio.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/iolibio.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iolibio.h	(revision 18)
@@ -0,0 +1,63 @@
+#include "libio.h"
+
+/* These emulate stdio functionality, but with a different name
+   (_IO_ungetc instead of ungetc), and using _IO_FILE instead of FILE. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int _IO_fclose __P((_IO_FILE*));
+extern _IO_FILE *_IO_fdopen __P((int, const char*));
+extern int _IO_fflush __P((_IO_FILE*));
+extern int _IO_fgetpos __P((_IO_FILE*, _IO_fpos_t*));
+extern char* _IO_fgets __P((char*, int, _IO_FILE*));
+extern _IO_FILE *_IO_fopen __P((const char*, const char*));
+extern int _IO_fprintf __P((_IO_FILE*, const char*, ...));
+extern int _IO_fputs __P((const char*, _IO_FILE*));
+extern int _IO_fsetpos __P((_IO_FILE*, const _IO_fpos_t *));
+extern long int _IO_ftell __P((_IO_FILE*));
+extern _IO_size_t _IO_fread __P((void*, _IO_size_t, _IO_size_t, _IO_FILE*));
+extern _IO_size_t _IO_fwrite __P((const void*,
+				      _IO_size_t, _IO_size_t, _IO_FILE*));
+extern char* _IO_gets __P((char*));
+extern void _IO_perror __P((const char*));
+extern int _IO_printf __P((const char*, ...));
+extern int _IO_puts __P((const char*));
+extern int _IO_scanf __P((const char*, ...));
+extern void _IO_setbuffer __P((_IO_FILE *, char*, _IO_size_t));
+extern int _IO_setvbuf __P((_IO_FILE*, char*, int, _IO_size_t));
+extern int _IO_sscanf __P((const char*, const char*, ...));
+extern int _IO_sprintf __P((char *, const char*, ...));
+extern int _IO_ungetc __P((int, _IO_FILE*));
+extern int _IO_vsscanf __P((const char *, const char *, _IO_va_list));
+extern int _IO_vsprintf __P((char*, const char*, _IO_va_list));
+
+struct obstack;
+extern int _IO_obstack_vprintf __P ((struct obstack *, const char *,
+                                    _IO_va_list));
+extern int _IO_obstack_printf __P ((struct obstack *, const char *, ...));
+#ifndef _IO_pos_BAD
+#define _IO_pos_BAD ((_IO_fpos_t)(-1))
+#endif
+#define _IO_clearerr(FP) ((FP)->_flags &= ~(_IO_ERR_SEEN|_IO_EOF_SEEN))
+#define _IO_fseek(__fp, __offset, __whence) \
+  (_IO_seekoff(__fp, __offset, __whence, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD ? EOF : 0)
+#define _IO_rewind(FILE) (void)_IO_seekoff(FILE, 0, 0, _IOS_INPUT|_IOS_OUTPUT)
+#define _IO_vprintf(FORMAT, ARGS) _IO_vfprintf(_IO_stdout, FORMAT, ARGS)
+#if _G_IO_IO_FILE_VERSION == 0x20001
+#define _IO_freopen(FILENAME, MODE, FP) \
+  (_IO_file_close_it(FP), _IO_file_fopen(FP, FILENAME, MODE, 0))
+#else
+#define _IO_freopen(FILENAME, MODE, FP) \
+  (_IO_file_close_it(FP), _IO_file_fopen(FP, FILENAME, MODE))
+#endif
+#define _IO_fileno(FP) ((FP)->_fileno)
+extern _IO_FILE* _IO_popen __P((const char*, const char*));
+#define _IO_pclose _IO_fclose
+#define _IO_setbuf(_FP, _BUF) _IO_setbuffer(_FP, _BUF, _IO_BUFSIZ)
+#define _IO_setlinebuf(_FP) _IO_setvbuf(_FP, NULL, 1, 0)
+
+#ifdef __cplusplus
+}
+#endif
Index: trunk/src/emx/include/Attic/cpp/iomanip
===================================================================
--- trunk/src/emx/include/Attic/cpp/iomanip	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iomanip	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __IOMANIP__
+#define __IOMANIP__
+#include <iomanip.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/iomanip.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/iomanip.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iomanip.h	(revision 18)
@@ -0,0 +1,176 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#ifndef _IOMANIP_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _IOMANIP_H
+
+#include <iostream.h>
+
+extern "C++" {
+//-----------------------------------------------------------------------------
+//	Parametrized Manipulators as specified by ANSI draft
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+//	Stream Manipulators
+//-----------------------------------------------------------------------------
+//
+template<class TP> class smanip; // TP = Type Param
+
+template<class TP> class sapp {
+    ios& (*_f)(ios&, TP);
+public: 
+    sapp(ios& (*f)(ios&, TP)) : _f(f) {}
+    //
+    smanip<TP> operator()(TP a) 
+      { return smanip<TP>(_f, a); }
+};
+
+template<class TP>
+inline istream& operator>>(istream& i, const smanip<TP>& m);
+template<class TP>
+inline ostream& operator<<(ostream& o, const smanip<TP>& m);
+
+template <class TP> class smanip {
+    ios& (*_f)(ios&, TP);
+    TP _a;
+public:
+    smanip(ios& (*f)(ios&, TP), TP a) : _f(f), _a(a) {}
+    //
+    friend 
+      istream& operator>> <>(istream& i, const smanip<TP>& m);
+    friend
+      ostream& operator<< <>(ostream& o, const smanip<TP>& m);
+};
+
+#ifdef __GNUG__
+extern template class smanip<int>;
+extern template class smanip<ios::fmtflags>;
+#endif
+
+template<class TP>
+inline istream& operator>>(istream& i, const smanip<TP>& m)
+{ (*m._f)(i, m._a); return i; }
+
+template<class TP>
+inline ostream& operator<<(ostream& o, const smanip<TP>& m)
+{ (*m._f)(o, m._a); return o;}
+
+#ifdef __GNUG__
+extern template istream& operator>>(istream&, const smanip<int>&);
+extern template istream& operator>>(istream&, const smanip<ios::fmtflags>&);
+extern template ostream& operator<<(ostream&, const smanip<int>&);
+extern template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&);
+#endif
+
+//-----------------------------------------------------------------------------
+//	Input-Stream Manipulators
+//-----------------------------------------------------------------------------
+//
+template<class TP> class imanip; 
+
+template<class TP> class iapp {
+    istream& (*_f)(istream&, TP);
+public: 
+    iapp(istream& (*f)(istream&,TP)) : _f(f) {}
+    //
+    imanip<TP> operator()(TP a)
+       { return imanip<TP>(_f, a); }
+};
+
+template <class TP>
+inline istream& operator>>(istream&, const imanip<TP>&);
+
+template <class TP> class imanip {
+    istream& (*_f)(istream&, TP);
+    TP _a;
+public:
+    imanip(istream& (*f)(istream&, TP), TP a) : _f(f), _a(a) {}
+    //
+    friend
+      istream& operator>> <>(istream& i, const imanip<TP>& m);
+};
+
+template <class TP>
+inline istream& operator>>(istream& i, const imanip<TP>& m)
+{ return (*m._f)( i, m._a); }
+
+//-----------------------------------------------------------------------------
+//	Output-Stream Manipulators
+//-----------------------------------------------------------------------------
+//
+template<class TP> class omanip; 
+
+template<class TP> class oapp {
+    ostream& (*_f)(ostream&, TP);
+public: 
+    oapp(ostream& (*f)(ostream&,TP)) : _f(f) {}
+    //
+    omanip<TP> operator()(TP a)
+      { return omanip<TP>(_f, a); }
+};
+
+template <class TP>
+inline ostream& operator<<(ostream&, const omanip<TP>&);
+
+template <class TP> class omanip {
+    ostream& (*_f)(ostream&, TP);
+    TP _a;
+public:
+    omanip(ostream& (*f)(ostream&, TP), TP a) : _f(f), _a(a) {}
+    //
+    friend
+      ostream& operator<< <>(ostream& o, const omanip<TP>& m);
+};
+
+template <class TP>
+inline ostream& operator<<(ostream& o, const omanip<TP>& m)
+{ return (*m._f)(o, m._a); }
+
+//-----------------------------------------------------------------------------
+//	Available Manipulators
+//-----------------------------------------------------------------------------
+
+//
+// Macro to define an iomanip function, with one argument
+// The underlying function is `__iomanip_<name>' 
+//
+#define __DEFINE_IOMANIP_FN1(type,param,function)         \
+	extern ios& __iomanip_##function (ios&, param); \
+	inline type<param> function (param n)           \
+		        { return type<param> (__iomanip_##function, n); }
+
+__DEFINE_IOMANIP_FN1( smanip, int, setbase)
+__DEFINE_IOMANIP_FN1( smanip, int, setfill)
+__DEFINE_IOMANIP_FN1( smanip, int, setprecision)
+__DEFINE_IOMANIP_FN1( smanip, int, setw)
+
+__DEFINE_IOMANIP_FN1( smanip, ios::fmtflags, resetiosflags)
+__DEFINE_IOMANIP_FN1( smanip, ios::fmtflags, setiosflags)
+} // extern "C++"
+
+#endif /*!_IOMANIP_H*/
Index: trunk/src/emx/include/Attic/cpp/iosfwd
===================================================================
--- trunk/src/emx/include/Attic/cpp/iosfwd	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iosfwd	(revision 18)
@@ -0,0 +1,15 @@
+// -*- C++ -*- I/O forward declaration header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __IOSFWD__
+#define __IOSFWD__
+class ios;
+class streambuf;
+class istream;
+class ostream;
+class iostream;
+class filebuf;
+class ifstream;
+class ofstream;
+class fstream;
+#endif
Index: trunk/src/emx/include/Attic/cpp/iostdio.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/iostdio.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iostdio.h	(revision 18)
@@ -0,0 +1,114 @@
+/* 
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/* This file defines a stdio-like environment, except that it avoid
+   link-time name clashes with an existing stdio.
+   It allows for testing the libio using stdio-using programs
+   with an incompatible libc.a.
+   It is not predantically correct - e.g. some macros are used
+   that may evaluate a stream argument more than once.  */
+
+#ifndef _IOSTDIO_H
+#define _IOSTDIO_H
+
+#include "iolibio.h"
+
+typedef _IO_FILE FILE;
+#ifndef EOF
+#define EOF (-1)
+#endif
+#ifndef BUFSIZ
+#define BUFSIZ 1024
+#endif
+
+/* #define size_t, fpos_t L_tmpname TMP_MAX */
+
+#define _IOFBF 0 /* Fully buffered. */
+#define _IOLBF 1 /* Line buffered. */
+#define _IONBF 2 /* No buffering. */
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#define stdin _IO_stdin
+#define stdout _IO_stdout
+#define stderr _IO_stderr
+
+#define getc(_fp) _IO_getc(_fp)
+#define putc(_ch, _fp) _IO_putc(_ch, _fp)
+
+#define clearerr _IO_clearerr
+#define fclose _IO_fclose
+#define feof _IO_feof
+#define ferror _IO_ferror
+#define fflush _IO_fflush
+#define fgetc(__fp) _IO_getc(_fp)
+#define fgetpos _IO_fgetpos
+#define fgets _IO_fgets
+#define fopen _IO_fopen
+#define fprintf _IO_fprintf
+#define fputc(_ch, _fp) _IO_putc(_ch, _fp)
+#define fputs _IO_fputs
+#define fread _IO_fread
+#define freopen _IO_freopen
+#define fscanf _IO_fscanf
+#define fseek _IO_fseek
+#define fsetpos _IO_fsetpos
+#define ftell _IO_ftell
+#define fwrite _IO_fwrite
+#define gets _IO_gets
+#define perror _IO_perror
+#define printf _IO_printf
+#define puts _IO_puts
+#define rewind _IO_rewind
+#define scanf _IO_scanf
+#define setbuf _IO_setbuf
+#define setbuffer _IO_setbuffer
+#define setvbuf _IO_setvbuf
+#define sprintf _IO_sprintf
+#define sscanf _IO_sscanf
+#define ungetc _IO_ungetc
+#define vfprintf _IO_vfprintf
+#define vprintf(__fmt, __args) vfprintf(stdout, __fmt, __args)
+#define vsprintf _IO_vsprintf
+
+#if 0
+/* We can use the libc versions of these, since they don't pass FILE*s. */
+#define remove ??? __P((const char*))
+#define rename ??? __P((const char* _old, const char* _new))
+#define tmpfile ??? __P((void))
+#define tmpnam ??? __P((char*))
+#endif
+
+#if !defined(__STRICT_ANSI__) || defined(_POSIX_SOURCE)
+#define fdopen _IO_fdopen
+#define fileno _IO_fileno
+#define popen _IO_popen
+#define pclose _IO_pclose
+#define setbuf _IO_setbuf
+#define setlinebuf _IO_setlinebuf
+#endif
+
+#endif /* _IOSTDIO_H */
Index: trunk/src/emx/include/Attic/cpp/iostream
===================================================================
--- trunk/src/emx/include/Attic/cpp/iostream	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iostream	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __IOSTREAM__
+#define __IOSTREAM__
+#include <iostream.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/iostream.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/iostream.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iostream.h	(revision 18)
@@ -0,0 +1,272 @@
+/*  This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#ifndef _IOSTREAM_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+#define _IOSTREAM_H
+
+#include <streambu.h>
+
+extern "C++" {
+class istream; class ostream;
+typedef ios& (*__manip)(ios&);
+typedef istream& (*__imanip)(istream&);
+typedef ostream& (*__omanip)(ostream&);
+
+extern istream& ws(istream& ins);
+extern ostream& flush(ostream& outs);
+extern ostream& endl(ostream& outs);
+extern ostream& ends(ostream& outs);
+
+class ostream : virtual public ios
+{
+    // NOTE: If fields are changed, you must fix _fake_ostream in stdstreams.C!
+    void do_osfx();
+  public:
+    ostream() { }
+    ostream(streambuf* sb, ostream* tied=NULL);
+    int opfx() {
+	if (!good()) return 0;
+	else { if (_tie) _tie->flush(); _IO_flockfile(_strbuf); return 1;} }
+    void osfx() { _IO_funlockfile(_strbuf);
+		  if (flags() & (ios::unitbuf|ios::stdio))
+		      do_osfx(); }
+    ostream& flush();
+    ostream& put(char c) { _strbuf->sputc(c); return *this; }
+#ifdef _STREAM_COMPAT
+    /* Temporary binary compatibility.  REMOVE IN NEXT RELEASE. */
+    ostream& put(unsigned char c) { return put((char)c); }
+    ostream& put(signed char c) { return put((char)c); }
+#endif
+    ostream& write(const char *s, streamsize n);
+    ostream& write(const unsigned char *s, streamsize n)
+      { return write((const char*)s, n);}
+    ostream& write(const signed char *s, streamsize n)
+      { return write((const char*)s, n);}
+    ostream& write(const void *s, streamsize n)
+      { return write((const char*)s, n);}
+    ostream& seekp(streampos);
+    ostream& seekp(streamoff, _seek_dir);
+    streampos tellp();
+    ostream& form(const char *format ...);
+    ostream& vform(const char *format, _IO_va_list args);
+
+    ostream& operator<<(char c);
+    ostream& operator<<(unsigned char c) { return (*this) << (char)c; }
+    ostream& operator<<(signed char c) { return (*this) << (char)c; }
+    ostream& operator<<(const char *s);
+    ostream& operator<<(const unsigned char *s)
+	{ return (*this) << (const char*)s; }
+    ostream& operator<<(const signed char *s)
+	{ return (*this) << (const char*)s; }
+    ostream& operator<<(const void *p);
+    ostream& operator<<(int n);
+    ostream& operator<<(unsigned int n);
+    ostream& operator<<(long n);
+    ostream& operator<<(unsigned long n);
+#if defined(__GNUC__)
+    __extension__ ostream& operator<<(long long n);
+    __extension__ ostream& operator<<(unsigned long long n);
+#endif
+    ostream& operator<<(short n) {return operator<<((int)n);}
+    ostream& operator<<(unsigned short n) {return operator<<((unsigned int)n);}
+#if _G_HAVE_BOOL
+    ostream& operator<<(bool b) { return operator<<((int)b); }
+#endif
+    ostream& operator<<(double n);
+    ostream& operator<<(float n) { return operator<<((double)n); }
+#if _G_HAVE_LONG_DOUBLE_IO
+    ostream& operator<<(long double n);
+#else
+    ostream& operator<<(long double n) { return operator<<((double)n); }
+#endif
+    ostream& operator<<(__omanip func) { return (*func)(*this); }
+    ostream& operator<<(__manip func) {(*func)(*this); return *this;}
+    ostream& operator<<(streambuf*);
+#ifdef _STREAM_COMPAT
+    streambuf* ostreambuf() const { return _strbuf; }
+#endif
+};
+
+class istream : virtual public ios
+{
+    // NOTE: If fields are changed, you must fix _fake_istream in stdstreams.C!
+protected:
+    _IO_size_t _gcount;
+
+    int _skip_ws();
+  public:
+    istream(): _gcount (0) { }
+    istream(streambuf* sb, ostream*tied=NULL);
+    istream& get(char* ptr, int len, char delim = '\n');
+    istream& get(unsigned char* ptr, int len, char delim = '\n')
+	{ return get((char*)ptr, len, delim); }
+    istream& get(char& c);
+    istream& get(unsigned char& c) { return get((char&)c); }
+    istream& getline(char* ptr, int len, char delim = '\n');
+    istream& getline(unsigned char* ptr, int len, char delim = '\n')
+	{ return getline((char*)ptr, len, delim); }
+    istream& get(signed char& c)  { return get((char&)c); }
+    istream& get(signed char* ptr, int len, char delim = '\n')
+	{ return get((char*)ptr, len, delim); }
+    istream& getline(signed char* ptr, int len, char delim = '\n')
+	{ return getline((char*)ptr, len, delim); }
+    istream& read(char *ptr, streamsize n);
+    istream& read(unsigned char *ptr, streamsize n)
+      { return read((char*)ptr, n); }
+    istream& read(signed char *ptr, streamsize n)
+      { return read((char*)ptr, n); }
+    istream& read(void *ptr, streamsize n)
+      { return read((char*)ptr, n); }
+    istream& get(streambuf& sb, char delim = '\n');
+    istream& gets(char **s, char delim = '\n');
+    int ipfx(int need = 0) {
+	if (!good()) { set(ios::failbit); return 0; }
+	else {
+	  _IO_flockfile(_strbuf);
+	  if (_tie && (need == 0 || rdbuf()->in_avail() < need)) _tie->flush();
+	  if (!need && (flags() & ios::skipws)) return _skip_ws();
+	  else return 1;
+	}
+    }
+    int ipfx0() { // Optimized version of ipfx(0).
+	if (!good()) { set(ios::failbit); return 0; }
+	else {
+	  _IO_flockfile(_strbuf);
+	  if (_tie) _tie->flush();
+	  if (flags() & ios::skipws) return _skip_ws();
+	  else return 1;
+	}
+    }
+    int ipfx1() { // Optimized version of ipfx(1).
+	if (!good()) { set(ios::failbit); return 0; }
+	else {
+	  _IO_flockfile(_strbuf);
+	  if (_tie && rdbuf()->in_avail() == 0) _tie->flush();
+	  return 1;
+	}
+    }
+    void isfx() { _IO_funlockfile(_strbuf); }
+    int get() { if (!ipfx1()) return EOF;
+		else { int ch = _strbuf->sbumpc();
+		       if (ch == EOF) set(ios::eofbit);
+		       return ch;
+		     } }
+    int peek();
+    _IO_size_t gcount() { return _gcount; }
+    istream& ignore(int n=1, int delim = EOF);
+    int sync ();
+    istream& seekg(streampos);
+    istream& seekg(streamoff, _seek_dir);
+    streampos tellg();
+    istream& putback(char ch) {
+	if (good() && _strbuf->sputbackc(ch) == EOF) clear(ios::badbit);
+	return *this;}
+    istream& unget() {
+	if (good() && _strbuf->sungetc() == EOF) clear(ios::badbit);
+	return *this;}
+    istream& scan(const char *format ...);
+    istream& vscan(const char *format, _IO_va_list args);
+#ifdef _STREAM_COMPAT
+    istream& unget(char ch) { return putback(ch); }
+    int skip(int i);
+    streambuf* istreambuf() const { return _strbuf; }
+#endif
+
+    istream& operator>>(char*);
+    istream& operator>>(unsigned char* p) { return operator>>((char*)p); }
+    istream& operator>>(signed char*p) { return operator>>((char*)p); }
+    istream& operator>>(char& c);
+    istream& operator>>(unsigned char& c) {return operator>>((char&)c);}
+    istream& operator>>(signed char& c) {return operator>>((char&)c);}
+    istream& operator>>(int&);
+    istream& operator>>(long&);
+#if defined(__GNUC__)
+    __extension__ istream& operator>>(long long&);
+    __extension__ istream& operator>>(unsigned long long&);
+#endif
+    istream& operator>>(short&);
+    istream& operator>>(unsigned int&);
+    istream& operator>>(unsigned long&);
+    istream& operator>>(unsigned short&);
+#if _G_HAVE_BOOL
+    istream& operator>>(bool&);
+#endif
+    istream& operator>>(float&);
+    istream& operator>>(double&);
+    istream& operator>>(long double&);
+    istream& operator>>( __manip func) {(*func)(*this); return *this;}
+    istream& operator>>(__imanip func) { return (*func)(*this); }
+    istream& operator>>(streambuf*);
+};
+
+class iostream : public istream, public ostream
+{
+  public:
+    iostream() { }
+    iostream(streambuf* sb, ostream*tied=NULL);
+};
+
+class _IO_istream_withassign : public istream {
+public:
+  _IO_istream_withassign& operator=(istream&);
+  _IO_istream_withassign& operator=(_IO_istream_withassign& rhs)
+    { return operator= (static_cast<istream&> (rhs)); }
+};
+
+class _IO_ostream_withassign : public ostream {
+public:
+  _IO_ostream_withassign& operator=(ostream&);
+  _IO_ostream_withassign& operator=(_IO_ostream_withassign& rhs)
+    { return operator= (static_cast<ostream&> (rhs)); }
+};
+
+extern _IO_istream_withassign cin;
+// clog->rdbuf() == cerr->rdbuf()
+extern _IO_ostream_withassign cout, cerr;
+
+extern _IO_ostream_withassign clog
+#if _G_CLOG_CONFLICT
+__asm__ ("__IO_clog")
+#endif
+;
+
+extern istream& lock(istream& ins);
+extern istream& unlock(istream& ins);
+extern ostream& lock(ostream& outs);
+extern ostream& unlock(ostream& outs);
+
+struct Iostream_init { } ;  // Compatibility hack for AT&T library.
+
+inline ios& dec(ios& i)
+{ i.setf(ios::dec, ios::dec|ios::hex|ios::oct); return i; }
+inline ios& hex(ios& i)
+{ i.setf(ios::hex, ios::dec|ios::hex|ios::oct); return i; }
+inline ios& oct(ios& i)
+{ i.setf(ios::oct, ios::dec|ios::hex|ios::oct); return i; }
+} // extern "C++"
+
+#endif /*!_IOSTREAM_H*/
Index: trunk/src/emx/include/Attic/cpp/istream.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/istream.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/istream.h	(revision 18)
@@ -0,0 +1,25 @@
+/* 
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include <stream.h>
Index: trunk/src/emx/include/Attic/cpp/iterator
===================================================================
--- trunk/src/emx/include/Attic/cpp/iterator	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iterator	(revision 18)
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_ITERATOR
+#define __SGI_STL_ITERATOR
+
+#include <stl_conf.h>
+#include <stl_relo.h>
+#include <stddef.h>
+#include <iostream.h>
+#include <stl_iter.h>
+
+#endif /* __SGI_STL_ITERATOR */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/iterator.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/iterator.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/iterator.h	(revision 18)
@@ -0,0 +1,104 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_ITERATOR_H
+#define __SGI_STL_ITERATOR_H
+
+#ifndef __SGI_STL_FUNCTION_H
+#include <function.h>
+#endif
+#include <stddef.h>
+#include <iostream.h>
+#ifndef __SGI_STL_INTERNAL_ITERATOR_H
+#include <stl_iter.h>
+#endif
+#ifndef __TYPE_TRAITS_H
+#include <type_tra.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_CONSTRUCT_H
+#include <stl_cons.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_RAW_STORAGE_ITERATOR_H
+#include <stl_raw_.h>
+#endif
+
+#ifdef __STL_USE_NAMESPACES
+
+// Names from stl_iterator.h
+
+using __STD::input_iterator_tag;
+using __STD::output_iterator_tag;
+using __STD::forward_iterator_tag;
+using __STD::bidirectional_iterator_tag;
+using __STD::random_access_iterator_tag;
+
+#if 0
+using __STD::iterator;
+#endif
+using __STD::input_iterator;
+using __STD::output_iterator;
+using __STD::forward_iterator;
+using __STD::bidirectional_iterator;
+using __STD::random_access_iterator;
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+using __STD::iterator_traits;
+#endif
+
+using __STD::iterator_category;
+using __STD::distance_type;
+using __STD::value_type;
+
+using __STD::distance; 
+using __STD::advance; 
+
+using __STD::insert_iterator;
+using __STD::front_insert_iterator;
+using __STD::back_insert_iterator;
+using __STD::inserter;
+using __STD::front_inserter;
+using __STD::back_inserter;
+
+using __STD::reverse_iterator;
+using __STD::reverse_bidirectional_iterator;
+
+using __STD::istream_iterator;
+using __STD::ostream_iterator;
+
+// Names from stl_construct.h
+using __STD::construct;
+using __STD::destroy;
+
+// Names from stl_raw_storage_iter.h
+using __STD::raw_storage_iterator;
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_ITERATOR_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/libc.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/libc.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/libc.h	(revision 18)
@@ -0,0 +1,1 @@
+#include <stdlib.h>
Index: trunk/src/emx/include/Attic/cpp/libio.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/libio.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/libio.h	(revision 18)
@@ -0,0 +1,356 @@
+/* Copyright (C) 1991, 92, 93, 94, 95, 97, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+   Written by Per Bothner <bothner@cygnus.com>.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#ifndef _IO_STDIO_H
+#define _IO_STDIO_H
+
+#include <_G_confi.h>
+#define _IO_pos_t _G_fpos_t /* obsolete */
+#define _IO_fpos_t _G_fpos_t
+#define _IO_size_t _G_size_t
+#define _IO_ssize_t _G_ssize_t
+#define _IO_off_t _G_off_t
+#define _IO_pid_t _G_pid_t
+#define _IO_uid_t _G_uid_t
+#define _IO_HAVE_SYS_WAIT _G_HAVE_SYS_WAIT
+#define _IO_HAVE_ST_BLKSIZE _G_HAVE_ST_BLKSIZE
+#define _IO_BUFSIZ _G_BUFSIZ
+#define _IO_va_list _G_va_list
+#if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001
+#define _IO_fpos64_t _G_fpos64_t
+#define _IO_off64_t _G_off64_t
+#endif
+
+#ifdef _G_NEED_STDARG_H
+/* This define avoids name pollution if we're using GNU stdarg.h */
+# define __need___va_list
+# include <stdarg.h>
+# ifdef __GNUC_VA_LIST
+#  undef _IO_va_list
+#  define _IO_va_list __gnuc_va_list
+# endif /* __GNUC_VA_LIST */
+#endif
+
+#ifndef __P
+# if _G_HAVE_SYS_CDEFS
+#  include <sys/cdefs.h>
+# else
+#  ifdef __STDC__
+#   define __P(protos) protos
+#  else
+#   define __P(protos) ()
+#  endif
+# endif
+#endif /*!__P*/
+
+/* For backward compatibility */
+#ifndef _PARAMS
+# define _PARAMS(protos) __P(protos)
+#endif /*!_PARAMS*/
+
+#ifndef __STDC__
+# define const
+#endif
+#define _IO_UNIFIED_JUMPTABLES 1
+#if !_G_HAVE_PRINTF_FP
+# define _IO_USE_DTOA 1
+#endif
+
+#ifndef EOF
+# define EOF (-1)
+#endif
+#ifndef NULL
+# if defined __GNUG__ && \
+    (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
+#  define NULL (__null)
+# else
+#  if !defined(__cplusplus)
+#   define NULL ((void*)0)
+#  else
+#   define NULL (0)
+#  endif
+# endif
+#endif
+
+#define _IOS_INPUT	1
+#define _IOS_OUTPUT	2
+#define _IOS_ATEND	4
+#define _IOS_APPEND	8
+#define _IOS_TRUNC	16
+#define _IOS_NOCREATE	32
+#define _IOS_NOREPLACE	64
+#define _IOS_BIN	128
+
+/* Magic numbers and bits for the _flags field.
+   The magic numbers use the high-order bits of _flags;
+   the remaining bits are available for variable flags.
+   Note: The magic numbers must all be negative if stdio
+   emulation is desired. */
+
+#define _IO_MAGIC 0xFBAD0000 /* Magic number */
+#define _OLD_STDIO_MAGIC 0xFABC0000 /* Emulate old stdio. */
+#define _IO_MAGIC_MASK 0xFFFF0000
+#define _IO_USER_BUF 1 /* User owns buffer; don't delete it on close. */
+#define _IO_UNBUFFERED 2
+#define _IO_NO_READS 4 /* Reading not allowed */
+#define _IO_NO_WRITES 8 /* Writing not allowd */
+#define _IO_EOF_SEEN 0x10
+#define _IO_ERR_SEEN 0x20
+#define _IO_DELETE_DONT_CLOSE 0x40 /* Don't call close(_fileno) on cleanup. */
+#define _IO_LINKED 0x80 /* Set if linked (using _chain) to streambuf::_list_all.*/
+#define _IO_IN_BACKUP 0x100
+#define _IO_LINE_BUF 0x200
+#define _IO_TIED_PUT_GET 0x400 /* Set if put and get pointer logicly tied. */
+#define _IO_CURRENTLY_PUTTING 0x800
+#define _IO_IS_APPENDING 0x1000
+#define _IO_IS_FILEBUF 0x2000
+#define _IO_BAD_SEEN 0x4000
+
+/* These are "formatting flags" matching the iostream fmtflags enum values. */
+#define _IO_SKIPWS 01
+#define _IO_LEFT 02
+#define _IO_RIGHT 04
+#define _IO_INTERNAL 010
+#define _IO_DEC 020
+#define _IO_OCT 040
+#define _IO_HEX 0100
+#define _IO_SHOWBASE 0200
+#define _IO_SHOWPOINT 0400
+#define _IO_UPPERCASE 01000
+#define _IO_SHOWPOS 02000
+#define _IO_SCIENTIFIC 04000
+#define _IO_FIXED 010000
+#define _IO_UNITBUF 020000
+#define _IO_STDIO 040000
+#define _IO_DONT_CLOSE 0100000
+#define _IO_BOOLALPHA 0200000
+
+
+struct _IO_jump_t;  struct _IO_FILE;
+
+/* Handle lock.  */
+#ifdef _IO_MTSAFE_IO
+# if defined __GLIBC__ && __GLIBC__ >= 2
+#  if __GLIBC_MINOR__ > 0
+#   include <bits/stdio-lock.h>
+#  else
+#   include <stdio-lock.h>
+#  endif
+#  define _IO_LOCK_T _IO_lock_t *
+# else
+/*# include <comthread.h>*/
+# endif
+#else
+# if defined(__GLIBC__) && __GLIBC__ >= 2
+   typedef void _IO_lock_t;
+#  define _IO_LOCK_T void *
+# else
+#  ifdef __linux__
+    struct _IO_lock_t { void *ptr; short int field1; short int field2; };
+#   define _IO_LOCK_T struct _IO_lock_t
+#  else
+    typedef void _IO_lock_t;
+#  endif
+# endif
+#endif
+
+
+/* A streammarker remembers a position in a buffer. */
+
+struct _IO_marker {
+  struct _IO_marker *_next;
+  struct _IO_FILE *_sbuf;
+  /* If _pos >= 0
+ it points to _buf->Gbase()+_pos. FIXME comment */
+  /* if _pos < 0, it points to _buf->eBptr()+_pos. FIXME comment */
+  int _pos;
+#if 0
+    void set_streampos(streampos sp) { _spos = sp; }
+    void set_offset(int offset) { _pos = offset; _spos = (streampos)(-2); }
+  public:
+    streammarker(streambuf *sb);
+    ~streammarker();
+    int saving() { return  _spos == -2; }
+    int delta(streammarker&);
+    int delta();
+#endif
+};
+
+struct _IO_FILE {
+  int _flags;		/* High-order word is _IO_MAGIC; rest is flags. */
+#define _IO_file_flags _flags
+
+  /* The following pointers correspond to the C++ streambuf protocol. */
+  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
+  char* _IO_read_ptr;	/* Current read pointer */
+  char* _IO_read_end;	/* End of get area. */
+  char* _IO_read_base;	/* Start of putback+get area. */
+  char* _IO_write_base;	/* Start of put area. */
+  char* _IO_write_ptr;	/* Current put pointer. */
+  char* _IO_write_end;	/* End of put area. */
+  char* _IO_buf_base;	/* Start of reserve area. */
+  char* _IO_buf_end;	/* End of reserve area. */
+  /* The following fields are used to support backing up and undo. */
+  char *_IO_save_base; /* Pointer to start of non-current get area. */
+  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
+  char *_IO_save_end; /* Pointer to end of non-current get area. */
+
+  struct _IO_marker *_markers;
+
+  struct _IO_FILE *_chain;
+
+  int _fileno;
+  int _blksize;
+#ifdef _G_IO_IO_FILE_VERSION
+  _IO_off_t _old_offset;
+#else
+  _IO_off_t _offset;
+#endif
+
+#define __HAVE_COLUMN /* temporary */
+  /* 1+column number of pbase(); 0 is unknown. */
+  unsigned short _cur_column;
+  char _unused;
+  char _shortbuf[1];
+
+  /*  char* _save_gptr;  char* _save_egptr; */
+
+#ifdef _IO_LOCK_T
+  _IO_LOCK_T _lock;
+#endif
+#if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001
+  _IO_off64_t _offset;
+  int _unused2[16];	/* Make sure we don't get into trouble again.  */
+#endif
+};
+
+#ifndef __cplusplus
+typedef struct _IO_FILE _IO_FILE;
+#endif
+
+#if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001
+#define _IO_stdin_ _IO_2_1_stdin_
+#define _IO_stdout_ _IO_2_1_stdout_
+#define _IO_stderr_ _IO_2_1_stderr_
+#endif
+
+struct _IO_FILE_plus;
+extern struct _IO_FILE_plus _IO_stdin_, _IO_stdout_, _IO_stderr_;
+#define _IO_stdin ((_IO_FILE*)(&_IO_stdin_))
+#define _IO_stdout ((_IO_FILE*)(&_IO_stdout_))
+#define _IO_stderr ((_IO_FILE*)(&_IO_stderr_))
+
+
+/* Define the user-visible type, with user-friendly member names.  */
+typedef struct
+{
+  _IO_ssize_t (*read) __P ((struct _IO_FILE *, void *, _IO_ssize_t));
+  _IO_ssize_t (*write) __P ((struct _IO_FILE *, const void *, _IO_ssize_t));
+  _IO_fpos_t (*seek) __P ((struct _IO_FILE *, _IO_off_t, int));
+  int (*close) __P ((struct _IO_FILE *));
+} _IO_cookie_io_functions_t;
+
+/* Special file type for fopencookie function.  */
+struct _IO_cookie_file
+{
+  struct _IO_FILE file;
+  const void *vtable;
+  void *cookie;
+  _IO_cookie_io_functions_t io_functions;
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int __underflow __P ((_IO_FILE *));
+extern int __uflow __P ((_IO_FILE *));
+extern int __overflow __P ((_IO_FILE *, int));
+
+#define _IO_getc_unlocked(_fp) \
+       ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end ? __uflow (_fp) \
+	: *(unsigned char *) (_fp)->_IO_read_ptr++)
+#define _IO_peekc_unlocked(_fp) \
+       ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end \
+	  && __underflow (_fp) == EOF ? EOF \
+	: *(unsigned char *) (_fp)->_IO_read_ptr)
+
+#define _IO_putc_unlocked(_ch, _fp) \
+   (((_fp)->_IO_write_ptr >= (_fp)->_IO_write_end) \
+    ? __overflow (_fp, (unsigned char) (_ch)) \
+    : (unsigned char) (*(_fp)->_IO_write_ptr++ = (_ch)))
+
+#define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0)
+#define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0)
+
+extern int _IO_getc __P ((_IO_FILE *__fp));
+extern int _IO_putc __P ((int __c, _IO_FILE *__fp));
+extern int _IO_feof __P ((_IO_FILE *__fp));
+extern int _IO_ferror __P ((_IO_FILE *__fp));
+
+extern int _IO_peekc_locked __P ((_IO_FILE *__fp));
+
+/* This one is for Emacs. */
+#define _IO_PENDING_OUTPUT_COUNT(_fp)	\
+	((_fp)->_IO_write_ptr - (_fp)->_IO_write_base)
+
+extern void _IO_flockfile __P ((_IO_FILE *));
+extern void _IO_funlockfile __P ((_IO_FILE *));
+extern int _IO_ftrylockfile __P ((_IO_FILE *));
+
+#ifdef _IO_MTSAFE_IO
+# define _IO_peekc(_fp) _IO_peekc_locked (_fp)
+#else
+# define _IO_peekc(_fp) _IO_peekc_unlocked (_fp)
+# define _IO_flockfile(_fp) /**/
+# define _IO_funlockfile(_fp) /**/
+# define _IO_ftrylockfile(_fp) /**/
+# define _IO_cleanup_region_start(_fct, _fp) /**/
+# define _IO_cleanup_region_end(_Doit) /**/
+#endif /* !_IO_MTSAFE_IO */
+
+
+extern int _IO_vfscanf __P ((_IO_FILE *, const char *, _IO_va_list, int *));
+extern int _IO_vfprintf __P ((_IO_FILE *, const char *, _IO_va_list));
+extern _IO_ssize_t _IO_padn __P ((_IO_FILE *, int, _IO_ssize_t));
+extern _IO_size_t _IO_sgetn __P ((_IO_FILE *, void *, _IO_size_t));
+
+#if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001
+extern _IO_fpos64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));      
+extern _IO_fpos64_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos64_t, int));
+#else
+extern _IO_fpos_t _IO_seekoff __P ((_IO_FILE *, _IO_off_t, int, int));
+extern _IO_fpos_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos_t, int));
+#endif
+
+extern void _IO_free_backup_area __P ((_IO_FILE *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IO_STDIO_H */
Index: trunk/src/emx/include/Attic/cpp/list
===================================================================
--- trunk/src/emx/include/Attic/cpp/list	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/list	(revision 18)
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_LIST
+#define __SGI_STL_LIST
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_unin.h>
+#include <stl_list.h>
+
+#endif /* __SGI_STL_LIST */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/list.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/list.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/list.h	(revision 18)
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_LIST_H
+#define __SGI_STL_LIST_H
+
+#include <algobase.h>
+#include <alloc.h>
+#include <stl_list.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::list;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_LIST_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/map
===================================================================
--- trunk/src/emx/include/Attic/cpp/map	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/map	(revision 18)
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_MAP
+#define __SGI_STL_MAP
+
+#ifndef __SGI_STL_INTERNAL_TREE_H
+#include <stl_tree.h>
+#endif
+#include <stl_map.h>
+#include <stl_mmap.h>
+
+#endif /* __SGI_STL_MAP */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/map.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/map.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/map.h	(revision 18)
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_MAP_H
+#define __SGI_STL_MAP_H
+
+#include <tree.h>
+#include <stl_map.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::map;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_MAP_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/memory
===================================================================
--- trunk/src/emx/include/Attic/cpp/memory	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/memory	(revision 18)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __SGI_STL_MEMORY
+#define __SGI_STL_MEMORY
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_temp.h>
+#include <stl_unin.h>
+#include <stl_raw_.h>
+
+// Note: auto_ptr is commented out in this release because the details
+//  of the interface are still being discussed by the C++ standardization
+//  committee.  It will be included once the iterface is finalized.
+
+#if 0
+#if defined(_MUTABLE_IS_KEYWORD) && defined(_EXPLICIT_IS_KEYWORD) && \
+    defined(__STL_MEMBER_TEMPLATES)
+
+__STL_BEGIN_NAMESPACE
+
+template <class X> class auto_ptr {
+private:
+  X* ptr;
+  mutable bool owns;
+public:
+  typedef X element_type;
+  explicit auto_ptr(X* p = 0) __STL_NOTHROW : ptr(p), owns(p) {}
+  auto_ptr(const auto_ptr& a) __STL_NOTHROW : ptr(a.ptr), owns(a.owns) {
+    a.owns = 0;
+  }
+  template <class T> auto_ptr(const auto_ptr<T>& a) __STL_NOTHROW
+    : ptr(a.ptr), owns(a.owns) {
+      a.owns = 0;
+  }
+
+  auto_ptr& operator=(const auto_ptr& a) __STL_NOTHROW {
+    if (&a != this) {
+      if (owns)
+        delete ptr;
+      owns = a.owns;
+      ptr = a.ptr;
+      a.owns = 0;
+    }
+  }
+  template <class T> auto_ptr& operator=(const auto_ptr<T>& a) __STL_NOTHROW {
+    if (&a != this) {
+      if (owns)
+        delete ptr;
+      owns = a.owns;
+      ptr = a.ptr;
+      a.owns = 0;
+    }
+  }
+  ~auto_ptr() {
+    if (owns)
+      delete ptr;
+  }
+
+  X& operator*() const __STL_NOTHROW { return *ptr; }
+  X* operator->() const __STL_NOTHROW { return ptr; }
+  X* get() const __STL_NOTHROW { return ptr; }
+  X* release const __STL_NOTHROW { owns = false; return ptr }
+};
+
+__STL_END_NAMESPACE
+#endif /* mutable && explicit && member templates */
+#endif /* 0 */
+
+
+#endif /* __SGI_STL_MEMORY */
+
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/minmax.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/minmax.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/minmax.h	(revision 18)
@@ -0,0 +1,65 @@
+/*
+Copyright (C) 1992 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _minmax_h
+#ifdef _GNUG_
+#pragma interface
+#endif
+#define _minmax_h 1
+
+#include <_G_confi.h>
+
+inline char min(char a, char b) { return (a < b)?a:b;}
+#ifndef  _G_BROKEN_SIGNED_CHAR
+inline signed char min(signed char a, signed char b) { return (a < b)?a:b;}
+#endif
+inline unsigned char min(unsigned char a, unsigned char b) {return (a<b)?a:b;}
+
+inline short min(short a, short b) {return (a < b) ?a:b;}
+inline unsigned short min(unsigned short a, unsigned short b) {return (a < b)?a:b;}
+
+inline int min(int a, int b) {return (a < b)?a:b;}
+inline unsigned int min(unsigned int a, unsigned int b) {return (a < b)?a:b;}
+
+inline long min(long a, long b) {return (a < b)?a:b;}
+inline unsigned long min(unsigned long a, unsigned long b) {return (a<b)?a:b;}
+
+inline float min(float a, float b) {return (a < b)?a:b;}
+
+inline double min(double a, double b) {return (a < b)?a:b;}
+
+inline char max(char a, char b) { return (a > b)?a:b;}
+#ifndef  _G_BROKEN_SIGNED_CHAR
+inline signed char max(signed char a, signed char b) {return (a > b)?a:b;}
+#endif
+inline unsigned char max(unsigned char a, unsigned char b) {return (a>b)?a:b;}
+
+inline short max(short a, short b) {return (a > b) ?a:b;}
+inline unsigned short max(unsigned short a, unsigned short b) {return (a > b)?a:b;}
+
+inline int max(int a, int b) {return (a > b)?a:b;}
+inline unsigned int max(unsigned int a, unsigned int b) {return (a > b)?a:b;}
+
+inline long max(long a, long b) {return (a > b)?a:b;}
+inline unsigned long max(unsigned long a, unsigned long b) {return (a>b)?a:b;}
+
+inline float max(float a, float b) {return (a > b)?a:b;}
+
+inline double max(double a, double b) {return (a > b)?a:b;}
+
+#endif
+
Index: trunk/src/emx/include/Attic/cpp/multimap.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/multimap.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/multimap.h	(revision 18)
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_MULTIMAP_H
+#define __SGI_STL_MULTIMAP_H
+
+#include <tree.h>
+#include <stl_mmap.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::multimap;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_MULTIMAP_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/multiset.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/multiset.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/multiset.h	(revision 18)
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_MULTISET_H
+#define __SGI_STL_MULTISET_H
+
+#include <tree.h>
+#include <stl_mset.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::multiset;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_MULTISET_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/new
===================================================================
--- trunk/src/emx/include/Attic/cpp/new	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/new	(revision 18)
@@ -0,0 +1,48 @@
+// The -*- C++ -*- dynamic memory management header.
+// Copyright (C) 1994, 1996 Free Software Foundation
+
+#ifndef __NEW__
+#define __NEW__
+
+#pragma interface "new"
+#include <stddef.h>
+#include <exceptio>
+
+extern "C++" {
+
+#if 0
+namespace std {
+#endif
+
+  class bad_alloc : public exception {
+  public:
+    virtual const char* what() const throw() { return "bad_alloc"; }
+  };
+
+  struct nothrow_t {};
+  extern const nothrow_t nothrow;
+  typedef void (*new_handler)();
+  extern "C" new_handler set_new_handler (new_handler);
+
+#if 0
+} // namespace std
+#endif
+
+// G++ implementation internals
+extern new_handler __new_handler;
+extern "C" void __default_new_handler (void);
+
+// replaceable signatures
+void *operator new (size_t);
+void *operator new (size_t, const nothrow_t&) throw();
+void *operator new[] (size_t);
+void *operator new[] (size_t, const nothrow_t&) throw();
+void operator delete (void *) throw();
+void operator delete[] (void *) throw();
+
+// default placement versions of operator new
+inline void *operator new(size_t, void *place) throw() { return place; }
+inline void *operator new[](size_t, void *place) throw() { return place; }
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/new.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/new.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/new.h	(revision 18)
@@ -0,0 +1,13 @@
+// -*- C++ -*- forwarding header.
+
+#ifndef __NEW_H__
+#define __NEW_H__
+
+#include <new>
+
+#if 0
+using std::new_handler;
+using std::set_new_handler;
+#endif
+
+#endif // __NEW_H__
Index: trunk/src/emx/include/Attic/cpp/numeric
===================================================================
--- trunk/src/emx/include/Attic/cpp/numeric	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/numeric	(revision 18)
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_NUMERIC
+#define __SGI_STL_NUMERIC
+
+#include <stl_conf.h>
+#include <stl_relo.h>
+#include <stddef.h>
+#include <iostream.h>
+#include <stl_iter.h>
+#include <stl_func.h>
+#include <stl_nume.h>
+
+#endif /* __SGI_STL_NUMERIC */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/osfcn.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/osfcn.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/osfcn.h	(revision 18)
@@ -0,0 +1,17 @@
+
+#ifndef OSFCN_H
+#define OSFCN_H 1
+
+#include <std.h>
+#include <time.h>
+#include <sys/types.h>
+#if _G_HAVE_SYS_SOCKET
+#include <sys/socket.h>
+#endif
+#if _G_HAVE_SYS_RESOURCE
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/ostream.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/ostream.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/ostream.h	(revision 18)
@@ -0,0 +1,25 @@
+/* 
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include <stream.h>
Index: trunk/src/emx/include/Attic/cpp/pair.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/pair.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/pair.h	(revision 18)
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_PAIR_H
+#define __SGI_STL_PAIR_H
+
+#ifndef __STL_CONFIG_H
+#include <stl_conf.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_RELOPS
+#include <stl_relo.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_PAIR_H
+#include <stl_pair.h>
+#endif
+
+#ifdef __STL_USE_NAMESPACES
+
+using __STD::pair;
+using __STD::make_pair;
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_PAIR_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/parsestr.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/parsestr.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/parsestr.h	(revision 18)
@@ -0,0 +1,156 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License.
+
+Written by Per Bothner (bothner@cygnus.com). */
+
+#ifndef PARSESTREAM_H
+#define PARSESTREAM_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+#include "streambu.h"
+
+extern "C++" {
+// A parsebuf is a streambuf optimized for scanning text files.
+// It keeps track of line and column numbers.
+// It is guaranteed to remember the entire current line,
+// as well the '\n'-s on either side of it (if they exist).
+// You can arbitrarily seek (or unget) within this extended line.
+// Other backward seeks are not supported.
+// Normal read semantics are supported (and hence istream operators like >>).
+
+class parsebuf : public streambuf {
+  protected:
+    _IO_fpos_t pos_at_line_start;
+    long _line_length;
+    unsigned long __line_number;
+    char *buf_start;
+    char *buf_end;
+
+  public:
+    parsebuf *chain;
+
+    // Return column number (raw - don't handle tabs etc).
+    // Retult can be -1, meaning: at '\n' before current line.
+    virtual int tell_in_line();
+
+    // seek to (raw) column I in current line.
+    // Result is new (raw) column position - differs from I if unable to seek.
+    // Seek to -1 tries to seek to before previous LF.
+    virtual int seek_in_line(int i);
+
+    // Note: there is no "current line" initially, until something is read.
+
+    // Current line number, starting with 0.
+    // If tell_in_line()==-1, then line number of next line.
+    int line_number() { return __line_number; }
+
+    // Length of current line, not counting either '\n'.
+    int line_length() { return _line_length; }
+    // Current line - not a copy, so file ops may trash it. 
+    virtual char* current_line();
+    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
+    virtual streambuf* setbuf(char* p, int len);
+  protected:
+    parsebuf() { chain= NULL;
+	__line_number = 0; pos_at_line_start = 0; _line_length = -1; }
+    virtual int pbackfail(int c);
+};
+
+// A string_parsebuf is a parsebuf whose source is a fixed string.
+
+class string_parsebuf : public parsebuf {
+  public:
+    int do_delete;
+    string_parsebuf(char *str, int len, int delete_at_close=0);
+    virtual int underflow();
+    virtual char* current_line();
+    virtual int seek_in_line(int i);
+    virtual int tell_in_line();
+    char *left() const { return base(); }
+    char *right() const { return ebuf(); }
+//    streampos seekoff(streamoff, _seek_dir, int);
+};
+
+// A func_parsebuf calls a given function to get new input.
+// Each call returns an entire NUL-terminated line (without the '\n').
+// That line has been allocated with malloc(), not new.
+// The interface is tailored to the GNU readline library.
+// Example:
+// char* DoReadLine(void* arg)
+// {
+//   char *line = readline((char*)arg); /* 'arg' is used as prompt. */
+//   if line == NULL) { putc('\n', stderr); return NULL; }
+//   if (line[0] != '\0') add_history(line);
+//    return line;
+// }
+// char PromptBuffer[100] = "> ";
+// func_parsebuf my_stream(DoReadLine, PromptBuffer);
+
+typedef char *(*CharReader)(void *arg);
+class istream;
+
+class func_parsebuf : public parsebuf {
+  public:
+    void *arg;
+    CharReader read_func;
+    int backed_up_to_newline;
+    func_parsebuf(CharReader func, void *argm = NULL);
+    int underflow();
+    virtual int tell_in_line();
+    virtual int seek_in_line(int i);
+    virtual char* current_line();
+};
+
+// A general_parsebuf is a parsebuf which gets its input from some
+// other streambuf. It explicitly buffers up an entire line.
+
+class general_parsebuf : public parsebuf {
+  public:
+    streambuf *sbuf;
+    int delete_buf; // Delete sbuf when destroying this.
+    general_parsebuf(streambuf *buf, int delete_arg_buf = 0);
+    int underflow();
+    virtual int tell_in_line();
+    virtual int seek_in_line(int i);
+    ~general_parsebuf();
+    virtual char* current_line();
+};
+
+#if 0
+class parsestream : public istream {
+    streammarker marks[2];
+    short _first; // of the two marks; either 0 or 1
+    int _lineno;
+    int first() { return _first; }
+    int second() { return 1-_first; }
+    int line_length() { marks[second].delta(marks[first]); }
+    int line_length() { marks[second].delta(marks[first]); }
+    int seek_in_line(int i);
+    int tell_in_line();
+    int line_number();
+};
+#endif
+} // extern "C++"
+#endif /*!defined(PARSESTREAM_H)*/
Index: trunk/src/emx/include/Attic/cpp/pfstream.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/pfstream.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/pfstream.h	(revision 18)
@@ -0,0 +1,59 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/* Written by Per Bothner (bothner@cygnus.com). */
+
+#ifndef _PFSTREAM_H
+#define _PFSTREAM_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+#include <fstream.h>
+
+extern "C++" {
+// ipfstream foo("NAME") is like: ifstream foo("NAME").  However,
+// if NAME starts *or ends* with a '|', the remainder of NAME is
+// evaluated as a shell command (using a procbuf), and all input
+// read from foo is whatever that shell writes to its standard output.
+// E.g. ipfstream foo("|zcat foo.Z") or ipfstream foo("zcat foo.Z|")
+// (These two forms are equivalent.)
+
+class ipfstream : public ifstream {
+  public:
+    ipfstream(const char *name, int mode=ios::in, int prot=0664);
+};
+
+// opfstream foo("NAME") is like: ofstream foo("NAME").
+// However, if NAME starts with a '|', the remainder of NAME is
+// evaluated as a shell command (using a procbuf), and all output
+// written to foo is piped to the standard input of that shell.
+// E.g. opfstream foo("|more");
+
+class opfstream : public ofstream {
+  public:
+    opfstream(const char *name, int mode=ios::out, int prot=0664);
+};
+} // extern "C++"
+#endif /*!_PFSTREAM_H*/
+
Index: trunk/src/emx/include/Attic/cpp/procbuf.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/procbuf.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/procbuf.h	(revision 18)
@@ -0,0 +1,50 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/* Written by Per Bothner (bothner@cygnus.com). */
+
+#ifndef _PROCBUF_H
+#define _PROCBUF_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <streambu.h>
+
+extern "C++" {
+class procbuf : public filebuf {
+    /* Following fields must match those in struct _IO_proc_file */
+    _IO_pid_t _pid;
+    procbuf *_next;
+  public:
+    procbuf() : filebuf() { }
+    procbuf(const char *command, int mode);
+    procbuf* open(const char *command, int mode);
+    procbuf *close() { return (procbuf*)filebuf::close(); }
+    virtual int sys_close();
+    ~procbuf();
+};
+} // extern "C++"
+
+#endif /* !_PROCBUF_H */
Index: trunk/src/emx/include/Attic/cpp/queue
===================================================================
--- trunk/src/emx/include/Attic/cpp/queue	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/queue	(revision 18)
@@ -0,0 +1,45 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_QUEUE
+#define __SGI_STL_QUEUE
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_unin.h>
+#include <stl_vect.h>
+#include <stl_bvec.h>
+#include <stl_heap.h>
+#include <stl_dequ.h>
+#include <stl_func.h>
+#include <stl_queu.h>
+
+#endif /* __SGI_STL_QUEUE */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/rope
===================================================================
--- trunk/src/emx/include/Attic/cpp/rope	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/rope	(revision 18)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_ROPE
+#define __SGI_STL_ROPE
+
+#include <stl_algb.h>
+#include <tempbuf.h>
+#include <stl_algo.h>
+#include <stl_func.h>
+#include <stl_nume.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_unin.h>
+#include <stl_hfun.h>
+#include <stl_rope.h>
+
+#endif /* __SGI_STL_ROPE */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/rope.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/rope.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/rope.h	(revision 18)
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_ROPE_H
+#define __SGI_STL_ROPE_H
+
+#include <hashtabl.h>
+#include <stl_rope.h>
+
+#ifdef __STL_USE_NAMESPACES
+
+using __STD::char_producer; 
+using __STD::sequence_buffer; 
+using __STD::rope; 
+using __STD::crope; 
+using __STD::wrope; 
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_ROPE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/ropeimpl.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/ropeimpl.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/ropeimpl.h	(revision 18)
@@ -0,0 +1,1537 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+# include <stdio.h>
+# include <iostream.h>
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+// Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf
+// if necessary.  Assumes path_end[leaf_index] and leaf_pos are correct.
+// Results in a valid buf_ptr if the iterator can be legitimately
+// dereferenced.
+template <class charT, class Alloc>
+void __rope_iterator_base<charT,Alloc>::setbuf
+(__rope_iterator_base<charT,Alloc> &x)
+{
+    const RopeBase * leaf = x.path_end[x.leaf_index];
+    size_t leaf_pos = x.leaf_pos;
+    size_t pos = x.current_pos;
+
+    switch(leaf -> tag) {
+	case RopeBase::leaf:
+	    x.buf_start = ((__rope_RopeLeaf<charT,Alloc> *)leaf) -> data;
+	    x.buf_ptr = x.buf_start + (pos - leaf_pos);
+	    x.buf_end = x.buf_start + leaf -> size;
+	    break;
+	case RopeBase::function:
+	case RopeBase::substringfn:
+	    {
+		size_t len = iterator_buf_len;
+		size_t buf_start_pos = leaf_pos;
+		size_t leaf_end = leaf_pos + leaf -> size;
+		char_producer<charT> *fn =
+			((__rope_RopeFunction<charT,Alloc> *)leaf) -> fn;
+
+		if (buf_start_pos + len <= pos) {
+		    buf_start_pos = pos - len/4;
+		    if (buf_start_pos + len > leaf_end) {
+			buf_start_pos = leaf_end - len;
+		    }
+		}
+		if (buf_start_pos + len > leaf_end) {
+		    len = leaf_end - buf_start_pos;
+		}
+		(*fn)(buf_start_pos - leaf_pos, len, x.tmp_buf);
+		x.buf_ptr = x.tmp_buf + (pos - buf_start_pos);
+		x.buf_start = x.tmp_buf;
+		x.buf_end = x.tmp_buf + len;
+	    }
+	    break;
+	default:
+	    __stl_assert(0);
+    }
+}
+
+// Set path and buffer inside a rope iterator.  We assume that 
+// pos and root are already set.
+template <class charT, class Alloc>
+void __rope_iterator_base<charT,Alloc>::setcache
+(__rope_iterator_base<charT,Alloc> &x)
+{
+    const RopeBase * path[RopeBase::max_rope_depth+1];
+    const RopeBase * curr_rope;
+    int curr_depth = -1;  /* index into path    */
+    size_t curr_start_pos = 0;
+    size_t pos = x.current_pos;
+    unsigned char dirns = 0;	// Bit vector indicating right turns in the path
+
+    __stl_assert(pos <= x.root -> size);
+    if (pos >= x.root -> size) {
+	x.buf_ptr = 0;
+	return;
+    }
+    curr_rope = x.root;
+    if (0 != curr_rope -> c_string) {
+	/* Treat the root as a leaf. */
+	x.buf_start = curr_rope -> c_string;
+	x.buf_end = curr_rope -> c_string + curr_rope -> size;
+	x.buf_ptr = curr_rope -> c_string + pos;
+	x.path_end[0] = curr_rope;
+	x.leaf_index = 0;
+	x.leaf_pos = 0;
+	return;
+    }
+    for(;;) {
+	++curr_depth;
+	__stl_assert(curr_depth <= RopeBase::max_rope_depth);
+	path[curr_depth] = curr_rope;
+	switch(curr_rope -> tag) {
+	  case RopeBase::leaf:
+	  case RopeBase::function:
+	  case RopeBase::substringfn:
+	    x.leaf_pos = curr_start_pos;
+	    goto done;
+	  case RopeBase::concat:
+	    {
+		__rope_RopeConcatenation<charT,Alloc> *c =
+			(__rope_RopeConcatenation<charT,Alloc> *)curr_rope;
+		RopeBase * left = c -> left;
+		size_t left_len = left -> size;
+		
+		dirns <<= 1;
+		if (pos >= curr_start_pos + left_len) {
+		    dirns |= 1;
+		    curr_rope = c -> right;
+		    curr_start_pos += left_len;
+		} else {
+		    curr_rope = left;
+		}
+	    }
+	    break;
+	}
+    }
+  done:
+    // Copy last section of path into path_end.
+      {
+	int i = -1;
+	int j = curr_depth  + 1 - path_cache_len;
+
+	if (j < 0) j = 0;
+	while (j <= curr_depth) {
+	    x.path_end[++i] = path[j++];
+	}
+	x.leaf_index = i;
+      }
+      x.path_directions = dirns;
+    setbuf(x);
+}
+
+// Specialized version of the above.  Assumes that
+// the path cache is valid for the previous position.
+template <class charT, class Alloc>
+void __rope_iterator_base<charT,Alloc>::setcache_for_incr
+(__rope_iterator_base<charT,Alloc> &x)
+{
+    int current_index = x.leaf_index;
+    const RopeBase * current_node = x.path_end[current_index];
+    size_t len = current_node -> size;
+    size_t node_start_pos = x.leaf_pos;
+    unsigned char dirns = x.path_directions;
+    __rope_RopeConcatenation<charT,Alloc> * c;
+
+    __stl_assert(x.current_pos <= x.root -> size);
+    if (x.current_pos - node_start_pos < len) {
+	/* More stuff in this leaf, we just didn't cache it. */
+	setbuf(x);
+	return;
+    }
+    __stl_assert(node_start_pos + len == x.current_pos);
+    //  node_start_pos is starting position of last_node.
+    while (--current_index >= 0) {
+	if (!(dirns & 1) /* Path turned left */) break;
+	current_node = x.path_end[current_index];
+	c = (__rope_RopeConcatenation<charT,Alloc> *)current_node;
+	// Otherwise we were in the right child.  Thus we should pop
+	// the concatenation node.
+	node_start_pos -= c -> left -> size;
+	dirns >>= 1;
+    }
+    if (current_index < 0) {
+	// We underflowed the cache. Punt.
+	setcache(x);
+	return;
+    }
+    current_node = x.path_end[current_index];
+    c = (__rope_RopeConcatenation<charT,Alloc> *)current_node;
+    // current_node is a concatenation node.  We are positioned on the first
+    // character in its right child.
+    // node_start_pos is starting position of current_node.
+    node_start_pos += c -> left -> size;
+    current_node = c -> right;
+    x.path_end[++current_index] = current_node;
+    dirns |= 1;
+    while (RopeBase::concat == current_node -> tag) {
+	++current_index;
+	if (path_cache_len == current_index) {
+	    int i;
+	    for (i = 0; i < path_cache_len-1; i++) {
+		x.path_end[i] = x.path_end[i+1];
+	    }
+	    --current_index;
+	}
+	current_node =
+	    ((__rope_RopeConcatenation<charT,Alloc> *)current_node) -> left;
+	x.path_end[current_index] = current_node;
+	dirns <<= 1;
+	// node_start_pos is unchanged.
+    }
+    x.leaf_index = current_index;
+    x.leaf_pos = node_start_pos;
+    x.path_directions = dirns;
+    setbuf(x);
+}
+
+template <class charT, class Alloc>
+void __rope_iterator_base<charT,Alloc>::incr(size_t n) {
+    current_pos += n;
+    if (0 != buf_ptr) {
+        size_t chars_left = buf_end - buf_ptr;
+        if (chars_left > n) {
+            buf_ptr += n;
+        } else if (chars_left == n) {
+            buf_ptr += n;
+            setcache_for_incr(*this);
+        } else {
+            buf_ptr = 0;
+        }
+    }
+}
+
+template <class charT, class Alloc>
+void __rope_iterator_base<charT,Alloc>::decr(size_t n) {
+    if (0 != buf_ptr) {
+        size_t chars_left = buf_ptr - buf_start;
+        if (chars_left >= n) {
+            buf_ptr -= n;
+        } else {
+            buf_ptr = 0;
+        }
+    }
+    current_pos -= n;
+}
+
+template <class charT, class Alloc>
+void __rope_iterator<charT,Alloc>::check() {
+    if (root_rope -> tree_ptr != root) {
+        // Rope was modified.  Get things fixed up.
+        RopeBase::unref(root);
+        root = root_rope -> tree_ptr;
+        RopeBase::ref(root);
+        buf_ptr = 0;
+    }
+}
+
+template <class charT, class Alloc>
+inline __rope_const_iterator<charT, Alloc>::__rope_const_iterator
+(const __rope_iterator<charT,Alloc> & x)
+: __rope_iterator_base<charT,Alloc>(x) { }
+
+template <class charT, class Alloc>
+inline __rope_iterator<charT,Alloc>::__rope_iterator
+(rope<charT,Alloc>& r, size_t pos)
+        : __rope_iterator_base<charT,Alloc>(r.tree_ptr, pos), root_rope(&r) {
+    RopeBase::ref(root);
+}
+
+template <class charT, class Alloc>
+inline size_t rope<charT,Alloc>::char_ptr_len(const charT *s)
+{
+    const charT *p = s;
+
+    while (!is0(*p)) { ++p; }
+    return(p - s);
+}
+
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeLeaf *
+rope<charT,Alloc>::RopeLeaf_from_char_ptr(__GC_CONST charT *s, size_t size)
+{
+    RopeLeaf *t = LAlloc::allocate();
+
+    t -> tag = RopeBase::leaf;
+    if (__is_basic_char_type((charT *)0)) {
+	// already eos terminated.
+	t -> c_string = s;
+    } else {
+	t -> c_string = 0;
+    }
+    t -> is_balanced = true;
+    t -> depth = 0;
+    t -> size = size;
+    t -> data = s;
+#   ifndef __GC
+	t -> refcount = 1;
+	t -> init_refcount_lock();
+#   endif
+    return (t);
+}
+
+# ifdef __GC
+template <class charT, class Alloc>
+void __rope_RopeBase<charT,Alloc>::fn_finalization_proc(void * tree, void *)
+{
+    delete ((__rope_RopeFunction<charT,Alloc> *)tree) -> fn;
+}
+# endif
+
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeFunction *
+rope<charT,Alloc>::RopeFunction_from_fn
+(char_producer<charT> *fn, size_t size, bool delete_fn)
+{
+    if (0 == size) return 0;
+    RopeFunction *t = FAlloc::allocate();
+    t -> tag = RopeBase::function;
+    t -> c_string = 0;
+    t -> is_balanced = true;
+    t -> depth = 0;
+    t -> size = size;
+    t -> fn = fn;
+#   ifdef __GC
+	if (delete_fn) {
+	    GC_REGISTER_FINALIZER(t, RopeBase::fn_finalization_proc, 0, 0, 0);
+	}
+#   else
+	t -> delete_when_done = delete_fn;
+	t -> refcount = 1;
+	t -> init_refcount_lock();
+#   endif
+    return (t);
+}
+
+#ifndef __GC
+
+template <class charT, class Alloc>
+inline void __rope_RopeBase<charT,Alloc>::free_c_string()
+{
+    charT * cstr = c_string;
+    if (0 != cstr) {
+	size_t sz = size + 1;
+	destroy(cstr, cstr + sz);
+	DataAlloc::deallocate(cstr, sz);
+    }
+}
+
+template <class charT, class Alloc>
+inline void __rope_RopeBase<charT,Alloc>::free_string(charT* s, size_t n)
+{
+    if (!__is_basic_char_type((charT *)0)) {
+	destroy(s, s + n);
+    }
+    DataAlloc::deallocate(s, rounded_up_size(n));
+}
+
+template <class charT, class Alloc>
+void __rope_RopeBase<charT,Alloc>::free_tree()
+{
+    switch(tag) {
+	case leaf:
+	    {
+	        __rope_RopeLeaf<charT,Alloc> * l =
+			(__rope_RopeLeaf<charT,Alloc> *)this;
+		charT * d = l -> data;
+		
+		if (d != c_string) {
+		    free_c_string();
+		}
+		free_string(d, size);
+		LAlloc::deallocate(l);
+	    }
+	    break;
+	case concat:
+	    {
+		__rope_RopeConcatenation<charT,Alloc> * c =
+			(__rope_RopeConcatenation<charT,Alloc> *)this;
+		__rope_RopeBase * left = c -> left;
+		__rope_RopeBase * right = c -> right;
+		free_c_string();
+		left -> unref_nonnil();
+		right -> unref_nonnil();
+		CAlloc::deallocate(c);
+	    }
+	    break;
+	case function:
+	    {
+		__rope_RopeFunction<charT,Alloc> * fn =
+		  	(__rope_RopeFunction<charT,Alloc> *)this;
+	        free_c_string();
+	        if ( fn -> delete_when_done) {
+		    delete fn -> fn;
+	        }
+	        FAlloc::deallocate(fn);
+	        break;
+	    }
+	case substringfn:
+	    {
+	        __rope_RopeSubstring<charT,Alloc> * ss =
+			(__rope_RopeSubstring<charT,Alloc> *)this;
+		__rope_RopeBase *base = ss -> base;
+		free_c_string();
+		base -> unref_nonnil();
+		SAlloc::deallocate(ss);
+		break;
+	    }
+    }
+}
+#else
+
+template <class charT, class Alloc>
+inline void __rope_RopeBase<charT,Alloc>::free_string(charT* s, size_t n)
+{}
+
+#endif
+
+
+// Concatenate a C string onto a leaf rope by copying the rope data.
+// Used for short ropes.
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeLeaf *
+rope<charT,Alloc>::leaf_concat_char_iter
+		(RopeLeaf * r, const charT * iter, size_t len)
+{
+    size_t old_len = r -> size;
+    charT * new_data = (charT *)
+	DataAlloc::allocate(rounded_up_size(old_len + len));
+    RopeLeaf * result;
+    
+    uninitialized_copy_n(r -> data, old_len, new_data);
+    uninitialized_copy_n(iter, len, new_data + old_len);
+    __cond_store_eos(new_data[old_len + len]);
+    __STL_TRY {
+	result = RopeLeaf_from_char_ptr(new_data, old_len + len);
+    }
+    __STL_UNWIND(RopeBase::free_string(new_data, old_len + len));
+    return result;
+}
+
+#ifndef __GC
+// As above, but it's OK to clobber original if refcount is 1
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeLeaf *
+rope<charT,Alloc>::destr_leaf_concat_char_iter
+		(RopeLeaf * r, const charT * iter, size_t len)
+{
+    __stl_assert(r -> refcount >= 1);
+    if (r -> refcount > 1) return leaf_concat_char_iter(r, iter, len);
+    size_t old_len = r -> size;
+    if (allocated_capacity(old_len) >= old_len + len) {
+	// The space has been partially initialized for the standard
+	// character types.  But that doesn't matter for those types.
+	uninitialized_copy_n(iter, len, r -> data + old_len);
+	if (__is_basic_char_type((charT *)0)) {
+	    __cond_store_eos(r -> data[old_len + len]);
+	    __stl_assert(r -> c_string == r -> data);
+	} else if (r -> c_string != r -> data && 0 != r -> c_string) {
+	    r -> free_c_string();
+	    r -> c_string = 0;
+	}
+	r -> size = old_len + len;
+	__stl_assert(r -> refcount == 1);
+	r -> refcount = 2;
+	return r;
+    } else {
+	RopeLeaf * result = leaf_concat_char_iter(r, iter, len);
+	__stl_assert(result -> refcount == 1);
+	return result;
+    }
+}
+#endif
+
+// Assumes left and right are not 0.
+// Does not increment (nor decrement on exception) child reference counts.
+// Result has ref count 1.
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeBase *
+rope<charT,Alloc>::tree_concat (RopeBase * left, RopeBase * right)
+{
+    RopeConcatenation * result = CAlloc::allocate();
+    unsigned char child_depth = left -> depth;
+    size_t rsize;
+
+    result -> tag = RopeBase::concat;
+    result -> c_string = 0;
+    result -> is_balanced = false;
+    result -> size = rsize = left -> size + right -> size;
+    if (right -> depth > child_depth) child_depth = right -> depth;
+    unsigned char depth = (unsigned char)(child_depth + 1);
+    result -> depth = depth;
+    result -> left = left;
+    result -> right = right;
+#   ifndef __GC
+	result -> refcount = 1;
+	result -> init_refcount_lock();
+#   endif
+    if (depth > 20 && (rsize < 1000 || depth > RopeBase::max_rope_depth)) {
+	RopeBase * balanced;
+
+	__STL_TRY {
+	   balanced = balance(result);
+#          ifndef __GC
+	     if (result != balanced) {
+		__stl_assert(1 == result -> refcount
+			     && 1 == balanced -> refcount);
+	     }
+#          endif
+	   result -> unref_nonnil();
+        }
+	__STL_UNWIND(CAlloc::deallocate(result));
+		// In case of exception, we need to deallocate
+		// otherwise dangling result node.  But caller
+		// still owns its children.  Thus unref is
+		// inappropriate.
+	return balanced;
+    } else {
+	return result;
+    }
+}
+
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeBase * rope<charT,Alloc>::concat_char_iter
+		(RopeBase * r, const charT *s, size_t slen)
+{
+    RopeBase *result;
+    if (0 == slen) {
+	ref(r);
+	return r;
+    }
+    if (0 == r) return RopeLeaf_from_unowned_char_ptr(s, slen);
+    if (RopeBase::leaf == r -> tag && r -> size + slen <= copy_max) {
+	result = leaf_concat_char_iter((RopeLeaf *)r, s, slen);
+#       ifndef __GC
+	  __stl_assert(1 == result -> refcount);
+#       endif
+	return result;
+    }
+    if (RopeBase::concat == r -> tag
+	&& RopeBase::leaf == ((RopeConcatenation *)r) -> right -> tag) {
+	RopeLeaf *right = (RopeLeaf *)(((RopeConcatenation *)r) -> right);
+	if (right -> size + slen <= copy_max) {
+	  RopeBase * left = ((RopeConcatenation *)r) -> left;
+	  RopeBase * nright = leaf_concat_char_iter((RopeLeaf *)right, s, slen);
+	  left -> ref_nonnil();
+	  __STL_TRY {
+	    result = tree_concat(left, nright);
+          }
+	  __STL_UNWIND(unref(left); unref(nright));
+#         ifndef __GC
+	    __stl_assert(1 == result -> refcount);
+#         endif
+	  return result;
+	}
+    }
+    RopeBase * nright = RopeLeaf_from_unowned_char_ptr(s, slen);
+    __STL_TRY {
+      r -> ref_nonnil();
+      result = tree_concat(r, nright);
+    }
+    __STL_UNWIND(unref(r); unref(nright));
+#   ifndef __GC
+      __stl_assert(1 == result -> refcount);
+#   endif
+    return result;
+}
+
+#ifndef __GC
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeBase * rope<charT,Alloc>
+::destr_concat_char_iter
+		(RopeBase * r, const charT *s, size_t slen)
+{
+    RopeBase *result;
+    if (0 == r) return RopeLeaf_from_unowned_char_ptr(s, slen);
+    size_t count = r -> refcount;
+    size_t orig_size = r -> size;
+    __stl_assert(count >= 1);
+    if (count > 1) return concat_char_iter(r, s, slen);
+    if (0 == slen) {
+	r -> refcount = 2;      // One more than before
+	return r;
+    }
+    if (orig_size + slen <= copy_max && RopeBase::leaf == r -> tag) {
+	result = destr_leaf_concat_char_iter((RopeLeaf *)r, s, slen);
+	return result;
+    }
+    if (RopeBase::concat == r -> tag) {
+	RopeLeaf *right = (RopeLeaf *)(((RopeConcatenation *)r) -> right);
+	if (RopeBase::leaf == right -> tag
+	    && right -> size + slen <= copy_max) {
+	  RopeBase * new_right = destr_leaf_concat_char_iter(right, s, slen);
+	  if (right == new_right) {
+	      __stl_assert(new_right -> refcount == 2);
+	      new_right -> refcount = 1;
+	  } else {
+	      __stl_assert(new_right -> refcount >= 1);
+	      right -> unref_nonnil();
+	  }
+	  __stl_assert(r -> refcount == 1);
+	  r -> refcount = 2;    // One more than before.
+	  ((RopeConcatenation *)r) -> right = new_right;
+	  r -> size = orig_size + slen;
+	  if (0 != r -> c_string) {
+	      r -> free_c_string();
+	      r -> c_string = 0;
+	  }
+	  return r;
+	}
+    }
+    RopeBase *right = RopeLeaf_from_unowned_char_ptr(s, slen);
+    r -> ref_nonnil();
+    __STL_TRY {
+      result = tree_concat(r, right);
+    }
+    __STL_UNWIND(unref(r); unref(right))
+    __stl_assert(1 == result -> refcount);
+    return result;
+}
+#endif /* !__GC */
+
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeBase *
+rope<charT,Alloc>::concat(RopeBase * left, RopeBase * right)
+{
+    if (0 == left) {
+	ref(right);
+	return right;
+    }
+    if (0 == right) {
+	left -> ref_nonnil();
+	return left;
+    }
+    if (RopeBase::leaf == right -> tag) {
+	if (RopeBase::leaf == left -> tag) {
+	  if (right -> size + left -> size <= copy_max) {
+	    return leaf_concat_char_iter((RopeLeaf *)left,
+					 ((RopeLeaf *)right) -> data,
+					 right -> size);
+	  }
+	} else if (RopeBase::concat == left -> tag
+		   && RopeBase::leaf ==
+		      ((RopeConcatenation *)left) -> right -> tag) {
+	  RopeLeaf * leftright =
+		    (RopeLeaf *)(((RopeConcatenation *)left) -> right); 
+	  if (leftright -> size + right -> size <= copy_max) {
+	    RopeBase * leftleft = ((RopeConcatenation *)left) -> left;
+	    RopeBase * rest = leaf_concat_char_iter(leftright,
+					   ((RopeLeaf *)right) -> data,
+					   right -> size);
+	    leftleft -> ref_nonnil();
+	    __STL_TRY {
+	      return(tree_concat(leftleft, rest));
+            }
+	    __STL_UNWIND(unref(leftleft); unref(rest))
+	  }
+	}
+    }
+    left -> ref_nonnil();
+    right -> ref_nonnil();
+    __STL_TRY {
+      return(tree_concat(left, right));
+    }
+    __STL_UNWIND(unref(left); unref(right));
+}
+
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeBase *
+rope<charT,Alloc>::substring(RopeBase * base, size_t start, size_t endp1)
+{
+    if (0 == base) return 0;
+    size_t len = base -> size;
+    size_t adj_endp1;
+    const size_t lazy_threshold = 128;
+    
+    if (endp1 >= len) {
+	if (0 == start) {
+	    base -> ref_nonnil();
+	    return base;
+	} else {
+	    adj_endp1 = len;
+	}
+    } else {
+	adj_endp1 = endp1;
+    }
+    switch(base -> tag) {
+	case RopeBase::concat:
+	    {
+		RopeConcatenation *c = (RopeConcatenation *)base;
+		RopeBase *left = c -> left;
+		RopeBase *right = c -> right;
+		size_t left_len = left -> size;
+		RopeBase * result;
+
+		if (adj_endp1 <= left_len) {
+		    return substring(left, start, endp1);
+		} else if (start >= left_len) {
+		    return substring(right, start - left_len,
+				  adj_endp1 - left_len);
+		}
+		self_destruct_ptr left_result(substring(left, start,
+							left_len));
+		self_destruct_ptr right_result(
+				substring(right, 0, endp1 - left_len));
+		result = concat(left_result, right_result);
+#               ifndef __GC
+		  __stl_assert(1 == result -> refcount);
+#               endif
+		return result;
+	    }
+	case RopeBase::leaf:
+	    {
+		RopeLeaf * l = (RopeLeaf *)base;
+		RopeLeaf * result;
+		size_t result_len;
+		if (start >= adj_endp1) return 0;
+		result_len = adj_endp1 - start;
+		if (result_len > lazy_threshold) goto lazy;
+#               ifdef __GC
+		    const charT *section = l -> data + start;
+		    result = RopeLeaf_from_char_ptr(section, result_len);
+		    result -> c_string = 0;  // Not eos terminated.
+#               else
+		    // We should sometimes create substring node instead.
+		    result = RopeLeaf_from_unowned_char_ptr(
+					l -> data + start, result_len);
+#               endif
+		return result;
+	    }
+	case RopeBase::substringfn:
+	    // Avoid introducing mutiple layers of substring nodes.
+	    {
+		RopeSubstring *old = (RopeSubstring *)base;
+		size_t result_len;
+		if (start >= adj_endp1) return 0;
+		result_len = adj_endp1 - start;
+		if (result_len > lazy_threshold) {
+		    RopeSubstring * space = SAlloc::allocate();
+		    RopeSubstring * result =
+			new(space) RopeSubstring(old -> base,
+						 start + old -> start,
+						 adj_endp1 - start);
+		    return result;
+		} // else fall through:
+	    }
+	case RopeBase::function:
+	    {
+		RopeFunction * f = (RopeFunction *)base;
+		charT *section;
+		size_t result_len;
+		if (start >= adj_endp1) return 0;
+		result_len = adj_endp1 - start;
+
+		if (result_len > lazy_threshold) goto lazy;
+		section = (charT *)
+			DataAlloc::allocate(rounded_up_size(result_len));
+		__STL_TRY {
+		  (*(f -> fn))(start, result_len, section);
+                }
+		__STL_UNWIND(RopeBase::free_string(section, result_len));
+		__cond_store_eos(section[result_len]);
+		return RopeLeaf_from_char_ptr(section, result_len);
+	    }
+    }
+    /*NOTREACHED*/
+    __stl_assert(false);
+  lazy:
+    {
+	// Create substring node.
+	RopeSubstring * space = SAlloc::allocate();
+	RopeSubstring * result = new(space) RopeSubstring(base, start,
+							  adj_endp1 - start);
+	return result;
+    }
+}
+
+template<class charT>
+class __rope_flatten_char_consumer : public __rope_char_consumer<charT> {
+    private:
+	charT * buf_ptr;
+    public:
+	charT * buffer;
+	__rope_flatten_char_consumer(charT * buffer) {
+	    buf_ptr = buffer;
+	};
+	~__rope_flatten_char_consumer() {}
+	bool operator() (const charT* leaf, size_t n) {
+	    uninitialized_copy_n(leaf, n, buf_ptr);
+	    buf_ptr += n;
+	    return true;
+	}
+};
+	    
+template<class charT>
+class __rope_find_char_char_consumer : public __rope_char_consumer<charT> {
+    private:
+	charT pattern;
+    public:
+	size_t count;  // Number of nonmatching characters
+	__rope_find_char_char_consumer(charT p) : pattern(p), count(0) {}
+	~__rope_find_char_char_consumer() {}
+	bool operator() (const charT* leaf, size_t n) {
+	    size_t i;
+	    for (i = 0; i < n; i++) {
+		if (leaf[i] == pattern) {
+		    count += i; return false;
+		}
+	    }
+	    count += n; return true;
+	}
+};
+	    
+template<class charT>
+class __rope_insert_char_consumer : public __rope_char_consumer<charT> {
+    private:
+	typedef ostream insert_ostream;
+	insert_ostream & o;
+    public:
+	charT * buffer;
+	__rope_insert_char_consumer(insert_ostream & writer) : o(writer) {};
+	~__rope_insert_char_consumer() { };
+		// Caller is presumed to own the ostream
+	bool operator() (const charT* leaf, size_t n);
+		// Returns true to continue traversal.
+};
+	    
+template<class charT>
+bool __rope_insert_char_consumer<charT>::operator()
+					(const charT * leaf, size_t n)
+{
+    size_t i;
+    //  We assume that formatting is set up correctly for each element.
+    for (i = 0; i < n; i++) o << leaf[i];
+    return true;
+}
+
+inline bool __rope_insert_char_consumer<char>::operator()
+					(const char * leaf, size_t n)
+{
+    size_t i;
+    for (i = 0; i < n; i++) o.put(leaf[i]);
+    return true;
+}
+
+#if !defined(_MSC_VER) && !defined(__BORLANDC__)
+// I couldn't get this to work work with the VC++ version of basic_ostream.
+inline bool __rope_insert_char_consumer<wchar_t>::operator()
+					(const wchar_t * leaf, size_t n)
+{
+    size_t i;
+    for (i = 0; i < n; i++) o.put(leaf[i]);
+    return true;
+}
+#endif /* !_MSC_VER  && !BORLAND */
+
+template <class charT, class Alloc>
+bool rope<charT, Alloc>::apply_to_pieces(
+				__rope_char_consumer<charT>& c,
+				const RopeBase * r,
+				size_t begin, size_t end)
+{
+    if (0 == r) return true;
+    switch(r -> tag) {
+	case RopeBase::concat:
+	    {
+		RopeConcatenation *conc = (RopeConcatenation *)r;
+		RopeBase *left = conc -> left;
+		size_t left_len = left -> size;
+		if (begin < left_len) {
+		    size_t left_end = min(left_len, end);
+		    if (!apply_to_pieces(c, left, begin, left_end)) {
+			return false;
+		    }
+		}
+		if (end > left_len) {
+		    RopeBase *right = conc -> right;
+		    size_t right_start = max(left_len, begin);
+		    if (!apply_to_pieces(c, right,
+					 right_start - left_len,
+					 end - left_len)) {
+			return false;
+		    }
+		}
+	    }
+	    return true;
+	case RopeBase::leaf:
+	    {
+		RopeLeaf * l = (RopeLeaf *)r;
+		return c(l -> data + begin, end - begin);
+	    }
+	case RopeBase::function:
+	case RopeBase::substringfn:
+	    {
+		RopeFunction * f = (RopeFunction *)r;
+		size_t len = end - begin;
+		bool result;
+		charT * buffer = DataAlloc::allocate(len);
+		__STL_TRY {
+		  (*(f -> fn))(begin, end, buffer);
+		  result = c(buffer, len);
+                  DataAlloc::deallocate(buffer, len);
+                }
+		__STL_UNWIND(DataAlloc::deallocate(buffer, len))
+		return result;
+	    }
+	default:
+	    __stl_assert(false);
+	    /*NOTREACHED*/
+	    return false;
+    }
+}
+
+inline void __rope_fill(ostream& o, size_t n)
+{
+    char f = o.fill();
+    size_t i;
+
+    for (i = 0; i < n; i++) o.put(f);
+}
+    
+
+template <class charT> inline bool __rope_is_simple(charT *) { return false; }
+inline bool __rope_is_simple(char *) { return true; }
+inline bool __rope_is_simple(wchar_t *) { return true; }
+
+
+template<class charT, class Alloc>
+ostream& operator<< (ostream& o, const rope<charT, Alloc>& r)
+{
+    size_t w = o.width();
+    bool left = bool(o.flags() & ios::left);
+    size_t pad_len;
+    size_t rope_len = r.size();
+    __rope_insert_char_consumer<charT> c(o);
+    bool is_simple = __rope_is_simple((charT *)0);
+    
+    if (rope_len < w) {
+	pad_len = w - rope_len;
+    } else {
+	pad_len = 0;
+    }
+    if (!is_simple) o.width(w/rope_len);
+    __STL_TRY {
+      if (is_simple && !left && pad_len > 0) {
+	__rope_fill(o, pad_len);
+      }
+      r.apply_to_pieces(0, r.size(), c);
+      if (is_simple && left && pad_len > 0) {
+	__rope_fill(o, pad_len);
+      }
+      if (!is_simple)
+        o.width(w);
+    }
+    __STL_UNWIND(if (!is_simple) o.width(w))
+    return o;
+}
+
+template <class charT, class Alloc>
+charT *
+rope<charT,Alloc>::flatten(RopeBase * r,
+				 size_t start, size_t len,
+				 charT * buffer)
+{
+    __rope_flatten_char_consumer<charT> c(buffer);
+    apply_to_pieces(c, r, start, start + len);
+    return(buffer + len);
+}
+
+template <class charT, class Alloc>
+size_t
+rope<charT,Alloc>::find(charT pattern, size_t start) const
+{
+    __rope_find_char_char_consumer<charT> c(pattern);
+    apply_to_pieces(c, tree_ptr, start, size());
+    return start + c.count;
+}
+
+template <class charT, class Alloc>
+charT *
+rope<charT,Alloc>::flatten(RopeBase * r, charT * buffer)
+{
+    if (0 == r) return buffer;
+    switch(r -> tag) {
+	case RopeBase::concat:
+	    {
+		RopeConcatenation *c = (RopeConcatenation *)r;
+		RopeBase *left = c -> left;
+		RopeBase *right = c -> right;
+		charT * rest = flatten(left, buffer);
+		return flatten(right, rest);
+	    }
+	case RopeBase::leaf:
+	    {
+		RopeLeaf * l = (RopeLeaf *)r;
+		return copy_n(l -> data, l -> size, buffer).second;
+	    }
+	case RopeBase::function:
+	case RopeBase::substringfn:
+	    // We dont yet do anything with substring nodes.
+	    // This needs to be fixed before ropefiles will work well.
+	    {
+		RopeFunction * f = (RopeFunction *)r;
+		(*(f -> fn))(0, f -> size, buffer);
+		return buffer + f -> size;
+	    }
+	default:
+	    __stl_assert(false);
+	    /*NOTREACHED*/
+	    return 0;
+    }
+}
+
+
+// This needs work for charT != char
+template <class charT, class Alloc>
+void
+rope<charT,Alloc>::dump(RopeBase * r, int indent)
+{
+    for (int i = 0; i < indent; i++) putchar(' ');
+    if (0 == r) {
+	printf("NULL\n"); return;
+    }
+    if (RopeBase::concat == r -> tag) {
+	RopeConcatenation *c = (RopeConcatenation *)r;
+	RopeBase *left = c -> left;
+	RopeBase *right = c -> right;
+
+#       ifdef __GC
+	  printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n",
+		 r, r -> depth, r -> size, r -> is_balanced? "" : "not");
+#       else
+	  printf("Concatenation %p (rc = %ld, depth = %d, len = %ld, %s balanced)\n",
+		 r, r -> refcount, r -> depth, r -> size,
+		 r -> is_balanced? "" : "not");
+#       endif
+	dump(left, indent + 2);
+	dump(right, indent + 2);
+	return;
+    } else {
+	char * kind;
+
+	switch (r -> tag) {
+	    case RopeBase::leaf:
+		kind = "Leaf";
+		break;
+	    case RopeBase::function:
+		kind = "Function";
+		break;
+	    case RopeBase::substringfn:
+		kind = "Function representing substring";
+		break;
+	    default:
+		kind = "(corrupted kind field!)";
+	}
+#       ifdef __GC
+	  printf("%s %p (depth = %d, len = %ld) ",
+		 kind, r, r -> depth, r -> size);
+#       else
+	  printf("%s %p (rc = %ld, depth = %d, len = %ld) ",
+		 kind, r, r -> refcount, r -> depth, r -> size);
+#       endif
+	if (__is_one_byte_char_type((charT *)0)) {
+	    const int max_len = 40;
+	    self_destruct_ptr prefix(substring(r, 0, max_len));
+	    charT buffer[max_len + 1];
+	    bool too_big = r -> size > prefix-> size;
+
+	    flatten(prefix, buffer);
+	    buffer[prefix -> size] = __eos((charT *)0); 
+	    printf("%s%s\n", (char *)buffer, too_big? "...\n" : "\n");
+	} else {
+	    printf("\n");
+	}
+    }
+}
+
+template <class charT, class Alloc>
+const unsigned long
+rope<charT,Alloc>::min_len[__rope_RopeBase<charT,Alloc>::max_rope_depth + 1] = {
+/* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21,
+/* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377,
+/* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181,
+/* 18 */6765, /* 19 */10946, /* 20 */17711, /* 21 */28657, /* 22 */46368,
+/* 23 */75025, /* 24 */121393, /* 25 */196418, /* 26 */317811,
+/* 27 */514229, /* 28 */832040, /* 29 */1346269, /* 30 */2178309,
+/* 31 */3524578, /* 32 */5702887, /* 33 */9227465, /* 34 */14930352,
+/* 35 */24157817, /* 36 */39088169, /* 37 */63245986, /* 38 */102334155,
+/* 39 */165580141, /* 40 */267914296, /* 41 */433494437,
+/* 42 */701408733, /* 43 */1134903170, /* 44 */1836311903,
+/* 45 */2971215073 };
+// These are Fibonacci numbers < 2**32.
+
+template <class charT, class Alloc>
+rope<charT,Alloc>::RopeBase *
+rope<charT,Alloc>::balance(RopeBase *r)
+{
+    RopeBase * forest[RopeBase::max_rope_depth + 1];
+    RopeBase * result = 0;
+    int i;
+    // Inariant:
+    // The concatenation of forest in descending order is equal to r.
+    // forest[i].size >= min_len[i]
+    // forest[i].depth = i
+    // References from forest are included in refcount.
+
+    for (i = 0; i <= RopeBase::max_rope_depth; ++i) forest[i] = 0;
+    __STL_TRY {
+      add_to_forest(r, forest);
+      for (i = 0; i <= RopeBase::max_rope_depth; ++i) if (0 != forest[i]) {
+#	ifndef __GC
+	  self_destruct_ptr old(result);
+#	endif
+	result = concat(forest[i], result);
+	forest[i] -> unref_nonnil();
+#	if !defined(__GC) && defined(__STL_USE_EXCEPTIONS)
+	  forest[i] = 0;
+#	endif
+      }
+    }
+    __STL_UNWIND(for(i = 0; i <= RopeBase::max_rope_depth; i++)
+		 unref(forest[i]))
+    if (result -> depth > RopeBase::max_rope_depth) abort();
+    return(result);
+}
+
+
+template <class charT, class Alloc>
+void
+rope<charT,Alloc>::add_to_forest(RopeBase *r, RopeBase **forest)
+{
+    if (r -> is_balanced) {
+	add_leaf_to_forest(r, forest);
+	return;
+    }
+    __stl_assert(r -> tag == RopeBase::concat);
+    {
+	RopeConcatenation *c = (RopeConcatenation *)r;
+
+	add_to_forest(c -> left, forest);
+	add_to_forest(c -> right, forest);
+    }
+}
+
+
+template <class charT, class Alloc>
+void
+rope<charT,Alloc>::add_leaf_to_forest(RopeBase *r, RopeBase **forest)
+{
+    RopeBase * insertee;   		// included in refcount
+    RopeBase * too_tiny = 0;    	// included in refcount
+    int i;  				// forest[0..i-1] is empty
+    size_t s = r -> size;
+
+    for (i = 0; s >= min_len[i+1]/* not this bucket */; ++i) {
+	if (0 != forest[i]) {
+#	    ifndef __GC
+	      self_destruct_ptr old(too_tiny);
+#	    endif
+	    too_tiny = concat_and_set_balanced(forest[i], too_tiny);
+	    forest[i] -> unref_nonnil();
+	    forest[i] = 0;
+	}
+    }
+    {
+#	ifndef __GC
+	  self_destruct_ptr old(too_tiny);
+#	endif
+	insertee = concat_and_set_balanced(too_tiny, r);
+    }
+    // Too_tiny dead, and no longer included in refcount.
+    // Insertee is live and included.
+    __stl_assert(is_almost_balanced(insertee));
+    __stl_assert(insertee -> depth <= r -> depth + 1);
+    for (;; ++i) {
+	if (0 != forest[i]) {
+#	    ifndef __GC
+	      self_destruct_ptr old(insertee);
+#	    endif
+	    insertee = concat_and_set_balanced(forest[i], insertee);
+	    forest[i] -> unref_nonnil();
+	    forest[i] = 0;
+	    __stl_assert(is_almost_balanced(insertee));
+	}
+	__stl_assert(min_len[i] <= insertee -> size);
+	__stl_assert(forest[i] == 0);
+	if (i == RopeBase::max_rope_depth
+	    || insertee -> size < min_len[i+1]) {
+	    forest[i] = insertee;
+	    // refcount is OK since insertee is now dead.
+	    return;
+	}
+    }
+}
+
+template <class charT, class Alloc>
+charT
+rope<charT,Alloc>::fetch(RopeBase *r, size_type i)
+{
+    __GC_CONST charT * cstr = r -> c_string;
+
+    __stl_assert(i < r -> size);
+    if (0 != cstr) return cstr[i]; 
+    for(;;) {
+      switch(r -> tag) {
+	case RopeBase::concat:
+	    {
+		RopeConcatenation *c = (RopeConcatenation *)r;
+		RopeBase *left = c -> left;
+		size_t left_len = left -> size;
+
+		if (i >= left_len) {
+		    i -= left_len;
+		    r = c -> right;
+		} else {
+		    r = left;
+		}
+	    }
+	    break;
+	case RopeBase::leaf:
+	    {
+		RopeLeaf * l = (RopeLeaf *)r;
+		return l -> data[i];
+	    }
+	case RopeBase::function:
+	case RopeBase::substringfn:
+	    {
+		RopeFunction * f = (RopeFunction *)r;
+		charT result;
+
+		(*(f -> fn))(i, 1, &result);
+		return result;
+	    }
+      }
+    }
+}
+
+# ifndef __GC
+// Return a uniquely referenced character slot for the given
+// position, or 0 if that's not possible.
+template <class charT, class Alloc>
+charT*
+rope<charT,Alloc>::fetch_ptr(RopeBase *r, size_type i)
+{
+    RopeBase * clrstack[RopeBase::max_rope_depth];
+    size_t csptr = 0;
+
+    for(;;) {
+      if (r -> refcount > 1) return 0;
+      switch(r -> tag) {
+	case RopeBase::concat:
+	    {
+		RopeConcatenation *c = (RopeConcatenation *)r;
+		RopeBase *left = c -> left;
+		size_t left_len = left -> size;
+
+		if (c -> c_string != 0) clrstack[csptr++] = c;
+		if (i >= left_len) {
+		    i -= left_len;
+		    r = c -> right;
+		} else {
+		    r = left;
+		}
+	    }
+	    break;
+	case RopeBase::leaf:
+	    {
+		RopeLeaf * l = (RopeLeaf *)r;
+		if (l -> c_string != l -> data && l -> c_string != 0)
+		    clrstack[csptr++] = l;
+		while (csptr > 0) {
+		    -- csptr;
+		    RopeBase * d = clrstack[csptr];
+		    d -> free_c_string();
+		    d -> c_string = 0;
+		}
+		return l -> data + i;
+	    }
+	case RopeBase::function:
+	case RopeBase::substringfn:
+	    return 0;
+      }
+    }
+}
+# endif /* __GC */
+
+// The following could be implemented trivially using
+// lexicographical_compare_3way.
+// We do a little more work to avoid dealing with rope iterators for
+// flat strings.
+template <class charT, class Alloc>
+int
+rope<charT,Alloc>::compare (const RopeBase *left, const RopeBase *right)
+{
+    size_t left_len;
+    size_t right_len;
+
+    if (0 == right) return 0 != left;
+    if (0 == left) return -1;
+    left_len = left -> size;
+    right_len = right -> size;
+    if (RopeBase::leaf == left -> tag) {
+	RopeLeaf *l = (RopeLeaf *) left;
+	if (RopeBase::leaf == right -> tag) {
+	    RopeLeaf *r = (RopeLeaf *) right;
+	    return lexicographical_compare_3way(
+			l -> data, l -> data + left_len,
+			r -> data, r -> data + right_len);
+	} else {
+	    const_iterator rstart(right, 0);
+	    const_iterator rend(right, right_len);
+	    return lexicographical_compare_3way(
+			l -> data, l -> data + left_len,
+			rstart, rend);
+	}
+    } else {
+	const_iterator lstart(left, 0);
+	const_iterator lend(left, left_len);
+	if (RopeBase::leaf == right -> tag) {
+	    RopeLeaf *r = (RopeLeaf *) right;
+	    return lexicographical_compare_3way(
+				   lstart, lend,
+				   r -> data, r -> data + right_len);
+	} else {
+	    const_iterator rstart(right, 0);
+	    const_iterator rend(right, right_len);
+	    return lexicographical_compare_3way(
+				   lstart, lend,
+				   rstart, rend);
+	}
+    }
+}
+
+// Assignment to reference proxies.
+template <class charT, class Alloc>
+__rope_charT_ref_proxy<charT, Alloc>&
+__rope_charT_ref_proxy<charT, Alloc>::operator= (charT c) {
+    RopeBase * old = root -> tree_ptr;
+#   ifndef __GC
+	// First check for the case in which everything is uniquely
+	// referenced.  In that case we can do this destructively.
+	charT * charT_ptr = my_rope::fetch_ptr(old, pos);
+	if (0 != charT_ptr) {
+	    *charT_ptr = c;
+	    return *this;
+	}
+#   endif
+    self_destruct_ptr left(my_rope::substring(old, 0, pos));
+    self_destruct_ptr right(my_rope::substring(old, pos+1, old -> size));
+    self_destruct_ptr result_left(my_rope::destr_concat_char_iter(left, &c, 1));
+#   ifndef __GC
+      __stl_assert(left == result_left || 1 == result_left -> refcount);
+#   endif
+    RopeBase * result =
+		my_rope::concat(result_left, right);
+#   ifndef __GC
+      __stl_assert(1 <= result -> refcount);
+      RopeBase::unref(old);
+#   endif
+    root -> tree_ptr = result;
+    return *this;
+}
+
+template <class charT, class Alloc>
+inline __rope_charT_ref_proxy<charT, Alloc>::operator charT () const
+{
+    if (current_valid) {
+	return current;
+    } else {
+        return my_rope::fetch(root->tree_ptr, pos);
+    }
+}
+template <class charT, class Alloc>
+__rope_charT_ptr_proxy<charT, Alloc>
+__rope_charT_ref_proxy<charT, Alloc>::operator& () const {
+    return __rope_charT_ptr_proxy<charT, Alloc>(*this);
+}
+
+template <class charT, class Alloc>
+rope<charT, Alloc>::rope(size_t n, charT c)
+{
+    rope result;
+    const size_t exponentiate_threshold = 32;
+    size_t exponent;
+    size_t rest;
+    charT *rest_buffer;
+    RopeBase * remainder;
+    rope remainder_rope;
+
+    if (0 == n) { tree_ptr = 0; return; }
+    exponent = n / exponentiate_threshold;
+    rest = n % exponentiate_threshold;
+    if (0 == rest) {
+	remainder = 0;
+    } else {
+	rest_buffer = DataAlloc::allocate(rounded_up_size(rest));
+	uninitialized_fill_n(rest_buffer, rest, c);
+	__cond_store_eos(rest_buffer[rest]);
+	__STL_TRY {
+	    remainder = RopeLeaf_from_char_ptr(rest_buffer, rest);
+        }
+	__STL_UNWIND(RopeBase::free_string(rest_buffer, rest))
+    }
+    remainder_rope.tree_ptr = remainder;
+    if (exponent != 0) {
+	charT * base_buffer =
+		DataAlloc::allocate(rounded_up_size(exponentiate_threshold));
+	RopeLeaf * base_leaf;
+	rope base_rope;
+	uninitialized_fill_n(base_buffer, exponentiate_threshold, c);
+	__cond_store_eos(base_buffer[exponentiate_threshold]);
+	__STL_TRY {
+          base_leaf = RopeLeaf_from_char_ptr(base_buffer,
+                                             exponentiate_threshold);
+        }
+	__STL_UNWIND(RopeBase::free_string(base_buffer, exponentiate_threshold))
+	base_rope.tree_ptr = base_leaf;
+ 	if (1 == exponent) {
+	  result = base_rope;
+#         ifndef __GC
+	    __stl_assert(1 == result -> tree_ptr -> refcount);
+#         endif
+	} else {
+	  result = power(base_rope, exponent, concat_fn());
+	}
+	if (0 != remainder) {
+	  result += remainder_rope;
+	}
+    } else {
+	result = remainder_rope;
+    }
+    tree_ptr = result.tree_ptr;
+    tree_ptr -> ref_nonnil();
+}
+
+template<class charT, class Alloc> charT rope<charT,Alloc>::empty_c_str[1];
+
+# ifdef __STL_PTHREADS
+    template<class charT, class Alloc>
+    pthread_mutex_t rope<charT,Alloc>::swap_lock = PTHREAD_MUTEX_INITIALIZER;
+# endif
+
+template<class charT, class Alloc>
+const charT * rope<charT,Alloc>::c_str() const {
+    if (0 == tree_ptr) {
+        empty_c_str[0] = __eos((charT *)0);  // Possibly redundant,
+					     // but probably fast.
+        return empty_c_str;
+    }
+    __GC_CONST charT * old_c_string = tree_ptr -> c_string;
+    if (0 != old_c_string) return(old_c_string);
+    size_t s = size();
+    charT * result = DataAlloc::allocate(s + 1);
+    flatten(tree_ptr, result);
+    result[s] = __eos((charT *)0);
+#   ifdef __GC
+	tree_ptr -> c_string = result;
+#   else
+      if ((old_c_string = atomic_swap(&(tree_ptr -> c_string), result)) != 0) {
+	// It must have been added in the interim.  Hence it had to have been
+	// separately allocated.  Deallocate the old copy, since we just
+	// replaced it.
+	destroy(old_c_string, old_c_string + s + 1);
+	DataAlloc::deallocate(old_c_string, s + 1);
+      }
+#   endif
+    return(result);
+}
+
+template<class charT, class Alloc>
+const charT * rope<charT,Alloc>::replace_with_c_str() {
+    if (0 == tree_ptr) {
+        empty_c_str[0] = __eos((charT *)0);
+        return empty_c_str;
+    }
+    __GC_CONST charT * old_c_string = tree_ptr -> c_string;
+    if (RopeBase::leaf == tree_ptr -> tag && 0 != old_c_string) {
+	return(old_c_string);
+    }
+    size_t s = size();
+    charT * result = DataAlloc::allocate(rounded_up_size(s));
+    flatten(tree_ptr, result);
+    result[s] = __eos((charT *)0);
+    tree_ptr -> unref_nonnil();
+    tree_ptr = RopeLeaf_from_char_ptr(result, s);
+    return(result);
+}
+
+// Algorithm specializations.  More should be added.
+
+#ifndef _MSC_VER
+// I couldn't get this to work with VC++
+template<class charT,class Alloc>
+void
+__rope_rotate(__rope_iterator<charT,Alloc> first,
+              __rope_iterator<charT,Alloc> middle,
+              __rope_iterator<charT,Alloc> last) {
+    __stl_assert(first.container() == middle.container()
+                 && middle.container() == last.container());
+    rope<charT,Alloc>& r(first.container());
+    rope<charT,Alloc> prefix = r.substr(0, first.index());
+    rope<charT,Alloc> suffix = r.substr(last.index(), r.size() - last.index());
+    rope<charT,Alloc> part1 = r.substr(middle.index(),
+                                       last.index() - middle.index());
+    rope<charT,Alloc> part2 = r.substr(first.index(),
+                                       middle.index() - first.index());
+    r = prefix;
+    r += part1;
+    r += part2;
+    r += suffix;
+}
+
+inline void rotate(__rope_iterator<char,__ALLOC> first,
+                   __rope_iterator<char,__ALLOC> middle,
+                   __rope_iterator<char,__ALLOC> last) {
+    __rope_rotate(first, middle, last);
+}
+
+# if 0
+// Probably not useful for several reasons:
+// - for SGIs 7.1 compiler and probably some others,
+//   this forces lots of rope<wchar_t, ...> instantiations, creating a
+//   code bloat and compile time problem.  (Fixed in 7.2.)
+// - wchar_t is 4 bytes wide on most UNIX platforms, making it unattractive
+//   for unicode strings.  Unsigned short may be a better character
+//   type.
+inline void rotate(__rope_iterator<wchar_t,__ALLOC> first,
+                   __rope_iterator<wchar_t,__ALLOC> middle,
+                   __rope_iterator<wchar_t,__ALLOC> last) {
+    __rope_rotate(first, middle, last);
+}
+# endif
+#endif /* _MSC_VER */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/rx.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/rx.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/rx.h	(revision 18)
@@ -0,0 +1,3754 @@
+#if !defined(RXH) || defined(RX_WANT_SE_DEFS)
+#define RXH
+
+/*	Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of the librx library.
+
+Librx is free software; you can redistribute it and/or modify it under
+the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+Librx is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this software; see the file COPYING.LIB.  If not,
+write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA
+02139, USA.  */
+/*  t. lord	Wed Sep 23 18:20:57 1992	*/
+
+
+
+
+
+
+
+
+
+#ifndef RX_WANT_SE_DEFS
+
+/* This page: Bitsets */
+
+#ifndef RX_subset
+typedef unsigned int RX_subset;
+#define RX_subset_bits	(32)
+#define RX_subset_mask	(RX_subset_bits - 1)
+#endif
+
+typedef RX_subset * rx_Bitset;
+
+#ifdef __STDC__
+typedef void (*rx_bitset_iterator) (void *, int member_index);
+#else
+typedef void (*rx_bitset_iterator) ();
+#endif
+
+#define rx_bitset_subset(N)  ((N) / RX_subset_bits)
+#define rx_bitset_subset_val(B,N)  ((B)[rx_bitset_subset(N)])
+#define RX_bitset_access(B,N,OP) \
+  ((B)[rx_bitset_subset(N)] OP rx_subset_singletons[(N) & RX_subset_mask])
+#define RX_bitset_member(B,N)   RX_bitset_access(B, N, &)
+#define RX_bitset_enjoin(B,N)   RX_bitset_access(B, N, |=)
+#define RX_bitset_remove(B,N)   RX_bitset_access(B, N, &= ~)
+#define RX_bitset_toggle(B,N)   RX_bitset_access(B, N, ^= )
+#define rx_bitset_numb_subsets(N) (((N) + RX_subset_bits - 1) / RX_subset_bits)
+#define rx_sizeof_bitset(N)	(rx_bitset_numb_subsets(N) * sizeof(RX_subset))
+
+
+
+
+/* This page: Splay trees. */
+
+#ifdef __STDC__
+typedef int (*rx_sp_comparer) (void * a, void * b);
+#else
+typedef int (*rx_sp_comparer) ();
+#endif
+
+struct rx_sp_node 
+{
+  void * key;
+  void * data;
+  struct rx_sp_node * kids[2];
+};
+
+#ifdef __STDC__
+typedef void (*rx_sp_key_data_freer) (struct rx_sp_node *);
+#else
+typedef void (*rx_sp_key_data_freer) ();
+#endif
+
+
+
+/* giant inflatable hash trees */
+
+struct rx_hash_item
+{
+  struct rx_hash_item * next_same_hash;
+  struct rx_hash * table;
+  unsigned long hash;
+  void * data;
+  void * binding;
+};
+
+struct rx_hash
+{
+  struct rx_hash * parent;
+  int refs;
+  struct rx_hash * children[13];
+  struct rx_hash_item * buckets [13];
+  int bucket_size [13];
+};
+
+struct rx_hash_rules;
+
+#ifdef __STDC__
+/* should return like == */
+typedef int (*rx_hash_eq)(void *, void *);
+typedef struct rx_hash * (*rx_alloc_hash)(struct rx_hash_rules *);
+typedef void (*rx_free_hash)(struct rx_hash *,
+			    struct rx_hash_rules *);
+typedef struct rx_hash_item * (*rx_alloc_hash_item)(struct rx_hash_rules *,
+						    void *);
+typedef void (*rx_free_hash_item)(struct rx_hash_item *,
+				 struct rx_hash_rules *);
+#else
+typedef int (*rx_hash_eq)();
+typedef struct rx_hash * (*rx_alloc_hash)();
+typedef void (*rx_free_hash)();
+typedef struct rx_hash_item * (*rx_alloc_hash_item)();
+typedef void (*rx_free_hash_item)();
+#endif
+
+struct rx_hash_rules
+{
+  rx_hash_eq eq;
+  rx_alloc_hash hash_alloc;
+  rx_free_hash free_hash;
+  rx_alloc_hash_item hash_item_alloc;
+  rx_free_hash_item free_hash_item;
+};
+
+
+
+/* Forward declarations */
+
+struct rx_cache;
+struct rx_superset;
+struct rx;
+struct rx_se_list;
+
+
+
+
+/* 
+ * GLOSSARY
+ *
+ * regexp
+ * regular expression
+ * expression
+ * pattern - a `regular' expression.  The expression
+ *       need not be formally regular -- it can contain
+ *       constructs that don't correspond to purely regular
+ *       expressions.
+ *
+ * buffer
+ * string - the string (or strings) being searched or matched.
+ *
+ * pattern buffer - a structure of type `struct re_pattern_buffer'
+ *       This in turn contains a `struct rx', which holds the
+ *       NFA compiled from a pattern, as well as some of the state
+ *       of a matcher using the pattern.
+ *
+ * NFA - nondeterministic finite automata.  Some people
+ *       use this term to a member of the class of 
+ *       regular automata (those corresponding to a regular
+ *       language).  However, in this code, the meaning is
+ *       more general.  The automata used by Rx are comperable
+ *       in power to what are usually called `push down automata'.
+ *
+ *       Two NFA are built by rx for every pattern.  One is built
+ *       by the compiler.  The other is built from the first, on
+ *       the fly, by the matcher.  The latter is called the `superstate
+ *       NFA' because its states correspond to sets of states from
+ *       the first NFA.  (Joe Keane gets credit for the name
+ *       `superstate NFA').
+ *
+ * NFA edges
+ * epsilon edges
+ * side-effect edges - The NFA compiled from a pattern can have three
+ *       kinds of edges.  Epsilon edges can be taken freely anytime
+ *       their source state is reached.  Character set edges can be
+ *       taken when their source state is reached and when the next 
+ *       character in the buffer is a member of the set.  Side effect
+ *       edges imply a transition that can only be taken after the
+ *       indicated side effect has been successfully accomplished.
+ *       Some examples of side effects are:
+ *
+ *		Storing the current match position to record the
+ *              location of a parentesized subexpression.
+ *
+ *              Advancing the matcher over N characters if they
+ *              match the N characters previously matched by a 
+ *              parentesized subexpression.
+ *
+ *       Both of those kinds of edges occur in the NFA generated
+ *       by the pattern:  \(.\)\1
+ *
+ *       Epsilon and side effect edges are similar.  Unfortunately,
+ *       some of the code uses the name `epsilon edge' to mean
+ *       both epsilon and side effect edges.  For example,  the
+ *       function has_non_idempotent_epsilon_path computes the existance
+ *       of a non-trivial path containing only a mix of epsilon and
+ *       side effect edges.  In that case `nonidempotent epsilon' is being
+ *       used to mean `side effect'.
+ */
+
+
+
+
+
+
+/* LOW LEVEL PATTERN BUFFERS */
+
+/* Suppose that from some NFA state, more than one path through
+ * side-effect edges is possible.  In what order should the paths
+ * be tried?  A function of type rx_se_list_order answers that
+ * question.  It compares two lists of side effects, and says
+ * which list comes first.
+ */
+ 
+#ifdef __STDC__
+typedef int (*rx_se_list_order) (struct rx *,
+				 struct rx_se_list *, 
+				 struct rx_se_list *);
+#else
+typedef int (*rx_se_list_order) ();
+#endif
+
+
+
+/* Struct RX holds a compiled regular expression - that is, an nfa
+ * ready to be converted on demand to a more efficient superstate nfa.
+ * This is for the low level interface.  The high-level interfaces enclose
+ * this in a `struct re_pattern_buffer'.  
+ */
+struct rx
+{
+  /* The compiler assigns a unique id to every pattern.
+   * Like sequence numbers in X, there is a subtle bug here
+   * if you use Rx in a system that runs for a long time.
+   * But, because of the way the caches work out, it is almost
+   * impossible to trigger the Rx version of this bug.
+   *
+   * The id is used to validate superstates found in a cache
+   * of superstates.  It isn't sufficient to let a superstate
+   * point back to the rx for which it was compiled -- the caller
+   * may be re-using a `struct rx' in which case the superstate
+   * is not really valid.  So instead, superstates are validated
+   * by checking the sequence number of the pattern for which
+   * they were built.
+   */
+  int rx_id;
+
+  /* This is memory mgt. state for superstates.  This may be 
+   * shared by more than one struct rx.
+   */
+  struct rx_cache * cache;
+
+  /* Every regex defines the size of its own character set. 
+   * A superstate has an array of this size, with each element
+   * a `struct rx_inx'.  So, don't make this number too large.
+   * In particular, don't make it 2^16.
+   */
+  int local_cset_size;
+
+  /* After the NFA is built, it is copied into a contiguous region
+   * of memory (mostly for compatability with GNU regex).
+   * Here is that region, and it's size:
+   */
+  void * buffer;
+  unsigned long allocated;
+
+  /* Clients of RX can ask for some extra storage in the space pointed
+   * to by BUFFER.  The field RESERVED is an input parameter to the
+   * compiler.  After compilation, this much space will be available 
+   * at (buffer + allocated - reserved)
+   */
+  unsigned long reserved;
+
+  /* --------- The remaining fields are for internal use only. --------- */
+  /* --------- But! they must be initialized to 0.	       --------- */
+
+  /* NODEC is the number of nodes in the NFA with non-epsilon
+   * transitions. 
+   */
+  int nodec;
+
+  /* EPSNODEC is the number of nodes with only epsilon transitions. */
+  int epsnodec;
+
+  /* The sum (NODEC + EPSNODEC) is the total number of states in the
+   * compiled NFA.
+   */
+
+  /* Lists of side effects as stored in the NFA are `hash consed'..meaning
+   * that lists with the same elements are ==.  During compilation, 
+   * this table facilitates hash-consing.
+   */
+  struct rx_hash se_list_memo;
+
+  /* Lists of NFA states are also hashed. 
+   */
+  struct rx_hash set_list_memo;
+
+
+
+
+  /* The compiler and matcher must build a number of instruction frames.
+   * The format of these frames is fixed (c.f. struct rx_inx).  The values
+   * of the instructions is not fixed.
+   *
+   * An enumerated type (enum rx_opcode) defines the set of instructions
+   * that the compiler or matcher might generate.  When filling an instruction
+   * frame, the INX field is found by indexing this instruction table
+   * with an opcode:
+   */
+  void ** instruction_table;
+
+  /* The list of all states in an NFA.
+   * During compilation, the NEXT field of NFA states links this list.
+   * After compilation, all the states are compacted into an array,
+   * ordered by state id numbers.  At that time, this points to the base 
+   * of that array.
+   */
+  struct rx_nfa_state *nfa_states;
+
+  /* Every nfa begins with one distinguished starting state:
+   */
+  struct rx_nfa_state *start;
+
+  /* This orders the search through super-nfa paths.
+   * See the comment near the typedef of rx_se_list_order.
+   */
+  rx_se_list_order se_list_cmp;
+
+  struct rx_superset * start_set;
+};
+
+
+
+
+
+/* SYNTAX TREES */
+
+/* Compilation is in stages.  
+ *
+ * In the first stage, a pattern specified by a string is 
+ * translated into a syntax tree.  Later stages will convert
+ * the syntax tree into an NFA optimized for conversion to a
+ * superstate-NFA.
+ *
+ * This page is about syntax trees.
+ */
+
+enum rexp_node_type
+{
+  r_cset,			/* Match from a character set. `a' or `[a-z]'*/
+  r_concat,			/* Concat two subexpressions.   `ab' */
+  r_alternate,			/* Choose one of two subexpressions. `a\|b' */
+  r_opt,			/* Optional subexpression. `a?' */
+  r_star,			/* Repeated subexpression. `a*' */
+
+
+  /* A 2phase-star is a variation on a repeated subexpression.
+   * In this case, there are two subexpressions.  The first, if matched,
+   * begins a repitition (otherwise, the whole expression is matches the
+   * empth string).  
+   * 
+   * After matching the first subexpression, a 2phase star either finishes,
+   * or matches the second subexpression.  If the second subexpression is
+   * matched, then the whole construct repeats.
+   *
+   * 2phase stars are used in two circumstances.  First, they
+   * are used as part of the implementation of POSIX intervals (counted
+   * repititions).  Second, they are used to implement proper star
+   * semantics when the repeated subexpression contains paths of
+   * only side effects.  See rx_compile for more information.
+   */
+  r_2phase_star,
+
+
+  /* c.f. "typedef void * rx_side_effect" */
+  r_side_effect,
+
+  /* This is an extension type:  It is for transient use in source->source
+   * transformations (implemented over syntax trees).
+   */
+  r_data
+};
+
+/* A side effect is a matcher-specific action associated with
+ * transitions in the NFA.  The details of side effects are up
+ * to the matcher.  To the compiler and superstate constructors
+ * side effects are opaque:
+ */
+
+typedef void * rx_side_effect;
+
+/* Nodes in a syntax tree are of this type:
+ */
+struct rexp_node
+{
+  enum rexp_node_type type;
+  union
+  {
+    rx_Bitset cset;
+    rx_side_effect side_effect;
+    struct
+      {
+	struct rexp_node *left;
+	struct rexp_node *right;
+      } pair;
+    void * data;
+  } params;
+};
+
+
+
+
+/* NFA
+ *
+ * A syntax tree is compiled into an NFA.  This page defines the structure
+ * of that NFA.
+ */
+
+struct rx_nfa_state
+{
+  /* These are kept in a list as the NFA is being built. */
+  struct rx_nfa_state *next;
+
+  /* After the NFA is built, states are given integer id's.
+   * States whose outgoing transitions are all either epsilon or 
+   * side effect edges are given ids less than 0.  Other states
+   * are given successive non-negative ids starting from 0.
+   */
+  int id;
+
+  /* The list of NFA edges that go from this state to some other. */
+  struct rx_nfa_edge *edges;
+
+  /* If you land in this state, then you implicitly land
+   * in all other states reachable by only epsilon translations.
+   * Call the set of maximal paths to such states the epsilon closure
+   * of this state.
+   *
+   * There may be other states that are reachable by a mixture of
+   * epsilon and side effect edges.  Consider the set of maximal paths
+   * of that sort from this state.  Call it the epsilon-side-effect
+   * closure of the state.
+   * 
+   * The epsilon closure of the state is a subset of the epsilon-side-
+   * effect closure.  It consists of all the paths that contain 
+   * no side effects -- only epsilon edges.
+   * 
+   * The paths in the epsilon-side-effect closure  can be partitioned
+   * into equivalance sets. Two paths are equivalant if they have the
+   * same set of side effects, in the same order.  The epsilon-closure
+   * is one of these equivalance sets.  Let's call these equivalance
+   * sets: observably equivalant path sets.  That name is chosen
+   * because equivalance of two paths means they cause the same side
+   * effects -- so they lead to the same subsequent observations other
+   * than that they may wind up in different target states.
+   *
+   * The superstate nfa, which is derived from this nfa, is based on
+   * the observation that all of the paths in an observably equivalant
+   * path set can be explored at the same time, provided that the
+   * matcher keeps track not of a single nfa state, but of a set of
+   * states.   In particular, after following all the paths in an
+   * observably equivalant set, you wind up at a set of target states.
+   * That set of target states corresponds to one state in the
+   * superstate NFA.
+   *
+   * Staticly, before matching begins, it is convenient to analyze the
+   * nfa.  Each state is labeled with a list of the observably
+   * equivalant path sets who's union covers all the
+   * epsilon-side-effect paths beginning in this state.  This list is
+   * called the possible futures of the state.
+   *
+   * A trivial example is this NFA:
+   *             s1
+   *         A  --->  B
+   *
+   *             s2  
+   *            --->  C
+   *
+   *             epsilon           s1
+   *            --------->  D   ------> E
+   * 
+   * 
+   * In this example, A has two possible futures.
+   * One invokes the side effect `s1' and contains two paths,
+   * one ending in state B, the other in state E.
+   * The other invokes the side effect `s2' and contains only
+   * one path, landing in state C.
+   */
+  struct rx_possible_future *futures;
+
+
+  /* There are exactly two distinguished states in every NFA: */
+  unsigned int is_final:1;
+  unsigned int is_start:1;
+
+  /* These are used during NFA construction... */
+  unsigned int eclosure_needed:1;
+  unsigned int mark:1;
+};
+
+
+/* An edge in an NFA is typed: */
+enum rx_nfa_etype
+{
+  /* A cset edge is labled with a set of characters one of which
+   * must be matched for the edge to be taken.
+   */
+  ne_cset,
+
+  /* An epsilon edge is taken whenever its starting state is
+   * reached. 
+   */
+  ne_epsilon,
+
+  /* A side effect edge is taken whenever its starting state is
+   * reached.  Side effects may cause the match to fail or the
+   * position of the matcher to advance.
+   */
+  ne_side_effect		/* A special kind of epsilon. */
+};
+
+struct rx_nfa_edge
+{
+  struct rx_nfa_edge *next;
+  enum rx_nfa_etype type;
+  struct rx_nfa_state *dest;
+  union
+  {
+    rx_Bitset cset;
+    rx_side_effect side_effect;
+  } params;
+};
+
+
+
+/* A possible future consists of a list of side effects
+ * and a set of destination states.  Below are their
+ * representations.  These structures are hash-consed which
+ * means that lists with the same elements share a representation
+ * (their addresses are ==).
+ */
+
+struct rx_nfa_state_set
+{
+  struct rx_nfa_state * car;
+  struct rx_nfa_state_set * cdr;
+};
+
+struct rx_se_list
+{
+  rx_side_effect car;
+  struct rx_se_list * cdr;
+};
+
+struct rx_possible_future
+{
+  struct rx_possible_future *next;
+  struct rx_se_list * effects;
+  struct rx_nfa_state_set * destset;
+};
+
+
+
+
+/* This begins the description of the superstate NFA.
+ *
+ * The superstate NFA corresponds to the NFA in these ways:
+ *
+ * Every superstate NFA states SUPER correspond to sets of NFA states,
+ * nfa_states(SUPER).
+ *
+ * Superstate edges correspond to NFA paths.
+ *
+ * The superstate has no epsilon transitions;
+ * every edge has a character label, and a (possibly empty) side
+ * effect label.   The side effect label corresponds to a list of
+ * side effects that occur in the NFA.  These parts are referred
+ * to as:   superedge_character(EDGE) and superedge_sides(EDGE).
+ *
+ * For a superstate edge EDGE starting in some superstate SUPER,
+ * the following is true (in pseudo-notation :-):
+ *
+ *       exists DEST in nfa_states s.t. 
+ *         exists nfaEDGE in nfa_edges s.t.
+ *                 origin (nfaEDGE) == DEST
+ *              && origin (nfaEDGE) is a member of nfa_states(SUPER)
+ *              && exists PF in possible_futures(dest(nfaEDGE)) s.t.
+ * 	                sides_of_possible_future (PF) == superedge_sides (EDGE)
+ *
+ * also:
+ *
+ *      let SUPER2 := superedge_destination(EDGE)
+ *          nfa_states(SUPER2)
+ *           == union of all nfa state sets S s.t.
+ *                          exists PF in possible_futures(dest(nfaEDGE)) s.t.
+ * 	                       sides_of_possible_future (PF) == superedge_sides (EDGE)
+ *                          && S == dests_of_possible_future (PF) }
+ *
+ * Or in english, every superstate is a set of nfa states.  A given
+ * character and a superstate implies many transitions in the NFA --
+ * those that begin with an edge labeled with that character from a
+ * state in the set corresponding to the superstate.
+ * 
+ * The destinations of those transitions each have a set of possible
+ * futures.  A possible future is a list of side effects and a set of
+ * destination NFA states.  Two sets of possible futures can be
+ * `merged' by combining all pairs of possible futures that have the
+ * same side effects.  A pair is combined by creating a new future
+ * with the same side effect but the union of the two destination sets.
+ * In this way, all the possible futures suggested by a superstate
+ * and a character can be merged into a set of possible futures where
+ * no two elements of the set have the same set of side effects.
+ *
+ * The destination of a possible future, being a set of NFA states, 
+ * corresponds to a supernfa state.  So, the merged set of possible
+ * futures we just created can serve as a set of edges in the
+ * supernfa.
+ *
+ * The representation of the superstate nfa and the nfa is critical.
+ * The nfa has to be compact, but has to facilitate the rapid
+ * computation of missing superstates.  The superstate nfa has to 
+ * be fast to interpret, lazilly constructed, and bounded in space.
+ *
+ * To facilitate interpretation, the superstate data structures are 
+ * peppered with `instruction frames'.  There is an instruction set
+ * defined below which matchers using the supernfa must be able to
+ * interpret.
+ *
+ * We'd like to make it possible but not mandatory to use code
+ * addresses to represent instructions (c.f. gcc's computed goto).
+ * Therefore, we define an enumerated type of opcodes, and when
+ * writing one of these instructions into a data structure, use
+ * the opcode as an index into a table of instruction values.
+ * 
+ * Here are the opcodes that occur in the superstate nfa:
+ */
+ 
+
+/* Every superstate contains a table of instruction frames indexed 
+ * by characters.  A normal `move' in a matcher is to fetch the next
+ * character and use it as an index into a superstates transition
+ * table.
+ *
+ * In the fasted case, only one edge follows from that character.
+ * In other cases there is more work to do.
+ * 
+ * The descriptions of the opcodes refer to data structures that are
+ * described further below. 
+ */
+
+enum rx_opcode
+{
+  /* 
+   * BACKTRACK_POINT is invoked when a character transition in 
+   * a superstate leads to more than one edge.  In that case,
+   * the edges have to be explored independently using a backtracking
+   * strategy.
+   *
+   * A BACKTRACK_POINT instruction is stored in a superstate's 
+   * transition table for some character when it is known that that
+   * character crosses more than one edge.  On encountering this
+   * instruction, the matcher saves enough state to backtrack to this
+   * point in the match later.
+   */
+  rx_backtrack_point = 0,	/* data is (struct transition_class *) */
+
+  /* 
+   * RX_DO_SIDE_EFFECTS evaluates the side effects of an epsilon path.
+   * There is one occurence of this instruction per rx_distinct_future.
+   * This instruction is skipped if a rx_distinct_future has no side effects.
+   */
+  rx_do_side_effects = rx_backtrack_point + 1,
+
+  /* data is (struct rx_distinct_future *) */
+
+  /* 
+   * RX_CACHE_MISS instructions are stored in rx_distinct_futures whose
+   * destination superstate has been reclaimed (or was never built).
+   * It recomputes the destination superstate.
+   * RX_CACHE_MISS is also stored in a superstate transition table before
+   * any of its edges have been built.
+   */
+  rx_cache_miss = rx_do_side_effects + 1,
+  /* data is (struct rx_distinct_future *) */
+
+  /* 
+   * RX_NEXT_CHAR is called to consume the next character and take the
+   * corresponding transition.  This is the only instruction that uses 
+   * the DATA field of the instruction frame instead of DATA_2.
+   * (see EXPLORE_FUTURE in regex.c).
+   */
+  rx_next_char = rx_cache_miss + 1, /* data is (struct superstate *) */
+
+  /* RX_BACKTRACK indicates that a transition fails.
+   */
+  rx_backtrack = rx_next_char + 1, /* no data */
+
+  /* 
+   * RX_ERROR_INX is stored only in places that should never be executed.
+   */
+  rx_error_inx = rx_backtrack + 1, /* Not supposed to occur. */
+
+  rx_num_instructions = rx_error_inx + 1
+};
+
+/* An id_instruction_table holds the values stored in instruction
+ * frames.  The table is indexed by the enums declared above.
+ */
+extern void * rx_id_instruction_table[rx_num_instructions];
+
+/* The heart of the matcher is a `word-code-interpreter' 
+ * (like a byte-code interpreter, except that instructions
+ * are a full word wide).
+ *
+ * Instructions are not stored in a vector of code, instead,
+ * they are scattered throughout the data structures built
+ * by the regexp compiler and the matcher.  One word-code instruction,
+ * together with the arguments to that instruction, constitute
+ * an instruction frame (struct rx_inx).
+ *
+ * This structure type is padded by hand to a power of 2 because
+ * in one of the dominant cases, we dispatch by indexing a table
+ * of instruction frames.  If that indexing can be accomplished
+ * by just a shift of the index, we're happy.
+ *
+ * Instructions take at most one argument, but there are two
+ * slots in an instruction frame that might hold that argument.
+ * These are called data and data_2.  The data slot is only
+ * used for one instruction (RX_NEXT_CHAR).  For all other 
+ * instructions, data should be set to 0.
+ *
+ * RX_NEXT_CHAR is the most important instruction by far.
+ * By reserving the data field for its exclusive use, 
+ * instruction dispatch is sped up in that case.  There is
+ * no need to fetch both the instruction and the data,
+ * only the data is needed.  In other words, a `cycle' begins
+ * by fetching the field data.  If that is non-0, then it must
+ * be the destination state of a next_char transition, so
+ * make that value the current state, advance the match position
+ * by one character, and start a new cycle.  On the other hand,
+ * if data is 0, fetch the instruction and do a more complicated
+ * dispatch on that.
+ */
+
+struct rx_inx 
+{
+  void * data;
+  void * data_2;
+  void * inx;
+  void * fnord;
+};
+
+#ifndef RX_TAIL_ARRAY
+#define RX_TAIL_ARRAY  1
+#endif
+
+/* A superstate corresponds to a set of nfa states.  Those sets are
+ * represented by STRUCT RX_SUPERSET.  The constructors
+ * guarantee that only one (shared) structure is created for a given set.
+ */
+struct rx_superset
+{
+  int refs;			/* This is a reference counted structure. */
+
+  /* We keep these sets in a cache because (in an unpredictable way),
+   * the same set is often created again and again.  But that is also
+   * problematic -- compatibility with POSIX and GNU regex requires
+   * that we not be able to tell when a program discards a particular
+   * NFA (thus invalidating the supersets created from it).
+   *
+   * But when a cache hit appears to occur, we will have in hand the
+   * nfa for which it may have happened.  That is why every nfa is given
+   * its own sequence number.  On a cache hit, the cache is validated
+   * by comparing the nfa sequence number to this field:
+   */
+  int id;
+
+  struct rx_nfa_state * car;	/* May or may not be a valid addr. */
+  struct rx_superset * cdr;
+
+  /* If the corresponding superstate exists: */
+  struct rx_superstate * superstate;
+
+
+  /* There is another bookkeeping problem.  It is expensive to 
+   * compute the starting nfa state set for an nfa.  So, once computed,
+   * it is cached in the `struct rx'.
+   *
+   * But, the state set can be flushed from the superstate cache.
+   * When that happens, we can't know if the corresponding `struct rx'
+   * is still alive or if it has been freed or re-used by the program.
+   * So, the cached pointer to this set in a struct rx might be invalid
+   * and we need a way to validate it.
+   *
+   * Fortunately, even if this set is flushed from the cache, it is
+   * not freed.  It just goes on the free-list of supersets.
+   * So we can still examine it.  
+   *
+   * So to validate a starting set memo, check to see if the
+   * starts_for field still points back to the struct rx in question,
+   * and if the ID matches the rx sequence number.
+   */
+  struct rx * starts_for;
+
+  /* This is used to link into a hash bucket so these objects can
+   * be `hash-consed'.
+   */
+  struct rx_hash_item hash_item;
+};
+
+#define rx_protect_superset(RX,CON) (++(CON)->refs)
+
+/* The terminology may be confusing (rename this structure?).
+ * Every character occurs in at most one rx_super_edge per super-state.
+ * But, that structure might have more than one option, indicating a point
+ * of non-determinism. 
+ *
+ * In other words, this structure holds a list of superstate edges
+ * sharing a common starting state and character label.  The edges
+ * are in the field OPTIONS.  All superstate edges sharing the same
+ * starting state and character are in this list.
+ */
+struct rx_super_edge
+{
+  struct rx_super_edge *next;
+  struct rx_inx rx_backtrack_frame;
+  int cset_size;
+  rx_Bitset cset;
+  struct rx_distinct_future *options;
+};
+
+/* A superstate is a set of nfa states (RX_SUPERSET) along
+ * with a transition table.  Superstates are built on demand and reclaimed
+ * without warning.  To protect a superstate from this ghastly fate,
+ * use LOCK_SUPERSTATE. 
+ */
+struct rx_superstate
+{
+  int rx_id;			/* c.f. the id field of rx_superset */
+  int locks;			/* protection from reclamation */
+
+  /* Within a superstate cache, all the superstates are kept in a big
+   * queue.  The tail of the queue is the state most likely to be
+   * reclaimed.  The *recyclable fields hold the queue position of 
+   * this state.
+   */
+  struct rx_superstate * next_recyclable;
+  struct rx_superstate * prev_recyclable;
+
+  /* The supernfa edges that exist in the cache and that have
+   * this state as their destination are kept in this list:
+   */
+  struct rx_distinct_future * transition_refs;
+
+  /* The list of nfa states corresponding to this superstate: */
+  struct rx_superset * contents;
+
+  /* The list of edges in the cache beginning from this state. */
+  struct rx_super_edge * edges;
+
+  /* A tail of the recyclable queue is marked as semifree.  A semifree
+   * state has no incoming next_char transitions -- any transition
+   * into a semifree state causes a complex dispatch with the side
+   * effect of rescuing the state from its semifree state.
+   *
+   * An alternative to this might be to make next_char more expensive,
+   * and to move a state to the head of the recyclable queue whenever
+   * it is entered.  That way, popular states would never be recycled.
+   *
+   * But unilaterally making next_char more expensive actually loses.
+   * So, incoming transitions are only made expensive for states near
+   * the tail of the recyclable queue.  The more cache contention
+   * there is, the more frequently a state will have to prove itself
+   * and be moved back to the front of the queue.  If there is less 
+   * contention, then popular states just aggregate in the front of 
+   * the queue and stay there.
+   */
+  int is_semifree;
+
+
+  /* This keeps track of the size of the transition table for this
+   * state.  There is a half-hearted attempt to support variable sized
+   * superstates.
+   */
+  int trans_size;
+
+  /* Indexed by characters... */
+  struct rx_inx transitions[RX_TAIL_ARRAY];
+};
+
+
+/* A list of distinct futures define the edges that leave from a 
+ * given superstate on a given character.  c.f. rx_super_edge.
+ */
+
+struct rx_distinct_future
+{
+  struct rx_distinct_future * next_same_super_edge[2];
+  struct rx_distinct_future * next_same_dest;
+  struct rx_distinct_future * prev_same_dest;
+  struct rx_superstate * present;	/* source state */
+  struct rx_superstate * future;	/* destination state */
+  struct rx_super_edge * edge;
+
+
+  /* The future_frame holds the instruction that should be executed
+   * after all the side effects are done, when it is time to complete
+   * the transition to the next state.
+   *
+   * Normally this is a next_char instruction, but it may be a
+   * cache_miss instruction as well, depending on whether or not
+   * the superstate is in the cache and semifree.
+   * 
+   * If this is the only future for a given superstate/char, and
+   * if there are no side effects to be performed, this frame is
+   * not used (directly) at all.  Instead, its contents are copied
+   * into the transition table of the starting state of this dist. future.
+   */
+  struct rx_inx future_frame;
+
+  struct rx_inx side_effects_frame;
+  struct rx_se_list * effects;
+};
+
+#define rx_lock_superstate(R,S)  ((S)->locks++)
+#define rx_unlock_superstate(R,S) (--(S)->locks)
+
+
+
+/* This page destined for rx.h */
+
+struct rx_blocklist
+{
+  struct rx_blocklist * next;
+  int bytes;
+};
+
+struct rx_freelist
+{
+  struct rx_freelist * next;
+};
+
+struct rx_cache;
+
+#ifdef __STDC__
+typedef void (*rx_morecore_fn)(struct rx_cache *);
+#else
+typedef void (*rx_morecore_fn)();
+#endif
+
+/* You use this to control the allocation of superstate data 
+ * during matching.  Most of it should be initialized to 0.
+ *
+ * A MORECORE function is necessary.  It should allocate
+ * a new block of memory or return 0.
+ * A default that uses malloc is called `rx_morecore'.
+ *
+ * The number of SUPERSTATES_ALLOWED indirectly limits how much memory
+ * the system will try to allocate.  The default is 128.  Batch style
+ * applications that are very regexp intensive should use as high a number
+ * as possible without thrashing.
+ * 
+ * The LOCAL_CSET_SIZE is the number of characters in a character set.
+ * It is therefore the number of entries in a superstate transition table.
+ * Generally, it should be 256.  If your character set has 16 bits, 
+ * it is better to translate your regexps into equivalent 8 bit patterns.
+ */
+
+struct rx_cache
+{
+  struct rx_hash_rules superset_hash_rules;
+
+  /* Objects are allocated by incrementing a pointer that 
+   * scans across rx_blocklists.
+   */
+  struct rx_blocklist * memory;
+  struct rx_blocklist * memory_pos;
+  int bytes_left;
+  char * memory_addr;
+  rx_morecore_fn morecore;
+
+  /* Freelists. */
+  struct rx_freelist * free_superstates;
+  struct rx_freelist * free_transition_classes;
+  struct rx_freelist * free_discernable_futures;
+  struct rx_freelist * free_supersets;
+  struct rx_freelist * free_hash;
+
+  /* Two sets of superstates -- those that are semifreed, and those
+   * that are being used.
+   */
+  struct rx_superstate * lru_superstate;
+  struct rx_superstate * semifree_superstate;
+
+  struct rx_superset * empty_superset;
+
+  int superstates;
+  int semifree_superstates;
+  int hits;
+  int misses;
+  int superstates_allowed;
+
+  int local_cset_size;
+  void ** instruction_table;
+
+  struct rx_hash superset_table;
+};
+
+
+
+
+/* The lowest-level search function supports arbitrarily fragmented
+ * strings and (optionally) suspendable/resumable searches.
+ *
+ * Callers have to provide a few hooks.
+ */
+
+#ifndef __GNUC__
+#ifdef __STDC__
+#define __const__ const
+#else
+#define __const__
+#endif
+#endif
+
+/* This holds a matcher position */
+struct rx_string_position
+{
+  __const__ unsigned char * pos;	/* The current pos. */
+  __const__ unsigned char * string; /* The current string burst. */
+  __const__ unsigned char * end;	/* First invalid position >= POS. */
+  int offset;			/* Integer address of the current burst. */
+  int size;			/* Current string's size. */
+  int search_direction;		/* 1 or -1 */
+  int search_end;		/* First position to not try. */
+};
+
+
+enum rx_get_burst_return
+{
+  rx_get_burst_continuation,
+  rx_get_burst_error,
+  rx_get_burst_ok,
+  rx_get_burst_no_more
+};
+
+
+/* A call to get burst should make POS valid.  It might be invalid
+ * if the STRING field doesn't point to a burst that actually
+ * contains POS.
+ *
+ * GET_BURST should take a clue from SEARCH_DIRECTION (1 or -1) as to
+ * whether or not to pad to the left.  Padding to the right is always
+ * appropriate, but need not go past the point indicated by STOP.
+ *
+ * If a continuation is returned, then the reentering call to
+ * a search function will retry the get_burst.
+ */
+
+#ifdef __STDC__
+typedef enum rx_get_burst_return
+  (*rx_get_burst_fn) (struct rx_string_position * pos,
+		      void * app_closure,
+		      int stop);
+					       
+#else
+typedef enum rx_get_burst_return (*rx_get_burst_fn) ();
+#endif
+
+
+enum rx_back_check_return
+{
+  rx_back_check_continuation,
+  rx_back_check_error,
+  rx_back_check_pass,
+  rx_back_check_fail
+};
+
+/* Back_check should advance the position it is passed 
+ * over rparen - lparen characters and return pass iff
+ * the characters starting at POS match those indexed
+ * by [LPAREN..RPAREN].
+ *
+ * If a continuation is returned, then the reentering call to
+ * a search function will retry the back_check.
+ */
+
+#ifdef __STDC__
+typedef enum rx_back_check_return
+  (*rx_back_check_fn) (struct rx_string_position * pos,
+		       int lparen,
+		       int rparen,
+		       unsigned char * translate,
+		       void * app_closure,
+		       int stop);
+					       
+#else
+typedef enum rx_back_check_return (*rx_back_check_fn) ();
+#endif
+
+
+
+
+/* A call to fetch_char should return the character at POS or POS + 1.
+ * Returning continuations here isn't supported.  OFFSET is either 0 or 1
+ * and indicates which characters is desired.
+ */
+
+#ifdef __STDC__
+typedef int (*rx_fetch_char_fn) (struct rx_string_position * pos,
+				 int offset,
+				 void * app_closure,
+				 int stop);
+#else
+typedef int (*rx_fetch_char_fn) ();
+#endif
+
+
+enum rx_search_return
+{
+  rx_search_continuation = -4,
+  rx_search_error = -3,
+  rx_search_soft_fail = -2,	/* failed by running out of string */
+  rx_search_fail = -1		/* failed only by reaching failure states */
+  /* return values >= 0 indicate the position of a successful match */
+};
+
+
+
+
+
+
+
+/* regex.h
+ * 
+ * The remaining declarations replace regex.h.
+ */
+
+/* This is an array of error messages corresponding to the error codes.
+ */
+extern __const__ char *re_error_msg[];
+
+/* If any error codes are removed, changed, or added, update the
+   `re_error_msg' table in regex.c.  */
+typedef enum
+{
+  REG_NOERROR = 0,	/* Success.  */
+  REG_NOMATCH,		/* Didn't find a match (for regexec).  */
+
+  /* POSIX regcomp return error codes.  (In the order listed in the
+     standard.)  */
+  REG_BADPAT,		/* Invalid pattern.  */
+  REG_ECOLLATE,		/* Not implemented.  */
+  REG_ECTYPE,		/* Invalid character class name.  */
+  REG_EESCAPE,		/* Trailing backslash.  */
+  REG_ESUBREG,		/* Invalid back reference.  */
+  REG_EBRACK,		/* Unmatched left bracket.  */
+  REG_EPAREN,		/* Parenthesis imbalance.  */ 
+  REG_EBRACE,		/* Unmatched \{.  */
+  REG_BADBR,		/* Invalid contents of \{\}.  */
+  REG_ERANGE,		/* Invalid range end.  */
+  REG_ESPACE,		/* Ran out of memory.  */
+  REG_BADRPT,		/* No preceding re for repetition op.  */
+
+  /* Error codes we've added.  */
+  REG_EEND,		/* Premature end.  */
+  REG_ESIZE,		/* Compiled pattern bigger than 2^16 bytes.  */
+  REG_ERPAREN		/* Unmatched ) or \); not returned from regcomp.  */
+} reg_errcode_t;
+
+/* The regex.c support, as a client of rx, defines a set of possible
+ * side effects that can be added to the edge lables of nfa edges.
+ * Here is the list of sidef effects in use.
+ */
+
+enum re_side_effects
+{
+#define RX_WANT_SE_DEFS 1
+#undef RX_DEF_SE
+#undef RX_DEF_CPLX_SE
+#define RX_DEF_SE(IDEM, NAME, VALUE)	      NAME VALUE,
+#define RX_DEF_CPLX_SE(IDEM, NAME, VALUE)     NAME VALUE,
+#include "rx.h"
+#undef RX_DEF_SE
+#undef RX_DEF_CPLX_SE
+#undef RX_WANT_SE_DEFS
+   re_floogle_flap = 65533
+};
+
+/* These hold paramaters for the kinds of side effects that are possible
+ * in the supported pattern languages.  These include things like the 
+ * numeric bounds of {} operators and the index of paren registers for 
+ * subexpression measurement or backreferencing.
+ */
+struct re_se_params
+{
+  enum re_side_effects se;
+  int op1;
+  int op2;
+};
+
+typedef unsigned reg_syntax_t;
+
+struct re_pattern_buffer
+{
+  struct rx rx;
+  reg_syntax_t syntax;		/* See below for syntax bit definitions. */
+
+  unsigned int no_sub:1;	/* If set, don't  return register offsets. */
+  unsigned int not_bol:1;	/* If set, the anchors ('^' and '$') don't */
+  unsigned int not_eol:1;	/*     match at the ends of the string.  */  
+  unsigned int newline_anchor:1;/* If true, an anchor at a newline matches.*/
+  unsigned int least_subs:1;	/* If set, and returning registers, return
+				 * as few values as possible.  Only 
+				 * backreferenced groups and group 0 (the whole
+				 * match) will be returned.
+				 */
+
+  /* If true, this says that the matcher should keep registers on its
+   * backtracking stack.  For many patterns, we can easily determine that
+   * this isn't necessary.
+   */
+  unsigned int match_regs_on_stack:1;
+  unsigned int search_regs_on_stack:1;
+
+  /* is_anchored and begbuf_only are filled in by rx_compile. */
+  unsigned int is_anchored:1;	/* Anchorded by ^? */
+  unsigned int begbuf_only:1;	/* Anchored to char position 0? */
+
+  
+  /* If REGS_UNALLOCATED, allocate space in the `regs' structure
+   * for `max (RE_NREGS, re_nsub + 1)' groups.
+   * If REGS_REALLOCATE, reallocate space if necessary.
+   * If REGS_FIXED, use what's there.  
+   */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+  unsigned int regs_allocated:2;
+
+  
+  /* Either a translate table to apply to all characters before
+   * comparing them, or zero for no translation.  The translation
+   * is applied to a pattern when it is compiled and to a string
+   * when it is matched.
+   */
+  unsigned char * translate;
+
+  /* If this is a valid pointer, it tells rx not to store the extents of 
+   * certain subexpressions (those corresponding to non-zero entries).
+   * Passing 0x1 is the same as passing an array of all ones.  Passing 0x0
+   * is the same as passing an array of all zeros.
+   * The array should contain as many entries as their are subexps in the 
+   * regexp.
+   *
+   * For POSIX compatability, when using regcomp and regexec this field
+   * is zeroed and ignored.
+   */
+  char * syntax_parens;
+
+	/* Number of subexpressions found by the compiler.  */
+  size_t re_nsub;
+
+  void * buffer;		/* Malloced memory for the nfa. */
+  unsigned long allocated;	/* Size of that memory. */
+
+  /* Pointer to a fastmap, if any, otherwise zero.  re_search uses
+   * the fastmap, if there is one, to skip over impossible
+   * starting points for matches.  */
+  char *fastmap;
+
+  unsigned int fastmap_accurate:1; /* These three are internal. */
+  unsigned int can_match_empty:1;  
+  struct rx_nfa_state * start;	/* The nfa starting state. */
+
+  /* This is the list of iterator bounds for {lo,hi} constructs.
+   * The memory pointed to is part of the rx->buffer.
+   */
+  struct re_se_params *se_params;
+
+  /* This is a bitset representation of the fastmap.
+   * This is a true fastmap that already takes the translate
+   * table into account.
+   */
+  rx_Bitset fastset;
+};
+
+/* Type for byte offsets within the string.  POSIX mandates this.  */
+typedef int regoff_t;
+
+/* This is the structure we store register match data in.  See
+   regex.texinfo for a full description of what registers match.  */
+struct re_registers
+{
+  unsigned num_regs;
+  regoff_t *start;
+  regoff_t *end;
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+/* POSIX specification for registers.  Aside from the different names than
+   `re_registers', POSIX uses an array of structures, instead of a
+   structure of arrays.  */
+typedef struct
+{
+  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
+  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
+} regmatch_t;
+
+
+
+/* The following bits are used to determine the regexp syntax we
+   recognize.  The set/not-set meanings are chosen so that Emacs syntax
+   remains the value 0.  The bits are given in alphabetical order, and
+   the definitions shifted by one from the previous bit; thus, when we
+   add or remove a bit, only one other definition need change.  */
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+   If set, then such a \ quotes the following character.  */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+     literals. 
+   If set, then \+ and \? are operators and + and ? are literals.  */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported.  They are:
+     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
+     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+   If not set, then character classes are not supported.  */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+     expressions, of course).
+   If this bit is not set, then it depends:
+        ^  is an anchor if it is at the beginning of a regular
+           expression or after an open-group or an alternation operator;
+        $  is an anchor if it is at the end of a regular expression, or
+           before a close-group or an alternation operator.  
+
+   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+   POSIX draft 11.2 says that * etc. in leading positions is undefined.
+   We already implemented a previous draft which made those constructs
+   invalid, though, so we haven't changed the code back.  */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+     regardless of where they are in the pattern.
+   If this bit is not set, then special characters are special only in
+     some contexts; otherwise they are ordinary.  Specifically, 
+     * + ? and intervals are only special when not after the beginning,
+     open-group, or alternation operator.  */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+     immediately after an alternation or begin-group operator.  */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+   If not set, then it doesn't.  */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+   If not set, then it does.  */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+   If not set, they do.  */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+     interval, depending on RE_NO_BK_BRACES. 
+   If not set, \{, \}, {, and } are literals.  */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+   If not set, they are.  */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+   If not set, newline is literal.  */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+     are literals.
+  If not set, then `\{...\}' defines an interval.  */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+   If not set, \(...\) defines a group, and ( and ) are literals.  */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+   If not set, then \<digit> is a back-reference.  */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal. 
+   If not set, then \| is an alternation operator, and | is literal.  */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+     than the starting range point, as in [z-a], is invalid.
+   If not set, then when ending range point collates higher than the
+     starting range point, the range is ignored.  */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+   If not set, then an unmatched ) is invalid.  */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+   some interfaces).  When a regexp is compiled, the syntax used is
+   stored in the pattern buffer, so changing this does not affect
+   already-compiled regexps.  */
+extern reg_syntax_t re_syntax_options;
+
+
+/* Define combinations of the above bits for the standard possibilities.
+   (The [[[ comments delimit what gets put into the Texinfo file, so
+   don't delete them!)  */ 
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK							\
+  (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL			\
+   | RE_NO_BK_PARENS            | RE_NO_BK_REFS				\
+   | RE_NO_BK_VBAR               | RE_NO_EMPTY_RANGES			\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+#define RE_SYNTAX_POSIX_AWK 						\
+  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
+
+#define RE_SYNTAX_GREP							\
+  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES				\
+   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS				\
+   | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP							\
+  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE			\
+   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS				\
+   | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP						\
+  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
+
+#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax.  */
+#define _RE_SYNTAX_POSIX_COMMON						\
+  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\
+   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
+
+#define RE_SYNTAX_POSIX_BASIC						\
+  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
+   isn't minimal, since other operators, such as \`, aren't disabled.  */
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+#define RE_SYNTAX_POSIX_EXTENDED					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS  | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS       | RE_NO_BK_VBAR				\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
+   replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added.  */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED				\
+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS        | RE_NO_BK_REFS				\
+   | RE_NO_BK_VBAR	    | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+/* Maximum number of duplicates an interval can allow.  Some systems
+   (erroneously) define this in other header files, but we want our
+   value, so remove any previous define.  */
+#ifdef RE_DUP_MAX
+#undef RE_DUP_MAX
+#endif
+#define RE_DUP_MAX ((1 << 15) - 1) 
+
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp').  */
+
+/* If this bit is set, then use extended regular expression syntax.
+   If not set, then use basic regular expression syntax.  */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+   If not set, then case is significant.  */
+#define REG_ICASE (REG_EXTENDED << 1)
+ 
+/* If this bit is set, then anchors do not match at newline
+     characters in the string.
+   If not set, then anchors do match at newlines.  */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+   If not set, then returns differ between not matching and errors.  */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec).  */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+     the beginning of the string (presumably because it's not the
+     beginning of a line).
+   If not set, then the beginning-of-line operator does match the
+     beginning of the string.  */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line.  */
+#define REG_NOTEOL (1 << 1)
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+ * `re_match_2' returns information about at least this many registers
+ * the first time a `regs' structure is passed. 
+ *
+ * Also, this is the greatest number of backreferenced subexpressions
+ * allowed in a pattern being matched without caller-supplied registers.
+ */
+#ifndef RE_NREGS
+#define RE_NREGS 30
+#endif
+
+extern int rx_cache_bound;
+extern char rx_version_string[];
+
+
+
+
+#ifdef RX_WANT_RX_DEFS
+
+/* This is decls to the interesting subsystems and lower layers
+ * of rx.  Everything which doesn't have a public counterpart in 
+ * regex.c is declared here.
+ */
+
+
+#ifdef __STDC__
+typedef void (*rx_hash_freefn) (struct rx_hash_item * it);
+#else /* ndef __STDC__ */
+typedef void (*rx_hash_freefn) ();
+#endif /* ndef __STDC__ */
+
+
+
+
+
+#ifdef __STDC__
+RX_DECL int rx_bitset_is_equal (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL int rx_bitset_is_subset (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL int rx_bitset_empty (int size, rx_Bitset set);
+RX_DECL void rx_bitset_null (int size, rx_Bitset b);
+RX_DECL void rx_bitset_universe (int size, rx_Bitset b);
+RX_DECL void rx_bitset_complement (int size, rx_Bitset b);
+RX_DECL void rx_bitset_assign (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_union (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_intersection (int size,
+				     rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_difference (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_revdifference (int size,
+				      rx_Bitset a, rx_Bitset b);
+RX_DECL void rx_bitset_xor (int size, rx_Bitset a, rx_Bitset b);
+RX_DECL unsigned long rx_bitset_hash (int size, rx_Bitset b);
+RX_DECL struct rx_hash_item * rx_hash_find (struct rx_hash * table,
+					    unsigned long hash,
+					    void * value,
+					    struct rx_hash_rules * rules);
+RX_DECL struct rx_hash_item * rx_hash_store (struct rx_hash * table,
+					     unsigned long hash,
+					     void * value,
+					     struct rx_hash_rules * rules);
+RX_DECL void rx_hash_free (struct rx_hash_item * it, struct rx_hash_rules * rules);
+RX_DECL void rx_free_hash_table (struct rx_hash * tab, rx_hash_freefn freefn,
+				 struct rx_hash_rules * rules);
+RX_DECL rx_Bitset rx_cset (struct rx *rx);
+RX_DECL rx_Bitset rx_copy_cset (struct rx *rx, rx_Bitset a);
+RX_DECL void rx_free_cset (struct rx * rx, rx_Bitset c);
+RX_DECL struct rexp_node * rexp_node (struct rx *rx,
+				      enum rexp_node_type type);
+RX_DECL struct rexp_node * rx_mk_r_cset (struct rx * rx,
+					 rx_Bitset b);
+RX_DECL struct rexp_node * rx_mk_r_concat (struct rx * rx,
+					   struct rexp_node * a,
+					   struct rexp_node * b);
+RX_DECL struct rexp_node * rx_mk_r_alternate (struct rx * rx,
+					      struct rexp_node * a,
+					      struct rexp_node * b);
+RX_DECL struct rexp_node * rx_mk_r_opt (struct rx * rx,
+					struct rexp_node * a);
+RX_DECL struct rexp_node * rx_mk_r_star (struct rx * rx,
+					 struct rexp_node * a);
+RX_DECL struct rexp_node * rx_mk_r_2phase_star (struct rx * rx,
+						struct rexp_node * a,
+						struct rexp_node * b);
+RX_DECL struct rexp_node * rx_mk_r_side_effect (struct rx * rx,
+						rx_side_effect a);
+RX_DECL struct rexp_node * rx_mk_r_data  (struct rx * rx,
+					  void * a);
+RX_DECL void rx_free_rexp (struct rx * rx, struct rexp_node * node);
+RX_DECL struct rexp_node * rx_copy_rexp (struct rx *rx,
+					 struct rexp_node *node);
+RX_DECL struct rx_nfa_state * rx_nfa_state (struct rx *rx);
+RX_DECL void rx_free_nfa_state (struct rx_nfa_state * n);
+RX_DECL struct rx_nfa_state * rx_id_to_nfa_state (struct rx * rx,
+						  int id);
+RX_DECL struct rx_nfa_edge * rx_nfa_edge (struct rx *rx,
+					  enum rx_nfa_etype type,
+					  struct rx_nfa_state *start,
+					  struct rx_nfa_state *dest);
+RX_DECL void rx_free_nfa_edge (struct rx_nfa_edge * e);
+RX_DECL void rx_free_nfa (struct rx *rx);
+RX_DECL int rx_build_nfa (struct rx *rx,
+			  struct rexp_node *rexp,
+			  struct rx_nfa_state **start,
+			  struct rx_nfa_state **end);
+RX_DECL void rx_name_nfa_states (struct rx *rx);
+RX_DECL int rx_eclose_nfa (struct rx *rx);
+RX_DECL void rx_delete_epsilon_transitions (struct rx *rx);
+RX_DECL int rx_compactify_nfa (struct rx *rx,
+			       void **mem, unsigned long *size);
+RX_DECL void rx_release_superset (struct rx *rx,
+				  struct rx_superset *set);
+RX_DECL struct rx_superset * rx_superset_cons (struct rx * rx,
+					       struct rx_nfa_state *car, struct rx_superset *cdr);
+RX_DECL struct rx_superset * rx_superstate_eclosure_union
+  (struct rx * rx, struct rx_superset *set, struct rx_nfa_state_set *ecl);
+RX_DECL struct rx_superstate * rx_superstate (struct rx *rx,
+					      struct rx_superset *set);
+RX_DECL struct rx_inx * rx_handle_cache_miss
+  (struct rx *rx, struct rx_superstate *super, unsigned char chr, void *data);
+RX_DECL reg_errcode_t rx_compile (__const__ char *pattern, int size,
+				  reg_syntax_t syntax,
+				  struct re_pattern_buffer * rxb);
+RX_DECL void rx_blow_up_fastmap (struct re_pattern_buffer * rxb);
+#else /* STDC */
+RX_DECL int rx_bitset_is_equal ();
+RX_DECL int rx_bitset_is_subset ();
+RX_DECL int rx_bitset_empty ();
+RX_DECL void rx_bitset_null ();
+RX_DECL void rx_bitset_universe ();
+RX_DECL void rx_bitset_complement ();
+RX_DECL void rx_bitset_assign ();
+RX_DECL void rx_bitset_union ();
+RX_DECL void rx_bitset_intersection ();
+RX_DECL void rx_bitset_difference ();
+RX_DECL void rx_bitset_revdifference ();
+RX_DECL void rx_bitset_xor ();
+RX_DECL unsigned long rx_bitset_hash ();
+RX_DECL struct rx_hash_item * rx_hash_find ();
+RX_DECL struct rx_hash_item * rx_hash_store ();
+RX_DECL void rx_hash_free ();
+RX_DECL void rx_free_hash_table ();
+RX_DECL rx_Bitset rx_cset ();
+RX_DECL rx_Bitset rx_copy_cset ();
+RX_DECL void rx_free_cset ();
+RX_DECL struct rexp_node * rexp_node ();
+RX_DECL struct rexp_node * rx_mk_r_cset ();
+RX_DECL struct rexp_node * rx_mk_r_concat ();
+RX_DECL struct rexp_node * rx_mk_r_alternate ();
+RX_DECL struct rexp_node * rx_mk_r_opt ();
+RX_DECL struct rexp_node * rx_mk_r_star ();
+RX_DECL struct rexp_node * rx_mk_r_2phase_star ();
+RX_DECL struct rexp_node * rx_mk_r_side_effect ();
+RX_DECL struct rexp_node * rx_mk_r_data  ();
+RX_DECL void rx_free_rexp ();
+RX_DECL struct rexp_node * rx_copy_rexp ();
+RX_DECL struct rx_nfa_state * rx_nfa_state ();
+RX_DECL void rx_free_nfa_state ();
+RX_DECL struct rx_nfa_state * rx_id_to_nfa_state ();
+RX_DECL struct rx_nfa_edge * rx_nfa_edge ();
+RX_DECL void rx_free_nfa_edge ();
+RX_DECL void rx_free_nfa ();
+RX_DECL int rx_build_nfa ();
+RX_DECL void rx_name_nfa_states ();
+RX_DECL int rx_eclose_nfa ();
+RX_DECL void rx_delete_epsilon_transitions ();
+RX_DECL int rx_compactify_nfa ();
+RX_DECL void rx_release_superset ();
+RX_DECL struct rx_superset * rx_superset_cons ();
+RX_DECL struct rx_superset * rx_superstate_eclosure_union ();
+RX_DECL struct rx_superstate * rx_superstate ();
+RX_DECL struct rx_inx * rx_handle_cache_miss ();
+RX_DECL reg_errcode_t rx_compile ();
+RX_DECL void rx_blow_up_fastmap ();
+#endif /* STDC */
+
+
+#endif /* RX_WANT_RX_DEFS */
+
+
+
+
+#ifdef __STDC__
+extern int re_search_2 (struct re_pattern_buffer *rxb,
+			__const__ char * string1, int size1,
+			__const__ char * string2, int size2,
+			int startpos, int range,
+			struct re_registers *regs,
+			int stop);
+extern int re_search (struct re_pattern_buffer * rxb, __const__ char *string,
+		      int size, int startpos, int range,
+		      struct re_registers *regs);
+extern int re_match_2 (struct re_pattern_buffer * rxb,
+		       __const__ char * string1, int size1,
+		       __const__ char * string2, int size2,
+		       int pos, struct re_registers *regs, int stop);
+extern int re_match (struct re_pattern_buffer * rxb,
+		     __const__ char * string,
+		     int size, int pos,
+		     struct re_registers *regs);
+extern reg_syntax_t re_set_syntax (reg_syntax_t syntax);
+extern void re_set_registers (struct re_pattern_buffer *bufp,
+			      struct re_registers *regs,
+			      unsigned num_regs,
+			      regoff_t * starts, regoff_t * ends);
+extern __const__ char * re_compile_pattern (__const__ char *pattern,
+					int length,
+					struct re_pattern_buffer * rxb);
+extern int re_compile_fastmap (struct re_pattern_buffer * rxb);
+extern char * re_comp (__const__ char *s);
+extern int re_exec (__const__ char *s);
+extern int regcomp (regex_t * preg, __const__ char * pattern, int cflags);
+extern int regexec (__const__ regex_t *preg, __const__ char *string,
+		    size_t nmatch, regmatch_t pmatch[],
+		    int eflags);
+extern size_t regerror (int errcode, __const__ regex_t *preg,
+			char *errbuf, size_t errbuf_size);
+extern void regfree (regex_t *preg);
+
+#else /* STDC */
+extern int re_search_2 ();
+extern int re_search ();
+extern int re_match_2 ();
+extern int re_match ();
+extern reg_syntax_t re_set_syntax ();
+extern void re_set_registers ();
+extern __const__ char * re_compile_pattern ();
+extern int re_compile_fastmap ();
+extern char * re_comp ();
+extern int re_exec ();
+extern int regcomp ();
+extern int regexec ();
+extern size_t regerror ();
+extern void regfree ();
+
+#endif /* STDC */
+
+
+
+
+#ifdef RX_WANT_RX_DEFS
+
+struct rx_counter_frame
+{
+  int tag;
+  int val;
+  struct rx_counter_frame * inherited_from; /* If this is a copy. */
+  struct rx_counter_frame * cdr;
+};
+
+struct rx_backtrack_frame
+{
+  char * counter_stack_sp;
+
+  /* A frame is used to save the matchers state when it crosses a 
+   * backtracking point.  The `stk_' fields correspond to variables
+   * in re_search_2 (just strip off thes `stk_').  They are documented
+   * tere.
+   */
+  struct rx_superstate * stk_super;
+  unsigned int stk_c;
+  struct rx_string_position stk_test_pos;
+  int stk_last_l;
+  int stk_last_r;
+  int stk_test_ret;
+
+  /* This is the list of options left to explore at the backtrack
+   * point for which this frame was created. 
+   */
+  struct rx_distinct_future * df;
+  struct rx_distinct_future * first_df;
+
+#ifdef RX_DEBUG
+   int stk_line_no;
+#endif
+};
+
+struct rx_stack_chunk
+{
+  struct rx_stack_chunk * next_chunk;
+  int bytes_left;
+  char * sp;
+};
+
+enum rx_outer_entry
+{
+  rx_outer_start,
+  rx_outer_fastmap,
+  rx_outer_test,
+  rx_outer_restore_pos
+};
+
+enum rx_fastmap_return
+{
+  rx_fastmap_continuation,
+  rx_fastmap_error,
+  rx_fastmap_ok,
+  rx_fastmap_fail
+};
+
+enum rx_fastmap_entry
+{
+  rx_fastmap_start,
+  rx_fastmap_string_break
+};
+
+enum rx_test_return
+{
+  rx_test_continuation,
+  rx_test_error,
+  rx_test_fail,
+  rx_test_ok
+};
+
+enum rx_test_internal_return
+{
+  rx_test_internal_error,
+  rx_test_found_first,
+  rx_test_line_finished
+};
+
+enum rx_test_match_entry
+{
+  rx_test_start,
+  rx_test_cache_hit_loop,
+  rx_test_backreference_check,
+  rx_test_backtrack_return
+};
+
+struct rx_search_state
+{
+  /* Two groups of registers are kept.  The group with the register state
+   * of the current test match, and the group that holds the state at the end
+   * of the best known match, if any.
+   *
+   * For some patterns, there may also be registers saved on the stack.
+   */
+  unsigned num_regs;		/* Includes an element for register zero. */
+  regoff_t * lparen;		/* scratch space for register returns */
+  regoff_t * rparen;
+  regoff_t * best_lpspace;	/* in case the user doesn't want these */
+  regoff_t * best_rpspace;	/* values, we still need space to store
+				 * them.  Normally, this memoryis unused
+				 * and the space pointed to by REGS is 
+				 * used instead.
+				 */
+  
+  int last_l;			/* Highest index of a valid lparen. */
+  int last_r;			/* It's dual. */
+  
+  int * best_lparen;		/* This contains the best known register */
+  int * best_rparen;		/* assignments. 
+				 * This may point to the same mem as
+				 * best_lpspace, or it might point to memory
+				 * passed by the caller.
+				 */
+  int best_last_l;		/* best_last_l:best_lparen::last_l:lparen */
+  int best_last_r;
+
+
+  unsigned char * translate;  
+
+  struct rx_string_position outer_pos;
+
+  struct rx_superstate * start_super;
+  int nfa_choice;
+  int first_found;		/* If true, return after finding any match. */
+  int ret_val;
+
+  /* For continuations... */
+  enum rx_outer_entry outer_search_resume_pt;
+  struct re_pattern_buffer * saved_rxb;
+  int saved_startpos;
+  int saved_range;
+  int saved_stop;
+  int saved_total_size;
+  rx_get_burst_fn saved_get_burst;
+  rx_back_check_fn saved_back_check;
+  struct re_registers * saved_regs;
+  
+  /**
+   ** state for fastmap
+   **/
+  char * fastmap;
+  int fastmap_chr;
+  int fastmap_val;
+
+  /* for continuations in the fastmap procedure: */
+  enum rx_fastmap_entry fastmap_resume_pt;
+
+  /**
+   ** state for test_match 
+   **/
+
+  /* The current superNFA position of the matcher. */
+  struct rx_superstate * super;
+  
+  /* The matcher interprets a series of instruction frames.
+   * This is the `instruction counter' for the interpretation.
+   */
+  struct rx_inx * ifr;
+  
+  /* We insert a ghost character in the string to prime
+   * the nfa.  test_pos.pos, test_pos.str_half, and test_pos.end_half
+   * keep track of the test-match position and string-half.
+   */
+  unsigned char c;
+  
+  /* Position within the string. */
+  struct rx_string_position test_pos;
+
+  struct rx_stack_chunk * counter_stack;
+  struct rx_stack_chunk * backtrack_stack;
+  int backtrack_frame_bytes;
+  int chunk_bytes;
+  struct rx_stack_chunk * free_chunks;
+
+  /* To return from this function, set test_ret and 
+   * `goto test_do_return'.
+   *
+   * Possible return values are:
+   *     1   --- end of string while the superNFA is still going
+   *     0   --- internal error (out of memory)
+   *	-1   --- search completed by reaching the superNFA fail state
+   *    -2   --- a match was found, maybe not the longest.
+   *
+   * When the search is complete (-1), best_last_r indicates whether
+   * a match was found.
+   *
+   * -2 is return only if search_state.first_found is non-zero.
+   *
+   * if search_state.first_found is non-zero, a return of -1 indicates no match,
+   * otherwise, best_last_r has to be checked.
+   */
+  int test_ret;
+
+  int could_have_continued;
+  
+#ifdef RX_DEBUG
+  int backtrack_depth;
+  /* There is a search tree with every node as set of deterministic
+   * transitions in the super nfa.  For every branch of a 
+   * backtrack point is an edge in the tree.
+   * This counts up a pre-order of nodes in that tree.
+   * It's saved on the search stack and printed when debugging. 
+   */
+  int line_no;
+  int lines_found;
+#endif
+
+
+  /* For continuations within the match tester */
+  enum rx_test_match_entry test_match_resume_pt;
+  struct rx_inx * saved_next_tr_table;
+  struct rx_inx * saved_this_tr_table;
+  int saved_reg;
+  struct rx_backtrack_frame * saved_bf;
+  
+};
+
+
+
+extern char rx_slowmap[];
+extern unsigned char rx_id_translation[];
+
+static __inline__ void
+init_fastmap (rxb, search_state)
+     struct re_pattern_buffer * rxb;
+     struct rx_search_state * search_state;
+{
+  search_state->fastmap = (rxb->fastmap
+			   ? (char *)rxb->fastmap
+			   : (char *)rx_slowmap);
+  /* Update the fastmap now if not correct already. 
+   * When the regexp was compiled, the fastmap was computed
+   * and stored in a bitset.  This expands the bitset into a
+   * character array containing 1s and 0s.
+   */
+  if ((search_state->fastmap == rxb->fastmap) && !rxb->fastmap_accurate)
+    rx_blow_up_fastmap (rxb);
+  search_state->fastmap_chr = -1;
+  search_state->fastmap_val = 0;
+  search_state->fastmap_resume_pt = rx_fastmap_start;
+}
+
+static __inline__ void
+uninit_fastmap (rxb, search_state)
+     struct re_pattern_buffer * rxb;
+     struct rx_search_state * search_state;
+{
+  /* Unset the fastmap sentinel */
+  if (search_state->fastmap_chr >= 0)
+    search_state->fastmap[search_state->fastmap_chr]
+      = search_state->fastmap_val;
+}
+
+static __inline__ int
+fastmap_search (rxb, stop, get_burst, app_closure, search_state)
+     struct re_pattern_buffer * rxb;
+     int stop;
+     rx_get_burst_fn get_burst;
+     void * app_closure;
+     struct rx_search_state * search_state;
+{
+  enum rx_fastmap_entry pc;
+
+  if (0)
+    {
+    return_continuation:
+      search_state->fastmap_resume_pt = pc;
+      return rx_fastmap_continuation;
+    }
+
+  pc = search_state->fastmap_resume_pt;
+
+  switch (pc)
+    {
+    default:
+      return rx_fastmap_error;
+    case rx_fastmap_start:
+    init_fastmap_sentinal:
+      /* For the sake of fast fastmapping, set a sentinal in the fastmap.
+       * This sentinal will trap the fastmap loop when it reaches the last
+       * valid character in a string half.
+       *
+       * This must be reset when the fastmap/search loop crosses a string 
+       * boundry, and before returning to the caller.  So sometimes,
+       * the fastmap loop is restarted with `continue', othertimes by
+       * `goto init_fastmap_sentinal'.
+       */
+      if (search_state->outer_pos.size)
+	{
+	  search_state->fastmap_chr = ((search_state->outer_pos.search_direction == 1)
+				       ? *(search_state->outer_pos.end - 1)
+				       : *search_state->outer_pos.string);
+	  search_state->fastmap_val
+	    = search_state->fastmap[search_state->fastmap_chr];
+	  search_state->fastmap[search_state->fastmap_chr] = 1;
+	}
+      else
+	{
+	  search_state->fastmap_chr = -1;
+	  search_state->fastmap_val = 0;
+	}
+      
+      if (search_state->outer_pos.pos >= search_state->outer_pos.end)
+	goto fastmap_hit_bound;
+      else
+	{
+	  if (search_state->outer_pos.search_direction == 1)
+	    {
+	      if (search_state->fastmap_val)
+		{
+		  for (;;)
+		    {
+		      while (!search_state->fastmap[*search_state->outer_pos.pos])
+			++search_state->outer_pos.pos;
+		      return rx_fastmap_ok;
+		    }
+		}
+	      else
+		{
+		  for (;;)
+		    {
+		      while (!search_state->fastmap[*search_state->outer_pos.pos])
+			++search_state->outer_pos.pos;
+		      if (*search_state->outer_pos.pos != search_state->fastmap_chr)
+			return rx_fastmap_ok;
+		      else 
+			{
+			  ++search_state->outer_pos.pos;
+			  if (search_state->outer_pos.pos == search_state->outer_pos.end)
+			    goto fastmap_hit_bound;
+			}
+		    }
+		}
+	    }
+	  else
+	    {
+	      __const__ unsigned char * bound;
+	      bound = search_state->outer_pos.string - 1;
+	      if (search_state->fastmap_val)
+		{
+		  for (;;)
+		    {
+		      while (!search_state->fastmap[*search_state->outer_pos.pos])
+			--search_state->outer_pos.pos;
+		      return rx_fastmap_ok;
+		    }
+		}
+	      else
+		{
+		  for (;;)
+		    {
+		      while (!search_state->fastmap[*search_state->outer_pos.pos])
+			--search_state->outer_pos.pos;
+		      if ((*search_state->outer_pos.pos != search_state->fastmap_chr) || search_state->fastmap_val)
+			return rx_fastmap_ok;
+		      else 
+			{
+			  --search_state->outer_pos.pos;
+			  if (search_state->outer_pos.pos == bound)
+			    goto fastmap_hit_bound;
+			}
+		    }
+		}
+	    }
+	}
+      
+    case rx_fastmap_string_break:
+    fastmap_hit_bound:
+      {
+	/* If we hit a bound, it may be time to fetch another burst
+	 * of string, or it may be time to return a continuation to 
+ 	 * the caller, or it might be time to fail.
+	 */
+
+	int burst_state;
+	burst_state = get_burst (&search_state->outer_pos, app_closure, stop);
+	switch (burst_state)
+	  {
+	  default:
+	  case rx_get_burst_error:
+	    return rx_fastmap_error;
+	  case rx_get_burst_continuation:
+	    {
+	      pc = rx_fastmap_string_break;
+	      goto return_continuation;
+	    }
+	  case rx_get_burst_ok:
+	    goto init_fastmap_sentinal;
+	  case rx_get_burst_no_more:
+	    /* ...not a string split, simply no more string. 
+	     *
+	     * When searching backward, running out of string
+	     * is reason to quit.
+	     *
+	     * When searching forward, we allow the possibility
+	     * of an (empty) match after the last character in the
+	     * virtual string.  So, fall through to the matcher
+	     */
+	    return (  (search_state->outer_pos.search_direction == 1)
+		    ? rx_fastmap_ok
+		    : rx_fastmap_fail);
+	  }
+      }
+    }
+
+}
+
+
+
+
+#ifdef emacs
+/* The `emacs' switch turns on certain matching commands
+ * that make sense only in Emacs. 
+ */
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+#endif /* emacs */
+
+/* Setting RX_MEMDBUG is useful if you have dbmalloc.  Maybe with similar
+ * packages too.
+ */
+#ifdef RX_MEMDBUG
+#include <malloc.h>
+#endif /* RX_RX_MEMDBUG */
+
+/* We used to test for `BSTRING' here, but only GCC and Emacs define
+ * `BSTRING', as far as I know, and neither of them use this code.  
+ */
+#if HAVE_STRING_H || STDC_HEADERS
+#include <string.h>
+
+#ifndef bcmp
+#define bcmp(s1, s2, n)	memcmp ((s1), (s2), (n))
+#endif
+
+#ifndef bcopy
+#define bcopy(s, d, n)	memcpy ((d), (s), (n))
+#endif
+
+#ifndef bzero
+#define bzero(s, n)	memset ((s), 0, (n))
+#endif
+
+#else /*  HAVE_STRING_H || STDC_HEADERS */
+#include <strings.h>
+#endif   /* not (HAVE_STRING_H || STDC_HEADERS) */
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else /* not STDC_HEADERS */
+char *malloc ();
+char *realloc ();
+#endif /* not STDC_HEADERS */
+
+
+
+
+
+/* How many characters in the character set.  */
+#define CHAR_SET_SIZE (1 << CHARBITS)
+
+#ifndef emacs
+/* Define the syntax basics for \<, \>, etc.
+ * This must be nonzero for the wordchar and notwordchar pattern
+ * commands in re_match_2.
+ */
+#ifndef Sword 
+#define Sword 1
+#endif
+#define SYNTAX(c) re_syntax_table[c]
+RX_DECL char re_syntax_table[CHAR_SET_SIZE];
+#endif /* not emacs */
+
+
+/* Test if at very beginning or at very end of the virtual concatenation
+ *  of `string1' and `string2'.  If only one string, it's `string2'.  
+ */
+
+#define AT_STRINGS_BEG() \
+  (   -1		 \
+   == ((search_state.test_pos.pos - search_state.test_pos.string) \
+       + search_state.test_pos.offset))
+
+#define AT_STRINGS_END() \
+  (   (total_size - 1)	 \
+   == ((search_state.test_pos.pos - search_state.test_pos.string) \
+       + search_state.test_pos.offset))
+
+
+/* Test if POS + 1 points to a character which is word-constituent.  We have
+ * two special cases to check for: if past the end of string1, look at
+ * the first character in string2; and if before the beginning of
+ * string2, look at the last character in string1.
+ *
+ * Assumes `string1' exists, so use in conjunction with AT_STRINGS_BEG ().  
+ */
+#define LETTER_P(POS,OFF)						\
+  (   SYNTAX (fetch_char(POS, OFF, app_closure, stop))			\
+   == Sword)
+
+/* Test if the character at D and the one after D differ with respect
+ * to being word-constituent.  
+ */
+#define AT_WORD_BOUNDARY(d)						\
+  (AT_STRINGS_BEG () || AT_STRINGS_END () || LETTER_P (d,0) != LETTER_P (d, 1))
+
+
+#ifdef RX_SUPPORT_CONTINUATIONS
+#define RX_STACK_ALLOC(BYTES) malloc(BYTES)
+#define RX_STACK_FREE(MEM) free(MEM)
+#else
+#define RX_STACK_ALLOC(BYTES) alloca(BYTES)
+#define RX_STACK_FREE(MEM) \
+      ((struct rx_stack_chunk *)MEM)->next_chunk = search_state.free_chunks; \
+      search_state.free_chunks = ((struct rx_stack_chunk *)MEM);
+
+#endif
+
+#define PUSH(CHUNK_VAR,BYTES)   \
+  if (!CHUNK_VAR || (CHUNK_VAR->bytes_left < (BYTES)))  \
+    {					\
+      struct rx_stack_chunk * new_chunk;	\
+      if (search_state.free_chunks)			\
+	{				\
+	  new_chunk = search_state.free_chunks;	\
+	  search_state.free_chunks = search_state.free_chunks->next_chunk; \
+	}				\
+      else				\
+	{				\
+	  new_chunk = (struct rx_stack_chunk *)RX_STACK_ALLOC(search_state.chunk_bytes); \
+	  if (!new_chunk)		\
+	    {				\
+	      search_state.ret_val = 0;		\
+	      goto test_do_return;	\
+	    }				\
+	}				\
+      new_chunk->sp = (char *)new_chunk + sizeof (struct rx_stack_chunk); \
+      new_chunk->bytes_left = (search_state.chunk_bytes \
+			       - (BYTES) \
+			       - sizeof (struct rx_stack_chunk)); \
+      new_chunk->next_chunk = CHUNK_VAR; \
+      CHUNK_VAR = new_chunk;		\
+    } \
+  else \
+    (CHUNK_VAR->sp += (BYTES)), (CHUNK_VAR->bytes_left -= (BYTES))
+
+#define POP(CHUNK_VAR,BYTES) \
+  if (CHUNK_VAR->sp == ((char *)CHUNK_VAR + sizeof(*CHUNK_VAR))) \
+    { \
+      struct rx_stack_chunk * new_chunk = CHUNK_VAR->next_chunk; \
+      RX_STACK_FREE(CHUNK_VAR); \
+      CHUNK_VAR = new_chunk; \
+    } \
+  else \
+    (CHUNK_VAR->sp -= BYTES), (CHUNK_VAR->bytes_left += BYTES)
+
+
+
+#define SRCH_TRANSLATE(C)  search_state.translate[(unsigned char) (C)]
+
+
+
+
+
+#ifdef __STDC__
+RX_DECL __inline__ int
+rx_search  (struct re_pattern_buffer * rxb,
+	    int startpos,
+	    int range,
+	    int stop,
+	    int total_size,
+	    rx_get_burst_fn get_burst,
+	    rx_back_check_fn back_check,
+	    rx_fetch_char_fn fetch_char,
+	    void * app_closure,
+	    struct re_registers * regs,
+	    struct rx_search_state * resume_state,
+	    struct rx_search_state * save_state)
+#else
+RX_DECL __inline__ int
+rx_search  (rxb, startpos, range, stop, total_size,
+	    get_burst, back_check, fetch_char,
+	    app_closure, regs, resume_state, save_state)
+     struct re_pattern_buffer * rxb;
+     int startpos;
+     int range;
+     int stop;
+     int total_size;
+     rx_get_burst_fn get_burst;
+     rx_back_check_fn back_check;
+     rx_fetch_char_fn fetch_char;
+     void * app_closure;
+     struct re_registers * regs;
+     struct rx_search_state * resume_state;
+     struct rx_search_state * save_state;
+#endif
+{
+  int pc;
+  int test_state;
+  struct rx_search_state search_state;
+
+  search_state.free_chunks = 0;
+  if (!resume_state)
+    pc = rx_outer_start;
+  else
+    {
+      search_state = *resume_state;
+      regs = search_state.saved_regs;
+      rxb = search_state.saved_rxb;
+      startpos = search_state.saved_startpos;
+      range = search_state.saved_range;
+      stop = search_state.saved_stop;
+      total_size = search_state.saved_total_size;
+      get_burst = search_state.saved_get_burst;
+      back_check = search_state.saved_back_check;
+      pc = search_state.outer_search_resume_pt;
+      if (0)
+	{
+	return_continuation:
+	  if (save_state)
+	    {
+	      *save_state = search_state;
+	      save_state->saved_regs = regs;
+	      save_state->saved_rxb = rxb;
+	      save_state->saved_startpos = startpos;
+	      save_state->saved_range = range;
+	      save_state->saved_stop = stop;
+	      save_state->saved_total_size = total_size;
+	      save_state->saved_get_burst = get_burst;
+	      save_state->saved_back_check = back_check;
+	      save_state->outer_search_resume_pt = pc;
+	    }
+	  return rx_search_continuation;
+	}
+    }
+
+  switch (pc)
+    {
+    case rx_outer_start:
+      search_state.ret_val = rx_search_fail;
+      (  search_state.lparen
+       = search_state.rparen
+       = search_state.best_lpspace
+       = search_state.best_rpspace
+       = 0);
+      
+      /* figure the number of registers we may need for use in backreferences.
+       * the number here includes an element for register zero.  
+       */
+      search_state.num_regs = rxb->re_nsub + 1;
+      
+      
+      /* check for out-of-range startpos.  */
+      if ((startpos < 0) || (startpos > total_size))
+	return rx_search_fail;
+      
+      /* fix up range if it might eventually take us outside the string. */
+      {
+	int endpos;
+	endpos = startpos + range;
+	if (endpos < -1)
+	  range = (-1 - startpos);
+	else if (endpos > (total_size + 1))
+	  range = total_size - startpos;
+      }
+      
+      /* if the search isn't to be a backwards one, don't waste time in a
+       * long search for a pattern that says it is anchored.
+       */
+      if (rxb->begbuf_only && (range > 0))
+	{
+	  if (startpos > 0)
+	    return rx_search_fail;
+	  else
+	    range = 1;
+	}
+      
+      /* decide whether to use internal or user-provided reg buffers. */
+      if (!regs || rxb->no_sub)
+	{
+	  search_state.best_lpspace =
+	    (regoff_t *)REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t));
+	  search_state.best_rpspace =
+	    (regoff_t *)REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t));
+	  search_state.best_lparen = search_state.best_lpspace;
+	  search_state.best_rparen = search_state.best_rpspace;
+	}
+      else
+	{	
+	  /* have the register data arrays been allocated?  */
+	  if (rxb->regs_allocated == REGS_UNALLOCATED)
+	    { /* no.  so allocate them with malloc.  we need one
+		 extra element beyond `search_state.num_regs' for the `-1' marker
+		 gnu code uses.  */
+	      regs->num_regs = MAX (RE_NREGS, rxb->re_nsub + 1);
+	      regs->start = ((regoff_t *)
+			     malloc (regs->num_regs * sizeof ( regoff_t)));
+	      regs->end = ((regoff_t *)
+			   malloc (regs->num_regs * sizeof ( regoff_t)));
+	      if (regs->start == 0 || regs->end == 0)
+		return rx_search_error;
+	      rxb->regs_allocated = REGS_REALLOCATE;
+	    }
+	  else if (rxb->regs_allocated == REGS_REALLOCATE)
+	    { /* yes.  if we need more elements than were already
+		 allocated, reallocate them.  if we need fewer, just
+		 leave it alone.  */
+	      if (regs->num_regs < search_state.num_regs + 1)
+		{
+		  regs->num_regs = search_state.num_regs + 1;
+		  regs->start = ((regoff_t *)
+				 realloc (regs->start,
+					  regs->num_regs * sizeof (regoff_t)));
+		  regs->end = ((regoff_t *)
+			       realloc (regs->end,
+					regs->num_regs * sizeof ( regoff_t)));
+		  if (regs->start == 0 || regs->end == 0)
+		    return rx_search_error;
+		}
+	    }
+	  else if (rxb->regs_allocated != REGS_FIXED)
+	    return rx_search_error;
+	  
+	  if (regs->num_regs < search_state.num_regs + 1)
+	    {
+	      search_state.best_lpspace =
+		((regoff_t *)
+		 REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t)));
+	      search_state.best_rpspace =
+		((regoff_t *)
+		 REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t)));
+	      search_state.best_lparen = search_state.best_lpspace;
+	      search_state.best_rparen = search_state.best_rpspace;
+	    }
+	  else
+	    {
+	      search_state.best_lparen = regs->start;
+	      search_state.best_rparen = regs->end;
+	    }
+	}
+      
+      search_state.lparen =
+	(regoff_t *) REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t));
+      search_state.rparen =
+	(regoff_t *) REGEX_ALLOCATE (search_state.num_regs * sizeof(regoff_t)); 
+      
+      if (! (   search_state.best_rparen
+	     && search_state.best_lparen
+	     && search_state.lparen && search_state.rparen))
+	return rx_search_error;
+      
+      search_state.best_last_l = search_state.best_last_r = -1;
+      
+      search_state.translate = (rxb->translate
+				? rxb->translate
+				: rx_id_translation);
+      
+      
+      
+      /*
+       * two nfa's were compiled.  
+       * `0' is complete.
+       * `1' faster but gets registers wrong and ends too soon.
+       */
+      search_state.nfa_choice = (regs && !rxb->least_subs) ? '\0' : '\1';
+      
+      /* we have the option to look for the best match or the first
+       * one we can find.  if the user isn't asking for register information,
+       * we don't need to find the best match.
+       */
+      search_state.first_found = !regs;
+      
+      if (range >= 0)
+	{
+	  search_state.outer_pos.search_end = startpos + range;
+	  search_state.outer_pos.search_direction = 1;
+	}
+      else
+	{
+	  search_state.outer_pos.search_end = startpos + range;
+	  search_state.outer_pos.search_direction = -1;
+	}
+      
+      /* the vacuous search always turns up nothing. */
+      if ((search_state.outer_pos.search_direction == 1)
+	  ? (startpos > search_state.outer_pos.search_end)
+	  : (startpos < search_state.outer_pos.search_end))
+	return rx_search_fail;
+      
+      /* now we build the starting state of the supernfa. */
+      {
+	struct rx_superset * start_contents;
+	struct rx_nfa_state_set * start_nfa_set;
+	
+	/* we presume here that the nfa start state has only one
+	 * possible future with no side effects.  
+	 */
+	start_nfa_set = rxb->start->futures->destset;
+	if (   rxb->rx.start_set
+	    && (rxb->rx.start_set->starts_for == &rxb->rx))
+	  start_contents = rxb->rx.start_set;
+	else
+	  {
+	    start_contents =
+	      rx_superstate_eclosure_union (&rxb->rx,
+					    rx_superset_cons (&rxb->rx, 0, 0),
+					    start_nfa_set);
+	    
+	    if (!start_contents)
+	      return rx_search_fail;
+	    
+	    start_contents->starts_for = &rxb->rx;
+	    rxb->rx.start_set = start_contents;
+	  }
+	if (   start_contents->superstate
+	    && (start_contents->superstate->rx_id == rxb->rx.rx_id))
+	  {
+	    search_state.start_super = start_contents->superstate;
+	    rx_lock_superstate (&rxb->rx, search_state.start_super);
+	  }
+	else
+	  {
+	    rx_protect_superset (&rxb->rx, start_contents);
+	    
+	    search_state.start_super = rx_superstate (&rxb->rx, start_contents);
+	    if (!search_state.start_super)
+	      return rx_search_fail;
+	    rx_lock_superstate (&rxb->rx, search_state.start_super);
+	    rx_release_superset (&rxb->rx, start_contents);
+	  }
+      }
+      
+      
+      /* The outer_pos tracks the position within the strings
+       * as seen by loop that calls fastmap_search.
+       *
+       * The caller supplied get_burst function actually 
+       * gives us pointers to chars.
+       * 
+       * Communication with the get_burst function is through an
+       * rx_string_position structure.  Here, the structure for
+       * outer_pos is initialized.   It is set to point to the
+       * NULL string, at an offset of STARTPOS.  STARTPOS is out
+       * of range of the NULL string, so the first call to 
+       * getburst will patch up the rx_string_position to point
+       * to valid characters.
+       */
+
+      (  search_state.outer_pos.string
+       = search_state.outer_pos.end
+       = 0);
+
+      search_state.outer_pos.offset = 0;
+      search_state.outer_pos.size = 0;
+      search_state.outer_pos.pos = (unsigned char *)startpos;
+      init_fastmap (rxb, &search_state);
+
+      search_state.fastmap_resume_pt = rx_fastmap_start;
+    case rx_outer_fastmap:
+      /* do { */
+    pseudo_do:
+      {
+	{
+	  int fastmap_state;
+	  fastmap_state = fastmap_search (rxb, stop, get_burst, app_closure,
+					  &search_state);
+	  switch (fastmap_state)
+	    {
+	    case rx_fastmap_continuation:
+	      pc = rx_outer_fastmap;
+	      goto return_continuation;
+	    case rx_fastmap_fail:
+	      goto finish;
+	    case rx_fastmap_ok:
+	      break;
+	    }
+	}
+	
+	/* now the fastmap loop has brought us to a plausible 
+	 * starting point for a match.  so, it's time to run the
+	 * nfa and see if a match occured.
+	 */
+	startpos = (  search_state.outer_pos.pos
+		    - search_state.outer_pos.string
+		    + search_state.outer_pos.offset);
+#if 0
+/*|*/	if ((range > 0) && (startpos == search_state.outer_pos.search_end))
+/*|*/	  goto finish;
+#endif
+      }
+
+      search_state.test_match_resume_pt = rx_test_start;
+      /* do interrupted for entry point... */
+    case rx_outer_test:
+      /* ...do continued */
+      {
+	goto test_match;
+      test_returns_to_search:
+	switch (test_state)
+	  {
+	  case rx_test_continuation:
+	    pc = rx_outer_test;
+	    goto return_continuation;
+	  case rx_test_error:
+	    search_state.ret_val = rx_search_error;
+	    goto finish;
+	  case rx_test_fail:
+	    break;
+	  case rx_test_ok:
+	    goto finish;
+	  }
+	search_state.outer_pos.pos += search_state.outer_pos.search_direction;
+	startpos += search_state.outer_pos.search_direction;
+#if 0
+/*|*/	if (search_state.test_pos.pos < search_state.test_pos.end)
+/*|*/	  break;
+#endif
+      }
+      /* do interrupted for entry point... */
+    case rx_outer_restore_pos:
+      {
+	int x;
+	x = get_burst (&search_state.outer_pos, app_closure, stop);
+	switch (x)
+	  {
+	  case rx_get_burst_continuation:
+	    pc = rx_outer_restore_pos;
+	    goto return_continuation;
+	  case rx_get_burst_error:
+	    search_state.ret_val = rx_search_error;
+	    goto finish;
+	  case rx_get_burst_no_more:
+	    if (rxb->can_match_empty)
+	      break;
+	    goto finish;
+	  case rx_get_burst_ok:
+	    break;
+	  }
+      } /* } while (...see below...) */
+
+      if ((search_state.outer_pos.search_direction == 1)
+	  ? (startpos <= search_state.outer_pos.search_end)
+	  : (startpos > search_state.outer_pos.search_end))
+	goto pseudo_do;
+
+	
+    finish:
+      uninit_fastmap (rxb, &search_state);
+      if (search_state.start_super)
+	rx_unlock_superstate (&rxb->rx, search_state.start_super);
+      
+#ifdef regex_malloc
+      if (search_state.lparen) free (search_state.lparen);
+      if (search_state.rparen) free (search_state.rparen);
+      if (search_state.best_lpspace) free (search_state.best_lpspace);
+      if (search_state.best_rpspace) free (search_state.best_rpspace);
+#endif
+      return search_state.ret_val;
+    }
+
+
+ test_match:
+  {
+    enum rx_test_match_entry test_pc;
+    int inx;
+    test_pc = search_state.test_match_resume_pt;
+    if (test_pc == rx_test_start)
+      {
+#ifdef RX_DEBUG
+	search_state.backtrack_depth = 0;
+#endif
+	search_state.last_l = search_state.last_r = 0;
+	search_state.lparen[0] = startpos;
+	search_state.super = search_state.start_super;
+	search_state.c = search_state.nfa_choice;
+	search_state.test_pos.pos = search_state.outer_pos.pos - 1;    
+	search_state.test_pos.string = search_state.outer_pos.string;
+	search_state.test_pos.end = search_state.outer_pos.end;
+	search_state.test_pos.offset = search_state.outer_pos.offset;
+	search_state.test_pos.size = search_state.outer_pos.size;
+	search_state.test_pos.search_direction = 1;
+	search_state.counter_stack = 0;
+	search_state.backtrack_stack = 0;
+	search_state.backtrack_frame_bytes =
+	  (sizeof (struct rx_backtrack_frame)
+	   + (rxb->match_regs_on_stack
+	      ? sizeof (regoff_t) * (search_state.num_regs + 1) * 2
+	      : 0));
+	search_state.chunk_bytes = search_state.backtrack_frame_bytes * 64;
+	search_state.test_ret = rx_test_line_finished;
+	search_state.could_have_continued = 0;
+      }  
+    /* This is while (1)...except that the body of the loop is interrupted 
+     * by some alternative entry points.
+     */
+  pseudo_while_1:
+    switch (test_pc)
+      {
+      case rx_test_cache_hit_loop:
+	goto resume_continuation_1;
+      case rx_test_backreference_check:
+	goto resume_continuation_2;
+      case rx_test_backtrack_return:
+	goto resume_continuation_3;
+      case rx_test_start:
+#ifdef RX_DEBUG
+	/* There is a search tree with every node as set of deterministic
+	 * transitions in the super nfa.  For every branch of a 
+	 * backtrack point is an edge in the tree.
+	 * This counts up a pre-order of nodes in that tree.
+	 * It's saved on the search stack and printed when debugging. 
+	 */
+	search_state.line_no = 0;
+	search_state.lines_found = 0;
+#endif
+	
+      top_of_cycle:
+	/* A superstate is basicly a transition table, indexed by 
+	 * characters from the string being tested, and containing 
+	 * RX_INX (`instruction frame') structures.
+	 */
+	search_state.ifr = &search_state.super->transitions [search_state.c];
+	
+      recurse_test_match:
+	/* This is the point to which control is sent when the
+	 * test matcher `recurses'.  Before jumping here, some variables
+	 * need to be saved on the stack and the next instruction frame
+	 * has to be computed.
+	 */
+	
+      restart:
+	/* Some instructions don't advance the matcher, but just
+	 * carry out some side effects and fetch a new instruction.
+	 * To dispatch that new instruction, `goto restart'.
+	 */
+	
+	{
+	  struct rx_inx * next_tr_table;
+	  struct rx_inx * this_tr_table;
+	  /* The fastest route through the loop is when the instruction 
+	   * is RX_NEXT_CHAR.  This case is detected when SEARCH_STATE.IFR->DATA
+	   * is non-zero.  In that case, it points to the next
+	   * superstate. 
+	   *
+	   * This allows us to not bother fetching the bytecode.
+	   */
+	  next_tr_table = (struct rx_inx *)search_state.ifr->data;
+	  this_tr_table = search_state.super->transitions;
+	  while (next_tr_table)
+	    {
+#ifdef RX_DEBUG_0
+	      if (rx_debug_trace)
+		{
+		  struct rx_superset * setp;
+		  
+		  fprintf (stderr, "%d %d>> re_next_char @ %d (%d)",
+			   search_state.line_no,
+			   search_state.backtrack_depth,
+			   (search_state.test_pos.pos - search_state.test_pos.string
+			    + search_state.test_pos.offset), search_state.c);
+		  
+		  search_state.super =
+		    ((struct rx_superstate *)
+		     ((char *)this_tr_table
+		      - ((unsigned long)
+			 ((struct rx_superstate *)0)->transitions)));
+		  
+		  setp = search_state.super->contents;
+		  fprintf (stderr, "   superstet (rx=%d, &=%x: ",
+			   rxb->rx.rx_id, setp);
+		  while (setp)
+		    {
+		      fprintf (stderr, "%d ", setp->id);
+		      setp = setp->cdr;
+		    }
+		  fprintf (stderr, "\n");
+		}
+#endif
+	      this_tr_table = next_tr_table;
+	      ++search_state.test_pos.pos;
+	      if (search_state.test_pos.pos == search_state.test_pos.end)
+		{
+		  int burst_state;
+		try_burst_1:
+		  burst_state = get_burst (&search_state.test_pos,
+					   app_closure, stop);
+		  switch (burst_state)
+		    {
+		    case rx_get_burst_continuation:
+		      search_state.saved_this_tr_table = this_tr_table;
+		      search_state.saved_next_tr_table = next_tr_table;
+		      test_pc = rx_test_cache_hit_loop;
+		      goto test_return_continuation;
+		      
+		    resume_continuation_1:
+		      /* Continuation one jumps here to do its work: */
+		      search_state.saved_this_tr_table = this_tr_table;
+		      search_state.saved_next_tr_table = next_tr_table;
+		      goto try_burst_1;
+		      
+		    case rx_get_burst_ok:
+		      /* get_burst succeeded...keep going */
+		      break;
+		      
+		    case rx_get_burst_no_more:
+		      search_state.test_ret = rx_test_line_finished;
+		      search_state.could_have_continued = 1;
+		      goto test_do_return;
+		      
+		    case rx_get_burst_error:
+		      /* An error... */
+		      search_state.test_ret = rx_test_internal_error;
+		      goto test_do_return;
+		    }
+		}
+	      search_state.c = *search_state.test_pos.pos;
+	      search_state.ifr = this_tr_table + search_state.c;
+	      next_tr_table = (struct rx_inx *)search_state.ifr->data;
+	    } /* Fast loop through cached transition tables */
+	  
+	  /* Here when we ran out of cached next-char transitions. 
+	   * So, it will be necessary to do a more expensive
+	   * dispatch on the current instruction.  The superstate
+	   * pointer is allowed to become invalid during next-char
+	   * transitions -- now we must bring it up to date.
+	   */
+	  search_state.super =
+	    ((struct rx_superstate *)
+	     ((char *)this_tr_table
+	      - ((unsigned long)
+		 ((struct rx_superstate *)0)->transitions)));
+	}
+	
+	/* We've encountered an instruction other than next-char.
+	 * Dispatch that instruction:
+	 */
+	inx = (int)search_state.ifr->inx;
+#ifdef RX_DEBUG_0
+	if (rx_debug_trace)
+	  {
+	    struct rx_superset * setp = search_state.super->contents;
+	    
+	    fprintf (stderr, "%d %d>> %s @ %d (%d)", search_state.line_no,
+		     search_state.backtrack_depth,
+		     inx_names[inx],
+		     (search_state.test_pos.pos - search_state.test_pos.string
+		      + (test_pos.half == 0 ? 0 : size1)), search_state.c);
+	    
+	    fprintf (stderr, "   superstet (rx=%d, &=%x: ",
+		     rxb->rx.rx_id, setp);
+	    while (setp)
+	      {
+		fprintf (stderr, "%d ", setp->id);
+		setp = setp->cdr;
+	      }
+	    fprintf (stderr, "\n");
+	  }
+#endif
+	switch ((enum rx_opcode)inx)
+	  {
+	  case rx_do_side_effects:
+	    
+	    /*  RX_DO_SIDE_EFFECTS occurs when we cross epsilon 
+	     *  edges associated with parentheses, backreferencing, etc.
+	     */
+	    {
+	      struct rx_distinct_future * df =
+		(struct rx_distinct_future *)search_state.ifr->data_2;
+	      struct rx_se_list * el = df->effects;
+	      /* Side effects come in lists.  This walks down
+	       * a list, dispatching.
+	       */
+	      while (el)
+		{
+		  long effect;
+		  effect = (long)el->car;
+		  if (effect < 0)
+		    {
+#ifdef RX_DEBUG_0
+		      if (rx_debug_trace)
+			{
+			  struct rx_superset * setp = search_state.super->contents;
+			  
+			  fprintf (stderr, "....%d %d>> %s\n", search_state.line_no,
+				   search_state.backtrack_depth,
+				   efnames[-effect]);
+			}
+#endif
+		      switch ((enum re_side_effects) effect)
+
+			{
+			case re_se_pushback:
+			  search_state.ifr = &df->future_frame;
+			  if (!search_state.ifr->data)
+			    {
+			      struct rx_superstate * sup;
+			      sup = search_state.super;
+			      rx_lock_superstate (rx, sup);
+			      if (!rx_handle_cache_miss (&rxb->rx,
+							 search_state.super,
+							 search_state.c,
+							 (search_state.ifr
+							  ->data_2)))
+				{
+				  rx_unlock_superstate (rx, sup);
+				  search_state.test_ret = rx_test_internal_error;
+				  goto test_do_return;
+				}
+			      rx_unlock_superstate (rx, sup);
+			    }
+			  /* --search_state.test_pos.pos; */
+			  search_state.c = 't';
+			  search_state.super
+			    = ((struct rx_superstate *)
+			       ((char *)search_state.ifr->data
+				- (long)(((struct rx_superstate *)0)
+					 ->transitions)));
+			  goto top_of_cycle;
+			  break;
+			case re_se_push0:
+			  {
+			    struct rx_counter_frame * old_cf
+			      = (search_state.counter_stack
+				 ? ((struct rx_counter_frame *)
+				    search_state.counter_stack->sp)
+				 : 0);
+			    struct rx_counter_frame * cf;
+			    PUSH (search_state.counter_stack,
+				  sizeof (struct rx_counter_frame));
+			    cf = ((struct rx_counter_frame *)
+				  search_state.counter_stack->sp);
+			    cf->tag = re_se_iter;
+			    cf->val = 0;
+			    cf->inherited_from = 0;
+			    cf->cdr = old_cf;
+			    break;
+			  }
+			case re_se_fail:
+			  goto test_do_return;
+			case re_se_begbuf:
+			  if (!AT_STRINGS_BEG ())
+			    goto test_do_return;
+			  break;
+			case re_se_endbuf:
+			  if (!AT_STRINGS_END ())
+			    goto test_do_return;
+			  break;
+			case re_se_wordbeg:
+			  if (   LETTER_P (&search_state.test_pos, 1)
+			      && (   AT_STRINGS_BEG()
+				  || !LETTER_P (&search_state.test_pos, 0)))
+			    break;
+			  else
+			    goto test_do_return;
+			case re_se_wordend:
+			  if (   !AT_STRINGS_BEG ()
+			      && LETTER_P (&search_state.test_pos, 0)
+			      && (AT_STRINGS_END ()
+				  || !LETTER_P (&search_state.test_pos, 1)))
+			    break;
+			  else
+			    goto test_do_return;
+			case re_se_wordbound:
+			  if (AT_WORD_BOUNDARY (&search_state.test_pos))
+			    break;
+			  else
+			    goto test_do_return;
+			case re_se_notwordbound:
+			  if (!AT_WORD_BOUNDARY (&search_state.test_pos))
+			    break;
+			  else
+			    goto test_do_return;
+			case re_se_hat:
+			  if (AT_STRINGS_BEG ())
+			    {
+			      if (rxb->not_bol)
+				goto test_do_return;
+			      else
+				break;
+			    }
+			  else
+			    {
+			      char pos_c = *search_state.test_pos.pos;
+			      if (   (SRCH_TRANSLATE (pos_c)
+				      == SRCH_TRANSLATE('\n'))
+				  && rxb->newline_anchor)
+				break;
+			      else
+				goto test_do_return;
+			    }
+			case re_se_dollar:
+			  if (AT_STRINGS_END ())
+			    {
+			      if (rxb->not_eol)
+				goto test_do_return;
+			      else
+				break;
+			    }
+			  else
+			    {
+			      if (   (   SRCH_TRANSLATE (fetch_char
+						    (&search_state.test_pos, 1,
+						     app_closure, stop))
+				      == SRCH_TRANSLATE ('\n'))
+				  && rxb->newline_anchor)
+				break;
+			      else
+				goto test_do_return;
+			    }
+			  
+			case re_se_try:
+			  /* This is the first side effect in every
+			   * expression.
+			   *
+			   *  FOR NO GOOD REASON...get rid of it...
+			   */
+			  break;
+			  
+			case re_se_pushpos:
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    struct rx_counter_frame * old_cf
+			      = (search_state.counter_stack
+				 ? ((struct rx_counter_frame *)
+				    search_state.counter_stack->sp)
+				 : 0);
+			    struct rx_counter_frame * cf;
+			    PUSH(search_state.counter_stack,
+				 sizeof (struct rx_counter_frame));
+			    cf = ((struct rx_counter_frame *)
+				  search_state.counter_stack->sp);
+			    cf->tag = re_se_pushpos;
+			    cf->val = urhere;
+			    cf->inherited_from = 0;
+			    cf->cdr = old_cf;
+			    break;
+			  }
+			  
+			case re_se_chkpos:
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    struct rx_counter_frame * cf
+			      = ((struct rx_counter_frame *)
+				 search_state.counter_stack->sp);
+			    if (cf->val == urhere)
+			      goto test_do_return;
+			    cf->val = urhere;
+			    break;
+			  }
+			  break;
+			  
+			case re_se_poppos:
+			  POP(search_state.counter_stack,
+			      sizeof (struct rx_counter_frame));
+			  break;
+			  
+			  
+			case re_se_at_dot:
+			case re_se_syntax:
+			case re_se_not_syntax:
+#ifdef emacs
+			  /* 
+			   * this release lacks emacs support
+			   */
+#endif
+			  break;
+			case re_se_win:
+			case re_se_lparen:
+			case re_se_rparen:
+			case re_se_backref:
+			case re_se_iter:
+			case re_se_end_iter:
+			case re_se_tv:
+			case re_floogle_flap:
+			  search_state.ret_val = 0;
+			  goto test_do_return;
+			}
+		    }
+		  else
+		    {
+#ifdef RX_DEBUG_0
+		      if (rx_debug_trace)
+			fprintf (stderr, "....%d %d>> %s %d %d\n", search_state.line_no,
+				 search_state.backtrack_depth,
+				 efnames2[rxb->se_params [effect].se],
+				 rxb->se_params [effect].op1,
+				 rxb->se_params [effect].op2);
+#endif
+		      switch (rxb->se_params [effect].se)
+			{
+			case re_se_win:
+			  /* This side effect indicates that we've 
+			   * found a match, though not necessarily the 
+			   * best match.  This is a fancy assignment to 
+			   * register 0 unless the caller didn't 
+			   * care about registers.  In which case,
+			   * this stops the match.
+			   */
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    
+			    if (   (search_state.best_last_r < 0)
+				|| (urhere + 1 > search_state.best_rparen[0]))
+			      {
+				/* Record the best known and keep
+				 * looking.
+				 */
+				int x;
+				for (x = 0; x <= search_state.last_l; ++x)
+				  search_state.best_lparen[x] = search_state.lparen[x];
+				search_state.best_last_l = search_state.last_l;
+				for (x = 0; x <= search_state.last_r; ++x)
+				  search_state.best_rparen[x] = search_state.rparen[x];
+				search_state.best_rparen[0] = urhere + 1;
+				search_state.best_last_r = search_state.last_r;
+			      }
+			    /* If we're not reporting the match-length 
+			     * or other register info, we need look no
+			     * further.
+			     */
+			    if (search_state.first_found)
+			      {
+				search_state.test_ret = rx_test_found_first;
+				goto test_do_return;
+			      }
+			  }
+			  break;
+			case re_se_lparen:
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    
+			    int reg = rxb->se_params [effect].op1;
+#if 0
+			    if (reg > search_state.last_l)
+#endif
+			      {
+				search_state.lparen[reg] = urhere + 1;
+				/* In addition to making this assignment,
+				 * we now know that lower numbered regs
+				 * that haven't already been assigned,
+				 * won't be.  We make sure they're
+				 * filled with -1, so they can be
+				 * recognized as unassigned.
+				 */
+				if (search_state.last_l < reg)
+				  while (++search_state.last_l < reg)
+				    search_state.lparen[search_state.last_l] = -1;
+			      }
+			    break;
+			  }
+			  
+			case re_se_rparen:
+			  {
+			    int urhere =
+			      ((int)(search_state.test_pos.pos
+				     - search_state.test_pos.string)
+			       + search_state.test_pos.offset);
+			    int reg = rxb->se_params [effect].op1;
+			    search_state.rparen[reg] = urhere + 1;
+			    if (search_state.last_r < reg)
+			      {
+				while (++search_state.last_r < reg)
+				  search_state.rparen[search_state.last_r]
+				    = -1;
+			      }
+			    break;
+			  }
+			  
+			case re_se_backref:
+			  {
+			    int reg = rxb->se_params [effect].op1;
+			    if (   reg > search_state.last_r
+				|| search_state.rparen[reg] < 0)
+			      goto test_do_return;
+			    
+			    {
+			      int backref_status;
+			    check_backreference:
+			      backref_status
+				= back_check (&search_state.test_pos,
+					      search_state.lparen[reg],
+					      search_state.rparen[reg],
+					      search_state.translate,
+					      app_closure,
+					      stop);
+			      switch (backref_status)
+				{
+				case rx_back_check_continuation:
+				  search_state.saved_reg = reg;
+				  test_pc = rx_test_backreference_check;
+				  goto test_return_continuation;
+				resume_continuation_2:
+				  reg = search_state.saved_reg;
+				  goto check_backreference;
+				case rx_back_check_fail:
+				  /* Fail */
+				  goto test_do_return;
+				case rx_back_check_pass:
+				  /* pass --
+				   * test_pos now advanced to last
+				   * char matched by backref
+				   */
+				  break;
+				}
+			    }
+			    break;
+			  }
+			case re_se_iter:
+			  {
+			    struct rx_counter_frame * csp
+			      = ((struct rx_counter_frame *)
+				 search_state.counter_stack->sp);
+			    if (csp->val == rxb->se_params[effect].op2)
+			      goto test_do_return;
+			    else
+			      ++csp->val;
+			    break;
+			  }
+			case re_se_end_iter:
+			  {
+			    struct rx_counter_frame * csp
+			      = ((struct rx_counter_frame *)
+				 search_state.counter_stack->sp);
+			    if (csp->val < rxb->se_params[effect].op1)
+			      goto test_do_return;
+			    else
+			      {
+				struct rx_counter_frame * source = csp;
+				while (source->inherited_from)
+				  source = source->inherited_from;
+				if (!source || !source->cdr)
+				  {
+				    POP(search_state.counter_stack,
+					sizeof(struct rx_counter_frame));
+				  }
+				else
+				  {
+				    source = source->cdr;
+				    csp->val = source->val;
+				    csp->tag = source->tag;
+				    csp->cdr = 0;
+				    csp->inherited_from = source;
+				  }
+			      }
+			    break;
+			  }
+			case re_se_tv:
+			  /* is a noop */
+			  break;
+			case re_se_try:
+			case re_se_pushback:
+			case re_se_push0:
+			case re_se_pushpos:
+			case re_se_chkpos:
+			case re_se_poppos:
+			case re_se_at_dot:
+			case re_se_syntax:
+			case re_se_not_syntax:
+			case re_se_begbuf:
+			case re_se_hat:
+			case re_se_wordbeg:
+			case re_se_wordbound:
+			case re_se_notwordbound:
+			case re_se_wordend:
+			case re_se_endbuf:
+			case re_se_dollar:
+			case re_se_fail:
+			case re_floogle_flap:
+			  search_state.ret_val = 0;
+			  goto test_do_return;
+			}
+		    }
+		  el = el->cdr;
+		}
+	      /* Now the side effects are done,
+	       * so get the next instruction.
+	       * and move on.
+	       */
+	      search_state.ifr = &df->future_frame;
+	      goto restart;
+	    }
+	    
+	  case rx_backtrack_point:
+	    {
+	      /* A backtrack point indicates that we've reached a
+	       * non-determinism in the superstate NFA.  This is a
+	       * loop that exhaustively searches the possibilities.
+	       *
+	       * A backtracking strategy is used.  We keep track of what
+	       * registers are valid so we can erase side effects.
+	       *
+	       * First, make sure there is some stack space to hold 
+	       * our state.
+	       */
+	      
+	      struct rx_backtrack_frame * bf;
+	      
+	      PUSH(search_state.backtrack_stack,
+		   search_state.backtrack_frame_bytes);
+#ifdef RX_DEBUG_0
+	      ++search_state.backtrack_depth;
+#endif
+	      
+	      bf = ((struct rx_backtrack_frame *)
+		    search_state.backtrack_stack->sp);
+	      {
+		bf->stk_super = search_state.super;
+		/* We prevent the current superstate from being
+		 * deleted from the superstate cache.
+		 */
+		rx_lock_superstate (&rxb->rx, search_state.super);
+#ifdef RX_DEBUG_0
+		bf->stk_search_state.line_no = search_state.line_no;
+#endif
+		bf->stk_c = search_state.c;
+		bf->stk_test_pos = search_state.test_pos;
+		bf->stk_last_l = search_state.last_l;
+		bf->stk_last_r = search_state.last_r;
+		bf->df = ((struct rx_super_edge *)
+			  search_state.ifr->data_2)->options;
+		bf->first_df = bf->df;
+		bf->counter_stack_sp = (search_state.counter_stack
+					? search_state.counter_stack->sp
+					: 0);
+		bf->stk_test_ret = search_state.test_ret;
+		if (rxb->match_regs_on_stack)
+		  {
+		    int x;
+		    regoff_t * stk =
+		      (regoff_t *)((char *)bf + sizeof (*bf));
+		    for (x = 0; x <= search_state.last_l; ++x)
+		      stk[x] = search_state.lparen[x];
+		    stk += x;
+		    for (x = 0; x <= search_state.last_r; ++x)
+		      stk[x] = search_state.rparen[x];
+		  }
+	      }
+	      
+	      /* Here is a while loop whose body is mainly a function
+	       * call and some code to handle a return from that
+	       * function.
+	       *
+	       * From here on for the rest of `case backtrack_point' it
+	       * is unsafe to assume that the search_state copies of 
+	       * variables saved on the backtracking stack are valid
+	       * -- so read their values from the backtracking stack.
+	       *
+	       * This lets us use one generation fewer stack saves in
+	       * the call-graph of a search.
+	       */
+	      
+	    while_non_det_options:
+#ifdef RX_DEBUG_0
+	      ++search_state.lines_found;
+	      if (rx_debug_trace)
+		fprintf (stderr, "@@@ %d calls %d @@@\n",
+			 search_state.line_no, search_state.lines_found);
+	      
+	      search_state.line_no = search_state.lines_found;
+#endif
+	      
+	      if (bf->df->next_same_super_edge[0] == bf->first_df)
+		{
+		  /* This is a tail-call optimization -- we don't recurse
+		   * for the last of the possible futures.
+		   */
+		  search_state.ifr = (bf->df->effects
+				      ? &bf->df->side_effects_frame
+				      : &bf->df->future_frame);
+		  
+		  rx_unlock_superstate (&rxb->rx, search_state.super);
+		  POP(search_state.backtrack_stack,
+		      search_state.backtrack_frame_bytes);
+#ifdef RX_DEBUG
+		  --search_state.backtrack_depth;
+#endif
+		  goto restart;
+		}
+	      else
+		{
+		  if (search_state.counter_stack)
+		    {
+		      struct rx_counter_frame * old_cf
+			= ((struct rx_counter_frame *)search_state.counter_stack->sp);
+		      struct rx_counter_frame * cf;
+		      PUSH(search_state.counter_stack, sizeof (struct rx_counter_frame));
+		      cf = ((struct rx_counter_frame *)search_state.counter_stack->sp);
+		      cf->tag = old_cf->tag;
+		      cf->val = old_cf->val;
+		      cf->inherited_from = old_cf;
+		      cf->cdr = 0;
+		    }			
+		  /* `Call' this test-match block */
+		  search_state.ifr = (bf->df->effects
+				      ? &bf->df->side_effects_frame
+				      : &bf->df->future_frame);
+		  goto recurse_test_match;
+		}
+	      
+	      /* Returns in this block are accomplished by
+	       * goto test_do_return.  There are two cases.
+	       * If there is some search-stack left,
+	       * then it is a return from a `recursive' call.
+	       * If there is no search-stack left, then
+	       * we should return to the fastmap/search loop.
+	       */
+	      
+	    test_do_return:
+	      
+	      if (!search_state.backtrack_stack)
+		{
+#ifdef RX_DEBUG_0
+		  if (rx_debug_trace)
+		    fprintf (stderr, "!!! %d bails returning %d !!!\n",
+			     search_state.line_no, search_state.test_ret);
+#endif
+		  
+		  /* No more search-stack -- this test is done. */
+		  if (search_state.test_ret != rx_test_internal_error)
+		    goto return_from_test_match;
+		  else
+		    goto error_in_testing_match;
+		}
+	      
+	      /* Returning from a recursive call to 
+	       * the test match block:
+	       */
+	      
+	      bf = ((struct rx_backtrack_frame *)
+		    search_state.backtrack_stack->sp);
+#ifdef RX_DEBUG_0
+	      if (rx_debug_trace)
+		fprintf (stderr, "+++ %d returns %d (to %d)+++\n",
+			 search_state.line_no,
+			 search_state.test_ret,
+			 bf->stk_search_state.line_no);
+#endif
+	      
+	      while (search_state.counter_stack
+		     && (!bf->counter_stack_sp
+			 || (bf->counter_stack_sp
+			     != search_state.counter_stack->sp)))
+		{
+		  POP(search_state.counter_stack,
+		      sizeof (struct rx_counter_frame));
+		}
+	      
+	      if (search_state.test_ret == rx_test_internal_error)
+		{
+		  POP (search_state.backtrack_stack,
+		       search_state.backtrack_frame_bytes);
+		  search_state.test_ret = rx_test_internal_error;
+		  goto test_do_return;
+		}
+	      
+	      /* If a non-longest match was found and that is good 
+	       * enough, return immediately.
+	       */
+	      if (   (search_state.test_ret == rx_test_found_first)
+		  && search_state.first_found)
+		{
+		  rx_unlock_superstate (&rxb->rx, bf->stk_super);
+		  POP (search_state.backtrack_stack,
+		       search_state.backtrack_frame_bytes);
+		  goto test_do_return;
+		}
+	      
+	      search_state.test_ret = bf->stk_test_ret;
+	      search_state.last_l = bf->stk_last_l;
+	      search_state.last_r = bf->stk_last_r;
+	      bf->df = bf->df->next_same_super_edge[0];
+	      search_state.super = bf->stk_super;
+	      search_state.c = bf->stk_c;
+#ifdef RX_DEBUG_0
+	      search_state.line_no = bf->stk_search_state.line_no;
+#endif
+	      
+	      if (rxb->match_regs_on_stack)
+		{
+		  int x;
+		  regoff_t * stk =
+		    (regoff_t *)((char *)bf + sizeof (*bf));
+		  for (x = 0; x <= search_state.last_l; ++x)
+		    search_state.lparen[x] = stk[x];
+		  stk += x;
+		  for (x = 0; x <= search_state.last_r; ++x)
+		    search_state.rparen[x] = stk[x];
+		}
+	      
+	      {
+		int x;
+	      try_burst_2:
+		x = get_burst (&bf->stk_test_pos, app_closure, stop);
+		switch (x)
+		  {
+		  case rx_get_burst_continuation:
+		    search_state.saved_bf = bf;
+		    test_pc = rx_test_backtrack_return;
+		    goto test_return_continuation;
+		  resume_continuation_3:
+		    bf = search_state.saved_bf;
+		    goto try_burst_2;
+		  case rx_get_burst_no_more:
+		    /* Since we've been here before, it is some kind of
+		     * error that we can't return.
+		     */
+		  case rx_get_burst_error:
+		    search_state.test_ret = rx_test_internal_error;
+		    goto test_do_return;
+		  case rx_get_burst_ok:
+		    break;
+		  }
+	      }
+	      search_state.test_pos = bf->stk_test_pos;
+	      goto while_non_det_options;
+	    }
+	    
+	    
+	  case rx_cache_miss:
+	    /* Because the superstate NFA is lazily constructed,
+	     * and in fact may erode from underneath us, we sometimes
+	     * have to construct the next instruction from the hard way.
+	     * This invokes one step in the lazy-conversion.
+	     */
+	    search_state.ifr = rx_handle_cache_miss (&rxb->rx,
+						     search_state.super,
+						     search_state.c,
+						     search_state.ifr->data_2);
+	    if (!search_state.ifr)
+	      {
+		search_state.test_ret = rx_test_internal_error;
+		goto test_do_return;
+	      }
+	    goto restart;
+	    
+	  case rx_backtrack:
+	    /* RX_BACKTRACK means that we've reached the empty
+	     * superstate, indicating that match can't succeed
+	     * from this point.
+	     */
+	    goto test_do_return;
+	    
+	  case rx_next_char:
+	  case rx_error_inx:
+	  case rx_num_instructions:
+	    search_state.ret_val = 0;
+	    goto test_do_return;
+	  }
+	goto pseudo_while_1;
+      }
+    
+    /* Healthy exits from the test-match loop do a 
+     * `goto return_from_test_match'   On the other hand, 
+     * we might end up here.
+     */
+  error_in_testing_match:
+    test_state = rx_test_error;
+    goto test_returns_to_search;
+    
+    /***** fastmap/search loop body
+     *	      considering the results testing for a match
+     */
+    
+  return_from_test_match:
+    
+    if (search_state.best_last_l >= 0)
+      {
+	if (regs && (regs->start != search_state.best_lparen))
+	  {
+	    bcopy (search_state.best_lparen, regs->start,
+		   regs->num_regs * sizeof (int));
+	    bcopy (search_state.best_rparen, regs->end,
+		   regs->num_regs * sizeof (int));
+	  }
+	if (regs && !rxb->no_sub)
+	  {
+	    int q;
+	    int bound = (regs->num_regs > search_state.num_regs
+			 ? regs->num_regs
+			 : search_state.num_regs);
+	    regoff_t * s = regs->start;
+	    regoff_t * e = regs->end;
+	    for (q = search_state.best_last_l + 1;  q < bound; ++q)
+	      s[q] = e[q] = -1;
+	  }
+	search_state.ret_val = search_state.best_lparen[0];
+	test_state = rx_test_ok;
+	goto test_returns_to_search;
+      }
+    else
+      {
+	test_state = rx_test_fail;
+	goto test_returns_to_search;
+      }
+    
+  test_return_continuation:
+    search_state.test_match_resume_pt = test_pc;
+    test_state = rx_test_continuation;
+    goto test_returns_to_search;
+  }
+}
+
+
+
+#endif /* RX_WANT_RX_DEFS */
+
+
+
+#else /* RX_WANT_SE_DEFS */
+  /* Integers are used to represent side effects.
+   *
+   * Simple side effects are given negative integer names by these enums.
+   * 
+   * Non-negative names are reserved for complex effects.
+   *
+   * Complex effects are those that take arguments.  For example, 
+   * a register assignment associated with a group is complex because
+   * it requires an argument to tell which group is being matched.
+   * 
+   * The integer name of a complex effect is an index into rxb->se_params.
+   */
+ 
+  RX_DEF_SE(1, re_se_try, = -1)		/* Epsilon from start state */
+
+  RX_DEF_SE(0, re_se_pushback, = re_se_try - 1)
+  RX_DEF_SE(0, re_se_push0, = re_se_pushback -1)
+  RX_DEF_SE(0, re_se_pushpos, = re_se_push0 - 1)
+  RX_DEF_SE(0, re_se_chkpos, = re_se_pushpos -1)
+  RX_DEF_SE(0, re_se_poppos, = re_se_chkpos - 1)
+
+  RX_DEF_SE(1, re_se_at_dot, = re_se_poppos - 1)	/* Emacs only */
+  RX_DEF_SE(0, re_se_syntax, = re_se_at_dot - 1) /* Emacs only */
+  RX_DEF_SE(0, re_se_not_syntax, = re_se_syntax - 1) /* Emacs only */
+
+  RX_DEF_SE(1, re_se_begbuf, = re_se_not_syntax - 1) /* match beginning of buffer */
+  RX_DEF_SE(1, re_se_hat, = re_se_begbuf - 1) /* match beginning of line */
+
+  RX_DEF_SE(1, re_se_wordbeg, = re_se_hat - 1) 
+  RX_DEF_SE(1, re_se_wordbound, = re_se_wordbeg - 1)
+  RX_DEF_SE(1, re_se_notwordbound, = re_se_wordbound - 1)
+
+  RX_DEF_SE(1, re_se_wordend, = re_se_notwordbound - 1)
+  RX_DEF_SE(1, re_se_endbuf, = re_se_wordend - 1)
+
+  /* This fails except at the end of a line. 
+   * It deserves to go here since it is typicly one of the last steps 
+   * in a match.
+   */
+  RX_DEF_SE(1, re_se_dollar, = re_se_endbuf - 1)
+
+  /* Simple effects: */
+  RX_DEF_SE(1, re_se_fail, = re_se_dollar - 1)
+
+  /* Complex effects.  These are used in the 'se' field of 
+   * a struct re_se_params.  Indexes into the se array
+   * are stored as instructions on nfa edges.
+   */
+  RX_DEF_CPLX_SE(1, re_se_win, = 0)
+  RX_DEF_CPLX_SE(1, re_se_lparen, = re_se_win + 1)
+  RX_DEF_CPLX_SE(1, re_se_rparen, = re_se_lparen + 1)
+  RX_DEF_CPLX_SE(0, re_se_backref, = re_se_rparen + 1)
+  RX_DEF_CPLX_SE(0, re_se_iter, = re_se_backref + 1) 
+  RX_DEF_CPLX_SE(0, re_se_end_iter, = re_se_iter + 1)
+  RX_DEF_CPLX_SE(0, re_se_tv, = re_se_end_iter + 1)
+
+#endif
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/set
===================================================================
--- trunk/src/emx/include/Attic/cpp/set	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/set	(revision 18)
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_SET
+#define __SGI_STL_SET
+
+#ifndef __SGI_STL_INTERNAL_TREE_H
+#include <stl_tree.h>
+#endif
+#include <stl_set.h>
+#include <stl_mset.h>
+
+#endif /* __SGI_STL_SET */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/set.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/set.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/set.h	(revision 18)
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_SET_H
+#define __SGI_STL_SET_H
+
+#include <tree.h>
+#include <stl_set.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::set;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_SET_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/slist
===================================================================
--- trunk/src/emx/include/Attic/cpp/slist	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/slist	(revision 18)
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __SGI_STL_SLIST
+#define __SGI_STL_SLIST
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_unin.h>
+#include <stl_slis.h>
+
+#endif /* __SGI_STL_SLIST */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/slist.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/slist.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/slist.h	(revision 18)
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __SGI_STL_SLIST_H
+#define __SGI_STL_SLIST_H
+
+#include <algobase.h>
+#include <alloc.h>
+#include <stl_slis.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::slist;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_SLIST_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stack
===================================================================
--- trunk/src/emx/include/Attic/cpp/stack	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stack	(revision 18)
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_STACK
+#define __SGI_STL_STACK
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_unin.h>
+#include <stl_dequ.h>
+#include <stl_stac.h>
+
+#endif /* __SGI_STL_STACK */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stack.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stack.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stack.h	(revision 18)
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_STACK_H
+#define __SGI_STL_STACK_H
+
+#include <vector.h>
+#include <deque.h>
+#include <heap.h>
+#include <stl_stac.h>
+#include <stl_queu.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::stack;
+using __STD::queue;
+using __STD::priority_queue;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_STACK_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/std.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/std.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std.h	(revision 18)
@@ -0,0 +1,35 @@
+// This may look like C code, but it is really -*- C++ -*-
+/* 
+Copyright (C) 1988, 1992 Free Software Foundation
+    written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library.  This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.  This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _std_h
+#define _std_h 1
+
+#include <_G_confi.h>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <unistd.h>
+#include <cstdio> 
+#include <cerrno>
+#include <fcntl.h>
+
+extern "C" {
+int strcasecmp _G_ARGS((const char*, const char*));
+}
+
+#endif 
Index: trunk/src/emx/include/Attic/cpp/std/bastring.cc
===================================================================
--- trunk/src/emx/include/Attic/cpp/std/bastring.cc	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std/bastring.cc	(revision 18)
@@ -0,0 +1,518 @@
+// Member templates for the -*- C++ -*- string classes.
+// Copyright (C) 1994, 1998 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files
+// compiled with a GNU compiler to produce an executable, this does not cause
+// the resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+// Written by Jason Merrill based upon the specification by Takanori Adachi
+// in ANSI X3J16/94-0013R2.
+
+extern "C++" {
+template <class charT, class traits, class Allocator>
+inline void * basic_string <charT, traits, Allocator>::Rep::
+operator new (size_t s, size_t extra)
+{
+  return Allocator::allocate(s + extra * sizeof (charT));
+}
+
+template <class charT, class traits, class Allocator>
+inline void basic_string <charT, traits, Allocator>::Rep::
+operator delete (void * ptr)
+{
+  Allocator::deallocate(ptr, sizeof(Rep) +
+			reinterpret_cast<Rep *>(ptr)->res *
+			sizeof (charT)); 
+}
+
+template <class charT, class traits, class Allocator>
+inline size_t basic_string <charT, traits, Allocator>::Rep::
+frob_size (size_t s)
+{
+  size_t i = 16;
+  while (i < s) i *= 2;
+  return i;
+}
+
+template <class charT, class traits, class Allocator>
+inline basic_string <charT, traits, Allocator>::Rep *
+basic_string <charT, traits, Allocator>::Rep::
+create (size_t extra)
+{
+  extra = frob_size (extra + 1);
+  Rep *p = new (extra) Rep;
+  p->res = extra;
+  p->ref = 1;
+  p->selfish = false;
+  return p;
+}
+
+template <class charT, class traits, class Allocator>
+charT * basic_string <charT, traits, Allocator>::Rep::
+clone ()
+{
+  Rep *p = Rep::create (len);
+  p->copy (0, data (), len);
+  p->len = len;
+  return p->data ();
+}
+
+template <class charT, class traits, class Allocator>
+inline bool basic_string <charT, traits, Allocator>::Rep::
+excess_slop (size_t s, size_t r)
+{
+  return 2 * (s <= 16 ? 16 : s) < r;
+}
+
+template <class charT, class traits, class Allocator>
+inline bool basic_string <charT, traits, Allocator>::
+check_realloc (basic_string::size_type s) const
+{
+  s += sizeof (charT);
+  rep ()->selfish = false;
+  return (rep ()->ref > 1
+	  || s > capacity ()
+	  || Rep::excess_slop (s, capacity ()));
+}
+
+template <class charT, class traits, class Allocator>
+void basic_string <charT, traits, Allocator>::
+alloc (basic_string::size_type size, bool save)
+{
+  if (! check_realloc (size))
+    return;
+
+  Rep *p = Rep::create (size);
+
+  if (save)
+    {
+      p->copy (0, data (), length ());
+      p->len = length ();
+    }
+  else
+    p->len = 0;
+
+  repup (p);
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>&
+basic_string <charT, traits, Allocator>::
+replace (size_type pos1, size_type n1,
+	 const basic_string& str, size_type pos2, size_type n2)
+{
+  const size_t len2 = str.length ();
+
+  if (pos1 == 0 && n1 >= length () && pos2 == 0 && n2 >= len2)
+    return operator= (str);
+
+  OUTOFRANGE (pos2 > len2);
+
+  if (n2 > len2 - pos2)
+    n2 = len2 - pos2;
+
+  return replace (pos1, n1, str.data () + pos2, n2);
+}
+
+template <class charT, class traits, class Allocator>
+inline void basic_string <charT, traits, Allocator>::Rep::
+copy (size_t pos, const charT *s, size_t n)
+{
+  if (n)
+    traits::copy (data () + pos, s, n);
+}
+
+template <class charT, class traits, class Allocator>
+inline void basic_string <charT, traits, Allocator>::Rep::
+move (size_t pos, const charT *s, size_t n)
+{
+  if (n)
+    traits::move (data () + pos, s, n);
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>&
+basic_string <charT, traits, Allocator>::
+replace (size_type pos, size_type n1, const charT* s, size_type n2)
+{
+  const size_type len = length ();
+  OUTOFRANGE (pos > len);
+  if (n1 > len - pos)
+    n1 = len - pos;
+  LENGTHERROR (len - n1 > max_size () - n2);
+  size_t newlen = len - n1 + n2;
+
+  if (check_realloc (newlen))
+    {
+      Rep *p = Rep::create (newlen);
+      p->copy (0, data (), pos);
+      p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
+      p->copy (pos, s, n2);
+      repup (p);
+    }
+  else
+    {
+      rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
+      rep ()->copy (pos, s, n2);
+    }
+  rep ()->len = newlen;
+
+  return *this;
+}
+
+template <class charT, class traits, class Allocator>
+inline void basic_string <charT, traits, Allocator>::Rep::
+set (size_t pos, const charT c, size_t n)
+{
+  traits::set  (data () + pos, c, n);
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
+replace (size_type pos, size_type n1, size_type n2, charT c)
+{
+  const size_t len = length ();
+  OUTOFRANGE (pos > len);
+  if (n1 > len - pos)
+    n1 = len - pos;
+  LENGTHERROR (len - n1 > max_size () - n2);
+  size_t newlen = len - n1 + n2;
+
+  if (check_realloc (newlen))
+    {
+      Rep *p = Rep::create (newlen);
+      p->copy (0, data (), pos);
+      p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
+      p->set  (pos, c, n2);
+      repup (p);
+    }
+  else
+    {
+      rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
+      rep ()->set  (pos, c, n2);
+    }
+  rep ()->len = newlen;
+
+  return *this;
+}
+
+template <class charT, class traits, class Allocator>
+void basic_string <charT, traits, Allocator>::
+resize (size_type n, charT c)
+{
+  LENGTHERROR (n > max_size ());
+
+  if (n > length ())
+    append (n - length (), c);
+  else
+    erase (n);
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+copy (charT* s, size_type n, size_type pos)
+{
+  OUTOFRANGE (pos > length ());
+
+  if (n > length () - pos)
+    n = length () - pos;
+
+  traits::copy (s, data () + pos, n);
+  return n;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+find (const charT* s, size_type pos, size_type n) const
+{
+  size_t xpos = pos;
+  for (; xpos + n <= length (); ++xpos)
+    if (traits::eq (data () [xpos], *s)
+	&& traits::compare (data () + xpos, s, n) == 0)
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+inline basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+_find (const charT* ptr, charT c, size_type xpos, size_type len)
+{
+  for (; xpos < len; ++xpos)
+    if (traits::eq (ptr [xpos], c))
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+find (charT c, size_type pos) const
+{
+  return _find (data (), c, pos, length ());
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+rfind (const charT* s, size_type pos, size_type n) const
+{
+  if (n > length ())
+    return npos;
+
+  size_t xpos = length () - n;
+  if (xpos > pos)
+    xpos = pos;
+
+  for (++xpos; xpos-- > 0; )
+    if (traits::eq (data () [xpos], *s)
+	&& traits::compare (data () + xpos, s, n) == 0)
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+rfind (charT c, size_type pos) const
+{
+  if (1 > length ())
+    return npos;
+
+  size_t xpos = length () - 1;
+  if (xpos > pos)
+    xpos = pos;
+
+  for (++xpos; xpos-- > 0; )
+    if (traits::eq (data () [xpos], c))
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+find_first_of (const charT* s, size_type pos, size_type n) const
+{
+  size_t xpos = pos;
+  for (; xpos < length (); ++xpos)
+    if (_find (s, data () [xpos], 0, n) != npos)
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+find_last_of (const charT* s, size_type pos, size_type n) const
+{
+  size_t xpos = length () - 1;
+  if (xpos > pos)
+    xpos = pos;
+  for (; xpos; --xpos)
+    if (_find (s, data () [xpos], 0, n) != npos)
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+find_first_not_of (const charT* s, size_type pos, size_type n) const
+{
+  size_t xpos = pos;
+  for (; xpos < length (); ++xpos)
+    if (_find (s, data () [xpos], 0, n) == npos)
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+find_first_not_of (charT c, size_type pos) const
+{
+  size_t xpos = pos;
+  for (; xpos < length (); ++xpos)
+    if (traits::ne (data () [xpos], c))
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+find_last_not_of (const charT* s, size_type pos, size_type n) const
+{
+  size_t xpos = length () - 1;
+  if (xpos > pos)
+    xpos = pos;
+  for (; xpos; --xpos)
+    if (_find (s, data () [xpos], 0, n) == npos)
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::
+find_last_not_of (charT c, size_type pos) const
+{
+  size_t xpos = length () - 1;
+  if (xpos > pos)
+    xpos = pos;
+  for (; xpos; --xpos)
+    if (traits::ne (data () [xpos], c))
+      return xpos;
+  return npos;
+}
+
+template <class charT, class traits, class Allocator>
+int basic_string <charT, traits, Allocator>::
+compare (const basic_string& str, size_type pos, size_type n) const
+{
+  OUTOFRANGE (pos > length ());
+
+  size_t rlen = length () - pos;
+  if (rlen > n)
+    rlen = n;
+  if (rlen > str.length ())
+    rlen = str.length ();
+  int r = traits::compare (data () + pos, str.data (), rlen);
+  if (r != 0)
+    return r;
+  if (rlen == n)
+    return 0;
+  return (length () - pos) - str.length ();
+}
+
+template <class charT, class traits, class Allocator>
+int basic_string <charT, traits, Allocator>::
+compare (const charT* s, size_type pos, size_type n) const
+{
+  OUTOFRANGE (pos > length ());
+
+  size_t rlen = length () - pos;
+  if (rlen > n)
+    rlen = n;
+  int r = traits::compare (data () + pos, s, rlen);
+  if (r != 0)
+    return r;
+  return (length () - pos) - n;
+}
+
+#include <iostream.h>
+
+template <class charT, class traits, class Allocator>
+istream &
+operator>> (istream &is, basic_string <charT, traits, Allocator> &s)
+{
+  int w = is.width (0);
+  if (is.ipfx0 ())
+    {
+      register streambuf *sb = is.rdbuf ();
+      s.resize (0);
+      while (1)
+	{
+	  int ch = sb->sbumpc ();
+	  if (ch == EOF)
+	    {
+	      is.setstate (ios::eofbit);
+	      break;
+	    }
+	  else if (traits::is_del (ch))
+	    {
+	      sb->sungetc ();
+	      break;
+	    }
+	  s += ch;
+	  if (--w == 1)
+	    break;
+	}
+    }
+
+  is.isfx ();
+  if (s.length () == 0)
+    is.setstate (ios::failbit);
+
+  return is;
+}
+
+template <class charT, class traits, class Allocator>
+ostream &
+operator<< (ostream &o, const basic_string <charT, traits, Allocator>& s)
+{
+  return o.write (s.data (), s.length ());
+}
+
+template <class charT, class traits, class Allocator>
+istream&
+getline (istream &is, basic_string <charT, traits, Allocator>& s, charT delim)
+{
+  if (is.ipfx1 ())
+    {
+      _IO_size_t count = 0;
+      streambuf *sb = is.rdbuf ();
+      s.resize (0);
+
+      while (1)
+	{
+	  int ch = sb->sbumpc ();
+	  if (ch == EOF)
+	    {
+	      is.setstate (count == 0
+			   ? (ios::failbit|ios::eofbit)
+			   : ios::eofbit);
+	      break;
+	    }
+
+	  ++count;
+
+	  if (ch == delim)
+	    break;
+
+	  s += ch;
+
+	  if (s.length () == s.npos - 1)
+	    {
+	      is.setstate (ios::failbit);
+	      break;
+	    }
+	}
+    }
+
+  // We need to be friends with istream to do this.
+  // is._gcount = count;
+  is.isfx ();
+
+  return is;
+}
+
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>::Rep
+basic_string<charT, traits, Allocator>::nilRep = { 0, 0, 1, false };
+
+template <class charT, class traits, class Allocator>
+const basic_string <charT, traits, Allocator>::size_type
+basic_string <charT, traits, Allocator>::npos;
+
+} // extern "C++"
Index: trunk/src/emx/include/Attic/cpp/std/bastring.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/std/bastring.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std/bastring.h	(revision 18)
@@ -0,0 +1,610 @@
+// Main templates for the -*- C++ -*- string classes.
+// Copyright (C) 1994, 1995, 1998 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files
+// compiled with a GNU compiler to produce an executable, this does not cause
+// the resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+// Written by Jason Merrill based upon the specification by Takanori Adachi
+// in ANSI X3J16/94-0013R2.
+
+#ifndef __BASTRING__
+#define __BASTRING__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <cstddef>
+#include <std/straits.h>
+
+// NOTE : This does NOT conform to the draft standard and is likely to change
+#include <alloc.h>
+
+extern "C++" {
+class istream; class ostream;
+
+#include <iterator>
+
+#ifdef __STL_USE_EXCEPTIONS
+
+extern void __out_of_range (const char *);
+extern void __length_error (const char *);
+
+#define OUTOFRANGE(cond) \
+  do { if (cond) __out_of_range (#cond); } while (0)
+#define LENGTHERROR(cond) \
+  do { if (cond) __length_error (#cond); } while (0)
+
+#else
+
+#include <cassert>
+#define OUTOFRANGE(cond) assert (!(cond))
+#define LENGTHERROR(cond) assert (!(cond))
+
+#endif
+
+template <class charT, class traits = string_char_traits<charT>,
+	  class Allocator = alloc >
+class basic_string
+{
+private:
+  struct Rep {
+    size_t len, res, ref;
+    bool selfish;
+
+    charT* data () { return reinterpret_cast<charT *>(this + 1); }
+    charT& operator[] (size_t s) { return data () [s]; }
+    charT* grab () { if (selfish) return clone (); ++ref; return data (); }
+    void release () { if (--ref == 0) delete this; }
+
+    inline static void * operator new (size_t, size_t);
+    inline static void operator delete (void *);
+    inline static Rep* create (size_t);
+    charT* clone ();
+
+    inline void copy (size_t, const charT *, size_t);
+    inline void move (size_t, const charT *, size_t);
+    inline void set  (size_t, const charT,   size_t);
+
+    inline static bool excess_slop (size_t, size_t);
+    inline static size_t frob_size (size_t);
+
+  private:
+    Rep &operator= (const Rep &);
+  };
+
+public:
+// types:
+  typedef	   traits		traits_type;
+  typedef typename traits::char_type	value_type;
+  typedef	   Allocator		allocator_type;
+
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  typedef charT& reference;
+  typedef const charT& const_reference;
+  typedef charT* pointer;
+  typedef const charT* const_pointer;
+  typedef pointer iterator;
+  typedef const_pointer const_iterator;
+  typedef ::reverse_iterator<iterator> reverse_iterator;
+  typedef ::reverse_iterator<const_iterator> const_reverse_iterator;
+  static const size_type npos = static_cast<size_type>(-1);
+
+private:
+  Rep *rep () const { return reinterpret_cast<Rep *>(dat) - 1; }
+  void repup (Rep *p) { rep ()->release (); dat = p->data (); }
+
+public:
+  const charT* data () const
+    { return rep ()->data(); }
+  size_type length () const
+    { return rep ()->len; }
+  size_type size () const
+    { return rep ()->len; }
+  size_type capacity () const
+    { return rep ()->res; }
+  size_type max_size () const
+    { return (npos - 1)/sizeof (charT); }		// XXX
+  bool empty () const
+    { return size () == 0; }
+
+// _lib.string.cons_ construct/copy/destroy:
+  basic_string& operator= (const basic_string& str)
+    {
+      if (&str != this) { rep ()->release (); dat = str.rep ()->grab (); }
+      return *this;
+    }
+
+  explicit basic_string (): dat (nilRep.grab ()) { }
+  basic_string (const basic_string& str): dat (str.rep ()->grab ()) { }
+  basic_string (const basic_string& str, size_type pos, size_type n = npos)
+    : dat (nilRep.grab ()) { assign (str, pos, n); }
+  basic_string (const charT* s, size_type n)
+    : dat (nilRep.grab ()) { assign (s, n); }
+  basic_string (const charT* s)
+    : dat (nilRep.grab ()) { assign (s); }
+  basic_string (size_type n, charT c)
+    : dat (nilRep.grab ()) { assign (n, c); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template<class InputIterator>
+    basic_string(InputIterator begin, InputIterator end)
+#else
+  basic_string(const_iterator begin, const_iterator end)
+#endif
+    : dat (nilRep.grab ()) { assign (begin, end); }
+
+  ~basic_string ()
+    { rep ()->release (); }
+
+  void swap (basic_string &s) { charT *d = dat; dat = s.dat; s.dat = d; }
+
+  basic_string& append (const basic_string& str, size_type pos = 0,
+			size_type n = npos)
+    { return replace (length (), 0, str, pos, n); }
+  basic_string& append (const charT* s, size_type n)
+    { return replace (length (), 0, s, n); }
+  basic_string& append (const charT* s)
+    { return append (s, traits::length (s)); }
+  basic_string& append (size_type n, charT c)
+    { return replace (length (), 0, n, c); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template<class InputIterator>
+    basic_string& append(InputIterator first, InputIterator last)
+#else
+  basic_string& append(const_iterator first, const_iterator last)
+#endif
+    { return replace (iend (), iend (), first, last); }
+
+  basic_string& assign (const basic_string& str, size_type pos = 0,
+			size_type n = npos)
+    { return replace (0, npos, str, pos, n); }
+  basic_string& assign (const charT* s, size_type n)
+    { return replace (0, npos, s, n); }
+  basic_string& assign (const charT* s)
+    { return assign (s, traits::length (s)); }
+  basic_string& assign (size_type n, charT c)
+    { return replace (0, npos, n, c); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template<class InputIterator>
+    basic_string& assign(InputIterator first, InputIterator last)
+#else
+  basic_string& assign(const_iterator first, const_iterator last)
+#endif
+    { return replace (ibegin (), iend (), first, last); }
+
+  basic_string& operator= (const charT* s)
+    { return assign (s); }
+  basic_string& operator= (charT c)
+    { return assign (1, c); }
+
+  basic_string& operator+= (const basic_string& rhs)
+    { return append (rhs); }
+  basic_string& operator+= (const charT* s)
+    { return append (s); }
+  basic_string& operator+= (charT c)
+    { return append (1, c); }
+
+  basic_string& insert (size_type pos1, const basic_string& str,
+			size_type pos2 = 0, size_type n = npos)
+    { return replace (pos1, 0, str, pos2, n); }
+  basic_string& insert (size_type pos, const charT* s, size_type n)
+    { return replace (pos, 0, s, n); }
+  basic_string& insert (size_type pos, const charT* s)
+    { return insert (pos, s, traits::length (s)); }
+  basic_string& insert (size_type pos, size_type n, charT c)
+    { return replace (pos, 0, n, c); }
+  iterator insert(iterator p, charT c)
+    { insert (p - ibegin (), 1, c); selfish (); return p; }
+  iterator insert(iterator p, size_type n, charT c)
+    { insert (p - ibegin (), n, c); selfish (); return p; }
+#ifdef __STL_MEMBER_TEMPLATES
+  template<class InputIterator>
+    void insert(iterator p, InputIterator first, InputIterator last)
+#else
+  void insert(iterator p, const_iterator first, const_iterator last)
+#endif
+    { replace (p, p, first, last); }
+
+  basic_string& erase (size_type pos = 0, size_type n = npos)
+    { return replace (pos, n, (size_type)0, (charT)0); }
+  iterator erase(iterator p)
+    { replace (p-ibegin (), 1, (size_type)0, (charT)0); selfish (); return p; }
+  iterator erase(iterator f, iterator l)
+    { replace (f-ibegin (), l-f, (size_type)0, (charT)0);selfish ();return f; }
+
+  basic_string& replace (size_type pos1, size_type n1, const basic_string& str,
+			 size_type pos2 = 0, size_type n2 = npos);
+  basic_string& replace (size_type pos, size_type n1, const charT* s,
+			 size_type n2);
+  basic_string& replace (size_type pos, size_type n1, const charT* s)
+    { return replace (pos, n1, s, traits::length (s)); }
+  basic_string& replace (size_type pos, size_type n1, size_type n2, charT c);
+  basic_string& replace (size_type pos, size_type n, charT c)
+    { return replace (pos, n, 1, c); }
+  basic_string& replace (iterator i1, iterator i2, const basic_string& str)
+    { return replace (i1 - ibegin (), i2 - i1, str); }
+  basic_string& replace (iterator i1, iterator i2, const charT* s, size_type n)
+    { return replace (i1 - ibegin (), i2 - i1, s, n); }
+  basic_string& replace (iterator i1, iterator i2, const charT* s)
+    { return replace (i1 - ibegin (), i2 - i1, s); }
+  basic_string& replace (iterator i1, iterator i2, size_type n, charT c)
+    { return replace (i1 - ibegin (), i2 - i1, n, c); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template<class InputIterator>
+    basic_string& replace(iterator i1, iterator i2,
+			  InputIterator j1, InputIterator j2);
+#else
+  basic_string& replace(iterator i1, iterator i2,
+			const_iterator j1, const_iterator j2);
+#endif
+
+private:
+  static charT eos () { return traits::eos (); }
+  void unique () { if (rep ()->ref > 1) alloc (length (), true); }
+  void selfish () { unique (); rep ()->selfish = true; }
+
+public:
+  charT operator[] (size_type pos) const
+    {
+      if (pos == length ())
+	return eos ();
+      return data ()[pos];
+    }
+
+  reference operator[] (size_type pos)
+    { selfish (); return (*rep ())[pos]; }
+
+  reference at (size_type pos)
+    {
+      OUTOFRANGE (pos >= length ());
+      return (*this)[pos];
+    }
+  const_reference at (size_type pos) const
+    {
+      OUTOFRANGE (pos >= length ());
+      return data ()[pos];
+    }
+
+private:
+  void terminate () const
+    { traits::assign ((*rep ())[length ()], eos ()); }
+
+public:
+  const charT* c_str () const
+    { if (length () == 0) return ""; terminate (); return data (); }
+  void resize (size_type n, charT c);
+  void resize (size_type n)
+    { resize (n, eos ()); }
+  void reserve (size_type) { }
+
+  size_type copy (charT* s, size_type n, size_type pos = 0);
+
+  size_type find (const basic_string& str, size_type pos = 0) const
+    { return find (str.data(), pos, str.length()); }
+  size_type find (const charT* s, size_type pos, size_type n) const;
+  size_type find (const charT* s, size_type pos = 0) const
+    { return find (s, pos, traits::length (s)); }
+  size_type find (charT c, size_type pos = 0) const;
+
+  size_type rfind (const basic_string& str, size_type pos = npos) const
+    { return rfind (str.data(), pos, str.length()); }
+  size_type rfind (const charT* s, size_type pos, size_type n) const;
+  size_type rfind (const charT* s, size_type pos = npos) const
+    { return rfind (s, pos, traits::length (s)); }
+  size_type rfind (charT c, size_type pos = npos) const;
+
+  size_type find_first_of (const basic_string& str, size_type pos = 0) const
+    { return find_first_of (str.data(), pos, str.length()); }
+  size_type find_first_of (const charT* s, size_type pos, size_type n) const;
+  size_type find_first_of (const charT* s, size_type pos = 0) const
+    { return find_first_of (s, pos, traits::length (s)); }
+  size_type find_first_of (charT c, size_type pos = 0) const
+    { return find (c, pos); }
+
+  size_type find_last_of (const basic_string& str, size_type pos = npos) const
+    { return find_last_of (str.data(), pos, str.length()); }
+  size_type find_last_of (const charT* s, size_type pos, size_type n) const;
+  size_type find_last_of (const charT* s, size_type pos = npos) const
+    { return find_last_of (s, pos, traits::length (s)); }
+  size_type find_last_of (charT c, size_type pos = npos) const
+    { return rfind (c, pos); }
+
+  size_type find_first_not_of (const basic_string& str, size_type pos = 0) const
+    { return find_first_not_of (str.data(), pos, str.length()); }
+  size_type find_first_not_of (const charT* s, size_type pos, size_type n) const;
+  size_type find_first_not_of (const charT* s, size_type pos = 0) const
+    { return find_first_not_of (s, pos, traits::length (s)); }
+  size_type find_first_not_of (charT c, size_type pos = 0) const;
+
+  size_type find_last_not_of (const basic_string& str, size_type pos = npos) const
+    { return find_last_not_of (str.data(), pos, str.length()); }
+  size_type find_last_not_of (const charT* s, size_type pos, size_type n) const;
+  size_type find_last_not_of (const charT* s, size_type pos = npos) const
+    { return find_last_not_of (s, pos, traits::length (s)); }
+  size_type find_last_not_of (charT c, size_type pos = npos) const;
+
+  basic_string substr (size_type pos = 0, size_type n = npos) const
+    { return basic_string (*this, pos, n); }
+
+  int compare (const basic_string& str, size_type pos = 0, size_type n = npos) const;
+  // There is no 'strncmp' equivalent for charT pointers.
+  int compare (const charT* s, size_type pos, size_type n) const;
+  int compare (const charT* s, size_type pos = 0) const
+    { return compare (s, pos, traits::length (s)); }
+
+  iterator begin () { selfish (); return &(*this)[0]; }
+  iterator end () { selfish (); return &(*this)[length ()]; }
+
+private:
+  iterator ibegin () const { return &(*rep ())[0]; }
+  iterator iend () const { return &(*rep ())[length ()]; }
+
+public:
+  const_iterator begin () const { return ibegin (); }
+  const_iterator end () const { return iend (); }
+
+  reverse_iterator       rbegin() { return reverse_iterator (end ()); }
+  const_reverse_iterator rbegin() const
+    { return const_reverse_iterator (end ()); }
+  reverse_iterator       rend() { return reverse_iterator (begin ()); }
+  const_reverse_iterator rend() const
+    { return const_reverse_iterator (begin ()); }
+
+private:
+  void alloc (size_type size, bool save);
+  static size_type _find (const charT* ptr, charT c, size_type xpos, size_type len);
+  inline bool check_realloc (size_type s) const;
+
+  static Rep nilRep;
+  charT *dat;
+};
+
+#ifdef __STL_MEMBER_TEMPLATES
+template <class charT, class traits, class Allocator> template <class InputIterator>
+basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
+replace (iterator i1, iterator i2, InputIterator j1, InputIterator j2)
+#else
+template <class charT, class traits, class Allocator>
+basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
+replace (iterator i1, iterator i2, const_iterator j1, const_iterator j2)
+#endif
+{
+  const size_type len = length ();
+  size_type pos = i1 - ibegin ();
+  size_type n1 = i2 - i1;
+  size_type n2 = j2 - j1;
+
+  OUTOFRANGE (pos > len);
+  if (n1 > len - pos)
+    n1 = len - pos;
+  LENGTHERROR (len - n1 > max_size () - n2);
+  size_t newlen = len - n1 + n2;
+
+  if (check_realloc (newlen))
+    {
+      Rep *p = Rep::create (newlen);
+      p->copy (0, data (), pos);
+      p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
+      for (; j1 != j2; ++j1, ++pos)
+	traits::assign ((*p)[pos], *j1);
+      repup (p);
+    }
+  else
+    {
+      rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
+      for (; j1 != j2; ++j1, ++pos)
+	traits::assign ((*rep ())[pos], *j1);
+    }
+  rep ()->len = newlen;
+
+  return *this;
+}
+
+template <class charT, class traits, class Allocator>
+inline basic_string <charT, traits, Allocator>
+operator+ (const basic_string <charT, traits, Allocator>& lhs,
+	   const basic_string <charT, traits, Allocator>& rhs)
+{
+  basic_string <charT, traits, Allocator> str (lhs);
+  str.append (rhs);
+  return str;
+}
+
+template <class charT, class traits, class Allocator>
+inline basic_string <charT, traits, Allocator>
+operator+ (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
+{
+  basic_string <charT, traits, Allocator> str (lhs);
+  str.append (rhs);
+  return str;
+}
+
+template <class charT, class traits, class Allocator>
+inline basic_string <charT, traits, Allocator>
+operator+ (charT lhs, const basic_string <charT, traits, Allocator>& rhs)
+{
+  basic_string <charT, traits, Allocator> str (1, lhs);
+  str.append (rhs);
+  return str;
+}
+
+template <class charT, class traits, class Allocator>
+inline basic_string <charT, traits, Allocator>
+operator+ (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
+{
+  basic_string <charT, traits, Allocator> str (lhs);
+  str.append (rhs);
+  return str;
+}
+
+template <class charT, class traits, class Allocator>
+inline basic_string <charT, traits, Allocator>
+operator+ (const basic_string <charT, traits, Allocator>& lhs, charT rhs)
+{
+  basic_string <charT, traits, Allocator> str (lhs);
+  str.append (1, rhs);
+  return str;
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator== (const basic_string <charT, traits, Allocator>& lhs,
+	    const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (lhs.compare (rhs) == 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator== (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (rhs.compare (lhs) == 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator== (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
+{
+  return (lhs.compare (rhs) == 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator!= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (rhs.compare (lhs) != 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator!= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
+{
+  return (lhs.compare (rhs) != 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator< (const basic_string <charT, traits, Allocator>& lhs,
+	    const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (lhs.compare (rhs) < 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator< (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (rhs.compare (lhs) > 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator< (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
+{
+  return (lhs.compare (rhs) < 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator> (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (rhs.compare (lhs) < 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator> (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
+{
+  return (lhs.compare (rhs) > 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator<= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (rhs.compare (lhs) >= 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator<= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
+{
+  return (lhs.compare (rhs) <= 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator>= (const charT* lhs, const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (rhs.compare (lhs) <= 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator>= (const basic_string <charT, traits, Allocator>& lhs, const charT* rhs)
+{
+  return (lhs.compare (rhs) >= 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator!= (const basic_string <charT, traits, Allocator>& lhs,
+	    const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (lhs.compare (rhs) != 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator> (const basic_string <charT, traits, Allocator>& lhs,
+	   const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (lhs.compare (rhs) > 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator<= (const basic_string <charT, traits, Allocator>& lhs,
+	    const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (lhs.compare (rhs) <= 0);
+}
+
+template <class charT, class traits, class Allocator>
+inline bool
+operator>= (const basic_string <charT, traits, Allocator>& lhs,
+	    const basic_string <charT, traits, Allocator>& rhs)
+{
+  return (lhs.compare (rhs) >= 0);
+}
+
+class istream; class ostream;
+template <class charT, class traits, class Allocator> istream&
+operator>> (istream&, basic_string <charT, traits, Allocator>&);
+template <class charT, class traits, class Allocator> ostream&
+operator<< (ostream&, const basic_string <charT, traits, Allocator>&);
+template <class charT, class traits, class Allocator> istream&
+getline (istream&, basic_string <charT, traits, Allocator>&, charT delim = '\n');
+
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/std/complext.cc
===================================================================
--- trunk/src/emx/include/Attic/cpp/std/complext.cc	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std/complext.cc	(revision 18)
@@ -0,0 +1,273 @@
+// Member templates for the -*- C++ -*- complex number classes.
+// Copyright (C) 1994 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files
+// compiled with a GNU compiler to produce an executable, this does not cause
+// the resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+// Written by Jason Merrill based upon the specification in the 27 May 1994
+// C++ working paper, ANSI document X3J16/94-0098.
+
+#include <complex>
+
+extern "C++" {
+template <class FLOAT> complex<FLOAT>
+cos (const complex<FLOAT>& x)
+{
+  return complex<FLOAT> (cos (real (x)) * cosh (imag (x)),
+			   - sin (real (x)) * sinh (imag (x)));
+}
+
+template <class FLOAT> complex<FLOAT>
+cosh (const complex<FLOAT>& x)
+{
+  return complex<FLOAT> (cosh (real (x)) * cos (imag (x)),
+			   sinh (real (x)) * sin (imag (x)));
+}
+
+template <class FLOAT> complex<FLOAT>
+exp (const complex<FLOAT>& x)
+{
+  return polar (FLOAT (exp (real (x))), imag (x));
+}
+
+template <class FLOAT> complex<FLOAT>
+log (const complex<FLOAT>& x)
+{
+  return complex<FLOAT> (log (abs (x)), arg (x));
+}
+
+template <class FLOAT> complex<FLOAT>
+pow (const complex<FLOAT>& x, const complex<FLOAT>& y)
+{
+  FLOAT logr = log (abs (x));
+  FLOAT t = arg (x);
+
+  return polar (FLOAT (exp (logr * real (y) - imag (y) * t)),
+		FLOAT (imag (y) * logr + real (y) * t));
+}
+
+template <class FLOAT> complex<FLOAT>
+pow (const complex<FLOAT>& x, FLOAT y)
+{
+  return exp (FLOAT (y) * log (x));
+}
+
+template <class FLOAT> complex<FLOAT>
+pow (FLOAT x, const complex<FLOAT>& y)
+{
+  return exp (y * FLOAT (log (x)));
+}
+
+template <class FLOAT> complex<FLOAT>
+sin (const complex<FLOAT>& x)
+{
+  return complex<FLOAT> (sin (real (x)) * cosh (imag (x)),
+			   cos (real (x)) * sinh (imag (x)));
+}
+
+template <class FLOAT> complex<FLOAT>
+sinh (const complex<FLOAT>& x)
+{
+  return complex<FLOAT> (sinh (real (x)) * cos (imag (x)),
+			   cosh (real (x)) * sin (imag (x)));
+}
+
+#include <iostream.h>
+
+template <class FLOAT> istream&
+operator >> (istream& is, complex<FLOAT>& x)
+{
+  FLOAT re, im = 0;
+  char ch = 0;
+
+  if (is.ipfx0 ())
+    {
+      if (is.peek () == '(')
+	is >> ch;
+      is >> re;
+      if (ch == '(')
+	{
+	  is >> ch;
+	  if (ch == ',')
+	    is >> im >> ch;
+	}
+    }
+  is.isfx ();
+
+  if (ch != 0 && ch != ')')
+    is.setstate (ios::failbit);
+  else if (is.good ())
+    x = complex<FLOAT> (re, im);
+
+  return is;
+}
+
+template <class FLOAT> ostream&
+operator << (ostream& os, const complex<FLOAT>& x)
+{
+  return os << '(' << real (x) << ',' << imag (x) << ')';
+}
+
+// The code below is adapted from f2c's libF77, and is subject to this
+// copyright:
+
+/****************************************************************
+Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore.
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the names of AT&T Bell Laboratories or
+Bellcore or any of their entities not be used in advertising or
+publicity pertaining to distribution of the software without
+specific, written prior permission.
+
+AT&T and Bellcore disclaim all warranties with regard to this
+software, including all implied warranties of merchantability
+and fitness.  In no event shall AT&T or Bellcore be liable for
+any special, indirect or consequential damages or any damages
+whatsoever resulting from loss of use, data or profits, whether
+in an action of contract, negligence or other tortious action,
+arising out of or in connection with the use or performance of
+this software.
+****************************************************************/
+
+template <class FLOAT> complex<FLOAT>&
+__doadv (complex<FLOAT>* ths, const complex<FLOAT>& y)
+{
+  FLOAT ar = abs (y.re);
+  FLOAT ai = abs (y.im);
+  FLOAT nr, ni;
+  FLOAT t, d;
+  if (ar <= ai)
+    {
+      t = y.re / y.im;
+      d = y.im * (1 + t*t);
+      nr = (ths->re * t + ths->im) / d;
+      ni = (ths->im * t - ths->re) / d;
+    }
+  else
+    {
+      t = y.im / y.re;
+      d = y.re * (1 + t*t);
+      nr = (ths->re + ths->im * t) / d;
+      ni = (ths->im - ths->re * t) / d;
+    }
+  ths->re = nr;
+  ths->im = ni;
+  return *ths;
+}
+
+template <class FLOAT> complex<FLOAT>
+operator / (const complex<FLOAT>& x, const complex<FLOAT>& y)
+{
+  FLOAT ar = abs (real (y));
+  FLOAT ai = abs (imag (y));
+  FLOAT nr, ni;
+  FLOAT t, d;
+  if (ar <= ai)
+    {
+      t = real (y) / imag (y);
+      d = imag (y) * (1 + t*t);
+      nr = (real (x) * t + imag (x)) / d;
+      ni = (imag (x) * t - real (x)) / d;
+    }
+  else
+    {
+      t = imag (y) / real (y);
+      d = real (y) * (1 + t*t);
+      nr = (real (x) + imag (x) * t) / d;
+      ni = (imag (x) - real (x) * t) / d;
+    }
+  return complex<FLOAT> (nr, ni);
+}
+
+template <class FLOAT> complex<FLOAT>
+operator / (FLOAT x, const complex<FLOAT>& y)
+{
+  FLOAT ar = abs (real (y));
+  FLOAT ai = abs (imag (y));
+  FLOAT nr, ni;
+  FLOAT t, d;
+  if (ar <= ai)
+    {
+      t = real (y) / imag (y);
+      d = imag (y) * (1 + t*t);
+      nr = x * t / d;
+      ni = -x / d;
+    }
+  else
+    {
+      t = imag (y) / real (y);
+      d = real (y) * (1 + t*t);
+      nr = x / d;
+      ni = -x * t / d;
+    }
+  return complex<FLOAT> (nr, ni);
+}
+
+template <class FLOAT> complex<FLOAT>
+pow (const complex<FLOAT>& xin, int y)
+{
+  if (y == 0)
+    return complex<FLOAT> (1.0);
+  complex<FLOAT> r (1.0);
+  complex<FLOAT> x (xin);
+  if (y < 0)
+    {
+      y = -y;
+      x = 1/x;
+    }
+  for (;;)
+    {
+      if (y & 1)
+	r *= x;
+      if (y >>= 1)
+	x *= x;
+      else
+	return r;
+    }
+}
+
+template <class FLOAT> complex<FLOAT>
+sqrt (const complex<FLOAT>& x)
+{
+  FLOAT r = abs (x);
+  FLOAT nr, ni;
+  if (r == 0.0)
+    nr = ni = r;
+  else if (real (x) > 0)
+    {
+      nr = sqrt (0.5 * (r + real (x)));
+      ni = imag (x) / nr / 2;
+    }
+  else
+    {
+      ni = sqrt (0.5 * (r - real (x)));
+      if (imag (x) < 0)
+	ni = - ni;
+      nr = imag (x) / ni / 2;
+    }
+  return complex<FLOAT> (nr, ni); 
+}
+} // extern "C++"
Index: trunk/src/emx/include/Attic/cpp/std/complext.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/std/complext.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std/complext.h	(revision 18)
@@ -0,0 +1,400 @@
+// The template and inlines for the -*- C++ -*- complex number classes.
+// Copyright (C) 1994 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms of
+// the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files compiled
+// with a GNU compiler to produce an executable, this does not cause the
+// resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+// Written by Jason Merrill based upon the specification in the 27 May 1994
+// C++ working paper, ANSI document X3J16/94-0098.
+
+#ifndef __COMPLEXT__
+#define __COMPLEXT__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <cmath>
+
+#if ! defined (__GNUG__) && ! defined (__attribute__)
+#define __attribute__(foo) /* Ignore.  */
+#endif
+
+class istream;
+class ostream;
+
+extern "C++" {
+template <class _FLT> class complex;
+template <class _FLT> complex<_FLT>&
+  __doapl (complex<_FLT>* ths, const complex<_FLT>& r);
+template <class _FLT> complex<_FLT>&
+  __doami (complex<_FLT>* ths, const complex<_FLT>& r);
+template <class _FLT> complex<_FLT>&
+  __doaml (complex<_FLT>* ths, const complex<_FLT>& r);
+template <class _FLT> complex<_FLT>&
+  __doadv (complex<_FLT>* ths, const complex<_FLT>& r);
+
+template <class _FLT>
+class complex
+{
+public:
+  complex (_FLT r = 0, _FLT i = 0): re (r), im (i) { }
+  complex& operator += (const complex&);
+  complex& operator -= (const complex&);
+  complex& operator *= (const complex&);
+  complex& operator /= (const complex&);
+  _FLT real () const { return re; }
+  _FLT imag () const { return im; }
+private:
+  _FLT re, im;
+
+  friend complex& __doapl<> (complex *, const complex&);
+  friend complex& __doami<> (complex *, const complex&);
+  friend complex& __doaml<> (complex *, const complex&);
+  friend complex& __doadv<> (complex *, const complex&);
+};
+
+// Declare specializations.
+class complex<float>;
+class complex<double>;
+class complex<long double>;
+
+template <class _FLT>
+inline complex<_FLT>&
+__doapl (complex<_FLT>* ths, const complex<_FLT>& r)
+{
+  ths->re += r.re;
+  ths->im += r.im;
+  return *ths;
+}
+template <class _FLT>
+inline complex<_FLT>&
+complex<_FLT>::operator += (const complex<_FLT>& r)
+{
+  return __doapl (this, r);
+}
+
+template <class _FLT>
+inline complex<_FLT>&
+__doami (complex<_FLT>* ths, const complex<_FLT>& r)
+{
+  ths->re -= r.re;
+  ths->im -= r.im;
+  return *ths;
+}
+template <class _FLT>
+inline complex<_FLT>&
+complex<_FLT>::operator -= (const complex<_FLT>& r)
+{
+  return __doami (this, r);
+}
+
+template <class _FLT>
+inline complex<_FLT>&
+__doaml (complex<_FLT>* ths, const complex<_FLT>& r)
+{
+  _FLT f = ths->re * r.re - ths->im * r.im;
+  ths->im = ths->re * r.im + ths->im * r.re;
+  ths->re = f;
+  return *ths;
+}
+template <class _FLT>
+inline complex<_FLT>&
+complex<_FLT>::operator *= (const complex<_FLT>& r)
+{
+  return __doaml (this, r);
+}
+
+template <class _FLT>
+inline complex<_FLT>&
+complex<_FLT>::operator /= (const complex<_FLT>& r)
+{
+  return __doadv (this, r);
+}
+
+template <class _FLT> inline _FLT
+imag (const complex<_FLT>& x) __attribute__ ((const));
+
+template <class _FLT> inline _FLT
+imag (const complex<_FLT>& x)
+{
+  return x.imag ();
+}
+
+template <class _FLT> inline _FLT
+real (const complex<_FLT>& x) __attribute__ ((const));
+
+template <class _FLT> inline _FLT
+real (const complex<_FLT>& x)
+{
+  return x.real ();
+}
+
+template <class _FLT> inline complex<_FLT>
+operator + (const complex<_FLT>& x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator + (const complex<_FLT>& x, const complex<_FLT>& y)
+{
+  return complex<_FLT> (real (x) + real (y), imag (x) + imag (y));
+}
+
+template <class _FLT> inline complex<_FLT>
+operator + (const complex<_FLT>& x, _FLT y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator + (const complex<_FLT>& x, _FLT y)
+{
+  return complex<_FLT> (real (x) + y, imag (x));
+}
+
+template <class _FLT> inline complex<_FLT>
+operator + (_FLT x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator + (_FLT x, const complex<_FLT>& y)
+{
+  return complex<_FLT> (x + real (y), imag (y));
+}
+
+template <class _FLT> inline complex<_FLT>
+operator - (const complex<_FLT>& x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator - (const complex<_FLT>& x, const complex<_FLT>& y)
+{
+  return complex<_FLT> (real (x) - real (y), imag (x) - imag (y));
+}
+
+template <class _FLT> inline complex<_FLT>
+operator - (const complex<_FLT>& x, _FLT y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator - (const complex<_FLT>& x, _FLT y)
+{
+  return complex<_FLT> (real (x) - y, imag (x));
+}
+
+template <class _FLT> inline complex<_FLT>
+operator - (_FLT x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator - (_FLT x, const complex<_FLT>& y)
+{
+  return complex<_FLT> (x - real (y), - imag (y));
+}
+
+template <class _FLT> inline complex<_FLT>
+operator * (const complex<_FLT>& x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator * (const complex<_FLT>& x, const complex<_FLT>& y)
+{
+  return complex<_FLT> (real (x) * real (y) - imag (x) * imag (y),
+			   real (x) * imag (y) + imag (x) * real (y));
+}
+
+template <class _FLT> inline complex<_FLT>
+operator * (const complex<_FLT>& x, _FLT y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator * (const complex<_FLT>& x, _FLT y)
+{
+  return complex<_FLT> (real (x) * y, imag (x) * y);
+}
+
+template <class _FLT> inline complex<_FLT>
+operator * (_FLT x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator * (_FLT x, const complex<_FLT>& y)
+{
+  return complex<_FLT> (x * real (y), x * imag (y));
+}
+
+template <class _FLT> complex<_FLT>
+operator / (const complex<_FLT>& x, _FLT y) __attribute__ ((const));
+
+template <class _FLT> complex<_FLT>
+operator / (const complex<_FLT>& x, _FLT y)
+{
+  return complex<_FLT> (real (x) / y, imag (x) / y);
+}
+
+template <class _FLT> inline complex<_FLT>
+operator + (const complex<_FLT>& x) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator + (const complex<_FLT>& x)
+{
+  return x;
+}
+
+template <class _FLT> inline complex<_FLT>
+operator - (const complex<_FLT>& x) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+operator - (const complex<_FLT>& x)
+{
+  return complex<_FLT> (-real (x), -imag (x));
+}
+
+template <class _FLT> inline bool
+operator == (const complex<_FLT>& x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline bool
+operator == (const complex<_FLT>& x, const complex<_FLT>& y)
+{
+  return real (x) == real (y) && imag (x) == imag (y);
+}
+
+template <class _FLT> inline bool
+operator == (const complex<_FLT>& x, _FLT y) __attribute__ ((const));
+
+template <class _FLT> inline bool
+operator == (const complex<_FLT>& x, _FLT y)
+{
+  return real (x) == y && imag (x) == 0;
+}
+
+template <class _FLT> inline bool
+operator == (_FLT x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline bool
+operator == (_FLT x, const complex<_FLT>& y)
+{
+  return x == real (y) && imag (y) == 0;
+}
+
+template <class _FLT> inline bool
+operator != (const complex<_FLT>& x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline bool
+operator != (const complex<_FLT>& x, const complex<_FLT>& y)
+{
+  return real (x) != real (y) || imag (x) != imag (y);
+}
+
+template <class _FLT> inline bool
+operator != (const complex<_FLT>& x, _FLT y) __attribute__ ((const));
+
+template <class _FLT> inline bool
+operator != (const complex<_FLT>& x, _FLT y)
+{
+  return real (x) != y || imag (x) != 0;
+}
+
+template <class _FLT> inline bool
+operator != (_FLT x, const complex<_FLT>& y) __attribute__ ((const));
+
+template <class _FLT> inline bool
+operator != (_FLT x, const complex<_FLT>& y)
+{
+  return x != real (y) || imag (y) != 0;
+}
+
+// Some targets don't provide a prototype for hypot when -ansi.
+extern "C" double hypot (double, double) __attribute__ ((const));
+
+template <class _FLT> inline _FLT
+abs (const complex<_FLT>& x) __attribute__ ((const));
+
+template <class _FLT> inline _FLT
+abs (const complex<_FLT>& x)
+{
+  return hypot (real (x), imag (x));
+}
+
+template <class _FLT> inline _FLT
+arg (const complex<_FLT>& x) __attribute__ ((const));
+
+template <class _FLT> inline _FLT
+arg (const complex<_FLT>& x)
+{
+  return atan2 (imag (x), real (x));
+}
+
+template <class _FLT> inline complex<_FLT>
+polar (_FLT r, _FLT t) __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+polar (_FLT r, _FLT t)
+{
+  return complex<_FLT> (r * cos (t), r * sin (t));
+}
+
+template <class _FLT> inline complex<_FLT>
+conj (const complex<_FLT>& x)  __attribute__ ((const));
+
+template <class _FLT> inline complex<_FLT>
+conj (const complex<_FLT>& x) 
+{
+  return complex<_FLT> (real (x), -imag (x));
+}
+
+template <class _FLT> inline _FLT
+norm (const complex<_FLT>& x) __attribute__ ((const));
+
+template <class _FLT> inline _FLT
+norm (const complex<_FLT>& x)
+{
+  return real (x) * real (x) + imag (x) * imag (x);
+}
+
+// Declarations of templates in complext.ccI
+
+template <class _FLT> complex<_FLT>
+  operator / (const complex<_FLT>&, const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  operator / (_FLT, const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  cos (const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  cosh (const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  exp (const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  log (const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  pow (const complex<_FLT>&, const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  pow (const complex<_FLT>&, _FLT) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  pow (const complex<_FLT>&, int) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  pow (_FLT, const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  sin (const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  sinh (const complex<_FLT>&) __attribute__ ((const));
+template <class _FLT> complex<_FLT>
+  sqrt (const complex<_FLT>&) __attribute__ ((const));
+
+template <class _FLT> istream& operator >> (istream&, complex<_FLT>&);
+template <class _FLT> ostream& operator << (ostream&, const complex<_FLT>&);
+} // extern "C++"
+
+// Specializations and such
+
+#include <std/fcomplex.h>
+#include <std/dcomplex.h>
+#include <std/ldcomple.h>
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/std/dcomplex.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/std/dcomplex.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std/dcomplex.h	(revision 18)
@@ -0,0 +1,91 @@
+// The -*- C++ -*- double_complex class.
+// Copyright (C) 1994 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files
+// compiled with a GNU compiler to produce an executable, this does not cause
+// the resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+// Written by Jason Merrill based upon the specification in the 27 May 1994
+// C++ working paper, ANSI document X3J16/94-0098.
+
+#ifndef __DCOMPLEX__
+#define __DCOMPLEX__
+
+#ifdef __GNUG__
+#pragma interface "dcomplex"
+#endif
+
+extern "C++" {
+class complex<double>
+{
+public:
+  complex (double r = 0, double i = 0): re (r), im (i) { }
+  complex (const complex<float>& r): re (r.real ()), im (r.imag ()) { }
+  explicit complex (const complex<long double>& r);
+
+  complex& operator+= (const complex& r) { return __doapl (this, r); }
+  complex& operator-= (const complex& r) { return __doami (this, r); }
+  complex& operator*= (const complex& r) { return __doaml (this, r); }
+  complex& operator/= (const complex& r) { return __doadv (this, r); }
+
+  double real () const { return re; }
+  double imag () const { return im; }
+private:
+  double re, im;
+
+  friend complex& __doapl<> (complex *, const complex&);
+  friend complex& __doami<> (complex *, const complex&);
+  friend complex& __doaml<> (complex *, const complex&);
+  friend complex& __doadv<> (complex *, const complex&);
+
+#ifndef __STRICT_ANSI__
+  friend inline complex operator + (const complex& x, double y)
+    { return operator+<> (x, y); }
+  friend inline complex operator + (double x, const complex& y)
+    { return operator+<> (x, y); }
+  friend inline complex operator - (const complex& x, double y)
+    { return operator-<> (x, y); }
+  friend inline complex operator - (double x, const complex& y)
+    { return operator-<> (x, y); }
+  friend inline complex operator * (const complex& x, double y)
+    { return operator*<> (x, y); }
+  friend inline complex operator * (double x, const complex& y)
+    { return operator*<> (x, y); }
+  friend inline complex operator / (const complex& x, double y)
+    { return operator/<> (x, y); }
+  friend inline complex operator / (double x, const complex& y)
+    { return operator/<> (x, y); }
+  friend inline bool operator == (const complex& x, double y)
+    { return operator==<> (x, y); }
+  friend inline bool operator == (double x, const complex& y)
+    { return operator==<> (x, y); }
+  friend inline bool operator != (const complex& x, double y)
+    { return operator!=<> (x, y); }
+  friend inline bool operator != (double x, const complex& y)
+    { return operator!=<> (x, y); }
+#endif /* __STRICT_ANSI__ */
+};
+
+inline complex<float>::complex (const complex<double>& r)
+: re (r.real ()), im (r.imag ())
+{ }
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/std/fcomplex.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/std/fcomplex.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std/fcomplex.h	(revision 18)
@@ -0,0 +1,87 @@
+// The -*- C++ -*- float_complex class.
+// Copyright (C) 1994 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files
+// compiled with a GNU compiler to produce an executable, this does not cause
+// the resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+// Written by Jason Merrill based upon the specification in the 27 May 1994
+// C++ working paper, ANSI document X3J16/94-0098.
+
+#ifndef __FCOMPLEX__
+#define __FCOMPLEX__
+
+#ifdef __GNUG__
+#pragma interface "fcomplex"
+#endif
+
+extern "C++" {
+class complex<float>
+{
+public:
+  complex (float r = 0, float i = 0): re (r), im (i) { }
+  explicit complex (const complex<double>& r);
+  explicit complex (const complex<long double>& r);
+
+  complex& operator+= (const complex& r) { return __doapl (this, r); }
+  complex& operator-= (const complex& r) { return __doami (this, r); }
+  complex& operator*= (const complex& r) { return __doaml (this, r); }
+  complex& operator/= (const complex& r) { return __doadv (this, r); }
+
+  float real () const { return re; }
+  float imag () const { return im; }
+private:
+  float re, im;
+
+  friend complex& __doapl<> (complex *, const complex&);
+  friend complex& __doami<> (complex *, const complex&);
+  friend complex& __doaml<> (complex *, const complex&);
+  friend complex& __doadv<> (complex *, const complex&);
+
+#ifndef __STRICT_ANSI__
+  friend inline complex operator + (const complex& x, float y)
+    { return operator+<> (x, y); }
+  friend inline complex operator + (float x, const complex& y)
+    { return operator+<> (x, y); }
+  friend inline complex operator - (const complex& x, float y)
+    { return operator-<> (x, y); }
+  friend inline complex operator - (float x, const complex& y)
+    { return operator-<> (x, y); }
+  friend inline complex operator * (const complex& x, float y)
+    { return operator*<> (x, y); }
+  friend inline complex operator * (float x, const complex& y)
+    { return operator*<> (x, y); }
+  friend inline complex operator / (const complex& x, float y)
+    { return operator/<> (x, y); }
+  friend inline complex operator / (float x, const complex& y)
+    { return operator/<> (x, y); }
+  friend inline bool operator == (const complex& x, float y)
+    { return operator==<> (x, y); }
+  friend inline bool operator == (float x, const complex& y)
+    { return operator==<> (x, y); }
+  friend inline bool operator != (const complex& x, float y)
+    { return operator!=<> (x, y); }
+  friend inline bool operator != (float x, const complex& y)
+    { return operator!=<> (x, y); }
+#endif /* __STRICT_ANSI__ */
+};
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/std/ldcomple.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/std/ldcomple.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std/ldcomple.h	(revision 18)
@@ -0,0 +1,95 @@
+// The -*- C++ -*- long_double_complex class.
+// Copyright (C) 1994 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files
+// compiled with a GNU compiler to produce an executable, this does not cause
+// the resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+// Written by Jason Merrill based upon the specification in the 27 May 1994
+// C++ working paper, ANSI document X3J16/94-0098.
+
+#ifndef __LDCOMPLEX__
+#define __LDCOMPLEX__
+
+#ifdef __GNUG__
+#pragma interface "ldcomplex"
+#endif
+
+extern "C++" {
+class complex<long double>
+{
+public:
+  complex (long double r = 0, long double i = 0): re (r), im (i) { }
+  complex (const complex<float>& r): re (r.real ()), im (r.imag ()) { }
+  complex (const complex<double>& r): re (r.real ()), im (r.imag ()) { }
+
+  complex& operator+= (const complex& r) { return __doapl (this, r); }
+  complex& operator-= (const complex& r) { return __doami (this, r); }
+  complex& operator*= (const complex& r) { return __doaml (this, r); }
+  complex& operator/= (const complex& r) { return __doadv (this, r); }
+
+  long double real () const { return re; }
+  long double imag () const { return im; }
+private:
+  long double re, im;
+
+  friend complex& __doapl<> (complex *, const complex&);
+  friend complex& __doami<> (complex *, const complex&);
+  friend complex& __doaml<> (complex *, const complex&);
+  friend complex& __doadv<> (complex *, const complex&);
+
+#ifndef __STRICT_ANSI__
+  friend inline complex operator + (const complex& x, long double y)
+    { return operator+<> (x, y); }
+  friend inline complex operator + (long double x, const complex& y)
+    { return operator+<> (x, y); }
+  friend inline complex operator - (const complex& x, long double y)
+    { return operator-<> (x, y); }
+  friend inline complex operator - (long double x, const complex& y)
+    { return operator-<> (x, y); }
+  friend inline complex operator * (const complex& x, long double y)
+    { return operator*<> (x, y); }
+  friend inline complex operator * (long double x, const complex& y)
+    { return operator*<> (x, y); }
+  friend inline complex operator / (const complex& x, long double y)
+    { return operator/<> (x, y); }
+  friend inline complex operator / (long double x, const complex& y)
+    { return operator/<> (x, y); }
+  friend inline bool operator == (const complex& x, long double y)
+    { return operator==<> (x, y); }
+  friend inline bool operator == (long double x, const complex& y)
+    { return operator==<> (x, y); }
+  friend inline bool operator != (const complex& x, long double y)
+    { return operator!=<> (x, y); }
+  friend inline bool operator != (long double x, const complex& y)
+    { return operator!=<> (x, y); }
+#endif /* __STRICT_ANSI__ */
+};
+
+inline complex<float>::complex (const complex<long double>& r)
+: re (r.real ()), im (r.imag ())
+{ }
+
+inline complex<double>::complex (const complex<long double>& r)
+: re (r.real ()), im (r.imag ())
+{ }
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/std/straits.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/std/straits.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/std/straits.h	(revision 18)
@@ -0,0 +1,161 @@
+// Character traits template for the -*- C++ -*- string classes.
+// Copyright (C) 1994 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files
+// compiled with a GNU compiler to produce an executable, this does not cause
+// the resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+// Written by Jason Merrill based upon the specification by Takanori Adachi
+// in ANSI X3J16/94-0013R2.
+
+#ifndef __STRING_CHAR_TRAITS__
+#define __STRING_CHAR_TRAITS__
+
+#ifdef __GNUG__
+// For string_char_traits <char>
+#pragma interface "std/straits.h"
+#endif
+
+#include <cstddef>
+
+extern "C++" {
+template <class charT>
+struct string_char_traits {
+  typedef charT char_type; // for users to acquire the basic character type
+
+  // constraints
+
+  static void assign (char_type& c1, const char_type& c2)
+    { c1 = c2; }
+  static bool eq (const char_type& c1, const char_type& c2)
+    { return (c1 == c2); }
+  static bool ne (const char_type& c1, const char_type& c2)
+    { return !(c1 == c2); }
+  static bool lt (const char_type& c1, const char_type& c2)
+    { return (c1 < c2); }
+  static char_type eos () { return char_type(); } // the null character
+  static bool is_del(char_type a) { return 0; }
+  // characteristic function for delimiters of charT
+  
+  // speed-up functions
+
+  static int compare (const char_type* s1, const char_type* s2, size_t n)
+    {
+      size_t i;
+      for (i = 0; i < n; ++i)
+	if (ne (s1[i], s2[i]))
+	  return lt (s1[i], s2[i]) ? -1 : 1;
+
+      return 0;
+    }
+    
+  static size_t length (const char_type* s)
+    {
+      size_t l = 0;
+      while (ne (*s++, eos ()))
+	++l;
+      return l;
+    }
+
+  static char_type* copy (char_type* s1, const char_type* s2, size_t n)
+    {
+      for (; n--; )
+	assign (s1[n], s2[n]);
+      return s1;
+    }
+
+  static char_type* move (char_type* s1, const char_type* s2, size_t n)
+    {
+      char_type a[n];
+      size_t i;
+      for (i = 0; i < n; ++i)
+	assign (a[i], s2[i]);
+      for (i = 0; i < n; ++i)
+	assign (s1[i], a[i]);
+      return s1;
+    }
+
+  static char_type* set (char_type* s1, const char_type& c, size_t n)
+    {
+      for (; n--; )
+	assign (s1[n], c);
+      return s1;
+    }
+};
+
+class istream;
+class ostream;
+#include <cctype>
+#include <cstring>
+
+struct string_char_traits <char> {
+  typedef char char_type;
+
+  static void assign (char_type& c1, const char_type& c2)
+    { c1 = c2; }
+  static bool eq (const char_type & c1, const char_type& c2)
+    { return (c1 == c2); }
+  static bool ne (const char_type& c1, const char_type& c2)
+    { return (c1 != c2); }
+  static bool lt (const char_type& c1, const char_type& c2)
+    { return (c1 < c2); }
+  static char_type eos () { return 0; }
+  static bool is_del(char_type a) { return isspace(a); }
+
+  static int compare (const char_type* s1, const char_type* s2, size_t n)
+    { return memcmp (s1, s2, n); }
+  static size_t length (const char_type* s)
+    { return strlen (s); }
+  static char_type* copy (char_type* s1, const char_type* s2, size_t n)
+    { return (char_type*) memcpy (s1, s2, n); }
+  static char_type* move (char_type* s1, const char_type* s2, size_t n)
+    { return (char_type*) memmove (s1, s2, n); }
+  static char_type* set (char_type* s1, const char_type& c, size_t n)
+    { return (char_type*) memset (s1, c, n); }
+};
+
+#if 0
+#include <cwctype>
+struct string_char_traits <wchar_t> {
+  typedef wchar_t char_type;
+
+  static void assign (char_type& c1, const char_type& c2)
+    { c1 = c2; }
+  static bool eq (const char_type & c1, const char_type& c2)
+    { return (c1 == c2); }
+  static bool ne (const char_type& c1, const char_type& c2)
+    { return (c1 != c2); }
+  static bool lt (const char_type& c1, const char_type& c2)
+    { return (c1 < c2); }
+  static char_type eos () { return 0; }
+  static bool is_del(char_type a) { return iswspace(a); }
+
+  static int compare (const char_type* s1, const char_type* s2, size_t n)
+    { return wmemcmp (s1, s2, n); }
+  static size_t length (const char_type* s)
+    { return wcslen (s); }
+  static char_type* copy (char_type* s1, const char_type* s2, size_t n)
+    { return wmemcpy (s1, s2, n); }
+  static char_type* set (char_type* s1, const char_type& c, size_t n)
+    { return wmemset (s1, c, n); }
+};
+#endif
+} // extern "C++"
+#endif
Index: trunk/src/emx/include/Attic/cpp/stdexcep
===================================================================
--- trunk/src/emx/include/Attic/cpp/stdexcep	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stdexcep	(revision 18)
@@ -0,0 +1,93 @@
+// Methods for Exception Support for -*- C++ -*-
+// Copyright (C) 1994, 1995, 1997 Free Software Foundation
+
+// This file is part of the GNU ANSI C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+// As a special exception, if you link this library with files
+// compiled with a GNU compiler to produce an executable, this does not cause
+// the resulting executable to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+// Written by Mike Stump based upon the specification in the 20 September 1994
+// C++ working paper, ANSI document X3J16/94-0158.
+
+#ifndef __STDEXCEPT__
+#define __STDEXCEPT__
+
+#ifdef __GNUG__
+#pragma interface "stdexcept"
+#endif
+
+#include <exceptio>
+#include <string>
+
+extern "C++" {
+
+class logic_error : public exception {
+  string _what;
+public:
+  logic_error(const string& what_arg): _what (what_arg) { }
+  virtual const char* what () const { return _what.c_str (); }
+};
+
+class domain_error : public logic_error {
+public:
+  domain_error (const string& what_arg): logic_error (what_arg) { }
+};
+
+class invalid_argument : public logic_error {
+public:
+  invalid_argument (const string& what_arg): logic_error (what_arg) { }
+};
+
+class length_error : public logic_error {
+public:
+  length_error (const string& what_arg): logic_error (what_arg) { }
+};
+
+class out_of_range : public logic_error {
+public:
+  out_of_range (const string& what_arg): logic_error (what_arg) { }
+};
+
+class runtime_error : public exception {
+  string _what;
+public:
+  runtime_error(const string& what_arg): _what (what_arg) { }
+  virtual const char* what () const { return _what.c_str (); }
+protected:
+  runtime_error(): exception () { }
+};
+
+class range_error : public runtime_error {
+public:
+  range_error (const string& what_arg): runtime_error (what_arg) { }
+};
+
+class overflow_error : public runtime_error {
+public:
+  overflow_error (const string& what_arg): runtime_error (what_arg) { }
+};
+
+class underflow_error : public runtime_error {
+public:
+  underflow_error (const string& what_arg): runtime_error (what_arg) { }
+};
+
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/stdiostr.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stdiostr.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stdiostr.h	(revision 18)
@@ -0,0 +1,79 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/* Written by Per Bothner (bothner@cygnus.com). */
+
+#ifndef _STDIOSTREAM_H
+#define _STDIOSTREAM_H
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <iostream.h>
+#include <stdio.h>
+
+extern "C++" {
+class stdiobuf : public filebuf {
+  protected:
+    FILE *_file;
+  public:
+    FILE* stdiofile() const { return _file; }
+    stdiobuf(FILE *);
+    ~stdiobuf();
+    int buffered () const { return _flags & _IO_UNBUFFERED ? 0 : 1; }
+    void buffered (int);
+    virtual streamsize sys_read(char*, streamsize);
+    virtual streampos sys_seek(streamoff, _seek_dir);
+    virtual streamsize sys_write(const char*, streamsize);
+    virtual int sys_close();
+    virtual int sync();
+    virtual int overflow(int c = EOF);
+    streamsize xsputn(const char* s, streamsize n);
+};
+
+class istdiostream : public istream
+{
+private:
+  stdiobuf _file;
+public:
+  istdiostream (FILE* __f) : istream(), _file(__f) { init(&_file); }
+  stdiobuf* rdbuf()/* const */ { return &_file; }
+  int buffered () const { return _file.buffered (); }
+  void buffered (int _i) { _file.buffered (_i); }
+};
+
+class ostdiostream : public ostream
+{
+private:
+  stdiobuf _file;
+public:
+  ostdiostream (FILE* __f) : ostream(), _file(__f) { init(&_file); }
+  stdiobuf* rdbuf() /* const */ { return &_file; }
+  int buffered () const { return _file.buffered (); }
+  void buffered (int _i) { _file.buffered (_i); }
+};
+} // extern "C++"
+
+#endif /* !_STDIOSTREAM_H */
Index: trunk/src/emx/include/Attic/cpp/stl.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl.h	(revision 18)
@@ -0,0 +1,15 @@
+// -*- C++ -*- compatibility header.
+// This file is part of the GNU ANSI C++ Library.
+
+#include <algorithm>
+#include <deque>
+#include <functional>
+#include <iterator>
+#include <list>
+#include <map>
+#include <memory>
+#include <numeric>
+#include <set>
+#include <stack>
+#include <utility>
+#include <vector>
Index: trunk/src/emx/include/Attic/cpp/stl_algb.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_algb.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_algb.h	(revision 18)
@@ -0,0 +1,442 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+
+#ifndef __SGI_STL_INTERNAL_ALGOBASE_H
+#define __SGI_STL_INTERNAL_ALGOBASE_H
+
+#ifndef __STL_CONFIG_H
+#include <stl_conf.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_RELOPS
+#include <stl_relo.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_PAIR_H
+#include <stl_pair.h>
+#endif
+#ifndef __TYPE_TRAITS_H_
+#include <type_tra.h>
+#endif
+
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <new.h>
+#include <iostream.h>
+
+#ifndef __SGI_STL_INTERNAL_ITERATOR_H
+#include <stl_iter.h>
+#endif
+
+__STL_BEGIN_NAMESPACE
+
+template <class ForwardIterator1, class ForwardIterator2, class T>
+inline void __iter_swap(ForwardIterator1 a, ForwardIterator2 b, T*) {
+  T tmp = *a;
+  *a = *b;
+  *b = tmp;
+}
+
+template <class ForwardIterator1, class ForwardIterator2>
+inline void iter_swap(ForwardIterator1 a, ForwardIterator2 b) {
+  __iter_swap(a, b, value_type(a));
+}
+
+template <class T>
+inline void swap(T& a, T& b) {
+  T tmp = a;
+  a = b;
+  b = tmp;
+}
+
+#ifndef __BORLANDC__
+
+#undef min
+#undef max
+
+template <class T>
+inline const T& min(const T& a, const T& b) {
+  return b < a ? b : a;
+}
+
+template <class T>
+inline const T& max(const T& a, const T& b) {
+  return  a < b ? b : a;
+}
+
+#endif /* __BORLANDC__ */
+
+template <class T, class Compare>
+inline const T& min(const T& a, const T& b, Compare comp) {
+  return comp(b, a) ? b : a;
+}
+
+template <class T, class Compare>
+inline const T& max(const T& a, const T& b, Compare comp) {
+  return comp(a, b) ? b : a;
+}
+
+template <class InputIterator, class OutputIterator>
+inline OutputIterator __copy(InputIterator first, InputIterator last,
+                             OutputIterator result, input_iterator_tag)
+{
+  for ( ; first != last; ++result, ++first)
+    *result = *first;
+  return result;
+}
+
+template <class RandomAccessIterator, class OutputIterator, class Distance>
+inline OutputIterator
+__copy_d(RandomAccessIterator first, RandomAccessIterator last,
+         OutputIterator result, Distance*)
+{
+  for (Distance n = last - first; n > 0; --n, ++result, ++first) 
+    *result = *first;
+  return result;
+}
+
+template <class RandomAccessIterator, class OutputIterator>
+inline OutputIterator 
+__copy(RandomAccessIterator first, RandomAccessIterator last,
+       OutputIterator result, random_access_iterator_tag)
+{
+  return __copy_d(first, last, result, distance_type(first));
+}
+
+template <class InputIterator, class OutputIterator>
+struct __copy_dispatch
+{
+  OutputIterator operator()(InputIterator first, InputIterator last,
+                            OutputIterator result) {
+    return __copy(first, last, result, iterator_category(first));
+  }
+};
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION 
+
+template <class T>
+inline T* __copy_t(const T* first, const T* last, T* result, __true_type) {
+  memmove(result, first, sizeof(T) * (last - first));
+  return result + (last - first);
+}
+
+template <class T>
+inline T* __copy_t(const T* first, const T* last, T* result, __false_type) {
+  return __copy_d(first, last, result, (ptrdiff_t*) 0);
+}
+
+template <class T>
+struct __copy_dispatch<T*, T*>
+{
+  T* operator()(T* first, T* last, T* result) {
+    typedef typename __type_traits<T>::has_trivial_assignment_operator t; 
+    return __copy_t(first, last, result, t());
+  }
+};
+
+template <class T>
+struct __copy_dispatch<const T*, T*>
+{
+  T* operator()(const T* first, const T* last, T* result) {
+    typedef typename __type_traits<T>::has_trivial_assignment_operator t; 
+    return __copy_t(first, last, result, t());
+  }
+};
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class InputIterator, class OutputIterator>
+inline OutputIterator copy(InputIterator first, InputIterator last,
+                           OutputIterator result)
+{
+  return __copy_dispatch<InputIterator,OutputIterator>()(first, last, result);
+}
+
+inline char* copy(const char* first, const char* last, char* result) {
+  memmove(result, first, last - first);
+  return result + (last - first);
+}
+
+inline wchar_t* copy(const wchar_t* first, const wchar_t* last,
+                     wchar_t* result) {
+  memmove(result, first, sizeof(wchar_t) * (last - first));
+  return result + (last - first);
+}
+
+template <class BidirectionalIterator1, class BidirectionalIterator2>
+inline BidirectionalIterator2 __copy_backward(BidirectionalIterator1 first, 
+                                              BidirectionalIterator1 last, 
+                                              BidirectionalIterator2 result) {
+  while (first != last) *--result = *--last;
+  return result;
+}
+
+
+template <class BidirectionalIterator1, class BidirectionalIterator2>
+struct __copy_backward_dispatch
+{
+  BidirectionalIterator2 operator()(BidirectionalIterator1 first, 
+                                    BidirectionalIterator1 last, 
+                                    BidirectionalIterator2 result) {
+    return __copy_backward(first, last, result);
+  }
+};
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION 
+
+template <class T>
+inline T* __copy_backward_t(const T* first, const T* last, T* result,
+                            __true_type) {
+  const ptrdiff_t N = last - first;
+  memmove(result - N, first, sizeof(T) * N);
+  return result - N;
+}
+
+template <class T>
+inline T* __copy_backward_t(const T* first, const T* last, T* result,
+                            __false_type) {
+  return __copy_backward(first, last, result);
+}
+
+template <class T>
+struct __copy_backward_dispatch<T*, T*>
+{
+  T* operator()(T* first, T* last, T* result) {
+    typedef typename __type_traits<T>::has_trivial_assignment_operator t; 
+    return __copy_backward_t(first, last, result, t());
+  }
+};
+
+template <class T>
+struct __copy_backward_dispatch<const T*, T*>
+{
+  T* operator()(const T* first, const T* last, T* result) {
+    typedef typename __type_traits<T>::has_trivial_assignment_operator t; 
+    return __copy_backward_t(first, last, result, t());
+  }
+};
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class BidirectionalIterator1, class BidirectionalIterator2>
+inline BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, 
+                                            BidirectionalIterator1 last, 
+                                            BidirectionalIterator2 result) {
+  return __copy_backward_dispatch<BidirectionalIterator1, 
+                                  BidirectionalIterator2>()(first, last, 
+                                                            result);
+}
+
+template <class InputIterator, class Size, class OutputIterator>
+pair<InputIterator, OutputIterator> __copy_n(InputIterator first, Size count,
+                                             OutputIterator result,
+                                             input_iterator_tag) {
+  for ( ; count > 0; --count, ++first, ++result)
+    *result = *first;
+  return pair<InputIterator, OutputIterator>(first, result);
+}
+
+template <class RandomAccessIterator, class Size, class OutputIterator>
+inline pair<RandomAccessIterator, OutputIterator>
+__copy_n(RandomAccessIterator first, Size count,
+         OutputIterator result,
+         random_access_iterator_tag) {
+  RandomAccessIterator last = first + count;
+  return pair<RandomAccessIterator, OutputIterator>(last,
+                                                    copy(first, last, result));
+}
+
+template <class InputIterator, class Size, class OutputIterator>
+inline pair<InputIterator, OutputIterator>
+copy_n(InputIterator first, Size count,
+       OutputIterator result) {
+  return __copy_n(first, count, result, iterator_category(first));
+}
+
+template <class ForwardIterator, class T>
+void fill(ForwardIterator first, ForwardIterator last, const T& value) {
+  for ( ; first != last; ++first)
+    *first = value;
+}
+
+template <class OutputIterator, class Size, class T>
+OutputIterator fill_n(OutputIterator first, Size n, const T& value) {
+  for ( ; n > 0; --n, ++first)
+    *first = value;
+  return first;
+}
+
+template <class InputIterator1, class InputIterator2>
+pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1,
+					      InputIterator1 last1,
+					      InputIterator2 first2) {
+  while (first1 != last1 && *first1 == *first2) {
+    ++first1;
+    ++first2;
+  }
+  return pair<InputIterator1, InputIterator2>(first1, first2);
+}
+
+template <class InputIterator1, class InputIterator2, class BinaryPredicate>
+pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1,
+					      InputIterator1 last1,
+					      InputIterator2 first2,
+					      BinaryPredicate binary_pred) {
+  while (first1 != last1 && binary_pred(*first1, *first2)) {
+    ++first1;
+    ++first2;
+  }
+  return pair<InputIterator1, InputIterator2>(first1, first2);
+}
+
+template <class InputIterator1, class InputIterator2>
+inline bool equal(InputIterator1 first1, InputIterator1 last1,
+		  InputIterator2 first2) {
+  for ( ; first1 != last1; ++first1, ++first2)
+    if (*first1 != *first2)
+      return false;
+  return true;
+}
+
+template <class InputIterator1, class InputIterator2, class BinaryPredicate>
+inline bool equal(InputIterator1 first1, InputIterator1 last1,
+		  InputIterator2 first2, BinaryPredicate binary_pred) {
+  for ( ; first1 != last1; ++first1, ++first2)
+    if (!binary_pred(*first1, *first2))
+      return false;
+  return true;
+}
+
+template <class InputIterator1, class InputIterator2>
+bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
+			     InputIterator2 first2, InputIterator2 last2) {
+  for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) {
+    if (*first1 < *first2)
+      return true;
+    if (*first2 < *first1)
+      return false;
+  }
+  return first1 == last1 && first2 != last2;
+}
+
+template <class InputIterator1, class InputIterator2, class Compare>
+bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
+			     InputIterator2 first2, InputIterator2 last2,
+			     Compare comp) {
+  for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) {
+    if (comp(*first1, *first2))
+      return true;
+    if (comp(*first2, *first1))
+      return false;
+  }
+  return first1 == last1 && first2 != last2;
+}
+
+inline bool 
+lexicographical_compare(const unsigned char* first1,
+                        const unsigned char* last1,
+                        const unsigned char* first2,
+                        const unsigned char* last2)
+{
+  const size_t len1 = last1 - first1;
+  const size_t len2 = last2 - first2;
+  const int result = memcmp(first1, first2, min(len1, len2));
+  return result != 0 ? result < 0 : len1 < len2;
+}
+
+inline bool lexicographical_compare(const char* first1, const char* last1,
+                                    const char* first2, const char* last2)
+{
+#if CHAR_MAX == SCHAR_MAX
+  return lexicographical_compare((const signed char*) first1,
+                                 (const signed char*) last1,
+                                 (const signed char*) first2,
+                                 (const signed char*) last2);
+#else
+  return lexicographical_compare((const unsigned char*) first1,
+                                 (const unsigned char*) last1,
+                                 (const unsigned char*) first2,
+                                 (const unsigned char*) last2);
+#endif
+}
+
+template <class InputIterator1, class InputIterator2>
+int lexicographical_compare_3way(InputIterator1 first1, InputIterator1 last1,
+                                 InputIterator2 first2, InputIterator2 last2)
+{
+  while (first1 != last1 && first2 != last2) {
+    if (*first1 < *first2) return -1;
+    if (*first2 < *first1) return 1;
+    ++first1; ++first2;
+  }
+  if (first2 == last2) {
+    return !(first1 == last1);
+  } else {
+    return -1;
+  }
+}
+
+inline int
+lexicographical_compare_3way(const unsigned char* first1,
+                             const unsigned char* last1,
+                             const unsigned char* first2,
+                             const unsigned char* last2)
+{
+  const ptrdiff_t len1 = last1 - first1;
+  const ptrdiff_t len2 = last2 - first2;
+  const int result = memcmp(first1, first2, min(len1, len2));
+  return result != 0 ? result : (len1 == len2 ? 0 : (len1 < len2 ? -1 : 1));
+}
+
+inline int lexicographical_compare_3way(const char* first1, const char* last1,
+                                        const char* first2, const char* last2)
+{
+#if CHAR_MAX == SCHAR_MAX
+  return lexicographical_compare_3way(
+				(const signed char*) first1,
+                                (const signed char*) last1,
+                                (const signed char*) first2,
+                                (const signed char*) last2);
+#else
+  return lexicographical_compare_3way((const unsigned char*) first1,
+                                      (const unsigned char*) last1,
+                                      (const unsigned char*) first2,
+                                      (const unsigned char*) last2);
+#endif
+}
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_ALGOBASE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_algo.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_algo.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_algo.h	(revision 18)
@@ -0,0 +1,2674 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_ALGO_H
+#define __SGI_STL_INTERNAL_ALGO_H
+
+#include <stl_heap.h>
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1209
+#endif
+
+template <class T>
+inline const T& __median(const T& a, const T& b, const T& c) {
+  if (a < b)
+    if (b < c)
+      return b;
+    else if (a < c)
+      return c;
+    else
+      return a;
+  else if (a < c)
+    return a;
+  else if (b < c)
+    return c;
+  else
+    return b;
+}
+
+template <class T, class Compare>
+inline const T& __median(const T& a, const T& b, const T& c, Compare comp) {
+  if (comp(a, b))
+    if (comp(b, c))
+      return b;
+    else if (comp(a, c))
+      return c;
+    else
+      return a;
+  else if (comp(a, c))
+    return a;
+  else if (comp(b, c))
+    return c;
+  else
+    return b;
+}
+
+template <class InputIterator, class Function>
+Function for_each(InputIterator first, InputIterator last, Function f) {
+  for ( ; first != last; ++first)
+    f(*first);
+  return f;
+}
+
+template <class InputIterator, class T>
+InputIterator find(InputIterator first, InputIterator last, const T& value) {
+  while (first != last && *first != value) ++first;
+  return first;
+}
+
+template <class InputIterator, class Predicate>
+InputIterator find_if(InputIterator first, InputIterator last,
+                      Predicate pred) {
+  while (first != last && !pred(*first)) ++first;
+  return first;
+}
+
+template <class ForwardIterator>
+ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last) {
+  if (first == last) return last;
+  ForwardIterator next = first;
+  while(++next != last) {
+    if (*first == *next) return first;
+    first = next;
+  }
+  return last;
+}
+
+template <class ForwardIterator, class BinaryPredicate>
+ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last,
+                              BinaryPredicate binary_pred) {
+  if (first == last) return last;
+  ForwardIterator next = first;
+  while(++next != last) {
+    if (binary_pred(*first, *next)) return first;
+    first = next;
+  }
+  return last;
+}
+
+template <class InputIterator, class T, class Size>
+void count(InputIterator first, InputIterator last, const T& value,
+           Size& n) {
+  for ( ; first != last; ++first)
+    if (*first == value)
+      ++n;
+}
+
+template <class InputIterator, class Predicate, class Size>
+void count_if(InputIterator first, InputIterator last, Predicate pred,
+              Size& n) {
+  for ( ; first != last; ++first)
+    if (pred(*first))
+      ++n;
+}
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class InputIterator, class T>
+typename iterator_traits<InputIterator>::difference_type
+count(InputIterator first, InputIterator last, const T& value) {
+  typename iterator_traits<InputIterator>::difference_type n = 0;
+  for ( ; first != last; ++first)
+    if (*first == value)
+      ++n;
+  return n;
+}
+
+template <class InputIterator, class Predicate>
+typename iterator_traits<InputIterator>::difference_type
+count_if(InputIterator first, InputIterator last, Predicate pred) {
+  typename iterator_traits<InputIterator>::difference_type n = 0;
+  for ( ; first != last; ++first)
+    if (pred(*first))
+      ++n;
+  return n;
+}
+
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class ForwardIterator1, class ForwardIterator2, class Distance1,
+          class Distance2>
+ForwardIterator1 __search(ForwardIterator1 first1, ForwardIterator1 last1,
+                          ForwardIterator2 first2, ForwardIterator2 last2,
+                          Distance1*, Distance2*) {
+  Distance1 d1 = 0;
+  distance(first1, last1, d1);
+  Distance2 d2 = 0;
+  distance(first2, last2, d2);
+
+  if (d1 < d2) return last1;
+
+  ForwardIterator1 current1 = first1;
+  ForwardIterator2 current2 = first2;
+
+  while (current2 != last2) 
+    if (*current1 == *current2) {
+      ++current1;
+      ++current2;
+    }
+    else {
+      if (d1 == d2)
+        return last1;
+      else {
+        current1 = ++first1;
+        current2 = first2;
+        --d1;
+      }
+    }
+  return first1;
+}
+
+template <class ForwardIterator1, class ForwardIterator2>
+inline ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1,
+                               ForwardIterator2 first2, ForwardIterator2 last2)
+{
+  return __search(first1, last1, first2, last2, distance_type(first1),
+                  distance_type(first2));
+}
+
+template <class ForwardIterator1, class ForwardIterator2,
+          class BinaryPredicate, class Distance1, class Distance2>
+ForwardIterator1 __search(ForwardIterator1 first1, ForwardIterator1 last1,
+                          ForwardIterator2 first2, ForwardIterator2 last2,
+                          BinaryPredicate binary_pred, Distance1*, Distance2*) {
+  Distance1 d1 = 0;
+  distance(first1, last1, d1);
+  Distance2 d2 = 0;
+  distance(first2, last2, d2);
+
+  if (d1 < d2) return last1;
+
+  ForwardIterator1 current1 = first1;
+  ForwardIterator2 current2 = first2;
+
+  while (current2 != last2)
+    if (binary_pred(*current1, *current2)) {
+      ++current1;
+      ++current2;
+    }
+    else {
+      if (d1 == d2)
+        return last1;
+      else {
+        current1 = ++first1;
+        current2 = first2;
+        --d1;
+      }
+    }
+  return first1;
+}
+
+template <class ForwardIterator1, class ForwardIterator2,
+          class BinaryPredicate>
+inline ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1,
+                               ForwardIterator2 first2, ForwardIterator2 last2,
+                               BinaryPredicate binary_pred) {
+  return __search(first1, last1, first2, last2, binary_pred,
+                  distance_type(first1), distance_type(first2));
+}
+
+template <class ForwardIterator, class Integer, class T>
+ForwardIterator search_n(ForwardIterator first, ForwardIterator last,
+                         Integer count, const T& value) {
+  if (count <= 0)
+    return first;
+  else {
+    first = find(first, last, value);
+    while (first != last) {
+      Integer n = count - 1;
+      ForwardIterator i = first;
+      ++i;
+      while (i != last && n != 0 && *i == value) {
+        ++i;
+        --n;
+      }
+      if (n == 0)
+        return first;
+      else
+        first = find(i, last, value);
+    }
+    return last;
+  }
+}
+
+template <class ForwardIterator, class Integer, class T, class BinaryPredicate>
+ForwardIterator search_n(ForwardIterator first, ForwardIterator last,
+                         Integer count, const T& value,
+                         BinaryPredicate binary_pred) {
+  if (count <= 0)
+    return first;
+  else {
+    while (first != last) {
+      if (binary_pred(*first, value)) break;
+      ++first;
+    }
+    while (first != last) {
+      Integer n = count - 1;
+      ForwardIterator i = first;
+      ++i;
+      while (i != last && n != 0 && binary_pred(*i, value)) {
+        ++i;
+        --n;
+      }
+      if (n == 0)
+        return first;
+      else {
+        while (i != last) {
+          if (binary_pred(*i, value)) break;
+          ++i;
+        }
+        first = i;
+      }
+    }
+    return last;
+  }
+} 
+
+template <class ForwardIterator1, class ForwardIterator2>
+ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1,
+                             ForwardIterator2 first2) {
+  for ( ; first1 != last1; ++first1, ++first2)
+    iter_swap(first1, first2);
+  return first2;
+}
+
+template <class InputIterator, class OutputIterator, class UnaryOperation>
+OutputIterator transform(InputIterator first, InputIterator last,
+                         OutputIterator result, UnaryOperation op) {
+  for ( ; first != last; ++first, ++result)
+    *result = op(*first);
+  return result;
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator,
+          class BinaryOperation>
+OutputIterator transform(InputIterator1 first1, InputIterator1 last1,
+                         InputIterator2 first2, OutputIterator result,
+                         BinaryOperation binary_op) {
+  for ( ; first1 != last1; ++first1, ++first2, ++result)
+    *result = binary_op(*first1, *first2);
+  return result;
+}
+
+template <class ForwardIterator, class T>
+void replace(ForwardIterator first, ForwardIterator last, const T& old_value,
+             const T& new_value) {
+  for ( ; first != last; ++first)
+    if (*first == old_value) *first = new_value;
+}
+
+template <class ForwardIterator, class Predicate, class T>
+void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred,
+                const T& new_value) {
+  for ( ; first != last; ++first)
+    if (pred(*first)) *first = new_value;
+}
+
+template <class InputIterator, class OutputIterator, class T>
+OutputIterator replace_copy(InputIterator first, InputIterator last,
+                            OutputIterator result, const T& old_value,
+                            const T& new_value) {
+  for ( ; first != last; ++first, ++result)
+    *result = *first == old_value ? new_value : *first;
+  return result;
+}
+
+template <class Iterator, class OutputIterator, class Predicate, class T>
+OutputIterator replace_copy_if(Iterator first, Iterator last,
+                               OutputIterator result, Predicate pred,
+                               const T& new_value) {
+  for ( ; first != last; ++first, ++result)
+    *result = pred(*first) ? new_value : *first;
+  return result;
+}
+
+template <class ForwardIterator, class Generator>
+void generate(ForwardIterator first, ForwardIterator last, Generator gen) {
+  for ( ; first != last; ++first)
+    *first = gen();
+}
+
+template <class OutputIterator, class Size, class Generator>
+OutputIterator generate_n(OutputIterator first, Size n, Generator gen) {
+  for ( ; n > 0; --n, ++first)
+    *first = gen();
+  return first;
+}
+
+template <class InputIterator, class OutputIterator, class T>
+OutputIterator remove_copy(InputIterator first, InputIterator last,
+                           OutputIterator result, const T& value) {
+  for ( ; first != last; ++first)
+    if (*first != value) {
+      *result = *first;
+      ++result;
+    }
+  return result;
+}
+
+template <class InputIterator, class OutputIterator, class Predicate>
+OutputIterator remove_copy_if(InputIterator first, InputIterator last,
+                              OutputIterator result, Predicate pred) {
+  for ( ; first != last; ++first)
+    if (!pred(*first)) {
+      *result = *first;
+      ++result;
+    }
+  return result;
+}
+
+template <class ForwardIterator, class T>
+ForwardIterator remove(ForwardIterator first, ForwardIterator last,
+                       const T& value) {
+  first = find(first, last, value);
+  ForwardIterator next = first;
+  return first == last ? first : remove_copy(++next, last, first, value);
+}
+
+template <class ForwardIterator, class Predicate>
+ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
+                          Predicate pred) {
+  first = find_if(first, last, pred);
+  ForwardIterator next = first;
+  return first == last ? first : remove_copy_if(++next, last, first, pred);
+}
+
+template <class InputIterator, class ForwardIterator>
+ForwardIterator __unique_copy(InputIterator first, InputIterator last,
+                              ForwardIterator result, forward_iterator_tag) {
+  *result = *first;
+  while (++first != last)
+    if (*result != *first) *++result = *first;
+  return ++result;
+}
+
+
+template <class InputIterator, class OutputIterator, class T>
+OutputIterator __unique_copy(InputIterator first, InputIterator last,
+                             OutputIterator result, T*) {
+  T value = *first;
+  *result = value;
+  while (++first != last)
+    if (value != *first) {
+      value = *first;
+      *++result = value;
+    }
+  return ++result;
+}
+
+template <class InputIterator, class OutputIterator>
+inline OutputIterator __unique_copy(InputIterator first, InputIterator last,
+                                    OutputIterator result, 
+                                    output_iterator_tag) {
+  return __unique_copy(first, last, result, value_type(first));
+}
+
+template <class InputIterator, class OutputIterator>
+inline OutputIterator unique_copy(InputIterator first, InputIterator last,
+                                  OutputIterator result) {
+  if (first == last) return result;
+  return __unique_copy(first, last, result, iterator_category(result));
+}
+template <class InputIterator, class ForwardIterator, class BinaryPredicate>
+ForwardIterator __unique_copy(InputIterator first, InputIterator last,
+                              ForwardIterator result, 
+                              BinaryPredicate binary_pred,
+                              forward_iterator_tag) {
+  *result = *first;
+  while (++first != last)
+    if (!binary_pred(*result, *first)) *++result = *first;
+  return ++result;
+}
+
+template <class InputIterator, class OutputIterator, class BinaryPredicate,
+          class T>
+OutputIterator __unique_copy(InputIterator first, InputIterator last,
+                             OutputIterator result,
+                             BinaryPredicate binary_pred, T*) {
+  T value = *first;
+  *result = value;
+  while (++first != last)
+    if (!binary_pred(value, *first)) {
+      value = *first;
+      *++result = value;
+    }
+  return ++result;
+}
+
+template <class InputIterator, class OutputIterator, class BinaryPredicate>
+inline OutputIterator __unique_copy(InputIterator first, InputIterator last,
+                                    OutputIterator result,
+                                    BinaryPredicate binary_pred,
+                                    output_iterator_tag) {
+  return __unique_copy(first, last, result, binary_pred, value_type(first));
+}
+
+template <class InputIterator, class OutputIterator, class BinaryPredicate>
+inline OutputIterator unique_copy(InputIterator first, InputIterator last,
+                                  OutputIterator result,
+                                  BinaryPredicate binary_pred) {
+  if (first == last) return result;
+  return __unique_copy(first, last, result, binary_pred,
+                       iterator_category(result));
+}
+
+template <class ForwardIterator>
+ForwardIterator unique(ForwardIterator first, ForwardIterator last) {
+  first = adjacent_find(first, last);
+  return unique_copy(first, last, first);
+}
+
+template <class ForwardIterator, class BinaryPredicate>
+ForwardIterator unique(ForwardIterator first, ForwardIterator last,
+                       BinaryPredicate binary_pred) {
+  first = adjacent_find(first, last, binary_pred);
+  return unique_copy(first, last, first, binary_pred);
+}
+
+template <class BidirectionalIterator>
+void __reverse(BidirectionalIterator first, BidirectionalIterator last, 
+               bidirectional_iterator_tag) {
+  while (true)
+    if (first == last || first == --last)
+      return;
+    else
+      iter_swap(first++, last);
+}
+
+template <class RandomAccessIterator>
+void __reverse(RandomAccessIterator first, RandomAccessIterator last,
+               random_access_iterator_tag) {
+  while (first < last) iter_swap(first++, --last);
+}
+
+template <class BidirectionalIterator>
+inline void reverse(BidirectionalIterator first, BidirectionalIterator last) {
+  __reverse(first, last, iterator_category(first));
+}
+
+template <class BidirectionalIterator, class OutputIterator>
+OutputIterator reverse_copy(BidirectionalIterator first,
+                            BidirectionalIterator last,
+                            OutputIterator result) {
+  while (first != last) {
+    --last;
+    *result = *last;
+    ++result;
+  }
+  return result;
+}
+
+template <class ForwardIterator, class Distance>
+void __rotate(ForwardIterator first, ForwardIterator middle,
+              ForwardIterator last, Distance*, forward_iterator_tag) {
+  for (ForwardIterator i = middle; ;) {
+    iter_swap(first, i);
+    ++first;
+    ++i;
+    if (first == middle) {
+      if (i == last) return;
+      middle = i;
+    }
+    else if (i == last)
+      i = middle;
+  }
+}
+
+template <class BidirectionalIterator, class Distance>
+void __rotate(BidirectionalIterator first, BidirectionalIterator middle,
+              BidirectionalIterator last, Distance*,
+              bidirectional_iterator_tag) {
+  reverse(first, middle);
+  reverse(middle, last);
+  reverse(first, last);
+}
+
+template <class EuclideanRingElement>
+EuclideanRingElement __gcd(EuclideanRingElement m, EuclideanRingElement n)
+{
+  while (n != 0) {
+    EuclideanRingElement t = m % n;
+    m = n;
+    n = t;
+  }
+  return m;
+}
+
+template <class RandomAccessIterator, class Distance, class T>
+void __rotate_cycle(RandomAccessIterator first, RandomAccessIterator last,
+                    RandomAccessIterator initial, Distance shift, T*) {
+  T value = *initial;
+  RandomAccessIterator ptr1 = initial;
+  RandomAccessIterator ptr2 = ptr1 + shift;
+  while (ptr2 != initial) {
+    *ptr1 = *ptr2;
+    ptr1 = ptr2;
+    if (last - ptr2 > shift)
+      ptr2 += shift;
+    else
+      ptr2 = first + (shift - (last - ptr2));
+  }
+  *ptr1 = value;
+}
+
+template <class RandomAccessIterator, class Distance>
+void __rotate(RandomAccessIterator first, RandomAccessIterator middle,
+              RandomAccessIterator last, Distance*,
+              random_access_iterator_tag) {
+  Distance n = __gcd(last - first, middle - first);
+  while (n--)
+    __rotate_cycle(first, last, first + n, middle - first,
+                   value_type(first));
+}
+
+template <class ForwardIterator>
+inline void rotate(ForwardIterator first, ForwardIterator middle,
+                   ForwardIterator last) {
+  if (first == middle || middle == last) return;
+  __rotate(first, middle, last, distance_type(first),
+           iterator_category(first));
+}
+
+template <class ForwardIterator, class OutputIterator>
+OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle,
+                           ForwardIterator last, OutputIterator result) {
+  return copy(first, middle, copy(middle, last, result));
+}
+
+template <class RandomAccessIterator, class Distance>
+void __random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
+                      Distance*) {
+  if (first == last) return;
+  for (RandomAccessIterator i = first + 1; i != last; ++i) 
+#ifdef __STL_NO_DRAND48
+    iter_swap(i, first + Distance(rand() % ((i - first) + 1)));
+#else
+  iter_swap(i, first + Distance(lrand48() % ((i - first) + 1)));
+#endif
+}
+
+template <class RandomAccessIterator>
+inline void random_shuffle(RandomAccessIterator first,
+                           RandomAccessIterator last) {
+  __random_shuffle(first, last, distance_type(first));
+}
+
+template <class RandomAccessIterator, class RandomNumberGenerator>
+void random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
+                    RandomNumberGenerator& rand) {
+  if (first == last) return;
+  for (RandomAccessIterator i = first + 1; i != last; ++i)
+    iter_swap(i, first + rand((i - first) + 1));
+}
+
+template <class ForwardIterator, class OutputIterator, class Distance>
+OutputIterator random_sample_n(ForwardIterator first, ForwardIterator last,
+                               OutputIterator out, const Distance n)
+{
+  Distance remaining = 0;
+  distance(first, last, remaining);
+  Distance m = min(n, remaining);
+
+  while (m > 0) {
+#ifdef __STL_NO_DRAND48
+    if (rand() % remaining < m) {
+#else
+    if (lrand48() % remaining < m) {
+#endif
+      *out = *first;
+      ++out;
+      --m;
+    }
+
+    --remaining;
+    ++first;
+  }
+  return out;
+}
+
+template <class ForwardIterator, class OutputIterator, class Distance,
+          class RandomNumberGenerator>
+OutputIterator random_sample_n(ForwardIterator first, ForwardIterator last,
+                               OutputIterator out, const Distance n,
+                               RandomNumberGenerator& rand)
+{
+  Distance remaining = 0;
+  distance(first, last, remaining);
+  Distance m = min(n, remaining);
+
+  while (m > 0) {
+    if (rand(remaining) < m) {
+      *out = *first;
+      ++out;
+      --m;
+    }
+
+    --remaining;
+    ++first;
+  }
+  return out;
+}
+
+template <class InputIterator, class RandomAccessIterator, class Distance>
+RandomAccessIterator __random_sample(InputIterator first, InputIterator last,
+                                     RandomAccessIterator out,
+                                     const Distance n)
+{
+  Distance m = 0;
+  Distance t = n;
+  for ( ; first != last && m < n; ++m, ++first) 
+    out[m] = *first;
+
+  while (first != last) {
+    ++t;
+#ifdef __STL_NO_DRAND48
+    Distance M = rand() % t;
+#else
+    Distance M = lrand48() % t;
+#endif
+    if (M < n)
+      out[M] = *first;
+    ++first;
+  }
+
+  return out + m;
+}
+
+template <class InputIterator, class RandomAccessIterator,
+          class RandomNumberGenerator, class Distance>
+RandomAccessIterator __random_sample(InputIterator first, InputIterator last,
+                                     RandomAccessIterator out,
+                                     RandomNumberGenerator& rand,
+                                     const Distance n)
+{
+  Distance m = 0;
+  Distance t = n;
+  for ( ; first != last && m < n; ++m, ++first)
+    out[m] = *first;
+
+  while (first != last) {
+    ++t;
+    Distance M = rand(t);
+    if (M < n)
+      out[M] = *first;
+    ++first;
+  }
+
+  return out + m;
+}
+
+template <class InputIterator, class RandomAccessIterator>
+inline RandomAccessIterator
+random_sample(InputIterator first, InputIterator last,
+              RandomAccessIterator out_first, RandomAccessIterator out_last) 
+{
+  return __random_sample(first, last, out_first, out_last - out_first);
+}
+
+template <class InputIterator, class RandomAccessIterator, 
+          class RandomNumberGenerator>
+inline RandomAccessIterator
+random_sample(InputIterator first, InputIterator last,
+              RandomAccessIterator out_first, RandomAccessIterator out_last,
+              RandomNumberGenerator& rand) 
+{
+  return __random_sample(first, last, out_first, rand, out_last - out_first);
+}
+
+
+
+template <class BidirectionalIterator, class Predicate>
+BidirectionalIterator partition(BidirectionalIterator first,
+                                BidirectionalIterator last, Predicate pred) {
+  while (true) {
+    while (true)
+      if (first == last)
+        return first;
+      else if (pred(*first))
+        ++first;
+      else
+        break;
+    --last;
+    while (true)
+      if (first == last)
+        return first;
+      else if (!pred(*last))
+        --last;
+      else
+        break;
+    iter_swap(first, last);
+    ++first;
+  }
+}
+
+template <class ForwardIterator, class Predicate, class Distance>
+ForwardIterator __inplace_stable_partition(ForwardIterator first,
+                                           ForwardIterator last,
+                                           Predicate pred, Distance len) {
+  if (len == 1) return pred(*first) ? last : first;
+  ForwardIterator middle = first;
+  advance(middle, len / 2);
+  ForwardIterator 
+    first_cut = __inplace_stable_partition(first, middle, pred, len / 2);
+  ForwardIterator 
+    second_cut = __inplace_stable_partition(middle, last, pred,
+                                            len - len / 2);
+  rotate(first_cut, middle, second_cut);
+  len = 0;
+  distance(middle, second_cut, len);
+  advance(first_cut, len);
+  return first_cut;
+}
+
+template <class ForwardIterator, class Pointer, class Predicate, 
+          class Distance>
+ForwardIterator __stable_partition_adaptive(ForwardIterator first,
+                                            ForwardIterator last,
+                                            Predicate pred, Distance len,
+                                            Pointer buffer,
+                                            Distance buffer_size) {
+  if (len <= buffer_size) {
+    ForwardIterator result1 = first;
+    Pointer result2 = buffer;
+    for ( ; first != last ; ++first)
+      if (pred(*first)) {
+        *result1 = *first;
+        ++result1;
+      }
+      else {
+        *result2 = *first;
+        ++result2;
+      }
+    copy(buffer, result2, result1);
+    return result1;
+  }
+  else {
+    ForwardIterator middle = first;
+    advance(middle, len / 2);
+    ForwardIterator first_cut =
+      __stable_partition_adaptive(first, middle, pred, len / 2,
+                                  buffer, buffer_size);
+    ForwardIterator second_cut =
+      __stable_partition_adaptive(middle, last, pred, len - len / 2,
+                                  buffer, buffer_size);
+
+    rotate(first_cut, middle, second_cut);
+    len = 0;
+    distance(middle, second_cut, len);
+    advance(first_cut, len);
+    return first_cut;
+  }
+}
+
+template <class ForwardIterator, class Predicate, class T, class Distance>
+inline ForwardIterator __stable_partition_aux(ForwardIterator first,
+                                              ForwardIterator last, 
+                                              Predicate pred, T*, Distance*) {
+  temporary_buffer<ForwardIterator, T> buf(first, last);
+  if (buf.size() > 0)
+    return __stable_partition_adaptive(first, last, pred,
+                                       Distance(buf.requested_size()),
+                                       buf.begin(), buf.size());
+  else
+    return __inplace_stable_partition(first, last, pred, 
+                                      Distance(buf.requested_size()));
+}
+
+template <class ForwardIterator, class Predicate>
+inline ForwardIterator stable_partition(ForwardIterator first,
+                                        ForwardIterator last, 
+                                        Predicate pred) {
+  if (first == last)
+    return first;
+  else
+    return __stable_partition_aux(first, last, pred,
+                                  value_type(first), distance_type(first));
+}
+
+template <class RandomAccessIterator, class T>
+RandomAccessIterator __unguarded_partition(RandomAccessIterator first, 
+                                           RandomAccessIterator last, 
+                                           T pivot) {
+  while (true) {
+    while (*first < pivot) ++first;
+    --last;
+    while (pivot < *last) --last;
+    if (!(first < last)) return first;
+    iter_swap(first, last);
+    ++first;
+  }
+}    
+
+template <class RandomAccessIterator, class T, class Compare>
+RandomAccessIterator __unguarded_partition(RandomAccessIterator first, 
+                                           RandomAccessIterator last, 
+                                           T pivot, Compare comp) {
+  while (1) {
+    while (comp(*first, pivot)) ++first;
+    --last;
+    while (comp(pivot, *last)) --last;
+    if (!(first < last)) return first;
+    iter_swap(first, last);
+    ++first;
+  }
+}
+
+const int __stl_threshold = 16;
+
+
+template <class RandomAccessIterator, class T>
+void __unguarded_linear_insert(RandomAccessIterator last, T value) {
+  RandomAccessIterator next = last;
+  --next;
+  while (value < *next) {
+    *last = *next;
+    last = next;
+    --next;
+  }
+  *last = value;
+}
+
+template <class RandomAccessIterator, class T, class Compare>
+void __unguarded_linear_insert(RandomAccessIterator last, T value, 
+                               Compare comp) {
+  RandomAccessIterator next = last;
+  --next;  
+  while (comp(value , *next)) {
+    *last = *next;
+    last = next;
+    --next;
+  }
+  *last = value;
+}
+
+template <class RandomAccessIterator, class T>
+inline void __linear_insert(RandomAccessIterator first, 
+                            RandomAccessIterator last, T*) {
+  T value = *last;
+  if (value < *first) {
+    copy_backward(first, last, last + 1);
+    *first = value;
+  }
+  else
+    __unguarded_linear_insert(last, value);
+}
+
+template <class RandomAccessIterator, class T, class Compare>
+inline void __linear_insert(RandomAccessIterator first, 
+                            RandomAccessIterator last, T*, Compare comp) {
+  T value = *last;
+  if (comp(value, *first)) {
+    copy_backward(first, last, last + 1);
+    *first = value;
+  }
+  else
+    __unguarded_linear_insert(last, value, comp);
+}
+
+template <class RandomAccessIterator>
+void __insertion_sort(RandomAccessIterator first, RandomAccessIterator last) {
+  if (first == last) return; 
+  for (RandomAccessIterator i = first + 1; i != last; ++i)
+    __linear_insert(first, i, value_type(first));
+}
+
+template <class RandomAccessIterator, class Compare>
+void __insertion_sort(RandomAccessIterator first,
+                      RandomAccessIterator last, Compare comp) {
+  if (first == last) return;
+  for (RandomAccessIterator i = first + 1; i != last; ++i)
+    __linear_insert(first, i, value_type(first), comp);
+}
+
+template <class RandomAccessIterator, class T>
+void __unguarded_insertion_sort_aux(RandomAccessIterator first, 
+                                    RandomAccessIterator last, T*) {
+  for (RandomAccessIterator i = first; i != last; ++i)
+    __unguarded_linear_insert(i, T(*i));
+}
+
+template <class RandomAccessIterator>
+inline void __unguarded_insertion_sort(RandomAccessIterator first, 
+                                RandomAccessIterator last) {
+  __unguarded_insertion_sort_aux(first, last, value_type(first));
+}
+
+template <class RandomAccessIterator, class T, class Compare>
+void __unguarded_insertion_sort_aux(RandomAccessIterator first, 
+                                    RandomAccessIterator last,
+                                    T*, Compare comp) {
+  for (RandomAccessIterator i = first; i != last; ++i)
+    __unguarded_linear_insert(i, T(*i), comp);
+}
+
+template <class RandomAccessIterator, class Compare>
+inline void __unguarded_insertion_sort(RandomAccessIterator first, 
+                                       RandomAccessIterator last,
+                                       Compare comp) {
+  __unguarded_insertion_sort_aux(first, last, value_type(first), comp);
+}
+
+template <class RandomAccessIterator>
+void __final_insertion_sort(RandomAccessIterator first, 
+                            RandomAccessIterator last) {
+  if (last - first > __stl_threshold) {
+    __insertion_sort(first, first + __stl_threshold);
+    __unguarded_insertion_sort(first + __stl_threshold, last);
+  }
+  else
+    __insertion_sort(first, last);
+}
+
+template <class RandomAccessIterator, class Compare>
+void __final_insertion_sort(RandomAccessIterator first, 
+                            RandomAccessIterator last, Compare comp) {
+  if (last - first > __stl_threshold) {
+    __insertion_sort(first, first + __stl_threshold, comp);
+    __unguarded_insertion_sort(first + __stl_threshold, last, comp);
+  }
+  else
+    __insertion_sort(first, last, comp);
+}
+
+template <class Size>
+inline Size __lg(Size n) {
+  Size k;
+  for (k = 0; n != 1; n >>= 1) ++k;
+  return k;
+}
+
+template <class RandomAccessIterator, class T, class Size>
+void __introsort_loop(RandomAccessIterator first,
+                      RandomAccessIterator last, T*,
+                      Size depth_limit) {
+  while (last - first > __stl_threshold) {
+    if (depth_limit == 0) {
+      partial_sort(first, last, last);
+      return;
+    }
+    --depth_limit;
+    RandomAccessIterator cut = __unguarded_partition
+      (first, last, T(__median(*first, *(first + (last - first)/2),
+                               *(last - 1))));
+    __introsort_loop(cut, last, value_type(first), depth_limit);
+    last = cut;
+  }
+}
+
+template <class RandomAccessIterator, class T, class Size, class Compare>
+void __introsort_loop(RandomAccessIterator first,
+                      RandomAccessIterator last, T*,
+                      Size depth_limit, Compare comp) {
+  while (last - first > __stl_threshold) {
+    if (depth_limit == 0) {
+      partial_sort(first, last, last, comp);
+      return;
+    }
+    --depth_limit;
+    RandomAccessIterator cut = __unguarded_partition
+      (first, last, T(__median(*first, *(first + (last - first)/2),
+                               *(last - 1), comp)), comp);
+    __introsort_loop(cut, last, value_type(first), depth_limit, comp);
+    last = cut;
+  }
+}
+
+template <class RandomAccessIterator>
+inline void sort(RandomAccessIterator first, RandomAccessIterator last) {
+  if (first != last) {
+    __introsort_loop(first, last, value_type(first), __lg(last - first) * 2);
+    __final_insertion_sort(first, last);
+  }
+}
+
+template <class RandomAccessIterator, class Compare>
+inline void sort(RandomAccessIterator first, RandomAccessIterator last,
+                 Compare comp) {
+  if (first != last) {
+    __introsort_loop(first, last, value_type(first), __lg(last - first) * 2,
+                     comp);
+    __final_insertion_sort(first, last, comp);
+  }
+}
+
+
+template <class RandomAccessIterator>
+void __inplace_stable_sort(RandomAccessIterator first,
+                           RandomAccessIterator last) {
+  if (last - first < 15) {
+    __insertion_sort(first, last);
+    return;
+  }
+  RandomAccessIterator middle = first + (last - first) / 2;
+  __inplace_stable_sort(first, middle);
+  __inplace_stable_sort(middle, last);
+  __merge_without_buffer(first, middle, last, middle - first, last - middle);
+}
+
+template <class RandomAccessIterator, class Compare>
+void __inplace_stable_sort(RandomAccessIterator first,
+                           RandomAccessIterator last, Compare comp) {
+  if (last - first < 15) {
+    __insertion_sort(first, last, comp);
+    return;
+  }
+  RandomAccessIterator middle = first + (last - first) / 2;
+  __inplace_stable_sort(first, middle, comp);
+  __inplace_stable_sort(middle, last, comp);
+  __merge_without_buffer(first, middle, last, middle - first,
+                         last - middle, comp);
+}
+
+template <class RandomAccessIterator1, class RandomAccessIterator2,
+          class Distance>
+void __merge_sort_loop(RandomAccessIterator1 first,
+                       RandomAccessIterator1 last, 
+                       RandomAccessIterator2 result, Distance step_size) {
+  Distance two_step = 2 * step_size;
+
+  while (last - first >= two_step) {
+    result = merge(first, first + step_size,
+                   first + step_size, first + two_step, result);
+    first += two_step;
+  }
+
+  step_size = min(Distance(last - first), step_size);
+  merge(first, first + step_size, first + step_size, last, result);
+}
+
+template <class RandomAccessIterator1, class RandomAccessIterator2,
+          class Distance, class Compare>
+void __merge_sort_loop(RandomAccessIterator1 first,
+                       RandomAccessIterator1 last, 
+                       RandomAccessIterator2 result, Distance step_size,
+                       Compare comp) {
+  Distance two_step = 2 * step_size;
+
+  while (last - first >= two_step) {
+    result = merge(first, first + step_size,
+                   first + step_size, first + two_step, result, comp);
+    first += two_step;
+  }
+  step_size = min(Distance(last - first), step_size);
+
+  merge(first, first + step_size, first + step_size, last, result, comp);
+}
+
+const int __stl_chunk_size = 7;
+        
+template <class RandomAccessIterator, class Distance>
+void __chunk_insertion_sort(RandomAccessIterator first, 
+                            RandomAccessIterator last, Distance chunk_size) {
+  while (last - first >= chunk_size) {
+    __insertion_sort(first, first + chunk_size);
+    first += chunk_size;
+  }
+  __insertion_sort(first, last);
+}
+
+template <class RandomAccessIterator, class Distance, class Compare>
+void __chunk_insertion_sort(RandomAccessIterator first, 
+                            RandomAccessIterator last,
+                            Distance chunk_size, Compare comp) {
+  while (last - first >= chunk_size) {
+    __insertion_sort(first, first + chunk_size, comp);
+    first += chunk_size;
+  }
+  __insertion_sort(first, last, comp);
+}
+
+template <class RandomAccessIterator, class Pointer, class Distance>
+void __merge_sort_with_buffer(RandomAccessIterator first, 
+                              RandomAccessIterator last,
+                              Pointer buffer, Distance*) {
+  Distance len = last - first;
+  Pointer buffer_last = buffer + len;
+
+  Distance step_size = __stl_chunk_size;
+  __chunk_insertion_sort(first, last, step_size);
+
+  while (step_size < len) {
+    __merge_sort_loop(first, last, buffer, step_size);
+    step_size *= 2;
+    __merge_sort_loop(buffer, buffer_last, first, step_size);
+    step_size *= 2;
+  }
+}
+
+template <class RandomAccessIterator, class Pointer, class Distance,
+          class Compare>
+void __merge_sort_with_buffer(RandomAccessIterator first, 
+                              RandomAccessIterator last, Pointer buffer,
+                              Distance*, Compare comp) {
+  Distance len = last - first;
+  Pointer buffer_last = buffer + len;
+
+  Distance step_size = __stl_chunk_size;
+  __chunk_insertion_sort(first, last, step_size, comp);
+
+  while (step_size < len) {
+    __merge_sort_loop(first, last, buffer, step_size, comp);
+    step_size *= 2;
+    __merge_sort_loop(buffer, buffer_last, first, step_size, comp);
+    step_size *= 2;
+  }
+}
+
+template <class RandomAccessIterator, class Pointer, class Distance>
+void __stable_sort_adaptive(RandomAccessIterator first, 
+                            RandomAccessIterator last, Pointer buffer,
+                            Distance buffer_size) {
+  Distance len = (last - first + 1) / 2;
+  RandomAccessIterator middle = first + len;
+  if (len > buffer_size) {
+    __stable_sort_adaptive(first, middle, buffer, buffer_size);
+    __stable_sort_adaptive(middle, last, buffer, buffer_size);
+  } else {
+    __merge_sort_with_buffer(first, middle, buffer, (Distance*)0);
+    __merge_sort_with_buffer(middle, last, buffer, (Distance*)0);
+  }
+  __merge_adaptive(first, middle, last, Distance(middle - first), 
+                   Distance(last - middle), buffer, buffer_size);
+}
+
+template <class RandomAccessIterator, class Pointer, class Distance, 
+          class Compare>
+void __stable_sort_adaptive(RandomAccessIterator first, 
+                            RandomAccessIterator last, Pointer buffer,
+                            Distance buffer_size, Compare comp) {
+  Distance len = (last - first + 1) / 2;
+  RandomAccessIterator middle = first + len;
+  if (len > buffer_size) {
+    __stable_sort_adaptive(first, middle, buffer, buffer_size, 
+                           comp);
+    __stable_sort_adaptive(middle, last, buffer, buffer_size, 
+                           comp);
+  } else {
+    __merge_sort_with_buffer(first, middle, buffer, (Distance*)0, comp);
+    __merge_sort_with_buffer(middle, last, buffer, (Distance*)0, comp);
+  }
+  __merge_adaptive(first, middle, last, Distance(middle - first), 
+                   Distance(last - middle), buffer, buffer_size,
+                   comp);
+}
+
+template <class RandomAccessIterator, class T, class Distance>
+inline void __stable_sort_aux(RandomAccessIterator first,
+                              RandomAccessIterator last, T*, Distance*) {
+  temporary_buffer<RandomAccessIterator, T> buf(first, last);
+  if (buf.begin() == 0)
+    __inplace_stable_sort(first, last);
+  else 
+    __stable_sort_adaptive(first, last, buf.begin(), Distance(buf.size()));
+}
+
+template <class RandomAccessIterator, class T, class Distance, class Compare>
+inline void __stable_sort_aux(RandomAccessIterator first,
+                              RandomAccessIterator last, T*, Distance*,
+                              Compare comp) {
+  temporary_buffer<RandomAccessIterator, T> buf(first, last);
+  if (buf.begin() == 0)
+    __inplace_stable_sort(first, last, comp);
+  else 
+    __stable_sort_adaptive(first, last, buf.begin(), Distance(buf.size()),
+                           comp);
+}
+
+template <class RandomAccessIterator>
+inline void stable_sort(RandomAccessIterator first,
+                        RandomAccessIterator last) {
+  __stable_sort_aux(first, last, value_type(first), distance_type(first));
+}
+
+template <class RandomAccessIterator, class Compare>
+inline void stable_sort(RandomAccessIterator first,
+                        RandomAccessIterator last, Compare comp) {
+  __stable_sort_aux(first, last, value_type(first), distance_type(first), 
+                    comp);
+}
+
+template <class RandomAccessIterator, class T>
+void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle,
+                    RandomAccessIterator last, T*) {
+  make_heap(first, middle);
+  for (RandomAccessIterator i = middle; i < last; ++i)
+    if (*i < *first) 
+      __pop_heap(first, middle, i, T(*i), distance_type(first));
+  sort_heap(first, middle);
+}
+
+template <class RandomAccessIterator>
+inline void partial_sort(RandomAccessIterator first,
+                         RandomAccessIterator middle,
+                         RandomAccessIterator last) {
+  __partial_sort(first, middle, last, value_type(first));
+}
+
+template <class RandomAccessIterator, class T, class Compare>
+void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle,
+                    RandomAccessIterator last, T*, Compare comp) {
+  make_heap(first, middle, comp);
+  for (RandomAccessIterator i = middle; i < last; ++i)
+    if (comp(*i, *first))
+      __pop_heap(first, middle, i, T(*i), comp, distance_type(first));
+  sort_heap(first, middle, comp);
+}
+
+template <class RandomAccessIterator, class Compare>
+inline void partial_sort(RandomAccessIterator first,
+                         RandomAccessIterator middle,
+                         RandomAccessIterator last, Compare comp) {
+  __partial_sort(first, middle, last, value_type(first), comp);
+}
+
+template <class InputIterator, class RandomAccessIterator, class Distance,
+          class T>
+RandomAccessIterator __partial_sort_copy(InputIterator first,
+                                         InputIterator last,
+                                         RandomAccessIterator result_first,
+                                         RandomAccessIterator result_last, 
+                                         Distance*, T*) {
+  if (result_first == result_last) return result_last;
+  RandomAccessIterator result_real_last = result_first;
+  while(first != last && result_real_last != result_last) {
+    *result_real_last = *first;
+    ++result_real_last;
+    ++first;
+  }
+  make_heap(result_first, result_real_last);
+  while (first != last) {
+    if (*first < *result_first) 
+      __adjust_heap(result_first, Distance(0),
+                    Distance(result_real_last - result_first), T(*first));
+    ++first;
+  }
+  sort_heap(result_first, result_real_last);
+  return result_real_last;
+}
+
+template <class InputIterator, class RandomAccessIterator>
+inline RandomAccessIterator
+partial_sort_copy(InputIterator first, InputIterator last,
+                  RandomAccessIterator result_first,
+                  RandomAccessIterator result_last) {
+  return __partial_sort_copy(first, last, result_first, result_last, 
+                             distance_type(result_first), value_type(first));
+}
+
+template <class InputIterator, class RandomAccessIterator, class Compare,
+          class Distance, class T>
+RandomAccessIterator __partial_sort_copy(InputIterator first,
+                                         InputIterator last,
+                                         RandomAccessIterator result_first,
+                                         RandomAccessIterator result_last,
+                                         Compare comp, Distance*, T*) {
+  if (result_first == result_last) return result_last;
+  RandomAccessIterator result_real_last = result_first;
+  while(first != last && result_real_last != result_last) {
+    *result_real_last = *first;
+    ++result_real_last;
+    ++first;
+  }
+  make_heap(result_first, result_real_last, comp);
+  while (first != last) {
+    if (comp(*first, *result_first))
+      __adjust_heap(result_first, Distance(0),
+                    Distance(result_real_last - result_first), T(*first),
+                    comp);
+    ++first;
+  }
+  sort_heap(result_first, result_real_last, comp);
+  return result_real_last;
+}
+
+template <class InputIterator, class RandomAccessIterator, class Compare>
+inline RandomAccessIterator
+partial_sort_copy(InputIterator first, InputIterator last,
+                  RandomAccessIterator result_first,
+                  RandomAccessIterator result_last, Compare comp) {
+  return __partial_sort_copy(first, last, result_first, result_last, comp,
+                             distance_type(result_first), value_type(first));
+}
+
+template <class RandomAccessIterator, class T>
+void __nth_element(RandomAccessIterator first, RandomAccessIterator nth,
+                   RandomAccessIterator last, T*) {
+  while (last - first > 3) {
+    RandomAccessIterator cut = __unguarded_partition
+      (first, last, T(__median(*first, *(first + (last - first)/2),
+                               *(last - 1))));
+    if (cut <= nth)
+      first = cut;
+    else 
+      last = cut;
+  }
+  __insertion_sort(first, last);
+}
+
+template <class RandomAccessIterator>
+inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth,
+                        RandomAccessIterator last) {
+  __nth_element(first, nth, last, value_type(first));
+}
+
+template <class RandomAccessIterator, class T, class Compare>
+void __nth_element(RandomAccessIterator first, RandomAccessIterator nth,
+                   RandomAccessIterator last, T*, Compare comp) {
+  while (last - first > 3) {
+    RandomAccessIterator cut = __unguarded_partition
+      (first, last, T(__median(*first, *(first + (last - first)/2), 
+                               *(last - 1), comp)), comp);
+    if (cut <= nth)
+      first = cut;
+    else 
+      last = cut;
+  }
+  __insertion_sort(first, last, comp);
+}
+
+template <class RandomAccessIterator, class Compare>
+inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth,
+                 RandomAccessIterator last, Compare comp) {
+  __nth_element(first, nth, last, value_type(first), comp);
+}
+
+template <class ForwardIterator, class T, class Distance>
+ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last,
+                              const T& value, Distance*,
+                              forward_iterator_tag) {
+  Distance len = 0;
+  distance(first, last, len);
+  Distance half;
+  ForwardIterator middle;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first;
+    advance(middle, half);
+    if (*middle < value) {
+      first = middle;
+      ++first;
+      len = len - half - 1;
+    }
+    else
+      len = half;
+  }
+  return first;
+}
+
+template <class RandomAccessIterator, class T, class Distance>
+RandomAccessIterator __lower_bound(RandomAccessIterator first,
+                                   RandomAccessIterator last, const T& value,
+                                   Distance*, random_access_iterator_tag) {
+  Distance len = last - first;
+  Distance half;
+  RandomAccessIterator middle;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first + half;
+    if (*middle < value) {
+      first = middle + 1;
+      len = len - half - 1;
+    }
+    else
+      len = half;
+  }
+  return first;
+}
+
+template <class ForwardIterator, class T>
+inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
+                                   const T& value) {
+  return __lower_bound(first, last, value, distance_type(first),
+                       iterator_category(first));
+}
+
+template <class ForwardIterator, class T, class Compare, class Distance>
+ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last,
+                              const T& value, Compare comp, Distance*,
+                              forward_iterator_tag) {
+  Distance len = 0;
+  distance(first, last, len);
+  Distance half;
+  ForwardIterator middle;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first;
+    advance(middle, half);
+    if (comp(*middle, value)) {
+      first = middle;
+      ++first;
+      len = len - half - 1;
+    }
+    else
+      len = half;
+  }
+  return first;
+}
+
+template <class RandomAccessIterator, class T, class Compare, class Distance>
+RandomAccessIterator __lower_bound(RandomAccessIterator first,
+                                   RandomAccessIterator last,
+                                   const T& value, Compare comp, Distance*,
+                                   random_access_iterator_tag) {
+  Distance len = last - first;
+  Distance half;
+  RandomAccessIterator middle;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first + half;
+    if (comp(*middle, value)) {
+      first = middle + 1;
+      len = len - half - 1;
+    }
+    else
+      len = half;
+  }
+  return first;
+}
+
+template <class ForwardIterator, class T, class Compare>
+inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
+                                   const T& value, Compare comp) {
+  return __lower_bound(first, last, value, comp, distance_type(first),
+                       iterator_category(first));
+}
+
+template <class ForwardIterator, class T, class Distance>
+ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last,
+                              const T& value, Distance*,
+                              forward_iterator_tag) {
+  Distance len = 0;
+  distance(first, last, len);
+  Distance half;
+  ForwardIterator middle;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first;
+    advance(middle, half);
+    if (value < *middle)
+      len = half;
+    else {
+      first = middle;
+      ++first;
+      len = len - half - 1;
+    }
+  }
+  return first;
+}
+
+template <class RandomAccessIterator, class T, class Distance>
+RandomAccessIterator __upper_bound(RandomAccessIterator first,
+                                   RandomAccessIterator last, const T& value,
+                                   Distance*, random_access_iterator_tag) {
+  Distance len = last - first;
+  Distance half;
+  RandomAccessIterator middle;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first + half;
+    if (value < *middle)
+      len = half;
+    else {
+      first = middle + 1;
+      len = len - half - 1;
+    }
+  }
+  return first;
+}
+
+template <class ForwardIterator, class T>
+inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last,
+                                   const T& value) {
+  return __upper_bound(first, last, value, distance_type(first),
+                       iterator_category(first));
+}
+
+template <class ForwardIterator, class T, class Compare, class Distance>
+ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last,
+                              const T& value, Compare comp, Distance*,
+                              forward_iterator_tag) {
+  Distance len = 0;
+  distance(first, last, len);
+  Distance half;
+  ForwardIterator middle;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first;
+    advance(middle, half);
+    if (comp(value, *middle))
+      len = half;
+    else {
+      first = middle;
+      ++first;
+      len = len - half - 1;
+    }
+  }
+  return first;
+}
+
+template <class RandomAccessIterator, class T, class Compare, class Distance>
+RandomAccessIterator __upper_bound(RandomAccessIterator first,
+                                   RandomAccessIterator last,
+                                   const T& value, Compare comp, Distance*,
+                                   random_access_iterator_tag) {
+  Distance len = last - first;
+  Distance half;
+  RandomAccessIterator middle;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first + half;
+    if (comp(value, *middle))
+      len = half;
+    else {
+      first = middle + 1;
+      len = len - half - 1;
+    }
+  }
+  return first;
+}
+
+template <class ForwardIterator, class T, class Compare>
+inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last,
+                                   const T& value, Compare comp) {
+  return __upper_bound(first, last, value, comp, distance_type(first),
+                       iterator_category(first));
+}
+
+template <class ForwardIterator, class T, class Distance>
+pair<ForwardIterator, ForwardIterator>
+__equal_range(ForwardIterator first, ForwardIterator last, const T& value,
+              Distance*, forward_iterator_tag) {
+  Distance len = 0;
+  distance(first, last, len);
+  Distance half;
+  ForwardIterator middle, left, right;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first;
+    advance(middle, half);
+    if (*middle < value) {
+      first = middle;
+      ++first;
+      len = len - half - 1;
+    }
+    else if (value < *middle)
+      len = half;
+    else {
+      left = lower_bound(first, middle, value);
+      advance(first, len);
+      right = upper_bound(++middle, first, value);
+      return pair<ForwardIterator, ForwardIterator>(left, right);
+    }
+  }
+  return pair<ForwardIterator, ForwardIterator>(first, first);
+}
+
+template <class RandomAccessIterator, class T, class Distance>
+pair<RandomAccessIterator, RandomAccessIterator>
+__equal_range(RandomAccessIterator first, RandomAccessIterator last,
+              const T& value, Distance*, random_access_iterator_tag) {
+  Distance len = last - first;
+  Distance half;
+  RandomAccessIterator middle, left, right;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first + half;
+    if (*middle < value) {
+      first = middle + 1;
+      len = len - half - 1;
+    }
+    else if (value < *middle)
+      len = half;
+    else {
+      left = lower_bound(first, middle, value);
+      right = upper_bound(++middle, first + len, value);
+      return pair<RandomAccessIterator, RandomAccessIterator>(left,
+                                                              right);
+    }
+  }
+  return pair<RandomAccessIterator, RandomAccessIterator>(first, first);
+}
+
+template <class ForwardIterator, class T>
+inline pair<ForwardIterator, ForwardIterator>
+equal_range(ForwardIterator first, ForwardIterator last, const T& value) {
+  return __equal_range(first, last, value, distance_type(first),
+                       iterator_category(first));
+}
+
+template <class ForwardIterator, class T, class Compare, class Distance>
+pair<ForwardIterator, ForwardIterator>
+__equal_range(ForwardIterator first, ForwardIterator last, const T& value,
+              Compare comp, Distance*, forward_iterator_tag) {
+  Distance len = 0;
+  distance(first, last, len);
+  Distance half;
+  ForwardIterator middle, left, right;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first;
+    advance(middle, half);
+    if (comp(*middle, value)) {
+      first = middle;
+      ++first;
+      len = len - half - 1;
+    }
+    else if (comp(value, *middle))
+      len = half;
+    else {
+      left = lower_bound(first, middle, value, comp);
+      advance(first, len);
+      right = upper_bound(++middle, first, value, comp);
+      return pair<ForwardIterator, ForwardIterator>(left, right);
+    }
+  }
+  return pair<ForwardIterator, ForwardIterator>(first, first);
+}           
+
+template <class RandomAccessIterator, class T, class Compare, class Distance>
+pair<RandomAccessIterator, RandomAccessIterator>
+__equal_range(RandomAccessIterator first, RandomAccessIterator last,
+              const T& value, Compare comp, Distance*,
+              random_access_iterator_tag) {
+  Distance len = last - first;
+  Distance half;
+  RandomAccessIterator middle, left, right;
+
+  while (len > 0) {
+    half = len >> 1;
+    middle = first + half;
+    if (comp(*middle, value)) {
+      first = middle + 1;
+      len = len - half - 1;
+    }
+    else if (comp(value, *middle))
+      len = half;
+    else {
+      left = lower_bound(first, middle, value, comp);
+      right = upper_bound(++middle, first + len, value, comp);
+      return pair<RandomAccessIterator, RandomAccessIterator>(left,
+                                                              right);
+    }
+  }
+  return pair<RandomAccessIterator, RandomAccessIterator>(first, first);
+}           
+
+template <class ForwardIterator, class T, class Compare>
+inline pair<ForwardIterator, ForwardIterator>
+equal_range(ForwardIterator first, ForwardIterator last, const T& value,
+            Compare comp) {
+  return __equal_range(first, last, value, comp, distance_type(first),
+                       iterator_category(first));
+}    
+
+template <class ForwardIterator, class T>
+bool binary_search(ForwardIterator first, ForwardIterator last,
+                   const T& value) {
+  ForwardIterator i = lower_bound(first, last, value);
+  return i != last && !(value < *i);
+}
+
+template <class ForwardIterator, class T, class Compare>
+bool binary_search(ForwardIterator first, ForwardIterator last, const T& value,
+                   Compare comp) {
+  ForwardIterator i = lower_bound(first, last, value, comp);
+  return i != last && !comp(value, *i);
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator>
+OutputIterator merge(InputIterator1 first1, InputIterator1 last1,
+                     InputIterator2 first2, InputIterator2 last2,
+                     OutputIterator result) {
+  while (first1 != last1 && first2 != last2) {
+    if (*first2 < *first1) {
+      *result = *first2;
+      ++first2;
+    }
+    else {
+      *result = *first1;
+      ++first1;
+    }
+    ++result;
+  }
+  return copy(first2, last2, copy(first1, last1, result));
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator,
+          class Compare>
+OutputIterator merge(InputIterator1 first1, InputIterator1 last1,
+                     InputIterator2 first2, InputIterator2 last2,
+                     OutputIterator result, Compare comp) {
+  while (first1 != last1 && first2 != last2) {
+    if (comp(*first2, *first1)) {
+      *result = *first2;
+      ++first2;
+    }
+    else {
+      *result = *first1;
+      ++first1;
+    }
+    ++result;
+  }
+  return copy(first2, last2, copy(first1, last1, result));
+}
+
+template <class BidirectionalIterator, class Distance>
+void __merge_without_buffer(BidirectionalIterator first,
+                            BidirectionalIterator middle,
+                            BidirectionalIterator last,
+                            Distance len1, Distance len2) {
+  if (len1 == 0 || len2 == 0) return;
+  if (len1 + len2 == 2) {
+    if (*middle < *first) iter_swap(first, middle);
+    return;
+  }
+  BidirectionalIterator first_cut = first;
+  BidirectionalIterator second_cut = middle;
+  Distance len11 = 0;
+  Distance len22 = 0;
+  if (len1 > len2) {
+    len11 = len1 / 2;
+    advance(first_cut, len11);
+    second_cut = lower_bound(middle, last, *first_cut);
+    distance(middle, second_cut, len22);
+  }
+  else {
+    len22 = len2 / 2;
+    advance(second_cut, len22);
+    first_cut = upper_bound(first, middle, *second_cut);
+    distance(first, first_cut, len11);
+  }
+  rotate(first_cut, middle, second_cut);
+  BidirectionalIterator new_middle = first_cut;
+  advance(new_middle, len22);
+  __merge_without_buffer(first, first_cut, new_middle, len11, len22);
+  __merge_without_buffer(new_middle, second_cut, last, len1 - len11,
+                         len2 - len22);
+}
+
+template <class BidirectionalIterator, class Distance, class Compare>
+void __merge_without_buffer(BidirectionalIterator first,
+                            BidirectionalIterator middle,
+                            BidirectionalIterator last,
+                            Distance len1, Distance len2, Compare comp) {
+  if (len1 == 0 || len2 == 0) return;
+  if (len1 + len2 == 2) {
+    if (comp(*middle, *first)) iter_swap(first, middle);
+    return;
+  }
+  BidirectionalIterator first_cut = first;
+  BidirectionalIterator second_cut = middle;
+  Distance len11 = 0;
+  Distance len22 = 0;
+  if (len1 > len2) {
+    len11 = len1 / 2;
+    advance(first_cut, len11);
+    second_cut = lower_bound(middle, last, *first_cut, comp);
+    distance(middle, second_cut, len22);
+  }
+  else {
+    len22 = len2 / 2;
+    advance(second_cut, len22);
+    first_cut = upper_bound(first, middle, *second_cut, comp);
+    distance(first, first_cut, len11);
+  }
+  rotate(first_cut, middle, second_cut);
+  BidirectionalIterator new_middle = first_cut;
+  advance(new_middle, len22);
+  __merge_without_buffer(first, first_cut, new_middle, len11, len22, comp);
+  __merge_without_buffer(new_middle, second_cut, last, len1 - len11,
+                         len2 - len22, comp);
+}
+
+template <class BidirectionalIterator1, class BidirectionalIterator2,
+          class Distance>
+BidirectionalIterator1 __rotate_adaptive(BidirectionalIterator1 first,
+                                         BidirectionalIterator1 middle,
+                                         BidirectionalIterator1 last,
+                                         Distance len1, Distance len2,
+                                         BidirectionalIterator2 buffer,
+                                         Distance buffer_size) {
+  BidirectionalIterator2 buffer_end;
+  if (len1 > len2 && len2 <= buffer_size) {
+    buffer_end = copy(middle, last, buffer);
+    copy_backward(first, middle, last);
+    return copy(buffer, buffer_end, first);
+  } else if (len1 <= buffer_size) {
+    buffer_end = copy(first, middle, buffer);
+    copy(middle, last, first);
+    return copy_backward(buffer, buffer_end, last);
+  } else  {
+    rotate(first, middle, last);
+    advance(first, len2);
+    return first;
+  }
+}
+
+template <class BidirectionalIterator1, class BidirectionalIterator2,
+          class BidirectionalIterator3>
+BidirectionalIterator3 __merge_backward(BidirectionalIterator1 first1,
+                                        BidirectionalIterator1 last1,
+                                        BidirectionalIterator2 first2,
+                                        BidirectionalIterator2 last2,
+                                        BidirectionalIterator3 result) {
+  if (first1 == last1) return copy_backward(first2, last2, result);
+  if (first2 == last2) return copy_backward(first1, last1, result);
+  --last1;
+  --last2;
+  while (true) {
+    if (*last2 < *last1) {
+      *--result = *last1;
+      if (first1 == last1) return copy_backward(first2, ++last2, result);
+      --last1;
+    }
+    else {
+      *--result = *last2;
+      if (first2 == last2) return copy_backward(first1, ++last1, result);
+      --last2;
+    }
+  }
+}
+
+template <class BidirectionalIterator1, class BidirectionalIterator2,
+          class BidirectionalIterator3, class Compare>
+BidirectionalIterator3 __merge_backward(BidirectionalIterator1 first1,
+                                        BidirectionalIterator1 last1,
+                                        BidirectionalIterator2 first2,
+                                        BidirectionalIterator2 last2,
+                                        BidirectionalIterator3 result,
+                                        Compare comp) {
+  if (first1 == last1) return copy_backward(first2, last2, result);
+  if (first2 == last2) return copy_backward(first1, last1, result);
+  --last1;
+  --last2;
+  while (true) {
+    if (comp(*last2, *last1)) {
+      *--result = *last1;
+      if (first1 == last1) return copy_backward(first2, ++last2, result);
+      --last1;
+    }
+    else {
+      *--result = *last2;
+      if (first2 == last2) return copy_backward(first1, ++last1, result);
+      --last2;
+    }
+  }
+}
+
+template <class BidirectionalIterator, class Distance, class Pointer>
+void __merge_adaptive(BidirectionalIterator first, 
+                      BidirectionalIterator middle, 
+                      BidirectionalIterator last, Distance len1, Distance len2,
+                      Pointer buffer, Distance buffer_size) {
+  if (len1 <= len2 && len1 <= buffer_size) {
+    Pointer end_buffer = copy(first, middle, buffer);
+    merge(buffer, end_buffer, middle, last, first);
+  }
+  else if (len2 <= buffer_size) {
+    Pointer end_buffer = copy(middle, last, buffer);
+    __merge_backward(first, middle, buffer, end_buffer, last);
+  }
+  else {
+    BidirectionalIterator first_cut = first;
+    BidirectionalIterator second_cut = middle;
+    Distance len11 = 0;
+    Distance len22 = 0;
+    if (len1 > len2) {
+      len11 = len1 / 2;
+      advance(first_cut, len11);
+      second_cut = lower_bound(middle, last, *first_cut);
+      distance(middle, second_cut, len22);   
+    }
+    else {
+      len22 = len2 / 2;
+      advance(second_cut, len22);
+      first_cut = upper_bound(first, middle, *second_cut);
+      distance(first, first_cut, len11);
+    }
+    BidirectionalIterator new_middle =
+      __rotate_adaptive(first_cut, middle, second_cut, len1 - len11,
+                        len22, buffer, buffer_size);
+    __merge_adaptive(first, first_cut, new_middle, len11, len22, buffer,
+                     buffer_size);
+    __merge_adaptive(new_middle, second_cut, last, len1 - len11,
+                     len2 - len22, buffer, buffer_size);
+  }
+}
+
+template <class BidirectionalIterator, class Distance, class Pointer,
+          class Compare>
+void __merge_adaptive(BidirectionalIterator first, 
+                      BidirectionalIterator middle, 
+                      BidirectionalIterator last, Distance len1, Distance len2,
+                      Pointer buffer, Distance buffer_size, Compare comp) {
+  if (len1 <= len2 && len1 <= buffer_size) {
+    Pointer end_buffer = copy(first, middle, buffer);
+    merge(buffer, end_buffer, middle, last, first, comp);
+  }
+  else if (len2 <= buffer_size) {
+    Pointer end_buffer = copy(middle, last, buffer);
+    __merge_backward(first, middle, buffer, end_buffer, last, comp);
+  }
+  else {
+    BidirectionalIterator first_cut = first;
+    BidirectionalIterator second_cut = middle;
+    Distance len11 = 0;
+    Distance len22 = 0;
+    if (len1 > len2) {
+      len11 = len1 / 2;
+      advance(first_cut, len11);
+      second_cut = lower_bound(middle, last, *first_cut, comp);
+      distance(middle, second_cut, len22);   
+    }
+    else {
+      len22 = len2 / 2;
+      advance(second_cut, len22);
+      first_cut = upper_bound(first, middle, *second_cut, comp);
+      distance(first, first_cut, len11);
+    }
+    BidirectionalIterator new_middle =
+      __rotate_adaptive(first_cut, middle, second_cut, len1 - len11,
+                        len22, buffer, buffer_size);
+    __merge_adaptive(first, first_cut, new_middle, len11, len22, buffer,
+                     buffer_size, comp);
+    __merge_adaptive(new_middle, second_cut, last, len1 - len11,
+                     len2 - len22, buffer, buffer_size, comp);
+  }
+}
+
+template <class BidirectionalIterator, class T, class Distance>
+inline void __inplace_merge_aux(BidirectionalIterator first,
+                                BidirectionalIterator middle,
+                                BidirectionalIterator last, T*, Distance*) {
+  Distance len1 = 0;
+  distance(first, middle, len1);
+  Distance len2 = 0;
+  distance(middle, last, len2);
+
+  temporary_buffer<BidirectionalIterator, T> buf(first, last);
+  if (buf.begin() == 0)
+    __merge_without_buffer(first, middle, last, len1, len2);
+  else
+    __merge_adaptive(first, middle, last, len1, len2,
+                     buf.begin(), Distance(buf.size()));
+}
+
+template <class BidirectionalIterator, class T, class Distance, class Compare>
+inline void __inplace_merge_aux(BidirectionalIterator first,
+                                BidirectionalIterator middle,
+                                BidirectionalIterator last, T*, Distance*,
+                                Compare comp) {
+  Distance len1 = 0;
+  distance(first, middle, len1);
+  Distance len2 = 0;
+  distance(middle, last, len2);
+
+  temporary_buffer<BidirectionalIterator, T> buf(first, last);
+  if (buf.begin() == 0)
+    __merge_without_buffer(first, middle, last, len1, len2, comp);
+  else
+    __merge_adaptive(first, middle, last, len1, len2,
+                     buf.begin(), Distance(buf.size()),
+                     comp);
+}
+
+template <class BidirectionalIterator>
+inline void inplace_merge(BidirectionalIterator first,
+                          BidirectionalIterator middle,
+                          BidirectionalIterator last) {
+  if (first == middle || middle == last) return;
+  __inplace_merge_aux(first, middle, last, value_type(first),
+                      distance_type(first));
+}
+
+template <class BidirectionalIterator, class Compare>
+inline void inplace_merge(BidirectionalIterator first,
+                          BidirectionalIterator middle,
+                          BidirectionalIterator last, Compare comp) {
+  if (first == middle || middle == last) return;
+  __inplace_merge_aux(first, middle, last, value_type(first),
+                      distance_type(first), comp);
+}
+
+template <class InputIterator1, class InputIterator2>
+bool includes(InputIterator1 first1, InputIterator1 last1,
+              InputIterator2 first2, InputIterator2 last2) {
+  while (first1 != last1 && first2 != last2)
+    if (*first2 < *first1)
+      return false;
+    else if(*first1 < *first2) 
+      ++first1;
+    else
+      ++first1, ++first2;
+
+  return first2 == last2;
+}
+
+template <class InputIterator1, class InputIterator2, class Compare>
+bool includes(InputIterator1 first1, InputIterator1 last1,
+              InputIterator2 first2, InputIterator2 last2, Compare comp) {
+  while (first1 != last1 && first2 != last2)
+    if (comp(*first2, *first1))
+      return false;
+    else if(comp(*first1, *first2)) 
+      ++first1;
+    else
+      ++first1, ++first2;
+
+  return first2 == last2;
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator>
+OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
+                         InputIterator2 first2, InputIterator2 last2,
+                         OutputIterator result) {
+  while (first1 != last1 && first2 != last2) {
+    if (*first1 < *first2) {
+      *result = *first1;
+      ++first1;
+    }
+    else if (*first2 < *first1) {
+      *result = *first2;
+      ++first2;
+    }
+    else {
+      *result = *first1;
+      ++first1;
+      ++first2;
+    }
+    ++result;
+  }
+  return copy(first2, last2, copy(first1, last1, result));
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator,
+          class Compare>
+OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
+                         InputIterator2 first2, InputIterator2 last2,
+                         OutputIterator result, Compare comp) {
+  while (first1 != last1 && first2 != last2) {
+    if (comp(*first1, *first2)) {
+      *result = *first1;
+      ++first1;
+    }
+    else if (comp(*first2, *first1)) {
+      *result = *first2;
+      ++first2;
+    }
+    else {
+      *result = *first1;
+      ++first1;
+      ++first2;
+    }
+    ++result;
+  }
+  return copy(first2, last2, copy(first1, last1, result));
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator>
+OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
+                                InputIterator2 first2, InputIterator2 last2,
+                                OutputIterator result) {
+  while (first1 != last1 && first2 != last2) 
+    if (*first1 < *first2) 
+      ++first1;
+    else if (*first2 < *first1) 
+      ++first2;
+    else {
+      *result = *first1;
+      ++first1;
+      ++first2;
+      ++result;
+    }
+  return result;
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator,
+          class Compare>
+OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
+                                InputIterator2 first2, InputIterator2 last2,
+                                OutputIterator result, Compare comp) {
+  while (first1 != last1 && first2 != last2)
+    if (comp(*first1, *first2))
+      ++first1;
+    else if (comp(*first2, *first1))
+      ++first2;
+    else {
+      *result = *first1;
+      ++first1;
+      ++first2;
+      ++result;
+    }
+  return result;
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator>
+OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
+                              InputIterator2 first2, InputIterator2 last2,
+                              OutputIterator result) {
+  while (first1 != last1 && first2 != last2)
+    if (*first1 < *first2) {
+      *result = *first1;
+      ++first1;
+      ++result;
+    }
+    else if (*first2 < *first1)
+      ++first2;
+    else {
+      ++first1;
+      ++first2;
+    }
+  return copy(first1, last1, result);
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator, 
+          class Compare>
+OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
+                              InputIterator2 first2, InputIterator2 last2, 
+                              OutputIterator result, Compare comp) {
+  while (first1 != last1 && first2 != last2)
+    if (comp(*first1, *first2)) {
+      *result = *first1;
+      ++first1;
+      ++result;
+    }
+    else if (comp(*first2, *first1))
+      ++first2;
+    else {
+      ++first1;
+      ++first2;
+    }
+  return copy(first1, last1, result);
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator>
+OutputIterator set_symmetric_difference(InputIterator1 first1,
+                                        InputIterator1 last1,
+                                        InputIterator2 first2,
+                                        InputIterator2 last2,
+                                        OutputIterator result) {
+  while (first1 != last1 && first2 != last2)
+    if (*first1 < *first2) {
+      *result = *first1;
+      ++first1;
+      ++result;
+    }
+    else if (*first2 < *first1) {
+      *result = *first2;
+      ++first2;
+      ++result;
+    }
+    else {
+      ++first1;
+      ++first2;
+    }
+  return copy(first2, last2, copy(first1, last1, result));
+}
+
+template <class InputIterator1, class InputIterator2, class OutputIterator,
+          class Compare>
+OutputIterator set_symmetric_difference(InputIterator1 first1,
+                                        InputIterator1 last1,
+                                        InputIterator2 first2,
+                                        InputIterator2 last2,
+                                        OutputIterator result, Compare comp) {
+  while (first1 != last1 && first2 != last2)
+    if (comp(*first1, *first2)) {
+      *result = *first1;
+      ++first1;
+      ++result;
+    }
+    else if (comp(*first2, *first1)) {
+      *result = *first2;
+      ++first2;
+      ++result;
+    }
+    else {
+      ++first1;
+      ++first2;
+    }
+  return copy(first2, last2, copy(first1, last1, result));
+}
+
+template <class ForwardIterator>
+ForwardIterator max_element(ForwardIterator first, ForwardIterator last) {
+  if (first == last) return first;
+  ForwardIterator result = first;
+  while (++first != last) 
+    if (*result < *first) result = first;
+  return result;
+}
+
+template <class ForwardIterator, class Compare>
+ForwardIterator max_element(ForwardIterator first, ForwardIterator last,
+                            Compare comp) {
+  if (first == last) return first;
+  ForwardIterator result = first;
+  while (++first != last) 
+    if (comp(*result, *first)) result = first;
+  return result;
+}
+
+template <class ForwardIterator>
+ForwardIterator min_element(ForwardIterator first, ForwardIterator last) {
+  if (first == last) return first;
+  ForwardIterator result = first;
+  while (++first != last) 
+    if (*first < *result) result = first;
+  return result;
+}
+
+template <class ForwardIterator, class Compare>
+ForwardIterator min_element(ForwardIterator first, ForwardIterator last,
+                            Compare comp) {
+  if (first == last) return first;
+  ForwardIterator result = first;
+  while (++first != last) 
+    if (comp(*first, *result)) result = first;
+  return result;
+}
+
+template <class BidirectionalIterator>
+bool next_permutation(BidirectionalIterator first,
+                      BidirectionalIterator last) {
+  if (first == last) return false;
+  BidirectionalIterator i = first;
+  ++i;
+  if (i == last) return false;
+  i = last;
+  --i;
+
+  for(;;) {
+    BidirectionalIterator ii = i;
+    --i;
+    if (*i < *ii) {
+      BidirectionalIterator j = last;
+      while (!(*i < *--j));
+      iter_swap(i, j);
+      reverse(ii, last);
+      return true;
+    }
+    if (i == first) {
+      reverse(first, last);
+      return false;
+    }
+  }
+}
+
+template <class BidirectionalIterator, class Compare>
+bool next_permutation(BidirectionalIterator first, BidirectionalIterator last,
+                      Compare comp) {
+  if (first == last) return false;
+  BidirectionalIterator i = first;
+  ++i;
+  if (i == last) return false;
+  i = last;
+  --i;
+
+  for(;;) {
+    BidirectionalIterator ii = i;
+    --i;
+    if (comp(*i, *ii)) {
+      BidirectionalIterator j = last;
+      while (!comp(*i, *--j));
+      iter_swap(i, j);
+      reverse(ii, last);
+      return true;
+    }
+    if (i == first) {
+      reverse(first, last);
+      return false;
+    }
+  }
+}
+
+template <class BidirectionalIterator>
+bool prev_permutation(BidirectionalIterator first,
+                      BidirectionalIterator last) {
+  if (first == last) return false;
+  BidirectionalIterator i = first;
+  ++i;
+  if (i == last) return false;
+  i = last;
+  --i;
+
+  for(;;) {
+    BidirectionalIterator ii = i;
+    --i;
+    if (*ii < *i) {
+      BidirectionalIterator j = last;
+      while (!(*--j < *i));
+      iter_swap(i, j);
+      reverse(ii, last);
+      return true;
+    }
+    if (i == first) {
+      reverse(first, last);
+      return false;
+    }
+  }
+}
+
+template <class BidirectionalIterator, class Compare>
+bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last,
+                      Compare comp) {
+  if (first == last) return false;
+  BidirectionalIterator i = first;
+  ++i;
+  if (i == last) return false;
+  i = last;
+  --i;
+
+  for(;;) {
+    BidirectionalIterator ii = i;
+    --i;
+    if (comp(*ii, *i)) {
+      BidirectionalIterator j = last;
+      while (!comp(*--j, *i));
+      iter_swap(i, j);
+      reverse(ii, last);
+      return true;
+    }
+    if (i == first) {
+      reverse(first, last);
+      return false;
+    }
+  }
+}
+
+template <class InputIterator, class ForwardIterator>
+InputIterator find_first_of(InputIterator first1, InputIterator last1,
+                            ForwardIterator first2, ForwardIterator last2)
+{
+  for ( ; first1 != last1; ++first1) 
+    for (ForwardIterator iter = first2; iter != last2; ++iter)
+      if (*first1 == *iter)
+        return first1;
+  return last1;
+}
+
+template <class InputIterator, class ForwardIterator, class BinaryPredicate>
+InputIterator find_first_of(InputIterator first1, InputIterator last1,
+                            ForwardIterator first2, ForwardIterator last2,
+                            BinaryPredicate comp)
+{
+  for ( ; first1 != last1; ++first1) 
+    for (ForwardIterator iter = first2; iter != last2; ++iter)
+      if (comp(*first1, *iter))
+        return first1;
+  return last1;
+}
+
+
+// Search [first2, last2) as a subsequence in [first1, last1).
+
+// find_end for forward iterators. 
+template <class ForwardIterator1, class ForwardIterator2>
+ForwardIterator1 __find_end(ForwardIterator1 first1, ForwardIterator1 last1,
+                            ForwardIterator2 first2, ForwardIterator2 last2,
+                            forward_iterator_tag, forward_iterator_tag)
+{
+  if (first2 == last2)
+    return last1;
+  else {
+    ForwardIterator1 result = last1;
+    while (1) {
+      ForwardIterator1 new_result = search(first1, last1, first2, last2);
+      if (new_result == last1)
+        return result;
+      else {
+        result = new_result;
+        first1 = new_result;
+        ++first1;
+      }
+    }
+  }
+}
+
+template <class ForwardIterator1, class ForwardIterator2,
+          class BinaryPredicate>
+ForwardIterator1 __find_end(ForwardIterator1 first1, ForwardIterator1 last1,
+                            ForwardIterator2 first2, ForwardIterator2 last2,
+                            forward_iterator_tag, forward_iterator_tag,
+                            BinaryPredicate comp)
+{
+  if (first2 == last2)
+    return last1;
+  else {
+    ForwardIterator1 result = last1;
+    while (1) {
+      ForwardIterator1 new_result = search(first1, last1, first2, last2, comp);
+      if (new_result == last1)
+        return result;
+      else {
+        result = new_result;
+        first1 = new_result;
+        ++first1;
+      }
+    }
+  }
+}
+
+// find_end for bidirectional iterators.  Requires partial specialization.
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class BidirectionalIterator1, class BidirectionalIterator2>
+BidirectionalIterator1
+__find_end(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
+           BidirectionalIterator2 first2, BidirectionalIterator2 last2,
+           bidirectional_iterator_tag, bidirectional_iterator_tag)
+{
+  typedef reverse_iterator<BidirectionalIterator1> reviter1;
+  typedef reverse_iterator<BidirectionalIterator2> reviter2;
+
+  reviter1 rlast1(first1);
+  reviter2 rlast2(first2);
+  reviter1 rresult = search(reviter1(last1), rlast1, reviter2(last2), rlast2);
+
+  if (rresult == rlast1)
+    return last1;
+  else {
+    BidirectionalIterator1 result = rresult.base();
+    advance(result, -distance(first2, last2));
+    return result;
+  }
+}
+
+template <class BidirectionalIterator1, class BidirectionalIterator2,
+          class BinaryPredicate>
+BidirectionalIterator1
+__find_end(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
+           BidirectionalIterator2 first2, BidirectionalIterator2 last2,
+           bidirectional_iterator_tag, bidirectional_iterator_tag, 
+           BinaryPredicate comp)
+{
+  typedef reverse_iterator<BidirectionalIterator1> reviter1;
+  typedef reverse_iterator<BidirectionalIterator2> reviter2;
+
+  reviter1 rlast1(first1);
+  reviter2 rlast2(first2);
+  reviter1 rresult = search(reviter1(last1), rlast1, reviter2(last2), rlast2,
+                            comp);
+
+  if (rresult == rlast1)
+    return last1;
+  else {
+    BidirectionalIterator1 result = rresult.base();
+    advance(result, -distance(first2, last2));
+    return result;
+  }
+}
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+// Dispatching functions.
+
+template <class ForwardIterator1, class ForwardIterator2>
+inline ForwardIterator1 
+find_end(ForwardIterator1 first1, ForwardIterator1 last1, 
+         ForwardIterator2 first2, ForwardIterator2 last2)
+{
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+  typedef typename iterator_traits<ForwardIterator1>::iterator_category
+          category1;
+  typedef typename iterator_traits<ForwardIterator2>::iterator_category
+          category2;
+  return __find_end(first1, last1, first2, last2, category1(), category2());
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+  return __find_end(first1, last1, first2, last2,
+                    forward_iterator_tag(), forward_iterator_tag());
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+}
+
+template <class ForwardIterator1, class ForwardIterator2, 
+          class BinaryPredicate>
+inline ForwardIterator1 
+find_end(ForwardIterator1 first1, ForwardIterator1 last1, 
+         ForwardIterator2 first2, ForwardIterator2 last2,
+         BinaryPredicate comp)
+{
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+  typedef typename iterator_traits<ForwardIterator1>::iterator_category
+          category1;
+  typedef typename iterator_traits<ForwardIterator2>::iterator_category
+          category2;
+  return __find_end(first1, last1, first2, last2, category1(), category2(),
+                    comp);
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+  return __find_end(first1, last1, first2, last2,
+                    forward_iterator_tag(), forward_iterator_tag(),
+                    comp);
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+}
+
+template <class RandomAccessIterator, class Distance>
+bool __is_heap(RandomAccessIterator first, RandomAccessIterator last,
+               Distance*)
+{
+  const Distance n = last - first;
+
+  Distance parent = 0;
+  for (Distance child = 1; child < n; ++child) {
+    if (first[parent] < first[child]) 
+      return false;
+    if ((child & 1) == 0)
+      ++parent;
+  }
+  return true;
+}
+
+template <class RandomAccessIterator>
+inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last)
+{
+  return __is_heap(first, last, distance_type(first));
+}
+
+
+template <class RandomAccessIterator, class Distance, class StrictWeakOrdering>
+bool __is_heap(RandomAccessIterator first, RandomAccessIterator last,
+               StrictWeakOrdering comp,
+               Distance*)
+{
+  const Distance n = last - first;
+
+  Distance parent = 0;
+  for (Distance child = 1; child < n; ++child) {
+    if (comp(first[parent], first[child]))
+      return false;
+    if ((child & 1) == 0)
+      ++parent;
+  }
+  return true;
+}
+
+template <class RandomAccessIterator, class StrictWeakOrdering>
+inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last,
+                    StrictWeakOrdering comp)
+{
+  return __is_heap(first, last, comp, distance_type(first));
+}
+
+
+template <class ForwardIterator>
+bool is_sorted(ForwardIterator first, ForwardIterator last)
+{
+  if (first == last)
+    return true;
+
+  ForwardIterator next = first;
+  for (++next; next != last; first = next, ++next) {
+    if (*next < *first)
+      return false;
+  }
+
+  return true;
+}
+
+template <class ForwardIterator, class StrictWeakOrdering>
+bool is_sorted(ForwardIterator first, ForwardIterator last,
+               StrictWeakOrdering comp)
+{
+  if (first == last)
+    return true;
+
+  ForwardIterator next = first;
+  for (++next; next != last; first = next, ++next) {
+    if (comp(*next, *first))
+      return false;
+  }
+
+  return true;
+}
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1209
+#endif
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_ALGO_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_allo.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_allo.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_allo.h	(revision 18)
@@ -0,0 +1,698 @@
+/*
+ * Copyright (c) 1996-1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_ALLOC_H
+#define __SGI_STL_INTERNAL_ALLOC_H
+
+#ifdef __SUNPRO_CC
+#  define __PRIVATE public
+   // Extra access restrictions prevent us from really making some things
+   // private.
+#else
+#  define __PRIVATE private
+#endif
+
+#ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
+#  define __USE_MALLOC
+#endif
+
+
+// This implements some standard node allocators.  These are
+// NOT the same as the allocators in the C++ draft standard or in
+// in the original STL.  They do not encapsulate different pointer
+// types; indeed we assume that there is only one pointer type.
+// The allocation primitives are intended to allocate individual objects,
+// not larger arenas as with the original STL allocators.
+
+#if 0
+#   include <new>
+#   define __THROW_BAD_ALLOC throw bad_alloc
+#elif !defined(__THROW_BAD_ALLOC)
+#   include <iostream.h>
+#   define __THROW_BAD_ALLOC cerr << "out of memory" << endl; exit(1)
+#endif
+
+#ifndef __ALLOC
+#   define __ALLOC alloc
+#endif
+#ifdef __STL_WIN32THREADS
+#   include <windows.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#ifndef __RESTRICT
+#  define __RESTRICT
+#endif
+
+#if !defined(__STL_PTHREADS) && !defined(_NOTHREADS) \
+ && !defined(__STL_SGI_THREADS) && !defined(__STL_WIN32THREADS)
+#   define _NOTHREADS
+#endif
+
+# ifdef __STL_PTHREADS
+    // POSIX Threads
+    // This is dubious, since this is likely to be a high contention
+    // lock.   Performance may not be adequate.
+#   include <pthread.h>
+#   define __NODE_ALLOCATOR_LOCK \
+        if (threads) pthread_mutex_lock(&__node_allocator_lock)
+#   define __NODE_ALLOCATOR_UNLOCK \
+        if (threads) pthread_mutex_unlock(&__node_allocator_lock)
+#   define __NODE_ALLOCATOR_THREADS true
+#   define __VOLATILE volatile  // Needed at -O3 on SGI
+# endif
+# ifdef __STL_WIN32THREADS
+    // The lock needs to be initialized by constructing an allocator
+    // objects of the right type.  We do that here explicitly for alloc.
+#   define __NODE_ALLOCATOR_LOCK \
+        EnterCriticalSection(&__node_allocator_lock)
+#   define __NODE_ALLOCATOR_UNLOCK \
+        LeaveCriticalSection(&__node_allocator_lock)
+#   define __NODE_ALLOCATOR_THREADS true
+#   define __VOLATILE volatile  // may not be needed
+# endif /* WIN32THREADS */
+# ifdef __STL_SGI_THREADS
+    // This should work without threads, with sproc threads, or with
+    // pthreads.  It is suboptimal in all cases.
+    // It is unlikely to even compile on nonSGI machines.
+
+    extern "C" {
+      extern int __us_rsthread_malloc;
+    }
+	// The above is copied from malloc.h.  Including <malloc.h>
+	// would be cleaner but fails with certain levels of standard
+	// conformance.
+#   define __NODE_ALLOCATOR_LOCK if (threads && __us_rsthread_malloc) \
+                { __lock(&__node_allocator_lock); }
+#   define __NODE_ALLOCATOR_UNLOCK if (threads && __us_rsthread_malloc) \
+                { __unlock(&__node_allocator_lock); }
+#   define __NODE_ALLOCATOR_THREADS true
+#   define __VOLATILE volatile  // Needed at -O3 on SGI
+# endif
+# ifdef _NOTHREADS
+//  Thread-unsafe
+#   define __NODE_ALLOCATOR_LOCK
+#   define __NODE_ALLOCATOR_UNLOCK
+#   define __NODE_ALLOCATOR_THREADS false
+#   define __VOLATILE
+# endif
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+// Malloc-based allocator.  Typically slower than default alloc below.
+// Typically thread-safe and more storage efficient.
+#ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
+# ifdef __DECLARE_GLOBALS_HERE
+    void (* __malloc_alloc_oom_handler)() = 0;
+    // g++ 2.7.2 does not handle static template data members.
+# else
+    extern void (* __malloc_alloc_oom_handler)();
+# endif
+#endif
+
+template <int inst>
+class __malloc_alloc_template {
+
+private:
+
+static void *oom_malloc(size_t);
+
+static void *oom_realloc(void *, size_t);
+
+#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
+    static void (* __malloc_alloc_oom_handler)();
+#endif
+
+public:
+
+static void * allocate(size_t n)
+{
+    void *result = malloc(n);
+    if (0 == result) result = oom_malloc(n);
+    return result;
+}
+
+static void deallocate(void *p, size_t /* n */)
+{
+    free(p);
+}
+
+static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz)
+{
+    void * result = realloc(p, new_sz);
+    if (0 == result) result = oom_realloc(p, new_sz);
+    return result;
+}
+
+static void (* set_malloc_handler(void (*f)()))()
+{
+    void (* old)() = __malloc_alloc_oom_handler;
+    __malloc_alloc_oom_handler = f;
+    return(old);
+}
+
+};
+
+// malloc_alloc out-of-memory handling
+
+#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
+template <int inst>
+void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;
+#endif
+
+template <int inst>
+void * __malloc_alloc_template<inst>::oom_malloc(size_t n)
+{
+    void (* my_malloc_handler)();
+    void *result;
+
+    for (;;) {
+        my_malloc_handler = __malloc_alloc_oom_handler;
+        if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
+        (*my_malloc_handler)();
+        result = malloc(n);
+        if (result) return(result);
+    }
+}
+
+template <int inst>
+void * __malloc_alloc_template<inst>::oom_realloc(void *p, size_t n)
+{
+    void (* my_malloc_handler)();
+    void *result;
+
+    for (;;) {
+        my_malloc_handler = __malloc_alloc_oom_handler;
+        if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
+        (*my_malloc_handler)();
+        result = realloc(p, n);
+        if (result) return(result);
+    }
+}
+
+typedef __malloc_alloc_template<0> malloc_alloc;
+
+template<class T, class Alloc>
+class simple_alloc {
+
+public:
+    static T *allocate(size_t n)
+                { return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
+    static T *allocate(void)
+                { return (T*) Alloc::allocate(sizeof (T)); }
+    static void deallocate(T *p, size_t n)
+                { if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
+    static void deallocate(T *p)
+                { Alloc::deallocate(p, sizeof (T)); }
+};
+
+// Allocator adaptor to check size arguments for debugging.
+// Reports errors using assert.  Checking can be disabled with
+// NDEBUG, but it's far better to just use the underlying allocator
+// instead when no checking is desired.
+// There is some evidence that this can confuse Purify.
+template <class Alloc>
+class debug_alloc {
+
+private:
+
+enum {extra = 8};       // Size of space used to store size.  Note
+                        // that this must be large enough to preserve
+                        // alignment.
+
+public:
+
+static void * allocate(size_t n)
+{
+    char *result = (char *)Alloc::allocate(n + extra);
+    *(size_t *)result = n;
+    return result + extra;
+}
+
+static void deallocate(void *p, size_t n)
+{
+    char * real_p = (char *)p - extra;
+    assert(*(size_t *)real_p == n);
+    Alloc::deallocate(real_p, n + extra);
+}
+
+static void * reallocate(void *p, size_t old_sz, size_t new_sz)
+{
+    char * real_p = (char *)p - extra;
+    assert(*(size_t *)real_p == old_sz);
+    char * result = (char *)
+                  Alloc::reallocate(real_p, old_sz + extra, new_sz + extra);
+    *(size_t *)result = new_sz;
+    return result + extra;
+}
+
+
+};
+
+
+# ifdef __USE_MALLOC
+
+typedef malloc_alloc alloc;
+typedef malloc_alloc single_client_alloc;
+
+# else
+
+
+// Default node allocator.
+// With a reasonable compiler, this should be roughly as fast as the
+// original STL class-specific allocators, but with less fragmentation.
+// Default_alloc_template parameters are experimental and MAY
+// DISAPPEAR in the future.  Clients should just use alloc for now.
+//
+// Important implementation properties:
+// 1. If the client request an object of size > __MAX_BYTES, the resulting
+//    object will be obtained directly from malloc.
+// 2. In all other cases, we allocate an object of size exactly
+//    ROUND_UP(requested_size).  Thus the client has enough size
+//    information that we can return the object to the proper free list
+//    without permanently losing part of the object.
+//
+
+// The first template parameter specifies whether more than one thread
+// may use this allocator.  It is safe to allocate an object from
+// one instance of a default_alloc and deallocate it with another
+// one.  This effectively transfers its ownership to the second one.
+// This may have undesirable effects on reference locality.
+// The second parameter is unreferenced and serves only to allow the
+// creation of multiple default_alloc instances.
+// Node that containers built on different allocator instances have
+// different types, limiting the utility of this approach.
+#ifdef __SUNPRO_CC
+// breaks if we make these template class members:
+  enum {__ALIGN = 8};
+  enum {__MAX_BYTES = 128};
+  enum {__NFREELISTS = __MAX_BYTES/__ALIGN};
+#endif
+
+template <bool threads, int inst>
+class __default_alloc_template {
+
+private:
+  // Really we should use static const int x = N
+  // instead of enum { x = N }, but few compilers accept the former.
+# ifndef __SUNPRO_CC
+    enum {__ALIGN = 8};
+    enum {__MAX_BYTES = 128};
+    enum {__NFREELISTS = __MAX_BYTES/__ALIGN};
+# endif
+  static size_t ROUND_UP(size_t bytes) {
+        return (((bytes) + __ALIGN-1) & ~(__ALIGN - 1));
+  }
+__PRIVATE:
+  union obj {
+        union obj * free_list_link;
+        char client_data[1];    /* The client sees this.        */
+  };
+private:
+# ifdef __SUNPRO_CC
+    static obj * __VOLATILE free_list[]; 
+        // Specifying a size results in duplicate def for 4.1
+# else
+    static obj * __VOLATILE free_list[__NFREELISTS]; 
+# endif
+  static  size_t FREELIST_INDEX(size_t bytes) {
+        return (((bytes) + __ALIGN-1)/__ALIGN - 1);
+  }
+
+  // Returns an object of size n, and optionally adds to size n free list.
+  static void *refill(size_t n);
+  // Allocates a chunk for nobjs of size size.  nobjs may be reduced
+  // if it is inconvenient to allocate the requested number.
+  static char *chunk_alloc(size_t size, int &nobjs);
+
+  // Chunk allocation state.
+  static char *start_free;
+  static char *end_free;
+  static size_t heap_size;
+
+# ifdef __STL_SGI_THREADS
+    static volatile unsigned long __node_allocator_lock;
+    static void __lock(volatile unsigned long *); 
+    static inline void __unlock(volatile unsigned long *);
+# endif
+
+# ifdef __STL_PTHREADS
+    static pthread_mutex_t __node_allocator_lock;
+# endif
+
+# ifdef __STL_WIN32THREADS
+    static CRITICAL_SECTION __node_allocator_lock;
+    static bool __node_allocator_lock_initialized;
+
+  public:
+    __default_alloc_template() {
+	// This assumes the first constructor is called before threads
+	// are started.
+        if (!__node_allocator_lock_initialized) {
+            InitializeCriticalSection(&__node_allocator_lock);
+            __node_allocator_lock_initialized = true;
+        }
+    }
+  private:
+# endif
+
+    class lock {
+        public:
+            lock() { __NODE_ALLOCATOR_LOCK; }
+            ~lock() { __NODE_ALLOCATOR_UNLOCK; }
+    };
+    friend class lock;
+
+public:
+
+  /* n must be > 0      */
+  static void * allocate(size_t n)
+  {
+    obj * __VOLATILE * my_free_list;
+    obj * __RESTRICT result;
+
+    if (n > (size_t) __MAX_BYTES) {
+        return(malloc_alloc::allocate(n));
+    }
+    my_free_list = free_list + FREELIST_INDEX(n);
+    // Acquire the lock here with a constructor call.
+    // This ensures that it is released in exit or during stack
+    // unwinding.
+#       ifndef _NOTHREADS
+        /*REFERENCED*/
+        lock lock_instance;
+#       endif
+    result = *my_free_list;
+    if (result == 0) {
+        void *r = refill(ROUND_UP(n));
+        return r;
+    }
+    *my_free_list = result -> free_list_link;
+    return (result);
+  };
+
+  /* p may not be 0 */
+  static void deallocate(void *p, size_t n)
+  {
+    obj *q = (obj *)p;
+    obj * __VOLATILE * my_free_list;
+
+    if (n > (size_t) __MAX_BYTES) {
+        malloc_alloc::deallocate(p, n);
+        return;
+    }
+    my_free_list = free_list + FREELIST_INDEX(n);
+    // acquire lock
+#       ifndef _NOTHREADS
+        /*REFERENCED*/
+        lock lock_instance;
+#       endif /* _NOTHREADS */
+    q -> free_list_link = *my_free_list;
+    *my_free_list = q;
+    // lock is released here
+  }
+
+  static void * reallocate(void *p, size_t old_sz, size_t new_sz);
+
+} ;
+
+typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
+typedef __default_alloc_template<false, 0> single_client_alloc;
+
+
+
+/* We allocate memory in large chunks in order to avoid fragmenting     */
+/* the malloc heap too much.                                            */
+/* We assume that size is properly aligned.                             */
+/* We hold the allocation lock.                                         */
+template <bool threads, int inst>
+char*
+__default_alloc_template<threads, inst>::chunk_alloc(size_t size, int& nobjs)
+{
+    char * result;
+    size_t total_bytes = size * nobjs;
+    size_t bytes_left = end_free - start_free;
+
+    if (bytes_left >= total_bytes) {
+        result = start_free;
+        start_free += total_bytes;
+        return(result);
+    } else if (bytes_left >= size) {
+        nobjs = bytes_left/size;
+        total_bytes = size * nobjs;
+        result = start_free;
+        start_free += total_bytes;
+        return(result);
+    } else {
+        size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4);
+        // Try to make use of the left-over piece.
+        if (bytes_left > 0) {
+            obj * __VOLATILE * my_free_list =
+                        free_list + FREELIST_INDEX(bytes_left);
+
+            ((obj *)start_free) -> free_list_link = *my_free_list;
+            *my_free_list = (obj *)start_free;
+        }
+        start_free = (char *)malloc(bytes_to_get);
+        if (0 == start_free) {
+            int i;
+            obj * __VOLATILE * my_free_list, *p;
+            // Try to make do with what we have.  That can't
+            // hurt.  We do not try smaller requests, since that tends
+            // to result in disaster on multi-process machines.
+            for (i = size; i <= __MAX_BYTES; i += __ALIGN) {
+                my_free_list = free_list + FREELIST_INDEX(i);
+                p = *my_free_list;
+                if (0 != p) {
+                    *my_free_list = p -> free_list_link;
+                    start_free = (char *)p;
+                    end_free = start_free + i;
+                    return(chunk_alloc(size, nobjs));
+                    // Any leftover piece will eventually make it to the
+                    // right free list.
+                }
+            }
+	    end_free = 0;	// In case of exception.
+            start_free = (char *)malloc_alloc::allocate(bytes_to_get);
+            // This should either throw an
+            // exception or remedy the situation.  Thus we assume it
+            // succeeded.
+        }
+        heap_size += bytes_to_get;
+        end_free = start_free + bytes_to_get;
+        return(chunk_alloc(size, nobjs));
+    }
+}
+
+
+/* Returns an object of size n, and optionally adds to size n free list.*/
+/* We assume that n is properly aligned.                                */
+/* We hold the allocation lock.                                         */
+template <bool threads, int inst>
+void* __default_alloc_template<threads, inst>::refill(size_t n)
+{
+    int nobjs = 20;
+    char * chunk = chunk_alloc(n, nobjs);
+    obj * __VOLATILE * my_free_list;
+    obj * result;
+    obj * current_obj, * next_obj;
+    int i;
+
+    if (1 == nobjs) return(chunk);
+    my_free_list = free_list + FREELIST_INDEX(n);
+
+    /* Build free list in chunk */
+      result = (obj *)chunk;
+      *my_free_list = next_obj = (obj *)(chunk + n);
+      for (i = 1; ; i++) {
+        current_obj = next_obj;
+        next_obj = (obj *)((char *)next_obj + n);
+        if (nobjs - 1 == i) {
+            current_obj -> free_list_link = 0;
+            break;
+        } else {
+            current_obj -> free_list_link = next_obj;
+        }
+      }
+    return(result);
+}
+
+template <bool threads, int inst>
+void*
+__default_alloc_template<threads, inst>::reallocate(void *p,
+                                                    size_t old_sz,
+                                                    size_t new_sz)
+{
+    void * result;
+    size_t copy_sz;
+
+    if (old_sz > (size_t) __MAX_BYTES && new_sz > (size_t) __MAX_BYTES) {
+        return(realloc(p, new_sz));
+    }
+    if (ROUND_UP(old_sz) == ROUND_UP(new_sz)) return(p);
+    result = allocate(new_sz);
+    copy_sz = new_sz > old_sz? old_sz : new_sz;
+    memcpy(result, p, copy_sz);
+    deallocate(p, old_sz);
+    return(result);
+}
+
+#ifdef __STL_PTHREADS
+    template <bool threads, int inst>
+    pthread_mutex_t
+    __default_alloc_template<threads, inst>::__node_allocator_lock
+        = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#ifdef __STL_WIN32THREADS
+    template <bool threads, int inst> CRITICAL_SECTION
+    __default_alloc_template<threads, inst>::__node_allocator_lock;
+
+    template <bool threads, int inst> bool
+    __default_alloc_template<threads, inst>::__node_allocator_lock_initialized
+	= false;
+#endif
+
+#ifdef __STL_SGI_THREADS
+__STL_END_NAMESPACE
+#include <mutex.h>
+#include <time.h>
+__STL_BEGIN_NAMESPACE
+// Somewhat generic lock implementations.  We need only test-and-set
+// and some way to sleep.  These should work with both SGI pthreads
+// and sproc threads.  They may be useful on other systems.
+template <bool threads, int inst>
+volatile unsigned long
+__default_alloc_template<threads, inst>::__node_allocator_lock = 0;
+
+#if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) || defined(__GNUC__)
+#   define __test_and_set(l,v) test_and_set(l,v)
+#endif
+
+template <bool threads, int inst>
+void 
+__default_alloc_template<threads, inst>::__lock(volatile unsigned long *lock)
+{
+    const unsigned low_spin_max = 30;  // spin cycles if we suspect uniprocessor
+    const unsigned high_spin_max = 1000; // spin cycles for multiprocessor
+    static unsigned spin_max = low_spin_max;
+    unsigned my_spin_max;
+    static unsigned last_spins = 0;
+    unsigned my_last_spins;
+    static struct timespec ts = {0, 1000};
+    unsigned junk;
+#   define __ALLOC_PAUSE junk *= junk; junk *= junk; junk *= junk; junk *= junk
+    int i;
+
+    if (!__test_and_set((unsigned long *)lock, 1)) {
+        return;
+    }
+    my_spin_max = spin_max;
+    my_last_spins = last_spins;
+    for (i = 0; i < my_spin_max; i++) {
+        if (i < my_last_spins/2 || *lock) {
+            __ALLOC_PAUSE;
+            continue;
+        }
+        if (!__test_and_set((unsigned long *)lock, 1)) {
+            // got it!
+            // Spinning worked.  Thus we're probably not being scheduled
+            // against the other process with which we were contending.
+            // Thus it makes sense to spin longer the next time.
+            last_spins = i;
+            spin_max = high_spin_max;
+            return;
+        }
+    }
+    // We are probably being scheduled against the other process.  Sleep.
+    spin_max = low_spin_max;
+    for (;;) {
+        if (!__test_and_set((unsigned long *)lock, 1)) {
+            return;
+        }
+        nanosleep(&ts, 0);
+    }
+}
+
+template <bool threads, int inst>
+inline void
+__default_alloc_template<threads, inst>::__unlock(volatile unsigned long *lock)
+{
+#   if defined(__GNUC__) && __mips >= 3
+        asm("sync");
+        *lock = 0;
+#   elif __mips >= 3 && (defined (_ABIN32) || defined(_ABI64))
+        __lock_release(lock);
+#   else 
+        *lock = 0;
+        // This is not sufficient on many multiprocessors, since
+        // writes to protected variables and the lock may be reordered.
+#   endif
+}
+#endif
+
+template <bool threads, int inst>
+char *__default_alloc_template<threads, inst>::start_free = 0;
+
+template <bool threads, int inst>
+char *__default_alloc_template<threads, inst>::end_free = 0;
+
+template <bool threads, int inst>
+size_t __default_alloc_template<threads, inst>::heap_size = 0;
+
+template <bool threads, int inst>
+__default_alloc_template<threads, inst>::obj * __VOLATILE
+__default_alloc_template<threads, inst> ::free_list[
+# ifdef __SUNPRO_CC
+    __NFREELISTS
+# else
+    __default_alloc_template<threads, inst>::__NFREELISTS
+# endif
+] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
+// The 16 zeros are necessary to make version 4.1 of the SunPro
+// compiler happy.  Otherwise it appears to allocate too little
+// space for the array.
+
+# ifdef __STL_WIN32THREADS
+  // Create one to get critical section initialized.
+  // We do this onece per file, but only the first constructor
+  // does anything.
+  static alloc __node_allocator_dummy_instance;
+# endif
+
+#endif /* ! __USE_MALLOC */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+#undef __PRIVATE
+
+#endif /* __SGI_STL_INTERNAL_ALLOC_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_bvec.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_bvec.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_bvec.h	(revision 18)
@@ -0,0 +1,616 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_BVECTOR_H
+#define __SGI_STL_INTERNAL_BVECTOR_H
+
+__STL_BEGIN_NAMESPACE 
+
+static const int __WORD_BIT = int(CHAR_BIT*sizeof(unsigned int));
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+struct __bit_reference {
+  unsigned int* p;
+  unsigned int mask;
+  __bit_reference(unsigned int* x, unsigned int y) : p(x), mask(y) {}
+
+public:
+  __bit_reference() : p(0), mask(0) {}
+  operator bool() const { return !(!(*p & mask)); }
+  __bit_reference& operator=(bool x) {
+    if (x)      
+      *p |= mask;
+    else 
+      *p &= ~mask;
+    return *this;
+  }
+  __bit_reference& operator=(const __bit_reference& x) { return *this = bool(x); }
+  bool operator==(const __bit_reference& x) const {
+    return bool(*this) == bool(x);
+  }
+  bool operator<(const __bit_reference& x) const {
+    return bool(*this) < bool(x);
+  }
+  void flip() { *p ^= mask; }
+};
+
+inline void swap(__bit_reference x, __bit_reference y) {
+  bool tmp = x;
+  x = y;
+  y = tmp;
+}
+
+struct __bit_iterator : public random_access_iterator<bool, ptrdiff_t> {
+  typedef __bit_reference  reference;
+  typedef __bit_reference* pointer;
+  typedef __bit_iterator iterator;
+
+  unsigned int* p;
+  unsigned int offset;
+  void bump_up() {
+    if (offset++ == __WORD_BIT - 1) {
+      offset = 0;
+      ++p;
+    }
+  }
+  void bump_down() {
+    if (offset-- == 0) {
+      offset = __WORD_BIT - 1;
+      --p;
+    }
+  }
+
+  __bit_iterator() : p(0), offset(0) {}
+  __bit_iterator(unsigned int* x, unsigned int y) : p(x), offset(y) {}
+  reference operator*() const { return reference(p, 1U << offset); }
+  iterator& operator++() {
+    bump_up();
+    return *this;
+  }
+  iterator operator++(int) {
+    iterator tmp = *this;
+    bump_up();
+    return tmp;
+  }
+  iterator& operator--() {
+    bump_down();
+    return *this;
+  }
+  iterator operator--(int) {
+    iterator tmp = *this;
+    bump_down();
+    return tmp;
+  }
+  iterator& operator+=(difference_type i) {
+    difference_type n = i + offset;
+    p += n / __WORD_BIT;
+    n = n % __WORD_BIT;
+    if (n < 0) {
+      offset = (unsigned int) n + __WORD_BIT;
+      --p;
+    } else
+      offset = (unsigned int) n;
+    return *this;
+  }
+  iterator& operator-=(difference_type i) {
+    *this += -i;
+    return *this;
+  }
+  iterator operator+(difference_type i) const {
+    iterator tmp = *this;
+    return tmp += i;
+  }
+  iterator operator-(difference_type i) const {
+    iterator tmp = *this;
+    return tmp -= i;
+  }
+  difference_type operator-(iterator x) const {
+    return __WORD_BIT * (p - x.p) + offset - x.offset;
+  }
+  reference operator[](difference_type i) { return *(*this + i); }
+  bool operator==(const iterator& x) const {
+    return p == x.p && offset == x.offset;
+  }
+  bool operator!=(const iterator& x) const {
+    return p != x.p || offset != x.offset;
+  }
+  bool operator<(iterator x) const {
+    return p < x.p || (p == x.p && offset < x.offset);
+  }
+};
+
+struct __bit_const_iterator
+  : public random_access_iterator<bool, ptrdiff_t>
+{
+  typedef bool                 reference;
+  typedef bool                 const_reference;
+  typedef const bool*          pointer;
+  typedef __bit_const_iterator const_iterator;
+
+  unsigned int* p;
+  unsigned int offset;
+  void bump_up() {
+    if (offset++ == __WORD_BIT - 1) {
+      offset = 0;
+      ++p;
+    }
+  }
+  void bump_down() {
+    if (offset-- == 0) {
+      offset = __WORD_BIT - 1;
+      --p;
+    }
+  }
+
+  __bit_const_iterator() : p(0), offset(0) {}
+  __bit_const_iterator(unsigned int* x, unsigned int y) : p(x), offset(y) {}
+  __bit_const_iterator(const __bit_iterator& x) : p(x.p), offset(x.offset) {}
+  const_reference operator*() const {
+    return __bit_reference(p, 1U << offset);
+  }
+  const_iterator& operator++() {
+    bump_up();
+    return *this;
+  }
+  const_iterator operator++(int) {
+    const_iterator tmp = *this;
+    bump_up();
+    return tmp;
+  }
+  const_iterator& operator--() {
+    bump_down();
+    return *this;
+  }
+  const_iterator operator--(int) {
+    const_iterator tmp = *this;
+    bump_down();
+    return tmp;
+  }
+  const_iterator& operator+=(difference_type i) {
+    difference_type n = i + offset;
+    p += n / __WORD_BIT;
+    n = n % __WORD_BIT;
+    if (n < 0) {
+      offset = (unsigned int) n + __WORD_BIT;
+      --p;
+    } else
+      offset = (unsigned int) n;
+    return *this;
+  }
+  const_iterator& operator-=(difference_type i) {
+    *this += -i;
+    return *this;
+  }
+  const_iterator operator+(difference_type i) const {
+    const_iterator tmp = *this;
+    return tmp += i;
+  }
+  const_iterator operator-(difference_type i) const {
+    const_iterator tmp = *this;
+    return tmp -= i;
+  }
+  difference_type operator-(const_iterator x) const {
+    return __WORD_BIT * (p - x.p) + offset - x.offset;
+  }
+  const_reference operator[](difference_type i) { 
+    return *(*this + i); 
+  }
+  bool operator==(const const_iterator& x) const {
+    return p == x.p && offset == x.offset;
+  }
+  bool operator!=(const const_iterator& x) const {
+    return p != x.p || offset != x.offset;
+  }
+  bool operator<(const_iterator x) const {
+    return p < x.p || (p == x.p && offset < x.offset);
+  }
+};
+
+// The next few lines are confusing.  What we're doing is declaring a
+//  partial specialization of vector<T, Alloc> if we have the necessary
+//  compiler support.  Otherwise, we define a class bit_vector which uses
+//  the default allocator.  In either case, we typedef "data_allocator" 
+//  appropriately.
+
+#if defined(__STL_CLASS_PARTIAL_SPECIALIZATION) && !defined(__STL_NEED_BOOL)
+#define __SGI_STL_VECBOOL_TEMPLATE
+#define __BVECTOR vector
+#else
+#undef __SGI_STL_VECBOOL_TEMPLATE
+#define __BVECTOR bit_vector
+#endif
+
+#      ifdef __SGI_STL_VECBOOL_TEMPLATE
+       __STL_END_NAMESPACE
+#      include <stl_vect.h>
+       __STL_BEGIN_NAMESPACE
+template<class Alloc> class vector<bool, Alloc>
+#      else /* __SGI_STL_VECBOOL_TEMPLATE */
+class bit_vector
+#      endif /* __SGI_STL_VECBOOL_TEMPLATE */
+{
+#      ifdef __SGI_STL_VECBOOL_TEMPLATE
+  typedef simple_alloc<unsigned int, Alloc> data_allocator;
+#      else /* __SGI_STL_VECBOOL_TEMPLATE */
+  typedef simple_alloc<unsigned int, alloc> data_allocator;  
+#      endif /* __SGI_STL_VECBOOL_TEMPLATE */
+public:
+  typedef bool value_type;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type; 
+  typedef __bit_reference reference;
+  typedef bool const_reference;
+  typedef __bit_reference* pointer;
+  typedef const bool* const_pointer;
+
+  typedef __bit_iterator                iterator;
+  typedef __bit_const_iterator          const_iterator;
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+  typedef reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef reverse_iterator<iterator> reverse_iterator;
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+  typedef reverse_iterator<const_iterator, value_type, const_reference, 
+                           difference_type> const_reverse_iterator;
+  typedef reverse_iterator<iterator, value_type, reference, difference_type>
+          reverse_iterator;
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+protected:
+  iterator start;
+  iterator finish;
+  unsigned int* end_of_storage;
+  unsigned int* bit_alloc(size_type n) {
+    return data_allocator::allocate((n + __WORD_BIT - 1)/__WORD_BIT);
+  }
+  void deallocate() {
+    if (start.p)
+      data_allocator::deallocate(start.p, end_of_storage - start.p);
+  }
+  void initialize(size_type n) {
+    unsigned int* q = bit_alloc(n);
+    end_of_storage = q + (n + __WORD_BIT - 1)/__WORD_BIT;
+    start = iterator(q, 0);
+    finish = start + difference_type(n);
+  }
+  void insert_aux(iterator position, bool x) {
+    if (finish.p != end_of_storage) {
+      copy_backward(position, finish, finish + 1);
+      *position = x;
+      ++finish;
+    }
+    else {
+      size_type len = size() ? 2 * size() : __WORD_BIT;
+      unsigned int* q = bit_alloc(len);
+      iterator i = copy(begin(), position, iterator(q, 0));
+      *i++ = x;
+      finish = copy(position, end(), i);
+      deallocate();
+      end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT;
+      start = iterator(q, 0);
+    }
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void initialize_range(InputIterator first, InputIterator last,
+                        input_iterator_tag) {
+    start = iterator();
+    finish = iterator();
+    end_of_storage = 0;
+    for ( ; first != last; ++first) 
+      push_back(*first);
+  }
+
+  template <class ForwardIterator>
+  void initialize_range(ForwardIterator first, ForwardIterator last,
+                        forward_iterator_tag) {
+    size_type n = 0;
+    distance(first, last, n);
+    initialize(n);
+    copy(first, last, start);
+  }
+
+  template <class InputIterator>
+  void insert_range(iterator pos,
+                    InputIterator first, InputIterator last,
+                    input_iterator_tag) {
+    for ( ; first != last; ++first) {
+      pos = insert(pos, *first);
+      ++pos;
+    }
+  }
+
+  template <class ForwardIterator>
+  void insert_range(iterator position,
+                    ForwardIterator first, ForwardIterator last,
+                    forward_iterator_tag) {
+    if (first != last) {
+      size_type n = 0;
+      distance(first, last, n);
+      if (capacity() - size() >= n) {
+        copy_backward(position, end(), finish + difference_type(n));
+        copy(first, last, position);
+        finish += difference_type(n);
+      }
+      else {
+        size_type len = size() + max(size(), n);
+        unsigned int* q = bit_alloc(len);
+        iterator i = copy(begin(), position, iterator(q, 0));
+        i = copy(first, last, i);
+        finish = copy(position, end(), i);
+        deallocate();
+        end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT;
+        start = iterator(q, 0);
+      }
+    }
+  }      
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+public:
+  iterator begin() { return start; }
+  const_iterator begin() const { return start; }
+  iterator end() { return finish; }
+  const_iterator end() const { return finish; }
+
+  reverse_iterator rbegin() { return reverse_iterator(end()); }
+  const_reverse_iterator rbegin() const { 
+    return const_reverse_iterator(end()); 
+  }
+  reverse_iterator rend() { return reverse_iterator(begin()); }
+  const_reverse_iterator rend() const { 
+    return const_reverse_iterator(begin()); 
+  }
+
+  size_type size() const { return size_type(end() - begin()); }
+  size_type max_size() const { return size_type(-1); }
+  size_type capacity() const {
+    return size_type(const_iterator(end_of_storage, 0) - begin());
+  }
+  bool empty() const { return begin() == end(); }
+  reference operator[](size_type n) {
+    return *(begin() + difference_type(n));
+  }
+  const_reference operator[](size_type n) const {
+    return *(begin() + difference_type(n));
+  }
+  __BVECTOR() : start(iterator()), finish(iterator()), end_of_storage(0) {}
+  __BVECTOR(size_type n, bool value) {
+    initialize(n);
+    fill(start.p, end_of_storage, value ? ~0 : 0);
+  }
+  __BVECTOR(int n, bool value) {
+    initialize(n);
+    fill(start.p, end_of_storage, value ? ~0 : 0);
+  }
+  __BVECTOR(long n, bool value) {
+    initialize(n);
+    fill(start.p, end_of_storage, value ? ~0 : 0);
+  }
+  explicit __BVECTOR(size_type n) {
+    initialize(n);
+    fill(start.p, end_of_storage, 0);
+  }
+  __BVECTOR(const __BVECTOR& x) {
+    initialize(x.size());
+    copy(x.begin(), x.end(), start);
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  __BVECTOR(InputIterator first, InputIterator last) {
+    initialize_range(first, last, iterator_category(first));
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  __BVECTOR(const_iterator first, const_iterator last) {
+    size_type n = 0;
+    distance(first, last, n);
+    initialize(n);
+    copy(first, last, start);
+  }
+  __BVECTOR(const bool* first, const bool* last) {
+    size_type n = 0;
+    distance(first, last, n);
+    initialize(n);
+    copy(first, last, start);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  ~__BVECTOR() { deallocate(); }
+  __BVECTOR& operator=(const __BVECTOR& x) {
+    if (&x == this) return *this;
+    if (x.size() > capacity()) {
+      deallocate();
+      initialize(x.size());
+    }
+    copy(x.begin(), x.end(), begin());
+    finish = begin() + difference_type(x.size());
+    return *this;
+  }
+  void reserve(size_type n) {
+    if (capacity() < n) {
+      unsigned int* q = bit_alloc(n);
+      finish = copy(begin(), end(), iterator(q, 0));
+      deallocate();
+      start = iterator(q, 0);
+      end_of_storage = q + (n + __WORD_BIT - 1)/__WORD_BIT;
+    }
+  }
+  reference front() { return *begin(); }
+  const_reference front() const { return *begin(); }
+  reference back() { return *(end() - 1); }
+  const_reference back() const { return *(end() - 1); }
+  void push_back(bool x) {
+    if (finish.p != end_of_storage)
+      *finish++ = x;
+    else
+      insert_aux(end(), x);
+  }
+  void swap(__BVECTOR& x) {
+    __STD::swap(start, x.start);
+    __STD::swap(finish, x.finish);
+    __STD::swap(end_of_storage, x.end_of_storage);
+  }
+  iterator insert(iterator position, bool x = bool()) {
+    difference_type n = position - begin();
+    if (finish.p != end_of_storage && position == end())
+      *finish++ = x;
+    else
+      insert_aux(position, x);
+    return begin() + n;
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator> void insert(iterator position,
+                                             InputIterator first,
+                                             InputIterator last) {
+    insert_range(position, first, last, iterator_category(first));
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  void insert(iterator position, const_iterator first, 
+              const_iterator last) {
+    if (first == last) return;
+    size_type n = 0;
+    distance(first, last, n);
+    if (capacity() - size() >= n) {
+      copy_backward(position, end(), finish + n);
+      copy(first, last, position);
+      finish += n;
+    }
+    else {
+      size_type len = size() + max(size(), n);
+      unsigned int* q = bit_alloc(len);
+      iterator i = copy(begin(), position, iterator(q, 0));
+      i = copy(first, last, i);
+      finish = copy(position, end(), i);
+      deallocate();
+      end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT;
+      start = iterator(q, 0);
+    }
+  }
+
+  void insert(iterator position, const bool* first, const bool* last) {
+    if (first == last) return;
+    size_type n = 0;
+    distance(first, last, n);
+    if (capacity() - size() >= n) {
+      copy_backward(position, end(), finish + n);
+      copy(first, last, position);
+      finish += n;
+    }
+    else {
+      size_type len = size() + max(size(), n);
+      unsigned int* q = bit_alloc(len);
+      iterator i = copy(begin(), position, iterator(q, 0));
+      i = copy(first, last, i);
+      finish = copy(position, end(), i);
+      deallocate();
+      end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT;
+      start = iterator(q, 0);
+    }
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+  
+  void insert(iterator position, size_type n, bool x) {
+    if (n == 0) return;
+    if (capacity() - size() >= n) {
+      copy_backward(position, end(), finish + difference_type(n));
+      fill(position, position + difference_type(n), x);
+      finish += difference_type(n);
+    }
+    else {
+      size_type len = size() + max(size(), n);
+      unsigned int* q = bit_alloc(len);
+      iterator i = copy(begin(), position, iterator(q, 0));
+      fill_n(i, n, x);
+      finish = copy(position, end(), i + difference_type(n));
+      deallocate();
+      end_of_storage = q + (len + __WORD_BIT - 1)/__WORD_BIT;
+      start = iterator(q, 0);
+    }
+  }
+
+  void insert(iterator pos, int n, bool x)  { insert(pos, (size_type)n, x); }
+  void insert(iterator pos, long n, bool x) { insert(pos, (size_type)n, x); }
+
+  void pop_back() { --finish; }
+  iterator erase(iterator position) {
+    if (position + 1 != end())
+      copy(position + 1, end(), position);
+    --finish;
+    return position;
+  }
+  iterator erase(iterator first, iterator last) {
+    finish = copy(last, end(), first);
+    return first;
+  }
+  void resize(size_type new_size, bool x = bool()) {
+    if (new_size < size()) 
+      erase(begin() + difference_type(new_size), end());
+    else
+      insert(end(), new_size - size(), x);
+  }
+  void clear() { erase(begin(), end()); }
+};
+
+#ifdef __SGI_STL_VECBOOL_TEMPLATE
+
+typedef vector<bool, alloc> bit_vector;
+
+#else /* __SGI_STL_VECBOOL_TEMPLATE */
+
+inline bool operator==(const bit_vector& x, const bit_vector& y) {
+  return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
+}
+
+inline bool operator<(const bit_vector& x, const bit_vector& y) {
+  return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+#endif /* __SGI_STL_VECBOOL_TEMPLATE */
+
+#undef __SGI_STL_VECBOOL_TEMPLATE
+#undef __BVECTOR
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE 
+
+#endif /* __SGI_STL_INTERNAL_BVECTOR_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_conf.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_conf.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_conf.h	(revision 18)
@@ -0,0 +1,254 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef __STL_CONFIG_H
+# define __STL_CONFIG_H
+
+// What this file does.
+//  (1)  Defines bool, true, and false if the compiler doesn't do so already.
+//  (2)  Defines __STL_NO_DRAND48 if the compiler's standard library does
+//       not support the drand48() function.
+//  (3)  Defines __STL_STATIC_TEMPLATE_MEMBER_BUG if the compiler can't 
+//       handle static members of template classes.
+//  (4)  Defines 'typename' as a null macro if the compiler does not support
+//       the typename keyword.
+//  (5)  Defines __STL_CLASS_PARTIAL_SPECIALIZATION if the compiler 
+//       supports partial specialization of class templates.
+//  (6)  Defines __STL_FUNCTION_TMPL_PARTIAL_ORDER if the compiler supports
+//       partial ordering of function templates (a.k.a partial specialization
+//       of function templates.
+//  (7)  Defines __STL_EXPLICIT_FUNCTION_TMPL_ARGS if the compiler
+//       supports calling a function template by providing its template
+//       arguments explicitly.
+//  (8)  Defines __STL_MEMBER_TEMPLATES if the compiler supports
+//       template members of classes.
+//  (9)  Defines 'explicit' as a null macro if the compiler does not support
+//       the explicit keyword.    
+//  (10) Defines __STL_LIMITED_DEFAULT_TEMPLATES if the compiler is
+//       unable to handle default template parameters that depend on
+//       previous template parameters.
+//  (11) Defines __STL_NON_TYPE_TMPL_PARAM_BUG if the compiler has 
+//       trouble performing function template argument deduction for
+//       non-type template parameters.
+//  (12) Defines __SGI_STL_NO_ARROW_OPERATOR if the compiler is unable
+//       to support the -> operator for iterators.
+//  (13) Defines __STL_USE_EXCEPTIONS if the compiler (in the current
+//       compilation mode) supports exceptions.
+//  (14) Define __STL_USE_NAMESPACES if we're putting the STL into a 
+//       namespace.  
+//  (15) Defines __STL_SGI_THREADS if this is being compiled on an SGI
+//       compiler, and if the user hasn't selected pthreads or no threads
+//       instead.
+//  (16) Defines __STL_WIN32THREADS if this is being compiled on a 
+//       WIN32 compiler in multithreaded mode.
+//  (17) Define namespace-related macros (__STD, __STL_BEGIN_NAMESPACE, etc.)
+//       apropriately.
+//  (18) Define exception-related macros (__STL_TRY, __STL_UNWIND, etc.)
+//       appropriately.
+//  (19) Defines __stl_assert either as a test or as a null macro,
+//       depending on whether or not __STL_ASSERTIONS is defined.
+
+#ifdef _PTHREADS
+#   define __STL_PTHREADS
+#endif
+
+# if defined(__sgi) && !defined(__GNUC__)
+#   if !defined(_BOOL)
+#     define __STL_NEED_BOOL
+#   endif
+#   if !defined(_TYPENAME_IS_KEYWORD)
+#     define __STL_NEED_TYPENAME
+#   endif
+#   ifdef _PARTIAL_SPECIALIZATION_OF_CLASS_TEMPLATES
+#     define __STL_CLASS_PARTIAL_SPECIALIZATION
+#   endif
+#   ifdef _MEMBER_TEMPLATES
+#     define __STL_MEMBER_TEMPLATES
+#   endif
+#   if !defined(_EXPLICIT_IS_KEYWORD)
+#     define __STL_NEED_EXPLICIT
+#   endif
+#   ifdef __EXCEPTIONS
+#     define __STL_USE_EXCEPTIONS
+#   endif
+#   if (_COMPILER_VERSION >= 721) && defined(_NAMESPACES)
+#     define __STL_USE_NAMESPACES
+#   endif 
+#   if !defined(_NOTHREADS) && !defined(__STL_PTHREADS)
+#     define __STL_SGI_THREADS
+#   endif
+# endif
+
+# ifdef __GNUC__
+#   include <_G_confi.h>
+#   if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
+#     define __STL_STATIC_TEMPLATE_MEMBER_BUG
+#     define __STL_NEED_TYPENAME
+#     define __STL_NEED_EXPLICIT
+#   else
+#     define __STL_CLASS_PARTIAL_SPECIALIZATION
+#     define __STL_FUNCTION_TMPL_PARTIAL_ORDER
+#     define __STL_EXPLICIT_FUNCTION_TMPL_ARGS
+#     define __STL_MEMBER_TEMPLATES
+#   endif
+    /* glibc pre 2.0 is very buggy. We have to disable thread for it.
+       It should be upgraded to glibc 2.0 or later. */
+#   if !defined(_NOTHREADS) && __GLIBC__ >= 2 && defined(_G_USING_THUNKS)
+#     define __STL_PTHREADS
+#     ifdef __STRICT_ANSI__
+        /* Work around a bug in the glibc pthread.h.  */
+#       define sigset_t __sigset_t
+#     endif
+#   endif
+#   ifdef __EXCEPTIONS
+#     define __STL_USE_EXCEPTIONS
+#   endif
+# endif
+
+# if defined(__SUNPRO_CC) 
+#   define __STL_NEED_BOOL
+#   define __STL_NEED_TYPENAME
+#   define __STL_NEED_EXPLICIT
+#   define __STL_USE_EXCEPTIONS
+# endif
+
+# if defined(__COMO__)
+#   define __STL_MEMBER_TEMPLATES
+#   define __STL_CLASS_PARTIAL_SPECIALIZATION
+#   define __STL_USE_EXCEPTIONS
+#   define __STL_USE_NAMESPACES
+# endif
+
+# if defined(_MSC_VER)
+#   if _MSC_VER > 1000
+#     include <yvals.h>
+#   else
+#     define __STL_NEED_BOOL
+#   endif
+#   define __STL_NO_DRAND48
+#   define __STL_NEED_TYPENAME
+#   if _MSC_VER < 1100
+#     define __STL_NEED_EXPLICIT
+#   endif
+#   define __STL_NON_TYPE_TMPL_PARAM_BUG
+#   define __SGI_STL_NO_ARROW_OPERATOR
+#   ifdef _CPPUNWIND
+#     define __STL_USE_EXCEPTIONS
+#   endif
+#   ifdef _MT
+#     define __STL_WIN32THREADS
+#   endif
+# endif
+
+# if defined(__BORLANDC__)
+#   define __STL_NO_DRAND48
+#   define __STL_NEED_TYPENAME
+#   define __STL_LIMITED_DEFAULT_TEMPLATES
+#   define __SGI_STL_NO_ARROW_OPERATOR
+#   define __STL_NON_TYPE_TMPL_PARAM_BUG
+#   ifdef _CPPUNWIND
+#     define __STL_USE_EXCEPTIONS
+#   endif
+#   ifdef __MT__
+#     define __STL_WIN32THREADS
+#   endif
+# endif
+
+
+# if defined(__STL_NEED_BOOL)
+    typedef int bool;
+#   define true 1
+#   define false 0
+# endif
+
+# ifdef __STL_NEED_TYPENAME
+#   define typename
+# endif
+
+# ifdef __STL_NEED_EXPLICIT
+#   define explicit
+# endif
+
+# ifdef __STL_EXPLICIT_FUNCTION_TMPL_ARGS
+#   define __STL_NULL_TMPL_ARGS <>
+# else
+#   define __STL_NULL_TMPL_ARGS
+# endif
+
+# ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+#   define __STL_TEMPLATE_NULL template<>
+# else
+#   define __STL_TEMPLATE_NULL
+# endif
+
+// __STL_NO_NAMESPACES is a hook so that users can disable namespaces
+// without having to edit library headers.
+# if defined(__STL_USE_NAMESPACES) && !defined(__STL_NO_NAMESPACES)
+#   define __STD std
+#   define __STL_BEGIN_NAMESPACE namespace std {
+#   define __STL_END_NAMESPACE }
+#   define  __STL_USE_NAMESPACE_FOR_RELOPS
+#   define __STL_BEGIN_RELOPS_NAMESPACE namespace std {
+#   define __STL_END_RELOPS_NAMESPACE }
+#   define __STD_RELOPS std
+# else
+#   define __STD 
+#   define __STL_BEGIN_NAMESPACE 
+#   define __STL_END_NAMESPACE 
+#   undef  __STL_USE_NAMESPACE_FOR_RELOPS
+#   define __STL_BEGIN_RELOPS_NAMESPACE 
+#   define __STL_END_RELOPS_NAMESPACE 
+#   define __STD_RELOPS 
+# endif
+
+# ifdef __STL_USE_EXCEPTIONS
+#   define __STL_TRY try
+#   define __STL_CATCH_ALL catch(...)
+#   define __STL_RETHROW throw
+#   define __STL_NOTHROW throw()
+#   define __STL_UNWIND(action) catch(...) { action; throw; }
+# else
+#   define __STL_TRY 
+#   define __STL_CATCH_ALL if (false)
+#   define __STL_RETHROW 
+#   define __STL_NOTHROW 
+#   define __STL_UNWIND(action) 
+# endif
+
+#ifdef __STL_ASSERTIONS
+# include <stdio.h>
+# define __stl_assert(expr) \
+    if (!(expr)) { fprintf(stderr, "%s:%d STL assertion failure: %s\n", \
+			  __FILE__, __LINE__, # expr); abort(); }
+#else
+# define __stl_assert(expr)
+#endif
+
+#endif /* __STL_CONFIG_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_cons.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_cons.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_cons.h	(revision 18)
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_CONSTRUCT_H
+#define __SGI_STL_INTERNAL_CONSTRUCT_H
+
+#include <new.h>
+
+__STL_BEGIN_NAMESPACE
+
+template <class T>
+inline void destroy(T* pointer) {
+    pointer->~T();
+}
+
+template <class T1, class T2>
+inline void construct(T1* p, const T2& value) {
+  new (p) T1(value);
+}
+
+template <class ForwardIterator>
+inline void
+__destroy_aux(ForwardIterator first, ForwardIterator last, __false_type) {
+  for ( ; first < last; ++first)
+    destroy(&*first);
+}
+
+template <class ForwardIterator> 
+inline void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) {}
+
+template <class ForwardIterator, class T>
+inline void __destroy(ForwardIterator first, ForwardIterator last, T*) {
+  typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;
+  __destroy_aux(first, last, trivial_destructor());
+}
+
+template <class ForwardIterator>
+inline void destroy(ForwardIterator first, ForwardIterator last) {
+  __destroy(first, last, value_type(first));
+}
+
+inline void destroy(char*, char*) {}
+inline void destroy(wchar_t*, wchar_t*) {}
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_CONSTRUCT_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_dequ.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_dequ.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_dequ.h	(revision 18)
@@ -0,0 +1,1335 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_DEQUE_H
+#define __SGI_STL_INTERNAL_DEQUE_H
+
+/* Class invariants:
+ *  For any nonsingular iterator i:
+ *    i.node is the address of an element in the map array.  The
+ *      contents of i.node is a pointer to the beginning of a node.
+ *    i.first == *(i.node) 
+ *    i.last  == i.first + node_size
+ *    i.cur is a pointer in the range [i.first, i.last).  NOTE:
+ *      the implication of this is that i.cur is always a dereferenceable
+ *      pointer, even if i is a past-the-end iterator.
+ *  Start and Finish are always nonsingular iterators.  NOTE: this means
+ *    that an empty deque must have one node, and that a deque
+ *    with N elements, where N is the buffer size, must have two nodes.
+ *  For every node other than start.node and finish.node, every element
+ *    in the node is an initialized object.  If start.node == finish.node,
+ *    then [start.cur, finish.cur) are initialized objects, and
+ *    the elements outside that range are uninitialized storage.  Otherwise,
+ *    [start.cur, start.last) and [finish.first, finish.cur) are initialized
+ *    objects, and [start.first, start.cur) and [finish.cur, finish.last)
+ *    are uninitialized storage.
+ *  [map, map + map_size) is a valid, non-empty range.  
+ *  [start.node, finish.node] is a valid range contained within 
+ *    [map, map + map_size).  
+ *  A pointer in the range [map, map + map_size) points to an allocated
+ *    node if and only if the pointer is in the range [start.node, finish.node].
+ */
+
+
+/*
+ * In previous versions of deque, node_size was fixed by the 
+ * implementation.  In this version, however, users can select
+ * the node size.  Deque has three template parameters; the third,
+ * a number of type size_t, is the number of elements per node.
+ * If the third template parameter is 0 (which is the default), 
+ * then deque will use a default node size.
+ *
+ * The only reason for using an alternate node size is if your application
+ * requires a different performance tradeoff than the default.  If,
+ * for example, your program contains many deques each of which contains
+ * only a few elements, then you might want to save memory (possibly
+ * by sacrificing some speed) by using smaller nodes.
+ *
+ * Unfortunately, some compilers have trouble with non-type template 
+ * parameters; stl_config.h defines __STL_NON_TYPE_TMPL_PARAM_BUG if
+ * that is the case.  If your compiler is one of them, then you will
+ * not be able to use alternate node sizes; you will have to use the
+ * default value.
+ */
+
+__STL_BEGIN_NAMESPACE 
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+// Note: this function is simply a kludge to work around several compilers'
+//  bugs in handling constant expressions.
+inline size_t __deque_buf_size(size_t n, size_t sz)
+{
+  return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
+}
+
+#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
+template <class T, class Ref, class Ptr, size_t BufSiz>
+struct __deque_iterator {
+  typedef __deque_iterator<T, T&, T*, BufSiz>             iterator;
+  typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
+  static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); }
+#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+template <class T, class Ref, class Ptr>
+struct __deque_iterator {
+  typedef __deque_iterator<T, T&, T*>             iterator;
+  typedef __deque_iterator<T, const T&, const T*> const_iterator;
+  static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }
+#endif
+
+  typedef random_access_iterator_tag iterator_category;
+  typedef T value_type;
+  typedef Ptr pointer;
+  typedef Ref reference;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  typedef T** map_pointer;
+
+  typedef __deque_iterator self;
+
+  T* cur;
+  T* first;
+  T* last;
+  map_pointer node;
+
+  __deque_iterator(T* x, map_pointer y) 
+    : cur(x), first(*y), last(*y + buffer_size()), node(y) {}
+  __deque_iterator() : cur(0), first(0), last(0), node(0) {}
+  __deque_iterator(const iterator& x)
+    : cur(x.cur), first(x.first), last(x.last), node(x.node) {}
+
+  reference operator*() const { return *cur; }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+
+  difference_type operator-(const self& x) const {
+    return difference_type(buffer_size()) * (node - x.node - 1) +
+      (cur - first) + (x.last - x.cur);
+  }
+
+  self& operator++() {
+    ++cur;
+    if (cur == last) {
+      set_node(node + 1);
+      cur = first;
+    }
+    return *this; 
+  }
+  self operator++(int)  {
+    self tmp = *this;
+    ++*this;
+    return tmp;
+  }
+
+  self& operator--() {
+    if (cur == first) {
+      set_node(node - 1);
+      cur = last;
+    }
+    --cur;
+    return *this;
+  }
+  self operator--(int) {
+    self tmp = *this;
+    --*this;
+    return tmp;
+  }
+
+  self& operator+=(difference_type n) {
+    difference_type offset = n + (cur - first);
+    if (offset >= 0 && offset < difference_type(buffer_size()))
+      cur += n;
+    else {
+      difference_type node_offset =
+        offset > 0 ? offset / difference_type(buffer_size())
+                   : -difference_type((-offset - 1) / buffer_size()) - 1;
+      set_node(node + node_offset);
+      cur = first + (offset - node_offset * difference_type(buffer_size()));
+    }
+    return *this;
+  }
+
+  self operator+(difference_type n) const {
+    self tmp = *this;
+    return tmp += n;
+  }
+
+  self& operator-=(difference_type n) { return *this += -n; }
+ 
+  self operator-(difference_type n) const {
+    self tmp = *this;
+    return tmp -= n;
+  }
+
+  reference operator[](difference_type n) const { return *(*this + n); }
+
+  bool operator==(const self& x) const { return cur == x.cur; }
+  bool operator!=(const self& x) const { return !(*this == x); }
+  bool operator<(const self& x) const {
+    return (node == x.node) ? (cur < x.cur) : (node < x.node);
+  }
+
+  void set_node(map_pointer new_node) {
+    node = new_node;
+    first = *new_node;
+    last = first + difference_type(buffer_size());
+  }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
+
+template <class T, class Ref, class Ptr, size_t BufSiz>
+inline random_access_iterator_tag
+iterator_category(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
+  return random_access_iterator_tag();
+}
+
+template <class T, class Ref, class Ptr, size_t BufSiz>
+inline T* value_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
+  return 0;
+}
+
+template <class T, class Ref, class Ptr, size_t BufSiz>
+inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
+  return 0;
+}
+
+#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+
+template <class T, class Ref, class Ptr>
+inline random_access_iterator_tag
+iterator_category(const __deque_iterator<T, Ref, Ptr>&) {
+  return random_access_iterator_tag();
+}
+
+template <class T, class Ref, class Ptr>
+inline T* value_type(const __deque_iterator<T, Ref, Ptr>&) { return 0; }
+
+template <class T, class Ref, class Ptr>
+inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr>&) {
+  return 0;
+}
+
+#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+// See __deque_buf_size().  The only reason that the default value is 0
+//  is as a workaround for bugs in the way that some compilers handle
+//  constant expressions.
+template <class T, class Alloc = alloc, size_t BufSiz = 0> 
+class deque {
+public:                         // Basic types
+  typedef T value_type;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+
+public:                         // Iterators
+#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
+  typedef __deque_iterator<T, T&, T*, BufSiz>              iterator;
+  typedef __deque_iterator<T, const T&, const T&, BufSiz>  const_iterator;
+#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+  typedef __deque_iterator<T, T&, T*>                      iterator;
+  typedef __deque_iterator<T, const T&, const T*>          const_iterator;
+#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+  typedef reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef reverse_iterator<iterator> reverse_iterator;
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+  typedef reverse_iterator<const_iterator, value_type, const_reference, 
+                           difference_type>  
+          const_reverse_iterator;
+  typedef reverse_iterator<iterator, value_type, reference, difference_type>
+          reverse_iterator; 
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+protected:                      // Internal typedefs
+  typedef pointer* map_pointer;
+  typedef simple_alloc<value_type, Alloc> data_allocator;
+  typedef simple_alloc<pointer, Alloc> map_allocator;
+
+  static size_type buffer_size() {
+    return __deque_buf_size(BufSiz, sizeof(value_type));
+  }
+  static size_type initial_map_size() { return 8; }
+
+protected:                      // Data members
+  iterator start;
+  iterator finish;
+
+  map_pointer map;
+  size_type map_size;
+
+public:                         // Basic accessors
+  iterator begin() { return start; }
+  iterator end() { return finish; }
+  const_iterator begin() const { return start; }
+  const_iterator end() const { return finish; }
+
+  reverse_iterator rbegin() { return reverse_iterator(finish); }
+  reverse_iterator rend() { return reverse_iterator(start); }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(finish);
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(start);
+  }
+
+  reference operator[](size_type n) { return start[difference_type(n)]; }
+  const_reference operator[](size_type n) const {
+    return start[difference_type(n)];
+  }
+
+  reference front() { return *start; }
+  reference back() {
+    iterator tmp = finish;
+    --tmp;
+    return *tmp;
+  }
+  const_reference front() const { return *start; }
+  const_reference back() const {
+    const_iterator tmp = finish;
+    --tmp;
+    return *tmp;
+  }
+
+  size_type size() const { return finish - start;; }
+  size_type max_size() const { return size_type(-1); }
+  bool empty() const { return finish == start; }
+
+public:                         // Constructor, destructor.
+  deque()
+    : start(), finish(), map(0), map_size(0)
+  {
+    create_map_and_nodes(0);
+  }
+
+  deque(const deque& x)
+    : start(), finish(), map(0), map_size(0)
+  {
+    create_map_and_nodes(x.size());
+    __STL_TRY {
+      uninitialized_copy(x.begin(), x.end(), start);
+    }
+    __STL_UNWIND(destroy_map_and_nodes());
+  }
+
+  deque(size_type n, const value_type& value)
+    : start(), finish(), map(0), map_size(0)
+  {
+    fill_initialize(n, value);
+  }
+
+  deque(int n, const value_type& value)
+    : start(), finish(), map(0), map_size(0)
+  {
+    fill_initialize(n, value);
+  }
+ 
+  deque(long n, const value_type& value)
+    : start(), finish(), map(0), map_size(0)
+  {
+    fill_initialize(n, value);
+  }
+
+  explicit deque(size_type n)
+    : start(), finish(), map(0), map_size(0)
+  {
+    fill_initialize(n, value_type());
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+  template <class InputIterator>
+  deque(InputIterator first, InputIterator last)
+    : start(), finish(), map(0), map_size(0)
+  {
+    range_initialize(first, last, iterator_category(first));
+  }
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+  deque(const value_type* first, const value_type* last)
+    : start(), finish(), map(0), map_size(0)
+  {
+    create_map_and_nodes(last - first);
+    __STL_TRY {
+      uninitialized_copy(first, last, start);
+    }
+    __STL_UNWIND(destroy_map_and_nodes());
+  }
+
+  deque(const_iterator first, const_iterator last)
+    : start(), finish(), map(0), map_size(0)
+  {
+    create_map_and_nodes(last - first);
+    __STL_TRY {
+      uninitialized_copy(first, last, start);
+    }
+    __STL_UNWIND(destroy_map_and_nodes());
+  }
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  ~deque() {
+    destroy(start, finish);
+    destroy_map_and_nodes();
+  }
+
+  deque& operator= (const deque& x) {
+    const size_type len = size();
+    if (&x != this) {
+      if (len >= x.size())
+        erase(copy(x.begin(), x.end(), start), finish);
+      else {
+        const_iterator mid = x.begin() + difference_type(len);
+        copy(x.begin(), mid, start);
+        insert(finish, mid, x.end());
+      }
+    }
+    return *this;
+  }        
+
+  void swap(deque& x) {
+    __STD::swap(start, x.start);
+    __STD::swap(finish, x.finish);
+    __STD::swap(map, x.map);
+    __STD::swap(map_size, x.map_size);
+  }
+
+public:                         // push_* and pop_*
+  
+  void push_back(const value_type& t) {
+    if (finish.cur != finish.last - 1) {
+      construct(finish.cur, t);
+      ++finish.cur;
+    }
+    else
+      push_back_aux(t);
+  }
+
+  void push_front(const value_type& t) {
+    if (start.cur != start.first) {
+      construct(start.cur - 1, t);
+      --start.cur;
+    }
+    else
+      push_front_aux(t);
+  }
+
+  void pop_back() {
+    if (finish.cur != finish.first) {
+      --finish.cur;
+      destroy(finish.cur);
+    }
+    else
+      pop_back_aux();
+  }
+
+  void pop_front() {
+    if (start.cur != start.last - 1) {
+      destroy(start.cur);
+      ++start.cur;
+    }
+    else 
+      pop_front_aux();
+  }
+
+public:                         // Insert
+
+  iterator insert(iterator position, const value_type& x) {
+    if (position.cur == start.cur) {
+      push_front(x);
+      return start;
+    }
+    else if (position.cur == finish.cur) {
+      push_back(x);
+      iterator tmp = finish;
+      --tmp;
+      return tmp;
+    }
+    else {
+      return insert_aux(position, x);
+    }
+  }
+
+  iterator insert(iterator position) { return insert(position, value_type()); }
+
+  void insert(iterator pos, size_type n, const value_type& x); 
+
+  void insert(iterator pos, int n, const value_type& x) {
+    insert(pos, (size_type) n, x);
+  }
+  void insert(iterator pos, long n, const value_type& x) {
+    insert(pos, (size_type) n, x);
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES  
+
+  template <class InputIterator>
+  void insert(iterator pos, InputIterator first, InputIterator last) {
+    insert(pos, first, last, iterator_category(first));
+  }
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+  void insert(iterator pos, const value_type* first, const value_type* last);
+  void insert(iterator pos, const_iterator first, const_iterator last);
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  void resize(size_type new_size, const value_type& x) {
+    const size_type len = size();
+    if (new_size < len) 
+      erase(start + new_size, finish);
+    else
+      insert(finish, new_size - len, x);
+  }
+
+  void resize(size_type new_size) { resize(new_size, value_type()); }
+
+public:                         // Erase
+  iterator erase(iterator pos) {
+    iterator next = pos;
+    ++next;
+    difference_type index = pos - start;
+    if (index < (size() >> 1)) {
+      copy_backward(start, pos, next);
+      pop_front();
+    }
+    else {
+      copy(next, finish, pos);
+      pop_back();
+    }
+    return start + index;
+  }
+
+  iterator erase(iterator first, iterator last);
+  void clear(); 
+
+protected:                        // Internal construction/destruction
+
+  void create_map_and_nodes(size_type num_elements);
+  void destroy_map_and_nodes();
+  void fill_initialize(size_type n, const value_type& value);
+
+#ifdef __STL_MEMBER_TEMPLATES  
+
+  template <class InputIterator>
+  void range_initialize(InputIterator first, InputIterator last,
+                        input_iterator_tag);
+
+  template <class ForwardIterator>
+  void range_initialize(ForwardIterator first, ForwardIterator last,
+                        forward_iterator_tag);
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+protected:                        // Internal push_* and pop_*
+
+  void push_back_aux(const value_type& t);
+  void push_front_aux(const value_type& t);
+  void pop_back_aux();
+  void pop_front_aux();
+
+protected:                        // Internal insert functions
+
+#ifdef __STL_MEMBER_TEMPLATES  
+
+  template <class InputIterator>
+  void insert(iterator pos, InputIterator first, InputIterator last,
+              input_iterator_tag);
+
+  template <class ForwardIterator>
+  void insert(iterator pos, ForwardIterator first, ForwardIterator last,
+              forward_iterator_tag);
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  iterator insert_aux(iterator pos, const value_type& x);
+  void insert_aux(iterator pos, size_type n, const value_type& x);
+
+#ifdef __STL_MEMBER_TEMPLATES  
+
+  template <class ForwardIterator>
+  void insert_aux(iterator pos, ForwardIterator first, ForwardIterator last,
+                  size_type n);
+
+#else /* __STL_MEMBER_TEMPLATES */
+  
+  void insert_aux(iterator pos,
+                  const value_type* first, const value_type* last,
+                  size_type n);
+
+  void insert_aux(iterator pos, const_iterator first, const_iterator last,
+                  size_type n);
+ 
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  iterator reserve_elements_at_front(size_type n) {
+    size_type vacancies = start.cur - start.first;
+    if (n > vacancies) 
+      new_elements_at_front(n - vacancies);
+    return start - difference_type(n);
+  }
+
+  iterator reserve_elements_at_back(size_type n) {
+    size_type vacancies = (finish.last - finish.cur) - 1;
+    if (n > vacancies)
+      new_elements_at_back(n - vacancies);
+    return finish + difference_type(n);
+  }
+
+  void new_elements_at_front(size_type new_elements);
+  void new_elements_at_back(size_type new_elements);
+
+  void destroy_nodes_at_front(iterator before_start);
+  void destroy_nodes_at_back(iterator after_finish);
+
+protected:                      // Allocation of map and nodes
+
+  // Makes sure the map has space for new nodes.  Does not actually
+  //  add the nodes.  Can invalidate map pointers.  (And consequently, 
+  //  deque iterators.)
+
+  void reserve_map_at_back (size_type nodes_to_add = 1) {
+    if (nodes_to_add + 1 > map_size - (finish.node - map))
+      reallocate_map(nodes_to_add, false);
+  }
+
+  void reserve_map_at_front (size_type nodes_to_add = 1) {
+    if (nodes_to_add > start.node - map)
+      reallocate_map(nodes_to_add, true);
+  }
+
+  void reallocate_map(size_type nodes_to_add, bool add_at_front);
+
+  pointer allocate_node() { return data_allocator::allocate(buffer_size()); }
+  void deallocate_node(pointer n) {
+    data_allocator::deallocate(n, buffer_size());
+  }
+
+#ifdef __STL_NON_TYPE_TMPL_PARAM_BUG
+public:
+  bool operator==(const deque<T, Alloc, 0>& x) const {
+    return size() == x.size() && equal(begin(), end(), x.begin());
+  }
+  bool operator!=(const deque<T, Alloc, 0>& x) const {
+    return size() != x.size() || !equal(begin(), end(), x.begin());
+  }
+  bool operator<(const deque<T, Alloc, 0>& x) const {
+    return lexicographical_compare(begin(), end(), x.begin(), x.end());
+  }
+#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+};
+
+// Non-inline member functions
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+                                      size_type n, const value_type& x) {
+  if (pos.cur == start.cur) {
+    iterator new_start = reserve_elements_at_front(n);
+    uninitialized_fill(new_start, start, x);
+    start = new_start;
+  }
+  else if (pos.cur == finish.cur) {
+    iterator new_finish = reserve_elements_at_back(n);
+    uninitialized_fill(finish, new_finish, x);
+    finish = new_finish;
+  }
+  else 
+    insert_aux(pos, n, x);
+}
+
+#ifndef __STL_MEMBER_TEMPLATES  
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+                                      const value_type* first,
+                                      const value_type* last) {
+  size_type n = last - first;
+  if (pos.cur == start.cur) {
+    iterator new_start = reserve_elements_at_front(n);
+    __STL_TRY {
+      uninitialized_copy(first, last, new_start);
+      start = new_start;
+    }
+    __STL_UNWIND(destroy_nodes_at_front(new_start));
+  }
+  else if (pos.cur == finish.cur) {
+    iterator new_finish = reserve_elements_at_back(n);
+    __STL_TRY {
+      uninitialized_copy(first, last, finish);
+      finish = new_finish;
+    }
+    __STL_UNWIND(destroy_nodes_at_back(new_finish));
+  }
+  else
+    insert_aux(pos, first, last, n);
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+                                      const_iterator first,
+                                      const_iterator last)
+{
+  size_type n = last - first;
+  if (pos.cur == start.cur) {
+    iterator new_start = reserve_elements_at_front(n);
+    __STL_TRY {
+      uninitialized_copy(first, last, new_start);
+      start = new_start;
+    }
+    __STL_UNWIND(destroy_nodes_at_front(new_start));
+  }
+  else if (pos.cur == finish.cur) {
+    iterator new_finish = reserve_elements_at_back(n);
+    __STL_TRY {
+      uninitialized_copy(first, last, finish);
+      finish = new_finish;
+    }
+    __STL_UNWIND(destroy_nodes_at_back(new_finish));
+  }
+  else
+    insert_aux(pos, first, last, n);
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc, size_t BufSize>
+deque<T, Alloc, BufSize>::iterator 
+deque<T, Alloc, BufSize>::erase(iterator first, iterator last) {
+  if (first == start && last == finish) {
+    clear();
+    return finish;
+  }
+  else {
+    difference_type n = last - first;
+    difference_type elems_before = first - start;
+    if (elems_before < (size() - n) / 2) {
+      copy_backward(start, first, last);
+      iterator new_start = start + n;
+      destroy(start, new_start);
+      for (map_pointer cur = start.node; cur < new_start.node; ++cur)
+        data_allocator::deallocate(*cur, buffer_size());
+      start = new_start;
+    }
+    else {
+      copy(last, finish, first);
+      iterator new_finish = finish - n;
+      destroy(new_finish, finish);
+      for (map_pointer cur = new_finish.node + 1; cur <= finish.node; ++cur)
+        data_allocator::deallocate(*cur, buffer_size());
+      finish = new_finish;
+    }
+    return start + elems_before;
+  }
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::clear() {
+  for (map_pointer node = start.node + 1; node < finish.node; ++node) {
+    destroy(*node, *node + buffer_size());
+    data_allocator::deallocate(*node, buffer_size());
+  }
+
+  if (start.node != finish.node) {
+    destroy(start.cur, start.last);
+    destroy(finish.first, finish.cur);
+    data_allocator::deallocate(finish.first, buffer_size());
+  }
+  else
+    destroy(start.cur, finish.cur);
+
+  finish = start;
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::create_map_and_nodes(size_type num_elements) {
+  size_type num_nodes = num_elements / buffer_size() + 1;
+
+  map_size = max(initial_map_size(), num_nodes + 2);
+  map = map_allocator::allocate(map_size);
+
+  map_pointer nstart = map + (map_size - num_nodes) / 2;
+  map_pointer nfinish = nstart + num_nodes - 1;
+    
+  map_pointer cur;
+  __STL_TRY {
+    for (cur = nstart; cur <= nfinish; ++cur)
+      *cur = allocate_node();
+  }
+#     ifdef  __STL_USE_EXCEPTIONS 
+  catch(...) {
+    for (map_pointer n = nstart; n < cur; ++n)
+      deallocate_node(*n);
+    map_allocator::deallocate(map, map_size);
+    throw;
+  }
+#     endif /* __STL_USE_EXCEPTIONS */
+
+  start.set_node(nstart);
+  finish.set_node(nfinish);
+  start.cur = start.first;
+  finish.cur = finish.first + num_elements % buffer_size();
+}
+
+// This is only used as a cleanup function in catch clauses.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::destroy_map_and_nodes() {
+  for (map_pointer cur = start.node; cur <= finish.node; ++cur)
+    deallocate_node(*cur);
+  map_allocator::deallocate(map, map_size);
+}
+  
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::fill_initialize(size_type n,
+                                               const value_type& value) {
+  create_map_and_nodes(n);
+  map_pointer cur;
+  __STL_TRY {
+    for (cur = start.node; cur < finish.node; ++cur)
+      uninitialized_fill(*cur, *cur + buffer_size(), value);
+    uninitialized_fill(finish.first, finish.cur, value);
+  }
+#       ifdef __STL_USE_EXCEPTIONS
+  catch(...) {
+    for (map_pointer n = start.node; n < cur; ++n)
+      destroy(*n, *n + buffer_size());
+    destroy_map_and_nodes();
+    throw;
+  }
+#       endif /* __STL_USE_EXCEPTIONS */
+}
+
+#ifdef __STL_MEMBER_TEMPLATES  
+
+template <class T, class Alloc, size_t BufSize>
+template <class InputIterator>
+void deque<T, Alloc, BufSize>::range_initialize(InputIterator first,
+                                                InputIterator last,
+                                                input_iterator_tag) {
+  create_map_and_nodes(0);
+  for ( ; first != last; ++first)
+    push_back(*first);
+}
+
+template <class T, class Alloc, size_t BufSize>
+template <class ForwardIterator>
+void deque<T, Alloc, BufSize>::range_initialize(ForwardIterator first,
+                                                ForwardIterator last,
+                                                forward_iterator_tag) {
+  size_type n = 0;
+  distance(first, last, n);
+  create_map_and_nodes(n);
+  __STL_TRY {
+    uninitialized_copy(first, last, start);
+  }
+  __STL_UNWIND(destroy_map_and_nodes());
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+// Called only if finish.cur == finish.last - 1.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t) {
+  value_type t_copy = t;
+  reserve_map_at_back();
+  *(finish.node + 1) = allocate_node();
+  __STL_TRY {
+    construct(finish.cur, t_copy);
+    finish.set_node(finish.node + 1);
+    finish.cur = finish.first;
+  }
+  __STL_UNWIND(deallocate_node(*(finish.node + 1)));
+}
+
+// Called only if start.cur == start.first.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t) {
+  value_type t_copy = t;
+  reserve_map_at_front();
+  *(start.node - 1) = allocate_node();
+  __STL_TRY {
+    start.set_node(start.node - 1);
+    start.cur = start.last - 1;
+    construct(start.cur, t_copy);
+  }
+#     ifdef __STL_USE_EXCEPTIONS
+  catch(...) {
+    start.set_node(start.node + 1);
+    start.cur = start.first;
+    deallocate_node(*(start.node - 1));
+    throw;
+  }
+#     endif /* __STL_USE_EXCEPTIONS */
+} 
+
+// Called only if finish.cur == finish.first.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>:: pop_back_aux() {
+  deallocate_node(finish.first);
+  finish.set_node(finish.node - 1);
+  finish.cur = finish.last - 1;
+  destroy(finish.cur);
+}
+
+// Called only if start.cur == start.last - 1.  Note that if the deque
+//  has at least one element (a necessary precondition for this member
+//  function), and if start.cur == start.last, then the deque must have
+//  at least two nodes.
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::pop_front_aux() {
+  destroy(start.cur);
+  deallocate_node(start.first);
+  start.set_node(start.node + 1);
+  start.cur = start.first;
+}      
+
+#ifdef __STL_MEMBER_TEMPLATES  
+
+template <class T, class Alloc, size_t BufSize>
+template <class InputIterator>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+                                      InputIterator first, InputIterator last,
+                                      input_iterator_tag) {
+  copy(first, last, inserter(*this, pos));
+}
+
+template <class T, class Alloc, size_t BufSize>
+template <class ForwardIterator>
+void deque<T, Alloc, BufSize>::insert(iterator pos,
+                                      ForwardIterator first,
+                                      ForwardIterator last,
+                                      forward_iterator_tag) {
+  size_type n = 0;
+  distance(first, last, n);
+  if (pos.cur == start.cur) {
+    iterator new_start = reserve_elements_at_front(n);
+    __STL_TRY {
+      uninitialized_copy(first, last, new_start);
+      start = new_start;
+    }
+    __STL_UNWIND(destroy_nodes_at_front(new_start));
+  }
+  else if (pos.cur == finish.cur) {
+    iterator new_finish = reserve_elements_at_back(n);
+    __STL_TRY {
+      uninitialized_copy(first, last, finish);
+      finish = new_finish;
+    }
+    __STL_UNWIND(destroy_nodes_at_back(new_finish));
+  }
+  else
+    insert_aux(pos, first, last, n);
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc, size_t BufSize>
+typename deque<T, Alloc, BufSize>::iterator
+deque<T, Alloc, BufSize>::insert_aux(iterator pos, const value_type& x) {
+  difference_type index = pos - start;
+  value_type x_copy = x;
+  if (index < size() / 2) {
+    push_front(front());
+    iterator front1 = start;
+    ++front1;
+    iterator front2 = front1;
+    ++front2;
+    pos = start + index;
+    iterator pos1 = pos;
+    ++pos1;
+    copy(front2, pos1, front1);
+  }
+  else {
+    push_back(back());
+    iterator back1 = finish;
+    --back1;
+    iterator back2 = back1;
+    --back2;
+    pos = start + index;
+    copy_backward(pos, back2, back1);
+  }
+  *pos = x_copy;
+  return pos;
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
+                                          size_type n, const value_type& x) {
+  const difference_type elems_before = pos - start;
+  size_type length = size();
+  value_type x_copy = x;
+  if (elems_before < length / 2) {
+    iterator new_start = reserve_elements_at_front(n);
+    iterator old_start = start;
+    pos = start + elems_before;
+    __STL_TRY {
+      if (elems_before >= difference_type(n)) {
+        iterator start_n = start + difference_type(n);
+        uninitialized_copy(start, start_n, new_start);
+        start = new_start;
+        copy(start_n, pos, old_start);
+        fill(pos - difference_type(n), pos, x_copy);
+      }
+      else {
+        __uninitialized_copy_fill(start, pos, new_start, start, x_copy);
+        start = new_start;
+        fill(old_start, pos, x_copy);
+      }
+    }
+    __STL_UNWIND(destroy_nodes_at_front(new_start));
+  }
+  else {
+    iterator new_finish = reserve_elements_at_back(n);
+    iterator old_finish = finish;
+    const difference_type elems_after = difference_type(length) - elems_before;
+    pos = finish - elems_after;
+    __STL_TRY {
+      if (elems_after > difference_type(n)) {
+        iterator finish_n = finish - difference_type(n);
+        uninitialized_copy(finish_n, finish, finish);
+        finish = new_finish;
+        copy_backward(pos, finish_n, old_finish);
+        fill(pos, pos + difference_type(n), x_copy);
+      }
+      else {
+        __uninitialized_fill_copy(finish, pos + difference_type(n),
+                                  x_copy,
+                                  pos, finish);
+        finish = new_finish;
+        fill(pos, old_finish, x_copy);
+      }
+    }
+    __STL_UNWIND(destroy_nodes_at_back(new_finish));
+  }
+}
+
+#ifdef __STL_MEMBER_TEMPLATES  
+
+template <class T, class Alloc, size_t BufSize>
+template <class ForwardIterator>
+void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
+                                          ForwardIterator first,
+                                          ForwardIterator last,
+                                          size_type n)
+{
+  const difference_type elems_before = pos - start;
+  size_type length = size();
+  if (elems_before < length / 2) {
+    iterator new_start = reserve_elements_at_front(n);
+    iterator old_start = start;
+    pos = start + elems_before;
+    __STL_TRY {
+      if (elems_before >= difference_type(n)) {
+        iterator start_n = start + difference_type(n); 
+        uninitialized_copy(start, start_n, new_start);
+        start = new_start;
+        copy(start_n, pos, old_start);
+        copy(first, last, pos - difference_type(n));
+      }
+      else {
+        ForwardIterator mid = first;
+        advance(mid, difference_type(n) - elems_before);
+        __uninitialized_copy_copy(start, pos, first, mid, new_start);
+        start = new_start;
+        copy(mid, last, old_start);
+      }
+    }
+    __STL_UNWIND(destroy_nodes_at_front(new_start));
+  }
+  else {
+    iterator new_finish = reserve_elements_at_back(n);
+    iterator old_finish = finish;
+    const difference_type elems_after = difference_type(length) - elems_before;
+    pos = finish - elems_after;
+    __STL_TRY {
+      if (elems_after > difference_type(n)) {
+        iterator finish_n = finish - difference_type(n);
+        uninitialized_copy(finish_n, finish, finish);
+        finish = new_finish;
+        copy_backward(pos, finish_n, old_finish);
+        copy(first, last, pos);
+      }
+      else {
+        ForwardIterator mid = first;
+        advance(mid, elems_after);
+        __uninitialized_copy_copy(mid, last, pos, finish, finish);
+        finish = new_finish;
+        copy(first, mid, pos);
+      }
+    }
+    __STL_UNWIND(destroy_nodes_at_back(new_finish));
+  }
+}
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
+                                          const value_type* first,
+                                          const value_type* last,
+                                          size_type n)
+{
+  const difference_type elems_before = pos - start;
+  size_type length = size();
+  if (elems_before < length / 2) {
+    iterator new_start = reserve_elements_at_front(n);
+    iterator old_start = start;
+    pos = start + elems_before;
+    __STL_TRY {
+      if (elems_before >= difference_type(n)) {
+        iterator start_n = start + difference_type(n);
+        uninitialized_copy(start, start_n, new_start);
+        start = new_start;
+        copy(start_n, pos, old_start);
+        copy(first, last, pos - difference_type(n));
+      }
+      else {
+        const value_type* mid = first + (difference_type(n) - elems_before);
+        __uninitialized_copy_copy(start, pos, first, mid, new_start);
+        start = new_start;
+        copy(mid, last, old_start);
+      }
+    }
+    __STL_UNWIND(destroy_nodes_at_front(new_start));
+  }
+  else {
+    iterator new_finish = reserve_elements_at_back(n);
+    iterator old_finish = finish;
+    const difference_type elems_after = difference_type(length) - elems_before;
+    pos = finish - elems_after;
+    __STL_TRY {
+      if (elems_after > difference_type(n)) {
+        iterator finish_n = finish - difference_type(n);
+        uninitialized_copy(finish_n, finish, finish);
+        finish = new_finish;
+        copy_backward(pos, finish_n, old_finish);
+        copy(first, last, pos);
+      }
+      else {
+        const value_type* mid = first + elems_after;
+        __uninitialized_copy_copy(mid, last, pos, finish, finish);
+        finish = new_finish;
+        copy(first, mid, pos);
+      }
+    }
+    __STL_UNWIND(destroy_nodes_at_back(new_finish));
+  }
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
+                                          const_iterator first,
+                                          const_iterator last,
+                                          size_type n)
+{
+  const difference_type elems_before = pos - start;
+  size_type length = size();
+  if (elems_before < length / 2) {
+    iterator new_start = reserve_elements_at_front(n);
+    iterator old_start = start;
+    pos = start + elems_before;
+    __STL_TRY {
+      if (elems_before >= n) {
+        iterator start_n = start + n;
+        uninitialized_copy(start, start_n, new_start);
+        start = new_start;
+        copy(start_n, pos, old_start);
+        copy(first, last, pos - difference_type(n));
+      }
+      else {
+        const_iterator mid = first + (n - elems_before);
+        __uninitialized_copy_copy(start, pos, first, mid, new_start);
+        start = new_start;
+        copy(mid, last, old_start);
+      }
+    }
+    __STL_UNWIND(destroy_nodes_at_front(new_start));
+  }
+  else {
+    iterator new_finish = reserve_elements_at_back(n);
+    iterator old_finish = finish;
+    const difference_type elems_after = length - elems_before;
+    pos = finish - elems_after;
+    __STL_TRY {
+      if (elems_after > n) {
+        iterator finish_n = finish - difference_type(n);
+        uninitialized_copy(finish_n, finish, finish);
+        finish = new_finish;
+        copy_backward(pos, finish_n, old_finish);
+        copy(first, last, pos);
+      }
+      else {
+        const_iterator mid = first + elems_after;
+        __uninitialized_copy_copy(mid, last, pos, finish, finish);
+        finish = new_finish;
+        copy(first, mid, pos);
+      }
+    }
+    __STL_UNWIND(destroy_nodes_at_back(new_finish));
+  }
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::new_elements_at_front(size_type new_elements) {
+  size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size();
+  reserve_map_at_front(new_nodes);
+  size_type i;
+  __STL_TRY {
+    for (i = 1; i <= new_nodes; ++i)
+      *(start.node - i) = allocate_node();
+  }
+#       ifdef __STL_USE_EXCEPTIONS
+  catch(...) {
+    for (size_type j = 1; j < i; ++j)
+      deallocate_node(*(start.node - j));      
+    throw;
+  }
+#       endif /* __STL_USE_EXCEPTIONS */
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::new_elements_at_back(size_type new_elements) {
+  size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size();
+  reserve_map_at_back(new_nodes);
+  size_type i;
+  __STL_TRY {
+    for (i = 1; i <= new_nodes; ++i)
+      *(finish.node + i) = allocate_node();
+  }
+#       ifdef __STL_USE_EXCEPTIONS
+  catch(...) {
+    for (size_type j = 1; j < i; ++j)
+      deallocate_node(*(finish.node + j));      
+    throw;
+  }
+#       endif /* __STL_USE_EXCEPTIONS */
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::destroy_nodes_at_front(iterator before_start) {
+  for (map_pointer n = before_start.node; n < start.node; ++n)
+    deallocate_node(*n);
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::destroy_nodes_at_back(iterator after_finish) {
+  for (map_pointer n = after_finish.node; n > finish.node; --n)
+    deallocate_node(*n);
+}
+
+template <class T, class Alloc, size_t BufSize>
+void deque<T, Alloc, BufSize>::reallocate_map(size_type nodes_to_add,
+                                              bool add_at_front) {
+  size_type old_num_nodes = finish.node - start.node + 1;
+  size_type new_num_nodes = old_num_nodes + nodes_to_add;
+
+  map_pointer new_nstart;
+  if (map_size > 2 * new_num_nodes) {
+    new_nstart = map + (map_size - new_num_nodes) / 2 
+                     + (add_at_front ? nodes_to_add : 0);
+    if (new_nstart < start.node)
+      copy(start.node, finish.node + 1, new_nstart);
+    else
+      copy_backward(start.node, finish.node + 1, new_nstart + old_num_nodes);
+  }
+  else {
+    size_type new_map_size = map_size + max(map_size, nodes_to_add) + 2;
+
+    map_pointer new_map = map_allocator::allocate(new_map_size);
+    new_nstart = new_map + (new_map_size - new_num_nodes) / 2
+                         + (add_at_front ? nodes_to_add : 0);
+    copy(start.node, finish.node + 1, new_nstart);
+    map_allocator::deallocate(map, map_size);
+
+    map = new_map;
+    map_size = new_map_size;
+  }
+
+  start.set_node(new_nstart);
+  finish.set_node(new_nstart + old_num_nodes - 1);
+}
+
+
+// Nonmember functions.
+
+#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
+
+template <class T, class Alloc, size_t BufSiz>
+bool operator==(const deque<T, Alloc, BufSiz>& x,
+                const deque<T, Alloc, BufSiz>& y) {
+  return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
+}
+
+template <class T, class Alloc, size_t BufSiz>
+bool operator<(const deque<T, Alloc, BufSiz>& x,
+               const deque<T, Alloc, BufSiz>& y) {
+  return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
+
+#if defined(__STL_FUNCTION_TMPL_PARTIAL_ORDER) && \
+    !defined(__STL_NON_TYPE_TMPL_PARAM_BUG)
+
+template <class T, class Alloc, size_t BufSiz>
+inline void swap(deque<T, Alloc, BufSiz>& x, deque<T, Alloc, BufSiz>& y) {
+  x.swap(y);
+}
+
+#endif
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+          
+__STL_END_NAMESPACE 
+  
+#endif /* __SGI_STL_INTERNAL_DEQUE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_func.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_func.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_func.h	(revision 18)
@@ -0,0 +1,628 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_FUNCTION_H
+#define __SGI_STL_INTERNAL_FUNCTION_H
+
+__STL_BEGIN_NAMESPACE
+
+template <class Arg, class Result>
+struct unary_function {
+    typedef Arg argument_type;
+    typedef Result result_type;
+};
+
+template <class Arg1, class Arg2, class Result>
+struct binary_function {
+    typedef Arg1 first_argument_type;
+    typedef Arg2 second_argument_type;
+    typedef Result result_type;
+};      
+
+template <class T>
+struct plus : public binary_function<T, T, T> {
+    T operator()(const T& x, const T& y) const { return x + y; }
+};
+
+template <class T>
+struct minus : public binary_function<T, T, T> {
+    T operator()(const T& x, const T& y) const { return x - y; }
+};
+
+template <class T>
+struct multiplies : public binary_function<T, T, T> {
+    T operator()(const T& x, const T& y) const { return x * y; }
+};
+
+template <class T>
+struct divides : public binary_function<T, T, T> {
+    T operator()(const T& x, const T& y) const { return x / y; }
+};
+
+template <class T> inline T identity_element(plus<T>) { return T(0); }
+
+template <class T> inline T identity_element(multiplies<T>) { return T(1); }
+
+template <class T>
+struct modulus : public binary_function<T, T, T> {
+    T operator()(const T& x, const T& y) const { return x % y; }
+};
+
+template <class T>
+struct negate : public unary_function<T, T> {
+    T operator()(const T& x) const { return -x; }
+};
+
+template <class T>
+struct equal_to : public binary_function<T, T, bool> {
+    bool operator()(const T& x, const T& y) const { return x == y; }
+};
+
+template <class T>
+struct not_equal_to : public binary_function<T, T, bool> {
+    bool operator()(const T& x, const T& y) const { return x != y; }
+};
+
+template <class T>
+struct greater : public binary_function<T, T, bool> {
+    bool operator()(const T& x, const T& y) const { return x > y; }
+};
+
+template <class T>
+struct less : public binary_function<T, T, bool> {
+    bool operator()(const T& x, const T& y) const { return x < y; }
+};
+
+template <class T>
+struct greater_equal : public binary_function<T, T, bool> {
+    bool operator()(const T& x, const T& y) const { return x >= y; }
+};
+
+template <class T>
+struct less_equal : public binary_function<T, T, bool> {
+    bool operator()(const T& x, const T& y) const { return x <= y; }
+};
+
+template <class T>
+struct logical_and : public binary_function<T, T, bool> {
+    bool operator()(const T& x, const T& y) const { return x && y; }
+};
+
+template <class T>
+struct logical_or : public binary_function<T, T, bool> {
+    bool operator()(const T& x, const T& y) const { return x || y; }
+};
+
+template <class T>
+struct logical_not : public unary_function<T, bool> {
+    bool operator()(const T& x) const { return !x; }
+};
+
+template <class Predicate>
+class unary_negate
+  : public unary_function<typename Predicate::argument_type, bool> {
+protected:
+  Predicate pred;
+public:
+  explicit unary_negate(const Predicate& x) : pred(x) {}
+  bool operator()(const typename Predicate::argument_type& x) const {
+    return !pred(x);
+  }
+};
+
+template <class Predicate>
+inline unary_negate<Predicate> not1(const Predicate& pred) {
+  return unary_negate<Predicate>(pred);
+}
+
+template <class Predicate> 
+class binary_negate 
+  : public binary_function<typename Predicate::first_argument_type,
+                           typename Predicate::second_argument_type,
+                           bool> {
+protected:
+  Predicate pred;
+public:
+  explicit binary_negate(const Predicate& x) : pred(x) {}
+  bool operator()(const typename Predicate::first_argument_type& x, 
+                  const typename Predicate::second_argument_type& y) const {
+    return !pred(x, y); 
+  }
+};
+
+template <class Predicate>
+inline binary_negate<Predicate> not2(const Predicate& pred) {
+  return binary_negate<Predicate>(pred);
+}
+
+template <class Operation> 
+class binder1st
+  : public unary_function<typename Operation::second_argument_type,
+                          typename Operation::result_type> {
+protected:
+  Operation op;
+  typename Operation::first_argument_type value;
+public:
+  binder1st(const Operation& x,
+            const typename Operation::first_argument_type& y)
+      : op(x), value(y) {}
+  typename Operation::result_type
+  operator()(const typename Operation::second_argument_type& x) const {
+    return op(value, x); 
+  }
+};
+
+template <class Operation, class T>
+inline binder1st<Operation> bind1st(const Operation& op, const T& x) {
+  typedef typename Operation::first_argument_type arg1_type;
+  return binder1st<Operation>(op, arg1_type(x));
+}
+
+template <class Operation> 
+class binder2nd
+  : public unary_function<typename Operation::first_argument_type,
+                          typename Operation::result_type> {
+protected:
+  Operation op;
+  typename Operation::second_argument_type value;
+public:
+  binder2nd(const Operation& x,
+            const typename Operation::second_argument_type& y) 
+      : op(x), value(y) {}
+  typename Operation::result_type
+  operator()(const typename Operation::first_argument_type& x) const {
+    return op(x, value); 
+  }
+};
+
+template <class Operation, class T>
+inline binder2nd<Operation> bind2nd(const Operation& op, const T& x) {
+  typedef typename Operation::second_argument_type arg2_type;
+  return binder2nd<Operation>(op, arg2_type(x));
+}
+
+template <class Operation1, class Operation2>
+class unary_compose : public unary_function<typename Operation2::argument_type,
+                                            typename Operation1::result_type> {
+protected:
+  Operation1 op1;
+  Operation2 op2;
+public:
+  unary_compose(const Operation1& x, const Operation2& y) : op1(x), op2(y) {}
+  typename Operation1::result_type
+  operator()(const typename Operation2::argument_type& x) const {
+    return op1(op2(x));
+  }
+};
+
+template <class Operation1, class Operation2>
+inline unary_compose<Operation1, Operation2> compose1(const Operation1& op1, 
+                                                      const Operation2& op2) {
+  return unary_compose<Operation1, Operation2>(op1, op2);
+}
+
+template <class Operation1, class Operation2, class Operation3>
+class binary_compose
+  : public unary_function<typename Operation2::argument_type,
+                          typename Operation1::result_type> {
+protected:
+  Operation1 op1;
+  Operation2 op2;
+  Operation3 op3;
+public:
+  binary_compose(const Operation1& x, const Operation2& y, 
+                 const Operation3& z) : op1(x), op2(y), op3(z) { }
+  typename Operation1::result_type
+  operator()(const typename Operation2::argument_type& x) const {
+    return op1(op2(x), op3(x));
+  }
+};
+
+template <class Operation1, class Operation2, class Operation3>
+inline binary_compose<Operation1, Operation2, Operation3> 
+compose2(const Operation1& op1, const Operation2& op2, const Operation3& op3) {
+  return binary_compose<Operation1, Operation2, Operation3>(op1, op2, op3);
+}
+
+template <class Arg, class Result>
+class pointer_to_unary_function : public unary_function<Arg, Result> {
+protected:
+  Result (*ptr)(Arg);
+public:
+  pointer_to_unary_function() {}
+  explicit pointer_to_unary_function(Result (*x)(Arg)) : ptr(x) {}
+  Result operator()(Arg x) const { return ptr(x); }
+};
+
+template <class Arg, class Result>
+inline pointer_to_unary_function<Arg, Result> ptr_fun(Result (*x)(Arg)) {
+  return pointer_to_unary_function<Arg, Result>(x);
+}
+
+template <class Arg1, class Arg2, class Result>
+class pointer_to_binary_function : public binary_function<Arg1, Arg2, Result> {
+protected:
+    Result (*ptr)(Arg1, Arg2);
+public:
+    pointer_to_binary_function() {}
+    explicit pointer_to_binary_function(Result (*x)(Arg1, Arg2)) : ptr(x) {}
+    Result operator()(Arg1 x, Arg2 y) const { return ptr(x, y); }
+};
+
+template <class Arg1, class Arg2, class Result>
+inline pointer_to_binary_function<Arg1, Arg2, Result> 
+ptr_fun(Result (*x)(Arg1, Arg2)) {
+  return pointer_to_binary_function<Arg1, Arg2, Result>(x);
+}
+
+template <class T>
+struct identity : public unary_function<T, T> {
+  const T& operator()(const T& x) const { return x; }
+};
+
+template <class Pair>
+struct select1st : public unary_function<Pair, typename Pair::first_type> {
+  const typename Pair::first_type& operator()(const Pair& x) const
+  {
+    return x.first;
+  }
+};
+
+template <class Pair>
+struct select2nd : public unary_function<Pair, typename Pair::second_type> {
+  const typename Pair::second_type& operator()(const Pair& x) const
+  {
+    return x.second;
+  }
+};
+
+template <class Arg1, class Arg2>
+struct project1st : public binary_function<Arg1, Arg2, Arg1> {
+  Arg1 operator()(const Arg1& x, const Arg2&) const { return x; }
+};
+
+template <class Arg1, class Arg2>
+struct project2nd : public binary_function<Arg1, Arg2, Arg2> {
+  Arg2 operator()(const Arg1&, const Arg2& y) const { return y; }
+};
+
+template <class Result>
+struct constant_void_fun
+{
+  typedef Result result_type;
+  result_type val;
+  constant_void_fun(const result_type& v) : val(v) {}
+  const result_type& operator()() const { return val; }
+};  
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Result, class Argument = Result>
+#else
+template <class Result, class Argument>
+#endif
+struct constant_unary_fun : public unary_function<Argument, Result> {
+  Result val;
+  constant_unary_fun(const Result& v) : val(v) {}
+  const Result& operator()(const Argument&) const { return val; }
+};
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Result, class Arg1 = Result, class Arg2 = Arg1>
+#else
+template <class Result, class Arg1, class Arg2>
+#endif
+struct constant_binary_fun : public binary_function<Arg1, Arg2, Result> {
+  Result val;
+  constant_binary_fun(const Result& v) : val(v) {}
+  const Result& operator()(const Arg1&, const Arg2&) const {
+    return val;
+  }
+};
+
+template <class Result>
+inline constant_void_fun<Result> constant0(const Result& val)
+{
+  return constant_void_fun<Result>(val);
+}
+
+template <class Result>
+inline constant_unary_fun<Result,Result> constant1(const Result& val)
+{
+  return constant_unary_fun<Result,Result>(val);
+}
+
+template <class Result>
+inline constant_binary_fun<Result,Result,Result> constant2(const Result& val)
+{
+  return constant_binary_fun<Result,Result,Result>(val);
+}
+
+// Note: this code assumes that int is 32 bits.
+class subtractive_rng : public unary_function<unsigned int, unsigned int> {
+private:
+  unsigned int table[55];
+  size_t index1;
+  size_t index2;
+public:
+  unsigned int operator()(unsigned int limit) {
+    index1 = (index1 + 1) % 55;
+    index2 = (index2 + 1) % 55;
+    table[index1] = table[index1] - table[index2];
+    return table[index1] % limit;
+  }
+
+  void initialize(unsigned int seed)
+  {
+    unsigned int k = 1;
+    table[54] = seed;
+    size_t i;
+    for (i = 0; i < 54; i++) {
+        size_t ii = (21 * (i + 1) % 55) - 1;
+        table[ii] = k;
+        k = seed - k;
+        seed = table[ii];
+    }
+    for (int loop = 0; loop < 4; loop++) {
+        for (i = 0; i < 55; i++)
+            table[i] = table[i] - table[(1 + i + 30) % 55];
+    }
+    index1 = 0;
+    index2 = 31;
+  }
+
+  subtractive_rng(unsigned int seed) { initialize(seed); }
+  subtractive_rng() { initialize(161803398u); }
+};
+
+
+// Adaptor function objects: pointers to member functions.
+
+// There are a total of 16 = 2^4 function objects in this family.
+//  (1) Member functions taking no arguments vs member functions taking
+//       one argument.
+//  (2) Call through pointer vs call through reference.
+//  (3) Member function with void return type vs member function with
+//      non-void return type.
+//  (4) Const vs non-const member function.
+
+// Note that choice (4) is not present in the 8/97 draft C++ standard, 
+//  which only allows these adaptors to be used with non-const functions.
+//  This is likely to be recified before the standard becomes final.
+// Note also that choice (3) is nothing more than a workaround: according
+//  to the draft, compilers should handle void and non-void the same way.
+//  This feature is not yet widely implemented, though.  You can only use
+//  member functions returning void if your compiler supports partial
+//  specialization.
+
+// All of this complexity is in the function objects themselves.  You can
+//  ignore it by using the helper function mem_fun, mem_fun_ref,
+//  mem_fun1, and mem_fun1_ref, which create whichever type of adaptor
+//  is appropriate.
+
+
+template <class S, class T>
+class mem_fun_t : public unary_function<T*, S> {
+public:
+  explicit mem_fun_t(S (T::*pf)()) : f(pf) {}
+  S operator()(T* p) const { return (p->*f)(); }
+private:
+  S (T::*f)();
+};
+
+template <class S, class T>
+class const_mem_fun_t : public unary_function<const T*, S> {
+public:
+  explicit const_mem_fun_t(S (T::*pf)() const) : f(pf) {}
+  S operator()(const T* p) const { return (p->*f)(); }
+private:
+  S (T::*f)() const;
+};
+
+
+template <class S, class T>
+class mem_fun_ref_t : public unary_function<T, S> {
+public:
+  explicit mem_fun_ref_t(S (T::*pf)()) : f(pf) {}
+  S operator()(T& r) const { return (r.*f)(); }
+private:
+  S (T::*f)();
+};
+
+template <class S, class T>
+class const_mem_fun_ref_t : public unary_function<T, S> {
+public:
+  explicit const_mem_fun_ref_t(S (T::*pf)() const) : f(pf) {}
+  S operator()(const T& r) const { return (r.*f)(); }
+private:
+  S (T::*f)() const;
+};
+
+template <class S, class T, class A>
+class mem_fun1_t : public binary_function<T*, A, S> {
+public:
+  explicit mem_fun1_t(S (T::*pf)(A)) : f(pf) {}
+  S operator()(T* p, A x) const { return (p->*f)(x); }
+private:
+  S (T::*f)(A);
+};
+
+template <class S, class T, class A>
+class const_mem_fun1_t : public binary_function<const T*, A, S> {
+public:
+  explicit const_mem_fun1_t(S (T::*pf)(A) const) : f(pf) {}
+  S operator()(const T* p, A x) const { return (p->*f)(x); }
+private:
+  S (T::*f)(A) const;
+};
+
+template <class S, class T, class A>
+class mem_fun1_ref_t : public binary_function<T, A, S> {
+public:
+  explicit mem_fun1_ref_t(S (T::*pf)(A)) : f(pf) {}
+  S operator()(T& r, A x) const { return (r.*f)(x); }
+private:
+  S (T::*f)(A);
+};
+
+template <class S, class T, class A>
+class const_mem_fun1_ref_t : public binary_function<T, A, S> {
+public:
+  explicit const_mem_fun1_ref_t(S (T::*pf)(A) const) : f(pf) {}
+  S operator()(const T& r, A x) const { return (r.*f)(x); }
+private:
+  S (T::*f)(A) const;
+};
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class T>
+class mem_fun_t<void, T> : public unary_function<T*, void> {
+public:
+  explicit mem_fun_t(void (T::*pf)()) : f(pf) {}
+  void operator()(T* p) const { (p->*f)(); }
+private:
+  void (T::*f)();
+};
+
+template <class T>
+class const_mem_fun_t<void, T> : public unary_function<const T*, void> {
+public:
+  explicit const_mem_fun_t(void (T::*pf)() const) : f(pf) {}
+  void operator()(const T* p) const { (p->*f)(); }
+private:
+  void (T::*f)() const;
+};
+
+template <class T>
+class mem_fun_ref_t<void, T> : public unary_function<T, void> {
+public:
+  explicit mem_fun_ref_t(void (T::*pf)()) : f(pf) {}
+  void operator()(T& r) const { (r.*f)(); }
+private:
+  void (T::*f)();
+};
+
+template <class T>
+class const_mem_fun_ref_t<void, T> : public unary_function<T, void> {
+public:
+  explicit const_mem_fun_ref_t(void (T::*pf)() const) : f(pf) {}
+  void operator()(const T& r) const { (r.*f)(); }
+private:
+  void (T::*f)() const;
+};
+
+template <class T, class A>
+class mem_fun1_t<void, T, A> : public binary_function<T*, A, void> {
+public:
+  explicit mem_fun1_t(void (T::*pf)(A)) : f(pf) {}
+  void operator()(T* p, A x) const { (p->*f)(x); }
+private:
+  void (T::*f)(A);
+};
+
+template <class T, class A>
+class const_mem_fun1_t<void, T, A> : public binary_function<const T*, A, void> {
+public:
+  explicit const_mem_fun1_t(void (T::*pf)(A) const) : f(pf) {}
+  void operator()(const T* p, A x) const { (p->*f)(x); }
+private:
+  void (T::*f)(A) const;
+};
+
+template <class T, class A>
+class mem_fun1_ref_t<void, T, A> : public binary_function<T, A, void> {
+public:
+  explicit mem_fun1_ref_t(void (T::*pf)(A)) : f(pf) {}
+  void operator()(T& r, A x) const { (r.*f)(x); }
+private:
+  void (T::*f)(A);
+};
+
+template <class T, class A>
+class const_mem_fun1_ref_t<void, T, A> : public binary_function<T, A, void> {
+public:
+  explicit const_mem_fun1_ref_t(void (T::*pf)(A) const) : f(pf) {}
+  void operator()(const T& r, A x) const { (r.*f)(x); }
+private:
+  void (T::*f)(A) const;
+};
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+// Mem_fun adaptor helper functions.  There are only four:
+//  mem_fun, mem_fun_ref, mem_fun1, mem_fun1_ref.
+
+template <class S, class T>
+inline mem_fun_t<S,T> mem_fun(S (T::*f)()) { 
+  return mem_fun_t<S,T>(f);
+}
+
+template <class S, class T>
+inline const_mem_fun_t<S,T> mem_fun(S (T::*f)() const) {
+  return const_mem_fun_t<S,T>(f);
+}
+
+template <class S, class T>
+inline mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)()) { 
+  return mem_fun_ref_t<S,T>(f);
+}
+
+template <class S, class T>
+inline const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const) {
+  return const_mem_fun_ref_t<S,T>(f);
+}
+
+template <class S, class T, class A>
+inline mem_fun1_t<S,T,A> mem_fun1(S (T::*f)(A)) { 
+  return mem_fun1_t<S,T,A>(f);
+}
+
+template <class S, class T, class A>
+inline const_mem_fun1_t<S,T,A> mem_fun1(S (T::*f)(A) const) {
+  return const_mem_fun1_t<S,T,A>(f);
+}
+
+template <class S, class T, class A>
+inline mem_fun1_ref_t<S,T,A> mem_fun1_ref(S (T::*f)(A)) { 
+  return mem_fun1_ref_t<S,T,A>(f);
+}
+
+template <class S, class T, class A>
+inline const_mem_fun1_ref_t<S,T,A> mem_fun1_ref(S (T::*f)(A) const) {
+  return const_mem_fun1_ref_t<S,T,A>(f);
+}
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_FUNCTION_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_heap.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_heap.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_heap.h	(revision 18)
@@ -0,0 +1,226 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_HEAP_H
+#define __SGI_STL_INTERNAL_HEAP_H
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1209
+#endif
+
+template <class RandomAccessIterator, class Distance, class T>
+void __push_heap(RandomAccessIterator first, Distance holeIndex,
+                 Distance topIndex, T value) {
+  Distance parent = (holeIndex - 1) / 2;
+  while (holeIndex > topIndex && *(first + parent) < value) {
+    *(first + holeIndex) = *(first + parent);
+    holeIndex = parent;
+    parent = (holeIndex - 1) / 2;
+  }    
+  *(first + holeIndex) = value;
+}
+
+template <class RandomAccessIterator, class Distance, class T>
+inline void __push_heap_aux(RandomAccessIterator first,
+                            RandomAccessIterator last, Distance*, T*) {
+  __push_heap(first, Distance((last - first) - 1), Distance(0), 
+              T(*(last - 1)));
+}
+
+template <class RandomAccessIterator>
+inline void push_heap(RandomAccessIterator first, RandomAccessIterator last) {
+  __push_heap_aux(first, last, distance_type(first), value_type(first));
+}
+
+template <class RandomAccessIterator, class Distance, class T, class Compare>
+void __push_heap(RandomAccessIterator first, Distance holeIndex,
+                 Distance topIndex, T value, Compare comp) {
+  Distance parent = (holeIndex - 1) / 2;
+  while (holeIndex > topIndex && comp(*(first + parent), value)) {
+    *(first + holeIndex) = *(first + parent);
+    holeIndex = parent;
+    parent = (holeIndex - 1) / 2;
+  }
+  *(first + holeIndex) = value;
+}
+
+template <class RandomAccessIterator, class Compare, class Distance, class T>
+inline void __push_heap_aux(RandomAccessIterator first,
+                            RandomAccessIterator last, Compare comp,
+                            Distance*, T*) {
+  __push_heap(first, Distance((last - first) - 1), Distance(0), 
+              T(*(last - 1)), comp);
+}
+
+template <class RandomAccessIterator, class Compare>
+inline void push_heap(RandomAccessIterator first, RandomAccessIterator last,
+                      Compare comp) {
+  __push_heap_aux(first, last, comp, distance_type(first), value_type(first));
+}
+
+template <class RandomAccessIterator, class Distance, class T>
+void __adjust_heap(RandomAccessIterator first, Distance holeIndex,
+                   Distance len, T value) {
+  Distance topIndex = holeIndex;
+  Distance secondChild = 2 * holeIndex + 2;
+  while (secondChild < len) {
+    if (*(first + secondChild) < *(first + (secondChild - 1)))
+      secondChild--;
+    *(first + holeIndex) = *(first + secondChild);
+    holeIndex = secondChild;
+    secondChild = 2 * (secondChild + 1);
+  }
+  if (secondChild == len) {
+    *(first + holeIndex) = *(first + (secondChild - 1));
+    holeIndex = secondChild - 1;
+  }
+  __push_heap(first, holeIndex, topIndex, value);
+}
+
+template <class RandomAccessIterator, class T, class Distance>
+inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last,
+                       RandomAccessIterator result, T value, Distance*) {
+  *result = *first;
+  __adjust_heap(first, Distance(0), Distance(last - first), value);
+}
+
+template <class RandomAccessIterator, class T>
+inline void __pop_heap_aux(RandomAccessIterator first,
+                           RandomAccessIterator last, T*) {
+  __pop_heap(first, last - 1, last - 1, T(*(last - 1)), distance_type(first));
+}
+
+template <class RandomAccessIterator>
+inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last) {
+  __pop_heap_aux(first, last, value_type(first));
+}
+
+template <class RandomAccessIterator, class Distance, class T, class Compare>
+void __adjust_heap(RandomAccessIterator first, Distance holeIndex,
+                   Distance len, T value, Compare comp) {
+  Distance topIndex = holeIndex;
+  Distance secondChild = 2 * holeIndex + 2;
+  while (secondChild < len) {
+    if (comp(*(first + secondChild), *(first + (secondChild - 1))))
+      secondChild--;
+    *(first + holeIndex) = *(first + secondChild);
+    holeIndex = secondChild;
+    secondChild = 2 * (secondChild + 1);
+  }
+  if (secondChild == len) {
+    *(first + holeIndex) = *(first + (secondChild - 1));
+    holeIndex = secondChild - 1;
+  }
+  __push_heap(first, holeIndex, topIndex, value, comp);
+}
+
+template <class RandomAccessIterator, class T, class Compare, class Distance>
+inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last,
+                       RandomAccessIterator result, T value, Compare comp,
+                       Distance*) {
+  *result = *first;
+  __adjust_heap(first, Distance(0), Distance(last - first), value, comp);
+}
+
+template <class RandomAccessIterator, class T, class Compare>
+inline void __pop_heap_aux(RandomAccessIterator first,
+                           RandomAccessIterator last, T*, Compare comp) {
+  __pop_heap(first, last - 1, last - 1, T(*(last - 1)), comp,
+             distance_type(first));
+}
+
+template <class RandomAccessIterator, class Compare>
+inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last,
+                     Compare comp) {
+    __pop_heap_aux(first, last, value_type(first), comp);
+}
+
+template <class RandomAccessIterator, class T, class Distance>
+void __make_heap(RandomAccessIterator first, RandomAccessIterator last, T*,
+                 Distance*) {
+  if (last - first < 2) return;
+  Distance len = last - first;
+  Distance parent = (len - 2)/2;
+    
+  while (true) {
+    __adjust_heap(first, parent, len, T(*(first + parent)));
+    if (parent == 0) return;
+    parent--;
+  }
+}
+
+template <class RandomAccessIterator>
+inline void make_heap(RandomAccessIterator first, RandomAccessIterator last) {
+  __make_heap(first, last, value_type(first), distance_type(first));
+}
+
+template <class RandomAccessIterator, class Compare, class T, class Distance>
+void __make_heap(RandomAccessIterator first, RandomAccessIterator last,
+                 Compare comp, T*, Distance*) {
+  if (last - first < 2) return;
+  Distance len = last - first;
+  Distance parent = (len - 2)/2;
+    
+  while (true) {
+    __adjust_heap(first, parent, len, T(*(first + parent)), comp);
+    if (parent == 0) return;
+    parent--;
+  }
+}
+
+template <class RandomAccessIterator, class Compare>
+inline void make_heap(RandomAccessIterator first, RandomAccessIterator last,
+                      Compare comp) {
+  __make_heap(first, last, comp, value_type(first), distance_type(first));
+}
+
+template <class RandomAccessIterator>
+void sort_heap(RandomAccessIterator first, RandomAccessIterator last) {
+  while (last - first > 1) pop_heap(first, last--);
+}
+
+template <class RandomAccessIterator, class Compare>
+void sort_heap(RandomAccessIterator first, RandomAccessIterator last,
+               Compare comp) {
+  while (last - first > 1) pop_heap(first, last--, comp);
+}
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1209
+#endif
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_HEAP_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_hfun.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_hfun.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_hfun.h	(revision 18)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_HASH_FUN_H
+#define __SGI_STL_HASH_FUN_H
+
+#include <stddef.h>
+
+__STL_BEGIN_NAMESPACE
+
+template <class Key> struct hash { };
+
+inline size_t __stl_hash_string(const char* s)
+{
+  unsigned long h = 0; 
+  for ( ; *s; ++s)
+    h = 5*h + *s;
+  
+  return size_t(h);
+}
+
+__STL_TEMPLATE_NULL struct hash<char*>
+{
+  size_t operator()(const char* s) const { return __stl_hash_string(s); }
+};
+
+__STL_TEMPLATE_NULL struct hash<const char*>
+{
+  size_t operator()(const char* s) const { return __stl_hash_string(s); }
+};
+
+__STL_TEMPLATE_NULL struct hash<char> {
+  size_t operator()(char x) const { return x; }
+};
+__STL_TEMPLATE_NULL struct hash<unsigned char> {
+  size_t operator()(unsigned char x) const { return x; }
+};
+__STL_TEMPLATE_NULL struct hash<signed char> {
+  size_t operator()(unsigned char x) const { return x; }
+};
+__STL_TEMPLATE_NULL struct hash<short> {
+  size_t operator()(short x) const { return x; }
+};
+__STL_TEMPLATE_NULL struct hash<unsigned short> {
+  size_t operator()(unsigned short x) const { return x; }
+};
+__STL_TEMPLATE_NULL struct hash<int> {
+  size_t operator()(int x) const { return x; }
+};
+__STL_TEMPLATE_NULL struct hash<unsigned int> {
+  size_t operator()(unsigned int x) const { return x; }
+};
+__STL_TEMPLATE_NULL struct hash<long> {
+  size_t operator()(long x) const { return x; }
+};
+__STL_TEMPLATE_NULL struct hash<unsigned long> {
+  size_t operator()(unsigned long x) const { return x; }
+};
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_HASH_FUN_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_hmap.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_hmap.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_hmap.h	(revision 18)
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_HASH_MAP_H
+#define __SGI_STL_INTERNAL_HASH_MAP_H
+
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Key, class T, class HashFcn = hash<Key>,
+          class EqualKey = equal_to<Key>,
+          class Alloc = alloc>
+#else
+template <class Key, class T, class HashFcn, class EqualKey, 
+          class Alloc = alloc>
+#endif
+class hash_map
+{
+private:
+  typedef hashtable<pair<const Key, T>, Key, HashFcn,
+                    select1st<pair<const Key, T> >, EqualKey, Alloc> ht;
+  ht rep;
+
+public:
+  typedef typename ht::key_type key_type;
+  typedef T data_type;
+  typedef T mapped_type;
+  typedef typename ht::value_type value_type;
+  typedef typename ht::hasher hasher;
+  typedef typename ht::key_equal key_equal;
+
+  typedef typename ht::size_type size_type;
+  typedef typename ht::difference_type difference_type;
+  typedef typename ht::pointer pointer;
+  typedef typename ht::const_pointer const_pointer;
+  typedef typename ht::reference reference;
+  typedef typename ht::const_reference const_reference;
+
+  typedef typename ht::iterator iterator;
+  typedef typename ht::const_iterator const_iterator;
+
+  hasher hash_funct() const { return rep.hash_funct(); }
+  key_equal key_eq() const { return rep.key_eq(); }
+
+public:
+  hash_map() : rep(100, hasher(), key_equal()) {}
+  explicit hash_map(size_type n) : rep(n, hasher(), key_equal()) {}
+  hash_map(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {}
+  hash_map(size_type n, const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  hash_map(InputIterator f, InputIterator l)
+    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  template <class InputIterator>
+  hash_map(InputIterator f, InputIterator l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  template <class InputIterator>
+  hash_map(InputIterator f, InputIterator l, size_type n,
+           const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
+  template <class InputIterator>
+  hash_map(InputIterator f, InputIterator l, size_type n,
+           const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_unique(f, l); }
+
+#else
+  hash_map(const value_type* f, const value_type* l)
+    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  hash_map(const value_type* f, const value_type* l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  hash_map(const value_type* f, const value_type* l, size_type n,
+           const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
+  hash_map(const value_type* f, const value_type* l, size_type n,
+           const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_unique(f, l); }
+
+  hash_map(const_iterator f, const_iterator l)
+    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  hash_map(const_iterator f, const_iterator l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  hash_map(const_iterator f, const_iterator l, size_type n,
+           const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
+  hash_map(const_iterator f, const_iterator l, size_type n,
+           const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_unique(f, l); }
+#endif /*__STL_MEMBER_TEMPLATES */
+
+public:
+  size_type size() const { return rep.size(); }
+  size_type max_size() const { return rep.max_size(); }
+  bool empty() const { return rep.empty(); }
+  void swap(hash_map& hs) { rep.swap(hs.rep); }
+  friend bool
+  operator== __STL_NULL_TMPL_ARGS (const hash_map&, const hash_map&);
+
+  iterator begin() { return rep.begin(); }
+  iterator end() { return rep.end(); }
+  const_iterator begin() const { return rep.begin(); }
+  const_iterator end() const { return rep.end(); }
+
+public:
+  pair<iterator, bool> insert(const value_type& obj)
+    { return rep.insert_unique(obj); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert(InputIterator f, InputIterator l) { rep.insert_unique(f,l); }
+#else
+  void insert(const value_type* f, const value_type* l) {
+    rep.insert_unique(f,l);
+  }
+  void insert(const_iterator f, const_iterator l) { rep.insert_unique(f, l); }
+#endif /*__STL_MEMBER_TEMPLATES */
+  pair<iterator, bool> insert_noresize(const value_type& obj)
+    { return rep.insert_unique_noresize(obj); }    
+
+  iterator find(const key_type& key) { return rep.find(key); }
+  const_iterator find(const key_type& key) const { return rep.find(key); }
+
+  T& operator[](const key_type& key) {
+    return rep.find_or_insert(value_type(key, T())).second;
+  }
+
+  size_type count(const key_type& key) const { return rep.count(key); }
+  
+  pair<iterator, iterator> equal_range(const key_type& key)
+    { return rep.equal_range(key); }
+  pair<const_iterator, const_iterator> equal_range(const key_type& key) const
+    { return rep.equal_range(key); }
+
+  size_type erase(const key_type& key) {return rep.erase(key); }
+  void erase(iterator it) { rep.erase(it); }
+  void erase(iterator f, iterator l) { rep.erase(f, l); }
+  void clear() { rep.clear(); }
+
+public:
+  void resize(size_type hint) { rep.resize(hint); }
+  size_type bucket_count() const { return rep.bucket_count(); }
+  size_type max_bucket_count() const { return rep.max_bucket_count(); }
+  size_type elems_in_bucket(size_type n) const
+    { return rep.elems_in_bucket(n); }
+};
+
+template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
+inline bool operator==(const hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1,
+                       const hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2)
+{
+  return hm1.rep == hm2.rep;
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
+inline void swap(hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1,
+                 hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2)
+{
+  hm1.swap(hm2);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Key, class T, class HashFcn = hash<Key>,
+          class EqualKey = equal_to<Key>,
+          class Alloc = alloc>
+#else
+template <class Key, class T, class HashFcn, class EqualKey,
+          class Alloc = alloc>
+#endif
+class hash_multimap
+{
+private:
+  typedef hashtable<pair<const Key, T>, Key, HashFcn,
+                    select1st<pair<const Key, T> >, EqualKey, Alloc> ht;
+  ht rep;
+
+public:
+  typedef typename ht::key_type key_type;
+  typedef T data_type;
+  typedef T mapped_type;
+  typedef typename ht::value_type value_type;
+  typedef typename ht::hasher hasher;
+  typedef typename ht::key_equal key_equal;
+
+  typedef typename ht::size_type size_type;
+  typedef typename ht::difference_type difference_type;
+  typedef typename ht::pointer pointer;
+  typedef typename ht::const_pointer const_pointer;
+  typedef typename ht::reference reference;
+  typedef typename ht::const_reference const_reference;
+
+  typedef typename ht::iterator iterator;
+  typedef typename ht::const_iterator const_iterator;
+
+  hasher hash_funct() const { return rep.hash_funct(); }
+  key_equal key_eq() const { return rep.key_eq(); }
+
+public:
+  hash_multimap() : rep(100, hasher(), key_equal()) {}
+  explicit hash_multimap(size_type n) : rep(n, hasher(), key_equal()) {}
+  hash_multimap(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {}
+  hash_multimap(size_type n, const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  hash_multimap(InputIterator f, InputIterator l)
+    : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  template <class InputIterator>
+  hash_multimap(InputIterator f, InputIterator l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  template <class InputIterator>
+  hash_multimap(InputIterator f, InputIterator l, size_type n,
+                const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
+  template <class InputIterator>
+  hash_multimap(InputIterator f, InputIterator l, size_type n,
+                const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_equal(f, l); }
+
+#else
+  hash_multimap(const value_type* f, const value_type* l)
+    : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  hash_multimap(const value_type* f, const value_type* l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  hash_multimap(const value_type* f, const value_type* l, size_type n,
+                const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
+  hash_multimap(const value_type* f, const value_type* l, size_type n,
+                const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_equal(f, l); }
+
+  hash_multimap(const_iterator f, const_iterator l)
+    : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  hash_multimap(const_iterator f, const_iterator l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  hash_multimap(const_iterator f, const_iterator l, size_type n,
+                const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
+  hash_multimap(const_iterator f, const_iterator l, size_type n,
+                const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_equal(f, l); }
+#endif /*__STL_MEMBER_TEMPLATES */
+
+public:
+  size_type size() const { return rep.size(); }
+  size_type max_size() const { return rep.max_size(); }
+  bool empty() const { return rep.empty(); }
+  void swap(hash_multimap& hs) { rep.swap(hs.rep); }
+  friend bool
+  operator== __STL_NULL_TMPL_ARGS (const hash_multimap&, const hash_multimap&);
+
+  iterator begin() { return rep.begin(); }
+  iterator end() { return rep.end(); }
+  const_iterator begin() const { return rep.begin(); }
+  const_iterator end() const { return rep.end(); }
+
+public:
+  iterator insert(const value_type& obj) { return rep.insert_equal(obj); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert(InputIterator f, InputIterator l) { rep.insert_equal(f,l); }
+#else
+  void insert(const value_type* f, const value_type* l) {
+    rep.insert_equal(f,l);
+  }
+  void insert(const_iterator f, const_iterator l) { rep.insert_equal(f, l); }
+#endif /*__STL_MEMBER_TEMPLATES */
+  iterator insert_noresize(const value_type& obj)
+    { return rep.insert_equal_noresize(obj); }    
+
+  iterator find(const key_type& key) { return rep.find(key); }
+  const_iterator find(const key_type& key) const { return rep.find(key); }
+
+  size_type count(const key_type& key) const { return rep.count(key); }
+  
+  pair<iterator, iterator> equal_range(const key_type& key)
+    { return rep.equal_range(key); }
+  pair<const_iterator, const_iterator> equal_range(const key_type& key) const
+    { return rep.equal_range(key); }
+
+  size_type erase(const key_type& key) {return rep.erase(key); }
+  void erase(iterator it) { rep.erase(it); }
+  void erase(iterator f, iterator l) { rep.erase(f, l); }
+  void clear() { rep.clear(); }
+
+public:
+  void resize(size_type hint) { rep.resize(hint); }
+  size_type bucket_count() const { return rep.bucket_count(); }
+  size_type max_bucket_count() const { return rep.max_bucket_count(); }
+  size_type elems_in_bucket(size_type n) const
+    { return rep.elems_in_bucket(n); }
+};
+
+template <class Key, class T, class HF, class EqKey, class Alloc>
+inline bool operator==(const hash_multimap<Key, T, HF, EqKey, Alloc>& hm1,
+                       const hash_multimap<Key, T, HF, EqKey, Alloc>& hm2)
+{
+  return hm1.rep == hm2.rep;
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
+inline void swap(hash_multimap<Key, T, HashFcn, EqualKey, Alloc>& hm1,
+                 hash_multimap<Key, T, HashFcn, EqualKey, Alloc>& hm2)
+{
+  hm1.swap(hm2);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_HASH_MAP_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_hset.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_hset.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_hset.h	(revision 18)
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_HASH_SET_H
+#define __SGI_STL_INTERNAL_HASH_SET_H
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Value, class HashFcn = hash<Value>,
+          class EqualKey = equal_to<Value>,
+          class Alloc = alloc>
+#else
+template <class Value, class HashFcn, class EqualKey, class Alloc = alloc>
+#endif
+class hash_set
+{
+private:
+  typedef hashtable<Value, Value, HashFcn, identity<Value>, 
+                    EqualKey, Alloc> ht;
+  ht rep;
+
+public:
+  typedef typename ht::key_type key_type;
+  typedef typename ht::value_type value_type;
+  typedef typename ht::hasher hasher;
+  typedef typename ht::key_equal key_equal;
+
+  typedef typename ht::size_type size_type;
+  typedef typename ht::difference_type difference_type;
+  typedef typename ht::const_pointer pointer;
+  typedef typename ht::const_pointer const_pointer;
+  typedef typename ht::const_reference reference;
+  typedef typename ht::const_reference const_reference;
+
+  typedef typename ht::const_iterator iterator;
+  typedef typename ht::const_iterator const_iterator;
+
+  hasher hash_funct() const { return rep.hash_funct(); }
+  key_equal key_eq() const { return rep.key_eq(); }
+
+public:
+  hash_set() : rep(100, hasher(), key_equal()) {}
+  explicit hash_set(size_type n) : rep(n, hasher(), key_equal()) {}
+  hash_set(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {}
+  hash_set(size_type n, const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  hash_set(InputIterator f, InputIterator l)
+    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  template <class InputIterator>
+  hash_set(InputIterator f, InputIterator l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  template <class InputIterator>
+  hash_set(InputIterator f, InputIterator l, size_type n,
+           const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
+  template <class InputIterator>
+  hash_set(InputIterator f, InputIterator l, size_type n,
+           const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_unique(f, l); }
+#else
+
+  hash_set(const value_type* f, const value_type* l)
+    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  hash_set(const value_type* f, const value_type* l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  hash_set(const value_type* f, const value_type* l, size_type n,
+           const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
+  hash_set(const value_type* f, const value_type* l, size_type n,
+           const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_unique(f, l); }
+
+  hash_set(const_iterator f, const_iterator l)
+    : rep(100, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  hash_set(const_iterator f, const_iterator l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_unique(f, l); }
+  hash_set(const_iterator f, const_iterator l, size_type n,
+           const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_unique(f, l); }
+  hash_set(const_iterator f, const_iterator l, size_type n,
+           const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_unique(f, l); }
+#endif /*__STL_MEMBER_TEMPLATES */
+
+public:
+  size_type size() const { return rep.size(); }
+  size_type max_size() const { return rep.max_size(); }
+  bool empty() const { return rep.empty(); }
+  void swap(hash_set& hs) { rep.swap(hs.rep); }
+  friend bool operator== __STL_NULL_TMPL_ARGS (const hash_set&,
+                                               const hash_set&);
+
+  iterator begin() const { return rep.begin(); }
+  iterator end() const { return rep.end(); }
+
+public:
+  pair<iterator, bool> insert(const value_type& obj)
+    {
+      pair<typename ht::iterator, bool> p = rep.insert_unique(obj);
+      return pair<iterator, bool>(p.first, p.second);
+    }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert(InputIterator f, InputIterator l) { rep.insert_unique(f,l); }
+#else
+  void insert(const value_type* f, const value_type* l) {
+    rep.insert_unique(f,l);
+  }
+  void insert(const_iterator f, const_iterator l) {rep.insert_unique(f, l); }
+#endif /*__STL_MEMBER_TEMPLATES */
+  pair<iterator, bool> insert_noresize(const value_type& obj)
+  {
+    pair<typename ht::iterator, bool> p = rep.insert_unique_noresize(obj);
+    return pair<iterator, bool>(p.first, p.second);
+  }
+
+  iterator find(const key_type& key) const { return rep.find(key); }
+
+  size_type count(const key_type& key) const { return rep.count(key); }
+  
+  pair<iterator, iterator> equal_range(const key_type& key) const
+    { return rep.equal_range(key); }
+
+  size_type erase(const key_type& key) {return rep.erase(key); }
+  void erase(iterator it) { rep.erase(it); }
+  void erase(iterator f, iterator l) { rep.erase(f, l); }
+  void clear() { rep.clear(); }
+
+public:
+  void resize(size_type hint) { rep.resize(hint); }
+  size_type bucket_count() const { return rep.bucket_count(); }
+  size_type max_bucket_count() const { return rep.max_bucket_count(); }
+  size_type elems_in_bucket(size_type n) const
+    { return rep.elems_in_bucket(n); }
+};
+
+template <class Value, class HashFcn, class EqualKey, class Alloc>
+inline bool operator==(const hash_set<Value, HashFcn, EqualKey, Alloc>& hs1,
+                       const hash_set<Value, HashFcn, EqualKey, Alloc>& hs2)
+{
+  return hs1.rep == hs2.rep;
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Val, class HashFcn, class EqualKey, class Alloc>
+inline void swap(hash_set<Val, HashFcn, EqualKey, Alloc>& hs1,
+                 hash_set<Val, HashFcn, EqualKey, Alloc>& hs2) {
+  hs1.swap(hs2);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Value, class HashFcn = hash<Value>,
+          class EqualKey = equal_to<Value>,
+          class Alloc = alloc>
+#else
+template <class Value, class HashFcn, class EqualKey, class Alloc = alloc>
+#endif
+class hash_multiset
+{
+private:
+  typedef hashtable<Value, Value, HashFcn, identity<Value>, 
+                    EqualKey, Alloc> ht;
+  ht rep;
+
+public:
+  typedef typename ht::key_type key_type;
+  typedef typename ht::value_type value_type;
+  typedef typename ht::hasher hasher;
+  typedef typename ht::key_equal key_equal;
+
+  typedef typename ht::size_type size_type;
+  typedef typename ht::difference_type difference_type;
+  typedef typename ht::const_pointer pointer;
+  typedef typename ht::const_pointer const_pointer;
+  typedef typename ht::const_reference reference;
+  typedef typename ht::const_reference const_reference;
+
+  typedef typename ht::const_iterator iterator;
+  typedef typename ht::const_iterator const_iterator;
+
+  hasher hash_funct() const { return rep.hash_funct(); }
+  key_equal key_eq() const { return rep.key_eq(); }
+
+public:
+  hash_multiset() : rep(100, hasher(), key_equal()) {}
+  explicit hash_multiset(size_type n) : rep(n, hasher(), key_equal()) {}
+  hash_multiset(size_type n, const hasher& hf) : rep(n, hf, key_equal()) {}
+  hash_multiset(size_type n, const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  hash_multiset(InputIterator f, InputIterator l)
+    : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  template <class InputIterator>
+  hash_multiset(InputIterator f, InputIterator l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  template <class InputIterator>
+  hash_multiset(InputIterator f, InputIterator l, size_type n,
+                const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
+  template <class InputIterator>
+  hash_multiset(InputIterator f, InputIterator l, size_type n,
+                const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_equal(f, l); }
+#else
+
+  hash_multiset(const value_type* f, const value_type* l)
+    : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  hash_multiset(const value_type* f, const value_type* l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  hash_multiset(const value_type* f, const value_type* l, size_type n,
+                const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
+  hash_multiset(const value_type* f, const value_type* l, size_type n,
+                const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_equal(f, l); }
+
+  hash_multiset(const_iterator f, const_iterator l)
+    : rep(100, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  hash_multiset(const_iterator f, const_iterator l, size_type n)
+    : rep(n, hasher(), key_equal()) { rep.insert_equal(f, l); }
+  hash_multiset(const_iterator f, const_iterator l, size_type n,
+                const hasher& hf)
+    : rep(n, hf, key_equal()) { rep.insert_equal(f, l); }
+  hash_multiset(const_iterator f, const_iterator l, size_type n,
+                const hasher& hf, const key_equal& eql)
+    : rep(n, hf, eql) { rep.insert_equal(f, l); }
+#endif /*__STL_MEMBER_TEMPLATES */
+
+public:
+  size_type size() const { return rep.size(); }
+  size_type max_size() const { return rep.max_size(); }
+  bool empty() const { return rep.empty(); }
+  void swap(hash_multiset& hs) { rep.swap(hs.rep); }
+  friend bool operator== __STL_NULL_TMPL_ARGS (const hash_multiset&,
+                                               const hash_multiset&);
+
+  iterator begin() const { return rep.begin(); }
+  iterator end() const { return rep.end(); }
+
+public:
+  iterator insert(const value_type& obj) { return rep.insert_equal(obj); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert(InputIterator f, InputIterator l) { rep.insert_equal(f,l); }
+#else
+  void insert(const value_type* f, const value_type* l) {
+    rep.insert_equal(f,l);
+  }
+  void insert(const_iterator f, const_iterator l) { rep.insert_equal(f, l); }
+#endif /*__STL_MEMBER_TEMPLATES */
+  iterator insert_noresize(const value_type& obj)
+    { return rep.insert_equal_noresize(obj); }    
+
+  iterator find(const key_type& key) const { return rep.find(key); }
+
+  size_type count(const key_type& key) const { return rep.count(key); }
+  
+  pair<iterator, iterator> equal_range(const key_type& key) const
+    { return rep.equal_range(key); }
+
+  size_type erase(const key_type& key) {return rep.erase(key); }
+  void erase(iterator it) { rep.erase(it); }
+  void erase(iterator f, iterator l) { rep.erase(f, l); }
+  void clear() { rep.clear(); }
+
+public:
+  void resize(size_type hint) { rep.resize(hint); }
+  size_type bucket_count() const { return rep.bucket_count(); }
+  size_type max_bucket_count() const { return rep.max_bucket_count(); }
+  size_type elems_in_bucket(size_type n) const
+    { return rep.elems_in_bucket(n); }
+};
+
+template <class Val, class HashFcn, class EqualKey, class Alloc>
+inline bool operator==(const hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs1,
+                       const hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs2)
+{
+  return hs1.rep == hs2.rep;
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Val, class HashFcn, class EqualKey, class Alloc>
+inline void swap(hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs1,
+                 hash_multiset<Val, HashFcn, EqualKey, Alloc>& hs2)
+{
+  hs1.swap(hs2);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_HASH_SET_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_htab.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_htab.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_htab.h	(revision 18)
@@ -0,0 +1,948 @@
+/*
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_HASHTABLE_H
+#define __SGI_STL_INTERNAL_HASHTABLE_H
+
+// Hashtable class, used to implement the hashed associative containers
+// hash_set, hash_map, hash_multiset, and hash_multimap.
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_temp.h>
+#include <stl_algo.h>
+#include <stl_unin.h>
+#include <stl_func.h>
+#include <stl_vect.h>
+#include <stl_hfun.h>
+
+__STL_BEGIN_NAMESPACE
+
+template <class Value>
+struct __hashtable_node
+{
+  __hashtable_node* next;
+  Value val;
+};  
+
+template <class Value, class Key, class HashFcn,
+          class ExtractKey, class EqualKey, class Alloc = alloc>
+class hashtable;
+
+template <class Value, class Key, class HashFcn,
+          class ExtractKey, class EqualKey, class Alloc>
+struct __hashtable_iterator;
+
+template <class Value, class Key, class HashFcn,
+          class ExtractKey, class EqualKey, class Alloc>
+struct __hashtable_const_iterator;
+
+template <class Value, class Key, class HashFcn,
+          class ExtractKey, class EqualKey, class Alloc>
+struct __hashtable_iterator {
+  typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
+          hashtable;
+  typedef __hashtable_iterator<Value, Key, HashFcn, 
+                               ExtractKey, EqualKey, Alloc>
+          iterator;
+  typedef __hashtable_const_iterator<Value, Key, HashFcn, 
+                                     ExtractKey, EqualKey, Alloc>
+          const_iterator;
+  typedef __hashtable_node<Value> node;
+
+  typedef forward_iterator_tag iterator_category;
+  typedef Value value_type;
+  typedef ptrdiff_t difference_type;
+  typedef size_t size_type;
+  typedef Value& reference;
+  typedef Value* pointer;
+
+  node* cur;
+  hashtable* ht;
+
+  __hashtable_iterator(node* n, hashtable* tab) : cur(n), ht(tab) {}
+  __hashtable_iterator() {}
+  reference operator*() const { return cur->val; }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+  iterator& operator++();
+  iterator operator++(int);
+  bool operator==(const iterator& it) const { return cur == it.cur; }
+  bool operator!=(const iterator& it) const { return cur != it.cur; }
+};
+
+
+template <class Value, class Key, class HashFcn,
+          class ExtractKey, class EqualKey, class Alloc>
+struct __hashtable_const_iterator {
+  typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
+          hashtable;
+  typedef __hashtable_iterator<Value, Key, HashFcn, 
+                               ExtractKey, EqualKey, Alloc>
+          iterator;
+  typedef __hashtable_const_iterator<Value, Key, HashFcn, 
+                                     ExtractKey, EqualKey, Alloc>
+          const_iterator;
+  typedef __hashtable_node<Value> node;
+
+  typedef forward_iterator_tag iterator_category;
+  typedef Value value_type;
+  typedef ptrdiff_t difference_type;
+  typedef size_t size_type;
+  typedef const Value& reference;
+  typedef const Value* pointer;
+
+  const node* cur;
+  const hashtable* ht;
+
+  __hashtable_const_iterator(const node* n, const hashtable* tab)
+    : cur(n), ht(tab) {}
+  __hashtable_const_iterator() {}
+  __hashtable_const_iterator(const iterator& it) : cur(it.cur), ht(it.ht) {}
+  reference operator*() const { return cur->val; }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+  const_iterator& operator++();
+  const_iterator operator++(int);
+  bool operator==(const const_iterator& it) const { return cur == it.cur; }
+  bool operator!=(const const_iterator& it) const { return cur != it.cur; }
+};
+
+// Note: assumes long is at least 32 bits.
+static const int __stl_num_primes = 28;
+static const unsigned long __stl_prime_list[__stl_num_primes] =
+{
+  53,         97,         193,       389,       769,
+  1543,       3079,       6151,      12289,     24593,
+  49157,      98317,      196613,    393241,    786433,
+  1572869,    3145739,    6291469,   12582917,  25165843,
+  50331653,   100663319,  201326611, 402653189, 805306457, 
+  1610612741, 3221225473, 4294967291
+};
+
+inline unsigned long __stl_next_prime(unsigned long n)
+{
+  const unsigned long* first = __stl_prime_list;
+  const unsigned long* last = __stl_prime_list + __stl_num_primes;
+  const unsigned long* pos = lower_bound(first, last, n);
+  return pos == last ? *(last - 1) : *pos;
+}
+
+
+template <class Value, class Key, class HashFcn,
+          class ExtractKey, class EqualKey,
+          class Alloc>
+class hashtable {
+public:
+  typedef Key key_type;
+  typedef Value value_type;
+  typedef HashFcn hasher;
+  typedef EqualKey key_equal;
+
+  typedef size_t            size_type;
+  typedef ptrdiff_t         difference_type;
+  typedef value_type*       pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type&       reference;
+  typedef const value_type& const_reference;
+
+  hasher hash_funct() const { return hash; }
+  key_equal key_eq() const { return equals; }
+
+private:
+  hasher hash;
+  key_equal equals;
+  ExtractKey get_key;
+
+  typedef __hashtable_node<Value> node;
+  typedef simple_alloc<node, Alloc> node_allocator;
+
+  vector<node*,Alloc> buckets;
+  size_type num_elements;
+
+public:
+  typedef __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, 
+                               Alloc>
+  iterator;
+
+  typedef __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,
+                                     Alloc>
+  const_iterator;
+
+  friend struct
+  __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
+  friend struct
+  __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
+
+public:
+  hashtable(size_type n,
+            const HashFcn&    hf,
+            const EqualKey&   eql,
+            const ExtractKey& ext)
+    : hash(hf), equals(eql), get_key(ext), num_elements(0)
+  {
+    initialize_buckets(n);
+  }
+
+  hashtable(size_type n,
+            const HashFcn&    hf,
+            const EqualKey&   eql)
+    : hash(hf), equals(eql), get_key(ExtractKey()), num_elements(0)
+  {
+    initialize_buckets(n);
+  }
+
+  hashtable(const hashtable& ht)
+    : hash(ht.hash), equals(ht.equals), get_key(ht.get_key), num_elements(0)
+  {
+    copy_from(ht);
+  }
+
+  hashtable& operator= (const hashtable& ht)
+  {
+    if (&ht != this) {
+      clear();
+      hash = ht.hash;
+      equals = ht.equals;
+      get_key = ht.get_key;
+      copy_from(ht);
+    }
+    return *this;
+  }
+
+  ~hashtable() { clear(); }
+
+  size_type size() const { return num_elements; }
+  size_type max_size() const { return size_type(-1); }
+  bool empty() const { return size() == 0; }
+
+  void swap(hashtable& ht)
+  {
+    __STD::swap(hash, ht.hash);
+    __STD::swap(equals, ht.equals);
+    __STD::swap(get_key, ht.get_key);
+    buckets.swap(ht.buckets);
+    __STD::swap(num_elements, ht.num_elements);
+  }
+
+  iterator begin()
+  { 
+    for (size_type n = 0; n < buckets.size(); ++n)
+      if (buckets[n])
+        return iterator(buckets[n], this);
+    return end();
+  }
+
+  iterator end() { return iterator(0, this); }
+
+  const_iterator begin() const
+  {
+    for (size_type n = 0; n < buckets.size(); ++n)
+      if (buckets[n])
+        return const_iterator(buckets[n], this);
+    return end();
+  }
+
+  const_iterator end() const { return const_iterator(0, this); }
+
+  friend bool
+  operator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&);
+
+public:
+
+  size_type bucket_count() const { return buckets.size(); }
+
+  size_type max_bucket_count() const
+    { return __stl_prime_list[__stl_num_primes - 1]; } 
+
+  size_type elems_in_bucket(size_type bucket) const
+  {
+    size_type result = 0;
+    for (node* cur = buckets[bucket]; cur; cur = cur->next)
+      result += 1;
+    return result;
+  }
+
+  pair<iterator, bool> insert_unique(const value_type& obj)
+  {
+    resize(num_elements + 1);
+    return insert_unique_noresize(obj);
+  }
+
+  iterator insert_equal(const value_type& obj)
+  {
+    resize(num_elements + 1);
+    return insert_equal_noresize(obj);
+  }
+
+  pair<iterator, bool> insert_unique_noresize(const value_type& obj);
+  iterator insert_equal_noresize(const value_type& obj);
+ 
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert_unique(InputIterator f, InputIterator l)
+  {
+    insert_unique(f, l, iterator_category(f));
+  }
+
+  template <class InputIterator>
+  void insert_equal(InputIterator f, InputIterator l)
+  {
+    insert_equal(f, l, iterator_category(f));
+  }
+
+  template <class InputIterator>
+  void insert_unique(InputIterator f, InputIterator l,
+                     input_iterator_tag)
+  {
+    for ( ; f != l; ++f)
+      insert_unique(*f);
+  }
+
+  template <class InputIterator>
+  void insert_equal(InputIterator f, InputIterator l,
+                    input_iterator_tag)
+  {
+    for ( ; f != l; ++f)
+      insert_equal(*f);
+  }
+
+  template <class ForwardIterator>
+  void insert_unique(ForwardIterator f, ForwardIterator l,
+                     forward_iterator_tag)
+  {
+    size_type n = 0;
+    distance(f, l, n);
+    resize(num_elements + n);
+    for ( ; n > 0; --n, ++f)
+      insert_unique_noresize(*f);
+  }
+
+  template <class ForwardIterator>
+  void insert_equal(ForwardIterator f, ForwardIterator l,
+                    forward_iterator_tag)
+  {
+    size_type n = 0;
+    distance(f, l, n);
+    resize(num_elements + n);
+    for ( ; n > 0; --n, ++f)
+      insert_equal_noresize(*f);
+  }
+
+#else /* __STL_MEMBER_TEMPLATES */
+  void insert_unique(const value_type* f, const value_type* l)
+  {
+    size_type n = l - f;
+    resize(num_elements + n);
+    for ( ; n > 0; --n, ++f)
+      insert_unique_noresize(*f);
+  }
+
+  void insert_equal(const value_type* f, const value_type* l)
+  {
+    size_type n = l - f;
+    resize(num_elements + n);
+    for ( ; n > 0; --n, ++f)
+      insert_equal_noresize(*f);
+  }
+
+  void insert_unique(const_iterator f, const_iterator l)
+  {
+    size_type n = 0;
+    distance(f, l, n);
+    resize(num_elements + n);
+    for ( ; n > 0; --n, ++f)
+      insert_unique_noresize(*f);
+  }
+
+  void insert_equal(const_iterator f, const_iterator l)
+  {
+    size_type n = 0;
+    distance(f, l, n);
+    resize(num_elements + n);
+    for ( ; n > 0; --n, ++f)
+      insert_equal_noresize(*f);
+  }
+#endif /*__STL_MEMBER_TEMPLATES */
+
+  reference find_or_insert(const value_type& obj);
+
+  iterator find(const key_type& key) 
+  {
+    size_type n = bkt_num_key(key);
+    node* first;
+    for ( first = buckets[n];
+          first && !equals(get_key(first->val), key);
+          first = first->next)
+      {}
+    return iterator(first, this);
+  } 
+
+  const_iterator find(const key_type& key) const
+  {
+    size_type n = bkt_num_key(key);
+    const node* first;
+    for ( first = buckets[n];
+          first && !equals(get_key(first->val), key);
+          first = first->next)
+      {}
+    return const_iterator(first, this);
+  } 
+
+  size_type count(const key_type& key) const
+  {
+    const size_type n = bkt_num_key(key);
+    size_type result = 0;
+
+    for (const node* cur = buckets[n]; cur; cur = cur->next)
+      if (equals(get_key(cur->val), key))
+        ++result;
+    return result;
+  }
+
+  pair<iterator, iterator> equal_range(const key_type& key);
+  pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
+
+  size_type erase(const key_type& key);
+  void erase(const iterator& it);
+  void erase(iterator first, iterator last);
+
+  void erase(const const_iterator& it);
+  void erase(const_iterator first, const_iterator last);
+
+  void resize(size_type num_elements_hint);
+  void clear();
+
+private:
+  size_type next_size(size_type n) const { return __stl_next_prime(n); }
+
+  void initialize_buckets(size_type n)
+  {
+    const size_type n_buckets = next_size(n);
+    buckets.reserve(n_buckets);
+    buckets.insert(buckets.end(), n_buckets, (node*) 0);
+    num_elements = 0;
+  }
+
+  size_type bkt_num_key(const key_type& key) const
+  {
+    return bkt_num_key(key, buckets.size());
+  }
+
+  size_type bkt_num(const value_type& obj) const
+  {
+    return bkt_num_key(get_key(obj));
+  }
+
+  size_type bkt_num_key(const key_type& key, size_t n) const
+  {
+    return hash(key) % n;
+  }
+
+  size_type bkt_num(const value_type& obj, size_t n) const
+  {
+    return bkt_num_key(get_key(obj), n);
+  }
+
+  node* new_node(const value_type& obj)
+  {
+    node* n = node_allocator::allocate();
+    n->next = 0;
+    __STL_TRY {
+      construct(&n->val, obj);
+      return n;
+    }
+    __STL_UNWIND(node_allocator::deallocate(n));
+  }
+  
+  void delete_node(node* n)
+  {
+    destroy(&n->val);
+    node_allocator::deallocate(n);
+  }
+
+  void erase_bucket(const size_type n, node* first, node* last);
+  void erase_bucket(const size_type n, node* last);
+
+  void copy_from(const hashtable& ht);
+
+};
+
+template <class V, class K, class HF, class ExK, class EqK, class A>
+__hashtable_iterator<V, K, HF, ExK, EqK, A>&
+__hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++()
+{
+  const node* old = cur;
+  cur = cur->next;
+  if (!cur) {
+    size_type bucket = ht->bkt_num(old->val);
+    while (!cur && ++bucket < ht->buckets.size())
+      cur = ht->buckets[bucket];
+  }
+  return *this;
+}
+
+template <class V, class K, class HF, class ExK, class EqK, class A>
+inline __hashtable_iterator<V, K, HF, ExK, EqK, A>
+__hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++(int)
+{
+  iterator tmp = *this;
+  ++*this;
+  return tmp;
+}
+
+template <class V, class K, class HF, class ExK, class EqK, class A>
+__hashtable_const_iterator<V, K, HF, ExK, EqK, A>&
+__hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++()
+{
+  const node* old = cur;
+  cur = cur->next;
+  if (!cur) {
+    size_type bucket = ht->bkt_num(old->val);
+    while (!cur && ++bucket < ht->buckets.size())
+      cur = ht->buckets[bucket];
+  }
+  return *this;
+}
+
+template <class V, class K, class HF, class ExK, class EqK, class A>
+inline __hashtable_const_iterator<V, K, HF, ExK, EqK, A>
+__hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++(int)
+{
+  const_iterator tmp = *this;
+  ++*this;
+  return tmp;
+}
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class V, class K, class HF, class ExK, class EqK, class All>
+inline forward_iterator_tag
+iterator_category(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
+{
+  return forward_iterator_tag();
+}
+
+template <class V, class K, class HF, class ExK, class EqK, class All>
+inline V* value_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
+{
+  return (V*) 0;
+}
+
+template <class V, class K, class HF, class ExK, class EqK, class All>
+inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*
+distance_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
+{
+  return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0;
+}
+
+template <class V, class K, class HF, class ExK, class EqK, class All>
+inline forward_iterator_tag
+iterator_category(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
+{
+  return forward_iterator_tag();
+}
+
+template <class V, class K, class HF, class ExK, class EqK, class All>
+inline V* 
+value_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
+{
+  return (V*) 0;
+}
+
+template <class V, class K, class HF, class ExK, class EqK, class All>
+inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*
+distance_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
+{
+  return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0;
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+bool operator==(const hashtable<V, K, HF, Ex, Eq, A>& ht1,
+                const hashtable<V, K, HF, Ex, Eq, A>& ht2)
+{
+  typedef typename hashtable<V, K, HF, Ex, Eq, A>::node node;
+  if (ht1.buckets.size() != ht2.buckets.size())
+    return false;
+  for (int n = 0; n < ht1.buckets.size(); ++n) {
+    node* cur1 = ht1.buckets[n];
+    node* cur2 = ht2.buckets[n];
+    for ( ; cur1 && cur2 && cur1->val == cur2->val;
+          cur1 = cur1->next, cur2 = cur2->next)
+      {}
+    if (cur1 || cur2)
+      return false;
+  }
+  return true;
+}  
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Val, class Key, class HF, class Extract, class EqKey, class A>
+inline void swap(hashtable<Val, Key, HF, Extract, EqKey, A>& ht1,
+                 hashtable<Val, Key, HF, Extract, EqKey, A>& ht2) {
+  ht1.swap(ht2);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, bool> 
+hashtable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const value_type& obj)
+{
+  const size_type n = bkt_num(obj);
+  node* first = buckets[n];
+
+  for (node* cur = first; cur; cur = cur->next) 
+    if (equals(get_key(cur->val), get_key(obj)))
+      return pair<iterator, bool>(iterator(cur, this), false);
+
+  node* tmp = new_node(obj);
+  tmp->next = first;
+  buckets[n] = tmp;
+  ++num_elements;
+  return pair<iterator, bool>(iterator(tmp, this), true);
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+typename hashtable<V, K, HF, Ex, Eq, A>::iterator 
+hashtable<V, K, HF, Ex, Eq, A>::insert_equal_noresize(const value_type& obj)
+{
+  const size_type n = bkt_num(obj);
+  node* first = buckets[n];
+
+  for (node* cur = first; cur; cur = cur->next) 
+    if (equals(get_key(cur->val), get_key(obj))) {
+      node* tmp = new_node(obj);
+      tmp->next = cur->next;
+      cur->next = tmp;
+      ++num_elements;
+      return iterator(tmp, this);
+    }
+
+  node* tmp = new_node(obj);
+  tmp->next = first;
+  buckets[n] = tmp;
+  ++num_elements;
+  return iterator(tmp, this);
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+typename hashtable<V, K, HF, Ex, Eq, A>::reference 
+hashtable<V, K, HF, Ex, Eq, A>::find_or_insert(const value_type& obj)
+{
+  resize(num_elements + 1);
+
+  size_type n = bkt_num(obj);
+  node* first = buckets[n];
+
+  for (node* cur = first; cur; cur = cur->next)
+    if (equals(get_key(cur->val), get_key(obj)))
+      return cur->val;
+
+  node* tmp = new_node(obj);
+  tmp->next = first;
+  buckets[n] = tmp;
+  ++num_elements;
+  return tmp->val;
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator,
+     typename hashtable<V, K, HF, Ex, Eq, A>::iterator> 
+hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key)
+{
+  typedef pair<iterator, iterator> pii;
+  const size_type n = bkt_num_key(key);
+
+  for (node* first = buckets[n]; first; first = first->next) {
+    if (equals(get_key(first->val), key)) {
+      for (node* cur = first->next; cur; cur = cur->next)
+        if (!equals(get_key(cur->val), key))
+          return pii(iterator(first, this), iterator(cur, this));
+      for (size_type m = n + 1; m < buckets.size(); ++m)
+        if (buckets[m])
+          return pii(iterator(first, this),
+                     iterator(buckets[m], this));
+      return pii(iterator(first, this), end());
+    }
+  }
+  return pii(end(), end());
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+pair<typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator, 
+     typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator> 
+hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) const
+{
+  typedef pair<const_iterator, const_iterator> pii;
+  const size_type n = bkt_num_key(key);
+
+  for (const node* first = buckets[n] ; first; first = first->next) {
+    if (equals(get_key(first->val), key)) {
+      for (const node* cur = first->next; cur; cur = cur->next)
+        if (!equals(get_key(cur->val), key))
+          return pii(const_iterator(first, this),
+                     const_iterator(cur, this));
+      for (size_type m = n + 1; m < buckets.size(); ++m)
+        if (buckets[m])
+          return pii(const_iterator(first, this),
+                     const_iterator(buckets[m], this));
+      return pii(const_iterator(first, this), end());
+    }
+  }
+  return pii(end(), end());
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+typename hashtable<V, K, HF, Ex, Eq, A>::size_type 
+hashtable<V, K, HF, Ex, Eq, A>::erase(const key_type& key)
+{
+  const size_type n = bkt_num_key(key);
+  node* first = buckets[n];
+  size_type erased = 0;
+
+  if (first) {
+    node* cur = first;
+    node* next = cur->next;
+    while (next) {
+      if (equals(get_key(next->val), key)) {
+        cur->next = next->next;
+        delete_node(next);
+        next = cur->next;
+        ++erased;
+        --num_elements;
+      }
+      else {
+        cur = next;
+        next = cur->next;
+      }
+    }
+    if (equals(get_key(first->val), key)) {
+      buckets[n] = first->next;
+      delete_node(first);
+      ++erased;
+      --num_elements;
+    }
+  }
+  return erased;
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+void hashtable<V, K, HF, Ex, Eq, A>::erase(const iterator& it)
+{
+  if (node* const p = it.cur) {
+    const size_type n = bkt_num(p->val);
+    node* cur = buckets[n];
+
+    if (cur == p) {
+      buckets[n] = cur->next;
+      delete_node(cur);
+      --num_elements;
+    }
+    else {
+      node* next = cur->next;
+      while (next) {
+        if (next == p) {
+          cur->next = next->next;
+          delete_node(next);
+          --num_elements;
+          break;
+        }
+        else {
+          cur = next;
+          next = cur->next;
+        }
+      }
+    }
+  }
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+void hashtable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last)
+{
+  size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size();
+  size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size();
+
+  if (first.cur == last.cur)
+    return;
+  else if (f_bucket == l_bucket)
+    erase_bucket(f_bucket, first.cur, last.cur);
+  else {
+    erase_bucket(f_bucket, first.cur, 0);
+    for (size_type n = f_bucket + 1; n < l_bucket; ++n)
+      erase_bucket(n, 0);
+    if (l_bucket != buckets.size())
+      erase_bucket(l_bucket, last.cur);
+  }
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+inline void
+hashtable<V, K, HF, Ex, Eq, A>::erase(const_iterator first,
+                                      const_iterator last)
+{
+  erase(iterator(const_cast<node*>(first.cur),
+                 const_cast<hashtable*>(first.ht)),
+        iterator(const_cast<node*>(last.cur),
+                 const_cast<hashtable*>(last.ht)));
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+inline void
+hashtable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it)
+{
+  erase(iterator(const_cast<node*>(it.cur),
+                 const_cast<hashtable*>(it.ht)));
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+void hashtable<V, K, HF, Ex, Eq, A>::resize(size_type num_elements_hint)
+{
+  const size_type old_n = buckets.size();
+  if (num_elements_hint > old_n) {
+    const size_type n = next_size(num_elements_hint);
+    if (n > old_n) {
+      vector<node*, A> tmp(n, (node*) 0);
+      __STL_TRY {
+        for (size_type bucket = 0; bucket < old_n; ++bucket) {
+          node* first = buckets[bucket];
+          while (first) {
+            size_type new_bucket = bkt_num(first->val, n);
+            buckets[bucket] = first->next;
+            first->next = tmp[new_bucket];
+            tmp[new_bucket] = first;
+            first = buckets[bucket];          
+          }
+        }
+        buckets.swap(tmp);
+      }
+#         ifdef __STL_USE_EXCEPTIONS
+      catch(...) {
+        for (size_type bucket = 0; bucket < tmp.size(); ++bucket) {
+          while (tmp[bucket]) {
+            node* next = tmp[bucket]->next;
+            delete_node(tmp[bucket]);
+            tmp[bucket] = next;
+          }
+        }
+        throw;
+      }
+#         endif /* __STL_USE_EXCEPTIONS */
+    }
+  }
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+void hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, 
+                                                  node* first, node* last)
+{
+  node* cur = buckets[n];
+  if (cur == first)
+    erase_bucket(n, last);
+  else {
+    node* next;
+    for (next = cur->next; next != first; cur = next, next = cur->next)
+      ;
+    while (next) {
+      cur->next = next->next;
+      delete_node(next);
+      next = cur->next;
+      --num_elements;
+    }
+  }
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+void 
+hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last)
+{
+  node* cur = buckets[n];
+  while (cur != last) {
+    node* next = cur->next;
+    delete_node(cur);
+    cur = next;
+    buckets[n] = cur;
+    --num_elements;
+  }
+}
+
+template <class V, class K, class HF, class Ex, class Eq, class A>
+void hashtable<V, K, HF, Ex, Eq, A>::clear()
+{
+  for (size_type i = 0; i < buckets.size(); ++i) {
+    node* cur = buckets[i];
+    while (cur != 0) {
+      node* next = cur->next;
+      delete_node(cur);
+      cur = next;
+    }
+    buckets[i] = 0;
+  }
+  num_elements = 0;
+}
+
+    
+template <class V, class K, class HF, class Ex, class Eq, class A>
+void hashtable<V, K, HF, Ex, Eq, A>::copy_from(const hashtable& ht)
+{
+  buckets.clear();
+  buckets.reserve(ht.buckets.size());
+  buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0);
+  __STL_TRY {
+    for (size_type i = 0; i < ht.buckets.size(); ++i) {
+      if (const node* cur = ht.buckets[i]) {
+        node* copy = new_node(cur->val);
+        buckets[i] = copy;
+
+        for (node* next = cur->next; next; cur = next, next = cur->next) {
+          copy->next = new_node(next->val);
+          copy = copy->next;
+        }
+      }
+    }
+    num_elements = ht.num_elements;
+  }
+  __STL_UNWIND(clear());
+}
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_HASHTABLE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_iter.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_iter.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_iter.h	(revision 18)
@@ -0,0 +1,843 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_ITERATOR_H
+#define __SGI_STL_INTERNAL_ITERATOR_H
+
+__STL_BEGIN_NAMESPACE
+
+struct input_iterator_tag {};
+struct output_iterator_tag {};
+struct forward_iterator_tag : public input_iterator_tag {};
+struct bidirectional_iterator_tag : public forward_iterator_tag {};
+struct random_access_iterator_tag : public bidirectional_iterator_tag {};
+
+template <class T, class Distance> struct input_iterator {
+  typedef input_iterator_tag iterator_category;
+  typedef T                  value_type;
+  typedef Distance           difference_type;
+  typedef T*                 pointer;
+  typedef T&                 reference;
+};
+
+struct output_iterator {
+  typedef output_iterator_tag iterator_category;
+  typedef void                value_type;
+  typedef void                difference_type;
+  typedef void                pointer;
+  typedef void                reference;
+};
+
+template <class T, class Distance> struct forward_iterator {
+  typedef forward_iterator_tag iterator_category;
+  typedef T                    value_type;
+  typedef Distance             difference_type;
+  typedef T*                   pointer;
+  typedef T&                   reference;
+};
+
+
+template <class T, class Distance> struct bidirectional_iterator {
+  typedef bidirectional_iterator_tag iterator_category;
+  typedef T                          value_type;
+  typedef Distance                   difference_type;
+  typedef T*                         pointer;
+  typedef T&                         reference;
+};
+
+template <class T, class Distance> struct random_access_iterator {
+  typedef random_access_iterator_tag iterator_category;
+  typedef T                          value_type;
+  typedef Distance                   difference_type;
+  typedef T*                         pointer;
+  typedef T&                         reference;
+};
+
+#ifdef __STL_USE_NAMESPACES
+template <class Category, class T, class Distance = ptrdiff_t,
+          class Pointer = T*, class Reference = T&>
+struct iterator {
+  typedef Category  iterator_category;
+  typedef T         value_type;
+  typedef Distance  difference_type;
+  typedef Pointer   pointer;
+  typedef Reference reference;
+};
+#endif /* __STL_USE_NAMESPACES */
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class Iterator>
+struct iterator_traits {
+  typedef typename Iterator::iterator_category iterator_category;
+  typedef typename Iterator::value_type        value_type;
+  typedef typename Iterator::difference_type   difference_type;
+  typedef typename Iterator::pointer           pointer;
+  typedef typename Iterator::reference         reference;
+};
+
+template <class T>
+struct iterator_traits<T*> {
+  typedef random_access_iterator_tag iterator_category;
+  typedef T                          value_type;
+  typedef ptrdiff_t                  difference_type;
+  typedef T*                         pointer;
+  typedef T&                         reference;
+};
+
+template <class T>
+struct iterator_traits<const T*> {
+  typedef random_access_iterator_tag iterator_category;
+  typedef T                          value_type;
+  typedef ptrdiff_t                  difference_type;
+  typedef const T*                   pointer;
+  typedef const T&                   reference;
+};
+
+template <class Iterator>
+inline typename iterator_traits<Iterator>::iterator_category
+iterator_category(const Iterator&) {
+  typedef typename iterator_traits<Iterator>::iterator_category category;
+  return category();
+}
+
+template <class Iterator>
+inline typename iterator_traits<Iterator>::difference_type*
+distance_type(const Iterator&) {
+  return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
+}
+
+template <class Iterator>
+inline typename iterator_traits<Iterator>::value_type*
+value_type(const Iterator&) {
+  return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
+}
+
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class T, class Distance> 
+inline input_iterator_tag 
+iterator_category(const input_iterator<T, Distance>&) {
+  return input_iterator_tag();
+}
+
+inline output_iterator_tag iterator_category(const output_iterator&) {
+  return output_iterator_tag();
+}
+
+template <class T, class Distance> 
+inline forward_iterator_tag
+iterator_category(const forward_iterator<T, Distance>&) {
+  return forward_iterator_tag();
+}
+
+template <class T, class Distance> 
+inline bidirectional_iterator_tag
+iterator_category(const bidirectional_iterator<T, Distance>&) {
+  return bidirectional_iterator_tag();
+}
+
+template <class T, class Distance> 
+inline random_access_iterator_tag
+iterator_category(const random_access_iterator<T, Distance>&) {
+  return random_access_iterator_tag();
+}
+
+template <class T>
+inline random_access_iterator_tag iterator_category(const T*) {
+  return random_access_iterator_tag();
+}
+
+template <class T, class Distance> 
+inline T* value_type(const input_iterator<T, Distance>&) {
+  return (T*)(0); 
+}
+
+template <class T, class Distance> 
+inline T* value_type(const forward_iterator<T, Distance>&) {
+  return (T*)(0);
+}
+
+template <class T, class Distance> 
+inline T* value_type(const bidirectional_iterator<T, Distance>&) {
+  return (T*)(0);
+}
+
+template <class T, class Distance> 
+inline T* value_type(const random_access_iterator<T, Distance>&) {
+  return (T*)(0);
+}
+
+template <class T>
+inline T* value_type(const T*) { return (T*)(0); }
+
+template <class T, class Distance> 
+inline Distance* distance_type(const input_iterator<T, Distance>&) {
+  return (Distance*)(0);
+}
+
+template <class T, class Distance> 
+inline Distance* distance_type(const forward_iterator<T, Distance>&) {
+  return (Distance*)(0);
+}
+
+template <class T, class Distance> 
+inline Distance* 
+distance_type(const bidirectional_iterator<T, Distance>&) {
+  return (Distance*)(0);
+}
+
+template <class T, class Distance> 
+inline Distance* 
+distance_type(const random_access_iterator<T, Distance>&) {
+  return (Distance*)(0);
+}
+
+template <class T>
+inline ptrdiff_t* distance_type(const T*) { return (ptrdiff_t*)(0); }
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class InputIterator, class Distance>
+inline void __distance(InputIterator first, InputIterator last, Distance& n, 
+                       input_iterator_tag) {
+  while (first != last) { ++first; ++n; }
+}
+
+template <class RandomAccessIterator, class Distance>
+inline void __distance(RandomAccessIterator first, RandomAccessIterator last, 
+                       Distance& n, random_access_iterator_tag) {
+  n += last - first;
+}
+
+template <class InputIterator, class Distance>
+inline void distance(InputIterator first, InputIterator last, Distance& n) {
+  __distance(first, last, n, iterator_category(first));
+}
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class InputIterator>
+inline iterator_traits<InputIterator>::difference_type
+__distance(InputIterator first, InputIterator last, input_iterator_tag) {
+  iterator_traits<InputIterator>::difference_type n = 0;
+  while (first != last) {
+    ++first; ++n;
+  }
+  return n;
+}
+
+template <class RandomAccessIterator>
+inline iterator_traits<RandomAccessIterator>::difference_type
+__distance(RandomAccessIterator first, RandomAccessIterator last,
+           random_access_iterator_tag) {
+  return last - first;
+}
+
+template <class InputIterator>
+inline iterator_traits<InputIterator>::difference_type
+distance(InputIterator first, InputIterator last) {
+  typedef typename iterator_traits<InputIterator>::iterator_category category;
+  return __distance(first, last, category());
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class InputIterator, class Distance>
+inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
+  while (n--) ++i;
+}
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1183
+#endif
+
+template <class BidirectionalIterator, class Distance>
+inline void __advance(BidirectionalIterator& i, Distance n, 
+                      bidirectional_iterator_tag) {
+  if (n >= 0)
+    while (n--) ++i;
+  else
+    while (n++) --i;
+}
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1183
+#endif
+
+template <class RandomAccessIterator, class Distance>
+inline void __advance(RandomAccessIterator& i, Distance n, 
+                      random_access_iterator_tag) {
+  i += n;
+}
+
+template <class InputIterator, class Distance>
+inline void advance(InputIterator& i, Distance n) {
+  __advance(i, n, iterator_category(i));
+}
+
+template <class Container>
+class back_insert_iterator {
+protected:
+  Container* container;
+public:
+  typedef output_iterator_tag iterator_category;
+  typedef void                value_type;
+  typedef void                difference_type;
+  typedef void                pointer;
+  typedef void                reference;
+
+  explicit back_insert_iterator(Container& x) : container(&x) {}
+  back_insert_iterator<Container>&
+  operator=(const typename Container::value_type& value) { 
+    container->push_back(value);
+    return *this;
+  }
+  back_insert_iterator<Container>& operator*() { return *this; }
+  back_insert_iterator<Container>& operator++() { return *this; }
+  back_insert_iterator<Container>& operator++(int) { return *this; }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class Container>
+inline output_iterator_tag
+iterator_category(const back_insert_iterator<Container>&)
+{
+  return output_iterator_tag();
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class Container>
+inline back_insert_iterator<Container> back_inserter(Container& x) {
+  return back_insert_iterator<Container>(x);
+}
+
+template <class Container>
+class front_insert_iterator {
+protected:
+  Container* container;
+public:
+  typedef output_iterator_tag iterator_category;
+  typedef void                value_type;
+  typedef void                difference_type;
+  typedef void                pointer;
+  typedef void                reference;
+
+  explicit front_insert_iterator(Container& x) : container(&x) {}
+  front_insert_iterator<Container>&
+  operator=(const typename Container::value_type& value) { 
+    container->push_front(value);
+    return *this;
+  }
+  front_insert_iterator<Container>& operator*() { return *this; }
+  front_insert_iterator<Container>& operator++() { return *this; }
+  front_insert_iterator<Container>& operator++(int) { return *this; }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class Container>
+inline output_iterator_tag
+iterator_category(const front_insert_iterator<Container>&)
+{
+  return output_iterator_tag();
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class Container>
+inline front_insert_iterator<Container> front_inserter(Container& x) {
+  return front_insert_iterator<Container>(x);
+}
+
+template <class Container>
+class insert_iterator {
+protected:
+  Container* container;
+  typename Container::iterator iter;
+public:
+  typedef output_iterator_tag iterator_category;
+  typedef void                value_type;
+  typedef void                difference_type;
+  typedef void                pointer;
+  typedef void                reference;
+
+  insert_iterator(Container& x, typename Container::iterator i) 
+    : container(&x), iter(i) {}
+  insert_iterator<Container>&
+  operator=(const typename Container::value_type& value) { 
+    iter = container->insert(iter, value);
+    ++iter;
+    return *this;
+  }
+  insert_iterator<Container>& operator*() { return *this; }
+  insert_iterator<Container>& operator++() { return *this; }
+  insert_iterator<Container>& operator++(int) { return *this; }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class Container>
+inline output_iterator_tag
+iterator_category(const insert_iterator<Container>&)
+{
+  return output_iterator_tag();
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class Container, class Iterator>
+inline insert_iterator<Container> inserter(Container& x, Iterator i) {
+  typedef typename Container::iterator iter;
+  return insert_iterator<Container>(x, iter(i));
+}
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class BidirectionalIterator, class T, class Reference = T&, 
+          class Distance = ptrdiff_t> 
+#else
+template <class BidirectionalIterator, class T, class Reference, 
+          class Distance> 
+#endif
+class reverse_bidirectional_iterator {
+  typedef reverse_bidirectional_iterator<BidirectionalIterator, T, Reference,
+                                         Distance> self;
+protected:
+  BidirectionalIterator current;
+public:
+  typedef bidirectional_iterator_tag iterator_category;
+  typedef T                          value_type;
+  typedef Distance                   difference_type;
+  typedef T*                         pointer;
+  typedef Reference                  reference;
+
+  reverse_bidirectional_iterator() {}
+  explicit reverse_bidirectional_iterator(BidirectionalIterator x)
+    : current(x) {}
+  BidirectionalIterator base() const { return current; }
+  Reference operator*() const {
+    BidirectionalIterator tmp = current;
+    return *--tmp;
+  }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+  self& operator++() {
+    --current;
+    return *this;
+  }
+  self operator++(int) {
+    self tmp = *this;
+    --current;
+    return tmp;
+  }
+  self& operator--() {
+    ++current;
+    return *this;
+  }
+  self operator--(int) {
+    self tmp = *this;
+    ++current;
+    return tmp;
+  }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class BidirectionalIterator, class T, class Reference, 
+          class Distance>
+inline bidirectional_iterator_tag
+iterator_category(const reverse_bidirectional_iterator<BidirectionalIterator,
+                                                       T,
+                                                       Reference, Distance>&) {
+  return bidirectional_iterator_tag();
+}
+
+template <class BidirectionalIterator, class T, class Reference, 
+          class Distance>
+inline T*
+value_type(const reverse_bidirectional_iterator<BidirectionalIterator, T,
+                                               Reference, Distance>&) {
+  return (T*) 0;
+}
+
+template <class BidirectionalIterator, class T, class Reference, 
+          class Distance>
+inline Distance*
+distance_type(const reverse_bidirectional_iterator<BidirectionalIterator, T,
+                                                  Reference, Distance>&) {
+  return (Distance*) 0;
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class BidirectionalIterator, class T, class Reference,
+          class Distance>
+inline bool operator==(
+    const reverse_bidirectional_iterator<BidirectionalIterator, T, Reference,
+                                         Distance>& x, 
+    const reverse_bidirectional_iterator<BidirectionalIterator, T, Reference,
+                                         Distance>& y) {
+  return x.base() == y.base();
+}
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+// This is the new version of reverse_iterator, as defined in the
+//  draft C++ standard.  It relies on the iterator_traits template,
+//  which in turn relies on partial specialization.  The class
+//  reverse_bidirectional_iterator is no longer part of the draft
+//  standard, but it is retained for backward compatibility.
+
+template <class Iterator>
+class reverse_iterator 
+{
+protected:
+  Iterator current;
+public:
+  typedef typename iterator_traits<Iterator>::iterator_category
+          iterator_category;
+  typedef typename iterator_traits<Iterator>::value_type
+          value_type;
+  typedef typename iterator_traits<Iterator>::difference_type
+          difference_type;
+  typedef typename iterator_traits<Iterator>::pointer
+          pointer;
+  typedef typename iterator_traits<Iterator>::reference
+          reference;
+
+  typedef Iterator iterator_type;
+  typedef reverse_iterator<Iterator> self;
+
+public:
+  reverse_iterator() {}
+  explicit reverse_iterator(iterator_type x) : current(x) {}
+
+  reverse_iterator(const self& x) : current(x.current) {}
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class Iter>
+  reverse_iterator(const reverse_iterator<Iter>& x) : current(x.current) {}
+#endif /* __STL_MEMBER_TEMPLATES */
+    
+  iterator_type base() const { return current; }
+  reference operator*() const {
+    Iterator tmp = current;
+    return *--tmp;
+  }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+
+  self& operator++() {
+    --current;
+    return *this;
+  }
+  self operator++(int) {
+    self tmp = *this;
+    --current;
+    return tmp;
+  }
+  self& operator--() {
+    ++current;
+    return *this;
+  }
+  self operator--(int) {
+    self tmp = *this;
+    ++current;
+    return tmp;
+  }
+
+  self operator+(difference_type n) const {
+    return self(current - n);
+  }
+  self& operator+=(difference_type n) {
+    current -= n;
+    return *this;
+  }
+  self operator-(difference_type n) const {
+    return self(current + n);
+  }
+  self& operator-=(difference_type n) {
+    current += n;
+    return *this;
+  }
+  reference operator[](difference_type n) const { return *(*this + n); }  
+}; 
+ 
+template <class Iterator>
+inline bool operator==(const reverse_iterator<Iterator>& x, 
+                       const reverse_iterator<Iterator>& y) {
+  return x.base() == y.base();
+}
+
+template <class Iterator>
+inline bool operator<(const reverse_iterator<Iterator>& x, 
+                      const reverse_iterator<Iterator>& y) {
+  return y.base() < x.base();
+}
+
+template <class Iterator>
+inline typename reverse_iterator<Iterator>::difference_type
+operator-(const reverse_iterator<Iterator>& x, 
+          const reverse_iterator<Iterator>& y) {
+  return y.base() - x.base();
+}
+
+template <class Iterator>
+inline reverse_iterator<Iterator> 
+operator+(reverse_iterator<Iterator>::difference_type n,
+          const reverse_iterator<Iterator>& x) {
+  return reverse_iterator<Iterator>(x.base() - n);
+}
+
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+// This is the old version of reverse_iterator, as found in the original
+//  HP STL.  It does not use partial specialization.
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class RandomAccessIterator, class T, class Reference = T&,
+          class Distance = ptrdiff_t> 
+#else
+template <class RandomAccessIterator, class T, class Reference,
+          class Distance> 
+#endif
+class reverse_iterator {
+  typedef reverse_iterator<RandomAccessIterator, T, Reference, Distance>
+        self;
+protected:
+  RandomAccessIterator current;
+public:
+  typedef random_access_iterator_tag iterator_category;
+  typedef T                          value_type;
+  typedef Distance                   difference_type;
+  typedef T*                         pointer;
+  typedef Reference                  reference;
+
+  reverse_iterator() {}
+  explicit reverse_iterator(RandomAccessIterator x) : current(x) {}
+  RandomAccessIterator base() const { return current; }
+  Reference operator*() const { return *(current - 1); }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+  self& operator++() {
+    --current;
+    return *this;
+  }
+  self operator++(int) {
+    self tmp = *this;
+    --current;
+    return tmp;
+  }
+  self& operator--() {
+    ++current;
+    return *this;
+  }
+  self operator--(int) {
+    self tmp = *this;
+    ++current;
+    return tmp;
+  }
+  self operator+(Distance n) const {
+    return self(current - n);
+  }
+  self& operator+=(Distance n) {
+    current -= n;
+    return *this;
+  }
+  self operator-(Distance n) const {
+    return self(current + n);
+  }
+  self& operator-=(Distance n) {
+    current += n;
+    return *this;
+  }
+  Reference operator[](Distance n) const { return *(*this + n); }
+};
+
+template <class RandomAccessIterator, class T, class Reference, class Distance>
+inline random_access_iterator_tag
+iterator_category(const reverse_iterator<RandomAccessIterator, T,
+                                         Reference, Distance>&) {
+  return random_access_iterator_tag();
+}
+
+template <class RandomAccessIterator, class T, class Reference, class Distance>
+inline T* value_type(const reverse_iterator<RandomAccessIterator, T,
+                                            Reference, Distance>&) {
+  return (T*) 0;
+}
+
+template <class RandomAccessIterator, class T, class Reference, class Distance>
+inline Distance* distance_type(const reverse_iterator<RandomAccessIterator, T,
+                                                      Reference, Distance>&) {
+  return (Distance*) 0;
+}
+
+
+template <class RandomAccessIterator, class T, class Reference, class Distance>
+inline bool operator==(const reverse_iterator<RandomAccessIterator, T,
+                                              Reference, Distance>& x, 
+                       const reverse_iterator<RandomAccessIterator, T,
+                                              Reference, Distance>& y) {
+  return x.base() == y.base();
+}
+
+template <class RandomAccessIterator, class T, class Reference, class Distance>
+inline bool operator<(const reverse_iterator<RandomAccessIterator, T,
+                                             Reference, Distance>& x, 
+                      const reverse_iterator<RandomAccessIterator, T,
+                                             Reference, Distance>& y) {
+  return y.base() < x.base();
+}
+
+template <class RandomAccessIterator, class T, class Reference, class Distance>
+inline Distance operator-(const reverse_iterator<RandomAccessIterator, T,
+                                                 Reference, Distance>& x, 
+                          const reverse_iterator<RandomAccessIterator, T,
+                                                 Reference, Distance>& y) {
+  return y.base() - x.base();
+}
+
+template <class RandomAccessIter, class T, class Ref, class Dist>
+inline reverse_iterator<RandomAccessIter, T, Ref, Dist> 
+operator+(Dist n, const reverse_iterator<RandomAccessIter, T, Ref, Dist>& x) {
+  return reverse_iterator<RandomAccessIter, T, Ref, Dist>(x.base() - n);
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class T, class Distance = ptrdiff_t> 
+class istream_iterator {
+  friend bool
+  operator== __STL_NULL_TMPL_ARGS (const istream_iterator<T, Distance>& x,
+                                   const istream_iterator<T, Distance>& y);
+protected:
+  istream* stream;
+  T value;
+  bool end_marker;
+  void read() {
+    end_marker = (*stream) ? true : false;
+    if (end_marker) *stream >> value;
+    end_marker = (*stream) ? true : false;
+  }
+public:
+  typedef input_iterator_tag iterator_category;
+  typedef T                  value_type;
+  typedef Distance           difference_type;
+  typedef const T*           pointer;
+  typedef const T&           reference;
+
+  istream_iterator() : stream(&cin), end_marker(false) {}
+  istream_iterator(istream& s) : stream(&s) { read(); }
+  reference operator*() const { return value; }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+  istream_iterator<T, Distance>& operator++() { 
+    read(); 
+    return *this;
+  }
+  istream_iterator<T, Distance> operator++(int)  {
+    istream_iterator<T, Distance> tmp = *this;
+    read();
+    return tmp;
+  }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class T, class Distance>
+inline input_iterator_tag 
+iterator_category(const istream_iterator<T, Distance>&) {
+  return input_iterator_tag();
+}
+
+template <class T, class Distance>
+inline T* value_type(const istream_iterator<T, Distance>&) { return (T*) 0; }
+
+template <class T, class Distance>
+inline Distance* distance_type(const istream_iterator<T, Distance>&) {
+  return (Distance*) 0;
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class T, class Distance>
+inline bool operator==(const istream_iterator<T, Distance>& x,
+                       const istream_iterator<T, Distance>& y) {
+  return x.stream == y.stream && x.end_marker == y.end_marker ||
+         x.end_marker == false && y.end_marker == false;
+}
+
+template <class T>
+class ostream_iterator {
+protected:
+  ostream* stream;
+  const char* string;
+public:
+  typedef output_iterator_tag iterator_category;
+  typedef void                value_type;
+  typedef void                difference_type;
+  typedef void                pointer;
+  typedef void                reference;
+
+  ostream_iterator(ostream& s) : stream(&s), string(0) {}
+  ostream_iterator(ostream& s, const char* c) : stream(&s), string(c)  {}
+  ostream_iterator<T>& operator=(const T& value) { 
+    *stream << value;
+    if (string) *stream << string;
+    return *this;
+  }
+  ostream_iterator<T>& operator*() { return *this; }
+  ostream_iterator<T>& operator++() { return *this; } 
+  ostream_iterator<T>& operator++(int) { return *this; } 
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class T>
+inline output_iterator_tag 
+iterator_category(const ostream_iterator<T>&) {
+  return output_iterator_tag();
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_ITERATOR_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_list.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_list.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_list.h	(revision 18)
@@ -0,0 +1,617 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_LIST_H
+#define __SGI_STL_INTERNAL_LIST_H
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+template <class T>
+struct __list_node {
+  typedef void* void_pointer;
+  void_pointer next;
+  void_pointer prev;
+  T data;
+};
+
+template<class T, class Ref, class Ptr>
+struct __list_iterator {
+  typedef __list_iterator<T, T&, T*>             iterator;
+  typedef __list_iterator<T, const T&, const T*> const_iterator;
+  typedef __list_iterator<T, Ref, Ptr>           self;
+
+  typedef bidirectional_iterator_tag iterator_category;
+  typedef T value_type;
+  typedef Ptr pointer;
+  typedef Ref reference;
+  typedef __list_node<T>* link_type;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+
+  link_type node;
+
+  __list_iterator(link_type x) : node(x) {}
+  __list_iterator() {}
+  __list_iterator(const iterator& x) : node(x.node) {}
+
+  bool operator==(const self& x) const { return node == x.node; }
+  bool operator!=(const self& x) const { return node != x.node; }
+  reference operator*() const { return (*node).data; }
+
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+
+  self& operator++() { 
+    node = (link_type)((*node).next);
+    return *this;
+  }
+  self operator++(int) { 
+    self tmp = *this;
+    ++*this;
+    return tmp;
+  }
+  self& operator--() { 
+    node = (link_type)((*node).prev);
+    return *this;
+  }
+  self operator--(int) { 
+    self tmp = *this;
+    --*this;
+    return tmp;
+  }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class T, class Ref, class Ptr>
+inline bidirectional_iterator_tag
+iterator_category(const __list_iterator<T, Ref, Ptr>&) {
+  return bidirectional_iterator_tag();
+}
+
+template <class T, class Ref, class Ptr>
+inline T*
+value_type(const __list_iterator<T, Ref, Ptr>&) {
+  return 0;
+}
+
+template <class T, class Ref, class Ptr>
+inline ptrdiff_t*
+distance_type(const __list_iterator<T, Ref, Ptr>&) {
+  return 0;
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+template <class T, class Alloc = alloc>
+class list {
+protected:
+  typedef void* void_pointer;
+  typedef __list_node<T> list_node;
+  typedef simple_alloc<list_node, Alloc> list_node_allocator;
+public:      
+  typedef T value_type;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef list_node* link_type;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+
+public:
+  typedef __list_iterator<T, T&, T*>             iterator;
+  typedef __list_iterator<T, const T&, const T*> const_iterator;
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+  typedef reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef reverse_iterator<iterator> reverse_iterator;
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+  typedef reverse_bidirectional_iterator<const_iterator, value_type,
+  const_reference, difference_type>
+  const_reverse_iterator;
+  typedef reverse_bidirectional_iterator<iterator, value_type, reference,
+  difference_type>
+  reverse_iterator; 
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+protected:
+  link_type get_node() { return list_node_allocator::allocate(); }
+  void put_node(link_type p) { list_node_allocator::deallocate(p); }
+
+  link_type create_node(const T& x) {
+    link_type p = get_node();
+    __STL_TRY {
+      construct(&p->data, x);
+    }
+    __STL_UNWIND(put_node(p));
+    return p;
+  }
+  void destroy_node(link_type p) {
+    destroy(&p->data);
+    put_node(p);
+  }
+
+protected:
+  void empty_initialize() { 
+    node = get_node();
+    node->next = node;
+    node->prev = node;
+  }
+
+  void fill_initialize(size_type n, const T& value) {
+    empty_initialize();
+    __STL_TRY {
+      insert(begin(), n, value);
+    }
+    __STL_UNWIND(clear(); put_node(node));
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void range_initialize(InputIterator first, InputIterator last) {
+    empty_initialize();
+    __STL_TRY {
+      insert(begin(), first, last);
+    }
+    __STL_UNWIND(clear(); put_node(node));
+  }
+#else  /* __STL_MEMBER_TEMPLATES */
+  void range_initialize(const T* first, const T* last) {
+    empty_initialize();
+    __STL_TRY {
+      insert(begin(), first, last);
+    }
+    __STL_UNWIND(clear(); put_node(node));
+  }
+  void range_initialize(const_iterator first, const_iterator last) {
+    empty_initialize();
+    __STL_TRY {
+      insert(begin(), first, last);
+    }
+    __STL_UNWIND(clear(); put_node(node));
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+protected:
+  link_type node;
+
+public:
+  list() { empty_initialize(); }
+
+  iterator begin() { return (link_type)((*node).next); }
+  const_iterator begin() const { return (link_type)((*node).next); }
+  iterator end() { return node; }
+  const_iterator end() const { return node; }
+  reverse_iterator rbegin() { return reverse_iterator(end()); }
+  const_reverse_iterator rbegin() const { 
+    return const_reverse_iterator(end()); 
+  }
+  reverse_iterator rend() { return reverse_iterator(begin()); }
+  const_reverse_iterator rend() const { 
+    return const_reverse_iterator(begin());
+  } 
+  bool empty() const { return node->next == node; }
+  size_type size() const {
+    size_type result = 0;
+    distance(begin(), end(), result);
+    return result;
+  }
+  size_type max_size() const { return size_type(-1); }
+  reference front() { return *begin(); }
+  const_reference front() const { return *begin(); }
+  reference back() { return *(--end()); }
+  const_reference back() const { return *(--end()); }
+  void swap(list<T, Alloc>& x) { __STD::swap(node, x.node); }
+  iterator insert(iterator position, const T& x) {
+    link_type tmp = create_node(x);
+    tmp->next = position.node;
+    tmp->prev = position.node->prev;
+    (link_type(position.node->prev))->next = tmp;
+    position.node->prev = tmp;
+    return tmp;
+  }
+  iterator insert(iterator position) { return insert(position, T()); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert(iterator position, InputIterator first, InputIterator last);
+#else /* __STL_MEMBER_TEMPLATES */
+  void insert(iterator position, const T* first, const T* last);
+  void insert(iterator position,
+              const_iterator first, const_iterator last);
+#endif /* __STL_MEMBER_TEMPLATES */
+  void insert(iterator pos, size_type n, const T& x);
+  void insert(iterator pos, int n, const T& x) {
+    insert(pos, (size_type)n, x);
+  }
+  void insert(iterator pos, long n, const T& x) {
+    insert(pos, (size_type)n, x);
+  }
+
+  void push_front(const T& x) { insert(begin(), x); }
+  void push_back(const T& x) { insert(end(), x); }
+  iterator erase(iterator position) {
+    link_type next_node = link_type(position.node->next);
+    link_type prev_node = link_type(position.node->prev);
+    prev_node->next = next_node;
+    next_node->prev = prev_node;
+    destroy_node(position.node);
+    return iterator(next_node);
+  }
+  iterator erase(iterator first, iterator last);
+  void resize(size_type new_size, const T& x);
+  void resize(size_type new_size) { resize(new_size, T()); }
+  void clear();
+
+  void pop_front() { erase(begin()); }
+  void pop_back() { 
+    iterator tmp = end();
+    erase(--tmp);
+  }
+  list(size_type n, const T& value) { fill_initialize(n, value); }
+  list(int n, const T& value) { fill_initialize(n, value); }
+  list(long n, const T& value) { fill_initialize(n, value); }
+  explicit list(size_type n) { fill_initialize(n, T()); }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  list(InputIterator first, InputIterator last) {
+    range_initialize(first, last);
+  }
+
+#else /* __STL_MEMBER_TEMPLATES */
+  list(const T* first, const T* last) { range_initialize(first, last); }
+  list(const_iterator first, const_iterator last) {
+    range_initialize(first, last);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+  list(const list<T, Alloc>& x) {
+    range_initialize(x.begin(), x.end());
+  }
+  ~list() {
+    clear();
+    put_node(node);
+  }
+  list<T, Alloc>& operator=(const list<T, Alloc>& x);
+
+protected:
+  void transfer(iterator position, iterator first, iterator last) {
+    if (position != last) {
+      (*(link_type((*last.node).prev))).next = position.node;
+      (*(link_type((*first.node).prev))).next = last.node;
+      (*(link_type((*position.node).prev))).next = first.node;  
+      link_type tmp = link_type((*position.node).prev);
+      (*position.node).prev = (*last.node).prev;
+      (*last.node).prev = (*first.node).prev; 
+      (*first.node).prev = tmp;
+    }
+  }
+
+public:
+  void splice(iterator position, list& x) {
+    if (!x.empty()) 
+      transfer(position, x.begin(), x.end());
+  }
+  void splice(iterator position, list&, iterator i) {
+    iterator j = i;
+    ++j;
+    if (position == i || position == j) return;
+    transfer(position, i, j);
+  }
+  void splice(iterator position, list&, iterator first, iterator last) {
+    if (first != last) 
+      transfer(position, first, last);
+  }
+  void remove(const T& value);
+  void unique();
+  void merge(list& x);
+  void reverse();
+  void sort();
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class Predicate> void remove_if(Predicate);
+  template <class BinaryPredicate> void unique(BinaryPredicate);
+  template <class StrictWeakOrdering> void merge(list&, StrictWeakOrdering);
+  template <class StrictWeakOrdering> void sort(StrictWeakOrdering);
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  friend bool operator== __STL_NULL_TMPL_ARGS (const list& x, const list& y);
+};
+
+template <class T, class Alloc>
+inline bool operator==(const list<T,Alloc>& x, const list<T,Alloc>& y) {
+  typedef typename list<T,Alloc>::link_type link_type;
+  link_type e1 = x.node;
+  link_type e2 = y.node;
+  link_type n1 = (link_type) e1->next;
+  link_type n2 = (link_type) e2->next;
+  for ( ; n1 != e1 && n2 != e2 ;
+          n1 = (link_type) n1->next, n2 = (link_type) n2->next)
+    if (n1->data != n2->data)
+      return false;
+  return n1 == e1 && n2 == e2;
+}
+
+template <class T, class Alloc>
+inline bool operator<(const list<T, Alloc>& x, const list<T, Alloc>& y) {
+  return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class T, class Alloc>
+inline void swap(list<T, Alloc>& x, list<T, Alloc>& y) {
+  x.swap(y);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+template <class T, class Alloc> template <class InputIterator>
+void list<T, Alloc>::insert(iterator position,
+                            InputIterator first, InputIterator last) {
+  for ( ; first != last; ++first)
+    insert(position, *first);
+}
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc>
+void list<T, Alloc>::insert(iterator position, const T* first, const T* last) {
+  for ( ; first != last; ++first)
+    insert(position, *first);
+}
+
+template <class T, class Alloc>
+void list<T, Alloc>::insert(iterator position,
+                            const_iterator first, const_iterator last) {
+  for ( ; first != last; ++first)
+    insert(position, *first);
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc>
+void list<T, Alloc>::insert(iterator position, size_type n, const T& x) {
+  for ( ; n > 0; --n)
+    insert(position, x);
+}
+
+template <class T, class Alloc>
+list<T,Alloc>::iterator list<T, Alloc>::erase(iterator first, iterator last) {
+  while (first != last) erase(first++);
+  return last;
+}
+
+template <class T, class Alloc>
+void list<T, Alloc>::resize(size_type new_size, const T& x)
+{
+  iterator i = begin();
+  size_type len = 0;
+  for ( ; i != end() && len < new_size; ++i, ++len)
+    ;
+  if (len == new_size)
+    erase(i, end());
+  else                          // i == end()
+    insert(end(), new_size - len, x);
+}
+
+template <class T, class Alloc> 
+void list<T, Alloc>::clear()
+{
+  link_type cur = (link_type) node->next;
+  while (cur != node) {
+    link_type tmp = cur;
+    cur = (link_type) cur->next;
+    destroy_node(tmp);
+  }
+  node->next = node;
+  node->prev = node;
+}
+
+template <class T, class Alloc>
+list<T, Alloc>& list<T, Alloc>::operator=(const list<T, Alloc>& x) {
+  if (this != &x) {
+    iterator first1 = begin();
+    iterator last1 = end();
+    const_iterator first2 = x.begin();
+    const_iterator last2 = x.end();
+    while (first1 != last1 && first2 != last2) *first1++ = *first2++;
+    if (first2 == last2)
+      erase(first1, last1);
+    else
+      insert(last1, first2, last2);
+  }
+  return *this;
+}
+
+template <class T, class Alloc>
+void list<T, Alloc>::remove(const T& value) {
+  iterator first = begin();
+  iterator last = end();
+  while (first != last) {
+    iterator next = first;
+    ++next;
+    if (*first == value) erase(first);
+    first = next;
+  }
+}
+
+template <class T, class Alloc>
+void list<T, Alloc>::unique() {
+  iterator first = begin();
+  iterator last = end();
+  if (first == last) return;
+  iterator next = first;
+  while (++next != last) {
+    if (*first == *next)
+      erase(next);
+    else
+      first = next;
+    next = first;
+  }
+}
+
+template <class T, class Alloc>
+void list<T, Alloc>::merge(list<T, Alloc>& x) {
+  iterator first1 = begin();
+  iterator last1 = end();
+  iterator first2 = x.begin();
+  iterator last2 = x.end();
+  while (first1 != last1 && first2 != last2)
+    if (*first2 < *first1) {
+      iterator next = first2;
+      transfer(first1, first2, ++next);
+      first2 = next;
+    }
+    else
+      ++first1;
+  if (first2 != last2) transfer(last1, first2, last2);
+}
+
+template <class T, class Alloc>
+void list<T, Alloc>::reverse() {
+  if (node->next == node || link_type(node->next)->next == node) return;
+  iterator first = begin();
+  ++first;
+  while (first != end()) {
+    iterator old = first;
+    ++first;
+    transfer(begin(), old, first);
+  }
+}    
+
+template <class T, class Alloc>
+void list<T, Alloc>::sort() {
+  if (node->next == node || link_type(node->next)->next == node) return;
+  list<T, Alloc> carry;
+  list<T, Alloc> counter[64];
+  int fill = 0;
+  while (!empty()) {
+    carry.splice(carry.begin(), *this, begin());
+    int i = 0;
+    while(i < fill && !counter[i].empty()) {
+      counter[i].merge(carry);
+      carry.swap(counter[i++]);
+    }
+    carry.swap(counter[i]);         
+    if (i == fill) ++fill;
+  } 
+
+  for (int i = 1; i < fill; ++i) counter[i].merge(counter[i-1]);
+  swap(counter[fill-1]);
+}
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+template <class T, class Alloc> template <class Predicate>
+void list<T, Alloc>::remove_if(Predicate pred) {
+  iterator first = begin();
+  iterator last = end();
+  while (first != last) {
+    iterator next = first;
+    ++next;
+    if (pred(*first)) erase(first);
+    first = next;
+  }
+}
+
+template <class T, class Alloc> template <class BinaryPredicate>
+void list<T, Alloc>::unique(BinaryPredicate binary_pred) {
+  iterator first = begin();
+  iterator last = end();
+  if (first == last) return;
+  iterator next = first;
+  while (++next != last) {
+    if (binary_pred(*first, *next))
+      erase(next);
+    else
+      first = next;
+    next = first;
+  }
+}
+
+template <class T, class Alloc> template <class StrictWeakOrdering>
+void list<T, Alloc>::merge(list<T, Alloc>& x, StrictWeakOrdering comp) {
+  iterator first1 = begin();
+  iterator last1 = end();
+  iterator first2 = x.begin();
+  iterator last2 = x.end();
+  while (first1 != last1 && first2 != last2)
+    if (comp(*first2, *first1)) {
+      iterator next = first2;
+      transfer(first1, first2, ++next);
+      first2 = next;
+    }
+    else
+      ++first1;
+  if (first2 != last2) transfer(last1, first2, last2);
+}
+
+template <class T, class Alloc> template <class StrictWeakOrdering>
+void list<T, Alloc>::sort(StrictWeakOrdering comp) {
+  if (node->next == node || link_type(node->next)->next == node) return;
+  list<T, Alloc> carry;
+  list<T, Alloc> counter[64];
+  int fill = 0;
+  while (!empty()) {
+    carry.splice(carry.begin(), *this, begin());
+    int i = 0;
+    while(i < fill && !counter[i].empty()) {
+      counter[i].merge(carry, comp);
+      carry.swap(counter[i++]);
+    }
+    carry.swap(counter[i]);         
+    if (i == fill) ++fill;
+  } 
+
+  for (int i = 1; i < fill; ++i) counter[i].merge(counter[i-1], comp);
+  swap(counter[fill-1]);
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE 
+
+#endif /* __SGI_STL_INTERNAL_LIST_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_map.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_map.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_map.h	(revision 18)
@@ -0,0 +1,217 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_MAP_H
+#define __SGI_STL_INTERNAL_MAP_H
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
+#else
+template <class Key, class T, class Compare, class Alloc = alloc>
+#endif
+class map {
+public:
+
+// typedefs:
+
+  typedef Key key_type;
+  typedef T data_type;
+  typedef T mapped_type;
+  typedef pair<const Key, T> value_type;
+  typedef Compare key_compare;
+    
+  class value_compare
+    : public binary_function<value_type, value_type, bool> {
+  friend class map<Key, T, Compare, Alloc>;
+  protected :
+    Compare comp;
+    value_compare(Compare c) : comp(c) {}
+  public:
+    bool operator()(const value_type& x, const value_type& y) const {
+      return comp(x.first, y.first);
+    }
+  };
+
+private:
+  typedef rb_tree<key_type, value_type, 
+                  select1st<value_type>, key_compare, Alloc> rep_type;
+  rep_type t;  // red-black tree representing map
+public:
+  typedef typename rep_type::pointer pointer;
+  typedef typename rep_type::const_pointer const_pointer;
+  typedef typename rep_type::reference reference;
+  typedef typename rep_type::const_reference const_reference;
+  typedef typename rep_type::iterator iterator;
+  typedef typename rep_type::const_iterator const_iterator;
+  typedef typename rep_type::reverse_iterator reverse_iterator;
+  typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
+  typedef typename rep_type::size_type size_type;
+  typedef typename rep_type::difference_type difference_type;
+
+  // allocation/deallocation
+
+  map() : t(Compare()) {}
+  explicit map(const Compare& comp) : t(comp) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  map(InputIterator first, InputIterator last)
+    : t(Compare()) { t.insert_unique(first, last); }
+
+  template <class InputIterator>
+  map(InputIterator first, InputIterator last, const Compare& comp)
+    : t(comp) { t.insert_unique(first, last); }
+#else
+  map(const value_type* first, const value_type* last)
+    : t(Compare()) { t.insert_unique(first, last); }
+  map(const value_type* first, const value_type* last, const Compare& comp)
+    : t(comp) { t.insert_unique(first, last); }
+
+  map(const_iterator first, const_iterator last)
+    : t(Compare()) { t.insert_unique(first, last); }
+  map(const_iterator first, const_iterator last, const Compare& comp)
+    : t(comp) { t.insert_unique(first, last); }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  map(const map<Key, T, Compare, Alloc>& x) : t(x.t) {}
+  map<Key, T, Compare, Alloc>& operator=(const map<Key, T, Compare, Alloc>& x)
+  {
+    t = x.t;
+    return *this; 
+  }
+
+  // accessors:
+
+  key_compare key_comp() const { return t.key_comp(); }
+  value_compare value_comp() const { return value_compare(t.key_comp()); }
+  iterator begin() { return t.begin(); }
+  const_iterator begin() const { return t.begin(); }
+  iterator end() { return t.end(); }
+  const_iterator end() const { return t.end(); }
+  reverse_iterator rbegin() { return t.rbegin(); }
+  const_reverse_iterator rbegin() const { return t.rbegin(); }
+  reverse_iterator rend() { return t.rend(); }
+  const_reverse_iterator rend() const { return t.rend(); }
+  bool empty() const { return t.empty(); }
+  size_type size() const { return t.size(); }
+  size_type max_size() const { return t.max_size(); }
+  T& operator[](const key_type& k) {
+    return (*((insert(value_type(k, T()))).first)).second;
+  }
+  void swap(map<Key, T, Compare, Alloc>& x) { t.swap(x.t); }
+
+  // insert/erase
+
+  pair<iterator,bool> insert(const value_type& x) { return t.insert_unique(x); }
+  iterator insert(iterator position, const value_type& x) {
+    return t.insert_unique(position, x);
+  }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert(InputIterator first, InputIterator last) {
+    t.insert_unique(first, last);
+  }
+#else
+  void insert(const value_type* first, const value_type* last) {
+    t.insert_unique(first, last);
+  }
+  void insert(const_iterator first, const_iterator last) {
+    t.insert_unique(first, last);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  void erase(iterator position) { t.erase(position); }
+  size_type erase(const key_type& x) { return t.erase(x); }
+  void erase(iterator first, iterator last) { t.erase(first, last); }
+  void clear() { t.clear(); }
+
+  // map operations:
+
+  iterator find(const key_type& x) { return t.find(x); }
+  const_iterator find(const key_type& x) const { return t.find(x); }
+  size_type count(const key_type& x) const { return t.count(x); }
+  iterator lower_bound(const key_type& x) {return t.lower_bound(x); }
+  const_iterator lower_bound(const key_type& x) const {
+    return t.lower_bound(x); 
+  }
+  iterator upper_bound(const key_type& x) {return t.upper_bound(x); }
+  const_iterator upper_bound(const key_type& x) const {
+    return t.upper_bound(x); 
+  }
+  
+  pair<iterator,iterator> equal_range(const key_type& x) {
+    return t.equal_range(x);
+  }
+  pair<const_iterator,const_iterator> equal_range(const key_type& x) const {
+    return t.equal_range(x);
+  }
+  friend bool operator== __STL_NULL_TMPL_ARGS (const map&, const map&);
+  friend bool operator< __STL_NULL_TMPL_ARGS (const map&, const map&);
+};
+
+template <class Key, class T, class Compare, class Alloc>
+inline bool operator==(const map<Key, T, Compare, Alloc>& x, 
+                       const map<Key, T, Compare, Alloc>& y) {
+  return x.t == y.t;
+}
+
+template <class Key, class T, class Compare, class Alloc>
+inline bool operator<(const map<Key, T, Compare, Alloc>& x, 
+                      const map<Key, T, Compare, Alloc>& y) {
+  return x.t < y.t;
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Key, class T, class Compare, class Alloc>
+inline void swap(map<Key, T, Compare, Alloc>& x, 
+                 map<Key, T, Compare, Alloc>& y) {
+  x.swap(y);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_MAP_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_mmap.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_mmap.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_mmap.h	(revision 18)
@@ -0,0 +1,214 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_MULTIMAP_H
+#define __SGI_STL_INTERNAL_MULTIMAP_H
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
+#else
+template <class Key, class T, class Compare, class Alloc = alloc>
+#endif
+class multimap {
+public:
+
+// typedefs:
+
+  typedef Key key_type;
+  typedef T data_type;
+  typedef T mapped_type;
+  typedef pair<const Key, T> value_type;
+  typedef Compare key_compare;
+
+  class value_compare : public binary_function<value_type, value_type, bool> {
+  friend class multimap<Key, T, Compare, Alloc>;
+  protected:
+    Compare comp;
+    value_compare(Compare c) : comp(c) {}
+  public:
+    bool operator()(const value_type& x, const value_type& y) const {
+      return comp(x.first, y.first);
+    }
+  };
+
+private:
+  typedef rb_tree<key_type, value_type, 
+                  select1st<value_type>, key_compare, Alloc> rep_type;
+  rep_type t;  // red-black tree representing multimap
+public:
+  typedef typename rep_type::pointer pointer;
+  typedef typename rep_type::const_pointer const_pointer;
+  typedef typename rep_type::reference reference;
+  typedef typename rep_type::const_reference const_reference;
+  typedef typename rep_type::iterator iterator;
+  typedef typename rep_type::const_iterator const_iterator; 
+  typedef typename rep_type::reverse_iterator reverse_iterator;
+  typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
+  typedef typename rep_type::size_type size_type;
+  typedef typename rep_type::difference_type difference_type;
+
+// allocation/deallocation
+
+  multimap() : t(Compare()) { }
+  explicit multimap(const Compare& comp) : t(comp) { }
+
+#ifdef __STL_MEMBER_TEMPLATES  
+  template <class InputIterator>
+  multimap(InputIterator first, InputIterator last)
+    : t(Compare()) { t.insert_equal(first, last); }
+
+  template <class InputIterator>
+  multimap(InputIterator first, InputIterator last, const Compare& comp)
+    : t(comp) { t.insert_equal(first, last); }
+#else
+  multimap(const value_type* first, const value_type* last)
+    : t(Compare()) { t.insert_equal(first, last); }
+  multimap(const value_type* first, const value_type* last,
+           const Compare& comp)
+    : t(comp) { t.insert_equal(first, last); }
+
+  multimap(const_iterator first, const_iterator last)
+    : t(Compare()) { t.insert_equal(first, last); }
+  multimap(const_iterator first, const_iterator last, const Compare& comp)
+    : t(comp) { t.insert_equal(first, last); }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  multimap(const multimap<Key, T, Compare, Alloc>& x) : t(x.t) { }
+  multimap<Key, T, Compare, Alloc>&
+  operator=(const multimap<Key, T, Compare, Alloc>& x) {
+    t = x.t;
+    return *this; 
+  }
+
+  // accessors:
+
+  key_compare key_comp() const { return t.key_comp(); }
+  value_compare value_comp() const { return value_compare(t.key_comp()); }
+  iterator begin() { return t.begin(); }
+  const_iterator begin() const { return t.begin(); }
+  iterator end() { return t.end(); }
+  const_iterator end() const { return t.end(); }
+  reverse_iterator rbegin() { return t.rbegin(); }
+  const_reverse_iterator rbegin() const { return t.rbegin(); }
+  reverse_iterator rend() { return t.rend(); }
+  const_reverse_iterator rend() const { return t.rend(); }
+  bool empty() const { return t.empty(); }
+  size_type size() const { return t.size(); }
+  size_type max_size() const { return t.max_size(); }
+  void swap(multimap<Key, T, Compare, Alloc>& x) { t.swap(x.t); }
+
+  // insert/erase
+
+  iterator insert(const value_type& x) { return t.insert_equal(x); }
+  iterator insert(iterator position, const value_type& x) {
+    return t.insert_equal(position, x);
+  }
+#ifdef __STL_MEMBER_TEMPLATES  
+  template <class InputIterator>
+  void insert(InputIterator first, InputIterator last) {
+    t.insert_equal(first, last);
+  }
+#else
+  void insert(const value_type* first, const value_type* last) {
+    t.insert_equal(first, last);
+  }
+  void insert(const_iterator first, const_iterator last) {
+    t.insert_equal(first, last);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+  void erase(iterator position) { t.erase(position); }
+  size_type erase(const key_type& x) { return t.erase(x); }
+  void erase(iterator first, iterator last) { t.erase(first, last); }
+  void clear() { t.clear(); }
+
+  // multimap operations:
+
+  iterator find(const key_type& x) { return t.find(x); }
+  const_iterator find(const key_type& x) const { return t.find(x); }
+  size_type count(const key_type& x) const { return t.count(x); }
+  iterator lower_bound(const key_type& x) {return t.lower_bound(x); }
+  const_iterator lower_bound(const key_type& x) const {
+    return t.lower_bound(x); 
+  }
+  iterator upper_bound(const key_type& x) {return t.upper_bound(x); }
+  const_iterator upper_bound(const key_type& x) const {
+    return t.upper_bound(x); 
+  }
+   pair<iterator,iterator> equal_range(const key_type& x) {
+    return t.equal_range(x);
+  }
+  pair<const_iterator,const_iterator> equal_range(const key_type& x) const {
+    return t.equal_range(x);
+  }
+  friend bool operator== __STL_NULL_TMPL_ARGS (const multimap&,
+                                               const multimap&);
+  friend bool operator< __STL_NULL_TMPL_ARGS (const multimap&,
+                                              const multimap&);
+};
+
+template <class Key, class T, class Compare, class Alloc>
+inline bool operator==(const multimap<Key, T, Compare, Alloc>& x, 
+                       const multimap<Key, T, Compare, Alloc>& y) {
+  return x.t == y.t;
+}
+
+template <class Key, class T, class Compare, class Alloc>
+inline bool operator<(const multimap<Key, T, Compare, Alloc>& x, 
+                      const multimap<Key, T, Compare, Alloc>& y) {
+  return x.t < y.t;
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Key, class T, class Compare, class Alloc>
+inline void swap(multimap<Key, T, Compare, Alloc>& x, 
+                 multimap<Key, T, Compare, Alloc>& y) {
+  x.swap(y);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_MULTIMAP_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_mset.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_mset.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_mset.h	(revision 18)
@@ -0,0 +1,200 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_MULTISET_H
+#define __SGI_STL_INTERNAL_MULTISET_H
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Key, class Compare = less<Key>, class Alloc = alloc>
+#else
+template <class Key, class Compare, class Alloc = alloc>
+#endif
+class multiset {
+public:
+  // typedefs:
+
+  typedef Key key_type;
+  typedef Key value_type;
+  typedef Compare key_compare;
+  typedef Compare value_compare;
+private:
+  typedef rb_tree<key_type, value_type, 
+                  identity<value_type>, key_compare, Alloc> rep_type;
+  rep_type t;  // red-black tree representing multiset
+public:
+  typedef typename rep_type::const_pointer pointer;
+  typedef typename rep_type::const_pointer const_pointer;
+  typedef typename rep_type::const_reference reference;
+  typedef typename rep_type::const_reference const_reference;
+  typedef typename rep_type::const_iterator iterator;
+  typedef typename rep_type::const_iterator const_iterator;
+  typedef typename rep_type::const_reverse_iterator reverse_iterator;
+  typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
+  typedef typename rep_type::size_type size_type;
+  typedef typename rep_type::difference_type difference_type;
+
+  // allocation/deallocation
+
+  multiset() : t(Compare()) {}
+  explicit multiset(const Compare& comp) : t(comp) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  multiset(InputIterator first, InputIterator last)
+    : t(Compare()) { t.insert_equal(first, last); }
+  template <class InputIterator>
+  multiset(InputIterator first, InputIterator last, const Compare& comp)
+    : t(comp) { t.insert_equal(first, last); }
+#else
+  multiset(const value_type* first, const value_type* last)
+    : t(Compare()) { t.insert_equal(first, last); }
+  multiset(const value_type* first, const value_type* last,
+           const Compare& comp)
+    : t(comp) { t.insert_equal(first, last); }
+
+  multiset(const_iterator first, const_iterator last)
+    : t(Compare()) { t.insert_equal(first, last); }
+  multiset(const_iterator first, const_iterator last, const Compare& comp)
+    : t(comp) { t.insert_equal(first, last); }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  multiset(const multiset<Key, Compare, Alloc>& x) : t(x.t) {}
+  multiset<Key, Compare, Alloc>&
+  operator=(const multiset<Key, Compare, Alloc>& x) {
+    t = x.t; 
+    return *this;
+  }
+
+  // accessors:
+
+  key_compare key_comp() const { return t.key_comp(); }
+  value_compare value_comp() const { return t.key_comp(); }
+  iterator begin() const { return t.begin(); }
+  iterator end() const { return t.end(); }
+  reverse_iterator rbegin() const { return t.rbegin(); } 
+  reverse_iterator rend() const { return t.rend(); }
+  bool empty() const { return t.empty(); }
+  size_type size() const { return t.size(); }
+  size_type max_size() const { return t.max_size(); }
+  void swap(multiset<Key, Compare, Alloc>& x) { t.swap(x.t); }
+
+  // insert/erase
+  iterator insert(const value_type& x) { 
+    return t.insert_equal(x);
+  }
+  iterator insert(iterator position, const value_type& x) {
+    typedef typename rep_type::iterator rep_iterator;
+    return t.insert_equal((rep_iterator&)position, x);
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES  
+  template <class InputIterator>
+  void insert(InputIterator first, InputIterator last) {
+    t.insert_equal(first, last);
+  }
+#else
+  void insert(const value_type* first, const value_type* last) {
+    t.insert_equal(first, last);
+  }
+  void insert(const_iterator first, const_iterator last) {
+    t.insert_equal(first, last);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+  void erase(iterator position) { 
+    typedef typename rep_type::iterator rep_iterator;
+    t.erase((rep_iterator&)position); 
+  }
+  size_type erase(const key_type& x) { 
+    return t.erase(x); 
+  }
+  void erase(iterator first, iterator last) { 
+    typedef typename rep_type::iterator rep_iterator;
+    t.erase((rep_iterator&)first, (rep_iterator&)last); 
+  }
+  void clear() { t.clear(); }
+
+  // multiset operations:
+
+  iterator find(const key_type& x) const { return t.find(x); }
+  size_type count(const key_type& x) const { return t.count(x); }
+  iterator lower_bound(const key_type& x) const {
+    return t.lower_bound(x);
+  }
+  iterator upper_bound(const key_type& x) const {
+    return t.upper_bound(x); 
+  }
+  pair<iterator,iterator> equal_range(const key_type& x) const {
+    return t.equal_range(x);
+  }
+  friend bool operator== __STL_NULL_TMPL_ARGS (const multiset&,
+                                               const multiset&);
+  friend bool operator< __STL_NULL_TMPL_ARGS (const multiset&,
+                                              const multiset&);
+};
+
+template <class Key, class Compare, class Alloc>
+inline bool operator==(const multiset<Key, Compare, Alloc>& x, 
+                       const multiset<Key, Compare, Alloc>& y) {
+  return x.t == y.t;
+}
+
+template <class Key, class Compare, class Alloc>
+inline bool operator<(const multiset<Key, Compare, Alloc>& x, 
+                      const multiset<Key, Compare, Alloc>& y) {
+  return x.t < y.t;
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Key, class Compare, class Alloc>
+inline void swap(multiset<Key, Compare, Alloc>& x, 
+                 multiset<Key, Compare, Alloc>& y) {
+  x.swap(y);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_MULTISET_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_nume.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_nume.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_nume.h	(revision 18)
@@ -0,0 +1,196 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+
+#ifndef __SGI_STL_INTERNAL_NUMERIC_H
+#define __SGI_STL_INTERNAL_NUMERIC_H
+
+__STL_BEGIN_NAMESPACE
+
+template <class InputIterator, class T>
+T accumulate(InputIterator first, InputIterator last, T init) {
+  for ( ; first != last; ++first)
+    init = init + *first;
+  return init;
+}
+
+template <class InputIterator, class T, class BinaryOperation>
+T accumulate(InputIterator first, InputIterator last, T init,
+             BinaryOperation binary_op) {
+  for ( ; first != last; ++first)
+    init = binary_op(init, *first);
+  return init;
+}
+
+template <class InputIterator1, class InputIterator2, class T>
+T inner_product(InputIterator1 first1, InputIterator1 last1,
+                InputIterator2 first2, T init) {
+  for ( ; first1 != last1; ++first1, ++first2)
+    init = init + (*first1 * *first2);
+  return init;
+}
+
+template <class InputIterator1, class InputIterator2, class T,
+          class BinaryOperation1, class BinaryOperation2>
+T inner_product(InputIterator1 first1, InputIterator1 last1,
+                InputIterator2 first2, T init, BinaryOperation1 binary_op1,
+                BinaryOperation2 binary_op2) {
+  for ( ; first1 != last1; ++first1, ++first2)
+    init = binary_op1(init, binary_op2(*first1, *first2));
+  return init;
+}
+
+template <class InputIterator, class OutputIterator, class T>
+OutputIterator __partial_sum(InputIterator first, InputIterator last,
+                             OutputIterator result, T*) {
+  T value = *first;
+  while (++first != last) {
+    value = value + *first;
+    *++result = value;
+  }
+  return ++result;
+}
+
+template <class InputIterator, class OutputIterator>
+OutputIterator partial_sum(InputIterator first, InputIterator last,
+                           OutputIterator result) {
+  if (first == last) return result;
+  *result = *first;
+  return __partial_sum(first, last, result, value_type(first));
+}
+
+template <class InputIterator, class OutputIterator, class T,
+          class BinaryOperation>
+OutputIterator __partial_sum(InputIterator first, InputIterator last,
+                             OutputIterator result, T*,
+                             BinaryOperation binary_op) {
+  T value = *first;
+  while (++first != last) {
+    value = binary_op(value, *first);
+    *++result = value;
+  }
+  return ++result;
+}
+
+template <class InputIterator, class OutputIterator, class BinaryOperation>
+OutputIterator partial_sum(InputIterator first, InputIterator last,
+                           OutputIterator result, BinaryOperation binary_op) {
+  if (first == last) return result;
+  *result = *first;
+  return __partial_sum(first, last, result, value_type(first), binary_op);
+}
+
+template <class InputIterator, class OutputIterator, class T>
+OutputIterator __adjacent_difference(InputIterator first, InputIterator last, 
+                                     OutputIterator result, T*) {
+  T value = *first;
+  while (++first != last) {
+    T tmp = *first;
+    *++result = tmp - value;
+    value = tmp;
+  }
+  return ++result;
+}
+
+template <class InputIterator, class OutputIterator>
+OutputIterator adjacent_difference(InputIterator first, InputIterator last, 
+                                   OutputIterator result) {
+  if (first == last) return result;
+  *result = *first;
+  return __adjacent_difference(first, last, result, value_type(first));
+}
+
+template <class InputIterator, class OutputIterator, class T, 
+          class BinaryOperation>
+OutputIterator __adjacent_difference(InputIterator first, InputIterator last, 
+                                     OutputIterator result, T*,
+                                     BinaryOperation binary_op) {
+  T value = *first;
+  while (++first != last) {
+    T tmp = *first;
+    *++result = binary_op(tmp, value);
+    value = tmp;
+  }
+  return ++result;
+}
+
+template <class InputIterator, class OutputIterator, class BinaryOperation>
+OutputIterator adjacent_difference(InputIterator first, InputIterator last,
+                                   OutputIterator result,
+                                   BinaryOperation binary_op) {
+  if (first == last) return result;
+  *result = *first;
+  return __adjacent_difference(first, last, result, value_type(first),
+                               binary_op);
+}
+
+// Returns x ** n, where n >= 0.  Note that "multiplication"
+//  is required to be associative, but not necessarily commutative.
+    
+template <class T, class Integer, class MonoidOperation>
+T power(T x, Integer n, MonoidOperation op) {
+  if (n == 0)
+    return identity_element(op);
+  else {
+    while ((n & 1) == 0) {
+      n >>= 1;
+      x = op(x, x);
+    }
+
+    T result = x;
+    n >>= 1;
+    while (n != 0) {
+      x = op(x, x);
+      if ((n & 1) != 0)
+        result = op(result, x);
+      n >>= 1;
+    }
+    return result;
+  }
+}
+
+template <class T, class Integer>
+inline T power(T x, Integer n) {
+  return power(x, n, multiplies<T>());
+}
+
+
+template <class ForwardIterator, class T>
+void iota(ForwardIterator first, ForwardIterator last, T value) {
+  while (first != last) *first++ = value++;
+}
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_NUMERIC_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_pair.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_pair.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_pair.h	(revision 18)
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_PAIR_H
+#define __SGI_STL_INTERNAL_PAIR_H
+
+__STL_BEGIN_NAMESPACE
+
+template <class T1, class T2>
+struct pair {
+  typedef T1 first_type;
+  typedef T2 second_type;
+
+  T1 first;
+  T2 second;
+  pair() : first(T1()), second(T2()) {}
+  pair(const T1& a, const T2& b) : first(a), second(b) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class U1, class U2>
+  pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}
+#endif
+};
+
+template <class T1, class T2>
+inline bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y) { 
+  return x.first == y.first && x.second == y.second; 
+}
+
+template <class T1, class T2>
+inline bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y) { 
+  return x.first < y.first || (!(y.first < x.first) && x.second < y.second); 
+}
+
+template <class T1, class T2>
+inline pair<T1, T2> make_pair(const T1& x, const T2& y) {
+  return pair<T1, T2>(x, y);
+}
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_PAIR_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_queu.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_queu.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_queu.h	(revision 18)
@@ -0,0 +1,134 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_QUEUE_H
+#define __SGI_STL_INTERNAL_QUEUE_H
+
+__STL_BEGIN_NAMESPACE
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class T, class Sequence = deque<T> >
+#else
+template <class T, class Sequence>
+#endif
+class queue {
+  friend bool operator== __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
+  friend bool operator< __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
+public:
+  typedef typename Sequence::value_type value_type;
+  typedef typename Sequence::size_type size_type;
+  typedef typename Sequence::reference reference;
+  typedef typename Sequence::const_reference const_reference;
+protected:
+  Sequence c;
+public:
+  bool empty() const { return c.empty(); }
+  size_type size() const { return c.size(); }
+  reference front() { return c.front(); }
+  const_reference front() const { return c.front(); }
+  reference back() { return c.back(); }
+  const_reference back() const { return c.back(); }
+  void push(const value_type& x) { c.push_back(x); }
+  void pop() { c.pop_front(); }
+};
+
+template <class T, class Sequence>
+bool operator==(const queue<T, Sequence>& x, const queue<T, Sequence>& y) {
+  return x.c == y.c;
+}
+
+template <class T, class Sequence>
+bool operator<(const queue<T, Sequence>& x, const queue<T, Sequence>& y) {
+  return x.c < y.c;
+}
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class T, class Sequence = vector<T>, 
+          class Compare = less<typename Sequence::value_type> >
+#else
+template <class T, class Sequence, class Compare>
+#endif
+class  priority_queue {
+public:
+  typedef typename Sequence::value_type value_type;
+  typedef typename Sequence::size_type size_type;
+  typedef typename Sequence::reference reference;
+  typedef typename Sequence::const_reference const_reference;
+protected:
+  Sequence c;
+  Compare comp;
+public:
+  priority_queue() : c() {}
+  explicit priority_queue(const Compare& x) :  c(), comp(x) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  priority_queue(InputIterator first, InputIterator last, const Compare& x)
+    : c(first, last), comp(x) { make_heap(c.begin(), c.end(), comp); }
+  template <class InputIterator>
+  priority_queue(InputIterator first, InputIterator last) 
+    : c(first, last) { make_heap(c.begin(), c.end(), comp); }
+#else /* __STL_MEMBER_TEMPLATES */
+  priority_queue(const value_type* first, const value_type* last, 
+                 const Compare& x) : c(first, last), comp(x) {
+    make_heap(c.begin(), c.end(), comp);
+  }
+  priority_queue(const value_type* first, const value_type* last) 
+    : c(first, last) { make_heap(c.begin(), c.end(), comp); }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  bool empty() const { return c.empty(); }
+  size_type size() const { return c.size(); }
+  const_reference top() const { return c.front(); }
+  void push(const value_type& x) {
+    __STL_TRY {
+      c.push_back(x); 
+      push_heap(c.begin(), c.end(), comp);
+    }
+    __STL_UNWIND(c.clear());
+  }
+  void pop() {
+    __STL_TRY {
+      pop_heap(c.begin(), c.end(), comp);
+      c.pop_back();
+    }
+    __STL_UNWIND(c.clear());
+  }
+};
+
+// no equality is provided
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_QUEUE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_raw_.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_raw_.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_raw_.h	(revision 18)
@@ -0,0 +1,81 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_RAW_STORAGE_ITERATOR_H
+#define __SGI_STL_INTERNAL_RAW_STORAGE_ITERATOR_H
+
+__STL_BEGIN_NAMESPACE
+
+template <class ForwardIterator, class T>
+class raw_storage_iterator {
+protected:
+  ForwardIterator iter;
+public:
+  typedef output_iterator_tag iterator_category;
+  typedef void                value_type;
+  typedef void                difference_type;
+  typedef void                pointer;
+  typedef void                reference;
+
+  explicit raw_storage_iterator(ForwardIterator x) : iter(x) {}
+  raw_storage_iterator<ForwardIterator, T>& operator*() { return *this; }
+  raw_storage_iterator<ForwardIterator, T>& operator=(const T& element) {
+    construct(&*iter, element);
+    return *this;
+  }        
+  raw_storage_iterator<ForwardIterator, T>& operator++() {
+    ++iter;
+    return *this;
+  }
+  raw_storage_iterator<ForwardIterator, T> operator++(int) {
+    raw_storage_iterator<ForwardIterator, T> tmp = *this;
+    ++iter;
+    return tmp;
+  }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class ForwardIterator, class T>
+inline output_iterator_tag
+iterator_category(const raw_storage_iterator<ForwardIterator, T>&)
+{
+  return output_iterator_tag();
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+#endif /* __SGI_STL_INTERNAL_RAW_STORAGE_ITERATOR_H */
+
+__STL_END_NAMESPACE
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_relo.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_relo.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_relo.h	(revision 18)
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_RELOPS
+#define __SGI_STL_INTERNAL_RELOPS
+
+__STL_BEGIN_RELOPS_NAMESPACE
+
+template <class T>
+inline bool operator!=(const T& x, const T& y) {
+  return !(x == y);
+}
+
+template <class T>
+inline bool operator>(const T& x, const T& y) {
+  return y < x;
+}
+
+template <class T>
+inline bool operator<=(const T& x, const T& y) {
+  return !(y < x);
+}
+
+template <class T>
+inline bool operator>=(const T& x, const T& y) {
+  return !(x < y);
+}
+
+__STL_END_RELOPS_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_RELOPS */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_rope.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_rope.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_rope.h	(revision 18)
@@ -0,0 +1,2112 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_ROPE_H
+# define __SGI_STL_INTERNAL_ROPE_H
+
+# ifdef __GC
+#   define __GC_CONST const
+# else
+#   define __GC_CONST   // constant except for deallocation
+# endif
+# ifdef __STL_SGI_THREADS
+#    include <mutex.h>
+# endif
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+// The end-of-C-string character.
+// This is what the draft standard says it should be.
+template <class charT>
+inline charT __eos(charT*) { return charT(); }
+
+// Test for basic character types.
+// For basic character types leaves having a trailing eos.
+template <class charT>
+inline bool __is_basic_char_type(charT *) { return false; }
+template <class charT>
+inline bool __is_one_byte_char_type(charT *) { return false; }
+
+inline bool __is_basic_char_type(char *) { return true; }
+inline bool __is_one_byte_char_type(char *) { return true; }
+inline bool __is_basic_char_type(wchar_t *) { return true; }
+
+// Store an eos iff charT is a basic character type.
+// Do not reference __eos if it isn't.
+template <class charT>
+inline void __cond_store_eos(charT&) {}
+
+inline void __cond_store_eos(char& c) { c = 0; }
+inline void __cond_store_eos(wchar_t& c) { c = 0; }
+	
+
+// rope<charT,Alloc> is a sequence of charT.
+// Ropes appear to be mutable, but update operations
+// really copy enough of the data structure to leave the original
+// valid.  Thus ropes can be logically copied by just copying
+// a pointer value.
+// The __eos function is used for those functions that
+// convert to/from C-like strings to detect the end of the string.
+// __compare is used as the character comparison function.
+template <class charT>
+class char_producer {
+    public:
+	virtual ~char_producer() {};
+	virtual void operator()(size_t start_pos, size_t len, charT* buffer)
+		= 0;
+	// Buffer should really be an arbitrary output iterator.
+	// That way we could flatten directly into an ostream, etc.
+	// This is thoroughly impossible, since iterator types don't
+	// have runtime descriptions.
+};
+
+// Sequence buffers:
+//
+// Sequence must provide an append operation that appends an
+// array to the sequence.  Sequence buffers are useful only if
+// appending an entire array is cheaper than appending element by element.
+// This is true for many string representations.
+// This should  perhaps inherit from ostream<sequence::value_type>
+// and be implemented correspondingly, so that they can be used
+// for formatted.  For the sake of portability, we don't do this yet.
+//
+// For now, sequence buffers behave as output iterators.  But they also
+// behave a little like basic_ostringstream<sequence::value_type> and a
+// little like containers.
+
+template<class sequence, size_t buf_sz = 100
+#   if defined(__sgi) && !defined(__GNUC__)
+#	 define __TYPEDEF_WORKAROUND
+         ,class v = typename sequence::value_type
+#   endif
+        >
+// The 3rd parameter works around a common compiler bug.
+class sequence_buffer : public output_iterator {
+    public:
+#       ifndef __TYPEDEF_WORKAROUND
+	    typedef typename sequence::value_type value_type;
+#	else
+	    typedef v value_type;
+#	endif
+    protected:
+	sequence *prefix;
+	value_type buffer[buf_sz];
+	size_t buf_count;
+    public:
+	void flush() {
+	    prefix->append(buffer, buffer + buf_count);
+	    buf_count = 0;
+	}
+	~sequence_buffer() { flush(); }
+	sequence_buffer() : prefix(0), buf_count(0) {}
+	sequence_buffer(const sequence_buffer & x) {
+	    prefix = x.prefix;
+            buf_count = x.buf_count;
+            copy(x.buffer, x.buffer + x.buf_count, buffer);
+	}
+	sequence_buffer(sequence_buffer & x) {
+	    x.flush();
+	    prefix = x.prefix;
+	    buf_count = 0;
+	}
+	sequence_buffer(sequence& s) : prefix(&s), buf_count(0) {}
+	sequence_buffer& operator= (sequence_buffer& x) {
+	    x.flush();
+	    prefix = x.prefix;
+	    buf_count = 0;
+	    return *this;
+	}
+	sequence_buffer& operator= (const sequence_buffer& x) {
+	    prefix = x.prefix;
+	    buf_count = x.buf_count;
+	    copy(x.buffer, x.buffer + x.buf_count, buffer);
+	    return *this;
+	}
+	void push_back(value_type x)
+	{
+	    if (buf_count < buf_sz) {
+		buffer[buf_count] = x;
+		++buf_count;
+	    } else {
+		flush();
+		buffer[0] = x;
+		buf_count = 1;
+	    }
+	}
+	void append(value_type *s, size_t len)
+	{
+	    if (len + buf_count <= buf_sz) {
+		size_t i, j;
+		for (i = buf_count, j = 0; j < len; i++, j++) {
+		    buffer[i] = s[j];
+		}
+		buf_count += len;
+	    } else if (0 == buf_count) {
+		prefix->append(s, s + len);
+	    } else {
+		flush();
+		append(s, len);
+	    }
+	}
+	sequence_buffer& write(value_type *s, size_t len)
+	{
+	    append(s, len);
+	    return *this;
+	}
+	sequence_buffer& put(value_type x)
+	{
+	    push_back(x);
+	    return *this;
+	}
+	sequence_buffer& operator=(const value_type& rhs)
+	{
+	    push_back(rhs);
+	    return *this;
+	}
+	sequence_buffer& operator*() { return *this; }
+	sequence_buffer& operator++() { return *this; }
+	sequence_buffer& operator++(int) { return *this; }
+};
+
+// The following should be treated as private, at least for now.
+template<class charT>
+class __rope_char_consumer {
+    public:
+	// If we had member templates, these should not be virtual.
+	// For now we need to use run-time parametrization where
+	// compile-time would do.  Hence this should all be private
+	// for now.
+	// The symmetry with char_producer is accidental and temporary.
+	virtual ~__rope_char_consumer() {};
+	virtual bool operator()(const charT* buffer, size_t len) = 0;
+};
+
+//
+// What follows should really be local to rope.  Unfortunately,
+// that doesn't work, since it makes it impossible to define generic
+// equality on rope iterators.  According to the draft standard, the
+// template parameters for such an equality operator cannot be inferred
+// from the occurence of a member class as a parameter.
+// (SGI compilers in fact allow this, but the result wouldn't be
+// portable.)
+// Similarly, some of the static member functions are member functions
+// only to avoid polluting the global namespace, and to circumvent
+// restrictions on type inference for template functions.
+//
+
+template<class CharT, class Alloc=__ALLOC> class rope;
+template<class CharT, class Alloc> struct __rope_RopeConcatenation;
+template<class CharT, class Alloc> struct __rope_RopeLeaf;
+template<class CharT, class Alloc> struct __rope_RopeFunction;
+template<class CharT, class Alloc> struct __rope_RopeSubstring;
+template<class CharT, class Alloc> class __rope_iterator;
+template<class CharT, class Alloc> class __rope_const_iterator;
+template<class CharT, class Alloc> class __rope_charT_ref_proxy;
+template<class CharT, class Alloc> class __rope_charT_ptr_proxy;
+
+//
+// The internal data structure for representing a rope.  This is
+// private to the implementation.  A rope is really just a pointer
+// to one of these.
+//
+// A few basic functions for manipulating this data structure
+// are members of RopeBase.  Most of the more complex algorithms
+// are implemented as rope members.
+//
+// Some of the static member functions of RopeBase have identically
+// named functions in rope that simply invoke the RopeBase versions.
+//
+
+template<class charT, class Alloc>
+struct __rope_RopeBase {
+    typedef rope<charT,Alloc> my_rope;
+    typedef simple_alloc<charT, Alloc> DataAlloc;
+    typedef simple_alloc<__rope_RopeConcatenation<charT,Alloc>, Alloc> CAlloc;
+    typedef simple_alloc<__rope_RopeLeaf<charT,Alloc>, Alloc> LAlloc;
+    typedef simple_alloc<__rope_RopeFunction<charT,Alloc>, Alloc> FAlloc;
+    typedef simple_alloc<__rope_RopeSubstring<charT,Alloc>, Alloc> SAlloc;
+    public:
+    enum { max_rope_depth = 45 };
+    enum {leaf, concat, substringfn, function} tag:8;
+    bool is_balanced:8;
+    unsigned char depth;
+    size_t size;
+    __GC_CONST charT * c_string;
+			/* Flattened version of string, if needed.  */
+			/* typically 0.                             */
+			/* If it's not 0, then the memory is owned  */
+			/* by this node.                            */
+			/* In the case of a leaf, this may point to */
+			/* the same memory as the data field.	    */
+#   ifndef __GC
+#       if defined(__STL_WIN32THREADS)
+	    long refcount;  	// InterlockedIncrement wants a long *
+#	else
+	    size_t refcount;
+#	endif
+	// We count references from rope instances
+	// and references from other rope nodes.  We
+	// do not count const_iterator references.
+	// Iterator references are counted so that rope modifications
+	// can be detected after the fact.
+	// Generally function results are counted, i.e.
+	// a pointer returned by a function is included at the
+	// point at which the pointer is returned.
+	// The recipient should decrement the count if the
+	// result is not needed.
+	// Generally function arguments are not reflected
+	// in the reference count.  The callee should increment
+	// the count before saving the argument someplace that
+	// will outlive the call.
+#   endif
+#   ifndef __GC
+#       ifdef __STL_SGI_THREADS
+	    // Reference counting with multiple threads and no
+	    // hardware or thread package support is pretty awful.
+	    // Mutexes are normally too expensive.
+	    // We'll assume a COMPARE_AND_SWAP(destp, old, new)
+	    // operation, which might be cheaper.
+#           if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64))
+#               define __add_and_fetch(l,v) add_then_test((unsigned long *)l,v)
+#           endif
+	    void init_refcount_lock() {}
+	    void incr_refcount ()
+	    {
+		__add_and_fetch(&refcount, 1);
+	    }
+	    size_t decr_refcount ()
+	    {
+		return __add_and_fetch(&refcount, (size_t)(-1));
+	    }
+#       elif defined(__STL_WIN32THREADS)
+	    void init_refcount_lock() {}
+            void incr_refcount ()
+            {
+                InterlockedIncrement(&refcount);
+            }
+            size_t decr_refcount ()
+            {
+                return InterlockedDecrement(&refcount);
+            }
+#	elif defined(__STL_PTHREADS)
+	    // This should be portable, but performance is expected
+	    // to be quite awful.  This really needs platform specific
+	    // code.
+	    pthread_mutex_t refcount_lock;
+	    void init_refcount_lock() {
+		pthread_mutex_init(&refcount_lock, 0);
+	    }
+	    void incr_refcount ()
+            {   
+		pthread_mutex_lock(&refcount_lock);
+                ++refcount;
+		pthread_mutex_unlock(&refcount_lock);
+            }
+            size_t decr_refcount ()
+            {   
+		size_t result;
+		pthread_mutex_lock(&refcount_lock);
+                result = --refcount;
+		pthread_mutex_unlock(&refcount_lock);
+                return result;
+            }
+#	else
+	    void init_refcount_lock() {}
+	    void incr_refcount ()
+	    {
+		++refcount;
+	    }
+	    size_t decr_refcount ()
+	    {
+		--refcount;
+		return refcount;
+	    }
+#       endif
+#   else
+	void incr_refcount () {}
+#   endif
+	static void free_string(charT *, size_t len);
+			// Deallocate data section of a leaf.
+			// This shouldn't be a member function.
+			// But its hard to do anything else at the
+			// moment, because it's templatized w.r.t.
+			// an allocator.
+			// Does nothing if __GC is defined.
+#   ifndef __GC
+	  void free_c_string();
+	  void free_tree();
+			// Deallocate t. Assumes t is not 0.
+	  void unref_nonnil()
+	  {
+	      if (0 == decr_refcount()) free_tree();
+	  }
+	  void ref_nonnil()
+	  {
+	      incr_refcount();
+	  }
+	  static void unref(__rope_RopeBase* t)
+	  {
+	      if (0 != t) {
+		  t -> unref_nonnil();
+	      }
+	  }
+	  static void ref(__rope_RopeBase* t)
+	  {
+	      if (0 != t) t -> incr_refcount();
+	  }
+	  static void free_if_unref(__rope_RopeBase* t)
+ 	  {
+	      if (0 != t && 0 == t -> refcount) t -> free_tree();
+	  }
+#   else /* __GC */
+	  void unref_nonnil() {}
+	  void ref_nonnil() {}
+	  static void unref(__rope_RopeBase* t) {}
+	  static void ref(__rope_RopeBase* t) {}
+	  static void fn_finalization_proc(void * tree, void *);
+	  static void free_if_unref(__rope_RopeBase* t) {}
+#   endif
+
+    // The data fields of leaves are allocated with some
+    // extra space, to accomodate future growth and for basic
+    // character types, to hold a trailing eos character.
+    enum { alloc_granularity = 8 };
+    static size_t rounded_up_size(size_t n) {
+        size_t size_with_eos;
+	     
+        if (__is_basic_char_type((charT *)0)) {
+    	    size_with_eos = n + 1;
+    	} else {
+  	    size_with_eos = n;
+	}
+#       ifdef __GC
+   	   return size_with_eos;
+#	else
+	   // Allow slop for in-place expansion.
+	   return (size_with_eos + alloc_granularity-1)
+			&~ (alloc_granularity-1);
+#	endif
+    }
+};
+
+template<class charT, class Alloc>
+struct __rope_RopeLeaf : public __rope_RopeBase<charT,Alloc> {
+  public:  // Apparently needed by VC++
+    __GC_CONST charT* data;     /* Not necessarily 0 terminated. */
+				/* The allocated size is	 */
+				/* rounded_up_size(size), except */
+				/* in the GC case, in which it	 */
+				/* doesn't matter.		 */
+};
+
+template<class charT, class Alloc>
+struct __rope_RopeConcatenation : public __rope_RopeBase<charT,Alloc> {
+  public:
+    __rope_RopeBase<charT,Alloc>* left;
+    __rope_RopeBase<charT,Alloc>* right;
+};
+
+template<class charT, class Alloc>
+struct __rope_RopeFunction : public __rope_RopeBase<charT,Alloc> {
+  public:
+    char_producer<charT>* fn;
+#   ifndef __GC
+      bool delete_when_done;	// Char_producer is owned by the
+				// rope and should be explicitly
+				// deleted when the rope becomes
+				// inaccessible.
+#   else
+      // In the GC case, we either register the rope for
+      // finalization, or not.  Thus the field is unnecessary;
+      // the information is stored in the collector data structures.
+#   endif
+};
+// Substring results are usually represented using just
+// concatenation nodes.  But in the case of very long flat ropes
+// or ropes with a functional representation that isn't practical.
+// In that case, we represent the result as a special case of
+// RopeFunction, whose char_producer points back to the rope itself.
+// In all cases except repeated substring operations and
+// deallocation, we treat the result as a RopeFunction.
+template<class charT, class Alloc>
+struct __rope_RopeSubstring: public __rope_RopeFunction<charT,Alloc>,
+			     public char_producer<charT> {
+  public:
+    __rope_RopeBase<charT,Alloc> * base;	// not 0
+    size_t start;
+    virtual ~__rope_RopeSubstring() {}
+    virtual void operator()(size_t start_pos, size_t req_len,
+			    charT *buffer) {
+	switch(base -> tag) {
+	    case function:
+	    case substringfn:
+	      {
+		char_producer<charT> *fn =
+			((__rope_RopeFunction<charT,Alloc> *)base) -> fn;
+		__stl_assert(start_pos + req_len <= size);
+		__stl_assert(start + size <= base -> size);
+		(*fn)(start_pos + start, req_len, buffer);
+	      }
+	      break;
+	    case leaf:
+	      {
+		__GC_CONST charT * s =
+			((__rope_RopeLeaf<charT,Alloc> *)base) -> data;
+		uninitialized_copy_n(s + start_pos + start, req_len,
+				     buffer);
+	      }
+	      break;
+	    default:
+	      __stl_assert(false);
+	}
+    }
+    __rope_RopeSubstring(__rope_RopeBase<charT,Alloc> * b, size_t s, size_t l) :
+	base(b), start(s) {
+#       ifndef __GC
+	    refcount = 1;
+	    init_refcount_lock();
+	    base -> ref_nonnil();
+#       endif
+	size = l;
+	tag = substringfn;
+	depth = 0;
+	c_string = 0;
+	fn = this;
+    }
+};
+
+
+// Self-destructing pointers to RopeBase.
+// These are not conventional smart pointers.  Their
+// only purpose in life is to ensure that unref is called
+// on the pointer either at normal exit or if an exception
+// is raised.  It is the caller's responsibility to
+// adjust reference counts when these pointers are initialized
+// or assigned to.  (This convention significantly reduces
+// the number of potentially expensive reference count
+// updates.)
+#ifndef __GC
+  template<class charT, class Alloc>
+  struct __rope_self_destruct_ptr {
+    __rope_RopeBase<charT,Alloc> * ptr;
+    ~__rope_self_destruct_ptr() { __rope_RopeBase<charT,Alloc>::unref(ptr); }
+#   ifdef __STL_USE_EXCEPTIONS
+	__rope_self_destruct_ptr() : ptr(0) {};
+#   else
+	__rope_self_destruct_ptr() {};
+#   endif
+    __rope_self_destruct_ptr(__rope_RopeBase<charT,Alloc> * p) : ptr(p) {}
+    __rope_RopeBase<charT,Alloc> & operator*() { return *ptr; }
+    __rope_RopeBase<charT,Alloc> * operator->() { return ptr; }
+    operator __rope_RopeBase<charT,Alloc> *() { return ptr; }
+    __rope_self_destruct_ptr & operator= (__rope_RopeBase<charT,Alloc> * x)
+	{ ptr = x; return *this; }
+  };
+#endif
+
+// Dereferencing a nonconst iterator has to return something
+// that behaves almost like a reference.  It's not possible to
+// return an actual reference since assignment requires extra
+// work.  And we would get into the same problems as with the
+// CD2 version of basic_string.
+template<class charT, class Alloc>
+class __rope_charT_ref_proxy {
+    friend class rope<charT,Alloc>;
+    friend class __rope_iterator<charT,Alloc>;
+    friend class __rope_charT_ptr_proxy<charT,Alloc>;
+#   ifdef __GC
+	typedef __rope_RopeBase<charT,Alloc> * self_destruct_ptr;
+#   else
+    	typedef __rope_self_destruct_ptr<charT,Alloc> self_destruct_ptr;
+#   endif
+    typedef __rope_RopeBase<charT,Alloc> RopeBase;
+    typedef rope<charT,Alloc> my_rope;
+    size_t pos;
+    charT current;
+    bool current_valid;
+    my_rope * root;     // The whole rope.
+  public:
+    __rope_charT_ref_proxy(my_rope * r, size_t p) :
+	pos(p), root(r), current_valid(false) {}
+    __rope_charT_ref_proxy(my_rope * r, size_t p,
+		    charT c) :
+	pos(p), root(r), current(c), current_valid(true) {}
+    operator charT () const;
+    __rope_charT_ref_proxy& operator= (charT c);
+    __rope_charT_ptr_proxy<charT,Alloc> operator& () const;
+    __rope_charT_ref_proxy& operator= (const __rope_charT_ref_proxy& c) {
+	return operator=((charT)c); 
+    }
+};
+
+template<class charT, class Alloc>
+class __rope_charT_ptr_proxy {
+    friend class __rope_charT_ref_proxy<charT,Alloc>;
+    size_t pos;
+    charT current;
+    bool current_valid;
+    rope<charT,Alloc> * root;     // The whole rope.
+  public:
+    __rope_charT_ptr_proxy(const __rope_charT_ref_proxy<charT,Alloc> & x) :
+	pos(x.pos), root(x.root), current_valid(x.current_valid),
+	current(x.current) {}
+    __rope_charT_ptr_proxy(const __rope_charT_ptr_proxy & x) :
+	pos(x.pos), root(x.root), current_valid(x.current_valid),
+	current(x.current) {}
+    __rope_charT_ptr_proxy() {}
+    __rope_charT_ptr_proxy(charT * x) : root(0), pos(0) {
+	__stl_assert(0 == x);
+    }
+    __rope_charT_ptr_proxy& operator= (const __rope_charT_ptr_proxy& x) {
+	pos = x.pos;
+	current = x.current;
+	current_valid = x.current_valid;
+	root = x.root;
+	return *this;
+    }
+    friend bool operator== __STL_NULL_TMPL_ARGS
+                (const __rope_charT_ptr_proxy<charT,Alloc> & x,
+                 const __rope_charT_ptr_proxy<charT,Alloc> & y);
+    __rope_charT_ref_proxy<charT,Alloc> operator *() const {
+	if (current_valid) {
+	    return __rope_charT_ref_proxy<charT,Alloc>(root, pos, current);
+	} else {
+	    return __rope_charT_ref_proxy<charT,Alloc>(root, pos);
+	}
+    }
+};
+
+// Rope iterators:
+// Unlike in the C version, we cache only part of the stack
+// for rope iterators, since they must be efficiently copyable.
+// When we run out of cache, we have to reconstruct the iterator
+// value.
+// Pointers from iterators are not included in reference counts.
+// Iterators are assumed to be thread private.  Ropes can
+// be shared.
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1375
+#endif
+
+template<class charT, class Alloc>
+class __rope_iterator_base:
+  public random_access_iterator<charT, ptrdiff_t> {
+  friend class rope<charT, Alloc>;
+  public:
+    typedef __rope_RopeBase<charT,Alloc> RopeBase;
+	// Borland doesnt want this to be protected.
+  protected:
+    enum { path_cache_len = 4 }; // Must be <= 9.
+    enum { iterator_buf_len = 15 };
+    size_t current_pos;
+    RopeBase * root;     // The whole rope.
+    size_t leaf_pos;    // Starting position for current leaf
+    __GC_CONST charT * buf_start;
+			// Buffer possibly
+			// containing current char.
+    __GC_CONST charT * buf_ptr;
+			// Pointer to current char in buffer.
+			// != 0 ==> buffer valid.
+    __GC_CONST charT * buf_end;
+			// One past last valid char in buffer.
+    // What follows is the path cache.  We go out of our
+    // way to make this compact.
+    // Path_end contains the bottom section of the path from
+    // the root to the current leaf.
+    const RopeBase * path_end[path_cache_len];
+    int leaf_index;     // Last valid pos in path_end;
+    			// path_end[0] ... path_end[leaf_index-1]
+			// point to concatenation nodes.
+    unsigned char path_directions;
+			  // (path_directions >> i) & 1 is 1
+			  // iff we got from path_end[leaf_index - i - 1]
+			  // to path_end[leaf_index - i] by going to the
+			  // right. Assumes path_cache_len <= 9.
+    charT tmp_buf[iterator_buf_len];
+			// Short buffer for surrounding chars.
+			// This is useful primarily for 
+			// RopeFunctions.  We put the buffer
+			// here to avoid locking in the
+			// multithreaded case.
+    // The cached path is generally assumed to be valid
+    // only if the buffer is valid.
+    static void setbuf(__rope_iterator_base &x);
+					// Set buffer contents given
+					// path cache.
+    static void setcache(__rope_iterator_base &x);
+					// Set buffer contents and
+					// path cache.
+    static void setcache_for_incr(__rope_iterator_base &x);
+					// As above, but assumes path
+					// cache is valid for previous posn.
+    __rope_iterator_base() {}
+    __rope_iterator_base(RopeBase * root, size_t pos):
+		   root(root), current_pos(pos), buf_ptr(0) {}
+    __rope_iterator_base(const __rope_iterator_base& x) {
+	if (0 != x.buf_ptr) {
+	    *this = x;
+	} else {
+	    current_pos = x.current_pos;
+	    root = x.root;
+	    buf_ptr = 0;
+	}
+    }
+    void incr(size_t n);
+    void decr(size_t n);
+  public:
+    size_t index() const { return current_pos; }
+};
+
+template<class charT, class Alloc> class __rope_iterator;
+
+template<class charT, class Alloc>
+class __rope_const_iterator : public __rope_iterator_base<charT,Alloc> {
+    friend class rope<charT,Alloc>;
+  protected:
+    __rope_const_iterator(const RopeBase * root, size_t pos):
+		   __rope_iterator_base<charT,Alloc>(
+		     const_cast<RopeBase *>(root), pos)
+		   // Only nonconst iterators modify root ref count
+    {}
+  public:
+    typedef charT reference;    // Really a value.  Returning a reference
+				// Would be a mess, since it would have
+				// to be included in refcount.
+    typedef const charT* pointer;
+
+  public:
+    __rope_const_iterator() {};
+    __rope_const_iterator(const __rope_const_iterator & x) :
+				__rope_iterator_base<charT,Alloc>(x) { }
+    __rope_const_iterator(const __rope_iterator<charT,Alloc> & x);
+    __rope_const_iterator(const rope<charT,Alloc> &r, size_t pos) :
+	__rope_iterator_base<charT,Alloc>(r.tree_ptr, pos) {}
+    __rope_const_iterator& operator= (const __rope_const_iterator & x) {
+	if (0 != x.buf_ptr) {
+	    *this = x;
+	} else {
+	    current_pos = x.current_pos;
+	    root = x.root;
+	    buf_ptr = 0;
+	}
+	return(*this);
+    }
+    reference operator*() {
+	if (0 == buf_ptr) setcache(*this);
+	return *buf_ptr;
+    }
+    __rope_const_iterator& operator++() {
+	__GC_CONST charT * next;
+	if (0 != buf_ptr && (next = buf_ptr + 1) < buf_end) {
+	    buf_ptr = next;
+	    ++current_pos;
+	} else {
+	    incr(1);
+	}
+	return *this;
+    }
+    __rope_const_iterator& operator+=(ptrdiff_t n) {
+	if (n >= 0) {
+	    incr(n);
+	} else {
+	    decr(-n);
+	}
+	return *this;
+    }
+    __rope_const_iterator& operator--() {
+	decr(1);
+	return *this;
+    }
+    __rope_const_iterator& operator-=(ptrdiff_t n) {
+	if (n >= 0) {
+	    decr(n);
+	} else {
+	    incr(-n);
+	}
+	return *this;
+    }
+    __rope_const_iterator operator++(int) {
+	size_t old_pos = current_pos;
+	incr(1);
+	return __rope_const_iterator<charT,Alloc>(root, old_pos);
+	// This makes a subsequent dereference expensive.
+	// Perhaps we should instead copy the iterator
+	// if it has a valid cache?
+    }
+    __rope_const_iterator operator--(int) {
+	size_t old_pos = current_pos;
+	decr(1);
+	return __rope_const_iterator<charT,Alloc>(root, old_pos);
+    }
+    friend __rope_const_iterator<charT,Alloc> operator- __STL_NULL_TMPL_ARGS
+	(const __rope_const_iterator<charT,Alloc> & x,
+	 ptrdiff_t n);
+    friend __rope_const_iterator<charT,Alloc> operator+ __STL_NULL_TMPL_ARGS
+	(const __rope_const_iterator<charT,Alloc> & x,
+	 ptrdiff_t n);
+    friend __rope_const_iterator<charT,Alloc> operator+ __STL_NULL_TMPL_ARGS
+	(ptrdiff_t n,
+	 const __rope_const_iterator<charT,Alloc> & x);
+    reference operator[](size_t n) {
+	return rope<charT,Alloc>::fetch(root, current_pos + n);
+    }
+    friend bool operator== __STL_NULL_TMPL_ARGS
+	(const __rope_const_iterator<charT,Alloc> & x,
+	 const __rope_const_iterator<charT,Alloc> & y);
+    friend bool operator< __STL_NULL_TMPL_ARGS
+	(const __rope_const_iterator<charT,Alloc> & x,
+	 const __rope_const_iterator<charT,Alloc> & y);
+    friend ptrdiff_t operator- __STL_NULL_TMPL_ARGS
+	(const __rope_const_iterator<charT,Alloc> & x,
+	 const __rope_const_iterator<charT,Alloc> & y);
+};
+
+template<class charT, class Alloc>
+class __rope_iterator : public __rope_iterator_base<charT,Alloc> {
+    friend class rope<charT,Alloc>;
+  protected:
+    rope<charT,Alloc> * root_rope;
+	// root is treated as a cached version of this,
+	// and is used to detect changes to the underlying
+	// rope.
+	// Root is included in the reference count.
+	// This is necessary so that we can detect changes reliably.
+	// Unfortunately, it requires careful bookkeeping for the
+	// nonGC case.
+    __rope_iterator(rope<charT,Alloc> * r, size_t pos):
+	     __rope_iterator_base<charT,Alloc>(r -> tree_ptr, pos),
+	     root_rope(r) {
+		RopeBase::ref(root);
+	     }
+    void check();
+  public:
+    typedef __rope_charT_ref_proxy<charT,Alloc>  reference;
+    typedef __rope_charT_ref_proxy<charT,Alloc>* pointer;
+
+  public:
+    rope<charT,Alloc>& container() { return *root_rope; }
+    __rope_iterator() {
+	root = 0;  // Needed for reference counting.
+    };
+    __rope_iterator(const __rope_iterator & x) :
+	__rope_iterator_base<charT,Alloc>(x) {
+	root_rope = x.root_rope;
+	RopeBase::ref(root);
+    }
+    __rope_iterator(rope<charT,Alloc>& r, size_t pos);
+    ~__rope_iterator() {
+	RopeBase::unref(root);
+    }
+    __rope_iterator& operator= (const __rope_iterator & x) {
+	RopeBase *old = root;
+
+	RopeBase::ref(x.root);
+	if (0 != x.buf_ptr) {
+	    *this = x;
+	} else {
+	    current_pos = x.current_pos;
+	    root = x.root;
+	    root_rope = x.root_rope;
+	    buf_ptr = 0;
+	}
+	RopeBase::unref(old);
+	return(*this);
+    }
+    reference operator*() {
+	check();
+	if (0 == buf_ptr) {
+	    return __rope_charT_ref_proxy<charT,Alloc>(root_rope, current_pos);
+	} else {
+	    return __rope_charT_ref_proxy<charT,Alloc>(root_rope,
+						       current_pos, *buf_ptr);
+	}
+    }
+    __rope_iterator& operator++() {
+	incr(1);
+	return *this;
+    }
+    __rope_iterator& operator+=(difference_type n) {
+	if (n >= 0) {
+	    incr(n);
+	} else {
+	    decr(-n);
+	}
+	return *this;
+    }
+    __rope_iterator& operator--() {
+	decr(1);
+	return *this;
+    }
+    __rope_iterator& operator-=(difference_type n) {
+	if (n >= 0) {
+	    decr(n);
+	} else {
+	    incr(-n);
+	}
+	return *this;
+    }
+    __rope_iterator operator++(int) {
+	size_t old_pos = current_pos;
+	incr(1);
+	return __rope_iterator<charT,Alloc>(root_rope, old_pos);
+    }
+    __rope_iterator operator--(int) {
+	size_t old_pos = current_pos;
+	decr(1);
+	return __rope_iterator<charT,Alloc>(root_rope, old_pos);
+    }
+    reference operator[](ptrdiff_t n) {
+	return __rope_charT_ref_proxy<charT,Alloc>(root_rope, current_pos + n);
+    }
+    friend bool operator== __STL_NULL_TMPL_ARGS
+	(const __rope_iterator<charT,Alloc> & x,
+	 const __rope_iterator<charT,Alloc> & y);
+    friend bool operator< __STL_NULL_TMPL_ARGS
+	(const __rope_iterator<charT,Alloc> & x,
+	 const __rope_iterator<charT,Alloc> & y);
+    friend ptrdiff_t operator- __STL_NULL_TMPL_ARGS
+	(const __rope_iterator<charT,Alloc> & x,
+	 const __rope_iterator<charT,Alloc> & y);
+    friend __rope_iterator<charT,Alloc> operator- __STL_NULL_TMPL_ARGS
+	(const __rope_iterator<charT,Alloc> & x,
+	 ptrdiff_t n);
+    friend __rope_iterator<charT,Alloc> operator+ __STL_NULL_TMPL_ARGS
+	(const __rope_iterator<charT,Alloc> & x,
+	 ptrdiff_t n);
+    friend __rope_iterator<charT,Alloc> operator+ __STL_NULL_TMPL_ARGS
+	(ptrdiff_t n,
+	 const __rope_iterator<charT,Alloc> & x);
+
+};
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1375
+#endif
+
+template <class charT, class Alloc>
+class rope {
+    public:
+	typedef charT value_type;
+	typedef ptrdiff_t difference_type;
+	typedef size_t size_type;
+	typedef charT const_reference;
+	typedef const charT* const_pointer;
+	typedef __rope_iterator<charT,Alloc> iterator;
+	typedef __rope_const_iterator<charT,Alloc> const_iterator;
+	typedef __rope_charT_ref_proxy<charT,Alloc> reference;
+	typedef __rope_charT_ptr_proxy<charT,Alloc> pointer;
+
+	friend class __rope_iterator<charT,Alloc>;
+	friend class __rope_const_iterator<charT,Alloc>;
+	friend struct __rope_RopeBase<charT,Alloc>;
+	friend class __rope_iterator_base<charT,Alloc>;
+	friend class __rope_charT_ptr_proxy<charT,Alloc>;
+	friend class __rope_charT_ref_proxy<charT,Alloc>;
+	friend struct __rope_RopeSubstring<charT,Alloc>;
+
+    protected:
+	typedef __GC_CONST charT * cstrptr;
+#       ifdef __STL_SGI_THREADS
+	    static cstrptr atomic_swap(cstrptr *p, cstrptr q) {
+#               if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64))
+                    return (cstrptr) test_and_set((unsigned long *)p,
+			   		          (unsigned long)q);
+#		else
+                    return (cstrptr) __test_and_set((unsigned long *)p,
+			   		            (unsigned long)q);
+#		endif
+            }
+#       elif defined(__STL_WIN32THREADS)
+	    static cstrptr atomic_swap(cstrptr *p, cstrptr q) {
+		return (cstrptr) InterlockedExchange((LPLONG)p, (LONG)q);
+	    }
+#	elif defined(__STL_PTHREADS)
+	    // This should be portable, but performance is expected
+	    // to be quite awful.  This really needs platform specific
+	    // code.
+	    static pthread_mutex_t swap_lock;
+	    static cstrptr atomic_swap(cstrptr *p, cstrptr q) {
+		pthread_mutex_lock(&swap_lock);
+		cstrptr result = *p;
+		*p = q;
+		pthread_mutex_unlock(&swap_lock);
+		return result;
+            }
+#	else
+	    static cstrptr atomic_swap(cstrptr *p, cstrptr q) {
+                cstrptr result = *p;
+                *p = q;
+		return result;
+	    }
+#       endif
+
+	static charT empty_c_str[1];
+
+    	typedef simple_alloc<charT, Alloc> DataAlloc;
+    	typedef simple_alloc<__rope_RopeConcatenation<charT,Alloc>, Alloc> CAlloc;
+    	typedef simple_alloc<__rope_RopeLeaf<charT,Alloc>, Alloc> LAlloc;
+    	typedef simple_alloc<__rope_RopeFunction<charT,Alloc>, Alloc> FAlloc;
+    	typedef simple_alloc<__rope_RopeSubstring<charT,Alloc>, Alloc> SAlloc;
+	static bool is0(charT c) { return c == __eos((charT *)0); }
+	enum { copy_max = 23 };
+		// For strings shorter than copy_max, we copy to
+		// concatenate.
+
+	typedef __rope_RopeBase<charT,Alloc> RopeBase;
+	typedef __rope_RopeConcatenation<charT,Alloc> RopeConcatenation;
+	typedef __rope_RopeLeaf<charT,Alloc> RopeLeaf;
+	typedef __rope_RopeFunction<charT,Alloc> RopeFunction;
+	typedef __rope_RopeSubstring<charT,Alloc> RopeSubstring;
+
+	// The only data member of a rope:
+	RopeBase *tree_ptr;
+
+	// Retrieve a character at the indicated position.
+	static charT fetch(RopeBase * r, size_type pos);
+
+#	ifndef __GC
+	    // Obtain a pointer to the character at the indicated position.
+	    // The pointer can be used to change the character.
+	    // If such a pointer cannot be produced, as is frequently the
+	    // case, 0 is returned instead.
+	    // (Returns nonzero only if all nodes in the path have a refcount
+	    // of 1.)
+	    static charT * fetch_ptr(RopeBase * r, size_type pos);
+#	endif
+
+	static bool apply_to_pieces(
+				// should be template parameter
+				__rope_char_consumer<charT>& c,
+				const RopeBase * r,
+				size_t begin, size_t end);
+				// begin and end are assumed to be in range.
+
+#	ifndef __GC
+	  static void unref(RopeBase* t)
+	  {
+	      RopeBase::unref(t);
+	  }
+	  static void ref(RopeBase* t)
+	  {
+	      RopeBase::ref(t);
+	  }
+#       else /* __GC */
+	  static void unref(RopeBase* t) {}
+	  static void ref(RopeBase* t) {}
+#       endif
+
+
+#       ifdef __GC
+	    typedef __rope_RopeBase<charT,Alloc> * self_destruct_ptr;
+#   	else
+	    typedef __rope_self_destruct_ptr<charT,Alloc> self_destruct_ptr;
+#	endif
+
+	// Result is counted in refcount.
+	static RopeBase * substring(RopeBase * base,
+				    size_t start, size_t endp1);
+
+	static RopeBase * concat_char_iter(RopeBase * r,
+					  const charT *iter, size_t slen);
+		// Concatenate rope and char ptr, copying s.
+		// Should really take an arbitrary iterator.
+		// Result is counted in refcount.
+	static RopeBase * destr_concat_char_iter(RopeBase * r,
+						 const charT *iter, size_t slen)
+		// As above, but one reference to r is about to be
+		// destroyed.  Thus the pieces may be recycled if all
+		// relevent reference counts are 1.
+#	    ifdef __GC
+		// We can't really do anything since refcounts are unavailable.
+		{ return concat_char_iter(r, iter, slen); }
+#	    else
+		;
+#	    endif
+
+	static RopeBase * concat(RopeBase *left, RopeBase *right);
+		// General concatenation on RopeBase.  Result
+		// has refcount of 1.  Adjusts argument refcounts.
+
+   public:
+	void apply_to_pieces( size_t begin, size_t end,
+			      __rope_char_consumer<charT>& c) const {
+	    apply_to_pieces(c, tree_ptr, begin, end);
+	}
+
+
+   protected:
+
+	static size_t rounded_up_size(size_t n) {
+	    return RopeBase::rounded_up_size(n);
+	}
+
+	static size_t allocated_capacity(size_t n) {
+	    if (__is_basic_char_type((charT *)0)) {
+		return rounded_up_size(n) - 1;
+	    } else {
+		return rounded_up_size(n);
+	    }
+	}
+		
+	// s should really be an arbitrary input iterator.
+	// Adds a trailing NULL for basic char types.
+	static charT * alloc_copy(const charT *s, size_t size)
+	{
+	    charT * result = DataAlloc::allocate(rounded_up_size(size));
+
+	    uninitialized_copy_n(s, size, result);
+	    __cond_store_eos(result[size]);
+	    return(result);
+	}
+
+	// Basic constructors for rope tree nodes.
+	// These return tree nodes with a 0 reference count.
+	static RopeLeaf * RopeLeaf_from_char_ptr(__GC_CONST charT *s,
+						 size_t size);
+		// Takes ownership of its argument.
+		// Result has refcount 1.
+		// In the nonGC, basic_char_type  case it assumes that s
+		// is eos-terminated.
+		// In the nonGC case, it was allocated from Alloc with
+		// rounded_up_size(size).
+
+	static RopeLeaf * RopeLeaf_from_unowned_char_ptr(const charT *s,
+						         size_t size) {
+	    charT * buf = alloc_copy(s, size);
+            __STL_TRY {
+              return RopeLeaf_from_char_ptr(buf, size);
+            }
+            __STL_UNWIND(RopeBase::free_string(buf, size))
+	}
+	    
+
+	// Concatenation of nonempty strings.
+	// Always builds a concatenation node.
+	// Rebalances if the result is too deep.
+	// Result has refcount 1.
+	// Does not increment left and right ref counts even though
+	// they are referenced.
+	static RopeBase * tree_concat(RopeBase * left, RopeBase * right);
+
+	// Result has refcount 1.
+	// If delete_fn is true, then fn is deleted when the rope
+	// becomes inaccessible.
+	static RopeFunction * RopeFunction_from_fn
+			(char_producer<charT> *fn, size_t size,
+			 bool delete_fn);
+
+	// Concatenation helper functions
+	static RopeLeaf * leaf_concat_char_iter
+			(RopeLeaf * r, const charT * iter, size_t slen);
+		// Concatenate by copying leaf.
+		// should take an arbitrary iterator
+		// result has refcount 1.
+#	ifndef __GC
+	  static RopeLeaf * destr_leaf_concat_char_iter
+			(RopeLeaf * r, const charT * iter, size_t slen);
+	  // A version that potentially clobbers r if r -> refcount == 1.
+#       endif
+
+	// A helper function for exponentiating strings.
+	// This uses a nonstandard refcount convention.
+	// The result has refcount 0.
+	struct concat_fn;
+	friend struct rope<charT,Alloc>::concat_fn;
+
+	struct concat_fn
+		: public binary_function<rope<charT,Alloc>, rope<charT,Alloc>,
+				         rope<charT,Alloc> > {
+		rope operator() (const rope& x, const rope& y) {
+		    return x + y;
+		}
+	};
+
+        friend rope identity_element(concat_fn) { return rope<charT,Alloc>(); }
+
+	static size_t char_ptr_len(const charT * s);
+			// slightly generalized strlen
+
+	rope(RopeBase *t) : tree_ptr(t) { }
+
+
+	// Copy r to the CharT buffer.
+	// Returns buffer + r -> size.
+	// Assumes that buffer is uninitialized.
+	static charT * flatten(RopeBase * r, charT * buffer);
+
+	// Again, with explicit starting position and length.
+	// Assumes that buffer is uninitialized.
+	static charT * flatten(RopeBase * r,
+			       size_t start, size_t len,
+			       charT * buffer);
+
+	static const unsigned long min_len[RopeBase::max_rope_depth + 1];
+
+	static bool is_balanced(RopeBase *r)
+		{ return (r -> size >= min_len[r -> depth]); }
+
+	static bool is_almost_balanced(RopeBase *r)
+		{ return (r -> depth == 0 ||
+			  r -> size >= min_len[r -> depth - 1]); }
+
+	static bool is_roughly_balanced(RopeBase *r)
+		{ return (r -> depth <= 1 ||
+			  r -> size >= min_len[r -> depth - 2]); }
+
+	// Assumes the result is not empty.
+	static RopeBase * concat_and_set_balanced(RopeBase *left,
+						  RopeBase *right)
+	{
+	    RopeBase * result = concat(left, right);
+	    if (is_balanced(result)) result -> is_balanced = true;
+	    return result;
+	}
+
+	// The basic rebalancing operation.  Logically copies the
+	// rope.  The result has refcount of 1.  The client will
+	// usually decrement the reference count of r.
+	// The result isd within height 2 of balanced by the above
+	// definition.
+	static RopeBase * balance(RopeBase * r);
+
+	// Add all unbalanced subtrees to the forest of balanceed trees.
+	// Used only by balance.
+	static void add_to_forest(RopeBase *r, RopeBase **forest);
+	
+	// Add r to forest, assuming r is already balanced.
+	static void add_leaf_to_forest(RopeBase *r, RopeBase **forest);
+
+	// Print to stdout, exposing structure
+	static void dump(RopeBase * r, int indent = 0);
+
+	// Return -1, 0, or 1 if x < y, x == y, or x > y resp.
+	static int compare(const RopeBase *x, const RopeBase *y);
+
+   public:
+	bool empty() const { return 0 == tree_ptr; }
+
+	// Comparison member function.  This is public only for those
+	// clients that need a ternary comparison.  Others
+	// should use the comparison operators below.
+	int compare(const rope &y) const {
+	    return compare(tree_ptr, y.tree_ptr);
+	}
+
+	rope(const charT *s)
+	{
+	    size_t len = char_ptr_len(s);
+
+	    if (0 == len) {
+		tree_ptr = 0;
+	    } else {
+		tree_ptr = RopeLeaf_from_unowned_char_ptr(s, len);
+#		ifndef __GC
+		  __stl_assert(1 == tree_ptr -> refcount);
+#		endif
+	    }
+	}
+
+	rope(const charT *s, size_t len)
+	{
+	    if (0 == len) {
+		tree_ptr = 0;
+	    } else {
+		tree_ptr = RopeLeaf_from_unowned_char_ptr(s, len);
+	    }
+	}
+
+	rope(const charT *s, charT *e)
+	{
+	    size_t len = e - s;
+
+	    if (0 == len) {
+		tree_ptr = 0;
+	    } else {
+		tree_ptr = RopeLeaf_from_unowned_char_ptr(s, len);
+	    }
+	}
+
+	rope(const const_iterator& s, const const_iterator& e)
+	{
+	    tree_ptr = substring(s.root, s.current_pos, e.current_pos);
+	}
+
+	rope(const iterator& s, const iterator& e)
+	{
+	    tree_ptr = substring(s.root, s.current_pos, e.current_pos);
+	}
+
+	rope(charT c)
+	{
+	    charT * buf = DataAlloc::allocate(rounded_up_size(1));
+
+	    construct(buf, c);
+	    __STL_TRY {
+	        tree_ptr = RopeLeaf_from_char_ptr(buf, 1);
+            }
+            __STL_UNWIND(RopeBase::free_string(buf, 1))
+	}
+
+	rope(size_t n, charT c);
+
+	// Should really be templatized with respect to the iterator type
+	// and use sequence_buffer.  (It should perhaps use sequence_buffer
+	// even now.)
+	rope(const charT *i, const charT *j)
+	{
+	    if (i == j) {
+		tree_ptr = 0;
+	    } else {
+		size_t len = j - i;
+		tree_ptr = RopeLeaf_from_unowned_char_ptr(i, len);
+	    }
+	}
+
+	rope()
+	{
+	    tree_ptr = 0;
+	}
+
+	// Construct a rope from a function that can compute its members
+	rope(char_producer<charT> *fn, size_t len, bool delete_fn)
+	{
+	    tree_ptr = RopeFunction_from_fn(fn, len, delete_fn);
+	}
+
+	rope(const rope &x)
+	{
+	    tree_ptr = x.tree_ptr;
+	    ref(tree_ptr);
+	}
+
+	~rope()
+	{
+	    unref(tree_ptr);
+	}
+
+	rope& operator=(const rope& x)
+	{
+	    RopeBase *old = tree_ptr;
+	    tree_ptr = x.tree_ptr;
+	    ref(tree_ptr);
+	    unref(old);
+	    return(*this);
+	}
+
+	void push_back(charT x)
+	{
+	    RopeBase *old = tree_ptr;
+	    tree_ptr = concat_char_iter(tree_ptr, &x, 1);
+	    unref(old);
+	}
+
+	void pop_back()
+	{
+	    RopeBase *old = tree_ptr;
+	    tree_ptr = substring(tree_ptr, 0, tree_ptr -> size - 1);
+	    unref(old);
+	}
+
+	charT back() const
+	{
+	    return fetch(tree_ptr, tree_ptr -> size - 1);
+	}
+
+	void push_front(charT x)
+	{
+	    RopeBase *old = tree_ptr;
+	    RopeBase *left;
+
+	    left = RopeLeaf_from_unowned_char_ptr(&x, 1);
+	    __STL_TRY {
+	      tree_ptr = concat(left, tree_ptr);
+	      unref(old);
+              unref(left);
+            }
+	    __STL_UNWIND(unref(left))
+	}
+
+	void pop_front()
+	{
+	    RopeBase *old = tree_ptr;
+	    tree_ptr = substring(tree_ptr, 1, tree_ptr -> size);
+	    unref(old);
+	}
+
+	charT front() const
+	{
+	    return fetch(tree_ptr, 0);
+	}
+
+	void balance()
+	{
+	    RopeBase *old = tree_ptr;
+	    tree_ptr = balance(tree_ptr);
+	    unref(old);
+	}
+
+	void copy(charT * buffer) const {
+	    destroy(buffer, buffer + size());
+	    flatten(tree_ptr, buffer);
+	}
+
+	// This is the copy function from the standard, but
+	// with the arguments reordered to make it consistent with the
+	// rest of the interface.
+	// Note that this guaranteed not to compile if the draft standard
+	// order is assumed.
+	size_type copy(size_type pos, size_type n, charT *buffer) const {
+	    size_t sz = size();
+	    size_t len = (pos + n > sz? sz - pos : n);
+
+	    destroy(buffer, buffer + len);
+	    flatten(tree_ptr, pos, len, buffer);
+	    return len;
+	}
+
+	// Print to stdout, exposing structure.  May be useful for
+	// performance debugging.
+	void dump() {
+	    dump(tree_ptr);
+	}
+
+	// Convert to 0 terminated string in new allocated memory.
+	// Embedded 0s in the input do not terminate the copy.
+	const charT * c_str() const;
+
+	// As above, but lso use the flattened representation as the
+	// the new rope representation.
+	const charT * replace_with_c_str();
+
+	// Reclaim memory for the c_str generated flattened string.
+	// Intentionally undocumented, since it's hard to say when this
+	// is safe for multiple threads.
+	void delete_c_str () {
+	    if (0 == tree_ptr) return;
+	    if (RopeBase::leaf == tree_ptr -> tag
+		&& ((RopeLeaf *)tree_ptr) -> data == tree_ptr -> c_string) {
+		// Representation shared
+		return;
+	    }
+#	    ifndef __GC
+	      tree_ptr -> free_c_string();
+#	    endif
+	    tree_ptr -> c_string = 0;
+	}
+
+	charT operator[] (size_type pos) const {
+	    return fetch(tree_ptr, pos);
+	}
+
+	charT at(size_type pos) const {
+	   // if (pos >= size()) throw out_of_range;
+	   return (*this)[pos];
+	}
+
+	const_iterator begin() const {
+	    return(const_iterator(tree_ptr, 0));
+	}
+
+	// An easy way to get a const iterator from a non-const container.
+	const_iterator const_begin() const {
+	    return(const_iterator(tree_ptr, 0));
+	}
+
+	const_iterator end() const {
+	    return(const_iterator(tree_ptr, size()));
+	}
+
+	const_iterator const_end() const {
+	    return(const_iterator(tree_ptr, size()));
+	}
+
+	size_type size() const { 
+	    return(0 == tree_ptr? 0 : tree_ptr -> size);
+	}
+
+	size_type length() const {
+	    return size();
+	}
+
+	size_type max_size() const {
+	    return min_len[RopeBase::max_rope_depth-1] - 1;
+	    //  Guarantees that the result can be sufficirntly
+	    //  balanced.  Longer ropes will probably still work,
+	    //  but it's harder to make guarantees.
+	}
+
+#     ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+        typedef reverse_iterator<const_iterator> const_reverse_iterator;
+#     else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+	typedef reverse_iterator<const_iterator, value_type, const_reference,
+				 difference_type>  const_reverse_iterator;
+#     endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ 
+
+	const_reverse_iterator rbegin() const {
+	    return const_reverse_iterator(end());
+	}
+
+	const_reverse_iterator const_rbegin() const {
+	    return const_reverse_iterator(end());
+	}
+
+	const_reverse_iterator rend() const {
+	    return const_reverse_iterator(begin());
+	}
+
+	const_reverse_iterator const_rend() const {
+	    return const_reverse_iterator(begin());
+	}
+
+	friend rope<charT,Alloc>
+        operator+ __STL_NULL_TMPL_ARGS (const rope<charT,Alloc> &left,
+                                        const rope<charT,Alloc> &right);
+	
+	friend rope<charT,Alloc>
+        operator+ __STL_NULL_TMPL_ARGS (const rope<charT,Alloc> &left,
+                                        const charT* right);
+	
+	friend rope<charT,Alloc>
+        operator+ __STL_NULL_TMPL_ARGS (const rope<charT,Alloc> &left,
+                                        charT right);
+	
+	// The symmetric cases are intentionally omitted, since they're presumed
+	// to be less common, and we don't handle them as well.
+
+	// The following should really be templatized.
+	// The first argument should be an input iterator or
+	// forward iterator with value_type charT.
+	rope& append(const charT* iter, size_t n) {
+	    RopeBase* result = destr_concat_char_iter(tree_ptr, iter, n);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	    return *this;
+	}
+
+	rope& append(const charT* c_string) {
+	    size_t len = char_ptr_len(c_string);
+	    append(c_string, len);
+	    return(*this);
+	}
+
+	rope& append(const charT* s, const charT* e) {
+	    RopeBase* result =
+			destr_concat_char_iter(tree_ptr, s, e - s);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	    return *this;
+	}
+
+	rope& append(const_iterator s, const_iterator e) {
+	    __stl_assert(s.root == e.root);
+	    self_destruct_ptr appendee(substring(s.root, s.current_pos,
+						 e.current_pos));
+	    RopeBase* result = concat(tree_ptr, (RopeBase *)appendee);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	    return *this;
+	}
+
+	rope& append(charT c) {
+	    RopeBase* result = destr_concat_char_iter(tree_ptr, &c, 1);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	    return *this;
+	}
+
+	rope& append() { return append(charT()); }
+
+	rope& append(const rope& y) {
+	    RopeBase* result = concat(tree_ptr, y.tree_ptr);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	    return *this;
+	}
+
+	rope& append(size_t n, charT c) {
+	    rope<charT,Alloc> last(n, c);
+	    return append(last);
+	}
+
+	void swap(rope& b) {
+	    RopeBase * tmp = tree_ptr;
+	    tree_ptr = b.tree_ptr;
+	    b.tree_ptr = tmp;
+	}
+
+
+    protected:
+	// Result is included in refcount.
+	static RopeBase * replace(RopeBase *old, size_t pos1,
+				  size_t pos2, RopeBase *r) {
+	    if (0 == old) { ref(r); return r; }
+	    self_destruct_ptr left(substring(old, 0, pos1));
+	    self_destruct_ptr right(substring(old, pos2, old -> size));
+	    RopeBase * result;
+
+	    if (0 == r) {
+		result = concat(left, right);
+	    } else {
+		self_destruct_ptr left_result(concat(left, r));
+		result = concat(left_result, right);
+	    }
+	    return result;
+	}
+
+    public:
+	void insert(size_t p, const rope& r) {
+	    RopeBase * result = replace(tree_ptr, p, p,
+					       r.tree_ptr);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	}
+
+	void insert(size_t p, size_t n, charT c) {
+	    rope<charT,Alloc> r(n,c);
+	    insert(p, r);
+	}
+
+	void insert(size_t p, const charT * i, size_t n) {
+	    self_destruct_ptr left(substring(tree_ptr, 0, p));
+	    self_destruct_ptr right(substring(tree_ptr, p, size()));
+	    self_destruct_ptr left_result(concat_char_iter(left, i, n));
+	    RopeBase * result =
+				concat(left_result, right);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	}
+
+	void insert(size_t p, const charT * c_string) {
+	    insert(p, c_string, char_ptr_len(c_string));
+	}
+
+	void insert(size_t p, charT c) {
+	    insert(p, &c, 1);
+	}
+
+	void insert(size_t p) {
+	    charT c = charT();
+	    insert(p, &c, 1);
+	}
+
+	void insert(size_t p, const charT *i, const charT *j) {
+	    rope r(i, j);
+	    insert(p, r);
+	}
+
+	void insert(size_t p, const const_iterator& i,
+			      const const_iterator& j) {
+	    rope r(i, j);
+	    insert(p, r);
+	}
+
+	void insert(size_t p, const iterator& i,
+			      const iterator& j) {
+	    rope r(i, j);
+	    insert(p, r);
+	}
+
+	// (position, length) versions of replace operations:
+
+	void replace(size_t p, size_t n, const rope& r) {
+	    RopeBase * result = replace(tree_ptr, p, p + n,
+					       r.tree_ptr);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	}
+
+	void replace(size_t p, size_t n, const charT *i, size_t i_len) {
+	    rope r(i, i_len);
+	    replace(p, n, r);
+	}
+
+	void replace(size_t p, size_t n, charT c) {
+	    rope r(c);
+	    replace(p, n, r);
+	}
+
+	void replace(size_t p, size_t n, const charT *c_string) {
+	    rope r(c_string);
+	    replace(p, n, r);
+	}
+
+	void replace(size_t p, size_t n, const charT *i, const charT *j) {
+	    rope r(i, j);
+	    replace(p, n, r);
+	}
+
+	void replace(size_t p, size_t n,
+		     const const_iterator& i, const const_iterator& j) {
+	    rope r(i, j);
+	    replace(p, n, r);
+	}
+
+	void replace(size_t p, size_t n,
+		     const iterator& i, const iterator& j) {
+	    rope r(i, j);
+	    replace(p, n, r);
+	}
+
+	// Single character variants:
+	void replace(size_t p, charT c) {
+	    iterator i(this, p);
+	    *i = c;
+	}
+
+	void replace(size_t p, const rope& r) {
+	    replace(p, 1, r);
+	}
+
+	void replace(size_t p, const charT *i, size_t i_len) {
+	    replace(p, 1, i, i_len);
+	}
+
+	void replace(size_t p, const charT *c_string) {
+	    replace(p, 1, c_string);
+	}
+
+	void replace(size_t p, const charT *i, const charT *j) {
+	    replace(p, 1, i, j);
+	}
+
+	void replace(size_t p, const const_iterator& i,
+			       const const_iterator& j) {
+	    replace(p, 1, i, j);
+	}
+
+	void replace(size_t p, const iterator& i,
+			       const iterator& j) {
+	    replace(p, 1, i, j);
+	}
+
+	// Erase, (position, size) variant.
+	void erase(size_t p, size_t n) {
+	    RopeBase * result = replace(tree_ptr, p, p + n, 0);
+	    unref(tree_ptr);
+	    tree_ptr = result;
+	}
+
+	// Erase, single character
+	void erase(size_t p) {
+	    erase(p, p + 1);
+	}
+
+	// Insert, iterator variants.  
+	iterator insert(const iterator& p, const rope& r)
+		{ insert(p.index(), r); return p; }
+	iterator insert(const iterator& p, size_t n, charT c)
+		{ insert(p.index(), n, c); return p; }
+	iterator insert(const iterator& p, charT c) 
+		{ insert(p.index(), c); return p; }
+	iterator insert(const iterator& p ) 
+		{ insert(p.index()); return p; }
+	iterator insert(const iterator& p, const charT *c_string) 
+		{ insert(p.index(), c_string); return p; }
+	iterator insert(const iterator& p, const charT *i, size_t n)
+		{ insert(p.index(), i, n); return p; }
+	iterator insert(const iterator& p, const charT *i, const charT *j)
+		{ insert(p.index(), i, j);  return p; }
+	iterator insert(const iterator& p,
+			const const_iterator& i, const const_iterator& j)
+		{ insert(p.index(), i, j); return p; }
+	iterator insert(const iterator& p,
+			const iterator& i, const iterator& j)
+		{ insert(p.index(), i, j); return p; }
+
+	// Replace, range variants.
+	void replace(const iterator& p, const iterator& q,
+		     const rope& r)
+		{ replace(p.index(), q.index() - p.index(), r); }
+	void replace(const iterator& p, const iterator& q, charT c)
+		{ replace(p.index(), q.index() - p.index(), c); }
+	void replace(const iterator& p, const iterator& q,
+		     const charT * c_string)
+		{ replace(p.index(), q.index() - p.index(), c_string); }
+	void replace(const iterator& p, const iterator& q,
+		     const charT *i, size_t n)
+		{ replace(p.index(), q.index() - p.index(), i, n); }
+	void replace(const iterator& p, const iterator& q,
+		     const charT *i, const charT *j)
+		{ replace(p.index(), q.index() - p.index(), i, j); }
+	void replace(const iterator& p, const iterator& q,
+		     const const_iterator& i, const const_iterator& j)
+		{ replace(p.index(), q.index() - p.index(), i, j); }
+	void replace(const iterator& p, const iterator& q,
+		     const iterator& i, const iterator& j)
+		{ replace(p.index(), q.index() - p.index(), i, j); }
+
+	// Replace, iterator variants.
+	void replace(const iterator& p, const rope& r)
+		{ replace(p.index(), r); }
+	void replace(const iterator& p, charT c)
+		{ replace(p.index(), c); }
+	void replace(const iterator& p, const charT * c_string)
+		{ replace(p.index(), c_string); }
+	void replace(const iterator& p, const charT *i, size_t n)
+		{ replace(p.index(), i, n); }
+	void replace(const iterator& p, const charT *i, const charT *j)
+		{ replace(p.index(), i, j); }
+	void replace(const iterator& p, const_iterator i, const_iterator j)
+		{ replace(p.index(), i, j); }
+	void replace(const iterator& p, iterator i, iterator j)
+		{ replace(p.index(), i, j); }
+
+	// Iterator and range variants of erase
+	iterator erase(const iterator &p, const iterator &q) {
+            size_t p_index = p.index();
+            erase(p_index, q.index() - p_index);
+            return iterator(this, p_index);
+        }
+        iterator erase(const iterator &p) {
+            size_t p_index = p.index();
+            erase(p_index, 1);
+            return iterator(this, p_index);
+        }
+
+	rope substr(size_t start, size_t len = 1) const {
+	    return rope<charT,Alloc>(
+			substring(tree_ptr, start, start + len));
+	}
+
+	rope substr(iterator start, iterator end) const {
+	    return rope<charT,Alloc>(
+			substring(tree_ptr, start.index(), end.index()));
+	}
+	
+	rope substr(iterator start) const {
+	    size_t pos = start.index();
+	    return rope<charT,Alloc>(
+			substring(tree_ptr, pos, pos + 1));
+	}
+	
+	rope substr(const_iterator start, const_iterator end) const {
+	    // This might eventually take advantage of the cache in the
+	    // iterator.
+	    return rope<charT,Alloc>
+		(substring(tree_ptr, start.index(), end.index()));
+	}
+
+	rope<charT,Alloc> substr(const_iterator start) {
+	    size_t pos = start.index();
+	    return rope<charT,Alloc>(substring(tree_ptr, pos, pos + 1));
+	}
+
+	size_type find(charT c, size_type pos = 0) const;
+	size_type find(charT *s, size_type pos = 0) const {
+	    const_iterator result = search(const_begin() + pos, const_end(),
+					   s, s + char_ptr_len(s));
+	    return result.index();
+	}
+
+	iterator mutable_begin() {
+	    return(iterator(this, 0));
+	}
+
+	iterator mutable_end() {
+	    return(iterator(this, size()));
+	}
+
+#     ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+        typedef reverse_iterator<iterator> reverse_iterator;
+#     else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+	typedef reverse_iterator<iterator, value_type, reference,
+				 difference_type>  reverse_iterator;
+#     endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ 
+
+	reverse_iterator mutable_rbegin() {
+	    return reverse_iterator(mutable_end());
+	}
+
+	reverse_iterator mutable_rend() {
+	    return reverse_iterator(mutable_begin());
+	}
+
+	reference mutable_reference_at(size_type pos) {
+	    return reference(this, pos);
+	}
+
+#	ifdef __STD_STUFF
+	    reference operator[] (size_type pos) {
+		return charT_ref_proxy(this, pos);
+	    }
+
+	    reference at(size_type pos) {
+		// if (pos >= size()) throw out_of_range;
+		return (*this)[pos];
+	    }
+
+	    void resize(size_type n, charT c) {}
+	    void resize(size_type n) {}
+	    void reserve(size_type res_arg = 0) {}
+	    size_type capacity() const {
+		return max_size();
+	    }
+
+	  // Stuff below this line is dangerous because it's error prone.
+	  // I would really like to get rid of it.
+	    // copy function with funny arg ordering.
+	      size_type copy(charT *buffer, size_type n, size_type pos = 0)
+								const {
+		return copy(pos, n, buffer);
+	      }
+
+	    iterator end() { return mutable_end(); }
+
+	    iterator begin() { return mutable_begin(); }
+
+	    reverse_iterator rend() { return mutable_rend(); }
+
+	    reverse_iterator rbegin() { return mutable_rbegin(); }
+
+#	else
+
+	    const_iterator end() { return const_end(); }
+
+	    const_iterator begin() { return const_begin(); }
+
+	    const_reverse_iterator rend() { return const_rend(); }
+  
+	    const_reverse_iterator rbegin() { return const_rbegin(); }
+
+#	endif
+	
+};
+
+template <class charT, class Alloc>
+inline bool operator== (const __rope_const_iterator<charT,Alloc> & x,
+			const __rope_const_iterator<charT,Alloc> & y) {
+	return (x.current_pos == y.current_pos && x.root == y.root);
+}
+
+template <class charT, class Alloc>
+inline bool operator< (const __rope_const_iterator<charT,Alloc> & x,
+		       const __rope_const_iterator<charT,Alloc> & y) {
+	return (x.current_pos < y.current_pos);
+}
+
+template <class charT, class Alloc>
+inline ptrdiff_t operator-(const __rope_const_iterator<charT,Alloc> & x,
+			   const __rope_const_iterator<charT,Alloc> & y) {
+	return x.current_pos - y.current_pos;
+}
+
+template <class charT, class Alloc>
+inline __rope_const_iterator<charT,Alloc>
+operator-(const __rope_const_iterator<charT,Alloc> & x,
+	  ptrdiff_t n) {
+	return __rope_const_iterator<charT,Alloc>(x.root, x.current_pos - n);
+}
+
+template <class charT, class Alloc>
+inline __rope_const_iterator<charT,Alloc>
+operator+(const __rope_const_iterator<charT,Alloc> & x,
+	  ptrdiff_t n) {
+	return __rope_const_iterator<charT,Alloc>(x.root, x.current_pos + n);
+}
+
+template <class charT, class Alloc>
+inline __rope_const_iterator<charT,Alloc>
+operator+(ptrdiff_t n,
+	  const __rope_const_iterator<charT,Alloc> & x) {
+	return __rope_const_iterator<charT,Alloc>(x.root, x.current_pos + n);
+}
+
+template <class charT, class Alloc>
+inline bool operator== (const __rope_iterator<charT,Alloc> & x,
+			const __rope_iterator<charT,Alloc> & y) {
+	return (x.current_pos == y.current_pos && x.root_rope == y.root_rope);
+}
+
+template <class charT, class Alloc>
+inline bool operator< (const __rope_iterator<charT,Alloc> & x,
+			const __rope_iterator<charT,Alloc> & y) {
+	return (x.current_pos < y.current_pos);
+}
+
+template <class charT, class Alloc>
+inline ptrdiff_t operator-(const __rope_iterator<charT,Alloc> & x,
+			   const __rope_iterator<charT,Alloc> & y) {
+	return x.current_pos - y.current_pos;
+}
+
+template <class charT, class Alloc>
+inline __rope_iterator<charT,Alloc>
+operator-(const __rope_iterator<charT,Alloc> & x,
+	  ptrdiff_t n) {
+	return __rope_iterator<charT,Alloc>(x.root_rope, x.current_pos - n);
+}
+
+template <class charT, class Alloc>
+inline __rope_iterator<charT,Alloc>
+operator+(const __rope_iterator<charT,Alloc> & x,
+	  ptrdiff_t n) {
+	return __rope_iterator<charT,Alloc>(x.root_rope, x.current_pos + n);
+}
+
+template <class charT, class Alloc>
+inline __rope_iterator<charT,Alloc>
+operator+(ptrdiff_t n,
+	  const __rope_iterator<charT,Alloc> & x) {
+	return __rope_iterator<charT,Alloc>(x.root_rope, x.current_pos + n);
+}
+
+template <class charT, class Alloc>
+inline
+rope<charT,Alloc>
+operator+ (const rope<charT,Alloc> &left,
+	   const rope<charT,Alloc> &right)
+{
+    return rope<charT,Alloc>
+		(rope<charT,Alloc>::concat(left.tree_ptr, right.tree_ptr));
+    // Inlining this should make it possible to keep left and
+    // right in registers.
+}
+
+template <class charT, class Alloc>
+inline
+rope<charT,Alloc>&
+operator+= (rope<charT,Alloc> &left,
+	    const rope<charT,Alloc> &right)
+{
+    left.append(right);
+    return left;
+}
+
+template <class charT, class Alloc>
+inline
+rope<charT,Alloc>
+operator+ (const rope<charT,Alloc> &left,
+	   const charT* right) {
+    size_t rlen = rope<charT,Alloc>::char_ptr_len(right);
+    return rope<charT,Alloc>
+	   (rope<charT,Alloc>::concat_char_iter(left.tree_ptr, right, rlen)); 
+}
+
+template <class charT, class Alloc>
+inline
+rope<charT,Alloc>&
+operator+= (rope<charT,Alloc> &left,
+	    const charT* right) {
+    left.append(right);
+    return left;
+}
+
+template <class charT, class Alloc>
+inline
+rope<charT,Alloc>
+operator+ (const rope<charT,Alloc> &left, charT right) {
+    return rope<charT,Alloc>
+		(rope<charT,Alloc>::concat_char_iter(left.tree_ptr, &right, 1));
+}
+
+template <class charT, class Alloc>
+inline
+rope<charT,Alloc>&
+operator+= (rope<charT,Alloc> &left, charT right) {
+    left.append(right);
+    return left;
+}
+
+template <class charT, class Alloc>
+bool
+operator< (const rope<charT,Alloc> &left, const rope<charT,Alloc> &right) {
+    return left.compare(right) < 0;
+}
+	
+template <class charT, class Alloc>
+bool
+operator== (const rope<charT,Alloc> &left, const rope<charT,Alloc> &right) {
+    return left.compare(right) == 0;
+}
+
+template <class charT, class Alloc>
+inline bool operator== (const __rope_charT_ptr_proxy<charT,Alloc> & x,
+			const __rope_charT_ptr_proxy<charT,Alloc> & y) {
+	return (x.pos == y.pos && x.root == y.root);
+}
+
+template<class charT, class Alloc>
+ostream& operator<< (ostream& o, const rope<charT, Alloc>& r);        
+	
+typedef rope<char, __ALLOC> crope;
+typedef rope<wchar_t, __ALLOC> wrope;
+
+inline crope::reference __mutable_reference_at(crope& c, size_t i)
+{
+    return c.mutable_reference_at(i);
+}
+
+inline wrope::reference __mutable_reference_at(wrope& c, size_t i)
+{
+    return c.mutable_reference_at(i);
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class charT, class Alloc>
+inline void swap(rope<charT, Alloc>& x, rope<charT, Alloc>& y) {
+  x.swap(y);
+}
+
+#else
+
+inline void swap(crope x, crope y) { x.swap(y); }
+inline void swap(wrope x, wrope y) { x.swap(y); }
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+// Hash functions should probably be revisited later:
+__STL_TEMPLATE_NULL struct hash<crope>
+{
+  size_t operator()(const crope& str) const
+  {
+    size_t sz = str.size();
+
+    if (0 == sz) return 0;
+    return 13*str[0] + 5*str[sz - 1] + sz;
+  }
+};
+
+
+__STL_TEMPLATE_NULL struct hash<wrope>
+{
+  size_t operator()(const wrope& str) const
+  {
+    size_t sz = str.size();
+
+    if (0 == sz) return 0;
+    return 13*str[0] + 5*str[sz - 1] + sz;
+  }
+};
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+# include <ropeimpl.h>
+# endif /* __SGI_STL_INTERNAL_ROPE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_set.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_set.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_set.h	(revision 18)
@@ -0,0 +1,198 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_SET_H
+#define __SGI_STL_INTERNAL_SET_H
+
+__STL_BEGIN_NAMESPACE
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class Key, class Compare = less<Key>, class Alloc = alloc>
+#else
+template <class Key, class Compare, class Alloc = alloc>
+#endif
+class set {
+public:
+  // typedefs:
+
+  typedef Key key_type;
+  typedef Key value_type;
+  typedef Compare key_compare;
+  typedef Compare value_compare;
+private:
+  typedef rb_tree<key_type, value_type, 
+                  identity<value_type>, key_compare, Alloc> rep_type;
+  rep_type t;  // red-black tree representing set
+public:
+  typedef typename rep_type::const_pointer pointer;
+  typedef typename rep_type::const_pointer const_pointer;
+  typedef typename rep_type::const_reference reference;
+  typedef typename rep_type::const_reference const_reference;
+  typedef typename rep_type::const_iterator iterator;
+  typedef typename rep_type::const_iterator const_iterator;
+  typedef typename rep_type::const_reverse_iterator reverse_iterator;
+  typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
+  typedef typename rep_type::size_type size_type;
+  typedef typename rep_type::difference_type difference_type;
+
+  // allocation/deallocation
+
+  set() : t(Compare()) {}
+  explicit set(const Compare& comp) : t(comp) {}
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  set(InputIterator first, InputIterator last)
+    : t(Compare()) { t.insert_unique(first, last); }
+
+  template <class InputIterator>
+  set(InputIterator first, InputIterator last, const Compare& comp)
+    : t(comp) { t.insert_unique(first, last); }
+#else
+  set(const value_type* first, const value_type* last) 
+    : t(Compare()) { t.insert_unique(first, last); }
+  set(const value_type* first, const value_type* last, const Compare& comp)
+    : t(comp) { t.insert_unique(first, last); }
+
+  set(const_iterator first, const_iterator last)
+    : t(Compare()) { t.insert_unique(first, last); }
+  set(const_iterator first, const_iterator last, const Compare& comp)
+    : t(comp) { t.insert_unique(first, last); }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  set(const set<Key, Compare, Alloc>& x) : t(x.t) {}
+  set<Key, Compare, Alloc>& operator=(const set<Key, Compare, Alloc>& x) { 
+    t = x.t; 
+    return *this;
+  }
+
+  // accessors:
+
+  key_compare key_comp() const { return t.key_comp(); }
+  value_compare value_comp() const { return t.key_comp(); }
+  iterator begin() const { return t.begin(); }
+  iterator end() const { return t.end(); }
+  reverse_iterator rbegin() const { return t.rbegin(); } 
+  reverse_iterator rend() const { return t.rend(); }
+  bool empty() const { return t.empty(); }
+  size_type size() const { return t.size(); }
+  size_type max_size() const { return t.max_size(); }
+  void swap(set<Key, Compare, Alloc>& x) { t.swap(x.t); }
+
+  // insert/erase
+  typedef  pair<iterator, bool> pair_iterator_bool; 
+  pair<iterator,bool> insert(const value_type& x) { 
+    pair<typename rep_type::iterator, bool> p = t.insert_unique(x); 
+    return pair<iterator, bool>(p.first, p.second);
+  }
+  iterator insert(iterator position, const value_type& x) {
+    typedef typename rep_type::iterator rep_iterator;
+    return t.insert_unique((rep_iterator&)position, x);
+  }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert(InputIterator first, InputIterator last) {
+    t.insert_unique(first, last);
+  }
+#else
+  void insert(const_iterator first, const_iterator last) {
+    t.insert_unique(first, last);
+  }
+  void insert(const value_type* first, const value_type* last) {
+    t.insert_unique(first, last);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+  void erase(iterator position) { 
+    typedef typename rep_type::iterator rep_iterator;
+    t.erase((rep_iterator&)position); 
+  }
+  size_type erase(const key_type& x) { 
+    return t.erase(x); 
+  }
+  void erase(iterator first, iterator last) { 
+    typedef typename rep_type::iterator rep_iterator;
+    t.erase((rep_iterator&)first, (rep_iterator&)last); 
+  }
+  void clear() { t.clear(); }
+
+  // set operations:
+
+  iterator find(const key_type& x) const { return t.find(x); }
+  size_type count(const key_type& x) const { return t.count(x); }
+  iterator lower_bound(const key_type& x) const {
+    return t.lower_bound(x);
+  }
+  iterator upper_bound(const key_type& x) const {
+    return t.upper_bound(x); 
+  }
+  pair<iterator,iterator> equal_range(const key_type& x) const {
+    return t.equal_range(x);
+  }
+  friend bool operator== __STL_NULL_TMPL_ARGS (const set&, const set&);
+  friend bool operator< __STL_NULL_TMPL_ARGS (const set&, const set&);
+};
+
+template <class Key, class Compare, class Alloc>
+inline bool operator==(const set<Key, Compare, Alloc>& x, 
+                       const set<Key, Compare, Alloc>& y) {
+  return x.t == y.t;
+}
+
+template <class Key, class Compare, class Alloc>
+inline bool operator<(const set<Key, Compare, Alloc>& x, 
+                      const set<Key, Compare, Alloc>& y) {
+  return x.t < y.t;
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Key, class Compare, class Alloc>
+inline void swap(set<Key, Compare, Alloc>& x, 
+                 set<Key, Compare, Alloc>& y) {
+  x.swap(y);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_SET_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_slis.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_slis.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_slis.h	(revision 18)
@@ -0,0 +1,740 @@
+/*
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_SLIST_H
+#define __SGI_STL_INTERNAL_SLIST_H
+
+
+__STL_BEGIN_NAMESPACE 
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+struct __slist_node_base
+{
+  __slist_node_base* next;
+};
+
+inline __slist_node_base* __slist_make_link(__slist_node_base* prev_node,
+                                            __slist_node_base* new_node)
+{
+  new_node->next = prev_node->next;
+  prev_node->next = new_node;
+  return new_node;
+}
+
+inline __slist_node_base* __slist_previous(__slist_node_base* head,
+                                           const __slist_node_base* node)
+{
+  while (head && head->next != node)
+    head = head->next;
+  return head;
+}
+
+inline const __slist_node_base* __slist_previous(const __slist_node_base* head,
+                                                 const __slist_node_base* node)
+{
+  while (head && head->next != node)
+    head = head->next;
+  return head;
+}
+
+inline void __slist_splice_after(__slist_node_base* pos,
+                                 __slist_node_base* before_first,
+                                 __slist_node_base* before_last)
+{
+  if (pos != before_first && pos != before_last) {
+    __slist_node_base* first = before_first->next;
+    __slist_node_base* after = pos->next;
+    before_first->next = before_last->next;
+    pos->next = first;
+    before_last->next = after;
+  }
+}
+
+inline __slist_node_base* __slist_reverse(__slist_node_base* node)
+{
+  __slist_node_base* result = node;
+  node = node->next;
+  result->next = 0;
+  while(node) {
+    __slist_node_base* next = node->next;
+    node->next = result;
+    result = node;
+    node = next;
+  }
+  return result;
+}
+
+template <class T>
+struct __slist_node : public __slist_node_base
+{
+  T data;
+};
+
+struct __slist_iterator_base
+{
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  typedef forward_iterator_tag iterator_category;
+
+  __slist_node_base* node;
+
+  __slist_iterator_base(__slist_node_base* x) : node(x) {}
+  void incr() { node = node->next; }
+
+  bool operator==(const __slist_iterator_base& x) const {
+    return node == x.node;
+  }
+  bool operator!=(const __slist_iterator_base& x) const {
+    return node != x.node;
+  }
+};
+
+template <class T, class Ref, class Ptr>
+struct __slist_iterator : public __slist_iterator_base
+{
+  typedef __slist_iterator<T, T&, T*>             iterator;
+  typedef __slist_iterator<T, const T&, const T*> const_iterator;
+  typedef __slist_iterator<T, Ref, Ptr>           self;
+
+  typedef T value_type;
+  typedef Ptr pointer;
+  typedef Ref reference;
+  typedef __slist_node<T> list_node;
+
+  __slist_iterator(list_node* x) : __slist_iterator_base(x) {}
+  __slist_iterator() : __slist_iterator_base(0) {}
+  __slist_iterator(const iterator& x) : __slist_iterator_base(x.node) {}
+
+  reference operator*() const { return ((list_node*) node)->data; }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+
+  self& operator++()
+  {
+    incr();
+    return *this;
+  }
+  self operator++(int)
+  {
+    self tmp = *this;
+    incr();
+    return tmp;
+  }
+};
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+inline ptrdiff_t*
+distance_type(const __slist_iterator_base&)
+{
+  return 0;
+}
+
+inline forward_iterator_tag
+iterator_category(const __slist_iterator_base&)
+{
+  return forward_iterator_tag();
+}
+
+template <class T, class Ref, class Ptr> 
+inline T* 
+value_type(const __slist_iterator<T, Ref, Ptr>&) {
+  return 0;
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+inline size_t __slist_size(__slist_node_base* node)
+{
+  size_t result = 0;
+  for ( ; node != 0; node = node->next)
+    ++result;
+  return result;
+}
+
+template <class T, class Alloc = alloc>
+class slist
+{
+public:
+  typedef T value_type;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+
+  typedef __slist_iterator<T, T&, T*>             iterator;
+  typedef __slist_iterator<T, const T&, const T*> const_iterator;
+
+private:
+  typedef __slist_node<T> list_node;
+  typedef __slist_node_base list_node_base;
+  typedef __slist_iterator_base iterator_base;
+  typedef simple_alloc<list_node, Alloc> list_node_allocator;
+
+  static list_node* create_node(const value_type& x) {
+    list_node* node = list_node_allocator::allocate();
+    __STL_TRY {
+      construct(&node->data, x);
+      node->next = 0;
+    }
+    __STL_UNWIND(list_node_allocator::deallocate(node));
+    return node;
+  }
+  
+  static void destroy_node(list_node* node) {
+    destroy(&node->data);
+    list_node_allocator::deallocate(node);
+  }
+
+  void fill_initialize(size_type n, const value_type& x) {
+    head.next = 0;
+    __STL_TRY {
+      _insert_after_fill(&head, n, x);
+    }
+    __STL_UNWIND(clear());
+  }    
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void range_initialize(InputIterator first, InputIterator last) {
+    head.next = 0;
+    __STL_TRY {
+      _insert_after_range(&head, first, last);
+    }
+    __STL_UNWIND(clear());
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  void range_initialize(const value_type* first, const value_type* last) {
+    head.next = 0;
+    __STL_TRY {
+      _insert_after_range(&head, first, last);
+    }
+    __STL_UNWIND(clear());
+  }
+  void range_initialize(const_iterator first, const_iterator last) {
+    head.next = 0;
+    __STL_TRY {
+      _insert_after_range(&head, first, last);
+    }
+    __STL_UNWIND(clear());
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+private:
+  list_node_base head;
+
+public:
+  slist() { head.next = 0; }
+
+  slist(size_type n, const value_type& x) { fill_initialize(n, x); }
+  slist(int n, const value_type& x) { fill_initialize(n, x); }
+  slist(long n, const value_type& x) { fill_initialize(n, x); }
+  explicit slist(size_type n) { fill_initialize(n, value_type()); }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  slist(InputIterator first, InputIterator last) {
+    range_initialize(first, last);
+  }
+
+#else /* __STL_MEMBER_TEMPLATES */
+  slist(const_iterator first, const_iterator last) {
+    range_initialize(first, last);
+  }
+  slist(const value_type* first, const value_type* last) {
+    range_initialize(first, last);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  slist(const slist& L) { range_initialize(L.begin(), L.end()); }
+
+  slist& operator= (const slist& L);
+
+  ~slist() { clear(); }
+
+public:
+
+  iterator begin() { return iterator((list_node*)head.next); }
+  const_iterator begin() const { return const_iterator((list_node*)head.next);}
+
+  iterator end() { return iterator(0); }
+  const_iterator end() const { return const_iterator(0); }
+
+  size_type size() const { return __slist_size(head.next); }
+  
+  size_type max_size() const { return size_type(-1); }
+
+  bool empty() const { return head.next == 0; }
+
+  void swap(slist& L)
+  {
+    list_node_base* tmp = head.next;
+    head.next = L.head.next;
+    L.head.next = tmp;
+  }
+
+public:
+  friend bool operator== __STL_NULL_TMPL_ARGS(const slist<T, Alloc>& L1,
+                                              const slist<T, Alloc>& L2);
+
+public:
+
+  reference front() { return ((list_node*) head.next)->data; }
+  const_reference front() const { return ((list_node*) head.next)->data; }
+  void push_front(const value_type& x)   {
+    __slist_make_link(&head, create_node(x));
+  }
+  void pop_front() {
+    list_node* node = (list_node*) head.next;
+    head.next = node->next;
+    destroy_node(node);
+  }
+
+  iterator previous(const_iterator pos) {
+    return iterator((list_node*) __slist_previous(&head, pos.node));
+  }
+  const_iterator previous(const_iterator pos) const {
+    return const_iterator((list_node*) __slist_previous(&head, pos.node));
+  }
+
+private:
+  list_node* _insert_after(list_node_base* pos, const value_type& x) {
+    return (list_node*) (__slist_make_link(pos, create_node(x)));
+  }
+
+  void _insert_after_fill(list_node_base* pos,
+                          size_type n, const value_type& x) {
+    for (size_type i = 0; i < n; ++i)
+      pos = __slist_make_link(pos, create_node(x));
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InIter>
+  void _insert_after_range(list_node_base* pos, InIter first, InIter last) {
+    while (first != last) {
+      pos = __slist_make_link(pos, create_node(*first));
+      ++first;
+    }
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  void _insert_after_range(list_node_base* pos,
+                           const_iterator first, const_iterator last) {
+    while (first != last) {
+      pos = __slist_make_link(pos, create_node(*first));
+      ++first;
+    }
+  }
+  void _insert_after_range(list_node_base* pos,
+                           const value_type* first, const value_type* last) {
+    while (first != last) {
+      pos = __slist_make_link(pos, create_node(*first));
+      ++first;
+    }
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  list_node_base* erase_after(list_node_base* pos) {
+    list_node* next = (list_node*) (pos->next);
+    list_node_base* next_next = next->next;
+    pos->next = next_next;
+    destroy_node(next);
+    return next_next;
+  }
+   
+  list_node_base* erase_after(list_node_base* before_first,
+                              list_node_base* last_node) {
+    list_node* cur = (list_node*) (before_first->next);
+    while (cur != last_node) {
+      list_node* tmp = cur;
+      cur = (list_node*) cur->next;
+      destroy_node(tmp);
+    }
+    before_first->next = last_node;
+    return last_node;
+  }
+
+
+public:
+
+  iterator insert_after(iterator pos, const value_type& x) {
+    return iterator(_insert_after(pos.node, x));
+  }
+
+  iterator insert_after(iterator pos) {
+    return insert_after(pos, value_type());
+  }
+
+  void insert_after(iterator pos, size_type n, const value_type& x) {
+    _insert_after_fill(pos.node, n, x);
+  }
+  void insert_after(iterator pos, int n, const value_type& x) {
+    _insert_after_fill(pos.node, (size_type) n, x);
+  }
+  void insert_after(iterator pos, long n, const value_type& x) {
+    _insert_after_fill(pos.node, (size_type) n, x);
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InIter>
+  void insert_after(iterator pos, InIter first, InIter last) {
+    _insert_after_range(pos.node, first, last);
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  void insert_after(iterator pos, const_iterator first, const_iterator last) {
+    _insert_after_range(pos.node, first, last);
+  }
+  void insert_after(iterator pos,
+                    const value_type* first, const value_type* last) {
+    _insert_after_range(pos.node, first, last);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  iterator insert(iterator pos, const value_type& x) {
+    return iterator(_insert_after(__slist_previous(&head, pos.node), x));
+  }
+
+  iterator insert(iterator pos) {
+    return iterator(_insert_after(__slist_previous(&head, pos.node),
+                                  value_type()));
+  }
+
+  void insert(iterator pos, size_type n, const value_type& x) {
+    _insert_after_fill(__slist_previous(&head, pos.node), n, x);
+  } 
+  void insert(iterator pos, int n, const value_type& x) {
+    _insert_after_fill(__slist_previous(&head, pos.node), (size_type) n, x);
+  } 
+  void insert(iterator pos, long n, const value_type& x) {
+    _insert_after_fill(__slist_previous(&head, pos.node), (size_type) n, x);
+  } 
+    
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InIter>
+  void insert(iterator pos, InIter first, InIter last) {
+    _insert_after_range(__slist_previous(&head, pos.node), first, last);
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  void insert(iterator pos, const_iterator first, const_iterator last) {
+    _insert_after_range(__slist_previous(&head, pos.node), first, last);
+  }
+  void insert(iterator pos, const value_type* first, const value_type* last) {
+    _insert_after_range(__slist_previous(&head, pos.node), first, last);
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+
+public:
+  iterator erase_after(iterator pos) {
+    return iterator((list_node*)erase_after(pos.node));
+  }
+  iterator erase_after(iterator before_first, iterator last) {
+    return iterator((list_node*)erase_after(before_first.node, last.node));
+  }
+
+  iterator erase(iterator pos) {
+    return (list_node*) erase_after(__slist_previous(&head, pos.node));
+  }
+  iterator erase(iterator first, iterator last) {
+    return (list_node*) erase_after(__slist_previous(&head, first.node),
+                                    last.node);
+  }
+
+  void resize(size_type new_size, const T& x);
+  void resize(size_type new_size) { resize(new_size, T()); }
+  void clear() { erase_after(&head, 0); }
+
+public:
+  // Moves the range [before_first + 1, before_last + 1) to *this,
+  //  inserting it immediately after pos.  This is constant time.
+  void splice_after(iterator pos, 
+                    iterator before_first, iterator before_last)
+  {
+    if (before_first != before_last) 
+      __slist_splice_after(pos.node, before_first.node, before_last.node);
+  }
+
+  // Moves the element that follows prev to *this, inserting it immediately
+  //  after pos.  This is constant time.
+  void splice_after(iterator pos, iterator prev)
+  {
+    __slist_splice_after(pos.node, prev.node, prev.node->next);
+  }
+
+
+  // Linear in distance(begin(), pos), and linear in L.size().
+  void splice(iterator pos, slist& L) {
+    if (L.head.next)
+      __slist_splice_after(__slist_previous(&head, pos.node),
+                           &L.head,
+                           __slist_previous(&L.head, 0));
+  }
+
+  // Linear in distance(begin(), pos), and in distance(L.begin(), i).
+  void splice(iterator pos, slist& L, iterator i) {
+    __slist_splice_after(__slist_previous(&head, pos.node),
+                         __slist_previous(&L.head, i.node),
+                         i.node);
+  }
+
+  // Linear in distance(begin(), pos), in distance(L.begin(), first),
+  // and in distance(first, last).
+  void splice(iterator pos, slist& L, iterator first, iterator last)
+  {
+    if (first != last)
+      __slist_splice_after(__slist_previous(&head, pos.node),
+                           __slist_previous(&L.head, first.node),
+                           __slist_previous(first.node, last.node));
+  }
+
+public:
+  void reverse() { if (head.next) head.next = __slist_reverse(head.next); }
+
+  void remove(const T& val); 
+  void unique(); 
+  void merge(slist& L);
+  void sort();     
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class Predicate> void remove_if(Predicate pred);
+  template <class BinaryPredicate> void unique(BinaryPredicate pred); 
+  template <class StrictWeakOrdering> void merge(slist&, StrictWeakOrdering); 
+  template <class StrictWeakOrdering> void sort(StrictWeakOrdering comp); 
+#endif /* __STL_MEMBER_TEMPLATES */
+};
+
+template <class T, class Alloc>
+slist<T, Alloc>& slist<T,Alloc>::operator=(const slist<T, Alloc>& L)
+{
+  if (&L != this) {
+    list_node_base* p1 = &head;
+    list_node* n1 = (list_node*) head.next;
+    const list_node* n2 = (const list_node*) L.head.next;
+    while (n1 && n2) {
+      n1->data = n2->data;
+      p1 = n1;
+      n1 = (list_node*) n1->next;
+      n2 = (const list_node*) n2->next;
+    }
+    if (n2 == 0)
+      erase_after(p1, 0);
+    else
+      _insert_after_range(p1,
+                          const_iterator((list_node*)n2), const_iterator(0));
+  }
+  return *this;
+} 
+
+template <class T, class Alloc>
+bool operator==(const slist<T, Alloc>& L1, const slist<T, Alloc>& L2)
+{
+  typedef typename slist<T,Alloc>::list_node list_node;
+  list_node* n1 = (list_node*) L1.head.next;
+  list_node* n2 = (list_node*) L2.head.next;
+  while (n1 && n2 && n1->data == n2->data) {
+    n1 = (list_node*) n1->next;
+    n2 = (list_node*) n2->next;
+  }
+  return n1 == 0 && n2 == 0;
+}
+
+template <class T, class Alloc>
+inline bool operator<(const slist<T, Alloc>& L1, const slist<T, Alloc>& L2)
+{
+  return lexicographical_compare(L1.begin(), L1.end(), L2.begin(), L2.end());
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class T, class Alloc>
+inline void swap(slist<T, Alloc>& x, slist<T, Alloc>& y) {
+  x.swap(y);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+
+template <class T, class Alloc>
+void slist<T, Alloc>::resize(size_type len, const T& x)
+{
+  list_node_base* cur = &head;
+  while (cur->next != 0 && len > 0) {
+    --len;
+    cur = cur->next;
+  }
+  if (cur->next) 
+    erase_after(cur, 0);
+  else
+    _insert_after_fill(cur, len, x);
+}
+
+template <class T, class Alloc>
+void slist<T,Alloc>::remove(const T& val)
+{
+  list_node_base* cur = &head;
+  while (cur && cur->next) {
+    if (((list_node*) cur->next)->data == val)
+      erase_after(cur);
+    else
+      cur = cur->next;
+  }
+}
+
+template <class T, class Alloc> 
+void slist<T,Alloc>::unique()
+{
+  list_node_base* cur = head.next;
+  if (cur) {
+    while (cur->next) {
+      if (((list_node*)cur)->data == ((list_node*)(cur->next))->data)
+        erase_after(cur);
+      else
+        cur = cur->next;
+    }
+  }
+}
+
+template <class T, class Alloc>
+void slist<T,Alloc>::merge(slist<T,Alloc>& L)
+{
+  list_node_base* n1 = &head;
+  while (n1->next && L.head.next) {
+    if (((list_node*) L.head.next)->data < ((list_node*) n1->next)->data) 
+      __slist_splice_after(n1, &L.head, L.head.next);
+    n1 = n1->next;
+  }
+  if (L.head.next) {
+    n1->next = L.head.next;
+    L.head.next = 0;
+  }
+}
+
+template <class T, class Alloc>
+void slist<T,Alloc>::sort()
+{
+  if (head.next && head.next->next) {
+    slist carry;
+    slist counter[64];
+    int fill = 0;
+    while (!empty()) {
+      __slist_splice_after(&carry.head, &head, head.next);
+      int i = 0;
+      while (i < fill && !counter[i].empty()) {
+        counter[i].merge(carry);
+        carry.swap(counter[i]);
+        ++i;
+      }
+      carry.swap(counter[i]);
+      if (i == fill)
+        ++fill;
+    }
+
+    for (int i = 1; i < fill; ++i)
+      counter[i].merge(counter[i-1]);
+    this->swap(counter[fill-1]);
+  }
+}
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+template <class T, class Alloc> 
+template <class Predicate> void slist<T,Alloc>::remove_if(Predicate pred)
+{
+  list_node_base* cur = &head;
+  while (cur->next) {
+    if (pred(((list_node*) cur->next)->data))
+      erase_after(cur);
+    else
+      cur = cur->next;
+  }
+}
+
+template <class T, class Alloc> template <class BinaryPredicate> 
+void slist<T,Alloc>::unique(BinaryPredicate pred)
+{
+  list_node* cur = (list_node*) head.next;
+  if (cur) {
+    while (cur->next) {
+      if (pred(((list_node*)cur)->data, ((list_node*)(cur->next))->data))
+        erase_after(cur);
+      else
+        cur = (list_node*) cur->next;
+    }
+  }
+}
+
+template <class T, class Alloc> template <class StrictWeakOrdering>
+void slist<T,Alloc>::merge(slist<T,Alloc>& L, StrictWeakOrdering comp)
+{
+  list_node_base* n1 = &head;
+  while (n1->next && L.head.next) {
+    if (comp(((list_node*) L.head.next)->data,
+             ((list_node*) n1->next)->data))
+      __slist_splice_after(n1, &L.head, L.head.next);
+    n1 = n1->next;
+  }
+  if (L.head.next) {
+    n1->next = L.head.next;
+    L.head.next = 0;
+  }
+}
+
+template <class T, class Alloc> template <class StrictWeakOrdering> 
+void slist<T,Alloc>::sort(StrictWeakOrdering comp)
+{
+  if (head.next && head.next->next) {
+    slist carry;
+    slist counter[64];
+    int fill = 0;
+    while (!empty()) {
+      __slist_splice_after(&carry.head, &head, head.next);
+      int i = 0;
+      while (i < fill && !counter[i].empty()) {
+        counter[i].merge(carry, comp);
+        carry.swap(counter[i]);
+        ++i;
+      }
+      carry.swap(counter[i]);
+      if (i == fill)
+        ++fill;
+    }
+
+    for (int i = 1; i < fill; ++i)
+      counter[i].merge(counter[i-1], comp);
+    this->swap(counter[fill-1]);
+  }
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE 
+
+#endif /* __SGI_STL_INTERNAL_SLIST_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_stac.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_stac.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_stac.h	(revision 18)
@@ -0,0 +1,76 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_STACK_H
+#define __SGI_STL_INTERNAL_STACK_H
+
+__STL_BEGIN_NAMESPACE
+
+#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
+template <class T, class Sequence = deque<T> >
+#else
+template <class T, class Sequence>
+#endif
+class stack {
+  friend bool operator== __STL_NULL_TMPL_ARGS (const stack&, const stack&);
+  friend bool operator< __STL_NULL_TMPL_ARGS (const stack&, const stack&);
+public:
+  typedef typename Sequence::value_type value_type;
+  typedef typename Sequence::size_type size_type;
+  typedef typename Sequence::reference reference;
+  typedef typename Sequence::const_reference const_reference;
+protected:
+  Sequence c;
+public:
+  bool empty() const { return c.empty(); }
+  size_type size() const { return c.size(); }
+  reference top() { return c.back(); }
+  const_reference top() const { return c.back(); }
+  void push(const value_type& x) { c.push_back(x); }
+  void pop() { c.pop_back(); }
+};
+
+template <class T, class Sequence>
+bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
+  return x.c == y.c;
+}
+
+template <class T, class Sequence>
+bool operator<(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
+  return x.c < y.c;
+}
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_STACK_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_temp.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_temp.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_temp.h	(revision 18)
@@ -0,0 +1,123 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_TEMPBUF_H
+#define __SGI_STL_INTERNAL_TEMPBUF_H
+
+
+__STL_BEGIN_NAMESPACE
+
+template <class T>
+pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t len, T*) {
+  if (len > ptrdiff_t(INT_MAX / sizeof(T)))
+    len = INT_MAX / sizeof(T);
+
+  while (len > 0) {
+    T* tmp = (T*) malloc((size_t)len * sizeof(T));
+    if (tmp != 0)
+      return pair<T*, ptrdiff_t>(tmp, len);
+    len /= 2;
+  }
+
+  return pair<T*, ptrdiff_t>((T*)0, 0);
+}
+
+template <class T>
+void return_temporary_buffer(T* p) {
+  free(p);
+}
+
+template <class ForwardIterator,
+          class T 
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+                  = iterator_traits<ForwardIterator>::value_type 
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+         >
+class temporary_buffer {
+private:
+  ptrdiff_t original_len;
+  ptrdiff_t len;
+  T* buffer;
+
+  void allocate_buffer() {
+    original_len = len;
+    buffer = 0;
+
+    if (len > (ptrdiff_t)(INT_MAX / sizeof(T)))
+      len = INT_MAX / sizeof(T);
+
+    while (len > 0) {
+      buffer = (T*) malloc(len * sizeof(T));
+      if (buffer)
+        break;
+      len /= 2;
+    }
+  }
+
+  void initialize_buffer(const T&, __true_type) {}
+  void initialize_buffer(const T& val, __false_type) {
+    uninitialized_fill_n(buffer, len, val);
+  }
+
+public:
+  ptrdiff_t size() const { return len; }
+  ptrdiff_t requested_size() const { return original_len; }
+  T* begin() { return buffer; }
+  T* end() { return buffer + len; }
+
+  temporary_buffer(ForwardIterator first, ForwardIterator last) {
+    __STL_TRY {
+      len = 0;
+      distance(first, last, len);
+      allocate_buffer();
+      if (len > 0)
+        initialize_buffer(*first,
+                          __type_traits<T>::has_trivial_default_constructor());
+    }
+    __STL_UNWIND(free(buffer); buffer = 0; len = 0);
+  }
+ 
+  ~temporary_buffer() {  
+    destroy(buffer, buffer + len);
+    free(buffer);
+  }
+
+private:
+  temporary_buffer(const temporary_buffer&) {}
+  void operator=(const temporary_buffer&) {}
+};
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_TEMPBUF_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_tree.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_tree.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_tree.h	(revision 18)
@@ -0,0 +1,1099 @@
+/*
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_TREE_H
+#define __SGI_STL_INTERNAL_TREE_H
+
+/*
+
+Red-black tree class, designed for use in implementing STL
+associative containers (set, multiset, map, and multimap). The
+insertion and deletion algorithms are based on those in Cormen,
+Leiserson, and Rivest, Introduction to Algorithms (MIT Press, 1990),
+except that
+
+(1) the header cell is maintained with links not only to the root
+but also to the leftmost node of the tree, to enable constant time
+begin(), and to the rightmost node of the tree, to enable linear time
+performance when used with the generic set algorithms (set_union,
+etc.);
+
+(2) when a node being deleted has two children its successor node is
+relinked into its place, rather than copied, so that the only
+iterators invalidated are those referring to the deleted node.
+
+*/
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_func.h>
+
+__STL_BEGIN_NAMESPACE 
+
+typedef bool __rb_tree_color_type;
+const __rb_tree_color_type __rb_tree_red = false;
+const __rb_tree_color_type __rb_tree_black = true;
+
+struct __rb_tree_node_base
+{
+  typedef __rb_tree_color_type color_type;
+  typedef __rb_tree_node_base* base_ptr;
+
+  color_type color; 
+  base_ptr parent;
+  base_ptr left;
+  base_ptr right;
+
+  static base_ptr minimum(base_ptr x)
+  {
+    while (x->left != 0) x = x->left;
+    return x;
+  }
+
+  static base_ptr maximum(base_ptr x)
+  {
+    while (x->right != 0) x = x->right;
+    return x;
+  }
+};
+
+template <class Value>
+struct __rb_tree_node : public __rb_tree_node_base
+{
+  typedef __rb_tree_node<Value>* link_type;
+  Value value_field;
+};
+
+
+struct __rb_tree_base_iterator
+{
+  typedef __rb_tree_node_base::base_ptr base_ptr;
+  typedef bidirectional_iterator_tag iterator_category;
+  typedef ptrdiff_t difference_type;
+  base_ptr node;
+
+  void increment()
+  {
+    if (node->right != 0) {
+      node = node->right;
+      while (node->left != 0)
+        node = node->left;
+    }
+    else {
+      base_ptr y = node->parent;
+      while (node == y->right) {
+        node = y;
+        y = y->parent;
+      }
+      if (node->right != y)
+        node = y;
+    }
+  }
+
+  void decrement()
+  {
+    if (node->color == __rb_tree_red &&
+        node->parent->parent == node)
+      node = node->right;
+    else if (node->left != 0) {
+      base_ptr y = node->left;
+      while (y->right != 0)
+        y = y->right;
+      node = y;
+    }
+    else {
+      base_ptr y = node->parent;
+      while (node == y->left) {
+        node = y;
+        y = y->parent;
+      }
+      node = y;
+    }
+  }
+};
+
+template <class Value, class Ref, class Ptr>
+struct __rb_tree_iterator : public __rb_tree_base_iterator
+{
+  typedef Value value_type;
+  typedef Ref reference;
+  typedef Ptr pointer;
+  typedef __rb_tree_iterator<Value, Value&, Value*>             iterator;
+  typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator;
+  typedef __rb_tree_iterator<Value, Ref, Ptr>                   self;
+  typedef __rb_tree_node<Value>* link_type;
+
+  __rb_tree_iterator() {}
+  __rb_tree_iterator(link_type x) { node = x; }
+  __rb_tree_iterator(const iterator& it) { node = it.node; }
+
+  reference operator*() const { return link_type(node)->value_field; }
+#ifndef __SGI_STL_NO_ARROW_OPERATOR
+  pointer operator->() const { return &(operator*()); }
+#endif /* __SGI_STL_NO_ARROW_OPERATOR */
+
+  self& operator++() { increment(); return *this; }
+  self operator++(int) {
+    self tmp = *this;
+    increment();
+    return tmp;
+  }
+    
+  self& operator--() { decrement(); return *this; }
+  self operator--(int) {
+    self tmp = *this;
+    decrement();
+    return tmp;
+  }
+};
+
+inline bool operator==(const __rb_tree_base_iterator& x,
+                       const __rb_tree_base_iterator& y) {
+  return x.node == y.node;
+}
+
+inline bool operator!=(const __rb_tree_base_iterator& x,
+                       const __rb_tree_base_iterator& y) {
+  return x.node != y.node;
+}
+
+#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+inline bidirectional_iterator_tag
+iterator_category(const __rb_tree_base_iterator&) {
+  return bidirectional_iterator_tag();
+}
+
+inline __rb_tree_base_iterator::difference_type*
+distance_type(const __rb_tree_base_iterator&) {
+  return (__rb_tree_base_iterator::difference_type*) 0;
+}
+
+template <class Value, class Ref, class Ptr>
+inline Value* value_type(const __rb_tree_iterator<Value, Ref, Ptr>&) {
+  return (Value*) 0;
+}
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+inline void 
+__rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root)
+{
+  __rb_tree_node_base* y = x->right;
+  x->right = y->left;
+  if (y->left !=0)
+    y->left->parent = x;
+  y->parent = x->parent;
+
+  if (x == root)
+    root = y;
+  else if (x == x->parent->left)
+    x->parent->left = y;
+  else
+    x->parent->right = y;
+  y->left = x;
+  x->parent = y;
+}
+
+inline void 
+__rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root)
+{
+  __rb_tree_node_base* y = x->left;
+  x->left = y->right;
+  if (y->right != 0)
+    y->right->parent = x;
+  y->parent = x->parent;
+
+  if (x == root)
+    root = y;
+  else if (x == x->parent->right)
+    x->parent->right = y;
+  else
+    x->parent->left = y;
+  y->right = x;
+  x->parent = y;
+}
+
+inline void 
+__rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)
+{
+  x->color = __rb_tree_red;
+  while (x != root && x->parent->color == __rb_tree_red) {
+    if (x->parent == x->parent->parent->left) {
+      __rb_tree_node_base* y = x->parent->parent->right;
+      if (y && y->color == __rb_tree_red) {
+        x->parent->color = __rb_tree_black;
+        y->color = __rb_tree_black;
+        x->parent->parent->color = __rb_tree_red;
+        x = x->parent->parent;
+      }
+      else {
+        if (x == x->parent->right) {
+          x = x->parent;
+          __rb_tree_rotate_left(x, root);
+        }
+        x->parent->color = __rb_tree_black;
+        x->parent->parent->color = __rb_tree_red;
+        __rb_tree_rotate_right(x->parent->parent, root);
+      }
+    }
+    else {
+      __rb_tree_node_base* y = x->parent->parent->left;
+      if (y && y->color == __rb_tree_red) {
+        x->parent->color = __rb_tree_black;
+        y->color = __rb_tree_black;
+        x->parent->parent->color = __rb_tree_red;
+        x = x->parent->parent;
+      }
+      else {
+        if (x == x->parent->left) {
+          x = x->parent;
+          __rb_tree_rotate_right(x, root);
+        }
+        x->parent->color = __rb_tree_black;
+        x->parent->parent->color = __rb_tree_red;
+        __rb_tree_rotate_left(x->parent->parent, root);
+      }
+    }
+  }
+  root->color = __rb_tree_black;
+}
+
+inline __rb_tree_node_base*
+__rb_tree_rebalance_for_erase(__rb_tree_node_base* z,
+                              __rb_tree_node_base*& root,
+                              __rb_tree_node_base*& leftmost,
+                              __rb_tree_node_base*& rightmost)
+{
+  __rb_tree_node_base* y = z;
+  __rb_tree_node_base* x = 0;
+  __rb_tree_node_base* x_parent = 0;
+  if (y->left == 0)             // z has at most one non-null child. y == z.
+    x = y->right;               // x might be null.
+  else
+    if (y->right == 0)          // z has exactly one non-null child.  y == z.
+      x = y->left;              // x is not null.
+    else {                      // z has two non-null children.  Set y to
+      y = y->right;             //   z's successor.  x might be null.
+      while (y->left != 0)
+        y = y->left;
+      x = y->right;
+    }
+  if (y != z) {                 // relink y in place of z.  y is z's successor
+    z->left->parent = y; 
+    y->left = z->left;
+    if (y != z->right) {
+      x_parent = y->parent;
+      if (x) x->parent = y->parent;
+      y->parent->left = x;      // y must be a left child
+      y->right = z->right;
+      z->right->parent = y;
+    }
+    else
+      x_parent = y;  
+    if (root == z)
+      root = y;
+    else if (z->parent->left == z)
+      z->parent->left = y;
+    else 
+      z->parent->right = y;
+    y->parent = z->parent;
+    __STD::swap(y->color, z->color);
+    y = z;
+    // y now points to node to be actually deleted
+  }
+  else {                        // y == z
+    x_parent = y->parent;
+    if (x) x->parent = y->parent;   
+    if (root == z)
+      root = x;
+    else 
+      if (z->parent->left == z)
+        z->parent->left = x;
+      else
+        z->parent->right = x;
+    if (leftmost == z) 
+      if (z->right == 0)        // z->left must be null also
+        leftmost = z->parent;
+    // makes leftmost == header if z == root
+      else
+        leftmost = __rb_tree_node_base::minimum(x);
+    if (rightmost == z)  
+      if (z->left == 0)         // z->right must be null also
+        rightmost = z->parent;  
+    // makes rightmost == header if z == root
+      else                      // x == z->left
+        rightmost = __rb_tree_node_base::maximum(x);
+  }
+  if (y->color != __rb_tree_red) { 
+    while (x != root && (x == 0 || x->color == __rb_tree_black))
+      if (x == x_parent->left) {
+        __rb_tree_node_base* w = x_parent->right;
+        if (w->color == __rb_tree_red) {
+          w->color = __rb_tree_black;
+          x_parent->color = __rb_tree_red;
+          __rb_tree_rotate_left(x_parent, root);
+          w = x_parent->right;
+        }
+        if ((w->left == 0 || w->left->color == __rb_tree_black) &&
+            (w->right == 0 || w->right->color == __rb_tree_black)) {
+          w->color = __rb_tree_red;
+          x = x_parent;
+          x_parent = x_parent->parent;
+        } else {
+          if (w->right == 0 || w->right->color == __rb_tree_black) {
+            if (w->left) w->left->color = __rb_tree_black;
+            w->color = __rb_tree_red;
+            __rb_tree_rotate_right(w, root);
+            w = x_parent->right;
+          }
+          w->color = x_parent->color;
+          x_parent->color = __rb_tree_black;
+          if (w->right) w->right->color = __rb_tree_black;
+          __rb_tree_rotate_left(x_parent, root);
+          break;
+        }
+      } else {                  // same as above, with right <-> left.
+        __rb_tree_node_base* w = x_parent->left;
+        if (w->color == __rb_tree_red) {
+          w->color = __rb_tree_black;
+          x_parent->color = __rb_tree_red;
+          __rb_tree_rotate_right(x_parent, root);
+          w = x_parent->left;
+        }
+        if ((w->right == 0 || w->right->color == __rb_tree_black) &&
+            (w->left == 0 || w->left->color == __rb_tree_black)) {
+          w->color = __rb_tree_red;
+          x = x_parent;
+          x_parent = x_parent->parent;
+        } else {
+          if (w->left == 0 || w->left->color == __rb_tree_black) {
+            if (w->right) w->right->color = __rb_tree_black;
+            w->color = __rb_tree_red;
+            __rb_tree_rotate_left(w, root);
+            w = x_parent->left;
+          }
+          w->color = x_parent->color;
+          x_parent->color = __rb_tree_black;
+          if (w->left) w->left->color = __rb_tree_black;
+          __rb_tree_rotate_right(x_parent, root);
+          break;
+        }
+      }
+    if (x) x->color = __rb_tree_black;
+  }
+  return y;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare,
+          class Alloc = alloc>
+class rb_tree {
+protected:
+  typedef void* void_pointer;
+  typedef __rb_tree_node_base* base_ptr;
+  typedef __rb_tree_node<Value> rb_tree_node;
+  typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator;
+  typedef __rb_tree_color_type color_type;
+public:
+  typedef Key key_type;
+  typedef Value value_type;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef rb_tree_node* link_type;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+protected:
+  link_type get_node() { return rb_tree_node_allocator::allocate(); }
+  void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); }
+
+  link_type create_node(const value_type& x) {
+    link_type tmp = get_node();
+    __STL_TRY {
+      construct(&tmp->value_field, x);
+    }
+    __STL_UNWIND(put_node(tmp));
+    return tmp;
+  }
+
+  link_type clone_node(link_type x) {
+    link_type tmp = create_node(x->value_field);
+    tmp->color = x->color;
+    tmp->left = 0;
+    tmp->right = 0;
+    return tmp;
+  }
+
+  void destroy_node(link_type p) {
+    destroy(&p->value_field);
+    put_node(p);
+  }
+
+protected:
+  size_type node_count; // keeps track of size of tree
+  link_type header;  
+  Compare key_compare;
+
+  link_type& root() const { return (link_type&) header->parent; }
+  link_type& leftmost() const { return (link_type&) header->left; }
+  link_type& rightmost() const { return (link_type&) header->right; }
+
+  static link_type& left(link_type x) { return (link_type&)(x->left); }
+  static link_type& right(link_type x) { return (link_type&)(x->right); }
+  static link_type& parent(link_type x) { return (link_type&)(x->parent); }
+  static reference value(link_type x) { return x->value_field; }
+  static const Key& key(link_type x) { return KeyOfValue()(value(x)); }
+  static color_type& color(link_type x) { return (color_type&)(x->color); }
+
+  static link_type& left(base_ptr x) { return (link_type&)(x->left); }
+  static link_type& right(base_ptr x) { return (link_type&)(x->right); }
+  static link_type& parent(base_ptr x) { return (link_type&)(x->parent); }
+  static reference value(base_ptr x) { return ((link_type)x)->value_field; }
+  static const Key& key(base_ptr x) { return KeyOfValue()(value(link_type(x)));} 
+  static color_type& color(base_ptr x) { return (color_type&)(link_type(x)->color); }
+
+  static link_type minimum(link_type x) { 
+    return (link_type)  __rb_tree_node_base::minimum(x);
+  }
+  static link_type maximum(link_type x) {
+    return (link_type) __rb_tree_node_base::maximum(x);
+  }
+
+public:
+  typedef __rb_tree_iterator<value_type, reference, pointer> iterator;
+  typedef __rb_tree_iterator<value_type, const_reference, const_pointer> 
+          const_iterator;
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+  typedef reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef reverse_iterator<iterator> reverse_iterator;
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+  typedef reverse_bidirectional_iterator<iterator, value_type, reference,
+                                         difference_type>
+          reverse_iterator; 
+  typedef reverse_bidirectional_iterator<const_iterator, value_type,
+                                         const_reference, difference_type>
+          const_reverse_iterator;
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ 
+private:
+  iterator __insert(base_ptr x, base_ptr y, const value_type& v);
+  link_type __copy(link_type x, link_type p);
+  void __erase(link_type x);
+  void init() {
+    header = get_node();
+    color(header) = __rb_tree_red; // used to distinguish header from 
+                                   // root, in iterator.operator++
+    root() = 0;
+    leftmost() = header;
+    rightmost() = header;
+  }
+public:
+                                // allocation/deallocation
+  rb_tree(const Compare& comp = Compare())
+    : node_count(0), key_compare(comp) { init(); }
+
+  rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) 
+    : node_count(0), key_compare(x.key_compare)
+  { 
+    header = get_node();
+    color(header) = __rb_tree_red;
+    if (x.root() == 0) {
+      root() = 0;
+      leftmost() = header;
+      rightmost() = header;
+    }
+    else {
+      __STL_TRY {
+        root() = __copy(x.root(), header);
+      }
+      __STL_UNWIND(put_node(header));
+      leftmost() = minimum(root());
+      rightmost() = maximum(root());
+    }
+    node_count = x.node_count;
+  }
+  ~rb_tree() {
+    clear();
+    put_node(header);
+  }
+  rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& 
+  operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x);
+
+public:    
+                                // accessors:
+  Compare key_comp() const { return key_compare; }
+  iterator begin() { return leftmost(); }
+  const_iterator begin() const { return leftmost(); }
+  iterator end() { return header; }
+  const_iterator end() const { return header; }
+  reverse_iterator rbegin() { return reverse_iterator(end()); }
+  const_reverse_iterator rbegin() const { 
+    return const_reverse_iterator(end()); 
+  }
+  reverse_iterator rend() { return reverse_iterator(begin()); }
+  const_reverse_iterator rend() const { 
+    return const_reverse_iterator(begin());
+  } 
+  bool empty() const { return node_count == 0; }
+  size_type size() const { return node_count; }
+  size_type max_size() const { return size_type(-1); }
+
+  void swap(rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& t) {
+    __STD::swap(header, t.header);
+    __STD::swap(node_count, t.node_count);
+    __STD::swap(key_compare, t.key_compare);
+  }
+    
+public:
+                                // insert/erase
+  pair<iterator,bool> insert_unique(const value_type& x);
+  iterator insert_equal(const value_type& x);
+
+  iterator insert_unique(iterator position, const value_type& x);
+  iterator insert_equal(iterator position, const value_type& x);
+
+#ifdef __STL_MEMBER_TEMPLATES  
+  template <class InputIterator>
+  void insert_unique(InputIterator first, InputIterator last);
+  template <class InputIterator>
+  void insert_equal(InputIterator first, InputIterator last);
+#else /* __STL_MEMBER_TEMPLATES */
+  void insert_unique(const_iterator first, const_iterator last);
+  void insert_unique(const value_type* first, const value_type* last);
+  void insert_equal(const_iterator first, const_iterator last);
+  void insert_equal(const value_type* first, const value_type* last);
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  void erase(iterator position);
+  size_type erase(const key_type& x);
+  void erase(iterator first, iterator last);
+  void erase(const key_type* first, const key_type* last);
+  void clear() {
+    if (node_count != 0) {
+      __erase(root());
+      leftmost() = header;
+      root() = 0;
+      rightmost() = header;
+      node_count = 0;
+    }
+  }      
+
+public:
+                                // set operations:
+  iterator find(const key_type& x);
+  const_iterator find(const key_type& x) const;
+  size_type count(const key_type& x) const;
+  iterator lower_bound(const key_type& x);
+  const_iterator lower_bound(const key_type& x) const;
+  iterator upper_bound(const key_type& x);
+  const_iterator upper_bound(const key_type& x) const;
+  pair<iterator,iterator> equal_range(const key_type& x);
+  pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
+
+public:
+                                // Debugging.
+  bool __rb_verify() const;
+};
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+inline bool operator==(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, 
+                       const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) {
+  return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+inline bool operator<(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, 
+                      const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) {
+  return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+inline void swap(rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x, 
+                 rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& y) {
+  x.swap(y);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::
+operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) {
+  if (this != &x) {
+                                // Note that Key may be a constant type.
+    clear();
+    node_count = 0;
+    key_compare = x.key_compare;        
+    if (x.root() == 0) {
+      root() = 0;
+      leftmost() = header;
+      rightmost() = header;
+    }
+    else {
+      root() = __copy(x.root(), header);
+      leftmost() = minimum(root());
+      rightmost() = maximum(root());
+      node_count = x.node_count;
+    }
+  }
+  return *this;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::
+__insert(base_ptr x_, base_ptr y_, const Value& v) {
+  link_type x = (link_type) x_;
+  link_type y = (link_type) y_;
+  link_type z;
+
+  if (y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))) {
+    z = create_node(v);
+    left(y) = z;                // also makes leftmost() = z when y == header
+    if (y == header) {
+      root() = z;
+      rightmost() = z;
+    }
+    else if (y == leftmost())
+      leftmost() = z;           // maintain leftmost() pointing to min node
+  }
+  else {
+    z = create_node(v);
+    right(y) = z;
+    if (y == rightmost())
+      rightmost() = z;          // maintain rightmost() pointing to max node
+  }
+  parent(z) = y;
+  left(z) = 0;
+  right(z) = 0;
+  __rb_tree_rebalance(z, header->parent);
+  ++node_count;
+  return iterator(z);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_equal(const Value& v)
+{
+  link_type y = header;
+  link_type x = root();
+  while (x != 0) {
+    y = x;
+    x = key_compare(KeyOfValue()(v), key(x)) ? left(x) : right(x);
+  }
+  return __insert(x, y, v);
+}
+
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool>
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const Value& v)
+{
+  link_type y = header;
+  link_type x = root();
+  bool comp = true;
+  while (x != 0) {
+    y = x;
+    comp = key_compare(KeyOfValue()(v), key(x));
+    x = comp ? left(x) : right(x);
+  }
+  iterator j = iterator(y);   
+  if (comp)
+    if (j == begin())     
+      return pair<iterator,bool>(__insert(x, y, v), true);
+    else
+      --j;
+  if (key_compare(key(j.node), KeyOfValue()(v)))
+    return pair<iterator,bool>(__insert(x, y, v), true);
+  return pair<iterator,bool>(j, false);
+}
+
+
+template <class Key, class Val, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::iterator 
+rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::insert_unique(iterator position,
+                                                             const Val& v) {
+  if (position.node == header->left) // begin()
+    if (size() > 0 && key_compare(KeyOfValue()(v), key(position.node)))
+      return __insert(position.node, position.node, v);
+  // first argument just needs to be non-null 
+    else
+      return insert_unique(v).first;
+  else if (position.node == header) // end()
+    if (key_compare(key(rightmost()), KeyOfValue()(v)))
+      return __insert(0, rightmost(), v);
+    else
+      return insert_unique(v).first;
+  else {
+    iterator before = position;
+    --before;
+    if (key_compare(key(before.node), KeyOfValue()(v))
+        && key_compare(KeyOfValue()(v), key(position.node)))
+      if (right(before.node) == 0)
+        return __insert(0, before.node, v); 
+      else
+        return __insert(position.node, position.node, v);
+    // first argument just needs to be non-null 
+    else
+      return insert_unique(v).first;
+  }
+}
+
+template <class Key, class Val, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::iterator 
+rb_tree<Key, Val, KeyOfValue, Compare, Alloc>::insert_equal(iterator position,
+                                                            const Val& v) {
+  if (position.node == header->left) // begin()
+    if (size() > 0 && key_compare(KeyOfValue()(v), key(position.node)))
+      return __insert(position.node, position.node, v);
+  // first argument just needs to be non-null 
+    else
+      return insert_equal(v);
+  else if (position.node == header) // end()
+    if (!key_compare(KeyOfValue()(v), key(rightmost())))
+      return __insert(0, rightmost(), v);
+    else
+      return insert_equal(v);
+  else {
+    iterator before = position;
+    --before;
+    if (!key_compare(KeyOfValue()(v), key(before.node))
+        && !key_compare(key(position.node), KeyOfValue()(v)))
+      if (right(before.node) == 0)
+        return __insert(0, before.node, v); 
+      else
+        return __insert(position.node, position.node, v);
+    // first argument just needs to be non-null 
+    else
+      return insert_equal(v);
+  }
+}
+
+#ifdef __STL_MEMBER_TEMPLATES  
+
+template <class K, class V, class KoV, class Cmp, class Al> template<class II>
+void rb_tree<K, V, KoV, Cmp, Al>::insert_equal(II first, II last) {
+  for ( ; first != last; ++first)
+    insert_equal(*first);
+}
+
+template <class K, class V, class KoV, class Cmp, class Al> template<class II>
+void rb_tree<K, V, KoV, Cmp, Al>::insert_unique(II first, II last) {
+  for ( ; first != last; ++first)
+    insert_unique(*first);
+}
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+template <class K, class V, class KoV, class Cmp, class Al>
+void
+rb_tree<K, V, KoV, Cmp, Al>::insert_equal(const V* first, const V* last) {
+  for ( ; first != last; ++first)
+    insert_equal(*first);
+}
+
+template <class K, class V, class KoV, class Cmp, class Al>
+void
+rb_tree<K, V, KoV, Cmp, Al>::insert_equal(const_iterator first,
+                                          const_iterator last) {
+  for ( ; first != last; ++first)
+    insert_equal(*first);
+}
+
+template <class K, class V, class KoV, class Cmp, class A>
+void 
+rb_tree<K, V, KoV, Cmp, A>::insert_unique(const V* first, const V* last) {
+  for ( ; first != last; ++first)
+    insert_unique(*first);
+}
+
+template <class K, class V, class KoV, class Cmp, class A>
+void 
+rb_tree<K, V, KoV, Cmp, A>::insert_unique(const_iterator first,
+                                          const_iterator last) {
+  for ( ; first != last; ++first)
+    insert_unique(*first);
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+         
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+inline void
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator position) {
+  link_type y = (link_type) __rb_tree_rebalance_for_erase(position.node,
+                                                          header->parent,
+                                                          header->left,
+                                                          header->right);
+  destroy_node(y);
+  --node_count;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::size_type 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(const Key& x) {
+  pair<iterator,iterator> p = equal_range(x);
+  size_type n = 0;
+  distance(p.first, p.second, n);
+  erase(p.first, p.second);
+  return n;
+}
+
+template <class K, class V, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<K, V, KeyOfValue, Compare, Alloc>::link_type 
+rb_tree<K, V, KeyOfValue, Compare, Alloc>::__copy(link_type x, link_type p) {
+                                // structural copy.  x and p must be non-null.
+  link_type top = clone_node(x);
+  top->parent = p;
+ 
+  __STL_TRY {
+    if (x->right)
+      top->right = __copy(right(x), top);
+    p = top;
+    x = left(x);
+
+    while (x != 0) {
+      link_type y = clone_node(x);
+      p->left = y;
+      y->parent = p;
+      if (x->right)
+        y->right = __copy(right(x), y);
+      p = y;
+      x = left(x);
+    }
+  }
+  __STL_UNWIND(__erase(top));
+
+  return top;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__erase(link_type x) {
+                                // erase without rebalancing
+  while (x != 0) {
+    __erase(right(x));
+    link_type y = left(x);
+    destroy_node(x);
+    x = y;
+  }
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(iterator first, 
+                                                            iterator last) {
+  if (first == begin() && last == end())
+    clear();
+  else
+    while (first != last) erase(first++);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::erase(const Key* first, 
+                                                            const Key* last) {
+  while (first != last) erase(*first++);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Key& k) {
+  link_type y = header;        // Last node which is not less than k. 
+  link_type x = root();        // Current node. 
+
+  while (x != 0) 
+    if (!key_compare(key(x), k))
+      y = x, x = left(x);
+    else
+      x = right(x);
+
+  iterator j = iterator(y);   
+  return (j == end() || key_compare(k, key(j.node))) ? end() : j;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Key& k) const {
+  link_type y = header; /* Last node which is not less than k. */
+  link_type x = root(); /* Current node. */
+
+  while (x != 0) {
+    if (!key_compare(key(x), k))
+      y = x, x = left(x);
+    else
+      x = right(x);
+  }
+  const_iterator j = const_iterator(y);   
+  return (j == end() || key_compare(k, key(j.node))) ? end() : j;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::size_type 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::count(const Key& k) const {
+  pair<const_iterator, const_iterator> p = equal_range(k);
+  size_type n = 0;
+  distance(p.first, p.second, n);
+  return n;
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::lower_bound(const Key& k) {
+  link_type y = header; /* Last node which is not less than k. */
+  link_type x = root(); /* Current node. */
+
+  while (x != 0) 
+    if (!key_compare(key(x), k))
+      y = x, x = left(x);
+    else
+      x = right(x);
+
+  return iterator(y);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::lower_bound(const Key& k) const {
+  link_type y = header; /* Last node which is not less than k. */
+  link_type x = root(); /* Current node. */
+
+  while (x != 0) 
+    if (!key_compare(key(x), k))
+      y = x, x = left(x);
+    else
+      x = right(x);
+
+  return const_iterator(y);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::upper_bound(const Key& k) {
+  link_type y = header; /* Last node which is greater than k. */
+  link_type x = root(); /* Current node. */
+
+   while (x != 0) 
+     if (key_compare(k, key(x)))
+       y = x, x = left(x);
+     else
+       x = right(x);
+
+   return iterator(y);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::const_iterator 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::upper_bound(const Key& k) const {
+  link_type y = header; /* Last node which is greater than k. */
+  link_type x = root(); /* Current node. */
+
+   while (x != 0) 
+     if (key_compare(k, key(x)))
+       y = x, x = left(x);
+     else
+       x = right(x);
+
+   return const_iterator(y);
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+inline pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator,
+            typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator>
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::equal_range(const Key& k) {
+  return pair<iterator, iterator>(lower_bound(k), upper_bound(k));
+}
+
+template <class Key, class Value, class KoV, class Compare, class Alloc>
+inline pair<typename rb_tree<Key, Value, KoV, Compare, Alloc>::const_iterator,
+            typename rb_tree<Key, Value, KoV, Compare, Alloc>::const_iterator>
+rb_tree<Key, Value, KoV, Compare, Alloc>::equal_range(const Key& k) const {
+  return pair<const_iterator,const_iterator>(lower_bound(k), upper_bound(k));
+}
+
+inline int __black_count(__rb_tree_node_base* node, __rb_tree_node_base* root)
+{
+  if (node == 0)
+    return 0;
+  else {
+    int bc = node->color == __rb_tree_black ? 1 : 0;
+    if (node == root)
+      return bc;
+    else
+      return bc + __black_count(node->parent, root);
+  }
+}
+
+template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
+bool 
+rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__rb_verify() const
+{
+  if (node_count == 0 || begin() == end())
+    return node_count == 0 && begin() == end() &&
+      header->left == header && header->right == header;
+  
+  int len = __black_count(leftmost(), root());
+  for (const_iterator it = begin(); it != end(); ++it) {
+    link_type x = (link_type) it.node;
+    link_type L = left(x);
+    link_type R = right(x);
+
+    if (x->color == __rb_tree_red)
+      if ((L && L->color == __rb_tree_red) ||
+          (R && R->color == __rb_tree_red))
+        return false;
+
+    if (L && key_compare(key(x), key(L)))
+      return false;
+    if (R && key_compare(key(R), key(x)))
+      return false;
+
+    if (!L && !R && __black_count(x, root()) != len)
+      return false;
+  }
+
+  if (leftmost() != __rb_tree_node_base::minimum(root()))
+    return false;
+  if (rightmost() != __rb_tree_node_base::maximum(root()))
+    return false;
+
+  return true;
+}
+
+__STL_END_NAMESPACE 
+
+#endif /* __SGI_STL_INTERNAL_TREE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_unin.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_unin.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_unin.h	(revision 18)
@@ -0,0 +1,242 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_UNINITIALIZED_H
+#define __SGI_STL_INTERNAL_UNINITIALIZED_H
+
+__STL_BEGIN_NAMESPACE
+
+// Valid if copy construction is equivalent to assignment, and if the
+//  destructor is trivial.
+template <class InputIterator, class ForwardIterator>
+inline ForwardIterator 
+__uninitialized_copy_aux(InputIterator first, InputIterator last,
+                         ForwardIterator result,
+                         __true_type) {
+  return copy(first, last, result);
+}
+
+template <class InputIterator, class ForwardIterator>
+ForwardIterator 
+__uninitialized_copy_aux(InputIterator first, InputIterator last,
+                         ForwardIterator result,
+                         __false_type) {
+  ForwardIterator cur = result;
+  __STL_TRY {
+    for ( ; first != last; ++first, ++cur)
+      construct(&*cur, *first);
+    return cur;
+  }
+  __STL_UNWIND(destroy(result, cur));
+}
+
+
+template <class InputIterator, class ForwardIterator, class T>
+inline ForwardIterator
+__uninitialized_copy(InputIterator first, InputIterator last,
+                     ForwardIterator result, T*) {
+  typedef typename __type_traits<T>::is_POD_type is_POD;
+  return __uninitialized_copy_aux(first, last, result, is_POD());
+}
+
+template <class InputIterator, class ForwardIterator>
+inline ForwardIterator
+  uninitialized_copy(InputIterator first, InputIterator last,
+                     ForwardIterator result) {
+  return __uninitialized_copy(first, last, result, value_type(result));
+}
+
+inline char* uninitialized_copy(const char* first, const char* last,
+                                char* result) {
+  memmove(result, first, last - first);
+  return result + (last - first);
+}
+
+inline wchar_t* uninitialized_copy(const wchar_t* first, const wchar_t* last,
+                                   wchar_t* result) {
+  memmove(result, first, sizeof(wchar_t) * (last - first));
+  return result + (last - first);
+}
+
+template <class InputIterator, class Size, class ForwardIterator>
+pair<InputIterator, ForwardIterator>
+__uninitialized_copy_n(InputIterator first, Size count,
+                       ForwardIterator result,
+                       input_iterator_tag) {
+  ForwardIterator cur = result;
+  __STL_TRY {
+    for ( ; count > 0 ; --count, ++first, ++cur) 
+      construct(&*cur, *first);
+    return pair<InputIterator, ForwardIterator>(first, cur);
+  }
+  __STL_UNWIND(destroy(result, cur));
+}
+
+template <class RandomAccessIterator, class Size, class ForwardIterator>
+inline pair<RandomAccessIterator, ForwardIterator>
+__uninitialized_copy_n(RandomAccessIterator first, Size count,
+                       ForwardIterator result,
+                       random_access_iterator_tag) {
+  RandomAccessIterator last = first + count;
+  return make_pair(last, uninitialized_copy(first, last, result));
+}
+
+template <class InputIterator, class Size, class ForwardIterator>
+inline pair<InputIterator, ForwardIterator>
+uninitialized_copy_n(InputIterator first, Size count,
+                     ForwardIterator result) {
+  return __uninitialized_copy_n(first, count, result,
+                                iterator_category(first));
+}
+
+// Valid if copy construction is equivalent to assignment, and if the
+//  destructor is trivial.
+template <class ForwardIterator, class T>
+inline void
+__uninitialized_fill_aux(ForwardIterator first, ForwardIterator last, 
+                         const T& x, __true_type)
+{
+  fill(first, last, x);
+}
+
+template <class ForwardIterator, class T>
+void
+__uninitialized_fill_aux(ForwardIterator first, ForwardIterator last, 
+                         const T& x, __false_type)
+{
+  ForwardIterator cur = first;
+  __STL_TRY {
+    for ( ; cur != last; ++cur)
+      construct(&*cur, x);
+  }
+  __STL_UNWIND(destroy(first, cur));
+}
+
+template <class ForwardIterator, class T, class T1>
+inline void __uninitialized_fill(ForwardIterator first, ForwardIterator last, 
+                                 const T& x, T1*) {
+  typedef typename __type_traits<T1>::is_POD_type is_POD;
+  __uninitialized_fill_aux(first, last, x, is_POD());
+                   
+}
+
+template <class ForwardIterator, class T>
+inline void uninitialized_fill(ForwardIterator first, ForwardIterator last, 
+                               const T& x) {
+  __uninitialized_fill(first, last, x, value_type(first));
+}
+
+// Valid if copy construction is equivalent to assignment, and if the
+//  destructor is trivial.
+template <class ForwardIterator, class Size, class T>
+inline ForwardIterator
+__uninitialized_fill_n_aux(ForwardIterator first, Size n,
+                           const T& x, __true_type) {
+  return fill_n(first, n, x);
+}
+
+template <class ForwardIterator, class Size, class T>
+ForwardIterator
+__uninitialized_fill_n_aux(ForwardIterator first, Size n,
+                           const T& x, __false_type) {
+  ForwardIterator cur = first;
+  __STL_TRY {
+    for ( ; n > 0; --n, ++cur)
+      construct(&*cur, x);
+    return cur;
+  }
+  __STL_UNWIND(destroy(first, cur));
+}
+
+template <class ForwardIterator, class Size, class T, class T1>
+inline ForwardIterator __uninitialized_fill_n(ForwardIterator first, Size n,
+                                              const T& x, T1*) {
+  typedef typename __type_traits<T1>::is_POD_type is_POD;
+  return __uninitialized_fill_n_aux(first, n, x, is_POD());
+                                    
+}
+
+template <class ForwardIterator, class Size, class T>
+inline ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n,
+                                            const T& x) {
+  return __uninitialized_fill_n(first, n, x, value_type(first));
+}
+
+// Copies [first1, last1) into [result, result + (last1 - first1)), and
+//  copies [first2, last2) into
+//  [result, result + (last1 - first1) + (last2 - first2)).
+
+template <class InputIterator1, class InputIterator2, class ForwardIterator>
+inline ForwardIterator
+__uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1,
+                          InputIterator2 first2, InputIterator2 last2,
+                          ForwardIterator result) {
+  ForwardIterator mid = uninitialized_copy(first1, last1, result);
+  __STL_TRY {
+    return uninitialized_copy(first2, last2, mid);
+  }
+  __STL_UNWIND(destroy(result, mid));
+}
+
+// Fills [result, mid) with x, and copies [first, last) into
+//  [mid, mid + (last - first)).
+template <class ForwardIterator, class T, class InputIterator>
+inline ForwardIterator 
+__uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid,
+                          const T& x,
+                          InputIterator first, InputIterator last) {
+  uninitialized_fill(result, mid, x);
+  __STL_TRY {
+    return uninitialized_copy(first, last, mid);
+  }
+  __STL_UNWIND(destroy(result, mid));
+}
+
+// Copies [first1, last1) into [first2, first2 + (last1 - first1)), and
+//  fills [first2 + (last1 - first1), last2) with x.
+template <class InputIterator, class ForwardIterator, class T>
+inline void
+__uninitialized_copy_fill(InputIterator first1, InputIterator last1,
+                          ForwardIterator first2, ForwardIterator last2,
+                          const T& x) {
+  ForwardIterator mid2 = uninitialized_copy(first1, last1, first2);
+  __STL_TRY {
+    uninitialized_fill(mid2, last2, x);
+  }
+  __STL_UNWIND(destroy(first2, mid2));
+}
+
+__STL_END_NAMESPACE
+
+#endif /* __SGI_STL_INTERNAL_UNINITIALIZED_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/stl_vect.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stl_vect.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stl_vect.h	(revision 18)
@@ -0,0 +1,534 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/* NOTE: This is an internal header file, included by other STL headers.
+ *   You should not attempt to use it directly.
+ */
+
+#ifndef __SGI_STL_INTERNAL_VECTOR_H
+#define __SGI_STL_INTERNAL_VECTOR_H
+
+__STL_BEGIN_NAMESPACE 
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma set woff 1174
+#endif
+
+template <class T, class Alloc = alloc>
+class vector {
+public:
+  typedef T value_type;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type* iterator;
+  typedef const value_type* const_iterator;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+  typedef reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef reverse_iterator<iterator> reverse_iterator;
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+  typedef reverse_iterator<const_iterator, value_type, const_reference, 
+                           difference_type>  const_reverse_iterator;
+  typedef reverse_iterator<iterator, value_type, reference, difference_type>
+          reverse_iterator;
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+protected:
+  typedef simple_alloc<value_type, Alloc> data_allocator;
+  iterator start;
+  iterator finish;
+  iterator end_of_storage;
+  void insert_aux(iterator position, const T& x);
+  void deallocate() {
+    if (start) data_allocator::deallocate(start, end_of_storage - start);
+  }
+
+  void fill_initialize(size_type n, const T& value) {
+    start = allocate_and_fill(n, value);
+    finish = start + n;
+    end_of_storage = finish;
+  }
+public:
+  iterator begin() { return start; }
+  const_iterator begin() const { return start; }
+  iterator end() { return finish; }
+  const_iterator end() const { return finish; }
+  reverse_iterator rbegin() { return reverse_iterator(end()); }
+  const_reverse_iterator rbegin() const { 
+    return const_reverse_iterator(end()); 
+  }
+  reverse_iterator rend() { return reverse_iterator(begin()); }
+  const_reverse_iterator rend() const { 
+    return const_reverse_iterator(begin()); 
+  }
+  size_type size() const { return size_type(end() - begin()); }
+  size_type max_size() const { return size_type(-1) / sizeof(T); }
+  size_type capacity() const { return size_type(end_of_storage - begin()); }
+  bool empty() const { return begin() == end(); }
+  reference operator[](size_type n) { return *(begin() + n); }
+  const_reference operator[](size_type n) const { return *(begin() + n); }
+
+  vector() : start(0), finish(0), end_of_storage(0) {}
+  vector(size_type n, const T& value) { fill_initialize(n, value); }
+  vector(int n, const T& value) { fill_initialize(n, value); }
+  vector(long n, const T& value) { fill_initialize(n, value); }
+  explicit vector(size_type n) { fill_initialize(n, T()); }
+
+  vector(const vector<T, Alloc>& x) {
+    start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
+    finish = start + (x.end() - x.begin());
+    end_of_storage = finish;
+  }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  vector(InputIterator first, InputIterator last) :
+    start(0), finish(0), end_of_storage(0)
+  {
+    range_initialize(first, last, iterator_category(first));
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  vector(const_iterator first, const_iterator last) {
+    size_type n = 0;
+    distance(first, last, n);
+    start = allocate_and_copy(n, first, last);
+    finish = start + n;
+    end_of_storage = finish;
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+  ~vector() { 
+    destroy(start, finish);
+    deallocate();
+  }
+  vector<T, Alloc>& operator=(const vector<T, Alloc>& x);
+  void reserve(size_type n) {
+    if (capacity() < n) {
+      const size_type old_size = size();
+      iterator tmp = allocate_and_copy(n, start, finish);
+      destroy(start, finish);
+      deallocate();
+      start = tmp;
+      finish = tmp + old_size;
+      end_of_storage = start + n;
+    }
+  }
+  reference front() { return *begin(); }
+  const_reference front() const { return *begin(); }
+  reference back() { return *(end() - 1); }
+  const_reference back() const { return *(end() - 1); }
+  void push_back(const T& x) {
+    if (finish != end_of_storage) {
+      construct(finish, x);
+      ++finish;
+    }
+    else
+      insert_aux(end(), x);
+  }
+  void swap(vector<T, Alloc>& x) {
+    __STD::swap(start, x.start);
+    __STD::swap(finish, x.finish);
+    __STD::swap(end_of_storage, x.end_of_storage);
+  }
+  iterator insert(iterator position, const T& x) {
+    size_type n = position - begin();
+    if (finish != end_of_storage && position == end()) {
+      construct(finish, x);
+      ++finish;
+    }
+    else
+      insert_aux(position, x);
+    return begin() + n;
+  }
+  iterator insert(iterator position) { return insert(position, T()); }
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void insert(iterator position, InputIterator first, InputIterator last) {
+    range_insert(position, first, last, iterator_category(first));
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  void insert(iterator position,
+              const_iterator first, const_iterator last);
+#endif /* __STL_MEMBER_TEMPLATES */
+
+  void insert (iterator pos, size_type n, const T& x);
+  void insert (iterator pos, int n, const T& x) {
+    insert(pos, (size_type) n, x);
+  }
+  void insert (iterator pos, long n, const T& x) {
+    insert(pos, (size_type) n, x);
+  }
+
+  void pop_back() {
+    --finish;
+    destroy(finish);
+  }
+  iterator erase(iterator position) {
+    if (position + 1 != end())
+      copy(position + 1, finish, position);
+    --finish;
+    destroy(finish);
+    return position;
+  }
+  iterator erase(iterator first, iterator last) {
+    iterator i = copy(last, finish, first);
+    destroy(i, finish);
+    finish = finish - (last - first);
+    return first;
+  }
+  void resize(size_type new_size, const T& x) {
+    if (new_size < size()) 
+      erase(begin() + new_size, end());
+    else
+      insert(end(), new_size - size(), x);
+  }
+  void resize(size_type new_size) { resize(new_size, T()); }
+  void clear() { erase(begin(), end()); }
+
+protected:
+  iterator allocate_and_fill(size_type n, const T& x) {
+    iterator result = data_allocator::allocate(n);
+    __STL_TRY {
+      uninitialized_fill_n(result, n, x);
+      return result;
+    }
+    __STL_UNWIND(data_allocator::deallocate(result, n));
+  }
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class ForwardIterator>
+  iterator allocate_and_copy(size_type n,
+                             ForwardIterator first, ForwardIterator last) {
+    iterator result = data_allocator::allocate(n);
+    __STL_TRY {
+      uninitialized_copy(first, last, result);
+      return result;
+    }
+    __STL_UNWIND(data_allocator::deallocate(result, n));
+  }
+#else /* __STL_MEMBER_TEMPLATES */
+  iterator allocate_and_copy(size_type n,
+                             const_iterator first, const_iterator last) {
+    iterator result = data_allocator::allocate(n);
+    __STL_TRY {
+      uninitialized_copy(first, last, result);
+      return result;
+    }
+    __STL_UNWIND(data_allocator::deallocate(result, n));
+  }
+#endif /* __STL_MEMBER_TEMPLATES */
+
+
+#ifdef __STL_MEMBER_TEMPLATES
+  template <class InputIterator>
+  void range_initialize(InputIterator first, InputIterator last,
+                        input_iterator_tag) {
+    for ( ; first != last; ++first)
+      push_back(*first);
+  }
+
+  // This function is only called by the constructor.  We have to worry
+  //  about resource leaks, but not about maintaining invariants.
+  template <class ForwardIterator>
+  void range_initialize(ForwardIterator first, ForwardIterator last,
+                        forward_iterator_tag) {
+    size_type n = 0;
+    distance(first, last, n);
+    start = allocate_and_copy(n, first, last);
+    finish = start + n;
+    end_of_storage = finish;
+  }
+
+  template <class InputIterator>
+  void range_insert(iterator pos,
+                    InputIterator first, InputIterator last,
+                    input_iterator_tag);
+
+  template <class ForwardIterator>
+  void range_insert(iterator pos,
+                    ForwardIterator first, ForwardIterator last,
+                    forward_iterator_tag);
+
+#endif /* __STL_MEMBER_TEMPLATES */
+};
+
+template <class T, class Alloc>
+inline bool operator==(const vector<T, Alloc>& x, const vector<T, Alloc>& y) {
+  return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
+}
+
+template <class T, class Alloc>
+inline bool operator<(const vector<T, Alloc>& x, const vector<T, Alloc>& y) {
+  return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
+
+template <class T, class Alloc>
+inline void swap(vector<T, Alloc>& x, vector<T, Alloc>& y) {
+  x.swap(y);
+}
+
+#endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
+
+template <class T, class Alloc>
+vector<T, Alloc>& vector<T, Alloc>::operator=(const vector<T, Alloc>& x) {
+  if (&x != this) {
+    if (x.size() > capacity()) {
+      iterator tmp = allocate_and_copy(x.end() - x.begin(),
+                                       x.begin(), x.end());
+      destroy(start, finish);
+      deallocate();
+      start = tmp;
+      end_of_storage = start + (x.end() - x.begin());
+    }
+    else if (size() >= x.size()) {
+      iterator i = copy(x.begin(), x.end(), begin());
+      destroy(i, finish);
+    }
+    else {
+      copy(x.begin(), x.begin() + size(), start);
+      uninitialized_copy(x.begin() + size(), x.end(), finish);
+    }
+    finish = start + x.size();
+  }
+  return *this;
+}
+
+template <class T, class Alloc>
+void vector<T, Alloc>::insert_aux(iterator position, const T& x) {
+  if (finish != end_of_storage) {
+    construct(finish, *(finish - 1));
+    ++finish;
+    T x_copy = x;
+    copy_backward(position, finish - 2, finish - 1);
+    *position = x_copy;
+  }
+  else {
+    const size_type old_size = size();
+    const size_type len = old_size != 0 ? 2 * old_size : 1;
+    iterator new_start = data_allocator::allocate(len);
+    iterator new_finish = new_start;
+    __STL_TRY {
+      new_finish = uninitialized_copy(start, position, new_start);
+      construct(new_finish, x);
+      ++new_finish;
+      new_finish = uninitialized_copy(position, finish, new_finish);
+    }
+
+#       ifdef  __STL_USE_EXCEPTIONS 
+    catch(...) {
+      destroy(new_start, new_finish); 
+      data_allocator::deallocate(new_start, len);
+      throw;
+    }
+#       endif /* __STL_USE_EXCEPTIONS */
+    destroy(begin(), end());
+    deallocate();
+    start = new_start;
+    finish = new_finish;
+    end_of_storage = new_start + len;
+  }
+}
+
+template <class T, class Alloc>
+void vector<T, Alloc>::insert(iterator position, size_type n, const T& x) {
+  if (n != 0) {
+    if (size_type(end_of_storage - finish) >= n) {
+      T x_copy = x;
+      const size_type elems_after = finish - position;
+      iterator old_finish = finish;
+      if (elems_after > n) {
+        uninitialized_copy(finish - n, finish, finish);
+        finish += n;
+        copy_backward(position, old_finish - n, old_finish);
+        fill(position, position + n, x_copy);
+      }
+      else {
+        uninitialized_fill_n(finish, n - elems_after, x_copy);
+        finish += n - elems_after;
+        uninitialized_copy(position, old_finish, finish);
+        finish += elems_after;
+        fill(position, old_finish, x_copy);
+      }
+    }
+    else {
+      const size_type old_size = size();        
+      const size_type len = old_size + max(old_size, n);
+      iterator new_start = data_allocator::allocate(len);
+      iterator new_finish = new_start;
+      __STL_TRY {
+        new_finish = uninitialized_copy(start, position, new_start);
+        new_finish = uninitialized_fill_n(new_finish, n, x);
+        new_finish = uninitialized_copy(position, finish, new_finish);
+      }
+#         ifdef  __STL_USE_EXCEPTIONS 
+      catch(...) {
+        destroy(new_start, new_finish);
+        data_allocator::deallocate(new_start, len);
+        throw;
+      }
+#         endif /* __STL_USE_EXCEPTIONS */
+      destroy(start, finish);
+      deallocate();
+      start = new_start;
+      finish = new_finish;
+      end_of_storage = new_start + len;
+    }
+  }
+}
+
+#ifdef __STL_MEMBER_TEMPLATES
+
+template <class T, class Alloc> template <class InputIterator>
+void vector<T, Alloc>::range_insert(iterator pos,
+                                    InputIterator first, InputIterator last,
+                                    input_iterator_tag) {
+  for ( ; first != last; ++first) {
+    pos = insert(pos, *first);
+    ++pos;
+  }
+}
+
+template <class T, class Alloc> template <class ForwardIterator>
+void vector<T, Alloc>::range_insert(iterator position,
+                                    ForwardIterator first,
+                                    ForwardIterator last,
+                                    forward_iterator_tag) {
+  if (first != last) {
+    size_type n = 0;
+    distance(first, last, n);
+    if (size_type(end_of_storage - finish) >= n) {
+      const size_type elems_after = finish - position;
+      iterator old_finish = finish;
+      if (elems_after > n) {
+        uninitialized_copy(finish - n, finish, finish);
+        finish += n;
+        copy_backward(position, old_finish - n, old_finish);
+        copy(first, last, position);
+      }
+      else {
+        ForwardIterator mid = first;
+        advance(mid, elems_after);
+        uninitialized_copy(mid, last, finish);
+        finish += n - elems_after;
+        uninitialized_copy(position, old_finish, finish);
+        finish += elems_after;
+        copy(first, mid, position);
+      }
+    }
+    else {
+      const size_type old_size = size();
+      const size_type len = old_size + max(old_size, n);
+      iterator new_start = data_allocator::allocate(len);
+      iterator new_finish = new_start;
+      __STL_TRY {
+        new_finish = uninitialized_copy(start, position, new_start);
+        new_finish = uninitialized_copy(first, last, new_finish);
+        new_finish = uninitialized_copy(position, finish, new_finish);
+      }
+#         ifdef __STL_USE_EXCEPTIONS
+      catch(...) {
+        destroy(new_start, new_finish);
+        data_allocator::deallocate(new_start, len);
+        throw;
+      }
+#         endif /* __STL_USE_EXCEPTIONS */
+      destroy(start, finish);
+      deallocate();
+      start = new_start;
+      finish = new_finish;
+      end_of_storage = new_start + len;
+    }
+  }
+}
+
+#else /* __STL_MEMBER_TEMPLATES */
+
+template <class T, class Alloc>
+void vector<T, Alloc>::insert(iterator position, 
+                              const_iterator first, 
+                              const_iterator last) {
+  if (first != last) {
+    size_type n = 0;
+    distance(first, last, n);
+    if (size_type(end_of_storage - finish) >= n) {
+      const size_type elems_after = finish - position;
+      iterator old_finish = finish;
+      if (elems_after > n) {
+        uninitialized_copy(finish - n, finish, finish);
+        finish += n;
+        copy_backward(position, old_finish - n, old_finish);
+        copy(first, last, position);
+      }
+      else {
+        uninitialized_copy(first + elems_after, last, finish);
+        finish += n - elems_after;
+        uninitialized_copy(position, old_finish, finish);
+        finish += elems_after;
+        copy(first, first + elems_after, position);
+      }
+    }
+    else {
+      const size_type old_size = size();
+      const size_type len = old_size + max(old_size, n);
+      iterator new_start = data_allocator::allocate(len);
+      iterator new_finish = new_start;
+      __STL_TRY {
+        new_finish = uninitialized_copy(start, position, new_start);
+        new_finish = uninitialized_copy(first, last, new_finish);
+        new_finish = uninitialized_copy(position, finish, new_finish);
+      }
+#         ifdef __STL_USE_EXCEPTIONS
+      catch(...) {
+        destroy(new_start, new_finish);
+        data_allocator::deallocate(new_start, len);
+        throw;
+      }
+#         endif /* __STL_USE_EXCEPTIONS */
+      destroy(start, finish);
+      deallocate();
+      start = new_start;
+      finish = new_finish;
+      end_of_storage = new_start + len;
+    }
+  }
+}
+
+#endif /* __STL_MEMBER_TEMPLATES */
+
+#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+#pragma reset woff 1174
+#endif
+
+__STL_END_NAMESPACE 
+
+#endif /* __SGI_STL_INTERNAL_VECTOR_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/strclass.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/strclass.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/strclass.h	(revision 18)
@@ -0,0 +1,6 @@
+/* Changed for emx by Eberhard Mattes -- Oct 1998 */
+#ifndef _strclass_h
+#define _strclass_h
+#include <Strng.h>
+typedef class String string;
+#endif
Index: trunk/src/emx/include/Attic/cpp/stream.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/stream.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/stream.h	(revision 18)
@@ -0,0 +1,59 @@
+/* 
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#ifndef _COMPAT_STREAM_H
+#define _COMPAT_STREAM_H
+
+// Compatibility with old library.
+// DO NOT USE THESE FUNCTIONS IN NEW CODE!
+// They are obsolete, non-standard, and non-reentrant.
+
+#define _STREAM_COMPAT
+#include <iostream.h>
+
+extern "C++" {
+extern char* form(const char*, ...);
+
+extern char* dec(long, int=0);
+extern char* dec(int, int=0);
+extern char* dec(unsigned long, int=0);
+extern char* dec(unsigned int, int=0);
+
+extern char* hex(long, int=0);
+extern char* hex(int, int=0);
+extern char* hex(unsigned long, int=0);
+extern char* hex(unsigned int, int=0);
+
+extern char* oct(long, int=0);
+extern char* oct(int, int=0);
+extern char* oct(unsigned long, int=0);
+extern char* oct(unsigned int, int=0);
+
+char*        chr(char ch, int width = 0);
+char*        str(const char* s, int width = 0);
+
+inline istream& WS(istream& str) { return ws(str); }
+} // extern "C++"
+
+#endif /* !_COMPAT_STREAM_H */
Index: trunk/src/emx/include/Attic/cpp/streambu.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/streambu.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/streambu.h	(revision 18)
@@ -0,0 +1,488 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993, 1998 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#ifndef _STREAMBUF_H
+#define _STREAMBUF_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+/* #define _G_IO_THROW */ /* Not implemented:  ios::failure */
+
+#define _IO_NEW_STREAMS // new optimizated stream representation
+
+extern "C" {
+#include <libio.h>
+}
+//#include <_G_config.h>
+#ifdef _G_NEED_STDARG_H
+#include <stdarg.h>
+#endif
+#ifndef _IO_va_list
+#define _IO_va_list char *
+#endif
+
+#ifndef EOF
+#define EOF (-1)
+#endif
+#ifndef NULL
+#ifdef __GNUG__
+#define NULL (__null)
+#else
+#define NULL (0)
+#endif
+#endif
+
+#ifndef _IO_wchar_t
+#if _G_IO_IO_FILE_VERSION == 0x20001
+#define _IO_wchar_t _G_wchar_t
+#else
+#define _IO_wchar_t short
+#endif
+#endif
+
+extern "C++" {
+class istream; /* Work-around for a g++ name mangling bug. Fixed in 2.6. */
+class ostream; class streambuf;
+
+// In case some header files defines these as macros.
+#undef open
+#undef close
+
+#if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001
+typedef _IO_off64_t streamoff;
+typedef _IO_fpos64_t streampos;
+#else
+typedef _IO_off_t streamoff;
+typedef _IO_fpos_t streampos;
+#endif
+typedef _IO_ssize_t streamsize;
+
+typedef unsigned long __fmtflags;
+typedef unsigned char __iostate;
+
+struct _ios_fields
+{ // The data members of an ios.
+    streambuf *_strbuf;
+    ostream* _tie;
+    int _width;
+    __fmtflags _flags;
+    _IO_wchar_t _fill;
+    __iostate _state;
+    __iostate _exceptions;
+    int _precision;
+
+    void *_arrays; /* Support for ios::iword and ios::pword. */
+};
+
+#define _IOS_GOOD	0
+#define _IOS_EOF	1
+#define _IOS_FAIL	2
+#define _IOS_BAD	4
+
+#define _IO_INPUT	1
+#define _IO_OUTPUT	2
+#define _IO_ATEND	4
+#define _IO_APPEND	8
+#define _IO_TRUNC	16
+#define _IO_NOCREATE	32
+#define _IO_NOREPLACE	64
+#define _IO_BIN		128
+
+#ifdef _STREAM_COMPAT
+enum state_value {
+    _good = _IOS_GOOD,
+    _eof = _IOS_EOF,
+    _fail = _IOS_FAIL,
+    _bad = _IOS_BAD };
+enum open_mode {
+    input = _IO_INPUT,
+    output = _IO_OUTPUT,
+    atend = _IO_ATEND,
+    append = _IO_APPEND };
+#endif
+
+class ios : public _ios_fields {
+  ios& operator=(ios&);  /* Not allowed! */
+  ios (const ios&); /* Not allowed! */
+  public:
+    typedef __fmtflags fmtflags;
+    typedef int iostate;
+    typedef int openmode;
+    typedef int streamsize;
+    enum io_state {
+	goodbit = _IOS_GOOD,
+	eofbit = _IOS_EOF,
+	failbit = _IOS_FAIL,
+	badbit = _IOS_BAD };
+    enum open_mode {
+	in = _IO_INPUT,
+	out = _IO_OUTPUT,
+	ate = _IO_ATEND,
+	app = _IO_APPEND,
+	trunc = _IO_TRUNC,
+	nocreate = _IO_NOCREATE,
+	noreplace = _IO_NOREPLACE,
+	bin = _IOS_BIN, // Deprecated - ANSI uses ios::binary.
+	binary = _IOS_BIN };
+    enum seek_dir { beg, cur, end};
+    typedef enum seek_dir seekdir;
+    // NOTE: If adding flags here, before to update ios::bitalloc().
+    enum { skipws=_IO_SKIPWS,
+	   left=_IO_LEFT, right=_IO_RIGHT, internal=_IO_INTERNAL,
+	   dec=_IO_DEC, oct=_IO_OCT, hex=_IO_HEX,
+	   showbase=_IO_SHOWBASE, showpoint=_IO_SHOWPOINT,
+	   uppercase=_IO_UPPERCASE, showpos=_IO_SHOWPOS,
+	   scientific=_IO_SCIENTIFIC, fixed=_IO_FIXED,
+	   unitbuf=_IO_UNITBUF, stdio=_IO_STDIO
+#ifndef _IO_NEW_STREAMS
+	   , dont_close=_IO_DONT_CLOSE // Don't delete streambuf on stream destruction
+#endif
+	   };
+    enum { // Masks.
+	basefield=dec+oct+hex,
+	floatfield = scientific+fixed,
+	adjustfield = left+right+internal
+    };
+
+#ifdef _IO_THROW
+    class failure : public xmsg {
+	ios* _stream;
+      public:
+	failure(ios* stream) { _stream = stream; }
+	failure(string cause, ios* stream) { _stream = stream; }
+	ios* rdios() const { return _stream; }
+    };
+#endif
+
+    ostream* tie() const { return _tie; }
+    ostream* tie(ostream* val) { ostream* save=_tie; _tie=val; return save; }
+
+    // Methods to change the format state.
+    _IO_wchar_t fill() const { return _fill; }
+    _IO_wchar_t fill(_IO_wchar_t newf)
+	{_IO_wchar_t oldf = _fill; _fill = newf; return oldf;}
+    fmtflags flags() const { return _flags; }
+    fmtflags flags(fmtflags new_val) {
+	fmtflags old_val = _flags; _flags = new_val; return old_val; }
+    int precision() const { return _precision; }
+    int precision(int newp) {
+	unsigned short oldp = _precision; _precision = (unsigned short)newp;
+	return oldp; }
+    fmtflags setf(fmtflags val) {
+	fmtflags oldbits = _flags;
+	_flags |= val; return oldbits; }
+    fmtflags setf(fmtflags val, fmtflags mask) {
+	fmtflags oldbits = _flags;
+	_flags = (_flags & ~mask) | (val & mask); return oldbits; }
+    fmtflags unsetf(fmtflags mask) {
+	fmtflags oldbits = _flags;
+	_flags &= ~mask; return oldbits; }
+    int width() const { return _width; }
+    int width(int val) { int save = _width; _width = val; return save; }
+
+#ifdef _IO_THROW
+    void _throw_failure() const { throw new ios::failure(this); }
+#else
+    void _throw_failure() const { }
+#endif
+    void clear(iostate state = 0) {
+	_state = _strbuf ? state : state|badbit;
+	if (_state & _exceptions) _throw_failure(); }
+    void set(iostate flag) { _state |= flag;
+	if (_state & _exceptions) _throw_failure(); }
+    void setstate(iostate flag) { _state |= flag; // ANSI
+	if (_state & _exceptions) _throw_failure(); }
+    int good() const { return _state == 0; }
+    int eof() const { return _state & ios::eofbit; }
+    int fail() const { return _state & (ios::badbit|ios::failbit); }
+    int bad() const { return _state & ios::badbit; }
+    iostate rdstate() const { return _state; }
+    operator void*() const { return fail() ? (void*)0 : (void*)(-1); }
+    int operator!() const { return fail(); }
+    iostate exceptions() const { return _exceptions; }
+    void exceptions(iostate enable) {
+	_exceptions = enable;
+	if (_state & _exceptions) _throw_failure(); }
+
+    streambuf* rdbuf() const { return _strbuf; }
+    streambuf* rdbuf(streambuf *_s) {
+      streambuf *_old = _strbuf; _strbuf = _s; clear (); return _old; }
+
+    static int sync_with_stdio(int on);
+    static void sync_with_stdio() { sync_with_stdio(1); }
+    static fmtflags bitalloc();
+    static int xalloc();
+    void*& pword(int);
+    void* pword(int) const;
+    long& iword(int);
+    long iword(int) const;
+
+#ifdef _STREAM_COMPAT
+    void unset(state_value flag) { _state &= ~flag; }
+    void close();
+    int is_open();
+    int readable();
+    int writable();
+#endif
+
+    // Used to initialize standard streams. Not needed in this implementation.
+    class Init {
+    public:
+      Init () { }
+    };
+
+  protected:
+    inline ios(streambuf* sb = 0, ostream* tie_to = 0);
+    inline virtual ~ios();
+    inline void init(streambuf* sb, ostream* tie = 0);
+};
+
+#if __GNUG__==1
+typedef int _seek_dir;
+#else
+typedef ios::seek_dir _seek_dir;
+#endif
+
+// Magic numbers and bits for the _flags field.
+// The magic numbers use the high-order bits of _flags;
+// the remaining bits are abailable for variable flags.
+// Note: The magic numbers must all be negative if stdio
+// emulation is desired.
+
+// A streammarker remembers a position in a buffer.
+// You are guaranteed to be able to seek back to it if it is saving().
+class streammarker : private _IO_marker {
+    friend class streambuf;
+    void set_offset(int offset) { _pos = offset; }
+  public:
+    streammarker(streambuf *sb);
+    ~streammarker();
+    int saving() { return  1; }
+    int delta(streammarker&);
+    int delta();
+};
+
+struct streambuf : public _IO_FILE { // protected??
+    friend class ios;
+    friend class istream;
+    friend class ostream;
+    friend class streammarker;
+    const void *&_vtable() { return *(const void**)((_IO_FILE*)this + 1); }
+  protected:
+    static streambuf* _list_all; /* List of open streambufs. */
+    _IO_FILE*& xchain() { return _chain; }
+    void _un_link();
+    void _link_in();
+    char* gptr() const
+      { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_ptr; }
+    char* pptr() const { return _IO_write_ptr; }
+    char* egptr() const
+      { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_end : _IO_read_end; }
+    char* epptr() const { return _IO_write_end; }
+    char* pbase() const { return _IO_write_base; }
+    char* eback() const
+      { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_base;}
+    char* base() const { return _IO_buf_base; }
+    char* ebuf() const { return _IO_buf_end; }
+    int blen() const { return _IO_buf_end - _IO_buf_base; }
+    void xput_char(char c) { *_IO_write_ptr++ = c; }
+    int xflags() { return _IO_file_flags; }
+    int xflags(int f) {int fl = _IO_file_flags; _IO_file_flags = f; return fl;}
+    void xsetflags(int f) { _IO_file_flags |= f; }
+    void xsetflags(int f, int mask)
+      { _IO_file_flags = (_IO_file_flags & ~mask) | (f & mask); }
+    void gbump(int n)
+      { _IO_file_flags & _IO_IN_BACKUP ? (_IO_save_base+=n):(_IO_read_ptr+=n);}
+    void pbump(int n) { _IO_write_ptr += n; }
+    void setb(char* b, char* eb, int a=0);
+    void setp(char* p, char* ep)
+      { _IO_write_base=_IO_write_ptr=p; _IO_write_end=ep; }
+    void setg(char* eb, char* g, char *eg) {
+      if (_IO_file_flags & _IO_IN_BACKUP) _IO_free_backup_area(this); 
+      _IO_read_base = eb; _IO_read_ptr = g; _IO_read_end = eg; }
+    char *shortbuf() { return _shortbuf; }
+
+    int in_backup() { return _flags & _IO_IN_BACKUP; }
+    // The start of the main get area:  FIXME:  wrong for write-mode filebuf?
+    char *Gbase() { return in_backup() ? _IO_save_base : _IO_read_base; }
+    // The end of the main get area:
+    char *eGptr() { return in_backup() ? _IO_save_end : _IO_read_end; }
+    // The start of the backup area:
+    char *Bbase() { return in_backup() ? _IO_read_base : _IO_save_base; }
+    char *Bptr() { return _IO_backup_base; }
+    // The end of the backup area:
+    char *eBptr() { return in_backup() ? _IO_read_end : _IO_save_end; }
+    char *Nbase() { return _IO_save_base; }
+    char *eNptr() { return _IO_save_end; }
+    int have_backup() { return _IO_save_base != NULL; }
+    int have_markers() { return _markers != NULL; }
+    void free_backup_area();
+    void unsave_markers(); // Make all streammarkers !saving().
+    int put_mode() { return _flags & _IO_CURRENTLY_PUTTING; }
+    int switch_to_get_mode();
+    
+    streambuf(int flags=0);
+  public:
+    static int flush_all();
+    static void flush_all_linebuffered(); // Flush all line buffered files.
+    virtual ~streambuf();
+    virtual int overflow(int c = EOF); // Leave public for now
+    virtual int underflow(); // Leave public for now
+    virtual int uflow(); // Leave public for now
+    virtual int pbackfail(int c);
+//    virtual int showmany ();
+    virtual streamsize xsputn(const char* s, streamsize n);
+    virtual streamsize xsgetn(char* s, streamsize n);
+    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
+    virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out);
+
+    streampos pubseekoff(streamoff o, _seek_dir d, int mode=ios::in|ios::out)
+      { return _IO_seekoff (this, o, d, mode); }
+    streampos pubseekpos(streampos pos, int mode = ios::in|ios::out)
+      { return _IO_seekpos (this, pos, mode); }
+    streampos sseekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
+    streampos sseekpos(streampos pos, int mode = ios::in|ios::out);
+    virtual streambuf* setbuf(char* p, int len);
+    virtual int sync();
+    virtual int doallocate();
+
+    int seekmark(streammarker& mark, int delta = 0);
+    int sputbackc(char c);
+    int sungetc();
+    int unbuffered() { return _flags & _IO_UNBUFFERED ? 1 : 0; }
+    int linebuffered() { return _flags & _IO_LINE_BUF ? 1 : 0; }
+    void unbuffered(int i)
+	{ if (i) _flags |= _IO_UNBUFFERED; else _flags &= ~_IO_UNBUFFERED; }
+    void linebuffered(int i)
+	{ if (i) _flags |= _IO_LINE_BUF; else _flags &= ~_IO_LINE_BUF; }
+    int allocate() { // For AT&T compatibility
+	if (base() || unbuffered()) return 0;
+	else return doallocate(); }
+    // Allocate a buffer if needed; use _shortbuf if appropriate.
+    void allocbuf() { if (base() == NULL) doallocbuf(); }
+    void doallocbuf();
+    int in_avail() { return _IO_read_end - _IO_read_ptr; }
+    int out_waiting() { return _IO_write_ptr - _IO_write_base; }
+    streamsize sputn(const char* s, streamsize n) { return xsputn(s, n); }
+    streamsize padn(char pad, streamsize n) { return _IO_padn(this, pad, n); }
+    streamsize sgetn(char* s, streamsize n) { return _IO_sgetn(this, s, n); }
+    int ignore(int);
+    int get_column();
+    int set_column(int);
+    long sgetline(char* buf, _IO_size_t n, char delim, int putback_delim);
+    int sputc(int c) { return _IO_putc(c, this); }
+    int sbumpc() { return _IO_getc(this); }
+    int sgetc() { return _IO_peekc(this); }
+    int snextc() {
+	if (_IO_read_ptr >= _IO_read_end && __underflow(this) == EOF)
+	  return EOF;
+	else return _IO_read_ptr++, sgetc(); }
+    void stossc() { if (_IO_read_ptr < _IO_read_end) _IO_read_ptr++; }
+    int vscan(char const *fmt0, _IO_va_list ap, ios* stream = NULL);
+    int scan(char const *fmt0 ...);
+    int vform(char const *fmt0, _IO_va_list ap);
+    int form(char const *fmt0 ...);
+#if 0 /* Work in progress */
+    int column();  // Current column number (of put pointer). -1 is unknown.
+    void column(int c);  // Set column number of put pointer to c.
+#endif
+    virtual streamsize sys_read(char* buf, streamsize size);
+    virtual streamsize sys_write(const char*, streamsize);
+    virtual streampos sys_seek(streamoff, _seek_dir);
+    virtual int sys_close();
+    virtual int sys_stat(void*); // Actually, a (struct stat*)
+#if _G_IO_IO_FILE_VERSION == 0x20001
+    virtual int showmanyc();
+    virtual void imbue(void *);
+#endif
+};
+
+// A backupbuf is a streambuf with full backup and savepoints on reading.
+// All standard streambufs in the GNU iostream library are backupbufs.
+
+class filebuf : public streambuf {
+  protected:
+    void init();
+  public:
+    static const int openprot; // Non-ANSI AT&T-ism:  Default open protection.
+    filebuf();
+    filebuf(int fd);
+    filebuf(int fd, char* p, int len);
+#if !_IO_UNIFIED_JUMPTABLES
+    static filebuf *__new();
+#endif
+    ~filebuf();
+    filebuf* attach(int fd);
+    filebuf* open(const char *filename, const char *mode);
+    filebuf* open(const char *filename, ios::openmode mode, int prot = 0664);
+    virtual int underflow();
+    virtual int overflow(int c = EOF);
+    int is_open() const { return _fileno >= 0; }
+    int fd() const { return is_open() ? _fileno : EOF; }
+    filebuf* close();
+    virtual int doallocate();
+    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
+    virtual streambuf* setbuf(char* p, int len);
+    streamsize xsputn(const char* s, streamsize n);
+    streamsize xsgetn(char* s, streamsize n);
+    virtual int sync();
+  protected: // See documentation in filebuf.C.
+//    virtual int pbackfail(int c);
+    int is_reading() { return eback() != egptr(); }
+    char* cur_ptr() { return is_reading() ?  gptr() : pptr(); }
+    /* System's idea of pointer */
+    char* file_ptr() { return eGptr(); }
+    // Low-level operations (Usually invoke system calls.)
+    virtual streamsize sys_read(char* buf, streamsize size);
+    virtual streampos sys_seek(streamoff, _seek_dir);
+    virtual streamsize sys_write(const char*, streamsize);
+    virtual int sys_stat(void*); // Actually, a (struct stat*)
+    virtual int sys_close();
+#if 0
+    virtual uflow;
+    virtual showmany;
+#endif
+};
+
+inline void ios::init(streambuf* sb, ostream* tie_to) {
+		_state = sb ? ios::goodbit : ios::badbit; _exceptions=0;
+		_strbuf=sb; _tie = tie_to; _width=0; _fill=' ';
+#ifdef _IO_NEW_STREAMS
+		_flags=ios::skipws|ios::dec;
+#else
+		_flags=ios::skipws|ios::dec|ios::dont_close;
+#endif
+		_precision=6; _arrays = 0; }
+
+inline ios::ios(streambuf* sb, ostream* tie_to) { init(sb, tie_to); }
+
+inline ios::~ios() {
+#ifndef _IO_NEW_STREAMS
+    if (!(_flags & (unsigned int)ios::dont_close)) delete rdbuf();
+#endif
+    if (_arrays) delete [] _arrays;
+}
+} // extern "C++"
+#endif /* _STREAMBUF_H */
Index: trunk/src/emx/include/Attic/cpp/strfile.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/strfile.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/strfile.h	(revision 18)
@@ -0,0 +1,63 @@
+/* Copyright (C) 1993, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include <libio.h>
+#ifdef TODO
+Merge into  libio.h ?
+#endif
+
+typedef void *(*_IO_alloc_type) __P ((_IO_size_t));
+typedef void (*_IO_free_type) __P ((void*));
+
+struct _IO_str_fields
+{
+  _IO_alloc_type _allocate_buffer;
+  _IO_free_type _free_buffer;
+};
+
+/* This is needed for the Irix6 N32 ABI, which has a 64 bit off_t type,
+   but a 32 bit pointer type.  In this case, we get 4 bytes of padding
+   after the vtable pointer.  Putting them in a structure together solves
+   this problem.  */
+
+struct _IO_streambuf
+{
+  struct _IO_FILE _f;
+  const void *_vtable;
+};
+
+typedef struct _IO_strfile_
+{
+  struct _IO_streambuf _sbf;
+  struct _IO_str_fields _s;
+} _IO_strfile;
+
+/* dynamic: set when the array object is allocated (or reallocated)  as
+   necessary to hold a character sequence that can change in length. */
+#define _IO_STR_DYNAMIC(FP) ((FP)->_s._allocate_buffer != (_IO_alloc_type)0)
+
+/* frozen: set when the program has requested that the array object not
+   be altered, reallocated, or freed. */
+#define _IO_STR_FROZEN(FP) ((FP)->_f._IO_file_flags & _IO_USER_BUF)
Index: trunk/src/emx/include/Attic/cpp/string
===================================================================
--- trunk/src/emx/include/Attic/cpp/string	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/string	(revision 18)
@@ -0,0 +1,13 @@
+// Main header for the -*- C++ -*- string classes.
+
+#ifndef __STRING__
+#define __STRING__
+
+#include <std/bastring.h>
+
+extern "C++" {
+typedef basic_string <char> string;
+// typedef basic_string <wchar_t> wstring;
+} // extern "C++"
+
+#endif
Index: trunk/src/emx/include/Attic/cpp/strstrea
===================================================================
--- trunk/src/emx/include/Attic/cpp/strstrea	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/strstrea	(revision 18)
@@ -0,0 +1,7 @@
+// -*- C++ -*- forwarding header.
+// This file is part of the GNU ANSI C++ Library.
+
+#ifndef __STRSTREAM__
+#define __STRSTREAM__
+#include <strstrea.h>
+#endif
Index: trunk/src/emx/include/Attic/cpp/strstrea.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/strstrea.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/strstrea.h	(revision 18)
@@ -0,0 +1,113 @@
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 1993 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/* Written by Per Bothner (bothner@cygnus.com). */
+
+#ifndef __STRSTREAM_H
+#define __STRSTREAM_H
+#ifdef __GNUG__
+#pragma interface
+#endif
+#include <iostream.h>
+#include <strfile.h>
+
+extern "C++" {
+class strstreambuf : public streambuf
+{
+  struct _IO_str_fields _s;
+  friend class istrstream;
+
+    void init_dynamic(_IO_alloc_type alloc, _IO_free_type free,
+		      int initial_size = 0);
+    void init_static(char *ptr, int size, char *pstart);
+    void init_readonly(const char *ptr, int size);
+  protected:
+    virtual int overflow(int = EOF);
+    virtual int underflow();
+    virtual int pbackfail(int c);
+  public:
+    virtual ~strstreambuf();
+    strstreambuf() { init_dynamic(0, 0); }
+    strstreambuf(int initial_size) { init_dynamic(0, 0, initial_size); }
+    strstreambuf(void *(*alloc)(_IO_size_t), void (*free)(void*))
+	{ init_dynamic(alloc, free); }
+    strstreambuf(char *ptr, int size, char *pstart = NULL)
+	{ init_static(ptr, size, pstart); }
+    strstreambuf(unsigned char *ptr, int size, unsigned char *pstart = NULL)
+	{ init_static((char*)ptr, size, (char*)pstart); }
+    strstreambuf(const char *ptr, int size)
+	{ init_readonly(ptr, size); }
+    strstreambuf(const unsigned char *ptr, int size)
+	{ init_readonly((const char*)ptr, size); }
+    strstreambuf(signed char *ptr, int size, signed char *pstart = NULL)
+	{ init_static((char*)ptr, size, (char*)pstart); }
+    strstreambuf(const signed char *ptr, int size)
+	{ init_readonly((const char*)ptr, size); }
+    // Note: frozen() is always true if !_IO_STR_DYNAMIC(this).
+    int frozen() { return _flags & _IO_USER_BUF ? 1 : 0; }
+    void freeze(int n=1)
+	{ if (_IO_STR_DYNAMIC(this))
+	    { if (n) _flags |= _IO_USER_BUF; else _flags &= ~_IO_USER_BUF; } }
+    _IO_ssize_t pcount();
+    char *str();
+    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
+};
+
+class strstreambase : virtual public ios {
+  protected:
+    strstreambuf __my_sb;
+  public:
+    strstreambuf* rdbuf() { return &__my_sb; }
+  protected:
+    strstreambase() { init (&__my_sb); }
+    strstreambase(char *cp, int n, int mode=ios::out);
+};
+
+class istrstream : public strstreambase, public istream {
+  public:
+    istrstream(const char*, int=0);
+};
+
+class ostrstream : public strstreambase, public ostream {
+  public:
+    ostrstream() { }
+    ostrstream(char *cp, int n, int mode=ios::out) :strstreambase(cp,n,mode){}
+    _IO_ssize_t pcount() { return ((strstreambuf*)_strbuf)->pcount(); }
+    char *str() { return ((strstreambuf*)_strbuf)->str(); }
+    void freeze(int n = 1) { ((strstreambuf*)_strbuf)->freeze(n); }
+    int frozen() { return ((strstreambuf*)_strbuf)->frozen(); }
+};
+
+class strstream : public strstreambase, public iostream {
+  public:
+  strstream() { }
+    strstream(char *cp, int n, int mode=ios::out) :strstreambase(cp,n,mode){}
+    _IO_ssize_t pcount() { return ((strstreambuf*)_strbuf)->pcount(); }
+    char *str() { return ((strstreambuf*)_strbuf)->str(); }
+    void freeze(int n = 1) { ((strstreambuf*)_strbuf)->freeze(n); }
+    int frozen() { return ((strstreambuf*)_strbuf)->frozen(); }
+};
+} // extern "C++"
+
+#endif /*!__STRSTREAM_H*/
Index: trunk/src/emx/include/Attic/cpp/swap.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/swap.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/swap.h	(revision 18)
@@ -0,0 +1,3 @@
+/* From Ron Guillmette; apparently needed for Hansen's code */
+
+#define swap(a,b) ({ typeof(a) temp = (a); (a) = (b); (b) = temp; })
Index: trunk/src/emx/include/Attic/cpp/sysent.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/sysent.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/sysent.h	(revision 18)
@@ -0,0 +1,2 @@
+/* Provided for compatibity with other C++ compilers ONLY! */
+#include <std.h>
Index: trunk/src/emx/include/Attic/cpp/tempbuf.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/tempbuf.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/tempbuf.h	(revision 18)
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_TEMPBUF_H
+#define __SGI_STL_TEMPBUF_H
+
+#ifndef __SGI_STL_PAIR_H
+#include <pair.h>
+#endif
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#ifndef __TYPE_TRAITS_H
+#include <type_tra.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_CONSTRUCT_H
+#include <stl_cons.h>
+#endif
+#ifndef __SGI_STL_INTERNAL_TEMPBUF_H
+#include <stl_temp.h>
+#endif
+
+#ifdef __STL_USE_NAMESPACES
+
+using __STD::get_temporary_buffer;
+using __STD::return_temporary_buffer;
+using __STD::temporary_buffer;
+
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_TEMPBUF_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/tree.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/tree.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/tree.h	(revision 18)
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ */
+
+#ifndef __SGI_STL_TREE_H
+#define __SGI_STL_TREE_H
+
+#ifndef __SGI_STL_INTERNAL_TREE_H
+#include <stl_tree.h>
+#endif
+#include <algobase.h>
+#include <alloc.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::rb_tree;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_TREE_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/type_tra.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/type_tra.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/type_tra.h	(revision 18)
@@ -0,0 +1,233 @@
+/*
+ *
+ * Copyright (c) 1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __TYPE_TRAITS_H
+#define __TYPE_TRAITS_H
+
+#ifndef __STL_CONFIG_H
+#include <stl_conf.h>
+#endif
+
+/*
+This header file provides a framework for allowing compile time dispatch
+based on type attributes. This is useful when writing template code.
+For example, when making a copy of an array of an unknown type, it helps
+to know if the type has a trivial copy constructor or not, to help decide
+if a memcpy can be used.
+
+The class template __type_traits provides a series of typedefs each of
+which is either __true_type or __false_type. The argument to
+__type_traits can be any type. The typedefs within this template will
+attain their correct values by one of these means:
+    1. The general instantiation contain conservative values which work
+       for all types.
+    2. Specializations may be declared to make distinctions between types.
+    3. Some compilers (such as the Silicon Graphics N32 and N64 compilers)
+       will automatically provide the appropriate specializations for all
+       types.
+
+EXAMPLE:
+
+//Copy an array of elements which have non-trivial copy constructors
+template <class T> void copy(T* source,T* destination,int n,__false_type);
+//Copy an array of elements which have trivial copy constructors. Use memcpy.
+template <class T> void copy(T* source,T* destination,int n,__true_type);
+
+//Copy an array of any type by using the most efficient copy mechanism
+template <class T> inline void copy(T* source,T* destination,int n) {
+   copy(source,destination,n,__type_traits<T>::has_trivial_copy_constructor());
+}
+*/
+
+
+struct __true_type {
+};
+
+struct __false_type {
+};
+
+template <class type>
+struct __type_traits { 
+   typedef __true_type     this_dummy_member_must_be_first;
+                   /* Do not remove this member. It informs a compiler which
+                      automatically specializes __type_traits that this
+                      __type_traits template is special. It just makes sure that
+                      things work if an implementation is using a template
+                      called __type_traits for something unrelated. */
+
+   /* The following restrictions should be observed for the sake of
+      compilers which automatically produce type specific specializations 
+      of this class:
+          - You may reorder the members below if you wish
+          - You may remove any of the members below if you wish
+          - You must not rename members without making the corresponding
+            name change in the compiler
+          - Members you add will be treated like regular members unless
+            you add the appropriate support in the compiler. */
+ 
+
+   typedef __false_type    has_trivial_default_constructor;
+   typedef __false_type    has_trivial_copy_constructor;
+   typedef __false_type    has_trivial_assignment_operator;
+   typedef __false_type    has_trivial_destructor;
+   typedef __false_type    is_POD_type;
+};
+
+
+
+// Provide some specializations.  This is harmless for compilers that
+//  have built-in __types_traits support, and essential for compilers
+//  that don't.
+
+__STL_TEMPLATE_NULL struct __type_traits<char> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<signed char> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<unsigned char> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<short> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<unsigned short> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<int> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<unsigned int> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<long> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<unsigned long> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<float> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<double> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+__STL_TEMPLATE_NULL struct __type_traits<long double> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
+
+template <class T>
+struct __type_traits<T*> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+struct __type_traits<char*> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+struct __type_traits<signed char*> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+struct __type_traits<unsigned char*> {
+   typedef __true_type    has_trivial_default_constructor;
+   typedef __true_type    has_trivial_copy_constructor;
+   typedef __true_type    has_trivial_assignment_operator;
+   typedef __true_type    has_trivial_destructor;
+   typedef __true_type    is_POD_type;
+};
+
+#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
+
+
+#endif /* __TYPE_TRAITS_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/typeinfo
===================================================================
--- trunk/src/emx/include/Attic/cpp/typeinfo	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/typeinfo	(revision 18)
@@ -0,0 +1,71 @@
+// RTTI support for -*- C++ -*-
+// Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+#ifndef __TYPEINFO__
+#define __TYPEINFO__
+
+#include <exceptio>
+
+extern "C++" {
+
+#if 0
+namespace std {
+#endif
+
+class type_info {
+private:
+  // assigning type_info is not supported.  made private.
+  type_info& operator= (const type_info&);
+  type_info (const type_info&);
+
+protected:
+  type_info (const char *n): _name (n) { }
+
+  const char *_name;
+
+public:
+  // destructor
+  virtual ~type_info ();
+    
+  bool before (const type_info& arg) const;
+  const char* name () const
+    { return _name; }
+  bool operator== (const type_info& arg) const;
+  bool operator!= (const type_info& arg) const;
+};
+
+// We can't rely on common symbols being shared between translation units
+// under Windows.  Sigh.
+
+#ifndef _WIN32
+inline bool type_info::
+operator== (const type_info& arg) const
+{
+  return &arg == this;
+}
+
+inline bool type_info::
+operator!= (const type_info& arg) const
+{
+  return &arg != this;
+}
+#endif
+
+class bad_cast : public exception {
+public:
+  bad_cast() { }
+  virtual ~bad_cast() { }
+};
+
+class bad_typeid : public exception {
+ public:
+  bad_typeid () { }
+  virtual ~bad_typeid () { }
+};
+
+#if 0
+} // namespace std
+#endif
+
+} // extern "C++"
+#endif
Index: trunk/src/emx/include/Attic/cpp/typemacr.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/typemacr.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/typemacr.h	(revision 18)
@@ -0,0 +1,8 @@
+#define _T(type) typeof(type)
+#define pointer_to(type) _T(_T(type)*)
+#define member_of(cls,type) _T(_T(type) cls::)
+#define function(res, args) _T(_T(res) args)
+
+#define _xq_yq(x,y) x ## _ ## y
+#define _x_y(x,y) _xq_yq(x,y) 
+#define _gensym(stem) _x_y(stem, __LINE__)
Index: trunk/src/emx/include/Attic/cpp/utility
===================================================================
--- trunk/src/emx/include/Attic/cpp/utility	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/utility	(revision 18)
@@ -0,0 +1,38 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_UTILITY
+#define __SGI_STL_UTILITY
+
+#include <stl_conf.h>
+#include <stl_relo.h>
+#include <stl_pair.h>
+
+#endif /* __SGI_STL_UTILITY */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/vector
===================================================================
--- trunk/src/emx/include/Attic/cpp/vector	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/vector	(revision 18)
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_VECTOR
+#define __SGI_STL_VECTOR
+
+#include <stl_algb.h>
+#include <stl_allo.h>
+#include <stl_cons.h>
+#include <stl_unin.h>
+#include <stl_vect.h>
+#include <stl_bvec.h>
+
+#endif /* __SGI_STL_VECTOR */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/Attic/cpp/vector.h
===================================================================
--- trunk/src/emx/include/Attic/cpp/vector.h	(revision 18)
+++ trunk/src/emx/include/Attic/cpp/vector.h	(revision 18)
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __SGI_STL_VECTOR_H
+#define __SGI_STL_VECTOR_H
+
+#include <algobase.h>
+#include <alloc.h>
+#include <stl_vect.h>
+
+#ifdef __STL_USE_NAMESPACES
+using __STD::vector;
+#endif /* __STL_USE_NAMESPACES */
+
+#endif /* __SGI_STL_VECTOR_H */
+
+// Local Variables:
+// mode:C++
+// End:
Index: trunk/src/emx/include/a_out.h
===================================================================
--- trunk/src/emx/include/a_out.h	(revision 18)
+++ trunk/src/emx/include/a_out.h	(revision 18)
@@ -0,0 +1,166 @@
+/* a_out.h -- changed for emx by Eberhard Mattes -- Sep 1998 */
+
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+#define __GNU_EXEC_MACROS__
+#ifndef __STRUCT_EXEC_OVERRIDE__
+struct exec
+{
+  unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
+  unsigned a_text;		/* length of text, in bytes */
+  unsigned a_data;		/* length of data, in bytes */
+  unsigned a_bss;		/* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;		/* length of symbol table data in file, in bytes */
+  unsigned a_entry;		/* start address */
+  unsigned a_trsize;		/* length of relocation info for text, in bytes */
+  unsigned a_drsize;		/* length of relocation info for data, in bytes */
+};
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+/* these go in the N_MACHTYPE field */
+enum machine_type {
+  M_OLDSUN2 = 0,
+  M_68010 = 1,
+  M_68020 = 2,
+  M_SPARC = 3,
+  /* skip a bunch so we don't run into any of sun's numbers */
+  M_386 = 100,
+};
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+	((exec).a_info = ((magic) & 0xffff) \
+	 | (((int)(type) & 0xff) << 16) \
+	 | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+	((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+#define N_SET_MACHTYPE(exec, machtype) \
+	((exec).a_info = \
+	 ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+#define N_SET_FLAGS(exec, flags) \
+	((exec).a_info = \
+	 ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+/* Code indicating object file or impure executable.  */
+#define OMAGIC 0407
+/* Code indicating pure executable.  */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable.  */
+#define ZMAGIC 0413
+#define N_BADMAG(x)					\
+ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC		\
+  && N_MAGIC(x) != ZMAGIC)
+#define _N_BADMAG(x)					\
+ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC		\
+  && N_MAGIC(x) != ZMAGIC)
+#define _N_HDROFF(x) (1024 - sizeof (struct exec))
+#define N_TXTOFF(x) \
+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
+#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
+#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
+/* Address of text segment in memory after it is loaded.  */
+#define N_TXTADDR(x) SEGMENT_SIZE      /* emx */
+
+/* Address of data segment in memory after it is loaded.
+   Note that it is up to you to define SEGMENT_SIZE
+   on machines not listed here.  */
+#ifdef vax
+#define SEGMENT_SIZE page_size
+#endif
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+
+#define SEGMENT_SIZE 0x10000    /* emx */
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+    (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+(x).a_text) \
+     : (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))))
+#endif
+/* Address of bss segment in memory after it is loaded.  */
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+
+
+struct nlist {
+  union {
+    char *n_name;
+    struct nlist *n_next;
+    long n_strx;
+  } n_un;
+  unsigned char n_type;
+  char n_other;
+  short n_desc;
+  unsigned long n_value;
+};
+#define N_UNDF 0
+#define N_ABS 2
+#define N_TEXT 4
+#define N_DATA 6
+#define N_BSS 8
+#define N_FN 15
+#define N_EXT 1
+#define N_TYPE 036
+#define N_STAB 0340
+/* The following type indicates the definition of a symbol as being
+   an indirect reference to another symbol.  The other symbol
+   appears as an undefined reference, immediately following this symbol.
+   Indirection is asymmetrical.  The other symbol's value will be used
+   to satisfy requests for the indirect symbol, but not vice versa.
+   If the other symbol does not have a definition, libraries will
+   be searched to find a definition.  */
+#define N_INDR 0xa
+/* The following symbols refer to set elements.
+   All the N_SET[ATDB] symbols with the same name form one set.
+   Space is allocated for the set in the text section, and each set
+   element's value is stored into one word of the space.
+   The first word of the space is the length of the set (number of elements).
+   The address of the set is made into an N_SETV symbol
+   whose name is the same as the name of the set.
+   This symbol acts like a N_DATA global symbol
+   in that it can satisfy undefined external references.  */ 
+
+/* These appear as input to LD, in a .o file.  */
+#define	N_SETA	0x14		/* Absolute set element symbol */
+#define	N_SETT	0x16		/* Text set element symbol */
+#define	N_SETD	0x18		/* Data set element symbol */
+#define	N_SETB	0x1A		/* Bss set element symbol */
+/* This is output from LD.  */
+#define N_SETV	0x1C		/* Pointer to set vector in data area.  */
+/* Copied from aout64.h of BFD */
+#define N_WEAKU 0x0d		/* Weak undefined symbol.  */
+/* emx */
+#define N_IMP1  0x68            /* Import definition symbol */
+
+
+/* This structure describes a single relocation to be performed.
+   The text-relocation section of the file is a vector of these structures,
+   all of which apply to the text section.
+   Likewise, the data-relocation section applies to the data section.  */
+struct relocation_info
+{
+  /* Address (within segment) to be relocated.  */
+  int r_address;
+  /* The meaning of r_symbolnum depends on r_extern.  */
+  unsigned int r_symbolnum:24;
+  /* Nonzero means value is a pc-relative offset
+     and it should be relocated for changes in its own address
+     as well as for changes in the symbol or section specified.  */
+  unsigned int r_pcrel:1;
+  /* Length (as exponent of 2) of the field to be relocated.
+     Thus, a value of 2 indicates 1<<2 bytes.  */
+  unsigned int r_length:2;
+  /* 1 => relocate with value of symbol.
+          r_symbolnum is the index of the symbol
+	  in file's the symbol table.
+     0 => relocate with the address of a segment.
+          r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+	  (the N_EXT bit may be set also, but signifies nothing).  */
+  unsigned int r_extern:1;
+  /* Four bits that aren't used, but when writing an object file
+     it is desirable to clear them.  */
+  unsigned int r_pad:4;
+};
+#endif /* __A_OUT_GNU_H__ */
Index: trunk/src/emx/include/alloca.h
===================================================================
--- trunk/src/emx/include/alloca.h	(revision 18)
+++ trunk/src/emx/include/alloca.h	(revision 18)
@@ -0,0 +1,10 @@
+/* alloca.h (emx+gcc) */
+
+#ifndef _ALLOCA_H
+#define _ALLOCA_H
+
+#if !defined (alloca)
+#define alloca(x) __builtin_alloca(x)
+#endif
+
+#endif /* not _ALLOCA_H */
Index: trunk/src/emx/include/ar.h
===================================================================
--- trunk/src/emx/include/ar.h	(revision 18)
+++ trunk/src/emx/include/ar.h	(revision 18)
@@ -0,0 +1,21 @@
+/* ar.h (emx+gcc) */
+
+#ifndef _AR_H
+#define _AR_H
+
+#define ARMAG  "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+struct ar_hdr
+{
+  char ar_name[16];
+  char ar_date[12];
+  char ar_uid[6];
+  char ar_gid[6];
+  char ar_mode[8];
+  char ar_size[10];
+  char ar_fmag[2];
+};
+
+#endif /* not _AR_H */
Index: trunk/src/emx/include/arpa/ftp.h
===================================================================
--- trunk/src/emx/include/arpa/ftp.h	(revision 18)
+++ trunk/src/emx/include/arpa/ftp.h	(revision 18)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1983, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ftp.h	5.6 (Berkeley) 4/3/91
+ */
+
+#ifndef _FTP_H_
+#define	_FTP_H_
+
+/* Definitions for FTP; see RFC-765. */
+
+/*
+ * Reply codes.
+ */
+#define PRELIM		1	/* positive preliminary */
+#define COMPLETE	2	/* positive completion */
+#define CONTINUE	3	/* positive intermediate */
+#define TRANSIENT	4	/* transient negative completion */
+#define ERROR		5	/* permanent negative completion */
+
+/*
+ * Type codes
+ */
+#define	TYPE_A		1	/* ASCII */
+#define	TYPE_E		2	/* EBCDIC */
+#define	TYPE_I		3	/* image */
+#define	TYPE_L		4	/* local byte size */
+
+#ifdef FTP_NAMES
+char *typenames[] =  {"0", "ASCII", "EBCDIC", "Image", "Local" };
+#endif
+
+/*
+ * Form codes
+ */
+#define	FORM_N		1	/* non-print */
+#define	FORM_T		2	/* telnet format effectors */
+#define	FORM_C		3	/* carriage control (ASA) */
+#ifdef FTP_NAMES
+char *formnames[] =  {"0", "Nonprint", "Telnet", "Carriage-control" };
+#endif
+
+/*
+ * Structure codes
+ */
+#define	STRU_F		1	/* file (no record structure) */
+#define	STRU_R		2	/* record structure */
+#define	STRU_P		3	/* page structure */
+#ifdef FTP_NAMES
+char *strunames[] =  {"0", "File", "Record", "Page" };
+#endif
+
+/*
+ * Mode types
+ */
+#define	MODE_S		1	/* stream */
+#define	MODE_B		2	/* block */
+#define	MODE_C		3	/* compressed */
+#ifdef FTP_NAMES
+char *modenames[] =  {"0", "Stream", "Block", "Compressed" };
+#endif
+
+/*
+ * Record Tokens
+ */
+#define	REC_ESC		'\377'	/* Record-mode Escape */
+#define	REC_EOR		'\001'	/* Record-mode End-of-Record */
+#define REC_EOF		'\002'	/* Record-mode End-of-File */
+
+/*
+ * Block Header
+ */
+#define	BLK_EOR		0x80	/* Block is End-of-Record */
+#define	BLK_EOF		0x40	/* Block is End-of-File */
+#define BLK_ERRORS	0x20	/* Block is suspected of containing errors */
+#define	BLK_RESTART	0x10	/* Block is Restart Marker */
+
+#define	BLK_BYTECOUNT	2	/* Bytes in this block */
+
+#endif /* !_FTP_H_ */
Index: trunk/src/emx/include/arpa/inet.h
===================================================================
--- trunk/src/emx/include/arpa/inet.h	(revision 18)
+++ trunk/src/emx/include/arpa/inet.h	(revision 18)
@@ -0,0 +1,57 @@
+/* Modified for emx by hv and em 1994
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)inet.h	5.7 (Berkeley) 4/3/91
+ *	$Id: inet.h,v 1.2 1993/08/01 18:46:22 mycroft Exp $
+ */
+
+#ifndef _INET_H_
+#define	_INET_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* External definitions for functions in inet(3) */
+extern u_long		inet_addr(__const__ char*);
+extern u_long		inet_lnaof(struct in_addr);
+extern struct in_addr	inet_makeaddr(u_long, u_long);
+extern u_long		inet_netof(struct in_addr);
+extern u_long		inet_network(__const__ char*);
+extern char*		inet_ntoa(struct in_addr);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_INET_H_ */
Index: trunk/src/emx/include/arpa/nameser.h
===================================================================
--- trunk/src/emx/include/arpa/nameser.h	(revision 18)
+++ trunk/src/emx/include/arpa/nameser.h	(revision 18)
@@ -0,0 +1,257 @@
+/* Modified for emx by hv 1994,1996
+ *
+ * Copyright (c) 1983, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)nameser.h	5.25 (Berkeley) 4/3/91
+ *	$Id: nameser.h,v 1.4 1993/10/27 00:10:40 mycroft Exp $
+ */
+
+#ifndef _NAMESER_H_
+#define	_NAMESER_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <sys/param.h>          /* htons() etc. */
+#include <machine/endian.h>	/* BYTE ORDER etc. */
+
+/*
+ * Define constants based on rfc883
+ */
+#define PACKETSZ	512		/* maximum packet size */
+#define MAXDNAME	256		/* maximum domain name */
+#define MAXCDNAME	255		/* maximum compressed domain name */
+#define MAXLABEL	63		/* maximum length of domain label */
+	/* Number of bytes of fixed size data in query structure */
+#define QFIXEDSZ	4
+	/* number of bytes of fixed size data in resource record */
+#define RRFIXEDSZ	10
+
+/*
+ * Internet nameserver port number
+ */
+#define NAMESERVER_PORT	53
+
+/*
+ * Currently defined opcodes
+ */
+#define QUERY		0x0		/* standard query */
+#define IQUERY		0x1		/* inverse query */
+#define STATUS		0x2		/* nameserver status query */
+/*#define xxx		0x3		   0x3 reserved */
+	/* non standard */
+/* IBM has changed these codes in TCP/IP for OS/2 */
+#define UPDATEA		100		/* add resource record */
+#define UPDATED		101		/* delete a specific resource record */
+#define UPDATEM		102		/* modify a specific resource record */
+#define ZONEINIT	103		/* initial zone transfer */
+#define ZONEREF		104		/* incremental zone referesh */
+
+/*
+ * Currently defined response codes
+ */
+#define NOERROR		0		/* no error */
+#define FORMERR		1		/* format error */
+#define SERVFAIL	2		/* server failure */
+#define NXDOMAIN	3		/* non existent domain */
+#define NOTIMP		4		/* not implemented */
+#define REFUSED		5		/* query refused */
+	/* non standard */
+#define NOCHANGE	100		/* update failed to change db */
+
+/*
+ * Type values for resources and queries
+ */
+#define T_A		1		/* host address */
+#define T_NS		2		/* authoritative server */
+#define T_MD		3		/* mail destination */
+#define T_MF		4		/* mail forwarder */
+#define T_CNAME		5		/* connonical name */
+#define T_SOA		6		/* start of authority zone */
+#define T_MB		7		/* mailbox domain name */
+#define T_MG		8		/* mail group member */
+#define T_MR		9		/* mail rename name */
+#define T_NULL		10		/* null resource record */
+#define T_WKS		11		/* well known service */
+#define T_PTR		12		/* domain name pointer */
+#define T_HINFO		13		/* host information */
+#define T_MINFO		14		/* mailbox information */
+#define T_MX		15		/* mail routing information */
+#define T_TXT		16		/* text strings */
+	/* non standard */
+#define T_UINFO		100		/* user (finger) information */
+#define T_UID		101		/* user ID */
+#define T_GID		102		/* group ID */
+#define T_UNSPEC	103		/* Unspecified format (binary data) */
+	/* Query type values which do not appear in resource records */
+#define T_AXFR		252		/* transfer zone of authority */
+#define T_MAILB		253		/* transfer mailbox records */
+#define T_MAILA		254		/* transfer mail agent records */
+#define T_ANY		255		/* wildcard match */
+
+/*
+ * Values for class field
+ */
+#define C_IN		1		/* the arpa internet */
+#define C_CHAOS		3		/* for chaos net at MIT */
+#define C_HS		4		/* for Hesiod name server at MIT */
+	/* Query class values which do not appear in resource records */
+#define C_ANY		255		/* wildcard match */
+
+/*
+ * Status return codes for T_UNSPEC conversion routines
+ */
+#define CONV_SUCCESS 0
+#define CONV_OVERFLOW -1
+#define CONV_BADFMT -2
+#define CONV_BADCKSUM -3
+#define CONV_BADBUFLEN -4
+
+/*
+ * Structure for query header, the order of the fields is machine and
+ * compiler dependent, in our case, the bits within a byte are assignd 
+ * least significant first, while the order of transmition is most 
+ * significant first.  This requires a somewhat confusing rearrangement.
+ */
+typedef struct {
+	u_short	id;		/* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+			/* fields in third byte */
+	u_char	qr:1;		/* response flag */
+	u_char	opcode:4;	/* purpose of message */
+	u_char	aa:1;		/* authoritive answer */
+	u_char	tc:1;		/* truncated message */
+	u_char	rd:1;		/* recursion desired */
+			/* fields in fourth byte */
+	u_char	ra:1;		/* recursion available */
+	u_char	pr:1;		/* primary server required (non standard) */
+	u_char	unused:2;	/* unused bits */
+	u_char	rcode:4;	/* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+			/* fields in third byte */
+	u_char	rd:1;		/* recursion desired */
+	u_char	tc:1;		/* truncated message */
+	u_char	aa:1;		/* authoritive answer */
+	u_char	opcode:4;	/* purpose of message */
+	u_char	qr:1;		/* response flag */
+			/* fields in fourth byte */
+	u_char	rcode:4;	/* response code */
+	u_char	unused:2;	/* unused bits */
+	u_char	pr:1;		/* primary server required (non standard) */
+	u_char	ra:1;		/* recursion available */
+#endif
+			/* remaining bytes */
+	u_short	qdcount;	/* number of question entries */
+	u_short	ancount;	/* number of answer entries */
+	u_short	nscount;	/* number of authority entries */
+	u_short	arcount;	/* number of resource entries */
+} HEADER;
+
+/*
+ * Defines for handling compressed domain names
+ */
+#define INDIR_MASK	0xc0
+
+/*
+ * Structure for passing resource records around.
+ */
+#pragma pack(4)
+struct rrec {
+	short	r_zone;			/* zone number */
+	short	r_class;		/* class number */
+	short	r_type;			/* type number */
+	u_long	r_ttl;			/* time to live */
+	int	r_size;			/* size of data area */
+	char	*r_data;		/* pointer to data */
+};
+#pragma pack()
+
+/*
+ * Inline versions of get/put short/long.
+ * Pointer is advanced; we assume that both arguments
+ * are lvalues and will already be in registers.
+ * cp MUST be u_char *.
+ */
+#define GETSHORT(s, cp) { \
+	(s) = *(cp)++ << 8; \
+	(s) |= *(cp)++; \
+}
+
+#define GETLONG(l, cp) { \
+	(l) = *(cp)++ << 8; \
+	(l) |= *(cp)++; (l) <<= 8; \
+	(l) |= *(cp)++; (l) <<= 8; \
+	(l) |= *(cp)++; \
+}
+
+
+#define PUTSHORT(s, cp) { \
+	*(cp)++ = (s) >> 8; \
+	*(cp)++ = (s); \
+}
+
+/*
+ * Warning: PUTLONG destroys its first argument.
+ */
+#define PUTLONG(l, cp) { \
+	(cp)[3] = l; \
+	(cp)[2] = (l >>= 8); \
+	(cp)[1] = (l >>= 8); \
+	(cp)[0] = l >> 8; \
+	(cp) += sizeof(u_long); \
+}
+
+/* function prototypes */
+u_short	_getshort(u_char*);
+u_long	_getlong(u_char*);
+void	putshort(u_short, u_char *);
+void	putlong(u_long, u_char *);
+int	dn_expand(__const__ u_char*, __const__ u_char*, __const__ u_char*, 
+		  u_char*, int);
+int	dn_comp(__const__ u_char*, u_char*, int, u_char**, u_char**);
+int	dn_find(u_char*, u_char*, u_char**, u_char**);
+int	dn_skipname(__const__ u_char*, __const__ u_char*);
+int	res_init(void);
+int	res_mkquery(int, __const__ char*, int, int, __const__ char*, 
+		    int, __const__ struct rrec*, char*, int);
+int	res_send(__const__ char*, int, char*, int);
+int	res_query(char*, int, int, u_char*, int);
+int	res_search(char*, int, int, u_char*, int);
+int	res_querydomain(char*, char*, int, int, u_char*, int);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_NAMESER_H_ */
Index: trunk/src/emx/include/arpa/telnet.h
===================================================================
--- trunk/src/emx/include/arpa/telnet.h	(revision 18)
+++ trunk/src/emx/include/arpa/telnet.h	(revision 18)
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)telnet.h	5.14 (Berkeley) 4/3/91
+ */
+
+#ifndef _TELNET_H_
+#define	_TELNET_H_
+
+/*
+ * Definitions for the TELNET protocol.
+ */
+#define	IAC	255		/* interpret as command: */
+#define	DONT	254		/* you are not to use option */
+#define	DO	253		/* please, you use option */
+#define	WONT	252		/* I won't use option */
+#define	WILL	251		/* I will use option */
+#define	SB	250		/* interpret as subnegotiation */
+#define	GA	249		/* you may reverse the line */
+#define	EL	248		/* erase the current line */
+#define	EC	247		/* erase the current character */
+#define	AYT	246		/* are you there */
+#define	AO	245		/* abort output--but let prog finish */
+#define	IP	244		/* interrupt process--permanently */
+#define	BREAK	243		/* break */
+#define	DM	242		/* data mark--for connect. cleaning */
+#define	NOP	241		/* nop */
+#define	SE	240		/* end sub negotiation */
+#define EOR     239             /* end of record (transparent mode) */
+#define	ABORT	238		/* Abort process */
+#define	SUSP	237		/* Suspend process */
+#define	xEOF	236		/* End of file: EOF is already used... */
+
+#define SYNCH	242		/* for telfunc calls */
+
+#ifdef TELCMDS
+char *telcmds[] = {
+	"EOF", "SUSP", "ABORT", "EOR",
+	"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
+	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
+};
+#else
+extern char *telcmds[];
+#endif
+
+#define	TELCMD_FIRST	xEOF
+#define	TELCMD_LAST	IAC
+#define	TELCMD_OK(x)	((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST)
+#define	TELCMD(x)	telcmds[(x)-TELCMD_FIRST]
+
+/* telnet options */
+#define TELOPT_BINARY	0	/* 8-bit data path */
+#define TELOPT_ECHO	1	/* echo */
+#define	TELOPT_RCP	2	/* prepare to reconnect */
+#define	TELOPT_SGA	3	/* suppress go ahead */
+#define	TELOPT_NAMS	4	/* approximate message size */
+#define	TELOPT_STATUS	5	/* give status */
+#define	TELOPT_TM	6	/* timing mark */
+#define	TELOPT_RCTE	7	/* remote controlled transmission and echo */
+#define TELOPT_NAOL 	8	/* negotiate about output line width */
+#define TELOPT_NAOP 	9	/* negotiate about output page size */
+#define TELOPT_NAOCRD	10	/* negotiate about CR disposition */
+#define TELOPT_NAOHTS	11	/* negotiate about horizontal tabstops */
+#define TELOPT_NAOHTD	12	/* negotiate about horizontal tab disposition */
+#define TELOPT_NAOFFD	13	/* negotiate about formfeed disposition */
+#define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops */
+#define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
+#define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
+#define TELOPT_XASCII	17	/* extended ascic character set */
+#define	TELOPT_LOGOUT	18	/* force logout */
+#define	TELOPT_BM	19	/* byte macro */
+#define	TELOPT_DET	20	/* data entry terminal */
+#define	TELOPT_SUPDUP	21	/* supdup protocol */
+#define	TELOPT_SUPDUPOUTPUT 22	/* supdup output */
+#define	TELOPT_SNDLOC	23	/* send location */
+#define	TELOPT_TTYPE	24	/* terminal type */
+#define	TELOPT_EOR	25	/* end or record */
+#define	TELOPT_TUID	26	/* TACACS user identification */
+#define	TELOPT_OUTMRK	27	/* output marking */
+#define	TELOPT_TTYLOC	28	/* terminal location number */
+#define	TELOPT_3270REGIME 29	/* 3270 regime */
+#define	TELOPT_X3PAD	30	/* X.3 PAD */
+#define	TELOPT_NAWS	31	/* window size */
+#define	TELOPT_TSPEED	32	/* terminal speed */
+#define	TELOPT_LFLOW	33	/* remote flow control */
+#define TELOPT_LINEMODE	34	/* Linemode option */
+#define TELOPT_XDISPLOC	35	/* X Display Location */
+#define TELOPT_ENVIRON	36	/* Environment variables */
+#define	TELOPT_AUTHENTICATION 37/* Authenticate */
+#define	TELOPT_ENCRYPT	38	/* Encryption option */
+#define	TELOPT_EXOPL	255	/* extended-options-list */
+
+
+#define	NTELOPTS	(1+TELOPT_ENCRYPT)
+#ifdef TELOPTS
+char *telopts[NTELOPTS+1] = {
+	"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
+	"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
+	"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
+	"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+	"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+	"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
+	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
+	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
+	"LINEMODE", "XDISPLOC", "ENVIRON", "AUTHENTICATION",
+	"ENCRYPT",
+	0,
+};
+#define	TELOPT_FIRST	TELOPT_BINARY
+#define	TELOPT_LAST	TELOPT_ENCRYPT
+#define	TELOPT_OK(x)	((x) <= TELOPT_LAST && (x) >= TELOPT_FIRST)
+#define	TELOPT(x)	telopts[(x)-TELOPT_FIRST]
+#endif
+
+/* sub-option qualifiers */
+#define	TELQUAL_IS	0	/* option is... */
+#define	TELQUAL_SEND	1	/* send option */
+#define	TELQUAL_INFO	2	/* ENVIRON: informational version of IS */
+#define	TELQUAL_REPLY	2	/* AUTHENTICATION: client version of IS */
+#define	TELQUAL_NAME	3	/* AUTHENTICATION: client version of IS */
+
+/*
+ * LINEMODE suboptions
+ */
+
+#define	LM_MODE		1
+#define	LM_FORWARDMASK	2
+#define	LM_SLC		3
+
+#define	MODE_EDIT	0x01
+#define	MODE_TRAPSIG	0x02
+#define	MODE_ACK	0x04
+#define MODE_SOFT_TAB	0x08
+#define MODE_LIT_ECHO	0x10
+
+#define	MODE_MASK	0x1f
+
+/* Not part of protocol, but needed to simplify things... */
+#define MODE_FLOW		0x0100
+#define MODE_ECHO		0x0200
+#define MODE_INBIN		0x0400
+#define MODE_OUTBIN		0x0800
+#define MODE_FORCE		0x1000
+
+#define	SLC_SYNCH	1
+#define	SLC_BRK		2
+#define	SLC_IP		3
+#define	SLC_AO		4
+#define	SLC_AYT		5
+#define	SLC_EOR		6
+#define	SLC_ABORT	7
+#define	SLC_EOF		8
+#define	SLC_SUSP	9
+#define	SLC_EC		10
+#define	SLC_EL		11
+#define	SLC_EW		12
+#define	SLC_RP		13
+#define	SLC_LNEXT	14
+#define	SLC_XON		15
+#define	SLC_XOFF	16
+#define	SLC_FORW1	17
+#define	SLC_FORW2	18
+
+#define	NSLC		18
+
+/*
+ * For backwards compatability, we define SLC_NAMES to be the
+ * list of names if SLC_NAMES is not defined.
+ */
+#define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
+			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
+			"LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0,
+#ifdef	SLC_NAMES
+char *slc_names[] = {
+	SLC_NAMELIST
+};
+#else
+extern char *slc_names[];
+#define	SLC_NAMES SLC_NAMELIST
+#endif
+
+#define	SLC_NAME_OK(x)	((x) >= 0 && (x) < NSLC)
+#define SLC_NAME(x)	slc_names[x]
+
+#define	SLC_NOSUPPORT	0
+#define	SLC_CANTCHANGE	1
+#define	SLC_VARIABLE	2
+#define	SLC_DEFAULT	3
+#define	SLC_LEVELBITS	0x03
+
+#define	SLC_FUNC	0
+#define	SLC_FLAGS	1
+#define	SLC_VALUE	2
+
+#define	SLC_ACK		0x80
+#define	SLC_FLUSHIN	0x40
+#define	SLC_FLUSHOUT	0x20
+
+#define	ENV_VALUE	0
+#define	ENV_VAR		1
+#define	ENV_ESC		2
+
+/*
+ * AUTHENTICATION suboptions
+ */
+
+/*
+ * Who is authenticating who ...
+ */
+#define	AUTH_WHO_CLIENT		0	/* Client authenticating server */
+#define	AUTH_WHO_SERVER		1	/* Server authenticating client */
+#define	AUTH_WHO_MASK		1
+
+/*
+ * amount of authentication done
+ */
+#define	AUTH_HOW_ONE_WAY	0
+#define	AUTH_HOW_MUTUAL		2
+#define	AUTH_HOW_MASK		2
+
+#define	AUTHTYPE_NULL		0
+#define	AUTHTYPE_KERBEROS_V4	1
+#define	AUTHTYPE_KERBEROS_V5	2
+#define	AUTHTYPE_SPX		3
+#define	AUTHTYPE_MINK		4
+#define	AUTHTYPE_CNT		5
+
+#define	AUTHTYPE_TEST		99
+
+#ifdef	AUTH_NAMES
+char *authtype_names[] = {
+	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
+};
+#else
+extern char *authtype_names[];
+#endif
+
+#define	AUTHTYPE_NAME_OK(x)	((x) >= 0 && (x) < AUTHTYPE_CNT)
+#define	AUTHTYPE_NAME(x)	authtype_names[x]
+
+/*
+ * ENCRYPTion suboptions
+ */
+#define	ENCRYPT_IS		0	/* I pick encryption type ... */
+#define	ENCRYPT_SUPPORT		1	/* I support encryption types ... */
+#define	ENCRYPT_REPLY		2	/* Initial setup response */
+#define	ENCRYPT_START		3	/* Am starting to send encrypted */
+#define	ENCRYPT_END		4	/* Am ending encrypted */
+#define	ENCRYPT_REQSTART	5	/* Request you start encrypting */
+#define	ENCRYPT_REQEND		6	/* Request you send encrypting */
+#define	ENCRYPT_ENC_KEYID	7
+#define	ENCRYPT_DEC_KEYID	8
+#define	ENCRYPT_CNT		9
+
+#define	ENCTYPE_ANY		0
+#define	ENCTYPE_DES_CFB64	1
+#define	ENCTYPE_DES_OFB64	2
+#define	ENCTYPE_CNT		3
+
+#ifdef	ENCRYPT_NAMES
+char *encrypt_names[] = {
+	"IS", "SUPPORT", "REPLY", "START", "END",
+	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
+	0,
+};
+char *enctype_names[] = {
+	"ANY", "DES_CFB64",  "DES_OFB64",  0,
+};
+#else
+extern char *encrypt_names[];
+extern char *enctype_names[];
+#endif
+
+
+#define	ENCRYPT_NAME_OK(x)	((x) >= 0 && (x) < ENCRYPT_CNT)
+#define	ENCRYPT_NAME(x)		encrypt_names[x]
+
+#define	ENCTYPE_NAME_OK(x)	((x) >= 0 && (x) < ENCTYPE_CNT)
+#define	ENCTYPE_NAME(x)		enctype_names[x]
+
+#endif /* !_TELNET_H_ */
Index: trunk/src/emx/include/assert.h
===================================================================
--- trunk/src/emx/include/assert.h	(revision 18)
+++ trunk/src/emx/include/assert.h	(revision 18)
@@ -0,0 +1,18 @@
+/* assert.h (emx+gcc) */
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#undef assert
+
+#if defined (NDEBUG)
+#define assert(exp) ((void)0)
+#else
+void _assert (__const__ char *, __const__ char *, unsigned);
+#define assert(exp) ((exp) ? (void)0 : _assert (#exp, __FILE__, __LINE__))
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
Index: trunk/src/emx/include/bsd/curses.h
===================================================================
--- trunk/src/emx/include/bsd/curses.h	(revision 18)
+++ trunk/src/emx/include/bsd/curses.h	(revision 18)
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1981 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)curses.h	5.9 (Berkeley) 7/1/90
+ */
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#ifndef WINDOW
+
+#include	<stdio.h>
+#include	<sys/ioctl.h>
+#include	<sys/termio.h>
+typedef	struct termio	SGTTY;
+
+#define	bool	char
+#define	reg	register
+
+#define	TRUE	(1)
+#define	FALSE	(0)
+#define	ERR	(0)
+#define	OK	(1)
+
+#define	_ENDLINE	001
+#define	_FULLWIN	002
+#define	_SCROLLWIN	004
+#define	_FLUSH		010
+#define	_FULLLINE	020
+#define	_IDLINE		040
+#define	_STANDOUT	0200
+#define	_NOCHANGE	-1
+
+#define	_puts(s)	tputs(s, 0, _putchar)
+
+/*
+ * Capabilities from termcap
+ */
+
+extern bool     AM, BS, CA, DA, DB, EO, HC, HZ, IN, MI, MS, NC, NS, OS, UL,
+		XB, XN, XT, XS, XX;
+extern char	*AL, *BC, *BT, *CD, *CE, *CL, *CM, *CR, *CS, *DC, *DL,
+		*DM, *DO, *ED, *EI, *K0, *K1, *K2, *K3, *K4, *K5, *K6,
+		*K7, *K8, *K9, *HO, *IC, *IM, *IP, *KD, *KE, *KH, *KL,
+		*KR, *KS, *KU, *LL, *MA, *ND, *NL, *RC, *SC, *SE, *SF,
+		*SO, *SR, *TA, *TE, *TI, *UC, *UE, *UP, *US, *VB, *VS,
+		*VE, *AL_PARM, *DL_PARM, *UP_PARM, *DOWN_PARM,
+		*LEFT_PARM, *RIGHT_PARM;
+extern char	PC;
+
+/*
+ * From the tty modes...
+ */
+
+extern bool	GT, NONL, UPPERCASE, normtty, _pfast;
+
+struct _win_st {
+	short		_cury, _curx;
+	short		_maxy, _maxx;
+	short		_begy, _begx;
+	short		_flags;
+	short		_ch_off;
+	bool		_clear;
+	bool		_leave;
+	bool		_scroll;
+	char		**_y;
+	short		*_firstch;
+	short		*_lastch;
+	struct _win_st	*_nextp, *_orig;
+};
+
+#define	WINDOW	struct _win_st
+
+extern bool	My_term, _echoit, _rawmode, _endwin;
+extern char	*Def_term, ttytype[];
+extern int	LINES, COLS, _tty_ch, _res_flg;
+extern SGTTY	_tty;
+extern WINDOW	*stdscr, *curscr;
+
+#define	VOID(x)	(x)
+
+/*
+ * pseudo functions for standard screen
+ */
+#define	addch(ch)	VOID(waddch(stdscr, ch))
+#define	getch()		VOID(wgetch(stdscr))
+#define	addbytes(da,co)	VOID(waddbytes(stdscr, da,co))
+#define	addstr(str)	VOID(waddbytes(stdscr, str, strlen(str)))
+#define	getstr(str)	VOID(wgetstr(stdscr, str))
+#define	move(y, x)	VOID(wmove(stdscr, y, x))
+#define	clear()		VOID(wclear(stdscr))
+#define	erase()		VOID(werase(stdscr))
+#define	clrtobot()	VOID(wclrtobot(stdscr))
+#define	clrtoeol()	VOID(wclrtoeol(stdscr))
+#define	insertln()	VOID(winsertln(stdscr))
+#define	deleteln()	VOID(wdeleteln(stdscr))
+#define	refresh()	VOID(wrefresh(stdscr))
+#define	inch()		VOID(winch(stdscr))
+#define	insch(c)	VOID(winsch(stdscr,c))
+#define	delch()		VOID(wdelch(stdscr))
+#define	standout()	VOID(wstandout(stdscr))
+#define	standend()	VOID(wstandend(stdscr))
+
+/*
+ * mv functions
+ */
+#define	mvwaddch(win,y,x,ch)	VOID(wmove(win,y,x)==ERR?ERR:waddch(win,ch))
+#define	mvwgetch(win,y,x)	VOID(wmove(win,y,x)==ERR?ERR:wgetch(win))
+#define	mvwaddbytes(win,y,x,da,co) \
+		VOID(wmove(win,y,x)==ERR?ERR:waddbytes(win,da,co))
+#define	mvwaddstr(win,y,x,str) \
+		VOID(wmove(win,y,x)==ERR?ERR:waddbytes(win,str,strlen(str)))
+#define mvwgetstr(win,y,x,str)  VOID(wmove(win,y,x)==ERR?ERR:wgetstr(win,str))
+#define	mvwinch(win,y,x)	VOID(wmove(win,y,x) == ERR ? ERR : winch(win))
+#define	mvwdelch(win,y,x)	VOID(wmove(win,y,x) == ERR ? ERR : wdelch(win))
+#define	mvwinsch(win,y,x,c)	VOID(wmove(win,y,x) == ERR ? ERR:winsch(win,c))
+#define	mvaddch(y,x,ch)		mvwaddch(stdscr,y,x,ch)
+#define	mvgetch(y,x)		mvwgetch(stdscr,y,x)
+#define	mvaddbytes(y,x,da,co)	mvwaddbytes(stdscr,y,x,da,co)
+#define	mvaddstr(y,x,str)	mvwaddstr(stdscr,y,x,str)
+#define mvgetstr(y,x,str)       mvwgetstr(stdscr,y,x,str)
+#define	mvinch(y,x)		mvwinch(stdscr,y,x)
+#define	mvdelch(y,x)		mvwdelch(stdscr,y,x)
+#define	mvinsch(y,x,c)		mvwinsch(stdscr,y,x,c)
+
+/*
+ * pseudo functions
+ */
+
+#define	clearok(win,bf)	 (win->_clear = bf)
+#define	leaveok(win,bf)	 (win->_leave = bf)
+#define	scrollok(win,bf) (win->_scroll = bf)
+#define flushok(win,bf)	 (bf ? (win->_flags |= _FLUSH):(win->_flags &= ~_FLUSH))
+#define	getyx(win,y,x)	 y = win->_cury, x = win->_curx
+#define	winch(win)	 (win->_y[win->_cury][win->_curx])
+
+#define crmode() cbreak()	/* backwards compatability */
+#define nocrmode() nocbreak()	/* backwards compatability */
+
+#define noraw()         _setraw(0)
+#define raw()           _setraw(1)
+#define nocbreak()      _setraw(2)
+#define cbreak()        _setraw(3)
+#define echo()          _setecho(1)
+#define noecho()        _setecho(0)
+#define nl()            _setnl(1)
+#define nonl()          _setnl(0)
+
+/*
+ * Used to be in unctrl.h.
+ */
+#define	unctrl(c)	_unctrl[(c) & 0377]
+extern char *_unctrl[];
+
+int baudrate (void);
+int box (WINDOW *win, int vert, int hor);
+int delwin (WINDOW *win);
+int endwin (void);
+int erasechar (void);
+char *getcap (char *name);
+int gettmode (void);
+WINDOW *initscr (void);
+int killchar (void);
+char *longname (char *bp, char *def);
+int mvcur (int ly, int lx, int y, int x);
+int mvprintw (int y, int x, const char *fmt, ...);
+int mvscanw (int y, int x, const char *fmt, ...);
+int mvwin (WINDOW *win, int by, int bx);
+int mvwprintw (WINDOW *win, int y, int x, const char *fmt, ...);
+int mvwscanw (WINDOW *win, int y, int x, const char *fmt, ...);
+WINDOW *newwin (int num_lines, int num_cols, int begy, int begx);
+int overlay (WINDOW *win1, WINDOW *win2);
+int overwrite (WINDOW *win1, WINDOW *win2);
+int printw (const char *fmt, ...);
+int resetty (void);
+int savetty (void);
+int scanw (const char *fmt, ...);
+int scroll (WINDOW *win);
+int setterm (char *type);
+WINDOW *subwin (WINDOW *orig, int num_lines, int num_cols, int begy, int begx);
+int touchline (WINDOW *win, int y, int sx, int ex);
+int touchwin (WINDOW *win);
+int waddbytes (reg WINDOW *win, reg char *bytes, reg int count);
+int waddch (WINDOW *win, int c);
+int waddstr (reg WINDOW *win, reg char *str);
+int wclear (WINDOW *win);
+int wclrtobot (WINDOW *win);
+int wclrtoeol (WINDOW *win);
+int wdelch (WINDOW *win);
+int wdeleteln (WINDOW *win);
+int werase (WINDOW *win);
+int wgetch (WINDOW *win);
+int wgetstr (WINDOW *win, char *str);
+int winsch (WINDOW *win, int c);
+int winsertln (WINDOW *win);
+int wmove (WINDOW *win, int y, int x);
+int wprintw (WINDOW *win, const char *fmt, ...);
+int wrefresh (WINDOW *win);
+int wscanw (WINDOW *win, const char *fmt, ...);
+char *wstandend (WINDOW *win);
+char *wstandout (WINDOW *win);
+char _putchar (int c);
+int _setecho (int on);
+int _setnl (int on);
+int _setraw (int on);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
Index: trunk/src/emx/include/bsd/termcap.h
===================================================================
--- trunk/src/emx/include/bsd/termcap.h	(revision 18)
+++ trunk/src/emx/include/bsd/termcap.h	(revision 18)
@@ -0,0 +1,25 @@
+/* bsd/termcap.h (emx+gcc) */
+
+#ifndef _TERMCAP_H
+#define _TERMCAP_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+extern char *UP;
+extern char *BC;
+extern char PC;
+
+int tgetent (char *, const char *);
+int tgetnum (const char *);
+int tgetflag (const char *);
+char *tgetstr (const char *, char **);
+char *tgoto (const char *, int, int);
+int tputs (const char *, int, int (*)());
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _TERMCAP_H */
Index: trunk/src/emx/include/check.cmd
===================================================================
--- trunk/src/emx/include/check.cmd	(revision 18)
+++ trunk/src/emx/include/check.cmd	(revision 18)
@@ -0,0 +1,3 @@
+/* check.cmd */
+
+'gfind . -type f -print | xargs grep -f check.re'
Index: trunk/src/emx/include/check.re
===================================================================
--- trunk/src/emx/include/check.re	(revision 18)
+++ trunk/src/emx/include/check.re	(revision 18)
@@ -0,0 +1,1 @@
+^#[ 	]*include[ 	]\+[<"]\(.*/\)*[^./]\{9,\}\(\.[ch]\|\.cc\|\)[>"]
Index: trunk/src/emx/include/conio.h
===================================================================
--- trunk/src/emx/include/conio.h	(revision 18)
+++ trunk/src/emx/include/conio.h	(revision 18)
@@ -0,0 +1,9 @@
+/* conio.h (emx+gcc) */
+
+#ifndef _CONIO_H
+#define _CONIO_H
+
+#define getch()   _read_kbd (0, 1, 0)
+#define getche()  _read_kbd (1, 1, 0)
+
+#endif /* not _CONIO_H */
Index: trunk/src/emx/include/ctype.h
===================================================================
--- trunk/src/emx/include/ctype.h	(revision 18)
+++ trunk/src/emx/include/ctype.h	(revision 18)
@@ -0,0 +1,103 @@
+/* ctype.h (emx+gcc) */
+
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+extern unsigned char _ctype[];
+
+#define _UPPER  0x01
+#define _LOWER  0x02
+#define _DIGIT  0x04
+#define _XDIGIT 0x08
+#define _CNTRL  0x10
+#define _SPACE  0x20
+#define _PUNCT  0x40
+#define _PRINT  0x80
+
+#if defined (__cplusplus)
+
+extern inline int isalnum (int _c)
+  { return (_ctype+1)[_c] & (_UPPER|_LOWER|_DIGIT); }
+extern inline int isalpha (int _c)
+  { return (_ctype+1)[_c] & (_UPPER|_LOWER); }
+extern inline int iscntrl (int _c)
+  { return (_ctype+1)[_c] & (_CNTRL); }
+extern inline int isdigit (int _c)
+  { return (_ctype+1)[_c] & (_DIGIT); }
+extern inline int isgraph (int _c)
+  { return (_ctype+1)[_c] & (_PUNCT|_UPPER|_LOWER|_DIGIT); }
+extern inline int islower (int _c)
+  { return (_ctype+1)[_c] & (_LOWER); }
+extern inline int isprint (int _c)
+  { return (_ctype+1)[_c] & (_PRINT); }
+extern inline int ispunct (int _c)
+  { return (_ctype+1)[_c] & (_PUNCT); }
+extern inline int isspace (int _c)
+  { return (_ctype+1)[_c] & (_SPACE); }
+extern inline int isupper (int _c)
+  { return (_ctype+1)[_c] & (_UPPER); }
+extern inline int isxdigit (int _c)
+  { return (_ctype+1)[_c] & (_XDIGIT); }
+
+#else
+
+#define isalnum(c)  ((_ctype+1)[c] & (_UPPER|_LOWER|_DIGIT))
+#define isalpha(c)  ((_ctype+1)[c] & (_UPPER|_LOWER))
+#define iscntrl(c)  ((_ctype+1)[c] & (_CNTRL))
+#define isdigit(c)  ((_ctype+1)[c] & (_DIGIT))
+#define isgraph(c)  ((_ctype+1)[c] & (_PUNCT|_UPPER|_LOWER|_DIGIT))
+#define islower(c)  ((_ctype+1)[c] & (_LOWER))
+#define isprint(c)  ((_ctype+1)[c] & (_PRINT))
+#define ispunct(c)  ((_ctype+1)[c] & (_PUNCT))
+#define isspace(c)  ((_ctype+1)[c] & (_SPACE))
+#define isupper(c)  ((_ctype+1)[c] & (_UPPER))
+#define isxdigit(c) ((_ctype+1)[c] & (_XDIGIT))
+
+int (isalnum)(int);
+int (isalpha)(int);
+int (iscntrl)(int);
+int (isdigit)(int);
+int (isgraph)(int);
+int (islower)(int);
+int (isprint)(int);
+int (ispunct)(int);
+int (isspace)(int);
+int (isupper)(int);
+int (isxdigit)(int);
+
+int toupper (int);
+int tolower (int);
+int _toupper (int);
+int _tolower (int);
+
+#endif
+
+#if !defined (_CTYPE_FUN)
+extern __inline__ int _toupper (int _c) { return (_c-'a'+'A'); }
+extern __inline__ int _tolower (int _c) { return (_c-'A'+'a'); }
+extern __inline__ int toupper(int _c)
+  {return (islower(_c) ? _toupper(_c) : _c);}
+extern __inline__ int tolower(int _c)
+  {return (isupper(_c) ? _tolower(_c) : _c);}
+#endif
+
+#if !defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)
+
+int (toascii)(int);
+int (isascii)(int);
+
+#define isascii(c)  ((unsigned)(c) <= 0x7f)
+#define toascii(c)  ((c) & 0x7f)
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _CTYPE_H */
Index: trunk/src/emx/include/curses.h
===================================================================
--- trunk/src/emx/include/curses.h	(revision 18)
+++ trunk/src/emx/include/curses.h	(revision 18)
@@ -0,0 +1,1 @@
+#include <bsd/curses.h>
Index: trunk/src/emx/include/db.h
===================================================================
--- trunk/src/emx/include/db.h	(revision 18)
+++ trunk/src/emx/include/db.h	(revision 18)
@@ -0,0 +1,245 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)db.h	8.7 (Berkeley) 6/16/94
+ */
+
+#ifndef _DB_H_
+#define	_DB_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+#include <limits.h>
+
+#ifdef __DBINTERFACE_PRIVATE
+#include <compat.h>
+#endif
+
+#define	RET_ERROR	-1		/* Return values. */
+#define	RET_SUCCESS	 0
+#define	RET_SPECIAL	 1
+
+#ifndef	__BIT_TYPES_DEFINED__
+#define	__BIT_TYPES_DEFINED__
+typedef	__signed char		   int8_t;
+typedef	unsigned char		 u_int8_t;
+typedef	short			  int16_t;
+typedef	unsigned short		u_int16_t;
+typedef	int			  int32_t;
+typedef	unsigned int		u_int32_t;
+#ifdef WE_DONT_NEED_QUADS
+typedef	long long		  int64_t;
+typedef	unsigned long long	u_int64_t;
+#endif
+#endif
+
+#define	MAX_PAGE_NUMBER	0xffffffff	/* >= # of pages in a file */
+typedef u_int32_t	pgno_t;
+#define	MAX_PAGE_OFFSET	65535		/* >= # of bytes in a page */
+typedef u_int16_t	indx_t;
+#define	MAX_REC_NUMBER	0xffffffff	/* >= # of records in a tree */
+typedef u_int32_t	recno_t;
+
+/* Key/data structure -- a Data-Base Thang. */
+typedef struct {
+	void	*data;			/* data */
+	size_t	 size;			/* data length */
+} DBT;
+
+/* Routine flags. */
+#define	R_CURSOR	1		/* del, put, seq */
+#define	__R_UNUSED	2		/* UNUSED */
+#define	R_FIRST		3		/* seq */
+#define	R_IAFTER	4		/* put (RECNO) */
+#define	R_IBEFORE	5		/* put (RECNO) */
+#define	R_LAST		6		/* seq (BTREE, RECNO) */
+#define	R_NEXT		7		/* seq */
+#define	R_NOOVERWRITE	8		/* put */
+#define	R_PREV		9		/* seq (BTREE, RECNO) */
+#define	R_SETCURSOR	10		/* put (RECNO) */
+#define	R_RECNOSYNC	11		/* sync (RECNO) */
+
+typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
+
+/*
+ * !!!
+ * The following flags are included in the dbopen(3) call as part of the
+ * open(2) flags.  In order to avoid conflicts with the open flags, start
+ * at the top of the 16 or 32-bit number space and work our way down.  If
+ * the open flags were significantly expanded in the future, it could be
+ * a problem.  Wish I'd left another flags word in the dbopen call.
+ *
+ * !!!
+ * None of this stuff is implemented yet.  The only reason that it's here
+ * is so that the access methods can skip copying the key/data pair when
+ * the DB_LOCK flag isn't set.
+ */
+#if UINT_MAX > 65535
+#define	DB_LOCK		0x20000000	/* Do locking. */
+#define	DB_SHMEM	0x40000000	/* Use shared memory. */
+#define	DB_TXN		0x80000000	/* Do transactions. */
+#else
+#define	DB_LOCK		    0x2000	/* Do locking. */
+#define	DB_SHMEM	    0x4000	/* Use shared memory. */
+#define	DB_TXN		    0x8000	/* Do transactions. */
+#endif
+
+/* Access method description structure. */
+typedef struct __db {
+	DBTYPE type;			/* Underlying db type. */
+	int (*close)	__P((struct __db *));
+	int (*del)	__P((const struct __db *, const DBT *, u_int));
+	int (*get)	__P((const struct __db *, const DBT *, DBT *, u_int));
+	int (*put)	__P((const struct __db *, DBT *, const DBT *, u_int));
+	int (*seq)	__P((const struct __db *, DBT *, DBT *, u_int));
+	int (*sync)	__P((const struct __db *, u_int));
+	void *internal;			/* Access method private. */
+	int (*fd)	__P((const struct __db *));
+} DB;
+
+#define	BTREEMAGIC	0x053162
+#define	BTREEVERSION	3
+
+/* Structure used to pass parameters to the btree routines. */
+typedef struct {
+#define	R_DUP		0x01	/* duplicate keys */
+	u_long	flags;
+	u_int	cachesize;	/* bytes to cache */
+	int	maxkeypage;	/* maximum keys per page */
+	int	minkeypage;	/* minimum keys per page */
+	u_int	psize;		/* page size */
+	int	(*compare)	/* comparison function */
+	    __P((const DBT *, const DBT *));
+	size_t	(*prefix)	/* prefix function */
+	    __P((const DBT *, const DBT *));
+	int	lorder;		/* byte order */
+} BTREEINFO;
+
+#define	HASHMAGIC	0x061561
+#define	HASHVERSION	2
+
+/* Structure used to pass parameters to the hashing routines. */
+typedef struct {
+	u_int	bsize;		/* bucket size */
+	u_int	ffactor;	/* fill factor */
+	u_int	nelem;		/* number of elements */
+	u_int	cachesize;	/* bytes to cache */
+	u_int32_t		/* hash function */
+		(*hash) __P((const void *, size_t));
+	int	lorder;		/* byte order */
+} HASHINFO;
+
+/* Structure used to pass parameters to the record routines. */
+typedef struct {
+#define	R_FIXEDLEN	0x01	/* fixed-length records */
+#define	R_NOKEY		0x02	/* key not required */
+#define	R_SNAPSHOT	0x04	/* snapshot the input */
+	u_long	flags;
+	u_int	cachesize;	/* bytes to cache */
+	u_int	psize;		/* page size */
+	int	lorder;		/* byte order */
+	size_t	reclen;		/* record length (fixed-length records) */
+	u_char	bval;		/* delimiting byte (variable-length records */
+	char	*bfname;	/* btree file name */ 
+} RECNOINFO;
+
+#ifdef __DBINTERFACE_PRIVATE
+/*
+ * Little endian <==> big endian 32-bit swap macros.
+ *	M_32_SWAP	swap a memory location
+ *	P_32_SWAP	swap a referenced memory location
+ *	P_32_COPY	swap from one location to another
+ */
+#define	M_32_SWAP(a) {							\
+	u_int32_t _tmp = a;						\
+	((char *)&a)[0] = ((char *)&_tmp)[3];				\
+	((char *)&a)[1] = ((char *)&_tmp)[2];				\
+	((char *)&a)[2] = ((char *)&_tmp)[1];				\
+	((char *)&a)[3] = ((char *)&_tmp)[0];				\
+}
+#define	P_32_SWAP(a) {							\
+	u_int32_t _tmp = *(u_int32_t *)a;				\
+	((char *)a)[0] = ((char *)&_tmp)[3];				\
+	((char *)a)[1] = ((char *)&_tmp)[2];				\
+	((char *)a)[2] = ((char *)&_tmp)[1];				\
+	((char *)a)[3] = ((char *)&_tmp)[0];				\
+}
+#define	P_32_COPY(a, b) {						\
+	((char *)&(b))[0] = ((char *)&(a))[3];				\
+	((char *)&(b))[1] = ((char *)&(a))[2];				\
+	((char *)&(b))[2] = ((char *)&(a))[1];				\
+	((char *)&(b))[3] = ((char *)&(a))[0];				\
+}
+
+/*
+ * Little endian <==> big endian 16-bit swap macros.
+ *	M_16_SWAP	swap a memory location
+ *	P_16_SWAP	swap a referenced memory location
+ *	P_16_COPY	swap from one location to another
+ */
+#define	M_16_SWAP(a) {							\
+	u_int16_t _tmp = a;						\
+	((char *)&a)[0] = ((char *)&_tmp)[1];				\
+	((char *)&a)[1] = ((char *)&_tmp)[0];				\
+}
+#define	P_16_SWAP(a) {							\
+	u_int16_t _tmp = *(u_int16_t *)a;				\
+	((char *)a)[0] = ((char *)&_tmp)[1];				\
+	((char *)a)[1] = ((char *)&_tmp)[0];				\
+}
+#define	P_16_COPY(a, b) {						\
+	((char *)&(b))[0] = ((char *)&(a))[1];				\
+	((char *)&(b))[1] = ((char *)&(a))[0];				\
+}
+#endif
+
+__BEGIN_DECLS
+DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
+
+#ifdef __DBINTERFACE_PRIVATE
+DB	*__bt_open __P((const char *, int, int, const BTREEINFO *, int));
+DB	*__hash_open __P((const char *, int, int, const HASHINFO *, int));
+DB	*__rec_open __P((const char *, int, int, const RECNOINFO *, int));
+void	 __dbpanic __P((DB *dbp));
+#endif
+__END_DECLS
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_DB_H_ */
Index: trunk/src/emx/include/dirent.h
===================================================================
--- trunk/src/emx/include/dirent.h	(revision 18)
+++ trunk/src/emx/include/dirent.h	(revision 18)
@@ -0,0 +1,42 @@
+/* dirent.h (emx+gcc) */
+
+#ifndef _DIRENT_H
+#define _DIRENT_H
+
+#if !defined (_SYS_TYPES_H)
+#warning <dirent.h> requires <sys/types.h>
+#include <sys/types.h>
+#endif
+
+#include <sys/dirent.h>
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+struct _dirdesc;
+
+typedef struct _dirdesc DIR;
+
+DIR *opendir (__const__ char *);
+struct dirent *readdir (DIR *);
+int closedir (DIR *);
+void rewinddir (DIR *);
+
+#if !defined (_POSIX_SOURCE)
+void seekdir (DIR *, long);
+long telldir (DIR *);
+#endif
+
+DIR *_opendir (__const__ char *);
+struct dirent *_readdir (DIR *);
+void _seekdir (DIR *, long);
+long _telldir (DIR *);
+int _closedir (DIR *);
+void _rewinddir (DIR *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _DIRENT_H */
Index: trunk/src/emx/include/dos.h
===================================================================
--- trunk/src/emx/include/dos.h	(revision 18)
+++ trunk/src/emx/include/dos.h	(revision 18)
@@ -0,0 +1,69 @@
+/* dos.h (emx+gcc) */
+
+#ifndef _DOS_H
+#define _DOS_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_REGS)
+#define _REGS
+
+struct _dwordregs
+{
+  unsigned int eax;
+  unsigned int ebx;
+  unsigned int ecx;
+  unsigned int edx;
+  unsigned int esi;
+  unsigned int edi;
+  unsigned int eflags;
+};
+
+struct _wordregs
+{
+  unsigned short ax, h_ax;
+  unsigned short bx, h_bx;
+  unsigned short cx, h_cx;
+  unsigned short dx, h_dx;
+  unsigned short si, h_si;
+  unsigned short di, h_di;
+  unsigned short flags, h_flags;
+};
+
+struct _byteregs
+{
+  unsigned char al, ah, h_al, h_ah;
+  unsigned char bl, bh, h_bl, h_bh;
+  unsigned char cl, ch, h_cl, h_ch;
+  unsigned char dl, dh, h_dl, h_dh;
+};
+
+union REGS
+{
+  struct _dwordregs e;
+  struct _wordregs  x;
+  struct _byteregs  h;
+};
+
+struct SREGS
+{
+  unsigned int cs;
+  unsigned int ds;
+  unsigned int es;
+  unsigned int fs;
+  unsigned int gs;
+  unsigned int ss;
+};
+
+#endif
+
+int _int86 (int, __const__ union REGS *, union REGS *);
+void _segread (struct SREGS *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _DOS_H */
Index: trunk/src/emx/include/emx/asm386.h
===================================================================
--- trunk/src/emx/include/emx/asm386.h	(revision 18)
+++ trunk/src/emx/include/emx/asm386.h	(revision 18)
@@ -0,0 +1,74 @@
+/ emx/asm386.h (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <sys/errno.h>
+
+#define _xam fxam; fstsww %ax; andb $0x45, %ah
+
+#define j_nan cmpb $0x01, %ah; je
+#define j_inf cmpb $0x05, %ah; je
+
+/* MATHSUFFIX1 is for sin() vs. sinf() vs. _sinl() */
+/* MATHSUFFIX2 is for _sin() vs. _sinf() vs. _sinl() */
+/* MATHSUFFIX3 is for sin() vs. sinf() vs. sinl () */
+
+#if defined (LONG_DOUBLE)
+#define FLD fldt
+#define MATHSUFFIX1(X)   _##X##l
+#define MATHSUFFIX2(X)  _##X##l
+#define MATHSUFFIX3(X)  X##l
+#define CONV(X)
+#elif defined (FLOAT)
+#define FLD flds
+#define MATHSUFFIX1(X)  _##X##f
+#define MATHSUFFIX2(X)  _##X##f
+#define MATHSUFFIX3(X)  X##f
+#define CONV(X) fstps X; flds X
+#else
+#define FLD fldl
+#define MATHSUFFIX1(X)  X
+#define MATHSUFFIX2(X)  _##X
+#define MATHSUFFIX3(X)  X
+#define CONV(X) fstpl X; fldl X
+#endif
+
+#define LABEL0(name)    _##name
+#define LABEL(name)     LABEL0(name)
+
+#define ALIGN   .align  2, 0x90
+
+#if !defined (__MT__)
+
+#define SET_ERRNO_CONST(x) \
+        movl    x, _errno
+
+#else
+
+#define SET_ERRNO_CONST(x) \
+        call    __errno ;\
+        movl    x, (%eax)
+
+#endif
+
+#if defined (__GPROF__)
+#define PROFILE_FRAME	call __mcount
+#define PROFILE_NOFRAME	pushl %ebp; movl %esp, %ebp; call __mcount; popl %ebp
+#else
+#define PROFILE_FRAME
+#define PROFILE_NOFRAME
+#endif
+
+#if defined (__EPILOGUE__)
+#define EPILOGUE_NO_RET(name) LABEL(__POST$##name):
+#else
+#define EPILOGUE_NO_RET(name)
+#endif
+
+#define EPILOGUE(name) EPILOGUE_NO_RET (name) ret
+
+/* Cf. <math.h> */
+
+#define FP_ZERO         0
+#define FP_SUBNORMAL    1
+#define FP_NORMAL       2
+#define FP_INFINITE     3
+#define FP_NAN          4
Index: trunk/src/emx/include/emx/bigint.h
===================================================================
--- trunk/src/emx/include/emx/bigint.h	(revision 18)
+++ trunk/src/emx/include/emx/bigint.h	(revision 18)
@@ -0,0 +1,196 @@
+/* emx/bigint.h (emx+gcc) */
+
+/* Big integers, for internal use by the floating point conversion
+   routines only.  Do not use in application programs. */
+
+/* Number of bits in a _bi_word. */
+
+#define _BI_WORDSIZE    32
+
+/* Maximum value of a _bi_word. */
+
+#define _BI_WORDMAX     0xffffffff
+
+/* Bigints are made up of `digits' of this type. */
+
+typedef unsigned long _bi_word;
+
+/* This type must be exactly twice as big as a _bi_word. */
+
+typedef unsigned long long _bi_dword;
+
+/* Ditto, signed. */
+
+typedef signed long long _bi_sdword;
+
+/* A bigint. */
+
+typedef struct
+{
+  /* Number of used elements of v; either n is 0 or v[n-1] is
+     non-zero. */
+
+  int n;
+
+  /* The least significant word is stored in v[0] (unless n is 0). */
+
+  _bi_word *v;
+} _bi_bigint;
+
+/* Compute the number of words required for a bigint of BITS bits. */
+
+#define _BI_WORDS(bits) (((bits) + _BI_WORDSIZE - 1) / _BI_WORDSIZE)
+
+/* Declare a bigint variable named VAR of WORDS words.  The _BI_INIT
+   macro must be used (as statement) to initialize such a variable. */
+
+#define _BI_DECLARE(var,words) \
+  _bi_word var##__v[words]; \
+  _bi_bigint var
+
+/* Initialize a bigint variable defined with _BI_DECLARE.  This macro
+   should be used as statement. */
+
+#define _BI_INIT(var) (var.v = var##__v)
+
+/* For the following functions, source and destination bigints must be
+   distinct, unless documented otherwise . */
+
+/* Assign the word SRC to the bigint pointed to by DST (having space
+   for DST_WORDS words).  Return 0 on success, 1 on overflow. */
+
+int _bi_set_w (_bi_bigint *dst, int dst_words, _bi_word src);
+
+/* Assign the double word SRC to the bigint pointed to by DST (having
+   space for DST_WORDS words).  Return 0 on success, 1 on overflow. */
+
+int _bi_set_d (_bi_bigint *dst, int dst_words, _bi_dword src);
+
+/* Assign the bigint pointed to by SRC to the bigint pointed to by DST
+   (having space for DST_WORDS words).  Return 0 on success, 1 on
+   overflow. */
+
+int _bi_set_b (_bi_bigint *dst, int dst_words, const _bi_bigint *src);
+
+/* Compare the bigint pointed to by SRC1 to the bigint pointed to by
+   SRC2.  Return 1 if the first bigint is bigger than the second
+   bigint, 0 if the bigints are equal, or -1 if the first bigint is
+   smaller than the second one. */
+
+int _bi_cmp_bb (const _bi_bigint *src1, const _bi_bigint *src2);
+
+/* Compare the bigint pointed to by SRC1 to 2^SHIFT2.  SHIFT2 may be
+   negative.  Return 1 if the bigint is bigger than the power of two,
+   0 if the numbers are equal, or -1 if the bigint is smaller than the
+   power of two. */
+
+int _bi_cmp_pow2 (const _bi_bigint *src1, int shift2);
+
+/* Add the bigints pointed to by SRC1 and SRC2, storing the result to
+   the bigint pointed to by DST (having space for DST_WORDS words).
+   DST may point to the same bigint as SRC1 or SRC2.  Return 0 on
+   success, 1 on overflow. */
+
+int _bi_add_bb (_bi_bigint *dst, int dst_words,
+                const _bi_bigint *src1, const _bi_bigint *src2);
+
+/* Subtract from the bigint pointed to by DST the product of FACTOR
+   and the bigint pointed to by SRC.  Return 0 on success.  Return 1
+   and leave the bigint pointed to by DST unchanged if the result
+   would be negative. */
+   
+int _bi_sub_mul_bw (_bi_bigint *dst, const _bi_bigint *src, _bi_word factor);
+
+/* Shift left the word SRC by SHIFT bits (SHIFT >= 0) and store the
+   result to the bigint pointed to by DST (having space for DST_WORDS
+   words).  Return 0 on success, 1 on overflow. */
+
+int _bi_shl_w (_bi_bigint *dst, int dst_words, _bi_word src, int shift);
+
+/* Shift left the bigint pointed to by SRC by SHIFT bits (SHIFT >= 0)
+   and store the result to the bigint pointed to by DST (having space
+   for DST_WORDS words).  DST may point to the same bigint as SRC.
+   Return 0 on success, 1 on overflow. */
+
+int _bi_shl_b (_bi_bigint *dst, int dst_words,
+               const _bi_bigint *src, int shift);
+
+/* Shift right the bigint pointed to by SRC by SHIFT bits (SHIFT >= 0)
+   and store the result to the bigint pointed to by DST (having space
+   for DST_WORDS words).  DST may point to the same bigint as SRC.
+   Return 0 on success, 1 on overflow. */
+
+int _bi_shr_b (_bi_bigint *dst, int dst_words, const _bi_bigint *src,
+               int shift);
+
+/* Store the product of the word FACTOR and the bigint pointed to by
+   SRC to the bigint pointed to by DST (having space for DST_WORDS
+   words).  DST may point to the same bigint as SRC.  Return 0 on
+   success, 1 on overflow. */
+
+int _bi_mul_bw (_bi_bigint *dst, int dst_words,
+                const _bi_bigint *src, _bi_word factor);
+
+/* Store the product of the bigints pointed to by SRC1 and SRC2 to the
+   bigint pointed to by DST (having space for DST_WORDS words).
+   Return 0 on success, 1 on overflow.  The check for overflow is not
+   based on the actual values of the bigints, only on their size. */
+
+int _bi_mul_bb (_bi_bigint *dst, int dst_words,
+                const _bi_bigint *src1, const _bi_bigint *src2);
+
+/* Divide the bigint pointed to by NUM by the bigint pointed to by
+   DEN.  Replace NUM with the remainder of the division, return the
+   quotient.  The quotient must fit in _BI_WORDSIZE-1 bits. */
+
+_bi_word _bi_hdiv_rem_b (_bi_bigint *num, const _bi_bigint *den);
+
+/* Divide the bigint pointed to by NUM by 2^SHIFT (SHIFT >= 0).
+   Replace NUM with the remainder of the division, return the
+   quotient.  The quotient must fit in a _bi_word. */
+
+_bi_word _bi_wdiv_rem_pow2 (_bi_bigint *num, int shift);
+
+/* Compute the product of 5^EXP, 2^SHIFT, and the bigint pointed to by
+   FACTOR.  0 <= EXP <= 4951 (5039, actually), 0 <= SHIFT.  If FACTOR
+   is NULL, the factor is taken to be one.  Store the result to the
+   bigint pointed to by DST (having space for DST_WORDS words).
+   Return 0 on success, 1 on overflow. */
+
+int _bi_pow5 (_bi_bigint *dst, int dst_words,
+              int exp, int shift, const _bi_bigint *factor);
+
+/* Return the number of the most significant set bit of the bigint
+   pointed to by SRC.  The least significant bit is numbered 1.
+   Return 0 if the bigint is zero. */
+
+int _bi_fls (const _bi_bigint *src);
+
+/* Divide the bigint pointed to by NUM by the word DEN.  Store the
+   quotient to the bigint pointed to by QUOT (having space for
+   QUOT_WORDS words) and store the remainder to the word pointed by
+   REM.  Return 0 on success, 1 on overflow or division by zero. */
+
+int _bi_div_rem_bw (_bi_bigint *quot, int quot_words, _bi_word *rem,
+                    const _bi_bigint *num, _bi_word den);
+
+/* Divide the bigint pointed to by NUM_REM by the bigint pointed to by
+   DEN.  Store the quotient to the bigint pointed to by QUOT (having
+   space for QUOT_WORDS words) and store the remainder to the bigint
+   pointed by NUM_REM (having space for NUM_REM_WORDS words, replacing
+   the numerator).  There must be at least one extra word available in
+   the bigint pointed to by NUM_REM.  Return 0 on success, 1 on
+   overflow or division by zero. */
+
+int _bi_div_rem_bb (_bi_bigint *num_rem, int num_rem_words,
+                    _bi_bigint *quot, int quot_words,
+                    const _bi_bigint *den);
+
+/* Divide the bigint pointed to by NUM_REM by 2^SHIFT (SHIFT >= 0).
+   Store the quotient to the bigint pointed to by QUOT (having space
+   for QUOT_WORDS words) and store the remainder to the bigint pointed
+   by NUM_REM (replacing the numerator).  Return 0 on success, 1 on
+   overflow. */
+
+int _bi_div_rem_pow2 (_bi_bigint *num_rem, _bi_bigint *quot, int quot_words,
+                      int shift);
Index: trunk/src/emx/include/emx/emxload.h
===================================================================
--- trunk/src/emx/include/emx/emxload.h	(revision 18)
+++ trunk/src/emx/include/emx/emxload.h	(revision 18)
@@ -0,0 +1,46 @@
+/* emx/emxload.h (emx+gcc) */
+
+#ifndef _EMX_EMXLOAD_H
+#define _EMX_EMXLOAD_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define _EMXLOAD_LOAD           1
+#define _EMXLOAD_UNLOAD         2
+#define _EMXLOAD_STOP           3
+#define _EMXLOAD_CONNECT        4
+#define _EMXLOAD_DISCONNECT     5
+#define _EMXLOAD_UNLOAD_WAIT    6
+#define _EMXLOAD_STOP_WAIT      7
+#define _EMXLOAD_LIST           8
+
+#define _EMXLOAD_PIPENAME       "/pipe/emx/emxload"
+
+typedef struct
+{
+  int req_code;
+  int seconds;
+  char name[260];
+} request;
+
+typedef struct
+{
+  int ans_code;
+  int seconds;
+  char name[260];
+} answer;
+
+int _emxload_request (int req_code, const char *name, int seconds);
+int _emxload_do_connect (int start);
+int _emxload_do_disconnect (int force);
+int _emxload_do_request (int req_code, const char *name, int seconds);
+int _emxload_do_receive (answer *ans);
+int _emxload_do_wait (void);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_EMXLOAD_H */
Index: trunk/src/emx/include/emx/float.h
===================================================================
--- trunk/src/emx/include/emx/float.h	(revision 18)
+++ trunk/src/emx/include/emx/float.h	(revision 18)
@@ -0,0 +1,46 @@
+/* emx/float.h (emx+gcc) */
+
+#ifndef _EMX_FLOAT_H
+#define _EMX_FLOAT_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define FX_P_NAN       1
+#define FX_N_NAN       3
+#define FX_P_NORMAL    4
+#define FX_P_INFINITY  5
+#define FX_N_NORMAL    6
+#define FX_N_INFINITY  7
+#define FX_P_ZERO      8
+#define FX_P_EMPTY     9
+#define FX_N_ZERO     10
+#define FX_N_EMPTY    11
+#define FX_P_DENORMAL 12
+#define FX_N_DENORMAL 14
+
+#define DTOA_PRINTF_E   0
+#define DTOA_PRINTF_F   1
+#define DTOA_PRINTF_G   2
+#define DTOA_GCVT       3
+
+const char * __atod (long double *p_result, const char *string,
+                     int min_exp, int max_exp, int bias,
+                     int mant_dig, int decimal_dig,
+                     int max_10_exp, int min_den_10_exp);
+
+char *__dtoa (char *buffer, int *p_exp, long double x, int ndigits,
+              int fmt, int dig);
+
+void __remove_zeros (char *digits, int keep);
+
+int _fxam (double);
+int _fxaml (long double);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_FLOAT_H */
Index: trunk/src/emx/include/emx/io.h
===================================================================
--- trunk/src/emx/include/emx/io.h	(revision 18)
+++ trunk/src/emx/include/emx/io.h	(revision 18)
@@ -0,0 +1,253 @@
+/* emx/io.h (emx+gcc) */
+
+#ifndef _EMX_IO_H
+#define _EMX_IO_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+/* Low-level i/o */
+
+/*      O_ACCMODE   0x00000003 */
+/*      O_NDELAY    0x00000004 */
+/*      O_APPEND    0x00000008 */
+/*      O_TEXT      0x00000010 */
+#define F_EOF       0x00000020
+#define F_TERMIO    0x00000040
+#define F_DEV       0x00000080
+/*      O_BINARY    0x00000100 */
+/*      O_CREAT     0x00000200 */
+/*      O_TRUNC     0x00000400 */
+/*      O_EXCL      0x00000800 */
+/*      O_NOINHERIT 0x00001000 */
+/*      O_SYNC      0x00002000 */
+/*      O_NOCTTY    0x00004000 */
+/*      O_SIZE      0x00008000 */
+#define F_SOCKET    0x10000000
+#define F_PIPE      0x20000000
+#define F_WRCRPEND  0x40000000
+#define F_CRLF      0x80000000
+
+/* stdio */
+
+/*      _IOREAD     0x00000001 */
+/*      _IOWRT      0x00000002 */
+/*      _IORW       0x00000004 */
+/*      _IOEOF      0x00000008 */
+/*      _IOERR      0x00000010 */
+/*      _IOLBF      0x00000020 */
+/*      _IONBF      0x00000040 */
+
+/* This bit is set if the stream is open. */
+
+#define _IOOPEN     0x00000080
+
+/* Mask for the buffer type. */
+
+#define _IOBUFMASK  0x00000700
+
+/* This buffer type is set until a buffer has been assigned. */
+
+#define _IOBUFNONE  0x00000000
+
+/* This buffer type is set by setvbuf() if a user-allocated buffer is
+   used. */
+
+#define _IOBUFUSER  0x00000100
+
+/* This buffer type is set by _fbuf() if a single-character buffer is
+   used. */
+
+#define _IOBUFCHAR  0x00000200
+
+/* This buffer type is set by _fbuf() if the stream buffer has been
+   allocated by the library, with malloc().  The buffer will be
+   deallocated by fclose(). */
+
+#define _IOBUFLIB   0x00000300
+
+/* This buffer type is set by _tmpbuf1() to indicate that a temporary
+   buffer has been assigned to the stream. */
+
+#define _IOBUFTMP   0x00000400
+
+/* This bit is set by tmpfile() to indicate a temporary file, to be
+   deleted by fclose(). */
+
+#define _IOTMP      0x00000800
+
+/* This bit is set for special streams which don't have an underlying
+   file. */
+
+#define _IOSPECIAL  0x00001000
+
+/* This bit is set by ungetc() to indicate that pushed-back characters
+   have been stored to the stream buffer -- fseek() must cause the
+   buffer to be reread. */
+
+#define _IOUNGETC   0x00002000
+
+/* This bit is set by _newstream() to avoid reusing the same slot in
+   another thread. */
+
+#define _IONEW      0x00004000
+
+/* This bit is set for byte-oriented streams. */
+
+#define _IOBYTE     0x00008000
+
+/* This bit is set for wide-oriented streams. */
+
+#define _IOWIDE     0x00010000
+
+
+#define _FLUSH_FLUSH  (-1)
+#define _FLUSH_FILL   (-2)
+
+struct _FILE;
+
+struct _file2
+{
+  struct _FILE *owner;
+#if defined (_SYS_RMUTEX_H)
+  _rmutex rsem;
+#else
+  char rsem_ersatz[16];
+#endif
+};
+
+#define nbuf(s) (((s)->_flags & _IOBUFMASK) == _IOBUFNONE)
+#define cbuf(s) (((s)->_flags & _IOBUFMASK) == _IOBUFCHAR)
+#define ubuf(s) (((s)->_flags & _IOBUFMASK) == _IOBUFUSER)
+#define lbuf(s) (((s)->_flags & _IOBUFMASK) == _IOBUFLIB)
+#define tbuf(s) (((s)->_flags & _IOBUFMASK) == _IOBUFTMP)
+
+#define bbuf(s) (ubuf (s) || lbuf (s) || tbuf (s))
+
+#define _tmpbuf(s,b) (nbuf (s) || cbuf (s) \
+                      ? b = alloca (BUFSIZ), _tmpbuf1 (s, b) : 0)
+#define _endbuf(s) (tbuf (s) ? _endbuf1 (s) : 0)
+
+#define alloca(x) __builtin_alloca(x)
+
+struct streamvec
+{
+  struct _FILE *vec;
+  struct streamvec *next;
+  int n;
+};
+
+struct fdvec
+{
+  int *flags;
+  int *lookahead;
+  struct fdvec *next;
+  int n;
+};
+
+extern struct streamvec _streamvec_head;
+
+extern int _io_ninherit;
+extern struct fdvec _fdvec_head;
+
+#if defined (__MT__)
+
+/* This is currently used only in the multi-thread libraries.  We
+   can't use and reallocate a single array because rmutex semaphores
+   cannot be moved. */
+
+struct streamvec2
+{
+  struct _file2 *vec;
+  struct streamvec2 *next;
+  int n;
+};
+
+extern struct streamvec2 _streamvec2_head;
+
+#if defined (_SYS_RMUTEX_H)
+
+/* This semaphore (defined in app/stdio.c) protects _streamv[].  Only
+   concurrent access by _newstream(), _setmore(), and freopen() in
+   different threads must be prevented to avoid using one element of
+   _streamv[] for multiple streams (in different threads).  All other
+   functions may concurrently access _streamv[], even concurrently to
+   _newstream(), _setmore(), and freopen(). */
+
+extern _rmutex _streamv_rmutex;
+
+#define STREAMV_LOCK    _rmutex_checked_request (&_streamv_rmutex, _FMR_IGNINT)
+#define STREAMV_UNLOCK  _rmutex_checked_release (&_streamv_rmutex)
+
+#define STREAM_LOCK(f) \
+  (_rmutex_request (&(f)->_more->rsem, _FMR_IGNINT) != 0 \
+   ? abort () : (void)0)
+
+#define STREAM_UNLOCK(f) \
+  (_rmutex_release (&(f)->_more->rsem) != 0 ? abort () : (void)0)
+
+#define STREAM_LOCK_NOWAIT(f) \
+  (_rmutex_request (&(f)->_more->rsem, _FMR_NOWAIT) == 0)
+
+#define STREAM_UNLOCKED(f) _rmutex_available (&(f)->_more->rsem)
+
+#endif /* defined (_SYS_RMUTEX_H) */
+
+#else /* !defined (__MT__) */
+
+#define STREAMV_LOCK            (void)0
+#define STREAMV_UNLOCK          (void)0
+
+#define STREAM_LOCK(f)          (void)0
+#define STREAM_UNLOCK(f)        (void)0
+#define STREAM_LOCK_NOWAIT(f)   1
+#define STREAM_UNLOCKED(f)      1
+
+#endif /* !defined (__MT__) */
+
+
+int _endbuf1 (struct _FILE *);
+void _fbuf (struct _FILE *);
+int *_fd_flags (int);
+int *_fd_init (int);
+int *_fd_lookahead (int);
+struct _FILE *_fopen (struct _FILE *, __const__ char *, __const__ char *,
+    int, int);
+int _flushstream (struct _FILE *, int);
+void _closestream (struct _FILE *);
+int _fflush_nolock (struct _FILE *);
+int _fseek_nolock (struct _FILE *, long, int);
+long _ftell_nolock (struct _FILE *);
+size_t _fwrite_nolock (const void *, size_t, size_t, struct _FILE *);
+int _input (struct _FILE *, __const__ char *, char *);
+struct _FILE *_newstream (void);
+int _output (struct _FILE *, __const__ char *, char *);
+void _setdummymore (struct _FILE *, struct _file2 *);
+int _setmore (struct _FILE *, int);
+int _stream_read (int, void *, size_t);
+int _stream_write (int, __const__ void *, size_t);
+int _tmpbuf1 (struct _FILE *, void *);
+int _trslash (__const__ char *, size_t, int);
+int _ungetc_nolock (int, struct _FILE *);
+int _vsopen (__const__ char *, int, int, char *);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_IO_H */
Index: trunk/src/emx/include/emx/locale.h
===================================================================
--- trunk/src/emx/include/emx/locale.h	(revision 18)
+++ trunk/src/emx/include/emx/locale.h	(revision 18)
@@ -0,0 +1,115 @@
+/* emx/locale.h (emx+gcc) */
+
+#ifndef _EMX_LOCALE_H
+#define _EMX_LOCALE_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+struct lconv;
+
+/* Multibyte characters (locale-specific) */
+
+#define _MB_8BITS     0         /* No multibyte characters */
+#define _MB_DBCS      1         /* OS/2 double-byte character set */
+#define _MB_SHIFT     2         /* Some sort of encoding with shift states */
+#define _MB_UTF_2     3         /* UTF-2 */
+
+struct _mbyte
+{
+  unsigned char mode;           /* _MB_8BITS etc. */
+};
+
+extern struct _mbyte _cur_mbyte;
+
+int _mbtowc (wchar_t *, __const__ char *, size_t, int *);
+int _wctomb (char *, wchar_t, size_t, int *);
+
+/* locales and strftime() */
+
+struct _lcf_time
+{
+  char *months1[12];
+  char *months2[12];
+  char *wdays1[12];
+  char *wdays2[12];
+  char *date_time_fmt;
+  char *date_fmt;
+  char *time_fmt;
+  char *am, *pm;
+};
+
+/* These structures contain character arrays instead of character
+   pointers to be able to read them from a file (future extension). */
+
+struct lc_collate
+{
+  char dummy;
+};
+
+struct lc_ctype
+{
+  char dummy;
+};
+
+struct lc_monetary
+{
+  char int_curr_symbol[6];
+  char currency_symbol[7];
+  char mon_decimal_point[2];
+  char mon_thousands_sep[2];
+  char mon_grouping[2];
+  char positive_sign[2];
+  char negative_sign[2];
+  char int_frac_digits;
+  char frac_digits;
+  char p_cs_precedes;
+  char p_sep_by_space;
+  char n_cs_precedes;
+  char n_sep_by_space;
+  char p_sign_posn;
+  char n_sign_posn;
+};
+
+struct lc_numeric
+{
+  char decimal_point[2];
+  char thousands_sep[2];
+  char grouping[2];
+};
+
+struct lc_time
+{
+  char months1[48];             /* 12 abb. month names, null-terminated */
+  char months2[128];            /* 12 month names, null-terminated */
+  char wdays1[32];              /* 7 abb. week day names, null-terminated */
+  char wdays2[80];              /* 7 week days, null-terminated */
+  char date_time_fmt[24];       /* strftime() format for %c */
+  char date_fmt[12];            /* strftime() format for %x */
+  char time_fmt[12];            /* strftime() format for %X */
+  char am[3];                   /* AM indicator for %p */
+  char pm[3];                   /* PM indicator for %p */
+};
+
+struct lc_data
+{
+  char               *name;
+  struct lc_collate  *collate;
+  struct lc_ctype    *ctype;
+  struct lc_monetary *monetary;
+  struct lc_numeric  *numeric;
+  struct lc_time     *time;
+};
+
+
+extern struct _lcf_time _cur_lcf_time;
+extern struct lconv _cur_lconv;
+extern const struct lc_data _lc_table[];
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_LOCALE_H */
Index: trunk/src/emx/include/emx/nls.h
===================================================================
--- trunk/src/emx/include/emx/nls.h	(revision 18)
+++ trunk/src/emx/include/emx/nls.h	(revision 18)
@@ -0,0 +1,18 @@
+/* emx/nls.h (emx+gcc) */
+
+#ifndef _EMX_NLS_H
+#define _EMX_NLS_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+void _nls_ctype_init (void);
+void _nls_tolower_init (void);
+void _nls_toupper_init (void);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_NLS_H */
Index: trunk/src/emx/include/emx/pwd.h
===================================================================
--- trunk/src/emx/include/emx/pwd.h	(revision 18)
+++ trunk/src/emx/include/emx/pwd.h	(revision 18)
@@ -0,0 +1,19 @@
+/* emx/pwd.h (emx+gcc) */
+
+#ifndef _EMX_PWD_H
+#define _EMX_PWD_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+struct passwd;
+
+struct passwd *_getpw (int, __const__ char *);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_PWD_H */
Index: trunk/src/emx/include/emx/startup.h
===================================================================
--- trunk/src/emx/include/emx/startup.h	(revision 18)
+++ trunk/src/emx/include/emx/startup.h	(revision 18)
@@ -0,0 +1,39 @@
+/* emx/startup.h (emx+gcc) */
+
+#ifndef _EMX_STARTUP_H
+#define _EMX_STARTUP_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* argv[i][-1] contains some flag bits: */
+
+#define _ARG_DQUOTE   0x01          /* Argument quoted (")                  */
+#define _ARG_RESPONSE 0x02          /* Argument read from response file     */
+#define _ARG_WILDCARD 0x04          /* Argument expanded from wildcard      */
+#define _ARG_ENV      0x08          /* Argument from environment            */
+#define _ARG_NONZERO  0x80          /* Always set, to avoid end of string   */
+
+/* Arrange that FUN will be called by _startup(). */
+
+#define _CRT_INIT1(fun) __asm__ (".stabs \"___crtinit1__\", 23, 0, 0, _" #fun);
+
+/* Arrange that FUN will be called by _cleanup(). */
+
+#define _CRT_EXIT1(fun) __asm__ (".stabs \"___crtexit1__\", 23, 0, 0, _" #fun);
+
+extern void (*_atexit_v[64])(void);
+extern int _atexit_n;
+
+extern char ** _org_environ;
+
+extern char _cdll_flag;
+
+void _cleanup (void);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_STARTUP_H */
Index: trunk/src/emx/include/emx/syscalls.h
===================================================================
--- trunk/src/emx/include/emx/syscalls.h	(revision 18)
+++ trunk/src/emx/include/emx/syscalls.h	(revision 18)
@@ -0,0 +1,238 @@
+/* emx/syscalls.h (emx+gcc) */
+
+#ifndef _EMX_SYSCALLS_H
+#define _EMX_SYSCALLS_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* __findfirst(), __findnext() */
+
+#define _A_NORMAL 0x00  /* No attributes */
+#define _A_RDONLY 0x01  /* Read-only     */
+#define _A_HIDDEN 0x02  /* Hidden        */
+#define _A_SYSTEM 0x04  /* System        */
+#define _A_VOLID  0x08  /* Volume label  */
+#define _A_SUBDIR 0x10  /* Directory     */
+#define _A_ARCH   0x20  /* Archive       */
+
+/* __open() */
+
+#define _SO_CREAT       0x00010000
+#define _SO_EXCL        0x00020000
+#define _SO_TRUNC       0x00040000
+#define _SO_NOINHERIT   0x00080000
+#define _SO_SYNC        0x00100000
+#define _SO_SIZE        0x00200000
+
+/* For debugging of signal handlers. */
+#define _SIG_MAGIC1     0xfeed6666
+#define _SIG_MAGIC2     0x47dead11
+#define _SIG_MAGIC3     0x9999beef
+#define _SIG_MAGIC4     0xaffe0815
+
+#if !defined (_SIGSET_T)
+#define _SIGSET_T
+typedef unsigned long sigset_t;
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+
+struct hostent;
+struct netent;
+struct protoent;
+struct servent;
+struct sigaction;
+struct sockaddr;
+struct stat;
+struct timeb;
+struct timeval;
+struct _fd_set;
+
+struct _find
+{
+  char           reserved[21];
+  unsigned char  attr;
+  unsigned short time;
+  unsigned short date;
+  unsigned short size_lo;         /* split due to alignment problems */
+  unsigned short size_hi;
+  char name[257];                 /* Big buffer for OS/2             */
+};
+
+struct _new_proc
+{
+  unsigned long  arg_off;
+  unsigned long  env_off;
+  unsigned long  fname_off;
+  unsigned short arg_sel;
+  unsigned short env_sel;
+  unsigned short fname_sel;
+  unsigned short arg_count;
+  unsigned short arg_size;
+  unsigned short env_count;
+  unsigned short env_size;
+  unsigned short mode;
+  unsigned short mode2;         /* Present only if (mode & 0x8000) */
+};
+
+struct _profil
+{
+  unsigned cb;
+  void *buff;
+  unsigned bufsiz;
+  unsigned offset;
+  unsigned scale;
+};
+
+struct _recvfrom
+{
+  int handle;
+  void *buf;
+  int len;
+  unsigned flags;
+  struct sockaddr *from;
+  int *pfromlen;
+};
+
+struct _select
+{
+  int              nfds;
+  struct _fd_set * readfds;
+  struct _fd_set * writefds;
+  struct _fd_set * exceptfds;
+  struct timeval * timeout;
+};
+
+struct _sendto
+{
+  int handle;
+  __const__ void *buf;
+  int len;
+  unsigned flags;
+  __const__ struct sockaddr *to;
+  int tolen;
+};
+
+
+int __accept (int handle, struct sockaddr *addr, int *paddrlen);
+unsigned __alarm (unsigned sec);
+int __bind (int handle, __const__ struct sockaddr *addr, int addrlen);
+void *__brk (void *addr);
+void __cgets (char *buffer);
+int __chdir (__const__ char *name);
+int __chmod (__const__ char *name, int flag, int attr);
+int __chdrive (char drive);
+int __chsize (int handle, long length);
+long long __clock (void);
+int __close (int handle);
+int __connect (int handle, __const__ struct sockaddr *addr, int addrlen);
+int __core (int handle);
+int __dup (int handle);
+int __dup2 (int handle1, int handle2);
+int __endthread (int tid);
+int __execname (char *buf, size_t bufsize);
+void __exit (int ret) __attribute__ ((__noreturn__));
+int __fcntl (int handle, int request, int arg);
+int __filesys (__const__ char *drive, char *name, size_t size);
+int __findfirst (__const__ char *name, int attr, struct _find *fp);
+int __findnext (struct _find *fp);
+int __fork (void);
+int __fstat (int handle, struct stat *buffer);
+int __fsync (int handle);
+void __ftime (struct timeb *ptr);
+int __ftruncate (int handle, long length);
+int __getcwd (char *buffer, char drive);
+char __getdrive (void);
+int __gethostbyaddr (__const__ char *addr, int len, int type,
+    struct hostent **dst);
+int __gethostbyname (__const__ char *name, struct hostent **dst);
+int __gethostid (int *dst);
+int __gethostname (char *name, int len);
+int __getnetbyname (__const__ char *name, struct netent **dst);
+int __getnetbyaddr (long net, struct netent **dst);
+int __getpeername (int handle, struct sockaddr *name, int *pnamelen);
+int __getpid (void);
+int __getppid (void);
+int __getprotobyname (__const__ char *name, struct protoent **dst);
+int __getprotobynumber (int prot, struct protoent **dst);
+int __getservbyname (__const__ char *name, __const__ char *proto,
+    struct servent **dst);
+int __getservbyport (int port, __const__ char *proto, struct servent **dst);
+int __getsockhandle (int handle);
+int __getsockname (int handle, struct sockaddr *name, int *pnamelen);
+int __getsockopt (int handle, int level, int optname, void *optval,
+    int *poptlen);
+int __imphandle (int handle);
+int __impsockhandle (int handle, int flags);
+int __initthread (void *preg);
+int __ioctl1 (int handle, int code);
+int __ioctl2 (int handle, int request, int arg);
+int __kill (int pid, int sig);
+int __listen (int handle, int backlog);
+int __lseek (int handle, long offset, int origin);
+void *__memaccess (unsigned first, unsigned last, int flag);
+int __memavail (void);
+int __mkdir (__const__ char *name);
+int __newthread (int tid);
+int __nls_ctype (unsigned char *buf);
+void __nls_memupr (unsigned char *buf, size_t size);
+int __open (__const__ char *name, int flags, unsigned long size);
+void __pause (void);
+int __pipe (int *two_handles, int pipe_size);
+int __portaccess (unsigned first, unsigned last);
+int __profil (__const__ struct _profil *p);
+int __ptrace (int request, int pid, int addr, int data);
+int __raise (int sig);
+int __read (int handle, void *buf, size_t nbyte);
+int __read_kbd (int echo, int wait, int sig);
+int __recv (int handle, void *buf, int len, unsigned flags);
+int __recvfrom (__const__ struct _recvfrom *args);
+int __remove (__const__ char *name);
+int __rename (__const__ char *old_name, __const__ char *new_name);
+int __rmdir (__const__ char *name);
+void *__sbrk (int incr);
+void __scrsize (int *dst);
+int __select (struct _select *args);
+int __send (int handle, __const__ void *buf, int len, unsigned flags);
+int __sendto (__const__ struct _sendto *args);
+int __setsockopt (int handle, int level, int optname, __const__ void *optval,
+    int optlen);
+int __setsyserrno (int e);
+int __settime (const struct timeval *tp);
+int __shutdown (int handle, int how);
+int __sigaction (int _sig, __const__ struct sigaction *_iact,
+    struct sigaction *_oact);
+void (*__signal (int sig, void (*handler)()))(int sig);
+int __sigpending (sigset_t *_set);
+int __sigprocmask (int _how, __const__ sigset_t *_iset, sigset_t *_oset);
+int __sigsuspend (__const__ sigset_t *_mask);
+unsigned __sleep (unsigned sec);
+unsigned __sleep2 (unsigned millisec);
+int __socket (int domain, int type, int protocol);
+int __spawnve (struct _new_proc *np);
+int __stat (__const__ char *name, struct stat *buffer);
+int __swchar (int flag, int new_char);
+int __syserrno (void);
+int __uflags (int mask, int new_flags);
+long __ulimit (int cmd, long new_limit);
+int __umask (int pmode);
+void __unwind2 (void *xcpt_reg_ptr);
+int __utimes (__const__ char *name, __const__ struct timeval *tvp);
+int __ttyname (int handle, char *buf, size_t buf_size);
+int __wait (int *status);
+int __waitpid (int pid, int *status, int options);
+int __write (int handle, __const__ void *buf, size_t nbyte);
+
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_SYSCALLS_H */
Index: trunk/src/emx/include/emx/thread.h
===================================================================
--- trunk/src/emx/include/emx/thread.h	(revision 18)
+++ trunk/src/emx/include/emx/thread.h	(revision 18)
@@ -0,0 +1,62 @@
+/* emx/thread.h (emx+gcc) */
+
+#ifndef _EMX_THREAD_H
+#define _EMX_THREAD_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined (__MT__)
+
+#if !defined (_TM)
+#define _TM
+struct tm         /* cf. <time.h> */
+{
+  int tm_sec;     /* 0..59 */
+  int tm_min;     /* 0..59 */
+  int tm_hour;    /* 0..23 */
+  int tm_mday;    /* 1..31 */
+  int tm_mon;     /* 0..11 */
+  int tm_year;    /* 0(:=1900).. */
+  int tm_wday;    /* 0..6 */
+  int tm_yday;    /* 0..365 */
+  int tm_isdst;   /* 0 */
+};
+#endif
+
+struct _uheap;
+
+struct _thread
+{
+  int             _th_errno;                /* comes first, cf. errnofun.s */
+  void          * _th_arg;
+  void          (*_th_start)(void *);
+  unsigned char * _th_strtok_ptr;
+  char            _th_asctime_buf[26+2];    /* 2 chars for padding */
+  char            _th_tmpnam_buf[16];       /* cf. stdio.h */
+  struct tm       _th_gmtime_buf;
+  unsigned int    _th_rand;                 /* Used by rand() */
+  void          * _th_store;                /* Pointer to user data */
+  int             _th_mblen_shift;          /* Shift state for mblen() */
+  int             _th_mbtowc_shift;         /* Shift state for mbtowc() */
+  int             _th_wctomb_shift;         /* Shift state for wctomb() */
+  char            _th_vollabel[12];         /* Used by _getvol() */
+  char            _th_error[28];            /* Used by strerror() */
+  struct _uheap * _th_rheap;                /* Default regular heap */
+  struct _uheap * _th_theap;                /* Default tiled heap */
+  char            _th_ttyname[32];          /* Used by ttyname() */
+  char            _th_inetntoa[16];         /* Used by inetntoa() */
+  int             _th_reserved[971];        /* 4096 bytes, total */
+};
+
+struct _thread *_thread (void);
+
+#endif /* defined (__MT__) */
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_THREAD_H */
Index: trunk/src/emx/include/emx/time.h
===================================================================
--- trunk/src/emx/include/emx/time.h	(revision 18)
+++ trunk/src/emx/include/emx/time.h	(revision 18)
@@ -0,0 +1,56 @@
+/* emx/time.h (emx+gcc) */
+
+#ifndef _EMX_TIME_H
+#define _EMX_TIME_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define _YEARS          (2106 - 1970 + 1)
+#define TIME_T_MAX      0xffffffffUL
+
+#if !defined (_TIME_T)
+#define _TIME_T
+typedef unsigned long time_t;
+#endif
+
+struct tm;
+
+struct _tzinfo
+{
+  char tzname[4];
+  char dstzname[4];
+  int tz, dst, shift;
+  int sm, sw, sd, st;
+  int em, ew, ed, et;
+};
+
+extern int _tzset_flag;
+extern struct _tzinfo _tzi;
+
+extern int const _year_day[_YEARS+1];
+extern int const _month_day_leap[];
+extern int const _month_day_non_leap[];
+
+
+int _day (int, int, int);
+int _gmt2loc (unsigned long *);
+int _loc2gmt (unsigned long *, int);
+struct tm *_gmtime (struct tm *, const time_t *);
+struct tm *_localtime (struct tm *, const time_t *);
+unsigned long _mktime (struct tm *);
+void _compute_dst_table (void);
+
+
+static __inline__ int _leap_year (unsigned y)
+{
+  return (y % 4 != 0 ? 0 : y % 100 != 0 ? 1 : y % 400 != 0 ? 0 : 1);
+}
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_TIME_H */
Index: trunk/src/emx/include/emx/umalloc.h
===================================================================
--- trunk/src/emx/include/emx/umalloc.h	(revision 18)
+++ trunk/src/emx/include/emx/umalloc.h	(revision 18)
@@ -0,0 +1,776 @@
+/* emx/umalloc.h (emx+gcc) */
+
+#ifndef _EMX_UMALLOC_H
+#define _EMX_UMALLOC_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* =========================== Introduction =========================== */
+
+/* This implementation of malloc() uses two different allocation
+   schemes, one for small blocks, one for big blocks.  Small blocks
+   are allocated from special big blocks, big blocks are made up of
+   fixed-sized pages to reduce fragmentation.
+
+   Glossary:
+
+   heap         A set of non-contiguous segments along with various
+                control information.  This is the entity passed by the
+                user to _umalloc() etc.  Each heap starts with a
+                struct _uheap.  Heap_t points to a heap.
+
+   segment      A contiguous area of memory made up of pages and
+                organized in lumps.  This is used for allocating big
+                blocks and for allocating crates.  Each segment starts
+                with a struct _um_seg; the rest of the segment is
+                divided into pages and used for lumps.
+
+   lump         A contiguous set of pages.  A lump is either free or
+                allocated.  An allocated lump is either used for a
+                user block or for a crate.  The first page of a lump
+                starts with a struct _um_lump which contains control
+                information about the lump.  The remaining bytes of
+                the first page and the remaining pages of the lump
+                make up a block.
+
+   page         Smallest allocation unit in a segment.  Division into
+                pages is used to reduce fragmentation.  The size of a
+                page, _UM_PAGE_SIZE, must be a power of two.
+
+   bucket       A set of free lumps of certain sizes.  Bucket i
+                contains free lumps of SIZE(i) through SIZE(i+1)-1
+                bytes, where SIZE(i) is a ower of two.  Buckets are
+                implemented as doubly-linked lists which may span
+                segments.  Each heap has its own set of buckets of
+                various sizes.
+
+   crate        A contiguous set of crumbs, all having the same size.
+                Crates are allocated as lumps from the heap.  Lumps
+                used for crates have state _UMS_CRATE.  Each crate
+                starts with a struct _um_crate followed by an array of
+                crumbs.
+
+   crumb        Allocation unit in crates, used for allocation of
+                small blocks.  All crumbs of a crate have the same
+                size.  Each crumb starts with a struct _um_crumb.
+
+   crateset     A linked list of crates and a doubly-linked list of
+                free crumbs (which may span several crates), all
+                crumbs having the same size.  Each heap has its own
+                set of cratesets of various (small) sizes.
+
+   block        Memory allocated from a heap.  malloc() returns a
+                pointer to a block.  Each block is preceded by control
+                information (header); the word immediately preceding a
+                block points to the parent structure (segment or
+                crate).  A block is either located in a lump or in a
+                crumb, distinguished by the magic word pointed to by
+                the parent pointer.
+
+   header       The control information (struct _um_hdr) preceding a
+                block.  At least, this is a pointer to the parent
+                structure (segment or crate).  The low 3 bits of the
+                pointer are used for flag bits, therefore the parent
+                structure must be aligned on a 8-byte boundary (the
+                low 3 bits of the pointer are set to zero).  The
+                `size' member of the header is not valid for used
+                crumbs (it's overlaid by the first word of the block).
+
+   A different allocation scheme (crumbs) for small blocks is used for
+   the following reasons:
+
+   - The granularity (page size) of lumps is 32 bytes.  That's quite a
+     lot of overhead for, say, 4-byte blocks
+
+   - If the page size were decreased to 4 to minimize overhead, there
+     wouldn't be enough space for keeping the two free list pointers
+     -- free crumbs don't need the size member, therefore it can be
+     overlaid with one of the pointers
+
+   - Moreover, decreasing the page size would increase fragmentation
+     of the heap
+
+   - Allocating small blocks as lumps would increase fragmentation of
+     the heap.
+
+   The following diagram shows four crumbs (of 4 bytes each), #2 being
+   free:
+
+       crumb #0    crumb #1    crumb #2    crumb #3
+       |<---12--->||<---12--->||<---12--->||<---12--->|
+       |======||==||======||==||==========||======||==|
+         hdr   blk   hdr   blk  _um_crumb    hdr    blk
+       |          ||          |            |          |
+       |=======...||=======...|            |=======...|
+        _um_crumb   _um_crumb               _um_crumb
+
+   Note that part of `struct _um_crumb' is overlaid by the block.  The
+   entire `struct _um_crumb' is used for the free crumb.
+
+   The following diagram shows four crumbs (of 8 bytes each), #2 being
+   free:
+
+       crumb #0        crumb #1        crumb #2        crumb #3
+       |<-----16----->||<-----16----->||<-----16----->||<-----16----->|
+       |======||======||======||======||==========|....|======||======|
+         hdr     blk     hdr     blk    _um_crumb        hdr     blk
+       |=======...|    |=======...|                    |=======...|
+        _um_crumb       _um_crumb                       _um_crumb
+
+   Again, part of `struct _um_crumb' is overlaid by the block.
+
+   We could save another 4 bytes per crumb for block sizes >= 8 by not
+   storing the size, which can be retrieved from the crate pointed to
+   by the header.  Then, _msize() would return the rounded size.  The
+   minimum crumb size is 12 bytes, therefore this wouldn't improve
+   things for 4-byte blocks.
+
+   The following diagram shows a used lump spanning two pages
+   with _UM_LUMP_HEADER_SIZE == 8 and _UM_PAGE_SIZE == 32:
+
+               32-byte boundary                32-byte boundary
+               |                               |
+       |<-------- page (32) --------->||<-------- page (32) --------->|
+       |<- 8->|                       ||                              |
+       |======||===================================|...............|==|
+         hdr                block                       unused     size
+       |              |
+       |=======.......|
+       struct _um_lump
+
+   By `mis-aligning' the pages by _UM_LUMP_HEADER_SIZE we can align
+   blocks on any power of two.  Note that part of `struct _um_lump' is
+   overlaid by the block.
+
+   The following diagram shows a free lump spanning two pages with
+   _UM_LUMP_HEADER_SIZE == 8 and _UM_PAGE_SIZE == 32:
+
+               32-byte boundary                32-byte boundary
+               |                               |
+       |<-------- page (32) --------->||<-------- page (32) --------->|
+       |==============|............................................|==|
+       struct _um_lump                  unused                     size
+
+   Note that the entire `struct _um_lump' is used.
+
+   */
+
+/* ======================== Common definitions ======================== */
+
+/* Magic numbers. */
+
+#define _UM_MAGIC_CRATE 0xdd63eeed
+#define _UM_MAGIC_SEG   0xdd73eeed
+#define _UM_MAGIC_HEAP  0xdd68eeed
+
+/* These flags are passed internally between the functions. */
+
+#define _UMFI_TILED     0x0001  /* Create tiled block */
+#define _UMFI_ZERO      0x0002  /* Zero the block if required */
+#define _UMFI_CRATE     0x0004  /* Create a lump for a crate */
+#define _UMFI_NOMOVE    0x0008  /* Expand block without moving */
+
+/* These flags are stored in the parent pointer of lumps and crumbs.
+   In consequence, we must align objects pointed to by those pointers
+   (ie, segments and crates) on 8-byte boundaries. */
+
+#define _UMF_MASK       0x07    /* Mask for all the following flags */
+#define _UMF_RESERVED   0x04    /* Not yet used, _udump_allocated_delta() */
+
+#define _UMS_MASK       0x03    /* Mask for the block status */
+#define _UMS_FREE       0x00    /* The block is free (1) */
+#define _UMS_USER       0x01    /* The block is used for a user block */
+#define _UMS_CRATE      0x02    /* The block is used for a crate */
+#define _UMS_RESERVED   0x03    /* Not yet used */
+
+/* (1) In most cases which check the status for equality or inequality
+       to _UMS_FREE.  Defining _UMS_FREE as zero makes these tests
+       efficient. */
+
+/* Segments and crates must be aligned on a _UM_PARENT_ALIGN byte
+   boundary. */
+
+#define _UM_PARENT_ALIGN        (_UMF_MASK + 1)
+
+/* Turn an _umint into a pointer.  This is used for the parent pointer
+   in the header. */
+
+#define _PTR_FROM_UMINT(x,t)  ((t *)((x) & ~_UMF_MASK))
+
+/* Turn a pointer into an _umint.  This is used for the parent pointer
+   in the header; the flags will be set to zero if the pointer is
+   properly aligned. */
+
+#define _UMINT_FROM_PTR(p)    ((_umint)(p))
+
+/* Return true iff P is suitably aligned for holding a tiled object of
+   S bytes. */
+
+#define _UM_TILE_ALIGNED(p,s) ((((unsigned long)(p) + (s)) & 0xffff) >= (s) \
+                               || ((unsigned long)(p) & 0xffff) == 0)
+
+/* Return true iff the address P is suitable for holding a tiled
+   object of S bytes. */
+
+#define _UM_TILE_TILED(p,s) ((unsigned long)(p) + (s) <= 0x20000000)
+
+/* Return true iff the address P can be used for a tiled object of S
+   bytes. */
+
+#define _UM_TILE_OK(p,s)      (_UM_TILE_ALIGNED ((p), (s)) \
+                               && _UM_TILE_TILED ((p), (s))) 
+
+/* Compute the smallest number X such that P will be aligned on a A
+   byte boundary if X is added (as a byte count) to P.  P can be
+   either a pointer or an integer, A must be a power of two. */
+
+#define _UM_ALIGN_DIFF(p,a) ((((unsigned long)(p) + (a) - 1) & ~((a) - 1)) \
+                             - (unsigned long)(p))
+
+/* Return true iff P is aligned on an A boundary.  A must be a power
+   of two. */
+
+#define _UM_IS_ALIGNED(p,a) (((unsigned long)(p) & ((a) - 1)) == 0)
+
+/* Return a void pointer pointing N bytes past the start of the object
+   pointed to be P.  In other words, add an integer to a pointer,
+   interpreting the integer as byte count. */
+
+#define _UM_ADD(p,n)  ((void *)((char *)(p) + (n)))
+
+/* Set the status of a crumb or lump to S.  V is the `parent' member
+   of the header. */
+
+#define _UM_SET_STATUS(v,s) ((v) = ((v) & ~_UMS_MASK) | (s))
+
+/* _uheap_walk() applies the _UM_WALK_ERROR macro when returning an
+   error.  Set a breakpoint in _um_walk_error() to find out more about
+   the error with a debugger. */
+
+#ifdef NDEBUG
+#define _UM_WALK_ERROR(x) x
+#else
+#define _UM_WALK_ERROR(x) _um_walk_error(x)
+int _um_walk_error (int);
+#endif
+
+/* _umint represents a pointer as unsigned integer. */
+
+typedef unsigned long _umint;
+
+/* _umagic holds a magic number. */
+
+typedef unsigned long _umagic;
+
+/* Declarations for forward references. */
+
+struct _uheap;
+
+
+/* ============================== Header ============================== */
+
+/* The control information immediately preceding free and allocated
+   blocks must have the following layout (`size' is not required for
+   free crumbs, but is required for free lumps): */
+
+struct _um_hdr
+{
+  _umint size;                  /* Valid if the block is allocated */
+  _umint parent;                /* Use _PTR_FROM_UMINT() to get the pointer */
+};
+
+#define _HDR_FROM_BLOCK(p)      (((struct _um_hdr *)(p)) - 1)
+
+/* Return the status of the crumb P. */
+
+#define _UM_HDR_STATUS(p)       ((p)->parent & _UMS_MASK)
+
+
+/* ========================= Crates and crumbs ======================== */
+
+/* Subheaps (crates) for blocks of constant size.  All the blocks
+   allocated from a crate have the same rounded size.  Each crate has
+   a header followed by an array of crumbs.  Initially, crumbs are
+   allocated directly from the array, starting at index INIT.  This is
+   done only for the most recently allocated crate as this is the only
+   one which has free crumbs at INIT.  Deallocating a crumb will put
+   it into a list of free crumbs.  If that list is non-empty, crumbs
+   will be allocated from that list. */
+
+#define _UM_MAX_CRATE_SIZE      8000
+
+struct _um_crumb
+{
+  union
+  {
+    struct
+    {
+      struct _um_crumb *prev;   /* Cf. struct _um_hdr (size) */
+      _umint parent_crate;      /* Cf. struct _um_hdr (parent) */
+      struct _um_crumb *next;
+    } free;
+    struct
+    {
+      _umint size;              /* Cf. struct _um_hdr (size) */
+      _umint parent_crate;      /* Cf. struct _um_hdr (parent) */
+      char data;
+    } used;
+  } x;
+};
+
+struct _um_crate
+{
+  /* This must be the first word.  It's used for consistency checking
+     and for distinguishing crates from segments. */
+
+  _umagic magic;
+
+  struct _um_crateset *parent_crateset;
+
+  /* PARENT_HEAP points to the heap this crate belongs to.  For
+     instance, we need this for locking the heap in free(). */
+
+  struct _uheap *parent_heap;
+
+  /* NEXT points to the next crate of the same size of the same heap.
+     This pointer is rarely needed, so a simply-linked list is
+     sufficient. */
+
+  struct _um_crate *next;
+
+  /* All crumbs in this crate have this size. */
+
+  size_t crumb_size;
+
+  /* Maximum number of crumbs in this crate. */
+
+  unsigned max;
+
+  /* Crumbs 0 through INIT-1 have been initialized, the free ones are
+     in the fre list.  Crumbs INIT through MAX-1 are available and
+     uninitialized (they are not in the free list). */
+
+  unsigned init;
+
+  /* Number of used crumbs in this crate */
+
+  unsigned used;
+};
+
+/* This is the overhead added to a block in a crumb. */
+
+#define _UM_CRUMB_OVERHEAD     offsetof (struct _um_crumb, x.used.data)
+
+/* Return a pointer to the Ith crumb of the crate P. */
+
+#define _UM_CRUMB_BY_INDEX(p,i) \
+    ((struct _um_crumb *) \
+     (_UMINT_FROM_PTR (p) + sizeof (struct _um_crate) \
+      + (i) * ((p)->crumb_size + _UM_CRUMB_OVERHEAD)))
+
+/* Return a pointer to the crumb containing block P. */
+
+#define _UM_CRUMB_FROM_BLOCK(p) \
+  ((struct _um_crumb *)((char *)(p) \
+                        - offsetof (struct _um_crumb, x.used.data)))
+
+/* Return a pointer to the block in crumb P. */
+
+#define _UM_BLOCK_FROM_CRUMB(p) ((void *)&(p)->x.used.data)
+
+/* Return the status of the crumb P. */
+
+#define _UM_CRUMB_STATUS(p)  ((p)->x.used.parent_crate & _UMS_MASK)
+
+/* Set the status of the crumb P to S. */
+
+#define _UM_CRUMB_SET_STATUS(p,s) \
+    _UM_SET_STATUS ((p)->x.used.parent_crate, (s))
+
+
+/* Note: the most recently allocated crate is at the head of the crate
+   list (ie, it's pointed to by crate_head).  The most recently
+   allocated crate is the only one which has INIT < MAX. */
+
+struct _um_crateset
+{
+  size_t crumb_size;
+  struct _um_crate *crate_head;
+  struct _um_crumb *crumb_head;
+  struct _um_crumb *crumb_tail;
+};
+
+
+/* ======================== Segments and lumps ======================== */
+
+/* Each lump starts with a `struct _um_lump'.  The block (of a used
+   lump) starts at the DATA member, which is overlaid by NEXT and PREV
+   in free lumps.  The block is followed by an _umint which repeats
+   the size.
+
+   IMPORTANT:
+
+       offsetof (struct _um_lump, x.used.data)
+
+   must divide the page size to make alignment work!  Additional
+   members (say, for debugging) must be inserted at the beginning of
+   the structure, preceding the SIZE member. */
+
+struct _um_lump
+{
+  _umint size;                  /* Cf. struct _um_hdr */
+  _umint parent_seg;            /* Cf. struct _um_hdr */
+  union
+  {
+    struct
+    {
+      struct _um_lump *next;
+      struct _um_lump *prev;
+    } free;
+    struct
+    {
+      char data;
+    } used;
+  } x;
+};
+
+
+/* Each segment starts with a `struct _um_seg'.  Note that this
+   structure might be preceded by padding for proper alignment.  See
+   MEM. */
+
+struct _um_seg
+{
+  /* This must be the first word.  It's used for consistency checking
+     and for distinguishing crates from segments. */
+
+  _umagic magic;
+
+  /* PARENT_HEAP points to the heap this segment belongs to. */
+
+  struct _uheap *parent_heap;
+
+  /* NEXT points to the next segment of the same heap.  This pointer
+     is rarely needed, so a simply-linked list is sufficient. */
+
+  struct _um_seg *next;
+
+  /* SIZE is the size of the memory area containing this segment.
+     SIZE is relative to MEM (see below). */
+
+  size_t size;
+
+  /* ZERO_LIMIT is used to avoid zeroing memory for _ucalloc() in
+     certain cases.  It is assumed that all pages at addresses >=
+     ZERO_LIMIT are already zeroed. */
+
+  void *zero_limit;
+
+  /* START points to the first page of this segment. */
+
+  void *start;
+
+  /* END points to the (non-existing) page one past the last page of
+     this segment. */
+
+  void *end;
+
+  /* Pointer to memory containing the segment.  This pointer is
+     required because struct _um_seg must be aligned on a
+     _UM_PARENT_ALIGN byte boundary. */
+
+  void *mem;
+};
+
+
+/* A bucket of lumps is implemented as doubly-linked list. */
+
+struct _um_bucket
+{
+  struct _um_lump *head;
+  struct _um_lump *tail;
+};
+
+/* This is the maximum size of a lump. */
+
+#define _UM_MAX_SIZE          0x40000000
+
+/* This constant determines the size of the smallest bucket, bucket 0.
+   Note that bucket numbers do not start at _UM_MIN_BUCKET! */
+
+#define _UM_MIN_BUCKET        5
+
+/* This constant determines the size of the biggest bucket.  Note that
+   bucket numbes do not end at _UM_MAX_BUCKET! */
+
+#define _UM_MAX_BUCKET        27        /* 128 MB */
+
+/* This is the number of buckets.  Buckets are numbered 0 through
+   _UM_BUCKETS-1. */
+
+#define _UM_BUCKETS           (_UM_MAX_BUCKET - _UM_MIN_BUCKET + 1)
+
+/* Bucket i contains free lumps with
+
+        _UM_BUCKET_SIZE(i) <= SIZE < _UM_BUCKET_SIZE(i+1)
+
+   where SIZE is the rounded size of the lumps.  The last bucket,
+   _UM_BUCKETS-1, contains all free lumps of _UM_BUCKET_SIZE(i) bytes
+   or more (there is no upper limit in the last bucket, except for
+   _UM_MAX_SIZE). */
+
+#define _UM_BUCKET_SIZE(i)    (1 << ((i) + _UM_MIN_BUCKET))
+
+/* The page size must be a power of two and must be greater than or
+   equal to _UM_LUMP_OVERHEAD. */
+
+#define _UM_PAGE_SIZE         (1 << _UM_MIN_BUCKET)
+
+/* This is the size of the header for a lump. */
+
+#define _UM_LUMP_HEADER_SIZE  offsetof (struct _um_lump, x.used.data)
+
+/* This is the overhead added to a block in a lump. */
+
+#define _UM_LUMP_OVERHEAD     (_UM_LUMP_HEADER_SIZE + sizeof (_umint))
+
+/* Compute the lump size from the block size.  The result is always a
+   multiple of the page size. */
+
+#define _UM_ROUND_LUMP(s)     (((s) + _UM_LUMP_OVERHEAD + _UM_PAGE_SIZE - 1) \
+                               & ~(_UM_PAGE_SIZE-1))
+
+/* Return true iff P is the first lump of segment S. */
+
+#define _UM_FIRST_LUMP(s,p)     ((p) == (s)->start)
+
+/* Return true iff P is the last lump of segment S. */
+
+#define _UM_LAST_LUMP(s,p)      (_UM_NEXT_LUMP (p) == (s)->end)
+
+/* Return a pointer to the lump immediately preceding the lump P.
+   This macro must not be applied to the first lump of a segment. */
+
+#define _UM_PREV_LUMP(p)    ((struct _um_lump *) \
+                             ((char *)(p) \
+                              - _UM_ROUND_LUMP (((_umint *)(p))[-1])))
+
+/* Return a pointer to the lump immediately following the lump P.
+   This macro can be applied to the last lump of a segment; in this
+   case, the result should be equal the END member of the segment. */
+
+#define _UM_NEXT_LUMP(p)    ((struct _um_lump *) \
+                            ((char *)(p) + _UM_ROUND_LUMP ((p)->size)))
+
+/* Return a pointer to the lump containing block P. */
+
+#define _UM_LUMP_FROM_BLOCK(p) \
+  ((struct _um_lump *)((char *)(p) \
+                        - offsetof (struct _um_lump, x.used.data)))
+
+/* Return a pointer to the block in lump P. */
+
+#define _UM_BLOCK_FROM_LUMP(p) ((void *)&(p)->x.used.data)
+
+
+/* Return the status of the lump P. */
+
+#define _UM_LUMP_STATUS(p)      ((p)->parent_seg & _UMS_MASK)
+
+/* Set the status of the lump P to S. */
+
+#define _UM_LUMP_SET_STATUS(p,s) _UM_SET_STATUS ((p)->parent_seg, (s))
+
+
+/* =============================== Heaps =============================== */
+
+/* This is the initial size of the default heap.  It should be a
+   multiple of 64K, see _default_alloc_fun(). */
+
+#define _INITIAL_DEFAULT_HEAP_SIZE      65536
+
+/* This is the maximum number of cratesets. */
+
+#define _UM_MAX_CRATESETS       5
+
+/* Each thread has its own default heap. */
+
+#if defined (__MT__)
+#define _UM_DEFAULT_REGULAR_HEAP tp->_th_rheap
+#define _UM_DEFAULT_TILED_HEAP   tp->_th_theap
+#define _UM_MT_DECL              struct _thread *tp = _thread ();
+#else
+#define _UM_DEFAULT_REGULAR_HEAP _um_regular_heap
+#define _UM_DEFAULT_TILED_HEAP   _um_tiled_heap
+#define _UM_MT_DECL
+#endif
+
+/* Note that _um_regular_heap is declared in <umalloc.h>.
+   _um_tiled_heap isn't, so we declare it here. */
+
+extern Heap_t _um_tiled_heap;
+
+
+/* This structure is stored at the start of a heap; it's pointed to by
+   Heap_t. */
+
+struct _uheap
+{
+  /* Magic number. */
+
+  _umagic magic;
+
+  /* Type flags passed to _ucreate(). */
+
+  unsigned type;
+
+  /* Functions for expanding the heap and for shrinking the heap. */
+
+  void *(*alloc_fun)(Heap_t, size_t *, int *);
+  void (*release_fun)(Heap_t, void *, size_t);
+  int (*expand_fun)(Heap_t, void *, size_t, size_t *, int *);
+  void (*shrink_fun)(Heap_t, void *, size_t, size_t *);
+
+  /* SEG_HEAD is the head of the segment list. */
+
+  struct _um_seg *seg_head;
+
+  /* INITIAL_SEG points to the initial segment created by _ucreate()
+     in the same memory area as this structure.  The initial segment
+     is never deallocated. */
+
+  struct _um_seg *initial_seg;
+
+  /* INITIAL_SEG_SIZE is the original size of the initial segment.  We
+     need INITIAL_SEG_SIZE for deallocating memory contiguously added
+     to the end of the initial segment. */
+
+  size_t initial_seg_size;
+
+  /* This is the number of segments.  That value could be computed
+     from the segment list.  However, we use it to avoid an infinite
+     loop in _uheapchk(). */
+
+  size_t n_segments;
+
+  /* This is the number of crates.  We use this number to avoid an
+     infinite loop in _uheapchk(). */
+
+  size_t n_crates;
+
+  /* This is an upper limit on the number of free crumbs.  It's just
+     the maximum number of crumbs all the crates can hold.  We use
+     this number to avoid an infinite loop in _uheapchk(). */
+
+  size_t max_crumbs;
+
+  /* This array holds the control structures for the buckets. */
+
+  struct _um_bucket buckets[_UM_BUCKETS];
+
+  /* This is the number of createsets.  A heap can have up to
+     _UM_MAX_CREATESETS createsets. */
+
+  int n_cratesets;
+
+  /* This array holds the control structures for the createsets. */
+
+  struct _um_crateset cratesets[_UM_MAX_CRATESETS];
+
+  /* Fast mutex semaphore for locking the heap.  There's no point in
+     using an HMTX; if the owner dies, we can't continue anyway
+     because the heap is probably not in a consistent state. */
+
+  _rmutex rsem;
+
+  /* This member is used for various purposes by _uheapchk():
+     _seg_walk() counts the number of crates in SCRATCH1.
+     _check_bucket() uses SCRATCH1 as upper limit for the number of
+     free lumps. */
+
+  size_t scratch1;
+};
+
+
+/* Defines types for walker functions. */
+
+typedef int _um_callback1 (const void *, size_t, int, int, const char *,
+                           size_t);
+
+typedef int _um_callback2 (Heap_t, const void *, size_t, int, int,
+                           const char *, size_t, void *);
+
+
+
+/* Prototypes for internal functions. */
+
+Heap_t _um_addmem_nolock (Heap_t, void *, size_t, int);
+void *_um_alloc_no_lock (Heap_t, size_t, size_t, unsigned);
+void _um_crumb_free_maybe_lock (struct _um_crate *, struct _um_crumb *, int);
+void *_um_default_alloc (Heap_t, size_t *, int *);
+int _um_default_expand (Heap_t, void *, size_t, size_t *, int *);
+void _um_default_release (Heap_t, void *, size_t);
+void _um_default_shrink (Heap_t, void *, size_t, size_t *);
+int _um_find_bucket (size_t);
+void _um_free_maybe_lock (void *, int);
+void _um_init_default_regular_heap (void);
+void _um_init_default_tiled_heap (void);
+void *_um_lump_alloc (Heap_t, size_t, size_t, unsigned);
+void _um_lump_coalesce_free (Heap_t, struct _um_lump *, struct _um_seg *,
+    size_t);
+void _um_lump_free_maybe_lock (struct _um_seg *, struct _um_lump *, int);
+void _um_lump_link_heap (Heap_t, struct _um_lump *);
+void _um_lump_make_free (Heap_t, struct _um_lump *, struct _um_seg *, size_t);
+void *_um_realloc (void *, size_t, size_t, unsigned);
+Heap_t _um_seg_addmem (Heap_t, struct _um_seg *, void *, size_t);
+Heap_t _um_seg_setmem (Heap_t, struct _um_seg *, void *, size_t, int);
+void _um_lump_unlink_bucket (struct _um_bucket *, struct _um_lump *);
+void _um_lump_unlink_heap (Heap_t, struct _um_lump *);
+int _um_walk_no_lock (Heap_t, _um_callback2 *, void *);
+
+/* Inline functions. */
+
+static __inline__ void _um_heap_lock (Heap_t h)
+{
+#if defined (__MT__)
+  _rmutex_checked_request (&h->rsem, _FMR_IGNINT);
+#endif
+}
+
+
+static __inline__ void _um_heap_unlock (Heap_t h)
+{
+#if defined (__MT__)
+  _rmutex_checked_release (&h->rsem);
+#endif
+}
+
+
+static __inline__ void _um_crumb_unlink (struct _um_crateset *crateset,
+                                         struct _um_crumb *crumb)
+{
+  if (crumb->x.free.prev == NULL)
+    crateset->crumb_head = crumb->x.free.next;
+  else
+    crumb->x.free.prev->x.free.next = crumb->x.free.next;
+  if (crumb->x.free.next == NULL)
+    crateset->crumb_tail = crumb->x.free.prev;
+  else
+    crumb->x.free.next->x.free.prev = crumb->x.free.prev;
+}
+
+
+static __inline__ void _um_lump_set_size (struct _um_lump *lump, size_t size)
+{
+  lump->size = size;            /* Must be done first */
+  ((_umint *)_UM_NEXT_LUMP (lump))[-1] = size;
+}
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_UMALLOC_H */
Index: trunk/src/emx/include/errno.h
===================================================================
--- trunk/src/emx/include/errno.h	(revision 18)
+++ trunk/src/emx/include/errno.h	(revision 18)
@@ -0,0 +1,6 @@
+/* errno.h (emx+gcc) */
+
+#ifndef _ERRNO_H
+#define _ERRNO_H
+#include <sys/errno.h>
+#endif /* not _ERRNO_H */
Index: trunk/src/emx/include/fcntl.h
===================================================================
--- trunk/src/emx/include/fcntl.h	(revision 18)
+++ trunk/src/emx/include/fcntl.h	(revision 18)
@@ -0,0 +1,6 @@
+/* fcntl.h (emx+gcc) */
+
+#ifndef _FCNTL_H
+#define _FCNTL_H
+#include <sys/fcntl.h>
+#endif /* not _FCNTL_H */
Index: trunk/src/emx/include/fix-args.h
===================================================================
--- trunk/src/emx/include/fix-args.h	(revision 18)
+++ trunk/src/emx/include/fix-args.h	(revision 18)
@@ -0,0 +1,38 @@
+/*----------------------------------------------------------------------*
+ * Bounds Checking for GCC.						*
+ * Copyright (C) 1995 Richard W.M. Jones <rwmj@doc.ic.ac.uk>.		*
+ *----------------------------------------------------------------------*
+ * This program is free software; you can redistribute it and/or modify	*
+ * it under the terms of the GNU General Public License as published by	*
+ * the Free Software Foundation; either version 2 of the License, or	*
+ * (at your option) any later version.					*
+ *									*
+ * This program is distributed in the hope that it will be useful,	*
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of	*
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	*
+ * GNU General Public License for more details.				*
+ *									*
+ * You should have received a copy of the GNU General Public License	*
+ * along with this program; if not, write to the Free Software		*
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		*
+ *----------------------------------------------------------------------*
+ * Modified for emx by Eberhard Mattes, Jun 1998			*
+ *----------------------------------------------------------------------*/
+
+#ifndef _FIX_ARGS_H_
+#define _FIX_ARGS_H_
+
+#ifdef __BOUNDS_CHECKING_ON
+
+extern int __bounds_debug_no_checking;
+
+#define va_arg(AP,TYPE) \
+  ({int __t = __bounds_debug_no_checking; \
+  TYPE __r; \
+  __bounds_debug_no_checking = 1; \
+  __r = __std_va_arg(AP,TYPE); \
+  __bounds_debug_no_checking = __t; \
+  __r;})
+
+#endif /* __BOUNDS_CHECKING_ON */
+#endif /* _FIX_ARGS_H_ */
Index: trunk/src/emx/include/float.h
===================================================================
--- trunk/src/emx/include/float.h	(revision 18)
+++ trunk/src/emx/include/float.h	(revision 18)
@@ -0,0 +1,110 @@
+/* float.h (emx+gcc) */
+
+#ifndef _FLOAT_H
+#define _FLOAT_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define FLT_RADIX       2
+#define FLT_ROUNDS      1
+
+#define DBL_MANT_DIG    53
+#define DBL_MIN_EXP     (-1021)
+#define DBL_MAX_EXP     1024
+#define DBL_DIG         15
+#define DBL_MIN_10_EXP  (-307)
+#define DBL_MAX_10_EXP  308
+#define DBL_MIN         2.2250738585072014e-308
+#define DBL_MAX         1.7976931348623158e+308
+#define DBL_EPSILON     2.2204460492503131e-016
+
+#define FLT_MANT_DIG    24
+#define FLT_MIN_EXP     (-125)
+#define FLT_MAX_EXP     128
+#define FLT_DIG         6
+#define FLT_MIN_10_EXP  (-37)
+#define FLT_MAX_10_EXP  38
+#define FLT_MIN         1.17549435e-38F
+#define FLT_MAX         3.40282346e+38F
+#define FLT_EPSILON     1.19209290e-07F
+
+#define LDBL_MANT_DIG   64
+#define LDBL_MIN_EXP    (-16381)
+#define LDBL_MAX_EXP    16384
+#define LDBL_DIG        18
+#define LDBL_MIN_10_EXP (-4931)
+#define LDBL_MAX_10_EXP 4932
+#define LDBL_MIN        3.3621031431120935063e-4932L
+#define LDBL_MAX        1.1897314953572317650e+4932L
+#define LDBL_EPSILON    1.08420217248550443400745280086994171142578125e-0019L
+
+#if !defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)
+
+#define M_E             2.71828182845904523536
+#define M_LOG2E         1.44269504088896340736
+#define M_LOG10E        0.434294481903251827651
+#define M_LN2           0.693147180559945309422
+#define M_LN10          2.302585092994045684018
+
+#define M_PI            3.14159265358979323846
+#define M_PI_2          1.57079632679489661923
+#define M_PI_4          0.785398163397448309616
+#define M_1_PI          0.318309886183790671538
+#define M_2_PI          0.636619772367581343076
+#define M_2_SQRTPI      1.12837916709551257390
+
+#define M_SQRT2         1.41421356237309504880
+#define M_SQRT1_2       0.707106781186547524401
+
+#if !defined (_OMIT_387_STUFF)
+
+#define MCW_EM                  0x003f
+#define EM_INVALID              0x0001
+#define EM_DENORMAL             0x0002
+#define EM_ZERODIVIDE           0x0004
+#define EM_OVERFLOW             0x0008
+#define EM_UNDERFLOW            0x0010
+#define EM_INEXACT              0x0020
+
+#define MCW_IC                  0x1000
+#define IC_PROJECTIVE           0x0000
+#define IC_AFFINE               0x1000
+
+#define MCW_RC                  0x0c00
+#define RC_NEAR                 0x0000
+#define RC_DOWN                 0x0400
+#define RC_UP                   0x0800
+#define RC_CHOP                 0x0c00
+
+#define MCW_PC                  0x0300
+#define PC_24                   0x0000
+#define PC_53                   0x0200
+#define PC_64                   0x0300
+
+#define CW_DEFAULT              (RC_NEAR | PC_64 | MCW_EM)
+
+#define SW_INVALID              0x0001
+#define SW_DENORMAL             0x0002
+#define SW_ZERODIVIDE           0x0004
+#define SW_OVERFLOW             0x0008
+#define SW_UNDERFLOW            0x0010
+#define SW_INEXACT              0x0020
+#define SW_STACKFAULT           0x0040
+#define SW_STACKOVERFLOW        0x0200
+
+unsigned _clear87 (void);
+unsigned _control87 (unsigned, unsigned);
+void _fpreset (void);
+unsigned _status87 (void);
+
+#endif /* !defined (_OMIT_387_STUFF) */
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _FLOAT_H */
Index: trunk/src/emx/include/fnmatch.h
===================================================================
--- trunk/src/emx/include/fnmatch.h	(revision 18)
+++ trunk/src/emx/include/fnmatch.h	(revision 18)
@@ -0,0 +1,46 @@
+/* fnmatch.h (emx+gcc) */
+
+#ifndef _FNMATCH_H
+#define _FNMATCH_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* POSIX.2 */
+
+#define FNM_NOMATCH        1
+
+#define FNM_NOESCAPE       16
+#define FNM_PATHNAME       32
+#define FNM_PERIOD         64
+
+int fnmatch (__const__ char *, __const__ char *, int);
+
+
+#if !defined (_POSIX_SOURCE) || defined (_WITH_UNDERSCORE)
+
+/* emx extensions */
+
+#define _FNM_MATCH         0
+#define _FNM_ERR           2
+
+#define _FNM_STYLE_MASK    15
+
+#define _FNM_POSIX         0
+#define _FNM_OS2           1
+#define _FNM_DOS           2
+
+#define _FNM_IGNORECASE    128
+#define _FNM_PATHPREFIX    256
+
+int _fnmatch (__const__ char *, __const__ char *, int);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _FNMATCH_H */
Index: trunk/src/emx/include/ftw.h
===================================================================
--- trunk/src/emx/include/ftw.h	(revision 18)
+++ trunk/src/emx/include/ftw.h	(revision 18)
@@ -0,0 +1,23 @@
+/* ftw.h (emx+gcc) */
+
+#ifndef _FTW_H
+#define _FTW_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define FTW_F           0
+#define FTW_D           1
+#define FTW_DNR         2
+#define FTW_NS          3
+
+int ftw (__const__ char *,
+    int (*)(__const__ char *, __const__ struct stat *, int),
+    int);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _FTW_H */
Index: trunk/src/emx/include/getopt.h
===================================================================
--- trunk/src/emx/include/getopt.h	(revision 18)
+++ trunk/src/emx/include/getopt.h	(revision 18)
@@ -0,0 +1,33 @@
+/* getopt (emx+gcc) */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+extern char *optarg;       /* argument of current option                    */
+extern int optind;         /* index of next argument; default=0: initialize */
+extern int opterr;         /* 0=disable error messages; default=1: enable   */
+extern int optopt;         /* option character which caused the error       */
+extern char *optswchar;    /* characters introducing options; default="-"   */
+
+extern enum _optmode
+{
+  GETOPT_UNIX,             /* options at start of argument list (default)   */
+  GETOPT_ANY,              /* move non-options to the end                   */
+  GETOPT_KEEP              /* return options in order                       */
+} optmode;
+
+
+/* Note: The 2nd argument is not const as GETOPT_ANY reorders the
+   array pointed to. */
+
+int getopt (int, char **, __const__ char *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _GETOPT_H */
Index: trunk/src/emx/include/glob.h
===================================================================
--- trunk/src/emx/include/glob.h	(revision 18)
+++ trunk/src/emx/include/glob.h	(revision 18)
@@ -0,0 +1,60 @@
+/* glob.h (emx+gcc) */
+
+#ifndef _GLOB_H
+#define _GLOB_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#define GLOB_APPEND     0x0001
+#define GLOB_DOOFFS     0x0002
+#define GLOB_ERR        0x0004
+#define GLOB_MARK       0x0008
+#define GLOB_NOCHECK    0x0010
+#define GLOB_NOESCAPE   0x0020
+#define GLOB_NOSORT     0x0040
+#define GLOB_PERIOD     0x0080  /* POSIX.2? */
+
+#define GLOB_ABEND      1
+#define GLOB_NOMATCH    2
+#define GLOB_NOSPACE    3
+
+typedef struct
+{
+  /* Required by POSIX.2 */
+  size_t gl_pathc;
+  char **gl_pathv;
+  size_t gl_offs;
+
+  /* BSD */
+  int gl_flags;
+
+  /* Internal */
+  size_t gl_alloc;
+  int gl_reserved[3];
+} glob_t;
+
+int glob (__const__ char *, int, int (*)(__const__ char *, int), glob_t *);
+void globfree (glob_t *);
+
+
+#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE >= 2
+#define GLOB_MAGCHAR    0x0100
+#endif
+
+
+int _glob (__const__ char *, int, int (*)(__const__ char *, int), glob_t *);
+void _globfree (glob_t *);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _GLOB_H */
Index: trunk/src/emx/include/gmon.h
===================================================================
--- trunk/src/emx/include/gmon.h	(revision 18)
+++ trunk/src/emx/include/gmon.h	(revision 18)
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)gmon.h	5.2 (Berkeley) 5/6/91
+ */
+
+struct phdr {
+    char	*lpc;
+    char	*hpc;
+    int		ncnt;
+};
+
+    /*
+     *	histogram counters are unsigned shorts (according to the kernel).
+     *	For emx, histogram counters are unsigned longs.
+     */
+#if 1 /* emx */
+#define	HISTCOUNTER	unsigned long
+#else
+#define	HISTCOUNTER	unsigned short
+#endif
+
+    /*
+     *	fraction of text space to allocate for histogram counters
+     *	here, 1/2
+     */
+#define	HISTFRACTION	2
+
+    /*
+     *	Fraction of text space to allocate for from hash buckets.
+     *	The value of HASHFRACTION is based on the minimum number of bytes
+     *	of separation between two subroutine call points in the object code.
+     *	Given MIN_SUBR_SEPARATION bytes of separation the value of
+     *	HASHFRACTION is calculated as:
+     *
+     *		HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
+     *
+     *	For the VAX, the shortest two call sequence is:
+     *
+     *		calls	$0,(r0)
+     *		calls	$0,(r0)
+     *
+     *	which is separated by only three bytes, thus HASHFRACTION is 
+     *	calculated as:
+     *
+     *		HASHFRACTION = 3 / (2 * 2 - 1) = 1
+     *
+     *	Note that the division above rounds down, thus if MIN_SUBR_FRACTION
+     *	is less than three, this algorithm will not work!
+     */
+#define	HASHFRACTION	1
+
+    /*
+     *	percent of text space to allocate for tostructs
+     *	with a minimum.
+     */
+#define ARCDENSITY	2
+#define MINARCS		50
+
+struct tostruct {
+    char		*selfpc;
+    long		count;
+    unsigned short	link;
+};
+
+    /*
+     *	a raw arc,
+     *	    with pointers to the calling site and the called site
+     *	    and a count.
+     */
+struct rawarc {
+    unsigned long	raw_frompc;
+    unsigned long	raw_selfpc;
+    long		raw_count;
+};
+
+struct veryrawarc {
+    char raw_frompc[4];
+    char raw_selfpc[4];
+    char raw_count[4];
+};
+
+    /*
+     *	general rounding functions.
+     */
+#define ROUNDDOWN(x,y)	(((x)/(y))*(y))
+#define ROUNDUP(x,y)	((((x)+(y)-1)/(y))*(y))
Index: trunk/src/emx/include/gnu/termcap.h
===================================================================
--- trunk/src/emx/include/gnu/termcap.h	(revision 18)
+++ trunk/src/emx/include/gnu/termcap.h	(revision 18)
@@ -0,0 +1,72 @@
+/* Declarations for termcap library.
+   Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Modified for emx by Eberhard Mattes, Aug 1994 */
+
+#ifndef _TERMCAP_H
+#define _TERMCAP_H 1
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if __STDC__
+
+extern int tgetent (char *buffer, const char *termtype);
+
+extern int tgetnum (const char *name);
+extern int tgetflag (const char *name);
+extern char *tgetstr (const char *name, char **area);
+
+extern char PC;
+extern short ospeed;
+extern void tputs (const char *string, int nlines, int (*outfun) ());
+
+extern char *tparam (const char *ctlstring, char *buffer, int size, ...);
+
+extern char *UP;
+extern char *BC;
+
+extern char *tgoto (const char *cstring, int hpos, int vpos);
+
+#else /* not __STDC__ */
+
+extern int tgetent ();
+
+extern int tgetnum ();
+extern int tgetflag ();
+extern char *tgetstr ();
+
+extern char PC;
+extern short ospeed;
+
+extern void tputs ();
+
+extern char *tparam ();
+
+extern char *UP;
+extern char *BC;
+
+extern char *tgoto ();
+
+#endif /* not __STDC__ */
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _TERMCAP_H */
Index: trunk/src/emx/include/graph.h
===================================================================
--- trunk/src/emx/include/graph.h	(revision 18)
+++ trunk/src/emx/include/graph.h	(revision 18)
@@ -0,0 +1,81 @@
+/* graph.h (emx+gcc) */
+
+#ifndef _GRAPH_H
+#define _GRAPH_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* g_mode() and g_modeset() arguments (MODE) */
+
+#define G_MODE_OFF         0    /* Back to previous mode                    */
+
+#define G_MODE_EGA_C      16    /* EGA 640x200 16 colors                    */
+#define G_MODE_EGA_E      17    /* EGA 640x350 16/64 colors                 */
+
+#define G_MODE_VGA_H      24    /* VGA 640x480 16 colors                    */
+#define G_MODE_VGA_L      26    /* VGA 320x200 256 colors                   */
+
+#define G_SET_KEEP         0     /* No change                               */
+
+/* g_wmode() arguments */
+
+#define G_NORM 0                /* Normal write mode */
+#define G_AND  1                /* `AND' mode        */
+#define G_OR   2                /* `OR' mode         */
+#define G_XOR  3                /* `XOR' mode        */
+
+/* Fill or draw outline */
+
+#define G_OUTLINE      0             /* Draw outline */
+#define G_FILL         1             /* Fill         */
+
+/* EGA colors */
+
+#define G_BLACK        0
+#define G_BLUE         1
+#define G_GREEN        2
+#define G_CYAN         3
+#define G_RED          4
+#define G_MAGENTA      5
+#define G_YELLOW       6
+#define G_BROWN        6
+#define G_WHITE        7
+
+#define G_INTENSITY    8
+
+/* Screen dimensions */
+
+extern int g_xsize;             /* Screen width             */
+extern int g_ysize;             /* Screen height            */
+extern int g_colors;            /* Number of colors         */
+
+
+void g_box (int x0, int y0, int x1, int y1, int color, int fill_flag);
+void g_clear (int color);
+void g_clip (int x0, int y0, int x1, int y1);
+void g_ellipse (int cx, int cy, int rx, int ry, int color, int fill_flag);
+int g_get (int x, int y);
+void g_hline (int y, int x0, int x1, int color);
+void g_line (int x0, int y0, int x1,int y1, int color);
+void g_lock (void);
+int g_mode (int mode);
+int g_modeset (int mode, int flag);
+void g_polygon (__const__ int *x, __const__ int *y, int n, int color,
+    int fill_flag);
+void g_set (int x, int y, int color);
+void g_triangle (int x0, int y0, int x1, int y1, int x2, int y2, int color,
+    int fill_flag);
+void g_unlock (void);
+void g_unlockall (void);
+void g_vgapal (__const__ char *pal, int first, int n, int wait_flag);
+void g_vline (int x, int y0, int y1,int color);
+void g_waitv (void);
+void g_wmode (int wmode);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _GRAPH_H */
Index: trunk/src/emx/include/grp.h
===================================================================
--- trunk/src/emx/include/grp.h	(revision 18)
+++ trunk/src/emx/include/grp.h	(revision 18)
@@ -0,0 +1,29 @@
+/* grp.h (emx+gcc) */
+
+#ifndef _GRP_H
+#define _GRP_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_GID_T)
+#define _GID_T
+typedef int gid_t;
+#endif
+
+struct group
+{
+  char *gr_name;
+  gid_t gr_gid;
+  char **gr_mem;
+};
+
+struct group *getgrgid (gid_t);
+struct group *getgrnam (__const__ char *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _GRP_H */
Index: trunk/src/emx/include/ieee.h
===================================================================
--- trunk/src/emx/include/ieee.h	(revision 18)
+++ trunk/src/emx/include/ieee.h	(revision 18)
@@ -0,0 +1,24 @@
+/* ieee.h */
+
+#define	_IEEE		1
+#define _HIDDENBIT	1
+#define _LENBASE	1
+#define _EXPBASE	(1 << _LENBASE)
+
+#define _DEXPLEN	11
+#define DMAXEXP		((1 << _DEXPLEN - 1) - 1 + _IEEE)
+#define DMINEXP		(-(DMAXEXP - 3))
+#define DSIGNIF		(64 - _DEXPLEN + _HIDDENBIT - 1)
+#define MAXDOUBLE	1.7976931348623157e+308
+#define MINDOUBLE       2.2250738585072014e-308
+#define LN_MAXDOUBLE	1418.87227860620804838
+#define LN_MINDOUBLE	(-1417.48598424508815776)
+
+#define _FEXPLEN	8
+#define FMAXEXP		((1 << _FEXPLEN - 1) - 1 + _IEEE)
+#define FMINEXP		(-(FMAXEXP - 3))
+#define FSIGNIF		(32  - _FEXPLEN + _HIDDENBIT - 1)
+#define MAXFLOAT	3.40282347e+38
+#define MINFLOAT        1.17549435e-38
+#define LN_MAXFLOAT	88.7228394
+#define LN_MINFLOAT     (-87.336544750553102)
Index: trunk/src/emx/include/io.h
===================================================================
--- trunk/src/emx/include/io.h	(revision 18)
+++ trunk/src/emx/include/io.h	(revision 18)
@@ -0,0 +1,98 @@
+/* io.h (emx+gcc) */
+
+#ifndef _IO_H
+#define _IO_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (SEEK_SET)
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+struct stat;
+struct _fd_set;
+struct timeval;
+
+int remove (__const__ char *);
+int rename (__const__ char *, __const__ char *);
+
+int access (__const__ char *, int);
+int chmod (__const__ char *, int);
+int chsize (int, long);
+int close (int);
+int creat (__const__ char *, int);
+int dup (int);
+int dup2 (int, int);
+int eof (int);
+long filelength (int);
+int fstat (int, struct stat *);
+int fsync (int);
+int ftruncate (int, long);
+int ioctl (int, int request, ...);
+int isatty (int);
+long lseek (int, long, int);
+int mkstemp (char *);
+char *mktemp (char *);
+int open (__const__ char *, int, ...);
+int pipe (int *);
+int read (int, void *, size_t);
+int select (int, struct _fd_set *, struct _fd_set *, struct _fd_set *,
+    struct timeval *);
+int setmode (int, int);
+int sopen (__const__ char *, int, int, ...);
+int stat (__const__ char *, struct stat *);
+long tell (int);
+int truncate (char *, long);
+int umask (int);
+int unlink (__const__ char *);
+int write (int, __const__ void *, size_t);
+
+int _access (__const__ char *, int);
+int _chmod (__const__ char *, int);
+int _chsize (int, long);
+int _close (int);
+int _creat (__const__ char *, int);
+int _crlf (char *, size_t, size_t *);
+int _dup (int);
+int _dup2 (int, int);
+int _eof (int);
+long _filelength (int);
+int _fstat (int, struct stat *);
+int _fsync (int);
+int _ftruncate (int, long);
+int _imphandle (int);
+int _ioctl (int, int request, ...);
+int _isatty (int);
+int _isterm (int);
+long _lseek (int, long, int);
+int _mkstemp (char *);
+char *_mktemp (char *);
+int _open (__const__ char *, int, ...);
+int _pipe (int *);
+int _read (int, void *, size_t);
+int _seek_hdr (int);
+int _select (int, struct _fd_set *, struct _fd_set *, struct _fd_set *,
+    struct timeval *);
+int _setmode (int, int);
+int _sopen (__const__ char *, int, int, ...);
+int _stat (__const__ char *, struct stat *);
+long _tell (int);
+int _truncate (char *, long);
+int _umask (int);
+int _unlink (__const__ char *);
+int _write (int, __const__ void *, size_t);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _IO_H */
Index: trunk/src/emx/include/iso646.h
===================================================================
--- trunk/src/emx/include/iso646.h	(revision 18)
+++ trunk/src/emx/include/iso646.h	(revision 18)
@@ -0,0 +1,17 @@
+/* iso646.h */
+
+#if !defined (__cplusplus)
+
+#define and     &&
+#define and_eq  &=
+#define bitand  &
+#define bitor   |
+#define compl   ~
+#define not     !
+#define not_eq  !=
+#define or      ||
+#define or_eq   |=
+#define xor     ^
+#define xor_eq  ^=
+
+#endif
Index: trunk/src/emx/include/limits.h
===================================================================
--- trunk/src/emx/include/limits.h	(revision 18)
+++ trunk/src/emx/include/limits.h	(revision 18)
@@ -0,0 +1,63 @@
+/* limits.h (emx+gcc) */
+
+#ifndef _LIMITS_H
+#define _LIMITS_H
+
+#define CHAR_BIT      8
+#define SCHAR_MIN   (-128)
+#define SCHAR_MAX     127
+#define UCHAR_MAX     0xffU
+#if defined (__CHAR_UNSIGNED__)
+#define CHAR_MIN      0
+#define CHAR_MAX      UCHAR_MAX
+#else
+#define CHAR_MIN      SCHAR_MIN
+#define CHAR_MAX      SCHAR_MAX
+#endif
+#define MB_LEN_MAX    6
+#define SHRT_MIN    (-32768)
+#define SHRT_MAX      32767
+#define USHRT_MAX     0xffffU
+#define LONG_MIN    (-0x7fffffffL-1L)
+#define LONG_MAX      0x7fffffffL
+#define ULONG_MAX     0xffffffffUL
+#define LLONG_MIN   (-0x7fffffffffffffffLL-1LL)
+#define LLONG_MAX     0x7fffffffffffffffLL
+#define ULLONG_MAX    0xffffffffffffffffULL
+
+#define INT_MIN     (-0x7fffffff-1)
+#define INT_MAX       0x7fffffff
+#define UINT_MAX      0xffffffffU
+
+
+#if !defined (__STRICT_ANSI__)
+
+#define _POSIX_ARG_MAX          4096
+#define _POSIX_CHILD_MAX        6
+#define _POSIX_LINK_MAX         8
+#define _POSIX_MAX_CANON        255
+#define _POSIX_MAX_INPUT        255
+#define _POSIX_NAME_MAX         14
+#define _POSIX_NGROUPS_MAX      0
+#define _POSIX_OPEN_MAX         16
+#define _POSIX_PATH_MAX         255
+#define _POSIX_PIPE_BUF         512
+#define _POSIX_SSIZE_MAX        32767
+#define _POSIX_STREAM_MAX       8
+#define _POSIX_TZNAME_MAX       3
+
+#define	NGROUPS_MAX             0
+
+#define SSIZE_MAX               INT_MAX
+
+#endif
+
+
+#if !defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)
+
+#define WORD_BIT        32
+#define USI_MAX         UINT_MAX
+
+#endif
+
+#endif /* not _LIMITS_H */
Index: trunk/src/emx/include/locale.h
===================================================================
--- trunk/src/emx/include/locale.h	(revision 18)
+++ trunk/src/emx/include/locale.h	(revision 18)
@@ -0,0 +1,71 @@
+/* locale.h (emx+gcc) */
+
+#ifndef _LOCALE_H
+#define _LOCALE_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#define LC_ALL          0
+#define LC_COLLATE      1
+#define LC_CTYPE        2
+#define LC_MONETARY     3
+#define LC_NUMERIC      4
+#define LC_TIME         5
+
+#define LC_C             "C"
+#define LC_C_FRANCE      "FRAN"
+#define LC_C_GERMANY     "GERM"
+#define LC_C_ITALY       "ITAL"
+#define LC_C_SPAIN       "SPAI"
+#define LC_C_UK          "UK"
+#define LC_C_USA         "USA"
+
+struct lconv
+{
+  char *decimal_point;
+  char *thousands_sep;
+  char *grouping;
+  char *int_curr_symbol;
+  char *currency_symbol;
+  char *mon_decimal_point;
+  char *mon_thousands_sep;
+  char *mon_grouping;
+  char *positive_sign;
+  char *negative_sign;
+  char int_frac_digits;
+  char frac_digits;
+  char p_cs_precedes;
+  char p_sep_by_space;
+  char n_cs_precedes;
+  char n_sep_by_space;
+  char p_sign_posn;
+  char n_sign_posn;
+};
+
+
+char *setlocale (int, __const__ char *);
+
+struct lconv *_localeconv (int);
+struct lconv *localeconv (void);
+
+#if defined (__CHAR_UNSIGNED__)
+#define localeconv() _localeconv (255)
+#else
+#define localeconv() _localeconv (127)
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _LOCALE_H */
Index: trunk/src/emx/include/long.cmd
===================================================================
--- trunk/src/emx/include/long.cmd	(revision 18)
+++ trunk/src/emx/include/long.cmd	(revision 18)
@@ -0,0 +1,38 @@
+/* long.cmd */
+
+'@echo off'
+
+call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
+call SysLoadFuncs
+
+if SysSearchPath('PATH', 'sed.exe') == '' then do
+  say 'sed.exe not found -- see INSTALL.DOC'
+  exit
+end
+
+say 'Renaming files'
+do while lines('longshrt.ls1')
+  line = linein('longshrt.ls1')
+  parse var line long short
+  file = filespec('path', translate(long, '\', '/'))||short
+  new = filespec('name', long)
+  if stream(file, 'C', 'QUERY EXISTS') \= '' then
+    'ren' file new
+end
+
+do while lines('longshrt.ls2')
+  file = translate(linein('longshrt.ls2'), '\', '/')
+  if stream(file, 'C', 'QUERY EXISTS') \= '' then do
+    say 'Patching' file
+    'sed -f long.sed >tmp' file
+    if rc \= 0 then do
+      say 'sed failed!'
+      exit
+    end
+    'touch -r' file 'tmp'
+    'del' file
+    'move tmp' file '>nul'
+  end
+end
+
+say 'Done'
Index: trunk/src/emx/include/long.sed
===================================================================
--- trunk/src/emx/include/long.sed	(revision 18)
+++ trunk/src/emx/include/long.sed	(revision 18)
@@ -0,0 +1,49 @@
+/^#[ 	]*include/s|\([<"/]\)algorith\([">]\)|\1algorithm\2|
+/^#[ 	]*include/s|\([<"/]\)AllocRin\.h\([">]\)|\1AllocRing\.h\2|
+/^#[ 	]*include/s|\([<"/]\)BitStrin\.h\([">]\)|\1BitString\.h\2|
+/^#[ 	]*include/s|\([<"/]\)builtinb\.h\([">]\)|\1builtinbuf\.h\2|
+/^#[ 	]*include/s|\([<"/]\)exceptio\([">]\)|\1exception\2|
+/^#[ 	]*include/s|\([<"/]\)function\([">]\)|\1functional\2|
+/^#[ 	]*include/s|\([<"/]\)SplayNod\.ccP\([">]\)|\1SplayNode\.ccP\2|
+/^#[ 	]*include/s|\([<"/]\)SplayNod\.hP\([">]\)|\1SplayNode\.hP\2|
+/^#[ 	]*include/s|\([<"/]\)getpages\.h\([">]\)|\1getpagesize\.h\2|
+/^#[ 	]*include/s|\([<"/]\)hashtabl\.h\([">]\)|\1hashtable\.h\2|
+/^#[ 	]*include/s|\([<"/]\)Incremen\.h\([">]\)|\1Incremental\.h\2|
+/^#[ 	]*include/s|\([<"/]\)indstrea\.h\([">]\)|\1indstream\.h\2|
+/^#[ 	]*include/s|\([<"/]\)parsestr\.h\([">]\)|\1parsestream\.h\2|
+/^#[ 	]*include/s|\([<"/]\)ldcomple\.h\([">]\)|\1ldcomplex\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stdexcep\([">]\)|\1stdexcept\2|
+/^#[ 	]*include/s|\([<"/]\)stdiostr\.h\([">]\)|\1stdiostream\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_algb\.h\([">]\)|\1stl_algobase\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_allo\.h\([">]\)|\1stl_alloc\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_bvec\.h\([">]\)|\1stl_bvector\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_conf\.h\([">]\)|\1stl_config\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_cons\.h\([">]\)|\1stl_construct\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_dequ\.h\([">]\)|\1stl_deque\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_func\.h\([">]\)|\1stl_function\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_htab\.h\([">]\)|\1stl_hashtable\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_hfun\.h\([">]\)|\1stl_hash_fun\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_hmap\.h\([">]\)|\1stl_hash_map\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_hset\.h\([">]\)|\1stl_hash_set\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_iter\.h\([">]\)|\1stl_iterator\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_mmap\.h\([">]\)|\1stl_multimap\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_mset\.h\([">]\)|\1stl_multiset\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_nume\.h\([">]\)|\1stl_numeric\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_queu\.h\([">]\)|\1stl_queue\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_raw_\.h\([">]\)|\1stl_raw_storage_iter\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_relo\.h\([">]\)|\1stl_relops\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_slis\.h\([">]\)|\1stl_slist\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_stac\.h\([">]\)|\1stl_stack\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_temp\.h\([">]\)|\1stl_tempbuf\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_unin\.h\([">]\)|\1stl_uninitialized\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_vect\.h\([">]\)|\1stl_vector\.h\2|
+/^#[ 	]*include/s|\([<"/]\)streambu\.h\([">]\)|\1streambuf\.h\2|
+/^#[ 	]*include/s|\([<"/]\)strstrea\([">]\)|\1strstream\2|
+/^#[ 	]*include/s|\([<"/]\)strstrea\.h\([">]\)|\1strstream\.h\2|
+/^#[ 	]*include/s|\([<"/]\)typemacr\.h\([">]\)|\1typemacros\.h\2|
+/^#[ 	]*include/s|\([<"/]\)type_tra\.h\([">]\)|\1type_traits\.h\2|
+/^#[ 	]*include/s|\([<"/]\)_G_confi\.h\([">]\)|\1_G_config\.h\2|
+/^#[ 	]*include/s|\([<"/]\)NXConstS\.h\([">]\)|\1NXConstStr\.h\2|
+/^#[ 	]*include/s|\([<"/]\)objc-lis\.h\([">]\)|\1objc-list\.h\2|
+/^#[ 	]*include/s|\([<"/]\)typedstr\.h\([">]\)|\1typedstream\.h\2|
+/^#[ 	]*include/s|\([<"/]\)unchecke\.h\([">]\)|\1unchecked\.h\2|
Index: trunk/src/emx/include/longshrt.ls1
===================================================================
--- trunk/src/emx/include/longshrt.ls1	(revision 18)
+++ trunk/src/emx/include/longshrt.ls1	(revision 18)
@@ -0,0 +1,49 @@
+cpp/algorithm algorith
+cpp/AllocRing.h AllocRin.h
+cpp/BitString.h BitStrin.h
+cpp/builtinbuf.h builtinb.h
+cpp/exception exceptio
+cpp/functional function
+cpp/gen/SplayNode.ccP SplayNod.ccP
+cpp/gen/SplayNode.hP SplayNod.hP
+cpp/getpagesize.h getpages.h
+cpp/hashtable.h hashtabl.h
+cpp/Incremental.h Incremen.h
+cpp/indstream.h indstrea.h
+cpp/parsestream.h parsestr.h
+cpp/std/ldcomplex.h ldcomple.h
+cpp/stdexcept stdexcep
+cpp/stdiostream.h stdiostr.h
+cpp/stl_algobase.h stl_algb.h
+cpp/stl_alloc.h stl_allo.h
+cpp/stl_bvector.h stl_bvec.h
+cpp/stl_config.h stl_conf.h
+cpp/stl_construct.h stl_cons.h
+cpp/stl_deque.h stl_dequ.h
+cpp/stl_function.h stl_func.h
+cpp/stl_hashtable.h stl_htab.h
+cpp/stl_hash_fun.h stl_hfun.h
+cpp/stl_hash_map.h stl_hmap.h
+cpp/stl_hash_set.h stl_hset.h
+cpp/stl_iterator.h stl_iter.h
+cpp/stl_multimap.h stl_mmap.h
+cpp/stl_multiset.h stl_mset.h
+cpp/stl_numeric.h stl_nume.h
+cpp/stl_queue.h stl_queu.h
+cpp/stl_raw_storage_iter.h stl_raw_.h
+cpp/stl_relops.h stl_relo.h
+cpp/stl_slist.h stl_slis.h
+cpp/stl_stack.h stl_stac.h
+cpp/stl_tempbuf.h stl_temp.h
+cpp/stl_uninitialized.h stl_unin.h
+cpp/stl_vector.h stl_vect.h
+cpp/streambuf.h streambu.h
+cpp/strstream strstrea
+cpp/strstream.h strstrea.h
+cpp/typemacros.h typemacr.h
+cpp/type_traits.h type_tra.h
+cpp/_G_config.h _G_confi.h
+objc/NXConstStr.h NXConstS.h
+objc/objc-list.h objc-lis.h
+objc/typedstream.h typedstr.h
+unchecked.h unchecke.h
Index: trunk/src/emx/include/longshrt.ls2
===================================================================
--- trunk/src/emx/include/longshrt.ls2	(revision 18)
+++ trunk/src/emx/include/longshrt.ls2	(revision 18)
@@ -0,0 +1,59 @@
+cpp/algo.h
+cpp/algobase.h
+cpp/algorithm
+cpp/alloc.h
+cpp/bool.h
+cpp/builtinbuf.h
+cpp/bvector.h
+cpp/cmath
+cpp/CursesW.h
+cpp/deque
+cpp/deque.h
+cpp/function.h
+cpp/functional
+cpp/hashtable.h
+cpp/hash_map
+cpp/hash_map.h
+cpp/hash_set
+cpp/hash_set.h
+cpp/heap.h
+cpp/iostream.h
+cpp/iterator
+cpp/iterator.h
+cpp/libio.h
+cpp/list
+cpp/map
+cpp/memory
+cpp/minmax.h
+cpp/multimap.h
+cpp/multiset.h
+cpp/new
+cpp/numeric
+cpp/pair.h
+cpp/parsestream.h
+cpp/procbuf.h
+cpp/queue
+cpp/RNG.h
+cpp/rope
+cpp/rope.h
+cpp/set
+cpp/slist
+cpp/slist.h
+cpp/stack
+cpp/stack.h
+cpp/std/complext.h
+cpp/std.h
+cpp/stdexcept
+cpp/stl_algobase.h
+cpp/stl_bvector.h
+cpp/stl_config.h
+cpp/stl_hashtable.h
+cpp/stl_tree.h
+cpp/strstream
+cpp/tempbuf.h
+cpp/typeinfo
+cpp/type_traits.h
+cpp/utility
+cpp/vector
+cpp/vector.h
+objc/Object.h
Index: trunk/src/emx/include/machine/endian.h
===================================================================
--- trunk/src/emx/include/machine/endian.h	(revision 18)
+++ trunk/src/emx/include/machine/endian.h	(revision 18)
@@ -0,0 +1,8 @@
+/* machine/endian.h (emx+gcc) */
+
+#ifndef _MACHINE_ENDIAN_H
+#define _MACHINE_ENDIAN_H
+
+#include <386/endian.h>
+
+#endif /* not _MACHINE_ENDIAN_H */
Index: trunk/src/emx/include/make.cmd
===================================================================
--- trunk/src/emx/include/make.cmd	(revision 18)
+++ trunk/src/emx/include/make.cmd	(revision 18)
@@ -0,0 +1,15 @@
+/* make.cmd */
+
+if stream('unchecked.h', 'C', 'QUERY EXISTS') == '',
+  |stream('cpp\stl_hash_set.h', 'C', 'QUERY EXISTS') == '' then do
+  say 'Do not run this procedure now.'
+  exit 1
+end
+
+'gfind . -type f -print|grep -e "^\(.*/\)*[^/.]\{9,\}\(\.[hc]\|\.cc\|\.hP\|\.ccP\|\)$" >make.$$1'
+'sed -f make1.sed make.$$1 >make.$$2'
+'sed -f make2.sed make.$$1 >longshrt.ls1'
+'gfind . -type f -print|grep -e "^\(.*/\)*[^/.]\+\(\.[hc]\|\.cc|\.hP\|\.ccP\|\)$"|xargs grep -l -f make.$$2 >longshrt.ls2'
+'sed -f make3.sed longshrt.ls1 >short.sed'
+'sed -f make4.sed longshrt.ls1 >long.sed'
+'del make.$$1 make.$$2 >nul'
Index: trunk/src/emx/include/make1.sed
===================================================================
--- trunk/src/emx/include/make1.sed	(revision 18)
+++ trunk/src/emx/include/make1.sed	(revision 18)
@@ -0,0 +1,2 @@
+s/\./\\./g
+s!^\(.*/\)*\(.*\)$!^#[ 	]*include[ 	]*[<"]\\(.*/\\)*\2[>"]!
Index: trunk/src/emx/include/make2.sed
===================================================================
--- trunk/src/emx/include/make2.sed	(revision 18)
+++ trunk/src/emx/include/make2.sed	(revision 18)
@@ -0,0 +1,8 @@
+s!^\(\(.*/\)*\)stl_algobase\.h$!\0 stl_algb.h!
+s!^\(\(.*/\)*\)stl_hashtable\.h$!\0 stl_htab.h!
+s!^\(\(.*/\)*\)stl_hash_fun\.h$!\0 stl_hfun.h!
+s!^\(\(.*/\)*\)stl_hash_map\.h$!\0 stl_hmap.h!
+s!^\(\(.*/\)*\)stl_hash_set\.h$!\0 stl_hset.h!
+s!^\(\(.*/\)*\)stl_multimap\.h$!\0 stl_mmap.h!
+s!^\(\(.*/\)*\)stl_multiset\.h$!\0 stl_mset.h!
+/ /!s!^\(\(.*/\)*\)\([^.][^.][^.][^.][^.][^.][^.][^.]\)[^.][^.]*\(\.[hc]\|\.cc\|\.hP\|\.ccP\|\)$!\0 \3\4!
Index: trunk/src/emx/include/make3.sed
===================================================================
--- trunk/src/emx/include/make3.sed	(revision 18)
+++ trunk/src/emx/include/make3.sed	(revision 18)
@@ -0,0 +1,2 @@
+s/\./\\./g
+s!^\(.*/\)*\(.*\) \(.*\)$!/^#[ 	]*include/s|\\([<"/]\\)\2\\([">]\\)|\\1\3\\2|!
Index: trunk/src/emx/include/make4.sed
===================================================================
--- trunk/src/emx/include/make4.sed	(revision 18)
+++ trunk/src/emx/include/make4.sed	(revision 18)
@@ -0,0 +1,2 @@
+s/\./\\./g
+s!^\(.*/\)*\(.*\) \(.*\)$!/^#[ 	]*include/s|\\([<"/]\\)\3\\([">]\\)|\\1\2\\2|!
Index: trunk/src/emx/include/malloc.h
===================================================================
--- trunk/src/emx/include/malloc.h	(revision 18)
+++ trunk/src/emx/include/malloc.h	(revision 18)
@@ -0,0 +1,63 @@
+/* malloc.h (emx+gcc) */
+
+#ifndef _MALLOC_H
+#define _MALLOC_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+void *calloc (size_t, size_t);
+void free (void *);
+void *malloc (size_t);
+void *realloc (void *, size_t);
+
+
+#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)) \
+    || defined (_WITH_UNDERSCORE)
+
+#if !defined (_HEAPOK)
+#define _HEAPOK       0
+#define _HEAPEMPTY    1
+#define _HEAPBADBEGIN 2
+#define _HEAPBADNODE  3
+#define _HEAPBADEND   4
+#define _HEAPBADROVER 5
+#endif
+
+void *_tcalloc (size_t, size_t);
+void _tfree (void *);
+int _theapmin (void);
+void *_tmalloc (size_t);
+void *_trealloc (void *, size_t);
+
+void *_expand (void *, size_t);
+int _heapchk (void);
+int _heapmin (void);
+int _heapset (unsigned);
+int _heap_walk (int (*)(__const__ void *, size_t, int, int,
+    __const__ char *, size_t));
+size_t _msize (__const__ void *);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _MALLOC_H */
Index: trunk/src/emx/include/math.h
===================================================================
--- trunk/src/emx/include/math.h	(revision 18)
+++ trunk/src/emx/include/math.h	(revision 18)
@@ -0,0 +1,210 @@
+/* math.h (emx+gcc) */
+
+#ifndef _MATH_H
+#define _MATH_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define HUGE_VAL        1e9999
+
+double acos (double);
+double asin (double);
+double atan (double);
+double atan2 (double, double);
+double cbrt (double);
+double ceil (double);
+double cos (double);
+double cosh (double);
+double exp (double);
+double fabs (double);
+double floor (double);
+double fmod (double, double);
+double frexp (double, int *);
+double hypot (double, double);
+double ldexp (double, int);
+double log (double);
+double log10 (double);
+double modf (double, double *);
+double pow (double, double);
+double rint (double);
+double sin (double);
+double sinh (double);
+double sqrt (double);
+double tan (double);
+double tanh (double);
+double trunc (double);
+
+#if !defined (__NO_C9X)
+
+#define HUGE_VALF       1e9999F
+#define HUGE_VALL       1e9999L
+#define INFINITY        1e9999          /* TODO: float_t */
+#define NAN             (0.0/0.0)       /* TODO: Exceptions, float_t */
+
+#define DECIMAL_DIG     21
+
+#define FP_ZERO         0
+#define FP_SUBNORMAL    1
+#define FP_NORMAL       2
+#define FP_INFINITE     3
+#define FP_NAN          4
+
+#define fpclassify(x) \
+    ((sizeof (x) == sizeof (float))  ? __fpclassifyf (x) \
+   : (sizeof (x) == sizeof (double)) ? __fpclassify (x) \
+   :                                   __fpclassifyl (x))
+
+#define signbit(x) \
+    ((sizeof (x) == sizeof (float))  ? __signbitf (x) \
+   : (sizeof (x) == sizeof (double)) ? __signbit (x) \
+   :                                   __signbitl (x))
+
+#define isfinite(x) \
+    ((sizeof (x) == sizeof (float))  ? __isfinitef (x) \
+   : (sizeof (x) == sizeof (double)) ? __isfinite (x) \
+   :                                   __isfinitel (x))
+
+#define isnormal(x) \
+    ((sizeof (x) == sizeof (float))  ? __isnormalf (x) \
+   : (sizeof (x) == sizeof (double)) ? __isnormal (x) \
+   :                                   __isnormall (x))
+
+#define isnan(x) \
+    ((sizeof (x) == sizeof (float))  ? __isnanf (x) \
+   : (sizeof (x) == sizeof (double)) ? __isnan (x) \
+   :                                   __isnanl (x))
+
+float copysignf (float, float);
+double copysign (double, double);
+long double copysignl (long double, long double);
+
+float nextafterf (float, float);
+double nextafter (double, double);
+long double nextafterl (long double, long double);
+
+long double acosl (long double);
+long double asinl (long double);
+long double atanl (long double);
+long double atan2l (long double, long double);
+long double cbrtl (long double);
+long double ceill (long double);
+long double cosl (long double);
+long double coshl (long double);
+long double expl (long double);
+long double fabsl (long double);
+long double floorl (long double);
+long double fmodl (long double, long double);
+long double frexpl (long double, int *);
+long double hypotl (long double, long double);
+long double ldexpl (long double, int);
+long double logl (long double);
+long double log10l (long double);
+long double modfl (long double, long double *);
+long double powl (long double, long double);
+long double rintl (long double);
+long double sinl (long double);
+long double sinhl (long double);
+long double sqrtl (long double);
+long double tanl (long double);
+long double tanhl (long double);
+long double truncl (long double);
+
+int __fpclassify (double);
+int __fpclassifyf (float);
+int __fpclassifyl (long double);
+
+int __signbit (double);
+int __signbitf (float);
+int __signbitl (long double);
+
+int __isfinite (double);
+int __isfinitef (float);
+int __isfinitel (long double);
+
+int __isnormal (double);
+int __isnormalf (float);
+int __isnormall (long double);
+
+int __isnan (double);
+int __isnanf (float);
+int __isnanl (long double);
+
+#endif
+
+#if !defined (__STRICT_ANSI__)
+
+#define HUGE    HUGE_VAL
+
+double atof (__const__ char *);
+
+#if !defined (_ABS)                                    /* see also stdlib.h */
+#define _ABS
+#if !defined (__GNUC__) || __GNUC__ >= 2
+extern int abs (int);
+extern long labs (long);
+#else
+extern __inline__ int abs (int _n) { return (_n < 0 ? -_n : _n); }
+extern __inline__ long labs (long _n) { return (_n < 0 ? -_n : _n); }
+#endif
+#endif
+
+#endif
+
+
+#if !defined (__STRICT_ANSI__) || defined (_WITH_UNDERSCORE)
+
+#define _HUGE_VALF      1e9999F
+#define _HUGE_VALL      1e9999L
+#define _INFINITY       1e9999          /* TODO: float_t */
+#define _NAN            (0.0/0.0)       /* TODO: Exceptions, float_t */
+
+#define _LHUGE_VAL      _HUGE_VALL
+#define _LHUGE          _HUGE_VALL
+
+
+float _copysignf (float, float);
+double _copysign (double, double);
+long double _copysignl (long double, long double);
+
+float _nextafterf (float, float);
+double _nextafter (double, double);
+long double _nextafterl (long double, long double);
+
+long double _acosl (long double);
+long double _asinl (long double);
+long double _atanl (long double);
+long double _atan2l (long double, long double);
+long double _atofl (__const__ char *);
+long double _cbrtl (long double);
+long double _ceill (long double);
+long double _cosl (long double);
+long double _coshl (long double);
+long double _hypotl (long double, long double);
+long double _expl (long double);
+long double _fabsl (long double);
+long double _floorl (long double);
+long double _fmodl (long double, long double);
+long double _frexpl (long double, int *);
+long double _ldexpl (long double, int);
+long double _logl (long double);
+long double _log10l (long double);
+long double _modfl (long double, long double *);
+long double _powl (long double, long double);
+long double _rintl (long double);
+long double _sinl (long double);
+long double _sinhl (long double);
+long double _sqrtl (long double);
+long double _tanl (long double);
+long double _tanhl (long double);
+long double _truncl (long double);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _MATH_H */
Index: trunk/src/emx/include/memory.h
===================================================================
--- trunk/src/emx/include/memory.h	(revision 18)
+++ trunk/src/emx/include/memory.h	(revision 18)
@@ -0,0 +1,44 @@
+/* memory.h (emx+gcc) */
+
+#ifndef _MEMORY_H
+#define _MEMORY_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#if !defined (_MEMDIF_EQ)
+#define _MEMDIF_EQ 0xffffffff
+#endif
+
+void *memccpy (void *, __const__ void *, int, size_t);
+void *memchr (__const__ void *, int, size_t);
+int memcmp (__const__ void *, __const__ void *, size_t);
+void *memcpy (void *, __const__ void *, size_t);
+int memicmp (__const__ void *, __const__ void *, size_t);
+void *memmove (void *, __const__ void *, size_t);
+void *memset (void *s, int, size_t);
+
+size_t _memcount (__const__ void *, int, size_t);
+size_t _memdif (__const__ void *, __const__ void *, size_t);
+void *_memrchr (__const__ void *, int, size_t);
+void _memswap (void *, void *, size_t);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _MEMORY_H */
Index: trunk/src/emx/include/net/if.h
===================================================================
--- trunk/src/emx/include/net/if.h	(revision 18)
+++ trunk/src/emx/include/net/if.h	(revision 18)
@@ -0,0 +1,384 @@
+/* Modifed for emx by hv 1994,1996
+ *
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)if.h	7.11 (Berkeley) 3/19/91
+ *	$Id: if.h,v 1.7 1994/02/10 17:16:33 mycroft Exp $
+ */
+
+#ifndef _NET_IF_H_
+#define _NET_IF_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * Structures defining a network interface, providing a packet
+ * transport mechanism (ala level 0 of the PUP protocols).
+ *
+ * Each interface accepts output datagrams of a specified maximum
+ * length, and provides higher level routines with input datagrams
+ * received from its medium.
+ *
+ * Output occurs when the routine if_output is called, with three parameters:
+ *	(*ifp->if_output)(ifp, m, dst)
+ * Here m is the mbuf chain to be sent and dst is the destination address.
+ * The output routine encapsulates the supplied datagram if necessary,
+ * and then transmits it on its medium.
+ *
+ * On input, each interface unwraps the data received by it, and either
+ * places it on the input queue of a internetwork datagram routine
+ * and posts the associated software interrupt, or passes the datagram to a raw
+ * packet input routine.
+ *
+ * Routines exist for locating interfaces by their addresses
+ * or for locating a interface on a certain network, as well as more general
+ * routing and gateway routines maintaining information used to locate
+ * interfaces.  These routines live in the files if.c and route.c
+ */
+/*  XXX fast fix for SNMP, going away soon */
+#include <sys/time.h>
+
+#ifdef TCPIPV4
+#pragma pack(1)
+#else
+#pragma pack(4)
+#endif
+
+
+/*
+ * Structure defining a queue for a network interface.
+ *
+ * (Would like to call this struct ``if'', but C isn't PL/1.)
+ */
+/*forward*/ struct mbuf;
+/*forward*/ struct ifaddr;
+struct ifnet {
+	char	*if_name;		/* name, e.g. ``en'' or ``lo'' */
+	short	if_unit;		/* sub-unit for lower level driver */
+	short	if_mtu;			/* maximum transmission unit */
+	short	if_flags;		/* up/down, broadcast, etc. */
+	short	if_timer;		/* time 'til if_watchdog called */
+	int	if_metric;		/* routing metric (external only) */
+	struct	ifaddr *if_addrlist;	/* linked list of addresses per if */
+	struct	ifqueue {
+		struct	mbuf *ifq_head;
+		struct	mbuf *ifq_tail;
+#ifndef TCPIPV4
+		int	ifq_len;
+		int	ifq_maxlen;
+		int	ifq_drops;
+#else
+		short	ifq_len;
+		short	ifq_maxlen;
+		u_short	ifq_drops;
+#endif
+	} if_snd;			/* output queue */
+/* procedure handles */
+	int	(*if_init)(void);	/* IBMSOCKETS */
+	int	(*if_output)(void);	/* output routine (enqueue) */
+	int	(*if_ioctl)(void);	/* ioctl routine */
+	int	(*if_reset)(void);	/* bus reset routine */
+	int	(*if_watchdog)(void);	/* timer routine */
+/* generic interface statistics */
+#ifndef TCPIPV4
+	int	if_ipackets;		/* packets received on interface */
+	int	if_ierrors;		/* input errors on interface */
+	int	if_opackets;		/* packets sent on interface */
+	int	if_oerrors;		/* output errors on interface */
+	int	if_collisions;		/* collisions on csma interfaces */
+#else
+	u_short	if_ipackets;		/* packets received on interface */
+	u_short	if_ierrors;		/* input errors on interface */
+	u_short	if_opackets;		/* packets sent on interface */
+	u_short	if_oerrors;		/* output errors on interface */
+	u_short	if_collisions;		/* collisions on csma interfaces */
+#endif
+/* end statistics */
+	struct	ifnet *if_next;
+
+/* the following structures are special for OS/2 TCP/IP only */
+	u_char	if_adapternum;          /* adapter number */
+	u_int	if_adaptype;
+	u_int	if_broadcast;
+	u_long	if_speed;
+
+#define IF_RTTSCALE	1000
+	u_short	if_rtt;                 /* Est interface rtt in ms */
+	u_short	if_rttvar;              /* Est interface rttvar in ms */
+	u_short	if_rttmin;              /* Fixed interface rttmin in ms */
+	u_short	if_sendpipe;            /* Send socket buffer/window size */
+	u_short	if_recvpipe;            /* Recv socket buffer/window size */
+	u_short	if_ssthresh;            /* Gateway buffer limit (slow strt) */
+#ifdef TCPIPV4
+	u_long	if_eflags;		/* Extended flags */
+	struct ifqueue if_traceq;	/* packet trace queue */
+	u_short	if_segsize;		/* segment size for interface */
+	u_short if_use576;		/* use 576 or 1460 as def. mss if */
+					/* going through a router */
+	u_short if_rfc1469;		/* using broadcast or functional */
+					/* addr for IP Multicast */
+#define	IFF_RFC1469_BC	1		/* use broadcast */
+#define	IFF_RFC1469_FA	2		/* use functional address */
+#define	IFF_RFC1469_MA	3		/* use multicast address */
+#endif
+};
+
+#ifndef TCPIPV4
+struct ifmib {
+	int	ifNumber;		/* number of network interfaces */
+	struct iftable {
+		int	ifIndex;	/* index of this interface */
+		char	ifDescr[45];	/* description */
+		int	ifType;		/* type of the interface */
+		int	ifMtu;		/* MTU of the interface */
+		char	ifPhysAddr[6];	/* MTU of the interface */
+		int	ifOperStatus;
+		u_long	ifSpeed;
+		u_long	ifLastChange;
+		u_long	ifInOctets;
+		u_long	ifOutOctets;
+		u_long	ifOutDiscards;
+		u_long	ifInDiscards;
+		u_long	ifInErrors;
+		u_long	ifOutErrors;
+		u_long	ifInUnknownProtos;
+		u_long	ifInUcastPkts;
+		u_long	ifOutUcastPkts;
+		u_long	ifInNUcastPkts;
+		u_long	ifOutNUcastPkts;
+	} iftable[20];
+};
+#else /* TCP/IP V4 */
+
+#ifndef IFMIB_ENTRIES
+#define IFMIB_ENTRIES 42
+#endif
+
+struct ifmib {
+	short	ifNumber;		/* number of network interfaces */
+	struct iftable {
+		short	ifIndex;	/* index of this interface */
+		char	ifDescr[45];	/* description */
+		short	ifType;		/* type of the interface */
+		short	ifMtu;		/* MTU of the interface */
+		char	ifPhysAddr[6];	/* MTU of the interface */
+		short	ifOperStatus;
+		u_long	ifSpeed;
+		u_long	ifLastChange;
+		u_long	ifInOctets;
+		u_long	ifOutOctets;
+		u_long	ifOutDiscards;
+		u_long	ifInDiscards;
+		u_long	ifInErrors;
+		u_long	ifOutErrors;
+		u_long	ifInUnknownProtos;
+		u_long	ifInUcastPkts;
+		u_long	ifOutUcastPkts;
+		u_long	ifInNUcastPkts;
+		u_long	ifOutNUcastPkts;
+	} iftable[IFMIB_ENTRIES];
+};
+#endif /* TCP/IP V4 */
+#pragma pack()
+
+#define	IFF_UP		0x1		/* interface is up */
+#define	IFF_BROADCAST	0x2		/* broadcast address valid */
+#define	IFF_DEBUG	0x4		/* turn on debugging */
+#define	IFF_LOOPBACK	0x8		/* is a loopback net */
+#define	IFF_POINTOPOINT	0x10		/* interface is point-to-point link */
+#define	IFF_NOTRAILERS	0x20		/* avoid use of trailers */
+#define	IFF_RUNNING	0x40		/* resources allocated */
+#define	IFF_NOARP	0x80		/* no address resolution protocol */
+/* next two not supported now, but reserved: */
+#define	IFF_PROMISC	0x100		/* receive all packets */
+#define	IFF_ALLMULTI	0x200		/* receive all multicast packets */
+#define	IFF_OACTIVE	0x400		/* transmission in progress */
+#define	IFF_SIMPLEX	0x800		/* can't hear own transmissions */
+#define	IFF_BRIDGE	0x1000		/* support token ring routine field */
+#define	IFF_SNAP	0x2000		/* support extended SNAP header */
+#define	IFF_ETHER	0x4000		/* ethernet interface */
+#define IFF_LOOPBRD	0x8000		/* ethernet interface */
+
+/*hv: flags set internally only */
+#ifdef BSD_TCPCOMPAT
+#define IFF_CANTCHANGE \
+	(IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE| \
+	IFF_SIMPLEX|IFF_MULTICAST)
+#else
+#define IFF_CANTCHANGE  (IFF_BROADCAST | IFF_POINTOPOINT | IFF_RUNNING)
+#endif
+
+#ifdef TCPIPV4
+/* packet tracing extension */
+#define	IFFE_PKTTRACE	0x00000001	/* trace datalink where possible */
+#define	IFFE_IPTRACE	0x00000002	/* trace ONLY IP packets */
+
+struct pkt_trace_hdr {
+	u_short		pt_htype;	/* header type */
+#define		HT_IP		0x01	/* 	IP */
+#define		HT_ETHER	0x06	/* 	Ethernet */
+#define		HT_ISO88023	0x07	/* 	CSMA CD */
+#define		HT_ISO88025	0x09	/* 	Token Ring */
+#define		HT_SLIP		0x1c	/* 	Serial Line IP */
+#define		HT_PPP		0x18	/* 	PPP IP */
+	u_short		pt_len;		/* in: pt_buf len, out: packet len */
+	caddr_t		pt_data;	/* packet ATTN: This is a _Seg16 addr! */
+	u_long		pt_tstamp;	/* time stamp in milliseconds */
+};
+
+#endif /* TCP/IP V4 */
+
+/*
+ * Output queues (ifp->if_snd) and internetwork datagram level (pup level 1)
+ * input routines have queues of messages stored on ifqueue structures
+ * (defined above).  Entries are added to and deleted from these structures
+ * by these macros, which should be called with ipl raised to splimp().
+ */
+#define	IF_QFULL(ifq)		((ifq)->ifq_len >= (ifq)->ifq_maxlen)
+#define	IF_DROP(ifq)		((ifq)->ifq_drops++)
+#define	IF_ENQUEUE(ifq, m) {\
+        (m)->m_act=0;\
+	if ((ifq)->ifq_tail==0)\
+		(ifq)->ifq_head=m;\
+	else\
+		(ifq)->ifq_tail->m_act=m;\
+	(ifq)->ifq_tail=m;\
+	(ifq)->ifq_len++;\
+}
+#define	IF_PREPEND(ifq, m) {\
+	(m)->m_act=(ifq)->ifq_head;\
+	if ((ifq)->ifq_tail==0)\
+		(ifq)->ifq_tail=(m);\
+	(ifq)->ifq_head=(m);\
+	(ifq)->ifq_len++;\
+}
+#define	IF_DEQUEUE(ifq, m) {\
+	(m)=(ifq)->ifq_head;\
+	if (m) {\
+		if (((ifq)->ifq_head=(m)->m_act)==0)\
+			(ifq)->ifq_tail=0;\
+		(m)->m_act=0;\
+		(ifq)->ifq_len--;\
+	}\
+}
+#define IF_ADJ(m) {\
+	(m)->m_off+=sizeof(struct ifnet*);\
+	(m)->m_len-=sizeof(struct ifnet*);\
+	if ((m)->m_len==0) {\
+		struct mbuf *n;\
+		MFREE((m), n);\
+		(m) = n;\
+	}\
+}
+#define IF_DEQUEUEIF(ifq, m, ifp) {\
+	(m)=(ifq)->ifq_head;\
+	if (m) {\
+		if (((ifq)->ifq_head=(m)->m_act)==0)\
+                        (ifq)->ifq_tail=0;\
+                (m)->m_act=0;\
+                (ifq)->ifq_len--;\
+                (ifp)=*(mtod((m), struct ifnet**));\
+                IF_ADJ(m);\
+        }\
+}
+
+#define	IFQ_MAXLEN	50
+#define	IFNET_SLOWHZ	1	/* granularity is 1 second */
+
+/*
+ * The ifaddr structure contains information about one address
+ * of an interface.  They are maintained by the different address families,
+ * are allocated and attached when an address is set, and are linked
+ * together so all addresses for an interface can be located.
+ */
+struct ifaddr {
+	struct sockaddr	ifa_addr;		/* address of interface */
+	union {
+		struct sockaddr	ifu_broadaddr;	/* broadcast address interface */
+		struct sockaddr	ifu_dstaddr;	/* other end of p-to-p link */
+	} ifa_ifu;
+#define ifa_broadaddr	ifa_ifu.ifu_broadaddr
+#define ifa_dstaddr	ifa_ifu.ifu_dstaddr
+	struct ifnet	*ifa_ifp;		/* back-pointer to interface */
+	struct ifaddr	*ifa_next;		/* next address for interface */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's.  All interface ioctl's must have parameter
+ * definitions which begin with ifr_name.  The
+ * remainder may be interface specific.
+ */
+struct	ifreq {
+#define	IFNAMSIZ	16
+	char	ifr_name[IFNAMSIZ];		/* if name, e.g. "en0" */
+	union {
+		struct	sockaddr ifru_addr;
+		struct	sockaddr ifru_dstaddr;
+		struct	sockaddr ifru_broadaddr;
+		short	ifru_flags;
+		int	ifru_metric;
+		caddr_t	ifru_data;
+	} ifr_ifru;
+#define	ifr_addr	ifr_ifru.ifru_addr	/* address */
+#define	ifr_dstaddr	ifr_ifru.ifru_dstaddr	/* other end of p-to-p link */
+#define	ifr_broadaddr	ifr_ifru.ifru_broadaddr	/* broadcast address */
+#define	ifr_flags	ifr_ifru.ifru_flags	/* flags */
+#define	ifr_metric	ifr_ifru.ifru_metric	/* metric */
+#define	ifr_data	ifr_ifru.ifru_data	/* for use by interface */
+};
+
+/*
+ * Structure used in SIOCGIFCONF request.
+ * Used to retrieve interface configuration
+ * for machine (useful for programs which
+ * must know all networks accessible).
+ */
+struct	ifconf {
+	int	ifc_len;		/* size of associated buffer */
+	union {
+		caddr_t	ifcu_buf;
+		struct	ifreq *ifcu_req;
+	} ifc_ifcu;
+#define	ifc_buf	ifc_ifcu.ifcu_buf	/* buffer address */
+#define	ifc_req	ifc_ifcu.ifcu_req	/* array of structures returned */
+};
+
+#include <net/if_arp.h>
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* _NET_IF_H_ */
Index: trunk/src/emx/include/net/if_arp.h
===================================================================
--- trunk/src/emx/include/net/if_arp.h	(revision 18)
+++ trunk/src/emx/include/net/if_arp.h	(revision 18)
@@ -0,0 +1,88 @@
+/* Modified for emx by hv 1994,1996
+ *
+ * Copyright (c) 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)if_arp.h	7.4 (Berkeley) 6/28/90
+ *	$Id: if_arp.h,v 1.5 1993/09/05 00:46:54 cassidy Exp $
+ */
+
+#ifndef _NET_IF_ARP_H_
+#define _NET_IF_ARP_H_
+
+/*
+ * Address Resolution Protocol.
+ *
+ * See RFC 826 for protocol description.  ARP packets are variable
+ * in size; the arphdr structure defines the fixed-length portion.
+ * Protocol type values are the same as those for 10 Mb/s Ethernet.
+ * It is followed by the variable-sized fields ar_sha, arp_spa,
+ * arp_tha and arp_tpa in that order, according to the lengths
+ * specified.  Field names used correspond to RFC 826.
+ */
+struct	arphdr {
+	u_short	ar_hrd;		/* format of hardware address */
+#define ARPHRD_ETHER 	1	/* ethernet hardware address */
+#define ARPHRD_802	6	/* 802 net hardware address */
+	u_short	ar_pro;		/* format of protocol address */
+	u_char	ar_hln;		/* length of hardware address */
+	u_char	ar_pln;		/* length of protocol address */
+	u_short	ar_op;		/* one of: */
+#define	ARPOP_REQUEST	1	/* request to resolve address */
+#define	ARPOP_REPLY	2	/* response to previous request */
+#define REVARP_REQUEST	3	/* reverse ARP request (not IBM) */
+#define REVARP_REPLY	4	/* reverse ARP reply (not IBM) */
+/*
+ * The remaining fields are variable in size,
+ * according to the sizes above.
+ */
+/*	u_char	ar_sha[];	 * sender hardware address */
+/*	u_char	ar_spa[];	 * sender protocol address */
+/*	u_char	ar_tha[];	 * target hardware address */
+/*	u_char	ar_tpa[];	 * target protocol address */
+};
+
+/*
+ * ARP ioctl request
+ */
+struct arpreq {
+	struct	sockaddr arp_pa;		/* protocol address */
+	struct	sockaddr arp_ha;		/* hardware address */
+	int	arp_flags;			/* flags */
+};
+/*  arp_flags and at_flags field values */
+#define	ATF_INUSE	0x01	/* entry in use */
+#define ATF_COM		0x02	/* completed entry (enaddr valid) */
+#define	ATF_PERM	0x04	/* permanent entry */
+#define	ATF_PUBL	0x08	/* publish entry (respond for other host) */
+#define	ATF_USETRAILERS	0x10	/* has requested trailers */
+
+#endif /* !_NET_IF_ARP_H_ */
Index: trunk/src/emx/include/net/route.h
===================================================================
--- trunk/src/emx/include/net/route.h	(revision 18)
+++ trunk/src/emx/include/net/route.h	(revision 18)
@@ -0,0 +1,191 @@
+/* Modified for emx by hv and em 1994,1996
+ * 
+ * Copyright (c) 1980, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)route.h	7.13 (Berkeley) 4/25/91
+ *	$Id: route.h,v 1.3 1993/05/20 03:06:10 cgd Exp $
+ */
+
+#ifndef _NET_ROUTE_H_
+#define _NET_ROUTE_H_
+
+#include <net/if.h>
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * Kernel resident routing tables.
+ * 
+ * The routing tables are initialized when interface addresses
+ * are set by making entries for all directly connected interfaces.
+ */
+
+/*
+ * A route consists of a destination address and a reference
+ * to a routing entry.  These are often held by protocols
+ * in their control blocks, e.g. inpcb.
+ */
+struct route {
+	struct	rtentry *ro_rt;
+	struct	sockaddr ro_dst;
+};
+
+/*
+ * rmx_rtt and rmx_rttvar are stored as microseconds;
+ * RTTTOPRHZ(rtt) converts to a value suitable for use
+ * by a protocol slowtimo counter.
+ */
+#define	RTM_RTTUNIT	1000000	/* units for rtt, rttvar, as units per sec */
+#define	RTTTOPRHZ(r)	((r) / (RTM_RTTUNIT / PR_SLOWHZ))
+
+/*
+ * We distinguish between routes to hosts and routes to networks,
+ * preferring the former if available.  For each route we infer
+ * the interface to use from the gateway address supplied when
+ * the route was entered.  Routes that forward packets through
+ * gateways are marked so that the output routines know to address the
+ * gateway rather than the ultimate destination.
+ *
+ * Following structure necessary for 4.3 compatibility;
+ */
+struct rtentry {
+	u_long	rt_hash;		/* to speed lookups */
+	struct	sockaddr rt_dst;	/* key */
+	struct	sockaddr rt_gateway;	/* value */
+	short	rt_flags;		/* up/down?, host/net */
+	short	rt_refcnt;		/* # held references */
+	u_long	rt_use;			/* raw # packets forwarded */
+	struct	ifnet *rt_ifp;		/* the answer: interface to use */
+	long metric1,metric2,metric3,metric4; /*IBM special */
+};
+
+#define	RTF_UP		0x1		/* route useable */
+#define	RTF_GATEWAY	0x2		/* destination is a gateway */
+#define	RTF_HOST	0x4		/* host entry (net otherwise) */
+#define	RTF_REJECT	0x8		/* host or net unreachable */
+#define	RTF_DYNAMIC	0x10		/* created dynamically (by redirect) */
+#define	RTF_MODIFIED	0x20		/* modified dynamically (by redirect) */
+#define RTF_DONE	0x40		/* message confirmed */
+#define RTF_MASK	0x80		/* subnet mask present */
+#define RTF_CLONING	0x100		/* generate new routes on use */
+#define RTF_XRESOLVE	0x200		/* external daemon resolves name */
+#define RTF_LLINFO	0x400		/* generated by ARP or ESIS */
+#define	RTF_STATIC	0x800		/* route manually added */
+#define	RTF_BLACKHOLE	0x1000		/* discard packets during updates */
+#define RTF_PROTO2	0x4000		/* protocol specific routing flag */
+#define RTF_PROTO1	0x8000		/* protocol specific routing flag */
+
+
+/*
+ * Routing statistics.
+ */
+struct	rtstat {
+	short	rts_badredirect;	/* bogus redirect calls */
+	short	rts_dynamic;		/* routes created by redirects */
+	short	rts_newgateway;		/* routes modified by redirects */
+	short	rts_unreach;		/* lookups which failed */
+	short	rts_wildcard;		/* lookups satisfied by a wildcard */
+};
+/*
+ * Structures for routing messages.
+ */
+#ifndef __EMX__
+struct rt_msghdr {
+	u_short	rtm_msglen;	/* to skip over non-understood messages */
+	u_char	rtm_version;	/* future binary compatability */
+	u_char	rtm_type;	/* message type */
+	u_short	rtm_index;	/* index for associated ifp */
+	pid_t	rtm_pid;	/* identify sender */
+	int	rtm_addrs;	/* bitmask identifying sockaddrs in msg */
+	int	rtm_seq;	/* for sender to identify action */
+	int	rtm_errno;	/* why failed */
+	int	rtm_flags;	/* flags, incl. kern & message, e.g. DONE */
+	int	rtm_use;	/* from rtentry */
+	u_long	rtm_inits;	/* which metrics we are initializing */
+	struct	rt_metrics rtm_rmx; /* metrics themselves */
+};
+
+struct route_cb {
+	int	ip_count;
+	int	ns_count;
+	int	iso_count;
+	int	any_count;
+};
+#define RTM_VERSION	2	/* Up the ante and ignore older versions */
+
+#define RTM_ADD		0x1	/* Add Route */
+#define RTM_DELETE	0x2	/* Delete Route */
+#define RTM_CHANGE	0x3	/* Change Metrics or flags */
+#define RTM_GET		0x4	/* Report Metrics */
+#define RTM_LOSING	0x5	/* Kernel Suspects Partitioning */
+#define RTM_REDIRECT	0x6	/* Told to use different route */
+#define RTM_MISS	0x7	/* Lookup failed on this address */
+#define RTM_LOCK	0x8	/* fix specified metrics */
+#define RTM_OLDADD	0x9	/* caused by SIOCADDRT */
+#define RTM_OLDDEL	0xa	/* caused by SIOCDELRT */
+#define RTM_RESOLVE	0xb	/* req to resolve dst to LL addr */
+
+#define RTV_MTU		0x1	/* init or lock _mtu */
+#define RTV_HOPCOUNT	0x2	/* init or lock _hopcount */
+#define RTV_EXPIRE	0x4	/* init or lock _hopcount */
+#define RTV_RPIPE	0x8	/* init or lock _recvpipe */
+#define RTV_SPIPE	0x10	/* init or lock _sendpipe */
+#define RTV_SSTHRESH	0x20	/* init or lock _ssthresh */
+#define RTV_RTT		0x40	/* init or lock _rtt */
+#define RTV_RTTVAR	0x80	/* init or lock _rttvar */
+
+#define RTA_DST		0x1	/* destination sockaddr present */
+#define RTA_GATEWAY	0x2	/* gateway sockaddr present */
+#define RTA_NETMASK	0x4	/* netmask sockaddr present */
+#define RTA_GENMASK	0x8	/* cloning mask sockaddr present */
+#define RTA_IFP		0x10	/* interface name sockaddr present */
+#define RTA_IFA		0x20	/* interface addr sockaddr present */
+#define RTA_AUTHOR	0x40	/* sockaddr for author of redirect */
+#endif
+
+/* IBM: hv: I think this is the internal structure of the RT table of the
+ * router daemon. Don't think it belongs here, but the toolkit has it as well
+ */
+#define RTENTRY_COUNT	512
+struct rtentries {
+	short	hostcount;
+	short	netcount;
+	struct rtentry rttable[RTENTRY_COUNT];
+};
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_NET_ROUTE_H_ */
Index: trunk/src/emx/include/netdb.h
===================================================================
--- trunk/src/emx/include/netdb.h	(revision 18)
+++ trunk/src/emx/include/netdb.h	(revision 18)
@@ -0,0 +1,188 @@
+/*- Modified for emx by hv and em 1994-1997
+ *
+ * Copyright (c) 1980, 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)netdb.h	5.15 (Berkeley) 4/3/91
+ *	netdb.h,v 1.1 2003/04/16 15:53:07 bird Exp
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#ifndef _EMX_TCPIP
+#define _EMX_TCPIP
+#endif
+
+#ifdef __RSXNT__    /* convert some int values to short */
+#define __INT_T short
+#pragma pack(1)
+#else /* emx */
+#define __INT_T int
+#endif
+
+extern int h_errno;
+
+#define	_PATH_HEQUIV	"/tcpip/etc/hosts.equiv"
+#define	_PATH_HOSTS	"/tcpip/etc/hosts"
+#define	_PATH_NETWORKS	"/tcpip/etc/networks"
+#define	_PATH_PROTOCOLS	"/tcpip/etc/protocols"
+#define	_PATH_SERVICES	"/tcpip/etc/services"
+
+/*
+ * Structures returned by network data base library.  All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+struct	hostent {
+	char	*h_name;	/* official name of host */
+	char	**h_aliases;	/* alias list */
+	__INT_T	h_addrtype;	/* host address type */
+	__INT_T	h_length;	/* length of address */
+	char	**h_addr_list;	/* list of addresses from name server */
+#define	h_addr	h_addr_list[0]	/* address, for backward compatiblity */
+};
+
+/*
+ * Assumption here is that a network number
+ * fits in 32 bits -- probably a poor one.
+ */
+struct	netent {
+	char		*n_name;	/* official name of net */
+	char		**n_aliases;	/* alias list */
+	__INT_T		n_addrtype;	/* net address type */
+	unsigned long	n_net;		/* network # */
+};
+
+struct	servent {
+	char	*s_name;	/* official service name */
+	char	**s_aliases;	/* alias list */
+	__INT_T	s_port;		/* port # */
+	char	*s_proto;	/* protocol to use */
+};
+
+struct	protoent {
+	char	*p_name;	/* official protocol name */
+	char	**p_aliases;	/* alias list */
+	__INT_T	p_proto;	/* protocol # */
+};
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+#if 0
+#define h_errno (tcp_h_errno())	/* thread safe */
+#endif
+#define	HOST_NOT_FOUND	1 /* Authoritative Answer Host not found */
+#define	TRY_AGAIN	2 /* Non-Authoritive Host not found, or SERVERFAIL */
+#define	NO_RECOVERY	3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define	NO_DATA		4 /* Valid name, no data record of requested type */
+#define	NO_ADDRESS	NO_DATA		/* no address, look for MX record */
+
+int		gethostname (char *, int);
+void		endhostent (void);
+void		endnetent (void);
+void		endprotoent (void);
+void		endservent (void);
+struct hostent	*gethostbyaddr (__const__ char *, int, int);
+struct hostent	*gethostbyname (__const__ char *);
+struct hostent	*gethostent (void);
+struct netent	*getnetbyaddr (u_long, int);
+struct netent	*getnetbyname (__const__ char *);
+struct netent	*getnetent (void);
+struct protoent	*getprotobyname (__const__ char *);
+struct protoent	*getprotobynumber (int);
+struct protoent	*getprotoent (void);
+struct servent	*getservbyname (__const__ char *, __const__ char *);
+struct servent	*getservbyport (int, __const__ char *);
+struct servent	*getservent (void);
+void		herror (__const__ char *);
+void		sethostent (int);
+void		setnetent (int);
+void		setprotoent (int);
+void		setservent (int);
+
+#ifdef NETDB_IBM_ADDENDUM
+
+/* IBM addendum structures and functions */
+#define	_HOSTBUFSIZE	(4096+1)
+#define	_MAXADDRS	35
+#define	_MAXALIASES	35
+#define	_MAXLINELEN	1024
+
+/* this is the internally used data structure to which pointers of 
+ * struct hostent ponit to, after gethostbyname_r/gethostbyaddr_r were
+ * called. ATTENTION EMX: The component _opaque_ is a pointer to a data
+ * structure which is not accessible by EMX
+ */
+struct hostent_data {
+	struct in_addr	host_addr;		/* host address pointer */
+	char	*h_addr_ptrs[_MAXADDRS+1];	/* host address */
+	char	hostaddr[_MAXADDRS];
+	char	hostbuf[_HOSTBUFSIZE+1];	/* host data */
+	char	*host_aliases[_MAXALIASES];
+	char	*host_addrs[2];
+	void	*_opaque_;			/* EMX: dead component! */
+	int	stayopen;			/* AIX addon */
+	u_long	host_addresses[_MAXADDRS];	/* Actual Addresses. */
+};                                              
+
+struct servent_data {
+	void	*_opaque_;
+	char	line[_MAXLINELEN];
+	char	*serv_aliases[_MAXALIASES];
+	int	_serv_stayopen;
+};
+
+int gethostbyname_r(char*, struct hostent*, struct hostent_data*);
+int gethostbyaddr_r(char*, int, int, struct hostent*, struct hostent_data*);
+int getservbyname_r(char*, char*, struct servent*, struct servent_data*);
+struct hostent *_gethtbyname(char*);
+struct hostent *_gethtbyaddr(char*, int, int);
+int tcp_h_errno(void);	/* thread safe h_errno */
+
+#endif /* NETDB_IBM_ADDENDUM */
+
+#ifdef __RSXNT__
+#pragma pack()
+#endif
+#undef __INT_T
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_NETDB_H_ */
Index: trunk/src/emx/include/netinet/if_ether.h
===================================================================
--- trunk/src/emx/include/netinet/if_ether.h	(revision 18)
+++ trunk/src/emx/include/netinet/if_ether.h	(revision 18)
@@ -0,0 +1,138 @@
+/* Modified for emx by hv 1994,1996
+ *
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)if_ether.h	7.5 (Berkeley) 6/28/90
+ *	$Id: if_ether.h,v 1.8 1994/02/02 05:58:54 hpeyerl Exp $
+ */
+
+#ifndef _NETINET_IF_ETHER_H_
+#define _NETINET_IF_ETHER_H_
+
+/*
+ * Ethernet address - 6 octets
+ * this is only used by the ethers(3) functions.
+ */
+struct ether_addr {
+	u_char ether_addr_octet[6];
+};
+
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct	ether_header {
+	u_char	ether_dhost[6];
+	u_char	ether_shost[6];
+	u_short	ether_type;
+};
+
+#define	ETHERTYPE_PUP		0x0200	/* PUP protocol */
+/* the IBM header corrects the following to 0x608 for OS/2 but I believe
+ * this is just a dirty hack 
+ */
+#define	ETHERTYPE_ARP		0x0806	/* address resolution protocol */
+#define	ETHERTYPE_IP		0x0800	/* IP protocol */
+#define	ETHERTYPE_REVARP	0x8035	/* reverse addr resolution protocol */
+
+/*
+ * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
+ * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
+ * by an ETHER type (as given above) and then the (variable-length) header.
+ */
+#define	ETHERTYPE_TRAIL		0x1000		/* Trailer packet */
+#define	ETHERTYPE_NTRAILER	16
+
+#define	ETHERMTU	1500
+#define	ETHERMIN	(60-14)
+
+/*
+ * Ethernet Address Resolution Protocol.
+ *
+ * See RFC 826 for protocol description.  Structure below is adapted
+ * to resolving internet addresses.  Field names used correspond to 
+ * RFC 826.
+ */
+struct	ether_arp {
+	struct	arphdr ea_hdr;	/* fixed-size header */
+	u_char	arp_sha[6];	/* sender hardware address */
+	u_char	arp_spa[4];	/* sender protocol address */
+	u_char	arp_tha[6];	/* target hardware address */
+	u_char	arp_tpa[4];	/* target protocol address */
+};
+#define	arp_hrd	ea_hdr.ar_hrd
+#define	arp_pro	ea_hdr.ar_pro
+#define	arp_hln	ea_hdr.ar_hln
+#define	arp_pln	ea_hdr.ar_pln
+#define	arp_op	ea_hdr.ar_op
+
+
+/*
+ * Structure shared between the ethernet driver modules and
+ * the address resolution code.  For example, each ec_softc or il_softc
+ * begins with this structure.
+ */
+struct	arpcom {
+	struct 	ifnet ac_if;		/* network-visible interface */
+	u_char	ac_enaddr[6];		/* ethernet hardware address */
+	struct in_addr ac_ipaddr;	/* copy of ip address- XXX */
+/* not os2 */
+/*	struct ether_multi *ac_multiaddrs;*/ /* list of ether multicast addrs */
+/*	int ac_multicnt;*/		/* length of ac_multiaddrs list */
+};
+
+/*
+ * Internet to ethernet address resolution table.
+ */
+#ifdef TCPIPV4
+#pragma pack(1)
+#else
+#pragma pack(4)
+#endif
+struct	arptab {
+	struct	in_addr at_iaddr;	/* internet address */
+	u_char	at_enaddr[6];		/* ethernet address */
+	u_char	at_timer;		/* minutes since last reference */
+	u_char	at_flags;		/* flags */
+	struct	mbuf *at_hold;		/* last packet until resolved/timeout */
+/* only os2 */
+	u_short	at_rcf;			/* token ring routing control field */
+	u_short at_rseg[8];		/* token ring routing segments */
+	u_long at_millisec;		/* TOD millsecons of last update */
+#ifdef TCPIPV4
+	short at_interface;		/* interface index */
+#else
+	int at_interface;		/* interface index */
+#endif
+};
+#pragma pack()
+
+#endif /* !_NETINET_IF_ETHER_H_ */
Index: trunk/src/emx/include/netinet/igmp.h
===================================================================
--- trunk/src/emx/include/netinet/igmp.h	(revision 18)
+++ trunk/src/emx/include/netinet/igmp.h	(revision 18)
@@ -0,0 +1,66 @@
+/* Modified for emx by hv 1996
+ *
+ * Copyright (c) 1988 Stephen Deering.
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)igmp.h	7.1 (Berkeley) 7/8/92
+ */
+
+/* Internet Group Management Protocol (IGMP) definitions. */
+
+#ifndef _NETINET_IGMP_H_
+#define _NETINET_IGMP_H_
+
+/*
+ * IGMP packet format.
+ */
+struct igmp {
+	u_char		igmp_type;	/* version & type of IGMP message  */
+	u_char		igmp_code;	/* unused, should be zero          */
+	u_short		igmp_cksum;	/* IP-style checksum               */
+	struct in_addr	igmp_group;	/* group address being reported    */
+};					/*  (zero for queries)             */
+
+#define	IGMP_MINLEN		     8
+
+#define	IGMP_HOST_MEMBERSHIP_QUERY   0x11  /* message types, incl. version */
+#define	IGMP_HOST_MEMBERSHIP_REPORT  0x12
+#define	IGMP_DVMRP		     0x13  /* for experimental multicast   */
+					   /*  routing protocol            */
+
+#define	IGMP_MAX_HOST_REPORT_DELAY   10    /* max delay for response to    */
+					   /*  query (in seconds)          */
+
+#endif
Index: trunk/src/emx/include/netinet/in.h
===================================================================
--- trunk/src/emx/include/netinet/in.h	(revision 18)
+++ trunk/src/emx/include/netinet/in.h	(revision 18)
@@ -0,0 +1,210 @@
+/* Modified for emx by hv and em 1994,1996
+ *
+ * Copyright (c) 1982, 1986, 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)in.h	7.11 (Berkeley) 4/20/91
+ *	$Id: in.h,v 1.8 1994/01/28 13:46:02 deraadt Exp $
+ */
+
+#ifndef _NETINET_IN_H_
+#define _NETINET_IN_H_
+
+#ifndef _EMX_TCPIP
+#define _EMX_TCPIP
+#endif
+
+#include <sys/param.h>          /* htons() etc. */
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * Constants and structures defined by the internet system,
+ * Per RFC 790, September 1981.
+ */
+
+/*
+ * Protocols
+ */
+#define	IPPROTO_IP		0		/* dummy for IP */
+#define	IPPROTO_ICMP		1		/* control message protocol */
+#define	IPPROTO_IGMP		2		/* group mgmt protocol */
+#define	IPPROTO_GGP		3		/* gateway^2 (deprecated) */
+#define	IPPROTO_TCP		6		/* tcp */
+#define	IPPROTO_EGP		8		/* exterior gateway protocol */
+#define	IPPROTO_PUP		12		/* pup */
+#define	IPPROTO_UDP		17		/* user datagram protocol */
+#define	IPPROTO_IDP		22		/* xns idp */
+#define	IPPROTO_TP		29 		/* tp-4 w/ class negotiation */
+#define	IPPROTO_EON		80		/* ISO cnlp */
+
+#define	IPPROTO_RAW		255		/* raw IP packet */
+#define	IPPROTO_MAX		256
+
+
+/*
+ * Local port number conventions:
+ * Ports < IPPORT_RESERVED are reserved for
+ * privileged processes (e.g. root).
+ * Ports > IPPORT_USERRESERVED are reserved
+ * for servers, not necessarily privileged.
+ */
+#define	IPPORT_RESERVED		1024
+#define	IPPORT_USERRESERVED	5000
+
+/*
+ * Internet address (a structure for historical reasons)
+ */
+struct in_addr {
+	u_long s_addr;
+};
+
+/*
+ * Definitions of bits in internet address integers.
+ * On subnets, the decomposition of addresses to host and net parts
+ * is done according to subnet mask, not the masks here.
+ */
+#define	IN_CLASSA(i)		(((long)(i) & 0x80000000) == 0)
+#define	IN_CLASSA_NET		0xff000000
+#define	IN_CLASSA_NSHIFT	24
+#define	IN_CLASSA_HOST		0x00ffffff
+#define	IN_CLASSA_MAX		128
+
+#define	IN_CLASSB(i)		(((long)(i) & 0xc0000000) == 0x80000000)
+#define	IN_CLASSB_NET		0xffff0000
+#define	IN_CLASSB_NSHIFT	16
+#define	IN_CLASSB_HOST		0x0000ffff
+#define	IN_CLASSB_MAX		65536
+
+#define	IN_CLASSC(i)		(((long)(i) & 0xe0000000) == 0xc0000000)
+#define	IN_CLASSC_NET		0xffffff00
+#define	IN_CLASSC_NSHIFT	8
+#define	IN_CLASSC_HOST		0x000000ff
+
+#define	IN_CLASSD(i)		(((long)(i) & 0xf0000000) == 0xe0000000)
+#define	IN_CLASSD_NET		0xf0000000	/* These ones aren't really */
+#define	IN_CLASSD_NSHIFT	28		/* net and host fields, but */
+#define	IN_CLASSD_HOST		0x0fffffff	/* routing needn't know. */
+#define	IN_MULTICAST(i)		IN_CLASSD(i)
+
+#define	IN_EXPERIMENTAL(i)	(((long)(i) & 0xe0000000) == 0xe0000000)
+#define	IN_BADCLASS(i)		(((long)(i) & 0xf0000000) == 0xf0000000)
+
+#define	INADDR_ANY		(u_long)0x00000000
+#define	INADDR_LOOPBACK		(u_long)0x7f000001
+#define	INADDR_BROADCAST	(u_long)0xffffffff	/* must be masked */
+#ifndef KERNEL
+#define	INADDR_NONE		0xffffffff		/* -1 return */
+#endif
+
+#define	INADDR_UNSPEC_GROUP	(u_long)0xe0000000	/* 224.0.0.0 */
+#define	INADDR_ALLHOSTS_GROUP	(u_long)0xe0000001	/* 224.0.0.1 */
+#define	INADDR_MAX_LOCAL_GROUP	(u_long)0xe00000ff	/* 224.0.0.255 */
+
+#define	IN_LOOPBACKNET		127			/* official! */
+
+/*
+ * Define a macro to stuff the loopback address into an Internet address
+ */
+#define	IN_SET_LOOPBACK_ADDR(a) { \
+	(a)->sin_addr.s_addr = htonl(INADDR_LOOPBACK); \
+	(a)->sin_family = AF_INET; }
+/*
+ * Socket address, internet style. 4.3BSD
+ */
+struct sockaddr_in {
+	short	sin_family;
+	u_short	sin_port;
+	struct	in_addr sin_addr;
+	char	sin_zero[8];
+};
+
+/*
+ * Structure used to describe IP options.
+ * Used to store options internally, to pass them to a process,
+ * or to restore options retrieved earlier.
+ * The ip_dst is used for the first-hop gateway when using a source route
+ * (this gets put into the header proper).
+ */
+struct ip_opts {
+	struct	in_addr ip_dst;		/* first hop, 0 w/o src rt */
+	char	ip_opts[40];		/* actually variable in size */
+};
+
+/*
+ * Options for use with [gs]etsockopt at the IP level.
+ * First word of comment is data type; bool is stored in int.
+ */
+#define	IP_OPTIONS		1	/* buf/ip_opts; set/get IP options */
+
+#define	IP_MULTICAST_IF		2	/* u_char; set/get IP mcast i/f */
+#define	IP_MULTICAST_TTL	3	/* u_char; set/get IP mcast ttl */
+#define	IP_MULTICAST_LOOP	4	/* u_char; set/get IP mcast loopback */
+#define	IP_ADD_MEMBERSHIP	5	/* ip_mreq; add IP group membership */
+#define	IP_DROP_MEMBERSHIP	6	/* ip_mreq; drop IP group membership */
+
+#ifndef __EMX__ /* not supported so far */
+#define	IP_HDRINCL		2	/* int; header is included with data */
+#define	IP_TOS			3	/* int; IP type of service and preced */
+#define	IP_TTL			4	/* int; IP time to live */
+#define	IP_RECVOPTS		5	/* bool; receive all IP opts w/dgram */
+#define	IP_RECVRETOPTS		6	/* bool; receive IP opts for response */
+#define	IP_RECVDSTADDR		7	/* bool; receive IP dst addr w/dgram */
+#define	IP_RETOPTS		8	/* ip_opts; set/get IP options */
+#endif
+
+#define	IP_DEFAULT_MULTICAST_TTL   1    /* normally limit m'casts to 1 hop  */
+#define	IP_DEFAULT_MULTICAST_LOOP  1    /* normally hear sends if a member  */
+#define	IP_MAX_MEMBERSHIPS         20   /* per socket; must fit in one mbuf */
+
+/*
+ * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
+ */
+struct ip_mreq {
+	struct	in_addr imr_multiaddr;	/* IP multicast address of group */
+	struct	in_addr imr_interface;	/* local IP address of interface */
+};
+
+/* prototypes for functions in inet(3) */
+extern	u_long		inet_addr(__const__ char*);
+extern	struct in_addr	inet_makeaddr(u_long, u_long);
+extern	u_long		inet_network(__const__ char*);
+extern	char		*inet_ntoa(struct in_addr);
+extern	u_long		inet_netof(struct in_addr);
+extern	u_long		inet_lnaof(struct in_addr);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_NETINET_IN_H_ */
Index: trunk/src/emx/include/netinet/in_systm.h
===================================================================
--- trunk/src/emx/include/netinet/in_systm.h	(revision 18)
+++ trunk/src/emx/include/netinet/in_systm.h	(revision 18)
@@ -0,0 +1,67 @@
+/* Modified for emx by hv 1994,1996
+ *
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)in_systm.h	7.4 (Berkeley) 6/28/90
+ *	$Id: in_systm.h,v 1.4 1994/01/08 23:50:41 mycroft Exp $
+ */
+
+#ifndef _NETINET_IN_SYSTM_H_
+#define _NETINET_IN_SYSTM_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * Miscellaneous internetwork
+ * definitions for kernel.
+ */
+
+/*
+ * Network types.
+ *
+ * Internally the system keeps counters in the headers with the bytes
+ * swapped so that VAX instructions will work on them.  It reverses
+ * the bytes before transmission at each protocol level.  The n_ types
+ * represent the types with the bytes in ``high-ender'' order.
+ */
+typedef u_short n_short;		/* short as received from the net */
+typedef u_long	n_long;			/* long as received from the net */
+
+typedef	u_long	n_time;			/* ms since 00:00 GMT, byte rev */
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_NETINET_IN_SYSTM_H_ */
Index: trunk/src/emx/include/netinet/ip.h
===================================================================
--- trunk/src/emx/include/netinet/ip.h	(revision 18)
+++ trunk/src/emx/include/netinet/ip.h	(revision 18)
@@ -0,0 +1,208 @@
+/* Modified for emx by hv 1994,1996
+ *
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)ip.h	7.10 (Berkeley) 6/28/90
+ *	$Id: ip.h,v 1.4 1994/01/08 21:21:44 mycroft Exp $
+ */
+
+#ifndef _NETINET_IP_H_
+#define _NETINET_IP_H_
+
+#ifdef __EMX__
+#include <machine/endian.h>
+#endif /* __EMX__ */
+
+/*
+ * Definitions for internet protocol version 4.
+ * Per RFC 791, September 1981.
+ */
+#define	IPVERSION	4
+
+/*
+ * Structure of an internet header, naked of options.
+ *
+ * We declare ip_len and ip_off to be short, rather than u_short
+ * pragmatically since otherwise unsigned comparisons can result
+ * against negative integers quite easily, and fail in subtle ways.
+ */
+struct ip {
+#if BYTE_ORDER == LITTLE_ENDIAN
+	u_char	ip_hl:4,		/* header length */
+		ip_v:4;			/* version */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	u_char	ip_v:4,			/* version */
+		ip_hl:4;		/* header length */
+#endif
+	u_char	ip_tos;			/* type of service */
+	short	ip_len;			/* total length */
+	u_short	ip_id;			/* identification */
+	short	ip_off;			/* fragment offset field */
+#define	IP_DF 0x4000			/* dont fragment flag */
+#define	IP_MF 0x2000			/* more fragments flag */
+	u_char	ip_ttl;			/* time to live */
+	u_char	ip_p;			/* protocol */
+	u_short	ip_sum;			/* checksum */
+	struct	in_addr ip_src,ip_dst;	/* source and dest address */
+};
+
+#define	IP_MAXPACKET	32767		/* OS2 maximum packet size */
+
+/*
+ * Definitions for IP type of service (ip_tos)
+ */
+#define	IPTOS_LOWDELAY		0x10
+#define	IPTOS_THROUGHPUT	0x08
+#define	IPTOS_RELIABILITY	0x04
+
+/*
+ * Definitions for IP precedence (also in ip_tos) (hopefully unused)
+ */
+#define	IPTOS_PREC_NETCONTROL		0xe0
+#define	IPTOS_PREC_INTERNETCONTROL	0xc0
+#define	IPTOS_PREC_CRITIC_ECP		0xa0
+#define	IPTOS_PREC_FLASHOVERRIDE	0x80
+#define	IPTOS_PREC_FLASH		0x60
+#define	IPTOS_PREC_IMMEDIATE		0x40
+#define	IPTOS_PREC_PRIORITY		0x20
+#define	IPTOS_PREC_ROUTINE		0x10
+
+/*
+ * Definitions for options.
+ */
+#define	IPOPT_COPIED(o)		((o)&0x80)
+#define	IPOPT_CLASS(o)		((o)&0x60)
+#define	IPOPT_NUMBER(o)		((o)&0x1f)
+
+#define	IPOPT_CONTROL		0x00
+#define	IPOPT_RESERVED1		0x20
+#define	IPOPT_DEBMEAS		0x40
+#define	IPOPT_RESERVED2		0x60
+
+#define	IPOPT_EOL		0		/* end of option list */
+#define	IPOPT_NOP		1		/* no operation */
+
+#define	IPOPT_RR		7		/* record packet route */
+#define	IPOPT_TS		68		/* timestamp */
+#define	IPOPT_SECURITY		130		/* provide s,c,h,tcc */
+#define	IPOPT_LSRR		131		/* loose source route */
+#define	IPOPT_SATID		136		/* satnet id */
+#define	IPOPT_SSRR		137		/* strict source route */
+
+/*
+ * Offsets to fields in options other than EOL and NOP.
+ */
+#define	IPOPT_OPTVAL		0		/* option ID */
+#define	IPOPT_OLEN		1		/* option length */
+#define	IPOPT_OFFSET		2		/* offset within option */
+#define	IPOPT_MINOFF		4		/* min value of above */
+
+/*
+ * Time stamp option structure.
+ */
+struct	ip_timestamp {
+	u_char	ipt_code;		/* IPOPT_TS */
+	u_char	ipt_len;		/* size of structure (variable) */
+	u_char	ipt_ptr;		/* index of current entry */
+#if BYTE_ORDER == LITTLE_ENDIAN
+	u_char	ipt_flg:4,		/* flags, see below */
+		ipt_oflw:4;		/* overflow counter */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	u_char	ipt_oflw:4,		/* overflow counter */
+		ipt_flg:4;		/* flags, see below */
+#endif
+	union ipt_timestamp {
+		n_long	ipt_time[1];
+		struct	ipt_ta {
+			struct in_addr ipt_addr;
+			n_long ipt_time;
+		} ipt_ta[1];
+	} ipt_timestamp;
+};
+
+/* flag bits for ipt_flg */
+#define	IPOPT_TS_TSONLY		0		/* timestamps only */
+#define	IPOPT_TS_TSANDADDR	1		/* timestamps and addresses */
+#define	IPOPT_TS_PRESPEC	3		/* specified modules only */
+
+/* bits for security (not byte swapped) */
+#define	IPOPT_SECUR_UNCLASS	0x0000
+#define	IPOPT_SECUR_CONFID	0xf135
+#define	IPOPT_SECUR_EFTO	0x789a
+#define	IPOPT_SECUR_MMMM	0xbc4d
+#define	IPOPT_SECUR_RESTR	0xaf13
+#define	IPOPT_SECUR_SECRET	0xd788
+#define	IPOPT_SECUR_TOPSECRET	0x6bc5
+
+/*
+ * Internet implementation parameters.
+ */
+#define	MAXTTL		255		/* maximum time to live (seconds) */
+#define	IPFRAGTTL	60		/* time to live for frags, slowhz */
+#define	IPTTLDEC	1		/* subtracted when forwarding */
+
+#define	IP_MSS		576		/* default maximum segment size */
+
+/* hv: this is a new data structure in TCPIPV4; consult IBM's doc for
+ * details (provided they tell anything about it at all)
+ */
+#ifdef TCPIPV4
+struct  ipstat {
+	long	ips_total;
+	long	ips_badsum;
+	long	ips_tooshort;
+	long	ips_toosmall;
+	long	ips_badhlen;
+	long	ips_badlen;
+	long	ips_fragments;
+	long	ips_fragdropped;
+	long	ips_fragtimeout;
+	long	ips_forward;
+	long	ips_cantforward;
+	long	ips_redirectsent;
+	long	ips_ipOutRequests;
+	long	ips_ipOutNoRoutes;
+	long	ips_ipFragFails;
+	long	ips_ipFragOKs;
+	long	ips_ipFragCreates;
+	long	ips_ipReasmOKs;
+	long	ips_ipOutDiscards;
+	long	ips_ipInDiscards;
+	long	ips_ipInAddrErrors;
+	long	ips_ipInDelivers;
+	long	ips_ipInUnknownProtos;
+};
+#endif
+
+#endif /* !_NETINET_IP_H_ */
Index: trunk/src/emx/include/netinet/ip_icmp.h
===================================================================
--- trunk/src/emx/include/netinet/ip_icmp.h	(revision 18)
+++ trunk/src/emx/include/netinet/ip_icmp.h	(revision 18)
@@ -0,0 +1,181 @@
+/* Modified for emx by hv 1994
+ *
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)ip_icmp.h	7.5 (Berkeley) 6/28/90
+ *	$Id$
+ */
+
+#ifndef _NETINET_IP_ICMP_H_
+#define _NETINET_IP_ICMP_H_
+
+/*
+ * Interface Control Message Protocol Definitions.
+ * Per RFC 792, September 1981.
+ */
+
+/*
+ * Structure of an icmp header.
+ */
+struct icmp {
+	u_char	icmp_type;		/* type of message, see below */
+	u_char	icmp_code;		/* type sub code */
+	u_short	icmp_cksum;		/* ones complement cksum of struct */
+	union {
+		u_char ih_pptr;			/* ICMP_PARAMPROB */
+		struct in_addr ih_gwaddr;	/* ICMP_REDIRECT */
+		struct ih_idseq {
+			n_short	icd_id;
+			n_short	icd_seq;
+		} ih_idseq;
+		int ih_void;
+	} icmp_hun;
+#define	icmp_pptr	icmp_hun.ih_pptr
+#define	icmp_gwaddr	icmp_hun.ih_gwaddr
+#define	icmp_id		icmp_hun.ih_idseq.icd_id
+#define	icmp_seq	icmp_hun.ih_idseq.icd_seq
+#define	icmp_void	icmp_hun.ih_void
+	union {
+		struct id_ts {
+			n_time its_otime;
+			n_time its_rtime;
+			n_time its_ttime;
+		} id_ts;
+		struct id_ip  {
+			struct ip idi_ip;
+			/* options and then 64 bits of data */
+		} id_ip;
+		u_long	id_mask;
+		char	id_data[1];
+	} icmp_dun;
+#define	icmp_otime	icmp_dun.id_ts.its_otime
+#define	icmp_rtime	icmp_dun.id_ts.its_rtime
+#define	icmp_ttime	icmp_dun.id_ts.its_ttime
+#define	icmp_ip		icmp_dun.id_ip.idi_ip
+#define	icmp_mask	icmp_dun.id_mask
+#define	icmp_data	icmp_dun.id_data
+};
+
+/*
+ * Lower bounds on packet lengths for various types.
+ * For the error advice packets must first insure that the
+ * packet is large enought to contain the returned ip header.
+ * Only then can we do the check to see if 64 bits of packet
+ * data have been returned, since we need to check the returned
+ * ip header length.
+ */
+#define	ICMP_MINLEN	8				/* abs minimum */
+#define	ICMP_TSLEN	(8 + 3 * sizeof (n_time))	/* timestamp */
+#define	ICMP_MASKLEN	12				/* address mask */
+#define	ICMP_ADVLENMIN	(8 + sizeof (struct ip) + 8)	/* min */
+#define	ICMP_ADVLEN(p)	(8 + ((p)->icmp_ip.ip_hl << 2) + 8)
+	/* N.B.: must separately check that ip_hl >= 5 */
+
+/*
+ * Definition of type and code field values.
+ */
+#define	ICMP_ECHOREPLY		0		/* echo reply */
+#define	ICMP_UNREACH		3		/* dest unreachable, codes: */
+#define		ICMP_UNREACH_NET	0		/* bad net */
+#define		ICMP_UNREACH_HOST	1		/* bad host */
+#define		ICMP_UNREACH_PROTOCOL	2		/* bad protocol */
+#define		ICMP_UNREACH_PORT	3		/* bad port */
+#define		ICMP_UNREACH_NEEDFRAG	4		/* IP_DF caused drop */
+#define		ICMP_UNREACH_SRCFAIL	5		/* src route failed */
+#define	ICMP_SOURCEQUENCH	4		/* packet lost, slow down */
+#define	ICMP_REDIRECT		5		/* shorter route, codes: */
+#define		ICMP_REDIRECT_NET	0		/* for network */
+#define		ICMP_REDIRECT_HOST	1		/* for host */
+#define		ICMP_REDIRECT_TOSNET	2		/* for tos and net */
+#define		ICMP_REDIRECT_TOSHOST	3		/* for tos and host */
+#define	ICMP_ECHO		8		/* echo service */
+#define	ICMP_TIMXCEED		11		/* time exceeded, code: */
+#define		ICMP_TIMXCEED_INTRANS	0		/* ttl==0 in transit */
+#define		ICMP_TIMXCEED_REASS	1		/* ttl==0 in reass */
+#define	ICMP_PARAMPROB		12		/* ip header bad */
+#define	ICMP_TSTAMP		13		/* timestamp request */
+#define	ICMP_TSTAMPREPLY	14		/* timestamp reply */
+#define	ICMP_IREQ		15		/* information request */
+#define	ICMP_IREQREPLY		16		/* information reply */
+#define	ICMP_MASKREQ		17		/* address mask request */
+#define	ICMP_MASKREPLY		18		/* address mask reply */
+
+#define	ICMP_MAXTYPE		18
+
+#define	ICMP_INFOTYPE(type) \
+	((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
+	(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
+	(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
+	(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
+
+/* hv: this is a new TCPIPV4 data structure. Consult IBM's doc on that. */
+#ifdef TCPIPV4
+struct  icmpstat {
+	short	icps_error;
+	short	icps_oldshort;
+	short	icps_oldicmp;
+	short	icps_outhist[ICMP_MAXTYPE + 1];
+	short	icps_badcode;
+	short	icps_tooshort;
+	short	icps_checksum;
+	short	icps_badlen;
+	short	icps_reflect;
+	short	icps_inhist[ICMP_MAXTYPE + 1];
+	u_long	icps_OutMsgs;
+	u_long	icps_OutErrors;
+	u_long	icps_InMsgs;
+	u_long	icps_InDestUnreachs;
+	u_long	icps_InTimeExcds;
+	u_long	icps_InParmProbs;
+	u_long	icps_InSrcQuenchs;
+	u_long	icps_InRedirects;
+	u_long	icps_InEchos;
+	u_long	icps_InEchoReps;
+	u_long	icps_InTimestamps;
+	u_long	icps_InTimestampReps;
+	u_long	icps_InAddrMasks;
+	u_long	icps_InAddrMaskReps;
+	u_long	icps_OutDestUnreachs;
+	u_long	icps_OutTimeExcds;
+	u_long	icps_OutParmProbs;
+	u_long	icps_OutSrcQuenchs;
+	u_long	icps_OutRedirects;
+	u_long	icps_OutEchos;
+	u_long	icps_OutEchoReps;
+	u_long	icps_OutTimestamps;
+	u_long	icps_OutTimestampReps;
+	u_long	icps_OutAddrMasks;
+	u_long	icps_OutAddrMaskReps;
+};
+#endif
+
+#endif /* !_NETINET_IP_ICMP_H_ */
Index: trunk/src/emx/include/netinet/tcp.h
===================================================================
--- trunk/src/emx/include/netinet/tcp.h	(revision 18)
+++ trunk/src/emx/include/netinet/tcp.h	(revision 18)
@@ -0,0 +1,98 @@
+/* Modified for emx by hv 1996
+ *
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)tcp.h	7.7 (Berkeley) 6/28/90
+ *	$Id: tcp.h,v 1.4 1994/01/08 21:21:56 mycroft Exp $
+ */
+
+#ifndef _NETINET_TCP_H_
+#define _NETINET_TCP_H_
+
+#include <machine/endian.h>
+
+typedef	u_long	tcp_seq;
+/*
+ * TCP header.
+ * Per RFC 793, September, 1981.
+ */
+struct tcphdr {
+	u_short	th_sport;		/* source port */
+	u_short	th_dport;		/* destination port */
+	tcp_seq	th_seq;			/* sequence number */
+	tcp_seq	th_ack;			/* acknowledgement number */
+#if BYTE_ORDER == LITTLE_ENDIAN
+	u_char	th_x2:4,		/* (unused) */
+		th_off:4;		/* data offset */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	u_char	th_off:4,		/* data offset */
+		th_x2:4;		/* (unused) */
+#endif
+	u_char	th_flags;
+#define	TH_FIN	0x01
+#define	TH_SYN	0x02
+#define	TH_RST	0x04
+#define	TH_PUSH	0x08
+#define	TH_ACK	0x10
+#define	TH_URG	0x20
+	u_short	th_win;			/* window */
+	u_short	th_sum;			/* checksum */
+	u_short	th_urp;			/* urgent pointer */
+};
+
+#define	TCPOPT_EOL	0
+#define	TCPOPT_NOP	1
+#define	TCPOPT_MAXSEG	2
+
+/*
+ * Default maximum segment size for TCP.
+ * With an IP MSS of 576, this is 536,
+ * but 512 is probably more convenient.
+ * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)).
+ */
+#define	TCP_MSS	512
+
+#define	TCP_MAXWIN	65535		/* largest value for window */
+
+/*
+ * User-settable options (used with setsockopt).
+ */
+#define	TCP_NODELAY	0x01	/* don't delay send to coalesce packets */
+#define	TCP_MAXSEG	0x02	/* set maximum segment size */
+
+/* hv: this is a new data structure in TCPIPV4. */
+#ifdef TCPIPV4
+#include <netinet/tcp_var.h>
+#endif
+
+#endif /* !_NETINET_TCP_H_ */
Index: trunk/src/emx/include/netinet/tcp_var.h
===================================================================
--- trunk/src/emx/include/netinet/tcp_var.h	(revision 18)
+++ trunk/src/emx/include/netinet/tcp_var.h	(revision 18)
@@ -0,0 +1,99 @@
+/* Modified for emx by hv 1996
+ * 
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)tcp_var.h	7.10 (Berkeley) 6/28/90
+ *	$Id: tcp_var.h,v 1.7 1994/01/10 23:27:47 mycroft Exp $
+ */
+
+#ifndef _NETINET_TCP_VAR_H_
+#define _NETINET_TCP_VAR_H_
+
+/*
+ * TCP statistics.
+ * Many of these should be kept per connection,
+ * but that's inconvenient at the moment.
+ */
+#ifdef TCPIPCV4
+struct	tcpstat {
+	u_long	tcps_connattempt;	/* connections initiated */
+	u_long	tcps_accepts;		/* connections accepted */
+	u_long	tcps_connects;		/* connections established */
+	u_long	tcps_drops;		/* connections dropped */
+	u_long	tcps_conndrops;		/* embryonic connections dropped */
+	u_long	tcps_closed;		/* conn. closed (includes drops) */
+	u_long	tcps_segstimed;		/* segs where we tried to get rtt */
+	u_long	tcps_rttupdated;	/* times we succeeded */
+	u_long	tcps_delack;		/* delayed acks sent */
+	u_long	tcps_timeoutdrop;	/* conn. dropped in rxmt timeout */
+	u_long	tcps_rexmttimeo;	/* retransmit timeouts */
+	u_long	tcps_persisttimeo;	/* persist timeouts */
+	u_long	tcps_keeptimeo;		/* keepalive timeouts */
+	u_long	tcps_keepprobe;		/* keepalive probes sent */
+	u_long	tcps_keepdrops;		/* connections dropped in keepalive */
+
+	u_long	tcps_sndtotal;		/* total packets sent */
+	u_long	tcps_sndpack;		/* data packets sent */
+	u_long	tcps_sndbyte;		/* data bytes sent */
+	u_long	tcps_sndrexmitpack;	/* data packets retransmitted */
+	u_long	tcps_sndrexmitbyte;	/* data bytes retransmitted */
+	u_long	tcps_sndacks;		/* ack-only packets sent */
+	u_long	tcps_sndprobe;		/* window probes sent */
+	u_long	tcps_sndurg;		/* packets sent with URG only */
+	u_long	tcps_sndwinup;		/* window update-only packets sent */
+	u_long	tcps_sndctrl;		/* control (SYN|FIN|RST) packets sent */
+
+	u_long	tcps_rcvtotal;		/* total packets received */
+	u_long	tcps_rcvpack;		/* packets received in sequence */
+	u_long	tcps_rcvbyte;		/* bytes received in sequence */
+	u_long	tcps_rcvbadsum;		/* packets received with ccksum errs */
+	u_long	tcps_rcvbadoff;		/* packets received with bad offset */
+	u_long	tcps_rcvshort;		/* packets received too short */
+	u_long	tcps_rcvduppack;	/* duplicate-only packets received */
+	u_long	tcps_rcvdupbyte;	/* duplicate-only bytes received */
+	u_long	tcps_rcvpartduppack;	/* packets with some duplicate data */
+	u_long	tcps_rcvpartdupbyte;	/* dup. bytes in part-dup. packets */
+	u_long	tcps_rcvoopack;		/* out-of-order packets received */
+	u_long	tcps_rcvoobyte;		/* out-of-order bytes received */
+	u_long	tcps_rcvpackafterwin;	/* packets with data after window */
+	u_long	tcps_rcvbyteafterwin;	/* bytes rcvd after window */
+	u_long	tcps_rcvafterclose;	/* packets rcvd after "close" */
+	u_long	tcps_rcvwinprobe;	/* rcvd window probe packets */
+	u_long	tcps_rcvdupack;		/* rcvd duplicate acks */
+	u_long	tcps_rcvacktoomuch;	/* rcvd acks for unsent data */
+	u_long	tcps_rcvackpack;	/* rcvd ack packets */
+	u_long	tcps_rcvackbyte;	/* bytes acked by rcvd acks */
+	u_long	tcps_rcvwinupd;		/* rcvd window update packets */
+};
+#endif
+
+#endif /* !_NETINET_TCP_VAR_H_ */
Index: trunk/src/emx/include/netinet/udp.h
===================================================================
--- trunk/src/emx/include/netinet/udp.h	(revision 18)
+++ trunk/src/emx/include/netinet/udp.h	(revision 18)
@@ -0,0 +1,65 @@
+/* Modified for emx by hv 1996
+ *
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)udp.h	7.4 (Berkeley) 6/28/90
+ *	$Id: udp.h,v 1.3 1993/05/20 03:50:46 cgd Exp $
+ */
+
+#ifndef _NETINET_UDP_H_
+#define _NETINET_UDP_H_
+
+/*
+ * Udp protocol header.
+ * Per RFC 768, September, 1981.
+ */
+struct udphdr {
+	u_short	uh_sport;		/* source port */
+	u_short	uh_dport;		/* destination port */
+	short	uh_ulen;		/* udp length */
+	u_short	uh_sum;			/* udp checksum */
+};
+
+/* hv: this is a new structure of TCPIPV4. Consult IBM's docs on that */
+#ifdef TCPIPV4
+#include <netinet/udp_var.h>
+struct  udpstat {
+	u_long	udps_hdrops;
+	u_long	udps_badsum;
+	u_long	udps_badlen;
+	u_long	udps_udpInDatagrams;
+	u_long	udps_udpNoPorts;
+	u_long	udps_udpOutDatagrams;
+};
+#endif
+
+#endif /* !_NETINET_UDP_H_ */
Index: trunk/src/emx/include/netinet/udp_var.h
===================================================================
--- trunk/src/emx/include/netinet/udp_var.h	(revision 18)
+++ trunk/src/emx/include/netinet/udp_var.h	(revision 18)
@@ -0,0 +1,67 @@
+/* Modified for emx by hv 1996
+ * 
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)udp_var.h	7.7 (Berkeley) 6/28/90
+ *	$Id: udp_var.h,v 1.5 1994/01/10 23:27:48 mycroft Exp $
+ */
+
+#ifndef _NETINET_UDP_VAR_H_
+#define _NETINET_UDP_VAR_H_
+
+#ifdef TCPIPV4
+struct	udpstat {
+				/* input statistics: */
+#ifndef __EMX__
+	u_long	udps_ipackets;		/* total input packets */
+#endif
+	u_long	udps_hdrops;		/* packet shorter than header */
+	u_long	udps_badsum;		/* checksum error */
+	u_long	udps_badlen;		/* data length larger than packet */
+#ifndef __EMX__
+	u_long	udps_noport;		/* no socket on port */
+	u_long	udps_noportbcast;	/* of above, arrived as broadcast */
+	u_long	udps_fullsock;		/* not delivered, input socket full */
+	u_long	udpps_pcbcachemiss;	/* input packets missing pcb cache */
+					/* output statistics: */
+	u_long	udps_opackets;		/* total output packets */
+#else /* __EMX__ */
+	u_long	udps_udpInDatagrams;
+	u_long	udps_udpNoPorts;
+	u_long	udps_udpOutDatagrams;
+#endif /* __EMX__ */
+};
+#endif /* TCPIPV4 */
+
+#define	UDP_TTL		30	/* default time to live for UDP packets */
+
+#endif /* !_NETINET_UDP_VAR_H_ */
Index: trunk/src/emx/include/netnb/nb.h
===================================================================
--- trunk/src/emx/include/netnb/nb.h	(revision 18)
+++ trunk/src/emx/include/netnb/nb.h	(revision 18)
@@ -0,0 +1,40 @@
+/* Copyright (C)1996 by Holger Veit
+ * This file may be freely used within the EMX development system
+ */
+
+/* NETBIOS declarations */
+
+#ifndef _NETNB_NB_H_
+#define _NETNB_NB_H_
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#define	NBPROTO_NB	1
+#define	NB_FAMILY	AF_NETBIOS
+#define	NB_ADDRSIZE	sizeof(struct sockaddr_nb)
+#define	NB_UNIQUE	0
+#define	NB_GROUP	1
+#define	NB_BROAD	2
+#define	NB_NAMELEN	16
+#define	NB_NETIDLEN	8
+#define	NB_HOSTLEN	12
+#define	NB_PORTLEN	4
+/*                       1234567890123456 */
+#define	NB_BCAST_NAME	"*               "
+#define	NB_BLANK_NAME	"                "
+#define NB_NULL_NAME	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+
+#define	NBPORT_RESERVED	IPPORT_RESERVED
+#define	NBPORT_USERRESERVED IPPORT_USERRESERVED
+
+/* address format for netbios */
+struct sockaddr_nb {
+	short	snb_family;		/* protocol family */
+	short	snb_type;		/* unique/multicast */
+	char	snb_netid[NB_NETIDLEN];	/* netid */
+	char	snb_name[NB_NAMELEN];	/* name */
+};
+
+#endif /* !_NETNB_NB_H_ */
+
Index: trunk/src/emx/include/objc/NXConstS.h
===================================================================
--- trunk/src/emx/include/objc/NXConstS.h	(revision 18)
+++ trunk/src/emx/include/objc/NXConstS.h	(revision 18)
@@ -0,0 +1,44 @@
+/* Interface for the NXConstantString class for Objective-C.
+   Copyright (C) 1995 Free Software Foundation, Inc.
+   Contributed by Pieter J. Schoenmakers <tiggr@es.ele.tue.nl>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+ 
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#ifndef __nxconstantstring_INCLUDE_GNU
+#define __nxconstantstring_INCLUDE_GNU
+
+#include "objc/Object.h"
+
+@interface NXConstantString: Object
+{
+  char *c_string;
+  unsigned int len;
+}
+
+-(const char *) cString;
+-(unsigned int) length;
+
+@end
+
+#endif
Index: trunk/src/emx/include/objc/Object.h
===================================================================
--- trunk/src/emx/include/objc/Object.h	(revision 18)
+++ trunk/src/emx/include/objc/Object.h	(revision 18)
@@ -0,0 +1,124 @@
+/* Interface for the Object class for Objective-C.
+   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files compiled
+   with GCC to produce an executable, this does not cause the resulting
+   executable to be covered by the GNU General Public License.  This
+   exception does not however invalidate any other reasons why the
+   executable file might be covered by the GNU General Public License. */
+
+#ifndef __object_INCLUDE_GNU
+#define __object_INCLUDE_GNU
+
+#include <objc/objc.h>
+#include <objc/typedstr.h>
+
+/*
+ * All classes are derived from Object.  As such,
+ * this is the overhead tacked onto those objects.
+ */
+@interface Object
+{
+    Class	isa;	/* A pointer to the instance's class structure */
+}
+
+        /* Initializing classes and instances */
++ initialize;
+- init;
+
+        /* Creating, freeing, and copying instances */
++ new;
++ alloc;
+- free;
+- copy;
+- shallowCopy;
+- deepen;
+- deepCopy;
+
+        /* Identifying classes */
+- (Class)class;
+- (Class)superClass;
+- (MetaClass)metaClass;
+- (const char *)name;
+
+        /* Identifying and comparing objects */
+- self;
+- (unsigned int)hash;
+- (BOOL)isEqual:anObject;
+- (int)compare:anotherObject;
+
+        /* Testing object type */
+- (BOOL)isMetaClass;
+- (BOOL)isClass;
+- (BOOL)isInstance;
+
+        /* Testing inheritance relationships */
+- (BOOL)isKindOf:(Class)aClassObject;
+- (BOOL)isMemberOf:(Class)aClassObject;
+- (BOOL)isKindOfClassNamed:(const char *)aClassName;
+- (BOOL)isMemberOfClassNamed:(const char *)aClassName;
+
+        /* Testing class functionality */
++ (BOOL)instancesRespondTo:(SEL)aSel;
+- (BOOL)respondsTo:(SEL)aSel;
+
+	/* Testing protocol conformance */
+- (BOOL)conformsTo:(Protocol*)aProtocol;
+
+        /* Introspection */
++ (IMP)instanceMethodFor:(SEL)aSel;
+- (IMP)methodFor:(SEL)aSel;
++ (struct objc_method_description *)descriptionForInstanceMethod:(SEL)aSel;
+- (struct objc_method_description *)descriptionForMethod:(SEL)aSel;
+
+        /* Sending messages determined at run time */
+- perform:(SEL)aSel;
+- perform:(SEL)aSel with:anObject;
+- perform:(SEL)aSel with:anObject1 with:anObject2;
+
+        /* Forwarding */
+- (retval_t)forward:(SEL)aSel :(arglist_t)argFrame;
+- (retval_t)performv:(SEL)aSel :(arglist_t)argFrame;
+
+        /* Posing */
++ poseAs:(Class)aClassObject;
+- (Class)transmuteClassTo:(Class)aClassObject;
+
+        /* Enforcing intentions */
+- subclassResponsibility:(SEL)aSel;
+- notImplemented:(SEL)aSel;
+- shouldNotImplement:(SEL)aSel;
+
+        /* Error handling */
+- doesNotRecognize:(SEL)aSel;
+- error:(const char *)aString, ...;
+
+        /* Archiving */
++ (int)version;
++ setVersion:(int)aVersion;
++ (int)streamVersion: (TypedStream*)aStream;
+
+- read: (TypedStream*)aStream;
+- write: (TypedStream*)aStream;
+- awake;
+
+@end
+
+#endif
Index: trunk/src/emx/include/objc/Protocol.h
===================================================================
--- trunk/src/emx/include/objc/Protocol.h	(revision 18)
+++ trunk/src/emx/include/objc/Protocol.h	(revision 18)
@@ -0,0 +1,58 @@
+/* Declare the class Protocol for Objective C programs.
+   Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#ifndef __Protocol_INCLUDE_GNU
+#define __Protocol_INCLUDE_GNU
+
+#include "objc/Object.h"
+
+@interface Protocol : Object
+{
+@private
+        char *protocol_name;
+        struct objc_protocol_list *protocol_list;
+        struct objc_method_description_list *instance_methods, *class_methods; 
+}
+
+/* Obtaining attributes intrinsic to the protocol */
+
+- (const char *)name;
+
+/* Testing protocol conformance */
+
+- (BOOL) conformsTo: (Protocol *)aProtocolObject;
+
+/* Looking up information specific to a protocol */
+
+- (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSel;
+- (struct objc_method_description *) descriptionForClassMethod:(SEL)aSel;
+
+@end
+
+
+
+
+#endif __Protocol_INCLUDE_GNU
Index: trunk/src/emx/include/objc/encoding.h
===================================================================
--- trunk/src/emx/include/objc/encoding.h	(revision 18)
+++ trunk/src/emx/include/objc/encoding.h	(revision 18)
@@ -0,0 +1,75 @@
+/* Encoding of types for Objective C.
+   Copyright (C) 1993, 1997 Free Software Foundation, Inc.
+
+Author: Kresten Krab Thorup
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#ifndef __encoding_INCLUDE_GNU
+#define __encoding_INCLUDE_GNU
+
+#include <ctype.h>
+#include "objc/objc-api.h"
+
+#define _C_CONST    'r'
+#define _C_IN       'n'
+#define _C_INOUT    'N'
+#define _C_OUT      'o'
+#define _C_BYCOPY   'O'
+#define _C_ONEWAY   'V'
+
+#define _F_CONST    0x01
+#define _F_IN       0x01
+#define _F_OUT      0x02
+#define _F_INOUT    0x03
+#define _F_BYCOPY   0x04
+#define _F_ONEWAY   0x08
+
+
+int objc_aligned_size (const char* type);
+int objc_sizeof_type (const char* type);
+int objc_alignof_type (const char* type);
+int objc_aligned_size (const char* type);
+int objc_promoted_size (const char* type);
+const char* objc_skip_type_qualifiers (const char* type);
+const char* objc_skip_typespec (const char* type);
+const char* objc_skip_offset (const char* type);
+const char* objc_skip_argspec (const char* type);
+int method_get_number_of_arguments (struct objc_method*);
+int method_get_sizeof_arguments (struct objc_method*);
+
+char* method_get_first_argument (struct objc_method*,
+				 arglist_t argframe, 
+				 const char** type);
+char* method_get_next_argument (arglist_t argframe, 
+				const char **type);
+char* method_get_nth_argument (struct objc_method* m, 
+			       arglist_t argframe,
+			       int arg, 
+			       const char **type);
+
+unsigned objc_get_type_qualifiers (const char* type);
+
+
+#endif /* __encoding_INCLUDE_GNU */
Index: trunk/src/emx/include/objc/hash.h
===================================================================
--- trunk/src/emx/include/objc/hash.h	(revision 18)
+++ trunk/src/emx/include/objc/hash.h	(revision 18)
@@ -0,0 +1,206 @@
+/* Hash tables for Objective C method dispatch.
+   Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+#ifndef __hash_INCLUDE_GNU
+#define __hash_INCLUDE_GNU
+
+#include <stddef.h>
+#include <objc/objc.h>
+
+/*
+ * This data structure is used to hold items
+ *  stored in a hash table.  Each node holds 
+ *  a key/value pair.
+ *
+ * Items in the cache are really of type void *.
+ */
+typedef struct cache_node
+{
+  struct cache_node *next;	/* Pointer to next entry on the list.
+				   NULL indicates end of list. */
+  const void *key;		/* Key used to locate the value.  Used
+				   to locate value when more than one
+				   key computes the same hash
+				   value. */
+  void *value;			/* Value stored for the key. */
+} *node_ptr;
+
+
+/*
+ * This data type is the function that computes a hash code given a key.
+ * Therefore, the key can be a pointer to anything and the function specific
+ * to the key type. 
+ *
+ * Unfortunately there is a mutual data structure reference problem with this
+ * typedef.  Therefore, to remove compiler warnings the functions passed to
+ * hash_new will have to be casted to this type. 
+ */
+typedef unsigned int (*hash_func_type)(void *, const void *);
+
+/*
+ * This data type is the function that compares two hash keys and returns an
+ * integer greater than, equal to, or less than 0, according as the first
+ * parameter is lexicographically greater than, equal to, or less than the
+ * second. 
+ */
+
+typedef int (*compare_func_type)(const void *, const void *);
+
+
+/*
+ * This data structure is the cache.
+ *
+ * It must be passed to all of the hashing routines
+ *   (except for new).
+ */
+typedef struct cache
+{
+  /* Variables used to implement the hash itself.  */
+  node_ptr *node_table; /* Pointer to an array of hash nodes.  */
+  /* Variables used to track the size of the hash table so to determine
+    when to resize it.  */
+  unsigned int size; /* Number of buckets allocated for the hash table
+			(number of array entries allocated for
+			"node_table").  Must be a power of two.  */
+  unsigned int used; /* Current number of entries in the hash table.  */
+  unsigned int mask; /* Precomputed mask.  */
+
+  /* Variables used to implement indexing through the hash table.  */
+
+  unsigned int last_bucket; /* Tracks which entry in the array where
+			       the last value was returned.  */
+  /* Function used to compute a hash code given a key. 
+     This function is specified when the hash table is created.  */
+  hash_func_type    hash_func;
+  /* Function used to compare two hash keys to see if they are equal.  */
+  compare_func_type compare_func;
+} *cache_ptr;
+
+
+/* Two important hash tables.  */
+extern cache_ptr module_hash_table, class_hash_table;
+
+/* Allocate and initialize a hash table.  */ 
+
+cache_ptr hash_new (unsigned int size,
+		    hash_func_type hash_func,
+		    compare_func_type compare_func);
+                       
+/* Deallocate all of the hash nodes and the cache itself.  */
+
+void hash_delete (cache_ptr cache);
+
+/* Add the key/value pair to the hash table.  If the
+   hash table reaches a level of fullness then it will be resized. 
+                                                   
+   assert if the key is already in the hash.  */
+
+void hash_add (cache_ptr *cachep, const void *key, void *value);
+     
+/* Remove the key/value pair from the hash table.  
+   assert if the key isn't in the table.  */
+
+void hash_remove (cache_ptr cache, const void *key);
+
+/* Used to index through the hash table.  Start with NULL
+   to get the first entry.
+                                                  
+   Successive calls pass the value returned previously.
+   ** Don't modify the hash during this operation *** 
+                                                  
+   Cache nodes are returned such that key or value can
+   be extracted.  */
+
+node_ptr hash_next (cache_ptr cache, node_ptr node);
+
+/* Used to return a value from a hash table using a given key.  */
+
+void *hash_value_for_key (cache_ptr cache, const void *key);
+
+/* Used to determine if the given key exists in the hash table */
+
+BOOL hash_is_key_in_hash (cache_ptr cache, const void *key);
+
+/************************************************
+
+        Useful hashing functions.  
+        
+        Declared inline for your pleasure.
+        
+************************************************/
+
+/* Calculate a hash code by performing some 
+   manipulation of the key pointer.  (Use the lowest bits
+   except for those likely to be 0 due to alignment.)  */
+
+static inline unsigned int
+hash_ptr (cache_ptr cache, const void *key)
+{
+  return ((size_t)key / sizeof (void *)) & cache->mask;
+}
+
+
+/* Calculate a hash code by iterating over a NULL 
+   terminate string.  */
+static inline unsigned int 
+hash_string (cache_ptr cache, const void *key)
+{
+  unsigned int ret = 0;
+  unsigned int ctr = 0;
+        
+        
+  while (*(char*)key) {
+    ret ^= *(char*)key++ << ctr;
+    ctr = (ctr + 1) % sizeof (void *);
+  }
+
+  return ret & cache->mask;
+}
+
+
+/* Compare two pointers for equality.  */
+static inline int 
+compare_ptrs (const void *k1, const void *k2)
+{
+  return !(k1 - k2);
+}
+
+
+/* Compare two strings.  */
+static inline int 
+compare_strings (const void *k1, const void *k2)
+{
+  if (k1 == k2)
+    return 1;
+  else if (k1 == 0 || k2 == 0)
+    return 0;
+  else
+    return !strcmp (k1, k2);
+}
+
+
+#endif /* not __hash_INCLUDE_GNU */
Index: trunk/src/emx/include/objc/objc-api.h
===================================================================
--- trunk/src/emx/include/objc/objc-api.h	(revision 18)
+++ trunk/src/emx/include/objc/objc-api.h	(revision 18)
@@ -0,0 +1,584 @@
+/* GNU Objective-C Runtime API.
+   Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files compiled
+   with GCC to produce an executable, this does not cause the resulting
+   executable to be covered by the GNU General Public License.  This
+   exception does not however invalidate any other reasons why the
+   executable file might be covered by the GNU General Public License. */
+
+#ifndef __objc_api_INCLUDE_GNU
+#define __objc_api_INCLUDE_GNU
+
+#include "objc/objc.h"
+#include "objc/hash.h"
+#include "objc/thr.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+/* For functions which return Method_t */
+#define METHOD_NULL	(Method_t)0
+                                                /* Boolean typedefs */
+/*
+** Method descriptor returned by introspective Object methods.
+** This is really just the first part of the more complete objc_method
+** structure defined below and used internally by the runtime.
+*/
+struct objc_method_description
+{
+    SEL name;			/* this is a selector, not a string */
+    char *types;		/* type encoding */
+};
+
+/* Filer types used to describe Ivars and Methods.  */
+#define _C_ID       '@'
+#define _C_CLASS    '#'
+#define _C_SEL      ':'
+#define _C_CHR      'c'
+#define _C_UCHR     'C'
+#define _C_SHT      's'
+#define _C_USHT     'S'
+#define _C_INT      'i'
+#define _C_UINT     'I'
+#define _C_LNG      'l'
+#define _C_ULNG     'L'
+#define _C_FLT      'f'
+#define _C_DBL      'd'
+#define _C_BFLD     'b'
+#define _C_VOID     'v'
+#define _C_UNDEF    '?'
+#define _C_PTR      '^'
+#define _C_CHARPTR  '*'
+#define _C_ATOM     '%'
+#define _C_ARY_B    '['
+#define _C_ARY_E    ']'
+#define _C_UNION_B  '('
+#define _C_UNION_E  ')'
+#define _C_STRUCT_B '{'
+#define _C_STRUCT_E '}'
+
+
+/*
+** Error handling
+**
+** Call objc_error() or objc_verror() to record an error; this error
+** routine will generally exit the program but not necessarily if the
+** user has installed his own error handler.
+**
+** Call objc_set_error_handler to assign your own function for
+** handling errors.  The function should return YES if it is ok
+** to continue execution, or return NO or just abort if the
+** program should be stopped.  The default error handler is just to
+** print a message on stderr.
+**
+** The error handler function should be of type objc_error_handler
+** The first parameter is an object instance of relevance.
+** The second parameter is an error code.
+** The third parameter is a format string in the printf style.
+** The fourth parameter is a variable list of arguments.
+*/
+extern void objc_error(id object, int code, const char* fmt, ...);
+extern void objc_verror(id object, int code, const char* fmt, va_list ap);
+typedef BOOL (*objc_error_handler)(id, int code, const char *fmt, va_list ap);
+objc_error_handler objc_set_error_handler(objc_error_handler func);
+
+/*
+** Error codes
+** These are used by the runtime library, and your
+** error handling may use them to determine if the error is
+** hard or soft thus whether execution can continue or abort.
+*/
+#define OBJC_ERR_UNKNOWN 0             /* Generic error */
+
+#define OBJC_ERR_OBJC_VERSION 1        /* Incorrect runtime version */
+#define OBJC_ERR_GCC_VERSION 2         /* Incorrect compiler version */
+#define OBJC_ERR_MODULE_SIZE 3         /* Bad module size */
+#define OBJC_ERR_PROTOCOL_VERSION 4    /* Incorrect protocol version */
+
+#define OBJC_ERR_MEMORY 10             /* Out of memory */
+
+#define OBJC_ERR_RECURSE_ROOT 20       /* Attempt to archive the root
+					  object more than once. */
+#define OBJC_ERR_BAD_DATA 21           /* Didn't read expected data */
+#define OBJC_ERR_BAD_KEY 22            /* Bad key for object */
+#define OBJC_ERR_BAD_CLASS 23          /* Unknown class */
+#define OBJC_ERR_BAD_TYPE 24           /* Bad type specification */
+#define OBJC_ERR_NO_READ 25            /* Cannot read stream */
+#define OBJC_ERR_NO_WRITE 26           /* Cannot write stream */
+#define OBJC_ERR_STREAM_VERSION 27     /* Incorrect stream version */
+#define OBJC_ERR_BAD_OPCODE 28         /* Bad opcode */
+
+#define OBJC_ERR_UNIMPLEMENTED 30      /* Method is not implemented */
+
+#define OBJC_ERR_BAD_STATE 40          /* Bad thread state */
+
+/*
+** Set this variable nonzero to print a line describing each
+** message that is sent.  (this is currently disabled)
+*/
+extern BOOL objc_trace;
+
+
+/* For every class which happens to have statically allocated instances in
+   this module, one OBJC_STATIC_INSTANCES is allocated by the compiler.
+   INSTANCES is NULL terminated and points to all statically allocated
+   instances of this class.  */
+struct objc_static_instances
+{
+  char *class_name;
+  id instances[0];
+};
+
+/*
+** Whereas a Module (defined further down) is the root (typically) of a file,
+** a Symtab is the root of the class and category definitions within the
+** module.  
+** 
+** A Symtab contains a variable length array of pointers to classes and
+** categories  defined in the module. 
+*/
+typedef struct objc_symtab {
+  unsigned long sel_ref_cnt;                     /* Unknown. */
+  SEL        refs;                              /* Unknown. */
+  unsigned short cls_def_cnt;                   /* Number of classes compiled
+                                                  (defined) in the module. */
+  unsigned short cat_def_cnt;                   /* Number of categories 
+                                                  compiled (defined) in the 
+                                                  module. */
+
+  void      *defs[1];                           /* Variable array of pointers.
+                                                  cls_def_cnt of type Class 
+                                                  followed by cat_def_cnt of
+                                                  type Category_t, followed
+						  by a NULL terminated array
+						  of objc_static_instances. */
+} Symtab,   *Symtab_t;
+
+
+/*
+** The compiler generates one of these structures for each module that
+** composes the executable (eg main.m).  
+** 
+** This data structure is the root of the definition tree for the module.  
+** 
+** A collect program runs between ld stages and creates a ObjC ctor array. 
+** That array holds a pointer to each module structure of the executable. 
+*/
+typedef struct objc_module {
+  unsigned long version;                        /* Compiler revision. */
+  unsigned long size;                           /* sizeof(Module). */
+  const char* name;                             /* Name of the file where the 
+                                                  module was generated.   The 
+                                                  name includes the path. */
+
+  Symtab_t    symtab;                           /* Pointer to the Symtab of
+                                                  the module.  The Symtab
+                                                  holds an array of 
+						  pointers to 
+                                                  the classes and categories 
+                                                  defined in the module. */
+} Module, *Module_t;
+
+
+/*
+** The compiler generates one of these structures for a class that has
+** instance variables defined in its specification. 
+*/
+typedef struct objc_ivar* Ivar_t;
+typedef struct objc_ivar_list {
+  int   ivar_count;                             /* Number of structures (Ivar) 
+                                                  contained in the list.  One
+                                                  structure per instance 
+                                                  variable defined in the
+                                                  class. */
+  struct objc_ivar {
+    const char* ivar_name;                      /* Name of the instance
+                                                  variable as entered in the
+                                                  class definition. */
+    const char* ivar_type;                      /* Description of the Ivar's
+                                                  type.  Useful for 
+                                                  debuggers. */
+    int        ivar_offset;                    /* Byte offset from the base 
+                                                  address of the instance 
+                                                  structure to the variable. */
+
+  } ivar_list[1];                               /* Variable length 
+                                                  structure. */
+} IvarList, *IvarList_t;
+
+
+/*
+** The compiler generates one (or more) of these structures for a class that
+** has methods defined in its specification. 
+** 
+** The implementation of a class can be broken into separate pieces in a file
+** and categories can break them across modules. To handle this problem is a
+** singly linked list of methods. 
+*/
+typedef struct objc_method Method;
+typedef Method* Method_t;
+typedef struct objc_method_list {
+  struct objc_method_list*  method_next;      /* This variable is used to link 
+                                                a method list to another.  It 
+                                                is a singly linked list. */
+  int            method_count;               /* Number of methods defined in 
+                                                this structure. */
+  struct objc_method {
+    SEL         method_name;                  /* This variable is the method's 
+                                                name.  It is a char*. 
+                                                  The unique integer passed to 
+                                                objc_msg_send is a char* too.  
+                                                It is compared against 
+                                                method_name using strcmp. */
+    const char* method_types;                 /* Description of the method's
+                                                parameter list.  Useful for
+                                                debuggers. */
+    IMP         method_imp;                   /* Address of the method in the 
+                                                executable. */
+  } method_list[1];                           /* Variable length 
+                                                structure. */
+} MethodList, *MethodList_t;
+
+struct objc_protocol_list {
+  struct objc_protocol_list *next;
+  int count;
+  Protocol *list[1];
+};
+
+/*
+** This is used to assure consistent access to the info field of 
+** classes
+*/
+#ifndef HOST_BITS_PER_LONG
+#define HOST_BITS_PER_LONG  (sizeof(long)*8)
+#endif 
+
+#define __CLS_INFO(cls) ((cls)->info)
+#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls)&mask)==mask)
+#define __CLS_SETINFO(cls, mask) (__CLS_INFO(cls) |= mask)
+
+/* The structure is of type MetaClass */
+#define _CLS_META 0x2L
+#define CLS_ISMETA(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_META))
+
+
+/* The structure is of type Class */
+#define _CLS_CLASS 0x1L
+#define CLS_ISCLASS(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_CLASS))
+
+/*
+** The class is initialized within the runtime.  This means that 
+** it has had correct super and sublinks assigned
+*/
+#define _CLS_RESOLV 0x8L
+#define CLS_ISRESOLV(cls) __CLS_ISINFO(cls, _CLS_RESOLV)
+#define CLS_SETRESOLV(cls) __CLS_SETINFO(cls, _CLS_RESOLV)
+
+/*
+** The class has been send a +initialize message or a such is not 
+** defined for this class
+*/
+#define _CLS_INITIALIZED 0x04L
+#define CLS_ISINITIALIZED(cls) __CLS_ISINFO(cls, _CLS_INITIALIZED)
+#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED)
+
+/*
+** The class number of this class.  This must be the same for both the 
+** class and it's meta class object
+*/
+#define CLS_GETNUMBER(cls) (__CLS_INFO(cls) >> (HOST_BITS_PER_LONG/2))
+#define CLS_SETNUMBER(cls, num) \
+  ({ (cls)->info <<= (HOST_BITS_PER_LONG/2); \
+     (cls)->info >>= (HOST_BITS_PER_LONG/2); \
+     __CLS_SETINFO(cls, (((unsigned long)num) << (HOST_BITS_PER_LONG/2))); })
+
+/*
+** The compiler generates one of these structures for each category.  A class
+** may have many categories and contain both instance and factory methods.  
+*/
+typedef struct objc_category {
+  const char*   category_name;                /* Name of the category.  Name
+                                                contained in the () of the
+                                                category definition. */
+  const char*   class_name;                   /* Name of the class to which
+                                                the category belongs. */
+  MethodList_t  instance_methods;             /* Linked list of instance
+                                                methods defined in the 
+                                                category. NULL indicates no
+                                                instance methods defined. */
+  MethodList_t  class_methods;                /* Linked list of factory 
+                                                methods defined in the
+                                                category.  NULL indicates no
+                                                class methods defined. */
+  struct objc_protocol_list *protocols;	      /* List of Protocols 
+					         conformed to */
+} Category, *Category_t;
+
+/*
+** Structure used when a message is send to a class's super class.  The
+** compiler generates one of these structures and passes it to
+** objc_msg_super.
+*/
+typedef struct objc_super {
+  id      self;                           /* Id of the object sending
+                                                the message. */
+  Class class;                              /* Object's super class. */
+} Super, *Super_t;
+
+IMP objc_msg_lookup_super(Super_t super, SEL sel);
+
+retval_t objc_msg_sendv(id, SEL, arglist_t);
+
+
+
+/*
+** This is a hook which is called by objc_lookup_class and
+** objc_get_class if the runtime is not able to find the class.
+** This may e.g. try to load in the class using dynamic loading.
+** The function is guaranteed to be passed a non-NULL name string.
+*/
+extern Class (*_objc_lookup_class)(const char *name);
+
+/*
+** This is a hook which is called by __objc_exec_class every time a class
+** or a category is loaded into the runtime.  This may e.g. help a
+** dynamic loader determine the classes that have been loaded when
+** an object file is dynamically linked in.
+*/
+extern void (*_objc_load_callback)(Class class, Category* category);
+
+/*
+** Hook functions for allocating, copying and disposing of instances
+*/
+extern id (*_objc_object_alloc)(Class class);
+extern id (*_objc_object_copy)(id object);
+extern id (*_objc_object_dispose)(id object);
+
+/*
+** Standard functions for memory allocation and disposal.
+** Users should use these functions in their ObjC programs so
+** that they work properly with garbage collectors as well as
+** can take advantage of the exception/error handling available.
+*/
+void *
+objc_malloc(size_t size);
+
+void *
+objc_atomic_malloc(size_t size);
+
+void *
+objc_valloc(size_t size);
+
+void *
+objc_realloc(void *mem, size_t size);
+
+void *
+objc_calloc(size_t nelem, size_t size);
+
+void
+objc_free(void *mem);
+
+/*
+** Hook functions for memory allocation and disposal.
+** This makes it easy to substitute garbage collection systems
+** such as Boehm's GC by assigning these function pointers
+** to the GC's allocation routines.  By default these point
+** to the ANSI standard malloc, realloc, free, etc.
+**
+** Users should call the normal objc routines above for
+** memory allocation and disposal within their programs.
+*/
+extern void *(*_objc_malloc)(size_t);
+extern void *(*_objc_atomic_malloc)(size_t);
+extern void *(*_objc_valloc)(size_t);
+extern void *(*_objc_realloc)(void *, size_t);
+extern void *(*_objc_calloc)(size_t, size_t);
+extern void (*_objc_free)(void *);
+
+Method_t class_get_class_method(MetaClass class, SEL aSel);
+
+Method_t class_get_instance_method(Class class, SEL aSel);
+
+Class class_pose_as(Class impostor, Class superclass);
+
+Class objc_get_class(const char *name);
+
+Class objc_lookup_class(const char *name);
+
+Class objc_next_class(void **enum_state);
+
+const char *sel_get_name(SEL selector);
+
+const char *sel_get_type(SEL selector);
+
+SEL sel_get_uid(const char *name);
+
+SEL sel_get_any_uid(const char *name);
+
+SEL sel_get_any_typed_uid(const char *name);
+
+SEL sel_get_typed_uid(const char *name, const char*);
+
+SEL sel_register_name(const char *name);
+
+SEL sel_register_typed_name(const char *name, const char*type);
+
+
+BOOL sel_is_mapped (SEL aSel);
+
+extern id class_create_instance(Class class);
+
+static inline const char *
+class_get_class_name(Class class)
+{
+  return CLS_ISCLASS(class)?class->name:((class==Nil)?"Nil":0);
+}
+
+static inline long
+class_get_instance_size(Class class)
+{
+  return CLS_ISCLASS(class)?class->instance_size:0;
+}
+
+static inline MetaClass
+class_get_meta_class(Class class)
+{
+  return CLS_ISCLASS(class)?class->class_pointer:Nil;
+}
+
+static inline Class
+class_get_super_class(Class class)
+{
+  return CLS_ISCLASS(class)?class->super_class:Nil;
+}
+
+static inline int
+class_get_version(Class class)
+{
+  return CLS_ISCLASS(class)?class->version:-1;
+}
+
+static inline BOOL
+class_is_class(Class class)
+{
+  return CLS_ISCLASS(class);
+}
+
+static inline BOOL
+class_is_meta_class(Class class)
+{
+  return CLS_ISMETA(class);
+}
+
+
+static inline void
+class_set_version(Class class, long version)
+{
+  if (CLS_ISCLASS(class))
+    class->version = version;
+}
+
+static inline IMP
+method_get_imp(Method_t method)
+{
+  return (method!=METHOD_NULL)?method->method_imp:(IMP)0;
+}
+
+IMP get_imp (Class class, SEL sel);
+
+/* Redefine on NeXTSTEP so as not to conflict with system function */
+#ifdef __NeXT__
+#define object_copy	gnu_object_copy
+#define object_dispose	gnu_object_dispose
+#endif
+
+id object_copy(id object);
+
+id object_dispose(id object);
+
+static inline Class
+object_get_class(id object)
+{
+  return ((object!=nil)
+	  ? (CLS_ISCLASS(object->class_pointer)
+	     ? object->class_pointer
+	     : (CLS_ISMETA(object->class_pointer)
+		? (Class)object
+		: Nil))
+	  : Nil);
+}
+
+static inline const char *
+object_get_class_name(id object)
+{
+  return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
+                         ?object->class_pointer->name
+                         :((Class)object)->name)
+                       :"Nil");
+}
+
+static inline MetaClass
+object_get_meta_class(id object)
+{
+  return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
+                         ?object->class_pointer->class_pointer
+                         :(CLS_ISMETA(object->class_pointer)
+                           ?object->class_pointer
+                           :Nil))
+                       :Nil);
+}
+
+static inline Class
+object_get_super_class
+(id object)
+{
+  return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
+                         ?object->class_pointer->super_class
+                         :(CLS_ISMETA(object->class_pointer)
+                           ?((Class)object)->super_class
+                           :Nil))
+                       :Nil);
+}
+
+static inline BOOL
+object_is_class(id object)
+{
+  return CLS_ISCLASS((Class)object);
+}
+
+static inline BOOL
+object_is_instance(id object)
+{
+  return (object!=nil)&&CLS_ISCLASS(object->class_pointer);
+}
+
+static inline BOOL
+object_is_meta_class(id object)
+{
+  return CLS_ISMETA((Class)object);
+}
+
+struct sarray* 
+objc_get_uninstalled_dtable(void);
+
+#endif /* not __objc_api_INCLUDE_GNU */
+
+
+
Index: trunk/src/emx/include/objc/objc-lis.h
===================================================================
--- trunk/src/emx/include/objc/objc-lis.h	(revision 18)
+++ trunk/src/emx/include/objc/objc-lis.h	(revision 18)
@@ -0,0 +1,147 @@
+/* Generic single linked list to keep various information 
+   Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+   Contributed by Kresten Krab Thorup.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files compiled with
+   GCC to produce an executable, this does not cause the resulting executable
+   to be covered by the GNU General Public License. This exception does not
+   however invalidate any other reasons why the executable file might be
+   covered by the GNU General Public License.  */
+
+#ifndef __GNU_OBJC_LIST_H
+#define __GNU_OBJC_LIST_H
+
+struct objc_list {
+  void *head;
+  struct objc_list *tail;
+};
+
+/* Return a cons cell produced from (head . tail) */
+
+static inline struct objc_list* 
+list_cons(void* head, struct objc_list* tail)
+{
+  struct objc_list* cell;
+
+  cell = (struct objc_list*)objc_malloc(sizeof(struct objc_list));
+  cell->head = head;
+  cell->tail = tail;
+  return cell;
+}
+
+/* Return the length of a list, list_length(NULL) returns zero */
+
+static inline int
+list_length(struct objc_list* list)
+{
+  int i = 0;
+  while(list)
+    {
+      i += 1;
+      list = list->tail;
+    }
+  return i;
+}
+
+/* Return the Nth element of LIST, where N count from zero.  If N 
+   larger than the list length, NULL is returned  */
+
+static inline void*
+list_nth(int index, struct objc_list* list)
+{
+  while(index-- != 0)
+    {
+      if(list->tail)
+	list = list->tail;
+      else
+	return 0;
+    }
+  return list->head;
+}
+
+/* Remove the element at the head by replacing it by its successor */
+
+static inline void
+list_remove_head(struct objc_list** list)
+{
+  if ((*list)->tail)
+    {
+      struct objc_list* tail = (*list)->tail; /* fetch next */
+      *(*list) = *tail;		/* copy next to list head */
+      objc_free(tail);			/* free next */
+    }
+  else				/* only one element in list */
+    {
+      objc_free(*list);
+      (*list) = 0;
+    }
+}
+
+
+/* Remove the element with `car' set to ELEMENT */
+
+static inline void
+list_remove_elem(struct objc_list** list, void* elem)
+{
+  while (*list) {
+    if ((*list)->head == elem)
+      list_remove_head(list);
+    list = &((*list)->tail);
+  }
+}
+
+/* Map FUNCTION over all elements in LIST */
+
+static inline void
+list_mapcar(struct objc_list* list, void(*function)(void*))
+{
+  while(list)
+    {
+      (*function)(list->head);
+      list = list->tail;
+    }
+}
+
+/* Return element that has ELEM as car */
+
+static inline struct objc_list**
+list_find(struct objc_list** list, void* elem)
+{
+  while(*list)
+    {
+    if ((*list)->head == elem)
+      return list;
+    list = &((*list)->tail);
+    }
+  return NULL;
+}
+
+/* Free list (backwards recursive) */
+
+static void
+list_free(struct objc_list* list)
+{
+  if(list)
+    {
+      list_free(list->tail);
+      objc_free(list);
+    }
+}
+#endif __GNU_OBJC_LIST_H
Index: trunk/src/emx/include/objc/objc.h
===================================================================
--- trunk/src/emx/include/objc/objc.h	(revision 18)
+++ trunk/src/emx/include/objc/objc.h	(revision 18)
@@ -0,0 +1,157 @@
+/* Basic data types for Objective C.
+   Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#ifndef __objc_INCLUDE_GNU
+#define __objc_INCLUDE_GNU
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+/*
+** Definition of the boolean type.  
+*/
+#ifdef __vxworks
+typedef int BOOL;
+#else
+typedef unsigned char  BOOL;
+#endif
+#define YES   (BOOL)1
+#define NO    (BOOL)0
+
+/*
+** Definition of a selector.  Selectors themselves are not unique, but
+** the sel_id is a unique identifier.
+*/
+typedef const struct objc_selector 
+{
+  void *sel_id;
+  const char *sel_types;
+} *SEL;
+
+inline static BOOL
+sel_eq (SEL s1, SEL s2)
+{
+  if (s1 == 0 || s2 == 0)
+    return s1 == s2;
+  else
+    return s1->sel_id == s2->sel_id;
+}
+
+
+/*
+** ObjC uses this typedef for untyped instances.
+*/
+typedef struct objc_object {
+  struct objc_class*  class_pointer;
+} *id;
+
+/*
+** Definition of method type.  When retrieving the implementation of a
+** method, this is type of the pointer returned
+*/
+typedef id (*IMP)(id, SEL, ...); 
+
+/*
+** More simple types...
+*/
+#define nil (id)0                               /* id of Nil instance */
+#define Nil (Class)0                            /* id of Nil class */
+typedef char *STR;                              /* String alias */
+
+/*
+** The compiler generates one of these structures for each class.  
+** 
+** This structure is the definition for classes. 
+** 
+** This structure is generated by the compiler in the executable and used by
+** the run-time during normal messaging operations.  Therefore some members
+** change type. The compiler generates "char* const" and places a string in
+** the following member variables:  super_class. 
+*/
+typedef struct objc_class *MetaClass;
+typedef struct objc_class *Class;
+struct objc_class {     
+  MetaClass           class_pointer;          /* Pointer to the class's
+                                                meta class. */
+  struct objc_class*  super_class;            /* Pointer to the super 
+                                                class. NULL for class 
+                                                Object. */
+  const char*         name;                   /* Name of the class. */
+  long                version;                /* Unknown. */
+  unsigned long       info;                   /* Bit mask.  See class masks 
+                                                defined above. */
+  long                instance_size;          /* Size in bytes of the class.  
+                                                The sum of the class 
+						definition and all super 
+						class definitions. */
+  struct objc_ivar_list* ivars;               /* Pointer to a structure that
+                                                describes the instance 
+                                                variables in the class
+                                                definition.  NULL indicates
+                                                no instance variables.  Does
+                                                not include super class
+                                                variables. */
+  struct objc_method_list*  methods;          /* Linked list of instance
+                                                methods defined for the 
+                                                class. */
+  struct sarray *    dtable;                  /* Pointer to instance 
+					         method dispatch table. */  
+  struct objc_class* subclass_list;           /* Subclasses */
+  struct objc_class* sibling_class;
+
+  struct objc_protocol_list *protocols;	      /* Protocols conformed to */
+};
+
+#ifndef __OBJC__
+typedef struct objc_protocol {
+  struct objc_class* class_pointer;
+  char *protocol_name;
+  struct objc_protocol_list *protocol_list;
+  struct objc_method_description_list *instance_methods, *class_methods; 
+} Protocol; 
+
+#else /* __OBJC__ */
+@class Protocol;
+#endif 
+
+typedef void* retval_t;		/* return value */
+typedef void(*apply_t)(void);	/* function pointer */
+typedef union {
+  char *arg_ptr;
+  char arg_regs[sizeof (char*)];
+} *arglist_t;			/* argument frame */
+
+
+IMP objc_msg_lookup(id receiver, SEL op);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not __objc_INCLUDE_GNU */
Index: trunk/src/emx/include/objc/sarray.h
===================================================================
--- trunk/src/emx/include/objc/sarray.h	(revision 18)
+++ trunk/src/emx/include/objc/sarray.h	(revision 18)
@@ -0,0 +1,238 @@
+/* Sparse Arrays for Objective C dispatch tables
+   Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+   Contributed by Kresten Krab Thorup.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#ifndef __sarray_INCLUDE_GNU
+#define __sarray_INCLUDE_GNU
+
+#define OBJC_SPARSE2		/* 2-level sparse array */
+/* #define OBJC_SPARSE3 */      /* 3-level sparse array */
+
+#ifdef OBJC_SPARSE2
+extern const char* __objc_sparse2_id;
+#endif
+
+#ifdef OBJC_SPARSE3
+extern const char* __objc_sparse3_id;
+#endif
+
+#include <stddef.h>
+
+#include "objc/thr.h"
+
+extern int nbuckets;		/* for stats */
+extern int nindices;
+extern int narrays;
+extern int idxsize;
+
+#include <assert.h>
+
+/* An unsigned integer of same size as a pointer */
+#define SIZET_BITS (sizeof(size_t)*8)
+
+#if defined(__sparc__) || defined(OBJC_SPARSE2)
+#define PRECOMPUTE_SELECTORS
+#endif
+
+#ifdef OBJC_SPARSE3
+
+/* Buckets are 8 words each */
+#define BUCKET_BITS 3
+#define BUCKET_SIZE (1<<BUCKET_BITS)
+#define BUCKET_MASK (BUCKET_SIZE-1)
+
+/* Indices are 16 words each */
+#define INDEX_BITS 4
+#define INDEX_SIZE (1<<INDEX_BITS)
+#define INDEX_MASK (INDEX_SIZE-1)
+
+#define INDEX_CAPACITY (BUCKET_SIZE*INDEX_SIZE)
+
+#else /* OBJC_SPARSE2 */
+
+/* Buckets are 32 words each */
+#define BUCKET_BITS 5
+#define BUCKET_SIZE (1<<BUCKET_BITS)
+#define BUCKET_MASK (BUCKET_SIZE-1)
+
+#endif /* OBJC_SPARSE2 */
+
+typedef size_t sidx;
+
+#ifdef PRECOMPUTE_SELECTORS
+
+struct soffset {
+#ifdef OBJC_SPARSE3
+  unsigned int unused : SIZET_BITS/4;
+  unsigned int eoffset : SIZET_BITS/4;
+  unsigned int boffset : SIZET_BITS/4;
+  unsigned int ioffset : SIZET_BITS/4;
+#else /* OBJC_SPARSE2 */
+#ifdef __sparc__
+  unsigned int boffset : (SIZET_BITS - 2) - BUCKET_BITS;
+  unsigned int eoffset : BUCKET_BITS;
+  unsigned int unused  : 2;
+#else
+  unsigned int boffset : SIZET_BITS/2;
+  unsigned int eoffset : SIZET_BITS/2;
+#endif
+#endif /* OBJC_SPARSE2 */
+};
+
+union sofftype {
+  struct soffset off;
+  sidx idx;
+};
+
+#endif /* not PRECOMPUTE_SELECTORS */
+
+union sversion {
+  int	version;
+  void *next_free;
+};
+
+struct sbucket {
+  void* elems[BUCKET_SIZE];	/* elements stored in array */
+  union sversion	version;		/* used for copy-on-write */
+};
+
+#ifdef OBJC_SPARSE3
+
+struct sindex {
+  struct sbucket* buckets[INDEX_SIZE];
+  union sversion	version;		/* used for copy-on-write */
+};
+
+#endif /* OBJC_SPARSE3 */
+
+struct sarray {
+#ifdef OBJC_SPARSE3
+  struct sindex** indices;
+  struct sindex* empty_index;
+#else /* OBJC_SPARSE2 */
+  struct sbucket** buckets;
+#endif  /* OBJC_SPARSE2 */
+  struct sbucket* empty_bucket;
+  union sversion	version;		/* used for copy-on-write */
+  short ref_count;
+  struct sarray* is_copy_of;
+  size_t capacity;
+};
+
+struct sarray* sarray_new(int, void* default_element);
+void sarray_free(struct sarray*);
+struct sarray* sarray_lazy_copy(struct sarray*);
+void sarray_realloc(struct sarray*, int new_size);
+void sarray_at_put(struct sarray*, sidx index, void* elem);
+void sarray_at_put_safe(struct sarray*, sidx index, void* elem);
+
+struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */
+void sarray_remove_garbage(void);
+
+
+
+#ifdef PRECOMPUTE_SELECTORS
+/* Transform soffset values to ints and vica verca */
+static inline unsigned int
+soffset_decode(sidx index)
+{
+  union sofftype x;
+  x.idx = index;
+#ifdef OBJC_SPARSE3
+  return x.off.eoffset
+    + (x.off.boffset*BUCKET_SIZE)
+      + (x.off.ioffset*INDEX_CAPACITY);
+#else /* OBJC_SPARSE2 */
+  return x.off.eoffset + (x.off.boffset*BUCKET_SIZE);
+#endif /* OBJC_SPARSE2 */
+}
+
+static inline sidx
+soffset_encode(size_t offset)
+{
+  union sofftype x;
+  x.off.eoffset = offset%BUCKET_SIZE;
+#ifdef OBJC_SPARSE3
+  x.off.boffset = (offset/BUCKET_SIZE)%INDEX_SIZE;
+  x.off.ioffset = offset/INDEX_CAPACITY;
+#else /* OBJC_SPARSE2 */
+  x.off.boffset = offset/BUCKET_SIZE;
+#endif
+  return (sidx)x.idx;
+}
+
+#else /* not PRECOMPUTE_SELECTORS */
+
+static inline size_t
+soffset_decode(sidx index)
+{
+  return index;
+}
+
+static inline sidx
+soffset_encode(size_t offset)
+{
+  return offset;
+}
+#endif /* not PRECOMPUTE_SELECTORS */
+
+/* Get element from the Sparse array `array' at offset `index' */
+
+static inline void* sarray_get(struct sarray* array, sidx index)
+{
+#ifdef PRECOMPUTE_SELECTORS
+  union sofftype x;
+  x.idx = index;
+#ifdef OBJC_SPARSE3
+  return 
+    array->
+      indices[x.off.ioffset]->
+	buckets[x.off.boffset]->
+	  elems[x.off.eoffset];
+#else /* OBJC_SPARSE2 */
+  return array->buckets[x.off.boffset]->elems[x.off.eoffset];
+#endif /* OBJC_SPARSE2 */
+#else /* not PRECOMPUTE_SELECTORS */
+#ifdef OBJC_SPARSE3
+  return array->
+    indices[index/INDEX_CAPACITY]->
+      buckets[(index/BUCKET_SIZE)%INDEX_SIZE]->
+	elems[index%BUCKET_SIZE];
+#else /* OBJC_SPARSE2 */
+  return array->buckets[index/BUCKET_SIZE]->elems[index%BUCKET_SIZE];
+#endif /* not OBJC_SPARSE3 */
+#endif /* not PRECOMPUTE_SELECTORS */
+}
+
+static inline void* sarray_get_safe(struct sarray* array, sidx index)
+{
+  if(soffset_decode(index) < array->capacity)
+    return sarray_get(array, index);
+  else
+    return (array->empty_bucket->elems[0]);
+}
+
+#endif /* __sarray_INCLUDE_GNU */
Index: trunk/src/emx/include/objc/thr.h
===================================================================
--- trunk/src/emx/include/objc/thr.h	(revision 18)
+++ trunk/src/emx/include/objc/thr.h	(revision 18)
@@ -0,0 +1,143 @@
+/* Thread and mutex controls for Objective C.
+   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+GNU CC is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public License along with
+GNU CC; see the file COPYING.  If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+#ifndef __thread_INCLUDE_GNU
+#define __thread_INCLUDE_GNU
+
+#include "objc/objc.h"
+
+/*************************************************************************
+ *  Universal static variables:
+ */
+extern int __objc_thread_exit_status;      /* Global exit status.   */
+
+/********
+ *  Thread safe implementation types and functions.  
+ */
+
+/* Thread priorities */
+#define OBJC_THREAD_INTERACTIVE_PRIORITY        2
+#define OBJC_THREAD_BACKGROUND_PRIORITY         1
+#define OBJC_THREAD_LOW_PRIORITY                0
+
+/* A thread */
+typedef void * objc_thread_t;
+
+/* This structure represents a single mutual exclusion lock. */
+struct objc_mutex
+{
+  volatile objc_thread_t owner;     /* Id of thread that owns. */
+  volatile int depth;               /* # of acquires. */
+  void * backend;                   /* Specific to backend */
+};
+typedef struct objc_mutex *objc_mutex_t;
+
+/* This structure represents a single condition mutex */
+struct objc_condition
+{
+  void * backend;                   /* Specific to backend */
+};
+typedef struct objc_condition *objc_condition_t;
+
+/* Frontend mutex functions */
+objc_mutex_t objc_mutex_allocate(void);
+int objc_mutex_deallocate(objc_mutex_t mutex);
+int objc_mutex_lock(objc_mutex_t mutex);
+int objc_mutex_unlock(objc_mutex_t mutex);
+int objc_mutex_trylock(objc_mutex_t mutex);
+
+/* Frontend condition mutex functions */
+objc_condition_t objc_condition_allocate(void);
+int objc_condition_deallocate(objc_condition_t condition);
+int objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex);
+int objc_condition_signal(objc_condition_t condition);
+int objc_condition_broadcast(objc_condition_t condition);
+
+/* Frontend thread functions */
+objc_thread_t objc_thread_detach(SEL selector, id object, id argument);
+void objc_thread_yield(void);
+int objc_thread_exit(void);
+int objc_thread_set_priority(int priority);
+int objc_thread_get_priority(void);
+void * objc_thread_get_data(void);
+int objc_thread_set_data(void *value);
+objc_thread_t objc_thread_id(void);
+
+/*
+  Use this to set the hook function that will be called when the 
+  runtime initially becomes multi threaded.
+  The hook function is only called once, meaning only when the 
+  2nd thread is spawned, not for each and every thread.
+
+  It returns the previous hook function or NULL if there is none.
+
+  A program outside of the runtime could set this to some function so
+  it can be informed; for example, the GNUstep Base Library sets it 
+  so it can implement the NSBecomingMultiThreaded notification.
+  */
+typedef void (*objc_thread_callback)();
+objc_thread_callback objc_set_thread_callback(objc_thread_callback func);
+
+/* Backend initialization functions */
+int __objc_init_thread_system(void);
+int __objc_fini_thread_system(void);
+
+/* Backend mutex functions */
+int __objc_mutex_allocate(objc_mutex_t mutex);
+int __objc_mutex_deallocate(objc_mutex_t mutex);
+int __objc_mutex_lock(objc_mutex_t mutex);
+int __objc_mutex_trylock(objc_mutex_t mutex);
+int __objc_mutex_unlock(objc_mutex_t mutex);
+
+/* Backend condition mutex functions */
+int __objc_condition_allocate(objc_condition_t condition);
+int __objc_condition_deallocate(objc_condition_t condition);
+int __objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex);
+int __objc_condition_broadcast(objc_condition_t condition);
+int __objc_condition_signal(objc_condition_t condition);
+
+/* Backend thread functions */
+objc_thread_t __objc_thread_detach(void (*func)(void *arg), void *arg);
+int __objc_thread_set_priority(int priority);
+int __objc_thread_get_priority(void);
+void __objc_thread_yield(void);
+int __objc_thread_exit(void);
+objc_thread_t __objc_thread_id(void);
+int __objc_thread_set_data(void *value);
+void * __objc_thread_get_data(void);
+
+#endif /* not __thread_INCLUDE_GNU */
Index: trunk/src/emx/include/objc/typedstr.h
===================================================================
--- trunk/src/emx/include/objc/typedstr.h	(revision 18)
+++ trunk/src/emx/include/objc/typedstr.h	(revision 18)
@@ -0,0 +1,132 @@
+/* GNU Objective-C Typed Streams interface.
+   Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files compiled
+   with GCC to produce an executable, this does not cause the resulting
+   executable to be covered by the GNU General Public License.  This
+   exception does not however invalidate any other reasons why the
+   executable file might be covered by the GNU General Public License. */
+
+#ifndef __typedstream_INCLUDE_GNU
+#define __typedstream_INCLUDE_GNU
+
+#include "objc/objc.h"
+#include "objc/hash.h"
+#include <stdio.h>
+
+typedef int (*objc_typed_read_func)(void*, char*, int);
+typedef int (*objc_typed_write_func)(void*, const char*, int);
+typedef int (*objc_typed_flush_func)(void*);
+typedef int (*objc_typed_eof_func)(void*);
+
+#define OBJC_READONLY   0x01
+#define OBJC_WRITEONLY  0x02
+
+#define OBJC_MANAGED_STREAM  0x01
+#define OBJC_FILE_STREAM     0x02
+#define OBJC_MEMORY_STREAM   0x04
+
+#define OBJC_TYPED_STREAM_VERSION 0x01
+
+typedef struct objc_typed_stream {
+  void* physical;
+  cache_ptr object_table;	/* read/written objects */
+  cache_ptr stream_table;	/* other read/written but shared things.. */
+  cache_ptr class_table;	/* class version mapping */
+  cache_ptr object_refs;	/* forward references */
+  int mode;			/* OBJC_READONLY or OBJC_WRITEONLY */
+  int type;			/* MANAGED, FILE, MEMORY etc bit string */
+  int version;			/* version used when writing */
+  int writing_root_p;
+  objc_typed_read_func read;
+  objc_typed_write_func write;
+  objc_typed_eof_func eof;
+  objc_typed_flush_func flush;
+} TypedStream;
+
+/* opcode masks */
+#define _B_VALUE   0x1fU
+#define _B_CODE    0xe0U
+#define _B_SIGN    0x10U
+#define _B_NUMBER  0x0fU
+
+/* standard opcodes */
+#define _B_INVALID 0x00U
+#define _B_SINT    0x20U
+#define _B_NINT    0x40U
+#define _B_SSTR    0x60U
+#define _B_NSTR    0x80U
+#define _B_RCOMM   0xa0U
+#define _B_UCOMM   0xc0U
+#define _B_EXT     0xe0U
+
+/* eXtension opcodes */
+#define _BX_OBJECT  0x00U
+#define _BX_CLASS   0x01U
+#define _BX_SEL     0x02U
+#define _BX_OBJREF  0x03U
+#define _BX_OBJROOT 0x04U
+#define _BX_EXT     0x1fU
+
+/*
+** Read and write objects as specified by TYPE.  All the `last'
+** arguments are pointers to the objects to read/write.  
+*/
+
+int objc_write_type (TypedStream* stream, const char* type, const void* data);
+int objc_read_type (TypedStream* stream, const char* type, void* data);
+
+int objc_write_types (TypedStream* stream, const char* type, ...);
+int objc_read_types (TypedStream* stream, const char* type, ...);
+
+int objc_write_object_reference (TypedStream* stream, id object);
+int objc_write_root_object (TypedStream* stream, id object);
+
+long objc_get_stream_class_version (TypedStream* stream, Class class);
+
+
+/*
+** Convenience functions
+*/
+
+int objc_write_array (TypedStream* stream, const char* type,
+		      int count, const void* data);
+int objc_read_array (TypedStream* stream, const char* type,
+		     int count, void* data);
+
+int objc_write_object (TypedStream* stream, id object);
+int objc_read_object (TypedStream* stream, id* object);
+
+
+
+/*
+** Open a typed stream for reading or writing.  MODE may be either of
+** OBJC_READONLY or OBJC_WRITEONLY.  
+*/
+
+TypedStream* objc_open_typed_stream (FILE* physical, int mode);
+TypedStream* objc_open_typed_stream_for_file (const char* file_name, int mode);
+
+void objc_close_typed_stream (TypedStream* stream);
+
+BOOL objc_end_of_typed_stream (TypedStream* stream);
+void objc_flush_typed_stream (TypedStream* stream);
+
+#endif /* not __typedstream_INCLUDE_GNU */
Index: trunk/src/emx/include/os2.h
===================================================================
--- trunk/src/emx/include/os2.h	(revision 18)
+++ trunk/src/emx/include/os2.h	(revision 18)
@@ -0,0 +1,28 @@
+/* os2.h (emx+gcc) */
+
+#ifndef _OS2_H
+#define _OS2_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define _Cdecl
+#define _Far16
+#define _Optlink
+#define _Pascal
+#define _Seg16
+#define _System
+
+#if defined (USE_OS2_TOOLKIT_HEADERS)
+#include <os2tk.h>
+#else
+#include <os2emx.h>          /* <-- change this line to use Toolkit headers */
+#endif
+#include <os2thunk.h>
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _OS2_H */
Index: trunk/src/emx/include/os2emx.h
===================================================================
--- trunk/src/emx/include/os2emx.h	(revision 18)
+++ trunk/src/emx/include/os2emx.h	(revision 18)
@@ -0,0 +1,12591 @@
+/* os2emx.h (emx+gcc) */
+
+#ifndef _OS2EMX_H
+#define _OS2EMX_H
+
+#pragma pack(1)
+
+/* ------------------------ INCL_ SYMBOLS --------------------------------- */
+
+#if defined (INCL_BASE)
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_SUB
+#endif
+
+#if defined (INCL_DOS)
+#define INCL_DOSDATETIME
+#define INCL_DOSDEVICES
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSFILEMGR
+#define INCL_DOSMEMMGR
+#define INCL_DOSMISC
+#define INCL_DOSMVDM
+#define INCL_DOSMODULEMGR
+#define INCL_DOSNLS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSRAS
+#define INCL_DOSQUEUES
+#define INCL_DOSRESOURCES
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSSESMGR
+#endif
+
+#if defined (INCL_REXXSAA)
+#define INCL_RXSUBCOM
+#define INCL_RXSHV
+#define INCL_RXFUNC
+#define INCL_RXSYSEXIT
+#define INCL_RXMACRO
+#define INCL_RXARI
+#endif
+
+#if defined (INCL_SUB)
+#define INCL_KBD
+#define INCL_VIO
+#define INCL_MOU
+#endif
+
+#if defined (INCL_PM)
+#define INCL_AVIO
+#define INCL_FONTFILEFORMAT
+#define INCL_GPI
+#define INCL_SPL
+#define INCL_WIN
+#define INCL_WINWORKPLACE
+#endif
+
+#if defined (INCL_WIN) || defined (RC_INVOKED)
+#define INCL_WINACCELERATORS
+#define INCL_WINBUTTONS
+#define INCL_WINDIALOGS
+#define INCL_WINENTRYFIELDS
+#define INCL_WINFRAMECTLS
+#define INCL_WINFRAMEMGR
+#define INCL_WINHELP
+#define INCL_WININPUT
+#define INCL_WINLISTBOXES
+#define INCL_WINMENUS
+#define INCL_WINMESSAGEMGR
+#define INCL_WINMLE
+#define INCL_WINPOINTERS
+#define INCL_WINSCROLLBARS
+#define INCL_WINSTATICS
+#define INCL_WINSTDDLGS
+#define INCL_WINSYS
+#endif /* INCL_WIN || RC_INVOKED */
+
+#if defined (INCL_WIN)
+#define INCL_WINATOM
+#define INCL_WINCLIPBOARD
+#define INCL_WINCOUNTRY
+#define INCL_WINCURSORS
+#define INCL_WINDDE
+#define INCL_WINDESKTOP
+#define INCL_WINERRORS
+#define INCL_WINHOOKS
+#define INCL_WINLOAD
+#define INCL_WINPALETTE
+#define INCL_WINPROGRAMLIST
+#define INCL_WINRECTANGLES
+#define INCL_WINSHELLDATA
+#define INCL_WINSWITCHLIST
+#define INCL_WINTHUNKAPI
+#define INCL_WINTIMER
+#define INCL_WINTRACKRECT
+#define INCL_WINTYPES
+#define INCL_WINWINDOWMGR
+#endif /* INCL_WIN */
+
+#if defined (INCL_WINCOMMON)
+#define INCL_WINWINDOWMGR
+#endif
+
+#if defined (INCL_WINSTDDLGS)
+#define INCL_WINCIRCULARSLIDER
+#define INCL_WINSTDBOOK
+#define INCL_WINSTDCNR
+#define INCL_WINSTDDRAG
+#define INCL_WINSTDFILE
+#define INCL_WINSTDFONT
+#define INCL_WINSTDSLIDER
+#define INCL_WINSTDSPIN
+#define INCL_WINSTDVALSET
+#endif
+
+#if defined (INCL_WINSTDCNR) || defined (INCL_WINSTDVALSET)
+#define INCL_WINSTDDRAG
+#endif
+
+#if defined (INCL_WINMLE) && !defined (INCL_WINENTRYFIELDS)
+#define INCL_WINENTRYFIELDS
+#endif
+
+#if defined (INCL_WINWORKPLACE)
+#define INCL_WPCLASS
+#endif
+
+#if defined (INCL_GPI)
+#define INCL_GPIBITMAPS
+#define INCL_GPICONTROL
+#define INCL_GPICORRELATION
+#define INCL_GPIINK
+#define INCL_GPISEGMENTS
+#endif
+
+#if defined (INCL_ERRORS)
+#define INCL_DOSERRORS
+#define INCL_GPIERRORS
+#define INCL_SHLERRORS
+#define INCL_WINERRORS
+#endif
+
+#if defined (INCL_DDIDEFS)
+#define INCL_GPIBITMAPS
+#define INCL_GPIERRORS
+#endif
+
+#if defined (INCL_CIRCULARSLIDER) && !defined (INCL_WINCIRCULARSLIDER)
+#define INCL_WINCIRCULARSLIDER
+#endif
+
+/* ------------------------ DISABLE KEYWORDS ------------------------------ */
+
+#define APIENTRY
+#define EXPENTRY
+#define FAR
+
+/* ------------------------ CONSTANTS AND TYPES --------------------------- */
+
+#if !defined (FALSE)
+#define FALSE 0
+#endif
+
+#if !defined (TRUE)
+#define TRUE 1
+#endif
+
+#define VOID				void
+
+#define NULLHANDLE			((LHANDLE)0)
+#define NULLSHANDLE			((SHANDLE)0)
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+typedef int INT;		/* Required for Toolkit sample programs */
+typedef unsigned UINT;
+typedef unsigned long APIRET;
+
+typedef unsigned long BOOL;
+typedef BOOL *PBOOL;
+
+typedef unsigned long BOOL32;
+typedef BOOL *PBOOL32;
+
+typedef char CHAR;
+typedef CHAR *PCHAR;
+
+#if !defined (OS2EMX_PLAIN_CHAR)
+
+typedef unsigned char BYTE;
+typedef unsigned char *PCH;
+typedef unsigned char *PSZ;
+typedef __const__ unsigned char *PCCH;
+typedef __const__ unsigned char *PCSZ;
+
+#else
+
+typedef char BYTE;
+typedef char *PCH;
+typedef char *PSZ;
+typedef __const__ char *PCCH;
+typedef __const__ char *PCSZ;
+
+#endif
+
+typedef BYTE *PBYTE;
+
+typedef unsigned char UCHAR;
+typedef UCHAR *PUCHAR;
+
+typedef short SHORT;
+typedef SHORT *PSHORT;
+
+typedef unsigned short USHORT;
+typedef USHORT *PUSHORT;
+
+typedef long LONG;
+typedef LONG *PLONG;
+
+typedef unsigned long ULONG;
+typedef ULONG *PULONG;
+
+typedef VOID *PVOID;
+typedef PVOID *PPVOID;
+
+typedef __const__ VOID *CPVOID;
+
+typedef CHAR STR8[8];
+typedef STR8 *PSTR8;
+
+typedef CHAR STR16[16];
+typedef STR16 *PSTR16;
+typedef CHAR STR32[32];
+typedef STR32 *PSTR32;
+typedef CHAR STR64[64];
+typedef STR64 *PSTR64;
+
+typedef unsigned short SHANDLE;
+typedef unsigned long LHANDLE;
+
+typedef LHANDLE HPIPE;
+typedef HPIPE *PHPIPE;
+
+typedef LHANDLE HQUEUE;
+typedef HQUEUE *PHQUEUE;
+
+typedef LHANDLE HMODULE;
+typedef HMODULE *PHMODULE;
+
+typedef VOID *HSEM;
+typedef HSEM *PHSEM;
+
+typedef LHANDLE HOBJECT;
+
+typedef ULONG PID;
+typedef PID *PPID;
+
+typedef ULONG TID;
+typedef TID *PTID;
+
+typedef int (*PFN)();
+typedef PFN *PPFN;
+
+typedef USHORT SEL;
+typedef SEL *PSEL;
+
+typedef ULONG HMTX;
+typedef HMTX *PHMTX;
+
+typedef ULONG HMUX;
+typedef HMUX *PHMUX;
+
+
+#define FIELDOFFSET(t,f)  ((SHORT)&(((t *)0)->f))
+
+#define MAKETYPE(v,t)	  (*((t *)&v))
+
+#define MAKEUSHORT(l,h)	  (((USHORT)(l)) | ((USHORT)(h))<<8)
+#define MAKESHORT(l,h)	  ((SHORT)MAKEUSHORT(l, h))
+
+#define MAKEULONG(l,h)	  ((ULONG)(((USHORT)(l)) | ((ULONG)((USHORT)(h)))<<16))
+#define MAKELONG(l,h)	  ((LONG)MAKEULONG(l, h))
+
+#define LOUCHAR(w)	  ((UCHAR)(w))
+#define HIUCHAR(w)	  ((UCHAR)((USHORT)(w)>>8))
+
+#define LOBYTE(x)	  LOUCHAR(x)
+#define HIBYTE(x)	  HIUCHAR(x)
+
+#define LOUSHORT(x)	  ((USHORT)((ULONG)(x)))
+#define HIUSHORT(x)	  ((USHORT)((ULONG)(x)>>16))
+
+/* ---------------------------- ERROR CODES ------------------------------- */
+
+#define WINERR_BASE			0x1000
+#define GPIERR_BASE			0x2000
+#define DEVERR_BASE			0x3000
+#define SPLERR_BASE			0x4000
+
+#define SEVERITY_NOERROR		0x0000
+#define SEVERITY_WARNING		0x0004
+#define SEVERITY_ERROR			0x0008
+#define SEVERITY_SEVERE			0x000c
+#define SEVERITY_UNRECOVERABLE		0x0010
+
+#if defined (INCL_DOSERRORS)
+
+#define NO_ERROR				0
+#define ERROR_INVALID_FUNCTION			1
+#define ERROR_FILE_NOT_FOUND			2
+#define ERROR_PATH_NOT_FOUND			3
+#define ERROR_TOO_MANY_OPEN_FILES		4
+#define ERROR_ACCESS_DENIED			5
+#define ERROR_INVALID_HANDLE			6
+#define ERROR_ARENA_TRASHED			7
+#define ERROR_NOT_ENOUGH_MEMORY			8
+#define ERROR_INVALID_BLOCK			9
+#define ERROR_BAD_ENVIRONMENT		       10
+#define ERROR_BAD_FORMAT		       11
+#define ERROR_INVALID_ACCESS		       12
+#define ERROR_INVALID_DATA		       13
+#define ERROR_INVALID_DRIVE		       15
+#define ERROR_CURRENT_DIRECTORY		       16
+#define ERROR_NOT_SAME_DEVICE		       17
+#define ERROR_NO_MORE_FILES		       18
+#define ERROR_WRITE_PROTECT		       19
+#define ERROR_BAD_UNIT			       20
+#define ERROR_NOT_READY			       21
+#define ERROR_BAD_COMMAND		       22
+#define ERROR_CRC			       23
+#define ERROR_BAD_LENGTH		       24
+#define ERROR_SEEK			       25
+#define ERROR_NOT_DOS_DISK		       26
+#define ERROR_SECTOR_NOT_FOUND		       27
+#define ERROR_OUT_OF_PAPER		       28
+#define ERROR_WRITE_FAULT		       29
+#define ERROR_READ_FAULT		       30
+#define ERROR_GEN_FAILURE		       31
+#define ERROR_SHARING_VIOLATION		       32
+#define ERROR_LOCK_VIOLATION		       33
+#define ERROR_WRONG_DISK		       34
+#define ERROR_FCB_UNAVAILABLE		       35
+#define ERROR_SHARING_BUFFER_EXCEEDED	       36
+#define ERROR_CODE_PAGE_MISMATCHED	       37
+#define ERROR_HANDLE_EOF		       38
+#define ERROR_HANDLE_DISK_FULL		       39
+#define ERROR_NOT_SUPPORTED		       50
+#define ERROR_REM_NOT_LIST		       51
+#define ERROR_DUP_NAME			       52
+#define ERROR_BAD_NETPATH		       53
+#define ERROR_NETWORK_BUSY		       54
+#define ERROR_DEV_NOT_EXIST		       55
+#define ERROR_TOO_MANY_CMDS		       56
+#define ERROR_ADAP_HDW_ERR		       57
+#define ERROR_BAD_NET_RESP		       58
+#define ERROR_UNEXP_NET_ERR		       59
+#define ERROR_BAD_REM_ADAP		       60
+#define ERROR_PRINTQ_FULL		       61
+#define ERROR_NO_SPOOL_SPACE		       62
+#define ERROR_PRINT_CANCELLED		       63
+#define ERROR_NETNAME_DELETED		       64
+#define ERROR_NETWORK_ACCESS_DENIED	       65
+#define ERROR_BAD_DEV_TYPE		       66
+#define ERROR_BAD_NET_NAME		       67
+#define ERROR_TOO_MANY_NAMES		       68
+#define ERROR_TOO_MANY_SESS		       69
+#define ERROR_SHARING_PAUSED		       70
+#define ERROR_REQ_NOT_ACCEP		       71
+#define ERROR_REDIR_PAUSED		       72
+#define ERROR_SBCS_ATT_WRITE_PROT	       73
+#define ERROR_SBCS_GENERAL_FAILURE	       74
+#define ERROR_XGA_OUT_MEMORY		       75
+#define ERROR_FILE_EXISTS		       80
+#define ERROR_DUP_FCB			       81
+#define ERROR_CANNOT_MAKE		       82
+#define ERROR_FAIL_I24			       83
+#define ERROR_OUT_OF_STRUCTURES		       84
+#define ERROR_ALREADY_ASSIGNED		       85
+#define ERROR_INVALID_PASSWORD		       86
+#define ERROR_INVALID_PARAMETER		       87
+#define ERROR_NET_WRITE_FAULT		       88
+#define ERROR_NO_PROC_SLOTS		       89
+#define ERROR_NOT_FROZEN		       90
+#define ERROR_SYS_COMP_NOT_LOADED	       90 /*!*/
+#define ERR_TSTOVFL			       91
+#define ERR_TSTDUP			       92
+#define ERROR_NO_ITEMS			       93
+#define ERROR_INTERRUPT			       95
+#define ERROR_DEVICE_IN_USE		       99
+#define ERROR_TOO_MANY_SEMAPHORES	      100
+#define ERROR_EXCL_SEM_ALREADY_OWNED	      101
+#define ERROR_SEM_IS_SET		      102
+#define ERROR_TOO_MANY_SEM_REQUESTS	      103
+#define ERROR_INVALID_AT_INTERRUPT_TIME	      104
+#define ERROR_SEM_OWNER_DIED		      105
+#define ERROR_SEM_USER_LIMIT		      106
+#define ERROR_DISK_CHANGE		      107
+#define ERROR_DRIVE_LOCKED		      108
+#define ERROR_BROKEN_PIPE		      109
+#define ERROR_OPEN_FAILED		      110
+#define ERROR_BUFFER_OVERFLOW		      111
+#define ERROR_DISK_FULL			      112
+#define ERROR_NO_MORE_SEARCH_HANDLES	      113
+#define ERROR_INVALID_TARGET_HANDLE	      114
+#define ERROR_PROTECTION_VIOLATION	      115
+#define ERROR_VIOKBD_REQUEST		      116
+#define ERROR_INVALID_CATEGORY		      117
+#define ERROR_INVALID_VERIFY_SWITCH	      118
+#define ERROR_BAD_DRIVER_LEVEL		      119
+#define ERROR_CALL_NOT_IMPLEMENTED	      120
+#define ERROR_SEM_TIMEOUT		      121
+#define ERROR_INSUFFICIENT_BUFFER	      122
+#define ERROR_INVALID_NAME		      123
+#define ERROR_INVALID_LEVEL		      124
+#define ERROR_NO_VOLUME_LABEL		      125
+#define ERROR_MOD_NOT_FOUND		      126
+#define ERROR_PROC_NOT_FOUND		      127
+#define ERROR_WAIT_NO_CHILDREN		      128
+#define ERROR_CHILD_NOT_COMPLETE	      129
+#define ERROR_DIRECT_ACCESS_HANDLE	      130
+#define ERROR_NEGATIVE_SEEK		      131
+#define ERROR_SEEK_ON_DEVICE		      132
+#define ERROR_IS_JOIN_TARGET		      133
+#define ERROR_IS_JOINED			      134
+#define ERROR_IS_SUBSTED		      135
+#define ERROR_NOT_JOINED		      136
+#define ERROR_NOT_SUBSTED		      137
+#define ERROR_JOIN_TO_JOIN		      138
+#define ERROR_SUBST_TO_SUBST		      139
+#define ERROR_JOIN_TO_SUBST		      140
+#define ERROR_SUBST_TO_JOIN		      141
+#define ERROR_BUSY_DRIVE		      142
+#define ERROR_SAME_DRIVE		      143
+#define ERROR_DIR_NOT_ROOT		      144
+#define ERROR_DIR_NOT_EMPTY		      145
+#define ERROR_IS_SUBST_PATH		      146
+#define ERROR_IS_JOIN_PATH		      147
+#define ERROR_PATH_BUSY			      148
+#define ERROR_IS_SUBST_TARGET		      149
+#define ERROR_SYSTEM_TRACE		      150
+#define ERROR_INVALID_EVENT_COUNT	      151
+#define ERROR_TOO_MANY_MUXWAITERS	      152
+#define ERROR_INVALID_LIST_FORMAT	      153
+#define ERROR_LABEL_TOO_LONG		      154
+#define ERROR_TOO_MANY_TCBS		      155
+#define ERROR_SIGNAL_REFUSED		      156
+#define ERROR_DISCARDED			      157
+#define ERROR_NOT_LOCKED		      158
+#define ERROR_BAD_THREADID_ADDR		      159
+#define ERROR_BAD_ARGUMENTS		      160
+#define ERROR_BAD_PATHNAME		      161
+#define ERROR_SIGNAL_PENDING		      162
+#define ERROR_UNCERTAIN_MEDIA		      163
+#define ERROR_MAX_THRDS_REACHED		      164
+#define ERROR_MONITORS_NOT_SUPPORTED	      165
+#define ERROR_UNC_DRIVER_NOT_INSTALLED	      166
+#define ERROR_LOCK_FAILED		      167
+#define ERROR_SWAPIO_FAILED		      168
+#define ERROR_SWAPIN_FAILED		      169
+#define ERROR_BUSY			      170
+#define ERROR_CANCEL_VIOLATION		      173
+#define ERROR_ATOMIC_LOCK_NOT_SUPPORTED	      174
+#define ERROR_READ_LOCKS_NOT_SUPPORTED	      175
+#define ERROR_INVALID_SEGMENT_NUMBER	      180
+#define ERROR_INVALID_CALLGATE		      181
+#define ERROR_INVALID_ORDINAL		      182
+#define ERROR_ALREADY_EXISTS		      183
+#define ERROR_NO_CHILD_PROCESS		      184
+#define ERROR_CHILD_ALIVE_NOWAIT	      185
+#define ERROR_INVALID_FLAG_NUMBER	      186
+#define ERROR_SEM_NOT_FOUND		      187
+#define ERROR_INVALID_STARTING_CODESEG	      188
+#define ERROR_INVALID_STACKSEG		      189
+#define ERROR_INVALID_MODULETYPE	      190
+#define ERROR_INVALID_EXE_SIGNATURE	      191
+#define ERROR_EXE_MARKED_INVALID	      192
+#define ERROR_BAD_EXE_FORMAT		      193
+#define ERROR_ITERATED_DATA_EXCEEDS_64K	      194
+#define ERROR_INVALID_MINALLOCSIZE	      195
+#define ERROR_DYNLINK_FROM_INVALID_RING	      196
+#define ERROR_IOPL_NOT_ENABLED		      197
+#define ERROR_INVALID_SEGDPL		      198
+#define ERROR_AUTODATASEG_EXCEEDS_64K	      199
+#define ERROR_RING2SEG_MUST_BE_MOVABLE	      200
+#define ERROR_RELOCSRC_CHAIN_EXCEEDS_SEGLIMIT 201
+#define ERROR_INFLOOP_IN_RELOC_CHAIN	      202
+#define ERROR_ENVVAR_NOT_FOUND		      203
+#define ERROR_NOT_CURRENT_CTRY		      204
+#define ERROR_NO_SIGNAL_SENT		      205
+#define ERROR_FILENAME_EXCED_RANGE	      206
+#define ERROR_RING2_STACK_IN_USE	      207
+#define ERROR_META_EXPANSION_TOO_LONG	      208
+#define ERROR_INVALID_SIGNAL_NUMBER	      209
+#define ERROR_THREAD_1_INACTIVE		      210
+#define ERROR_INFO_NOT_AVAIL		      211
+#define ERROR_LOCKED			      212
+#define ERROR_BAD_DYNALINK		      213
+#define ERROR_TOO_MANY_MODULES		      214
+#define ERROR_NESTING_NOT_ALLOWED	      215
+#define ERROR_CANNOT_SHRINK		      216
+#define ERROR_ZOMBIE_PROCESS		      217
+#define ERROR_STACK_IN_HIGH_MEMORY	      218
+#define ERROR_INVALID_EXITROUTINE_RING	      219
+#define ERROR_GETBUF_FAILED		      220
+#define ERROR_FLUSHBUF_FAILED		      221
+#define ERROR_TRANSFER_TOO_LONG		      222
+#define ERROR_FORCENOSWAP_FAILED	      223
+#define ERROR_SMG_NO_TARGET_WINDOW	      224
+#define ERROR_NO_CHILDREN		      228
+#define ERROR_INVALID_SCREEN_GROUP	      229
+#define ERROR_BAD_PIPE			      230
+#define ERROR_PIPE_BUSY			      231
+#define ERROR_NO_DATA			      232
+#define ERROR_PIPE_NOT_CONNECTED	      233
+#define ERROR_MORE_DATA			      234
+#define ERROR_VC_DISCONNECTED		      240
+#define ERROR_CIRCULARITY_REQUESTED	      250
+#define ERROR_DIRECTORY_IN_CDS		      251
+#define ERROR_INVALID_FSD_NAME		      252
+#define ERROR_INVALID_PATH		      253
+#define ERROR_INVALID_EA_NAME		      254
+#define ERROR_EA_LIST_INCONSISTENT	      255
+#define ERROR_EA_LIST_TOO_LONG		      256
+#define ERROR_NO_META_MATCH		      257
+#define ERROR_FINDNOTIFY_TIMEOUT	      258
+#define ERROR_NO_MORE_ITEMS		      259
+#define ERROR_SEARCH_STRUC_REUSED	      260
+#define ERROR_CHAR_NOT_FOUND		      261
+#define ERROR_TOO_MUCH_STACK		      262
+#define ERROR_INVALID_ATTR		      263
+#define ERROR_INVALID_STARTING_RING	      264
+#define ERROR_INVALID_DLL_INIT_RING	      265
+#define ERROR_CANNOT_COPY		      266
+#define ERROR_DIRECTORY			      267
+#define ERROR_OPLOCKED_FILE		      268
+#define ERROR_OPLOCK_THREAD_EXISTS	      269
+#define ERROR_VOLUME_CHANGED		      270
+#define ERROR_FINDNOTIFY_HANDLE_IN_USE	      271
+#define ERROR_FINDNOTIFY_HANDLE_CLOSED	      272
+#define ERROR_NOTIFY_OBJECT_REMOVED	      273
+#define ERROR_ALREADY_SHUTDOWN		      274
+#define ERROR_EAS_DIDNT_FIT		      275
+#define ERROR_EA_FILE_CORRUPT		      276
+#define ERROR_EA_TABLE_FULL		      277
+#define ERROR_INVALID_EA_HANDLE		      278
+#define ERROR_NO_CLUSTER		      279
+#define ERROR_CREATE_EA_FILE		      280
+#define ERROR_CANNOT_OPEN_EA_FILE	      281
+#define ERROR_EAS_NOT_SUPPORTED		      282
+#define ERROR_NEED_EAS_FOUND		      283
+#define ERROR_DUPLICATE_HANDLE		      284
+#define ERROR_DUPLICATE_NAME		      285
+#define ERROR_EMPTY_MUXWAIT		      286
+#define ERROR_MUTEX_OWNED		      287
+#define ERROR_NOT_OWNER			      288
+#define ERROR_PARAM_TOO_SMALL		      289
+#define ERROR_TOO_MANY_HANDLES		      290
+#define ERROR_TOO_MANY_OPENS		      291
+#define ERROR_WRONG_TYPE		      292
+#define ERROR_UNUSED_CODE		      293
+#define ERROR_THREAD_NOT_TERMINATED	      294
+#define ERROR_INIT_ROUTINE_FAILED	      295
+#define ERROR_MODULE_IN_USE		      296
+#define ERROR_NOT_ENOUGH_WATCHPOINTS	      297
+#define ERROR_TOO_MANY_POSTS		      298
+#define ERROR_ALREADY_POSTED		      299
+#define ERROR_ALREADY_RESET		      300
+#define ERROR_SEM_BUSY			      301
+#define ERROR_INVALID_PROCID		      303
+#define ERROR_INVALID_PDELTA		      304
+#define ERROR_NOT_DESCENDANT		      305
+#define ERROR_NOT_SESSION_MANAGER	      306
+#define ERROR_INVALID_PCLASS		      307
+#define ERROR_INVALID_SCOPE		      308
+#define ERROR_INVALID_THREADID		      309
+#define ERROR_DOSSUB_SHRINK		      310
+#define ERROR_DOSSUB_NOMEM		      311
+#define ERROR_DOSSUB_OVERLAP		      312
+#define ERROR_DOSSUB_BADSIZE		      313
+#define ERROR_DOSSUB_BADFLAG		      314
+#define ERROR_DOSSUB_BADSELECTOR	      315
+#define ERROR_MR_MSG_TOO_LONG		      316
+#define ERROR_MR_MID_NOT_FOUND		      317
+#define ERROR_MR_UN_ACC_MSGF		      318
+#define ERROR_MR_INV_MSGF_FORMAT	      319
+#define ERROR_MR_INV_IVCOUNT		      320
+#define ERROR_MR_UN_PERFORM		      321
+#define ERROR_TS_WAKEUP			      322
+#define ERROR_TS_SEMHANDLE		      323
+#define ERROR_TS_NOTIMER		      324
+#define ERROR_TS_HANDLE			      326
+#define ERROR_TS_DATETIME		      327
+#define ERROR_SYS_INTERNAL		      328
+#define ERROR_QUE_CURRENT_NAME		      329
+#define ERROR_QUE_PROC_NOT_OWNED	      330
+#define ERROR_QUE_PROC_OWNED		      331
+#define ERROR_QUE_DUPLICATE		      332
+#define ERROR_QUE_ELEMENT_NOT_EXIST	      333
+#define ERROR_QUE_NO_MEMORY		      334
+#define ERROR_QUE_INVALID_NAME		      335
+#define ERROR_QUE_INVALID_PRIORITY	      336
+#define ERROR_QUE_INVALID_HANDLE	      337
+#define ERROR_QUE_LINK_NOT_FOUND	      338
+#define ERROR_QUE_MEMORY_ERROR		      339
+#define ERROR_QUE_PREV_AT_END		      340
+#define ERROR_QUE_PROC_NO_ACCESS	      341
+#define ERROR_QUE_EMPTY			      342
+#define ERROR_QUE_NAME_NOT_EXIST	      343
+#define ERROR_QUE_NOT_INITIALIZED	      344
+#define ERROR_QUE_UNABLE_TO_ACCESS	      345
+#define ERROR_QUE_UNABLE_TO_ADD		      346
+#define ERROR_QUE_UNABLE_TO_INIT	      347
+#define ERROR_VIO_INVALID_MASK		      349
+#define ERROR_VIO_PTR			      350
+#define ERROR_VIO_APTR			      351
+#define ERROR_VIO_RPTR			      352
+#define ERROR_VIO_CPTR			      353
+#define ERROR_VIO_LPTR			      354
+#define ERROR_VIO_MODE			      355
+#define ERROR_VIO_WIDTH			      356
+#define ERROR_VIO_ATTR			      357
+#define ERROR_VIO_ROW			      358
+#define ERROR_VIO_COL			      359
+#define ERROR_VIO_TOPROW		      360
+#define ERROR_VIO_BOTROW		      361
+#define ERROR_VIO_RIGHTCOL		      362
+#define ERROR_VIO_LEFTCOL		      363
+#define ERROR_SCS_CALL			      364
+#define ERROR_SCS_VALUE			      365
+#define ERROR_VIO_WAIT_FLAG		      366
+#define ERROR_VIO_UNLOCK		      367
+#define ERROR_SGS_NOT_SESSION_MGR	      368
+#define ERROR_SMG_INVALID_SGID		      369
+#define ERROR_SMG_INVALID_SESSION_ID	      369 /*!*/
+#define ERROR_SMG_NOSG			      370
+#define ERROR_SMG_NO_SESSIONS		      370 /*!*/
+#define ERROR_SMG_GRP_NOT_FOUND		      371
+#define ERROR_SMG_SESSION_NOT_FOUND	      371 /*!*/
+#define ERROR_SMG_SET_TITLE		      372
+#define ERROR_KBD_PARAMETER		      373
+#define ERROR_KBD_NO_DEVICE		      374
+#define ERROR_KBD_INVALID_IOWAIT	      375
+#define ERROR_KBD_INVALID_LENGTH	      376
+#define ERROR_KBD_INVALID_ECHO_MASK	      377
+#define ERROR_KBD_INVALID_INPUT_MASK	      378
+#define ERROR_MON_INVALID_PARMS		      379
+#define ERROR_MON_INVALID_DEVNAME	      380
+#define ERROR_MON_INVALID_HANDLE	      381
+#define ERROR_MON_BUFFER_TOO_SMALL	      382
+#define ERROR_MON_BUFFER_EMPTY		      383
+#define ERROR_MON_DATA_TOO_LARGE	      384
+#define ERROR_MOUSE_NO_DEVICE		      385
+#define ERROR_MOUSE_INV_HANDLE		      386
+#define ERROR_MOUSE_INV_PARMS		      387
+#define ERROR_MOUSE_CANT_RESET		      388
+#define ERROR_MOUSE_DISPLAY_PARMS	      389
+#define ERROR_MOUSE_INV_MODULE		      390
+#define ERROR_MOUSE_INV_ENTRY_PT	      391
+#define ERROR_MOUSE_INV_MASK		      392
+#define NO_ERROR_MOUSE_NO_DATA		      393
+#define NO_ERROR_MOUSE_PTR_DRAWN	      394
+#define ERROR_INVALID_FREQUENCY		      395
+#define ERROR_NLS_NO_COUNTRY_FILE	      396
+#define ERROR_NLS_OPEN_FAILED		      397
+#define ERROR_NLS_NO_CTRY_CODE		      398
+#define ERROR_NLS_TABLE_TRUNCATED	      399
+#define ERROR_NLS_BAD_TYPE		      400
+#define ERROR_NLS_TYPE_NOT_FOUND	      401
+#define ERROR_VIO_SMG_ONLY		      402
+#define ERROR_VIO_INVALID_ASCIIZ	      403
+#define ERROR_VIO_DEREGISTER		      404
+#define ERROR_VIO_NO_POPUP		      405
+#define ERROR_VIO_EXISTING_POPUP	      406
+#define ERROR_KBD_SMG_ONLY		      407
+#define ERROR_KBD_INVALID_ASCIIZ	      408
+#define ERROR_KBD_INVALID_MASK		      409
+#define ERROR_KBD_REGISTER		      410
+#define ERROR_KBD_DEREGISTER		      411
+#define ERROR_MOUSE_SMG_ONLY		      412
+#define ERROR_MOUSE_INVALID_ASCIIZ	      413
+#define ERROR_MOUSE_INVALID_MASK	      414
+#define ERROR_MOUSE_REGISTER		      415
+#define ERROR_MOUSE_DEREGISTER		      416
+#define ERROR_SMG_BAD_ACTION		      417
+#define ERROR_SMG_INVALID_CALL		      418
+#define ERROR_SCS_SG_NOTFOUND		      419
+#define ERROR_SCS_NOT_SHELL		      420
+#define ERROR_VIO_INVALID_PARMS		      421
+#define ERROR_VIO_FUNCTION_OWNED	      422
+#define ERROR_VIO_RETURN		      423
+#define ERROR_SCS_INVALID_FUNCTION	      424
+#define ERROR_SCS_NOT_SESSION_MGR	      425
+#define ERROR_VIO_REGISTER		      426
+#define ERROR_VIO_NO_MODE_THREAD	      427
+#define ERROR_VIO_NO_SAVE_RESTORE_THD	      428
+#define ERROR_VIO_IN_BG			      429
+#define ERROR_VIO_ILLEGAL_DURING_POPUP	      430
+#define ERROR_SMG_NOT_BASESHELL		      431
+#define ERROR_SMG_BAD_STATUSREQ		      432
+#define ERROR_QUE_INVALID_WAIT		      433
+#define ERROR_VIO_LOCK			      434
+#define ERROR_MOUSE_INVALID_IOWAIT	      435
+#define ERROR_VIO_INVALID_HANDLE	      436
+#define ERROR_VIO_ILLEGAL_DURING_LOCK	      437
+#define ERROR_VIO_INVALID_LENGTH	      438
+#define ERROR_KBD_INVALID_HANDLE	      439
+#define ERROR_KBD_NO_MORE_HANDLE	      440
+#define ERROR_KBD_CANNOT_CREATE_KCB	      441
+#define ERROR_KBD_CODEPAGE_LOAD_INCOMPL	      442
+#define ERROR_KBD_INVALID_CODEPAGE_ID	      443
+#define ERROR_KBD_NO_CODEPAGE_SUPPORT	      444
+#define ERROR_KBD_FOCUS_REQUIRED	      445
+#define ERROR_KBD_FOCUS_ALREADY_ACTIVE	      446
+#define ERROR_KBD_KEYBOARD_BUSY		      447
+#define ERROR_KBD_INVALID_CODEPAGE	      448
+#define ERROR_KBD_UNABLE_TO_FOCUS	      449
+#define ERROR_SMG_SESSION_NON_SELECT	      450
+#define ERROR_SMG_SESSION_NOT_FOREGRND	      451
+#define ERROR_SMG_SESSION_NOT_PARENT	      452
+#define ERROR_SMG_INVALID_START_MODE	      453
+#define ERROR_SMG_INVALID_RELATED_OPT	      454
+#define ERROR_SMG_INVALID_BOND_OPTION	      455
+#define ERROR_SMG_INVALID_SELECT_OPT	      456
+#define ERROR_SMG_START_IN_BACKGROUND	      457
+#define ERROR_SMG_INVALID_STOP_OPTION	      458
+#define ERROR_SMG_BAD_RESERVE		      459
+#define ERROR_SMG_PROCESS_NOT_PARENT	      460
+#define ERROR_SMG_INVALID_DATA_LENGTH	      461
+#define ERROR_SMG_NOT_BOUND		      462
+#define ERROR_SMG_RETRY_SUB_ALLOC	      463
+#define ERROR_KBD_DETACHED		      464
+#define ERROR_VIO_DETACHED		      465
+#define ERROR_MOU_DETACHED		      466
+#define ERROR_VIO_FONT			      467
+#define ERROR_VIO_USER_FONT		      468
+#define ERROR_VIO_BAD_CP		      469
+#define ERROR_VIO_NO_CP			      470
+#define ERROR_VIO_NA_CP			      471
+#define ERROR_INVALID_CODE_PAGE		      472
+#define ERROR_CPLIST_TOO_SMALL		      473
+#define ERROR_CP_NOT_MOVED		      474
+#define ERROR_MODE_SWITCH_INIT		      475
+#define ERROR_CODE_PAGE_NOT_FOUND	      476
+#define ERROR_UNEXPECTED_SLOT_RETURNED	      477
+#define ERROR_SMG_INVALID_TRACE_OPTION	      478
+#define ERROR_VIO_INTERNAL_RESOURCE	      479
+#define ERROR_VIO_SHELL_INIT		      480
+#define ERROR_SMG_NO_HARD_ERRORS	      481
+#define ERROR_CP_SWITCH_INCOMPLETE	      482
+#define ERROR_VIO_TRANSPARENT_POPUP	      483
+#define ERROR_CRITSEC_OVERFLOW		      484
+#define ERROR_CRITSEC_UNDERFLOW		      485
+#define ERROR_VIO_BAD_RESERVE		      486
+#define ERROR_INVALID_ADDRESS		      487
+#define ERROR_ZERO_SELECTORS_REQUESTED	      488
+#define ERROR_NOT_ENOUGH_SELECTORS_AVA	      489
+#define ERROR_INVALID_SELECTOR		      490
+#define ERROR_SMG_INVALID_PROGRAM_TYPE	      491
+#define ERROR_SMG_INVALID_PGM_CONTROL	      492
+#define ERROR_SMG_INVALID_INHERIT_OPT	      493
+#define ERROR_VIO_EXTENDED_SG		      494
+#define ERROR_VIO_NOT_PRES_MGR_SG	      495
+#define ERROR_VIO_SHIELD_OWNED		      496
+#define ERROR_VIO_NO_MORE_HANDLES	      497
+#define ERROR_VIO_SEE_ERROR_LOG		      498
+#define ERROR_VIO_ASSOCIATED_DC		      499
+#define ERROR_KBD_NO_CONSOLE		      500
+#define ERROR_MOUSE_NO_CONSOLE		      501
+#define ERROR_MOUSE_INVALID_HANDLE	      502
+#define ERROR_SMG_INVALID_DEBUG_PARMS	      503
+#define ERROR_KBD_EXTENDED_SG		      504
+#define ERROR_MOU_EXTENDED_SG		      505
+#define ERROR_SMG_INVALID_ICON_FILE	      506
+#define ERROR_TRC_PID_NON_EXISTENT	      507
+#define ERROR_TRC_COUNT_ACTIVE		      508
+#define ERROR_TRC_SUSPENDED_BY_COUNT	      509
+#define ERROR_TRC_COUNT_INACTIVE	      510
+#define ERROR_TRC_COUNT_REACHED		      511
+#define ERROR_NO_MC_TRACE		      512
+#define ERROR_MC_TRACE			      513
+#define ERROR_TRC_COUNT_ZERO		      514
+#define ERROR_SMG_TOO_MANY_DDS		      515
+#define ERROR_SMG_INVALID_NOTIFICATION	      516
+#define ERROR_LF_INVALID_FUNCTION	      517
+#define ERROR_LF_NOT_AVAIL		      518
+#define ERROR_LF_SUSPENDED		      519
+#define ERROR_LF_BUF_TOO_SMALL		      520
+#define ERROR_LF_BUFFER_CORRUPTED	      521
+#define ERROR_LF_BUFFER_FULL		      521 /*!*/
+#define ERROR_LF_INVALID_DAEMON		      522
+#define ERROR_LF_INVALID_RECORD		      522 /*!*/
+#define ERROR_LF_INVALID_TEMPL		      523
+#define ERROR_LF_INVALID_SERVICE	      523 /*!*/
+#define ERROR_LF_GENERAL_FAILURE	      524
+#define ERROR_LF_INVALID_ID		      525
+#define ERROR_LF_INVALID_HANDLE		      526
+#define ERROR_LF_NO_ID_AVAIL		      527
+#define ERROR_LF_TEMPLATE_AREA_FULL	      528
+#define ERROR_LF_ID_IN_USE		      529
+#define ERROR_MOU_NOT_INITIALIZED	      530
+#define ERROR_MOUINITREAL_DONE		      531
+#define ERROR_DOSSUB_CORRUPTED		      532
+#define ERROR_MOUSE_CALLER_NOT_SUBSYS	      533
+#define ERROR_ARITHMETIC_OVERFLOW	      534
+#define ERROR_TMR_NO_DEVICE		      535
+#define ERROR_TMR_INVALID_TIME		      536
+#define ERROR_PVW_INVALID_ENTITY	      537
+#define ERROR_PVW_INVALID_ENTITY_TYPE	      538
+#define ERROR_PVW_INVALID_SPEC		      539
+#define ERROR_PVW_INVALID_RANGE_TYPE	      540
+#define ERROR_PVW_INVALID_COUNTER_BLK	      541
+#define ERROR_PVW_INVALID_TEXT_BLK	      542
+#define ERROR_PRF_NOT_INITIALIZED	      543
+#define ERROR_PRF_ALREADY_INITIALIZED	      544
+#define ERROR_PRF_NOT_STARTED		      545
+#define ERROR_PRF_ALREADY_STARTED	      546
+#define ERROR_PRF_TIMER_OUT_OF_RANGE	      547
+#define ERROR_PRF_TIMER_RESET		      548
+#define ERROR_VDD_LOCK_USEAGE_DENIED	      639
+#define ERROR_TIMEOUT			      640
+#define ERROR_VDM_DOWN			      641
+#define ERROR_VDM_LIMIT			      642
+#define ERROR_VDD_NOT_FOUND		      643
+#define ERROR_INVALID_CALLER		      644
+#define ERROR_PID_MISMATCH		      645
+#define ERROR_INVALID_VDD_HANDLE	      646
+#define ERROR_VLPT_NO_SPOOLER		      647
+#define ERROR_VCOM_DEVICE_BUSY		      648
+#define ERROR_VLPT_DEVICE_BUSY		      649
+#define ERROR_NESTING_TOO_DEEP		      650
+#define ERROR_VDD_MISSING		      651
+#define ERROR_BIDI_INVALID_LENGTH	      671
+#define ERROR_BIDI_INVALID_INCREMENT	      672
+#define ERROR_BIDI_INVALID_COMBINATION	      673
+#define ERROR_BIDI_INVALID_RESERVED	      674
+#define ERROR_BIDI_INVALID_EFFECT	      675
+#define ERROR_BIDI_INVALID_CSDREC	      676
+#define ERROR_BIDI_INVALID_CSDSTATE	      677
+#define ERROR_BIDI_INVALID_LEVEL	      678
+#define ERROR_BIDI_INVALID_TYPE_SUPPORT	      679
+#define ERROR_BIDI_INVALID_ORIENTATION	      680
+#define ERROR_BIDI_INVALID_NUM_SHAPE	      681
+#define ERROR_BIDI_INVALID_CSD		      682
+#define ERROR_BIDI_NO_SUPPORT		      683
+#define NO_ERROR_BIDI_RW_INCOMPLETE	      684
+#define ERROR_IMP_INVALID_PARM		      691
+#define ERROR_IMP_INVALID_LENGTH	      692
+#define ERROR_MON_BAD_BUFFER		      730
+#define ERROR_MODULE_CORRUPTED		      731
+#define ERROR_SM_OUTOF_SWAPFILE		     1477
+#define ERROR_LF_TIMEOUT		     2055
+#define ERROR_LF_SUSPEND_SUCCESS	     2057
+#define ERROR_LF_RESUME_SUCCESS		     2058
+#define ERROR_LF_REDIRECT_SUCCESS	     2059
+#define ERROR_LF_REDIRECT_FAILURE	     2060
+#define ERROR_SWAPPER_NOT_ACTIVE	    32768
+#define ERROR_INVALID_SWAPID		    32769
+#define ERROR_IOERR_SWAP_FILE		    32770
+#define ERROR_SWAP_TABLE_FULL		    32771
+#define ERROR_SWAP_FILE_FULL		    32772
+#define ERROR_CANT_INIT_SWAPPER		    32773
+#define ERROR_SWAPPER_ALREADY_INIT	    32774
+#define ERROR_PMM_INSUFFICIENT_MEMORY	    32775
+#define ERROR_PMM_INVALID_FLAGS		    32776
+#define ERROR_PMM_INVALID_ADDRESS	    32777
+#define ERROR_PMM_LOCK_FAILED		    32778
+#define ERROR_PMM_UNLOCK_FAILED		    32779
+#define ERROR_PMM_MOVE_INCOMPLETE	    32780
+#define ERROR_UCOM_DRIVE_RENAMED	    32781
+#define ERROR_UCOM_FILENAME_TRUNCATED	    32782
+#define ERROR_UCOM_BUFFER_LENGTH	    32783
+#define ERROR_MON_CHAIN_HANDLE		    32784
+#define ERROR_MON_NOT_REGISTERED	    32785
+#define ERROR_SMG_ALREADY_TOP		    32786
+#define ERROR_PMM_ARENA_MODIFIED	    32787
+#define ERROR_SMG_PRINTER_OPEN		    32788
+#define ERROR_PMM_SET_FLAGS_FAILED	    32789
+#define ERROR_INVALID_DOS_DD		    32790
+#define ERROR_BLOCKED			    32791
+#define ERROR_NOBLOCK			    32792
+#define ERROR_INSTANCE_SHARED		    32793
+#define ERROR_NO_OBJECT			    32794
+#define ERROR_PARTIAL_ATTACH		    32795
+#define ERROR_INCACHE			    32796
+#define ERROR_SWAP_IO_PROBLEMS		    32797
+#define ERROR_CROSSES_OBJECT_BOUNDARY	    32798
+#define ERROR_LONGLOCK			    32799
+#define ERROR_SHORTLOCK			    32800
+#define ERROR_UVIRTLOCK			    32801
+#define ERROR_ALIASLOCK			    32802
+#define ERROR_ALIAS			    32803
+#define ERROR_NO_MORE_HANDLES		    32804
+#define ERROR_SCAN_TERMINATED		    32805
+#define ERROR_TERMINATOR_NOT_FOUND	    32806
+#define ERROR_NOT_DIRECT_CHILD		    32807
+#define ERROR_DELAY_FREE		    32808
+#define ERROR_GUARDPAGE			    32809
+#define ERROR_SWAPERROR			    32900
+#define ERROR_LDRERROR			    32901
+#define ERROR_NOMEMORY			    32902
+#define ERROR_NOACCESS			    32903
+#define ERROR_NO_DLL_TERM		    32904
+#define ERROR_CPSIO_CODE_PAGE_INVALID	    65026
+#define ERROR_CPSIO_NO_SPOOLER		    65027
+#define ERROR_CPSIO_FONT_ID_INVALID	    65028
+#define ERROR_CPSIO_INTERNAL_ERROR	    65033
+#define ERROR_CPSIO_INVALID_PTR_NAME	    65034
+#define ERROR_CPSIO_NOT_ACTIVE		    65037
+#define ERROR_CPSIO_PID_FULL		    65039
+#define ERROR_CPSIO_PID_NOT_FOUND	    65040
+#define ERROR_CPSIO_READ_CTL_SEQ	    65043
+#define ERROR_CPSIO_READ_FNT_DEF	    65045
+#define ERROR_CPSIO_WRITE_ERROR		    65047
+#define ERROR_CPSIO_WRITE_FULL_ERROR	    65048
+#define ERROR_CPSIO_WRITE_HANDLE_BAD	    65049
+#define ERROR_CPSIO_SWIT_LOAD		    65074
+#define ERROR_CPSIO_INV_COMMAND		    65077
+#define ERROR_CPSIO_NO_FONT_SWIT	    65078
+#define ERROR_ENTRY_IS_CALLGATE		    65079
+
+#endif /* INCL_DOSERRORS */
+
+/* ----------------------------- ERRORS ----------------------------------- */
+
+#if defined (INCL_DOSERRORS)
+
+#define ERRACT_RETRY		1
+#define ERRACT_DLYRET		2
+#define ERRACT_USER		3
+#define ERRACT_ABORT		4
+#define ERRACT_PANIC		5
+#define ERRACT_IGNORE		6
+#define ERRACT_INTRET		7
+
+#define ERRCLASS_OUTRES		1
+#define ERRCLASS_TEMPSIT	2
+#define ERRCLASS_AUTH		3
+#define ERRCLASS_INTRN		4
+#define ERRCLASS_HRDFAIL	5
+#define ERRCLASS_SYSFAIL	6
+#define ERRCLASS_APPERR		7
+#define ERRCLASS_NOTFND		8
+#define ERRCLASS_BADFMT		9
+#define ERRCLASS_LOCKED		10
+#define ERRCLASS_MEDIA		11
+#define ERRCLASS_ALREADY	12
+#define ERRCLASS_UNK		13
+#define ERRCLASS_CANT		14
+#define ERRCLASS_TIME		15
+
+#define ERRLOC_UNK		1
+#define ERRLOC_DISK		2
+#define ERRLOC_NET		3
+#define ERRLOC_SERDEV		4
+#define ERRLOC_MEM		5
+
+#endif /* INCL_DOSERRORS */
+
+#if defined (INCL_DOSMISC)
+
+#define FERR_DISABLEHARDERR	0x0000L
+#define FERR_ENABLEHARDERR	0x0001L
+#define FERR_ENABLEEXCEPTION	0x0000L
+#define FERR_DISABLEEXCEPTION	0x0002L
+
+#define BEGIN_LIBPATH		1
+#define END_LIBPATH		2
+
+ULONG DosErrClass (ULONG ulCode, PULONG pulClass, PULONG pulAction,
+    PULONG pulLocus);
+ULONG DosError (ULONG ulError);
+ULONG DosQueryExtLIBPATH (PCSZ pszExtLIBPATH, ULONG flags);
+ULONG DosSetExtLIBPATH (PCSZ pszExtLIBPATH, ULONG flags);
+
+#endif /* INCL_DOSMISC */
+
+/* ----------------------------- FONTS ------------------------------------ */
+
+#define FACESIZE 32
+
+#define FATTR_SEL_ITALIC		0x0001
+#define FATTR_SEL_UNDERSCORE		0x0002
+#define FATTR_SEL_OUTLINE		0x0008
+#define FATTR_SEL_STRIKEOUT		0x0010
+#define FATTR_SEL_BOLD			0x0020
+
+#define FATTR_TYPE_KERNING		0x0004
+#define FATTR_TYPE_MBCS			0x0008
+#define FATTR_TYPE_DBCS			0x0010
+#define FATTR_TYPE_ANTIALIASED		0x0020
+
+#define FATTR_FONTUSE_NOMIX		0x0002
+#define FATTR_FONTUSE_OUTLINE		0x0004
+#define FATTR_FONTUSE_TRANSFORMABLE	0x0008
+
+#define FM_TYPE_FIXED			0x0001
+#define FM_TYPE_LICENSED		0x0002
+#define FM_TYPE_KERNING			0x0004
+#define FM_TYPE_DBCS			0x0010
+#define FM_TYPE_MBCS			0x0018
+#define FM_TYPE_64K			0x8000
+#define FM_TYPE_ATOMS			0x4000
+#define FM_TYPE_FAMTRUNC		0x2000
+#define FM_TYPE_FACETRUNC		0x1000
+
+#define FM_DEFN_OUTLINE			0x0001
+#define FM_DEFN_IFI			0x0002
+#define FM_DEFN_WIN			0x0004
+#define FM_DEFN_GENERIC			0x8000
+
+#define FM_SEL_ITALIC			0x0001
+#define FM_SEL_UNDERSCORE		0x0002
+#define FM_SEL_NEGATIVE			0x0004
+#define FM_SEL_OUTLINE			0x0008
+#define FM_SEL_STRIKEOUT		0x0010
+#define FM_SEL_BOLD			0x0020
+#define FM_SEL_ISO9241_TESTED		0x0040
+
+#define FM_CAP_NOMIX			0x0001
+
+#define FM_ISO_9518_640			0x01
+#define FM_ISO_9515_640			0x02
+#define FM_ISO_9515_1024		0x04
+#define FM_ISO_9517_640			0x08
+#define FM_ISO_9517_1024		0x10
+
+
+typedef struct _PANOSE
+{
+  BYTE bFamilyType;
+  BYTE bSerifStyle;
+  BYTE bWeight;
+  BYTE bProportion;
+  BYTE bContrast;
+  BYTE bStrokeVariation;
+  BYTE bArmStyle;
+  BYTE bLetterform;
+  BYTE bMidline;
+  BYTE bXHeight;
+  BYTE fbPassedISO;
+  BYTE fbFailedISO;
+} PANOSE;
+
+typedef struct _FONTMETRICS
+{
+  CHAR	 szFamilyname[FACESIZE];
+  CHAR	 szFacename[FACESIZE];
+  USHORT idRegistry;
+  USHORT usCodePage;
+  LONG	 lEmHeight;
+  LONG	 lXHeight;
+  LONG	 lMaxAscender;
+  LONG	 lMaxDescender;
+  LONG	 lLowerCaseAscent;
+  LONG	 lLowerCaseDescent;
+  LONG	 lInternalLeading;
+  LONG	 lExternalLeading;
+  LONG	 lAveCharWidth;
+  LONG	 lMaxCharInc;
+  LONG	 lEmInc;
+  LONG	 lMaxBaselineExt;
+  SHORT	 sCharSlope;
+  SHORT	 sInlineDir;
+  SHORT	 sCharRot;
+  USHORT usWeightClass;
+  USHORT usWidthClass;
+  SHORT	 sXDeviceRes;
+  SHORT	 sYDeviceRes;
+  SHORT	 sFirstChar;
+  SHORT	 sLastChar;
+  SHORT	 sDefaultChar;
+  SHORT	 sBreakChar;
+  SHORT	 sNominalPointSize;
+  SHORT	 sMinimumPointSize;
+  SHORT	 sMaximumPointSize;
+  USHORT fsType;
+  USHORT fsDefn;
+  USHORT fsSelection;
+  USHORT fsCapabilities;
+  LONG	 lSubscriptXSize;
+  LONG	 lSubscriptYSize;
+  LONG	 lSubscriptXOffset;
+  LONG	 lSubscriptYOffset;
+  LONG	 lSuperscriptXSize;
+  LONG	 lSuperscriptYSize;
+  LONG	 lSuperscriptXOffset;
+  LONG	 lSuperscriptYOffset;
+  LONG	 lUnderscoreSize;
+  LONG	 lUnderscorePosition;
+  LONG	 lStrikeoutSize;
+  LONG	 lStrikeoutPosition;
+  SHORT	 sKerningPairs;
+  SHORT	 sFamilyClass;
+  LONG	 lMatch;
+  LONG	 FamilyNameAtom;
+  LONG	 FaceNameAtom;
+  PANOSE panose;
+} FONTMETRICS;
+typedef FONTMETRICS *PFONTMETRICS;
+
+typedef struct _FATTRS
+{
+  USHORT usRecordLength;
+  USHORT fsSelection;
+  LONG	 lMatch;
+  CHAR	 szFacename[FACESIZE];
+  USHORT idRegistry;
+  USHORT usCodePage;
+  LONG	 lMaxBaselineExt;
+  LONG	 lAveCharWidth;
+  USHORT fsType;
+  USHORT fsFontUse;
+} FATTRS;
+typedef FATTRS *PFATTRS;
+
+/* ------------------------- MEMORY MANAGEMENT ---------------------------- */
+
+#if defined (INCL_DOSMEMMGR) || !defined (INCL_NOCOMMON)
+
+#define PAG_READ		0x0001
+#define PAG_WRITE		0x0002
+#define PAG_EXECUTE		0x0004
+#define PAG_GUARD		0x0008
+#define PAG_COMMIT		0x0010
+#define PAG_DECOMMIT		0x0020
+#define OBJ_TILE		0x0040
+#define OBJ_PROTECTED		0x0080
+#define OBJ_GETTABLE		0x0100
+#define OBJ_GIVEABLE		0x0200
+#define PAG_DEFAULT		0x0400
+#define PAG_SHARED		0x2000
+#define PAG_FREE		0x4000
+#define PAG_BASE		0x00010000
+
+#define DOSSUB_INIT		0x0001
+#define DOSSUB_GROW		0x0002
+#define DOSSUB_SPARSE_OBJ	0x0004
+#define DOSSUB_SERIALIZE	0x0008
+
+#define fPERM			(PAG_EXECUTE | PAG_READ | PAG_WRITE)
+#define fSHARE			(OBJ_GETTABLE | OBJ_GIVEABLE)
+#define fALLOC			(fPERM | OBJ_TILE | PAG_COMMIT)
+#define fALLOCSHR		(fPERM | fSHARE | OBJ_TILE | PAG_COMMIT)
+#define fGETNMSHR		(fPERM)
+#define fGETSHR			(fPERM)
+#define fGIVESHR		(fPERM)
+#define fSET			(fPERM|PAG_COMMIT|PAG_DECOMMIT|PAG_DEFAULT)
+
+ULONG DosAllocMem (PPVOID pBaseAddress, ULONG ulObjectSize,
+    ULONG ulAllocationFlags);
+ULONG DosAllocSharedMem (PPVOID pBaseAddress, PCSZ pszName,
+    ULONG ulObjectSize, ULONG ulAllocationFlags);
+ULONG DosFreeMem (PVOID pBaseAddress);
+ULONG DosGetNamedSharedMem (PPVOID pBaseAddress, PCSZ pszSharedMemName,
+    ULONG ulAttributeFlags);
+ULONG DosGetSharedMem (CPVOID pBaseAddress, ULONG ulAttributeFlags);
+ULONG DosGiveSharedMem (CPVOID pBaseAddress, PID idProcessId,
+    ULONG ulAttributeFlags);
+ULONG DosQueryMem (CPVOID pBaseAddress, PULONG pulRegionSize,
+    PULONG pulAllocationFlags);
+ULONG DosSetMem (CPVOID pBaseAddress, ULONG ulRegionSize,
+    ULONG ulAttributeFlags);
+ULONG DosSubAllocMem (PVOID pOffset, PPVOID pBlockOffset, ULONG ulSize);
+ULONG DosSubFreeMem (PVOID pOffset, PVOID pBlockOffset, ULONG ulSize);
+ULONG DosSubSetMem (PVOID pOffset, ULONG ulFlags, ULONG ulSize);
+ULONG DosSubUnsetMem (PVOID pOffset);
+
+#endif /* INCL_DOSMEMMGR || !INCL_NOCOMMON */
+
+/* --------------------------- FILE SYSTEM -------------------------------- */
+
+#define CCHMAXPATH			260
+#define CCHMAXPATHCOMP			256
+
+#if defined (INCL_DOSMISC)
+#define DSP_IMPLIEDCUR			1
+#define DSP_PATHREF			2
+#define DSP_IGNORENETERR		4
+#endif
+
+#if defined (INCL_DOSFILEMGR) || !defined (INCL_NOCOMMON)
+
+#define DCPY_EXISTING			0x0001
+#define DCPY_APPEND			0x0002
+#define DCPY_FAILEAS			0x0004
+
+#define DSPI_WRTTHRU			0x0010
+
+#define EAT_BINARY			0xfffe
+#define EAT_ASCII			0xfffd
+#define EAT_BITMAP			0xfffb
+#define EAT_METAFILE			0xfffa
+#define EAT_ICON			0xfff9
+#define EAT_EA				0xffee
+#define EAT_MVMT			0xffdf
+#define EAT_MVST			0xffde
+#define EAT_ASN1			0xffdd
+
+#define ENUMEA_LEVEL_NO_VALUE		1
+
+#define ENUMEA_REFTYPE_FHANDLE		0
+#define ENUMEA_REFTYPE_PATH		1
+#define ENUMEA_REFTYPE_MAX		ENUMEA_REFTYPE_PATH
+
+#define ENUMEA_REFTYPE_FHANDLE		0
+#define ENUMEA_REFTYPE_PATH		1
+
+#define FEA_NEEDEA			0x80
+
+#define FHB_DSKREMOTE			0x8000
+#define FHB_CHRDEVREMOTE		0x8000
+#define FHB_PIPEREMOTE			0x8000
+
+#define FHT_DISKFILE			0x0000
+#define FHT_CHRDEV			0x0001
+#define FHT_PIPE			0x0002
+
+#define FIL_STANDARD			1
+#define FIL_QUERYEASIZE			2
+#define FIL_QUERYEASFROMLIST		3
+#define FIL_QUERYFULLNAME		5 /* DosQueryPathInfo */
+
+#define FILE_BEGIN			0
+#define FILE_CURRENT			1
+#define FILE_END			2
+
+#define FILE_NORMAL			0x0000
+#define FILE_READONLY			0x0001
+#define FILE_HIDDEN			0x0002
+#define FILE_SYSTEM			0x0004
+#define FILE_DIRECTORY			0x0010
+#define FILE_ARCHIVED			0x0020
+
+#define FILE_IGNORE			0x10000
+
+#define FILE_EXISTED			0x0001
+#define FILE_CREATED			0x0002
+#define FILE_TRUNCATED			0x0003
+
+#define FILE_OPEN			0x0001
+#define FILE_TRUNCATE			0x0002
+#define FILE_CREATE			0x0010
+
+#define FS_ATTACH			0
+#define FS_DETACH			1
+#define FS_SPOOLATTACH			2
+#define FS_SPOOLDETACH			3
+
+#define FSAIL_QUERYNAME			1
+#define FSAIL_DEVNUMBER			2
+#define FSAIL_DRVNUMBER			3
+
+#define FSAT_CHARDEV			1
+#define FSAT_PSEUDODEV			2
+#define FSAT_LOCALDRV			3
+#define FSAT_REMOTEDRV			4
+
+#define FSCTL_HANDLE			1
+#define FSCTL_PATHNAME			2
+#define FSCTL_FSDNAME			3
+
+#define FSCTL_ERROR_INFO		1
+#define FSCTL_MAX_EASIZE		2
+#define FSCTL_GET_NEXT_ROUTE_NAME	3
+#define FSCTL_DAEMON_QUERY		4
+
+#define FSCTL_QUERY_COMPLETE		0
+#define FSCTL_QUERY_AGAIN		1
+
+#define FSIL_ALLOC			1
+#define FSIL_VOLSER			2
+
+#define HANDTYPE_FILE			0x0000
+#define HANDTYPE_DEVICE			0x0001
+#define HANDTYPE_PIPE			0x0002
+#define HANDTYPE_PROTECTED		0x4000
+#define HANDTYPE_NETWORK		0x8000
+
+#define HDIR_SYSTEM			1
+#define HDIR_CREATE			((HDIR)-1)
+
+#define MUST_HAVE_READONLY	(FILE_READONLY	| (FILE_READONLY  << 8))
+#define MUST_HAVE_HIDDEN	(FILE_HIDDEN	| (FILE_HIDDEN	  << 8))
+#define MUST_HAVE_SYSTEM	(FILE_SYSTEM	| (FILE_SYSTEM	  << 8))
+#define MUST_HAVE_DIRECTORY	(FILE_DIRECTORY | (FILE_DIRECTORY << 8))
+#define MUST_HAVE_ARCHIVED	(FILE_ARCHIVED	| (FILE_ARCHIVED  << 8))
+
+#define OPEN_ACTION_FAIL_IF_EXISTS     0x0000
+#define OPEN_ACTION_OPEN_IF_EXISTS     0x0001
+#define OPEN_ACTION_REPLACE_IF_EXISTS  0x0002
+#define OPEN_ACTION_FAIL_IF_NEW	       0x0000
+#define OPEN_ACTION_CREATE_IF_NEW      0x0010
+
+#define OPEN_ACCESS_READONLY	       0x0000
+#define OPEN_ACCESS_WRITEONLY	       0x0001
+#define OPEN_ACCESS_READWRITE	       0x0002
+
+#define OPEN_SHARE_DENYREADWRITE       0x0010
+#define OPEN_SHARE_DENYWRITE	       0x0020
+#define OPEN_SHARE_DENYREAD	       0x0030
+#define OPEN_SHARE_DENYNONE	       0x0040
+
+#define OPEN_FLAGS_NOINHERIT	       0x0080
+#define OPEN_FLAGS_NO_LOCALITY	       0x0000
+#define OPEN_FLAGS_SEQUENTIAL	       0x0100
+#define OPEN_FLAGS_RANDOM	       0x0200
+#define OPEN_FLAGS_RANDOMSEQUENTIAL    0x0300
+#define OPEN_FLAGS_NO_CACHE	       0x1000
+#define OPEN_FLAGS_FAIL_ON_ERROR       0x2000
+#define OPEN_FLAGS_WRITE_THROUGH       0x4000
+#define OPEN_FLAGS_DASD		       0x8000
+#define OPEN_FLAGS_NONSPOOLED	       0x40000
+#define OPEN_FLAGS_PROTECTED_HANDLE    0x40000000
+
+#define SEARCH_PATH			0x0000
+#define SEARCH_CUR_DIRECTORY		0x0001
+#define SEARCH_ENVIRONMENT		0x0002
+#define SEARCH_IGNORENETERRS		0x0004
+
+
+typedef LHANDLE HFILE;
+typedef HFILE *PHFILE;
+
+typedef ULONG FHLOCK;
+typedef PULONG PFHLOCK;
+
+typedef LHANDLE HDIR;
+typedef HDIR *PHDIR;
+
+
+typedef struct _FTIME
+{
+  USHORT twosecs : 5;
+  USHORT minutes : 6;
+  USHORT hours	 : 5;
+} FTIME;
+typedef FTIME *PFTIME;
+
+typedef struct _FDATE
+{
+  USHORT day   : 5;
+  USHORT month : 4;
+  USHORT year  : 7;
+} FDATE;
+typedef FDATE *PFDATE;
+
+typedef struct _FEA
+{
+  BYTE	 fEA;
+  BYTE	 cbName;
+  USHORT cbValue;
+} FEA;
+typedef FEA *PFEA;
+
+typedef struct _FEALIST
+{
+  ULONG cbList;
+  FEA	list[1];
+} FEALIST;
+typedef FEALIST *PFEALIST;
+
+typedef struct _GEA
+{
+  BYTE cbName;
+  CHAR szName[1];
+} GEA;
+typedef GEA *PGEA;
+
+typedef struct _GEALIST
+{
+  ULONG cbList;
+  GEA	list[1];
+} GEALIST;
+typedef GEALIST *PGEALIST;
+
+typedef struct _EAOP
+{
+  PGEALIST fpGEAList;
+  PFEALIST fpFEAList;
+  ULONG	   oError;
+} EAOP;
+typedef EAOP *PEAOP;
+
+typedef struct _FEA2
+{
+  ULONG	 oNextEntryOffset;
+  BYTE	 fEA;
+  BYTE	 cbName;
+  USHORT cbValue;
+  CHAR	 szName[1];
+} FEA2;
+typedef FEA2 *PFEA2;
+
+typedef struct _FEA2LIST
+{
+  ULONG cbList;
+  FEA2	list[1];
+} FEA2LIST;
+typedef FEA2LIST *PFEA2LIST;
+
+typedef struct _GEA2
+{
+  ULONG oNextEntryOffset;
+  BYTE	cbName;
+  CHAR	szName[1];
+} GEA2;
+typedef GEA2 *PGEA2;
+
+typedef struct _GEA2LIST
+{
+  ULONG cbList;
+  GEA2	list[1];
+} GEA2LIST;
+typedef GEA2LIST *PGEA2LIST;
+
+typedef struct _EAOP2
+{
+  PGEA2LIST fpGEA2List;
+  PFEA2LIST fpFEA2List;
+  ULONG	    oError;
+} EAOP2;
+typedef EAOP2 *PEAOP2;
+
+typedef struct _DENA1
+{
+  UCHAR	 reserved;
+  UCHAR	 cbName;
+  USHORT cbValue;
+  UCHAR	 szName[1];
+} DENA1;
+typedef DENA1 *PDENA1;
+
+typedef FEA2 DENA2;
+typedef PFEA2 PDENA2;
+
+typedef struct _EASIZEBUF
+{
+  USHORT cbMaxEASize;
+  ULONG	 cbMaxEAListSize;	/* Packed? */
+} EASIZEBUF;
+typedef EASIZEBUF *PEASIZEBUF;
+
+typedef struct _ROUTENAMEBUF
+{
+  ULONG hRouteHandle;
+  UCHAR szRouteName;
+} ROUTENAMEBUF;
+typedef ROUTENAMEBUF *PROUTENAMEBUF;
+
+typedef struct _FSDTHREAD
+{
+  USHORT usFunc;
+  USHORT usStackSize;
+  ULONG	 ulPriorityClass;
+  LONG	 lPriorityLevel;
+} FSDTHREAD;
+
+typedef struct _FSDDAEMON
+{
+  USHORT    usNumThreads;
+  USHORT    usMoreFlag;
+  USHORT    usCallInstance;
+  FSDTHREAD tdThrds[16];
+} FSDDAEMON;
+
+typedef struct _FILEFINDBUF
+{
+  FDATE	 fdateCreation;
+  FTIME	 ftimeCreation;
+  FDATE	 fdateLastAccess;
+  FTIME	 ftimeLastAccess;
+  FDATE	 fdateLastWrite;
+  FTIME	 ftimeLastWrite;
+  ULONG	 cbFile;
+  ULONG	 cbFileAlloc;
+  USHORT attrFile;
+  UCHAR	 cchName;
+  CHAR	 achName[CCHMAXPATHCOMP];
+} FILEFINDBUF;
+typedef FILEFINDBUF *PFILEFINDBUF;
+
+typedef struct _FILEFINDBUF2
+{
+  FDATE	 fdateCreation;
+  FTIME	 ftimeCreation;
+  FDATE	 fdateLastAccess;
+  FTIME	 ftimeLastAccess;
+  FDATE	 fdateLastWrite;
+  FTIME	 ftimeLastWrite;
+  ULONG	 cbFile;
+  ULONG	 cbFileAlloc;
+  USHORT attrFile;
+  ULONG	 cbList;
+  UCHAR	 cchName;
+  CHAR	 achName[CCHMAXPATHCOMP];
+} FILEFINDBUF2;
+typedef FILEFINDBUF2 *PFILEFINDBUF2;
+
+typedef struct _FILEFINDBUF3
+{
+  ULONG oNextEntryOffset;
+  FDATE fdateCreation;
+  FTIME ftimeCreation;
+  FDATE fdateLastAccess;
+  FTIME ftimeLastAccess;
+  FDATE fdateLastWrite;
+  FTIME ftimeLastWrite;
+  ULONG cbFile;
+  ULONG cbFileAlloc;
+  ULONG attrFile;
+  UCHAR cchName;
+  CHAR	achName[CCHMAXPATHCOMP];
+} FILEFINDBUF3;
+typedef FILEFINDBUF3 *PFILEFINDBUF3;
+
+typedef struct _FILEFINDBUF4
+{
+  ULONG oNextEntryOffset;
+  FDATE fdateCreation;
+  FTIME ftimeCreation;
+  FDATE fdateLastAccess;
+  FTIME ftimeLastAccess;
+  FDATE fdateLastWrite;
+  FTIME ftimeLastWrite;
+  ULONG cbFile;
+  ULONG cbFileAlloc;
+  ULONG attrFile;
+  ULONG cbList;
+  UCHAR cchName;
+  CHAR	achName[CCHMAXPATHCOMP];
+} FILEFINDBUF4;
+typedef FILEFINDBUF4 *PFILEFINDBUF4;
+
+typedef struct _FILELOCK
+{
+  LONG lOffset;
+  LONG lRange;
+} FILELOCK;
+typedef FILELOCK *PFILELOCK;
+
+typedef struct _FILESTATUS
+{
+  FDATE	 fdateCreation;
+  FTIME	 ftimeCreation;
+  FDATE	 fdateLastAccess;
+  FTIME	 ftimeLastAccess;
+  FDATE	 fdateLastWrite;
+  FTIME	 ftimeLastWrite;
+  ULONG	 cbFile;
+  ULONG	 cbFileAlloc;
+  USHORT attrFile;
+} FILESTATUS;
+typedef FILESTATUS *PFILESTATUS;
+
+typedef struct _FILESTATUS2
+{
+  FDATE	 fdateCreation;
+  FTIME	 ftimeCreation;
+  FDATE	 fdateLastAccess;
+  FTIME	 ftimeLastAccess;
+  FDATE	 fdateLastWrite;
+  FTIME	 ftimeLastWrite;
+  ULONG	 cbFile;
+  ULONG	 cbFileAlloc;
+  USHORT attrFile;
+  ULONG	 cbList;
+} FILESTATUS2;
+typedef FILESTATUS2 *PFILESTATUS2;
+
+typedef struct _FILESTATUS3
+{
+  FDATE fdateCreation;
+  FTIME ftimeCreation;
+  FDATE fdateLastAccess;
+  FTIME ftimeLastAccess;
+  FDATE fdateLastWrite;
+  FTIME ftimeLastWrite;
+  ULONG cbFile;
+  ULONG cbFileAlloc;
+  ULONG attrFile;
+} FILESTATUS3;
+typedef FILESTATUS3 *PFILESTATUS3;
+
+typedef struct _FILESTATUS4
+{
+  FDATE fdateCreation;
+  FTIME ftimeCreation;
+  FDATE fdateLastAccess;
+  FTIME ftimeLastAccess;
+  FDATE fdateLastWrite;
+  FTIME ftimeLastWrite;
+  ULONG cbFile;
+  ULONG cbFileAlloc;
+  ULONG attrFile;
+  ULONG cbList;
+} FILESTATUS4;
+typedef FILESTATUS4 *PFILESTATUS4;
+
+typedef struct _FSALLOCATE
+{
+  ULONG	 idFileSystem;
+  ULONG	 cSectorUnit;
+  ULONG	 cUnit;
+  ULONG	 cUnitAvail;
+  USHORT cbSector;
+} FSALLOCATE;
+typedef FSALLOCATE *PFSALLOCATE;
+
+typedef struct _FSQBUFFER
+{
+  USHORT iType;
+  USHORT cbName;
+  UCHAR	 szName[1];
+  USHORT cbFSDName;
+  UCHAR	 szFSDName[1];
+  USHORT cbFSAData;
+  UCHAR	 rgFSAData[1];
+} FSQBUFFER;
+typedef FSQBUFFER *PFSQBUFFER;
+
+typedef struct _FSQBUFFER2
+{
+  USHORT iType;
+  USHORT cbName;
+  USHORT cbFSDName;
+  USHORT cbFSAData;
+  UCHAR	 szName[1];
+  UCHAR	 szFSDName[1];
+  UCHAR	 rgFSAData[1];
+} FSQBUFFER2;
+typedef FSQBUFFER2 *PFSQBUFFER2;
+
+typedef struct _SPOOLATTACH
+{
+  USHORT hNmPipe;
+  ULONG	 ulKey;
+} SPOOLATTACH;
+typedef SPOOLATTACH *PSPOOLATTACH;
+
+typedef struct _VOLUMELABEL
+{
+  BYTE cch;
+  CHAR szVolLabel[12];
+} VOLUMELABEL;
+typedef VOLUMELABEL *PVOLUMELABEL;
+
+typedef struct _FSINFO
+{
+  FDATE fdateCreation;
+  FTIME ftimeCreation;
+  VOLUMELABEL vol;
+} FSINFO;
+typedef FSINFO *PFSINFO;
+
+
+ULONG DosCancelLockRequest (HFILE hFile, __const__ FILELOCK *pfl);
+ULONG DosClose (HFILE hFile);
+ULONG DosCopy (PCSZ pszSource, PCSZ pszTarget, ULONG ulOption);
+ULONG DosCreateDir (PCSZ pszDirName, PEAOP2 pEABuf);
+ULONG DosDelete (PCSZ pszFileName);
+ULONG DosDeleteDir (PCSZ pszDirName);
+ULONG DosDupHandle (HFILE hFile, PHFILE phFile);
+ULONG DosEditName (ULONG ulLevel, PCSZ pszSource, PCSZ pszEdit,
+    PBYTE pszTargetBuf, ULONG ulTargetBufLength);
+ULONG DosEnumAttribute (ULONG ulRefType, CPVOID pvFile, ULONG ulEntry,
+    PVOID pvBuf, ULONG ulBufLength, PULONG pulCount, ULONG ulInfoLevel);
+ULONG DosFindClose (HDIR hDir);
+ULONG DosFindFirst (PCSZ pszFileSpec, PHDIR phDir, ULONG flAttribute,
+    PVOID pFindBuf, ULONG ulFindBufLength, PULONG pulFileNames,
+    ULONG ulInfoLevel);
+ULONG DosFindNext (HDIR hDir, PVOID pFindBuf, ULONG ulFindBufLength,
+    PULONG pulFileNames);
+ULONG DosForceDelete (PCSZ pszFileName);
+ULONG DosFSAttach (PCSZ pszDevice, PCSZ pszFilesystem,
+    __const__ VOID *pData, ULONG ulDataLength, ULONG ulFlag);
+ULONG DosFSCtl (PVOID pData, ULONG ulDataLengthMax, PULONG pulDataLength,
+    PVOID pParmList, ULONG ulParmLengthMax, PULONG pulParmLength,
+    ULONG ulFunction, PCSZ pszRouteName, HFILE hFile, ULONG ulMethod);
+ULONG DosMove (PCSZ pszOldName, PCSZ pszNewName);
+ULONG DosOpen (PCSZ pszFileName, PHFILE phFile, PULONG pulAction,
+    ULONG ulFileSize, ULONG ulAttribute, ULONG ulOpenFlags, ULONG ulOpenMode,
+    PEAOP2 pEABuf);
+ULONG DosProtectClose (HFILE hFile, FHLOCK fhFileHandleLockID);
+ULONG DosProtectEnumAttribute (ULONG ulRefType, CPVOID pvFile,
+    ULONG ulEntry, PVOID pvBuf, ULONG ulBufLength, PULONG pulCount,
+    ULONG ulInfoLevel, FHLOCK fhFileHandleLockID);
+ULONG DosProtectOpen (PCSZ pszFileName, PHFILE phFile, PULONG pulAction,
+    ULONG ulFileSize, ULONG ulAttribute, ULONG ulOpenFlags, ULONG ulOpenMode,
+    PEAOP2 pEABuf, PFHLOCK pfhFileHandleLockID);
+ULONG DosProtectQueryFHState (HFILE hFile, PULONG pulMode,
+    FHLOCK fhFileHandleLockID);
+ULONG DosProtectQueryFileInfo (HFILE hFile, ULONG ulInfoLevel,
+    PVOID pInfoBuffer, ULONG ulInfoLength, FHLOCK fhFileHandleLockID);
+ULONG DosProtectRead (HFILE hFile, PVOID pBuffer, ULONG ulLength,
+    PULONG pulBytesRead, FHLOCK fhFileHandleLockID);
+ULONG DosProtectSetFHState (HFILE hFile, ULONG ulMode,
+    FHLOCK fhFileHandleLockID);
+ULONG DosProtectSetFileInfo (HFILE hFile, ULONG ulInfoLevel, PVOID pInfoBuffer,
+    ULONG ulInfoLength, FHLOCK fhFileHandleLockID);
+ULONG DosProtectSetFileLocks (HFILE hFile, __const__ FILELOCK *pflUnlock,
+    __const__ FILELOCK *pflLock, ULONG ulTimeout, ULONG ulFlags,
+    FHLOCK fhFileHandleLockID);
+ULONG DosProtectSetFilePtr (HFILE hFile, LONG lOffset, ULONG ulOrigin,
+    PULONG pulPos, FHLOCK fhFileHandleLockID);
+ULONG DosProtectSetFileSize (HFILE hFile, ULONG ulSize,
+    FHLOCK fhFileHandleLockID);
+ULONG DosProtectWrite (HFILE hFile, CPVOID pBuffer, ULONG ulLength,
+    PULONG pulBytesWritten, FHLOCK fhFileHandleLockID);
+ULONG DosQueryCurrentDir (ULONG ulDrive, PBYTE pPath, PULONG pulPathLength);
+ULONG DosQueryCurrentDisk (PULONG pulDrive, PULONG pulLogical);
+ULONG DosQueryFHState (HFILE hFile, PULONG pulMode);
+ULONG DosQueryFileInfo (HFILE hFile, ULONG ulInfoLevel, PVOID pInfoBuffer,
+    ULONG ulInfoLength);
+ULONG DosQueryFSAttach (PCSZ pszDeviceName, ULONG ulOrdinal,
+    ULONG ulFSAInfoLevel, PFSQBUFFER2 pfsqb, PULONG pulBufLength);
+ULONG DosQueryFSInfo (ULONG ulDrive, ULONG ulInfoLevel, PVOID pBuf,
+    ULONG ulBufLength);
+ULONG DosQueryHType (HFILE hFile, PULONG pulType, PULONG pulAttr);
+ULONG DosQueryPathInfo (PCSZ pszPathName, ULONG ulInfoLevel,
+    PVOID pInfoBuffer, ULONG ulInfoLength);
+ULONG DosQueryVerify (PBOOL32 pVerify);
+ULONG DosRead (HFILE hFile, PVOID pBuffer, ULONG ulLength,
+    PULONG pulBytesRead);
+ULONG DosResetBuffer (HFILE hf);
+ULONG DosSetCurrentDir (PCSZ pszDir);
+ULONG DosSetDefaultDisk (ULONG ulDrive);
+ULONG DosSetFHState (HFILE hFile, ULONG ulMode);
+ULONG DosSetFileInfo (HFILE hFile, ULONG ulInfoLevel, PVOID pInfoBuffer,
+    ULONG ulInfoLength);
+ULONG DosSetFileLocks (HFILE hFile, __const__ FILELOCK *pflUnlock,
+    __const__ FILELOCK *pflLock, ULONG ulTimeout, ULONG ulFlags);
+ULONG DosSetFilePtr (HFILE hFile, LONG lOffset, ULONG ulOrigin, PULONG pulPos);
+ULONG DosSetFileSize (HFILE hFile, ULONG ulSize);
+ULONG DosSetFSInfo (ULONG ulDrive, ULONG ulInfoLevel, PVOID pBuf,
+    ULONG ulBufLength);
+ULONG DosSetMaxFH (ULONG ulCount);
+ULONG DosSetPathInfo (PCSZ pszPathName, ULONG ulInfoLevel, PVOID pInfoBuffer,
+    ULONG ulInfoLength, ULONG ulOptions);
+ULONG DosSetRelMaxFH (PLONG pulReqCount, PULONG pulCurMaxFH);
+ULONG DosSetVerify (BOOL32 f32Verify);
+ULONG DosShutdown (ULONG ulReserved);
+ULONG DosWrite (HFILE hFile, CPVOID pBuffer, ULONG ulLength,
+    PULONG pulBytesWritten);
+
+#endif /* INCL_DOSFILEMGR || !INCL_NOCOMMON */
+
+
+#if defined (INCL_DOSMISC)
+ULONG DosSearchPath (ULONG ulControl, PCSZ pszPath, PCSZ pszFilename,
+    PBYTE pBuf, ULONG ulBufLength);
+#endif /* INCL_DOSMISC */
+
+/* ---------------------------- DEVICE I/O -------------------------------- */
+
+#if defined (INCL_DOSDEVICES)
+
+#define DEVINFO_PRINTER		       0
+#define DEVINFO_RS232		       1
+#define DEVINFO_FLOPPY		       2
+#define DEVINFO_COPROCESSOR	       3
+#define DEVINFO_SUBMODEL	       4
+#define DEVINFO_MODEL		       5
+#define DEVINFO_ADAPTER		       6
+
+#define INFO_COUNT_PARTITIONABLE_DISKS 1
+#define INFO_GETIOCTLHANDLE	       2
+#define INFO_FREEIOCTLHANDLE	       3
+
+ULONG DosDevConfig (PVOID pInfo, ULONG ulItem);
+ULONG DosDevIOCtl (HFILE hDevice, ULONG ulCategory, ULONG ulFunction,
+    PVOID pParams, ULONG ulParamsLengthMax, PULONG pulParamsLength,
+    PVOID pData, ULONG ulDataLengthMax, PULONG pulDataLength);
+ULONG DosPhysicalDisk (ULONG ulFunction, PVOID pBuffer, ULONG ulBufferLength,
+    PVOID pParams, ULONG ulParamsLength);
+
+#endif /* INCL_DOSDEVICES */
+
+#if defined (INCL_DOSDEVIOCTL)
+
+#define IOCTL_ASYNC			0x0001
+#define IOCTL_SCR_AND_PTRDRAW		0x0003
+#define IOCTL_KEYBOARD			0x0004
+#define IOCTL_PRINTER			0x0005
+#define IOCTL_LIGHTPEN			0x0006
+#define IOCTL_POINTINGDEVICE		0x0007
+#define IOCTL_DISK			0x0008
+#define IOCTL_PHYSICALDISK		0x0009
+#define IOCTL_MONITOR			0x000a
+#define IOCTL_GENERAL			0x000b
+#define IOCTL_POWER			0x000c
+#define IOCTL_OEMHLP			0x0080
+#define IOCTL_TESTCFG_SYS		0x0080
+#define IOCTL_CDROMDISK			0x0080
+#define IOCTL_CDROMAUDIO		0x0081
+#define IOCTL_TOUCH_DEVDEP		0x0081
+#define IOCTL_TOUCH_DEVINDEP		0x0081
+
+#define ASYNC_SETBAUDRATE		0x0041
+#define ASYNC_SETLINECTRL		0x0042
+#define ASYNC_EXTSETBAUDRATE		0x0043
+#define ASYNC_TRANSMITIMM		0x0044
+#define ASYNC_SETBREAKOFF		0x0045
+#define ASYNC_SETMODEMCTRL		0x0046
+#define ASYNC_STOPTRANSMIT		0x0047
+#define ASYNC_STARTTRANSMIT		0x0048
+#define ASYNC_SETBREAKON		0x004b
+#define ASYNC_SETDCBINFO		0x0053
+#define ASYNC_SETENHANCEDMODEPARMS	0x0054
+#define ASYNC_GETBAUDRATE		0x0061
+#define ASYNC_GETLINECTRL		0x0062
+#define ASYNC_EXTGETBAUDRATE		0x0063
+#define ASYNC_GETCOMMSTATUS		0x0064
+#define ASYNC_GETLINESTATUS		0x0065
+#define ASYNC_GETMODEMOUTPUT		0x0066
+#define ASYNC_GETMODEMINPUT		0x0067
+#define ASYNC_GETINQUECOUNT		0x0068
+#define ASYNC_GETOUTQUECOUNT		0x0069
+#define ASYNC_GETCOMMERROR		0x006d
+#define ASYNC_GETCOMMEVENT		0x0072
+#define ASYNC_GETDCBINFO		0x0073
+#define ASYNC_GETENHANCEDMODEPARMS	0x0074
+
+#define SCR_ALLOCLDT			0x0070
+#define SCR_DEALLOCLDT			0x0071
+#define PTR_GETPTRDRAWADDRESS		0x0072
+#define VID_INITCALLVECTOR		0x0073
+#define SCR_ABIOSPASSTHRU		0x0074
+#define SCR_ALLOCLDTOFF			0x0075
+#define SCR_ALLOCLDTBGVAL		0x0076
+#define SCR_ALLOCVIDEOBUFFER		0x007e
+#define SCR_GETROMFONTADDR		0x007f
+
+#define KBD_SETTRANSTABLE		0x0050
+#define KBD_SETINPUTMODE		0x0051
+#define KBD_SETINTERIMFLAG		0x0052
+#define KBD_SETSHIFTSTATE		0x0053
+#define KBD_SETTYPAMATICRATE		0x0054
+#define KBD_SETFGNDSCREENGRP		0x0055
+#define KBD_SETSESMGRHOTKEY		0x0056
+#define KBD_SETFOCUS			0x0057
+#define KBD_SETKCB			0x0058
+#define KBD_SETREADNOTIFICATION		0x0059
+#define KBD_ALTERKBDLED			0x005a
+#define KBD_SETNLS			0x005c
+#define KBD_CREATE			0x005d
+#define KBD_DESTROY			0x005e
+#define KBD_GETINPUTMODE		0x0071
+#define KBD_GETINTERIMFLAG		0x0072
+#define KBD_GETSHIFTSTATE		0x0073
+#define KBD_READCHAR			0x0074
+#define KBD_PEEKCHAR			0x0075
+#define KBD_GETSESMGRHOTKEY		0x0076
+#define KBD_GETKEYBDTYPE		0x0077
+#define KBD_GETCODEPAGEID		0x0078
+#define KBD_XLATESCAN			0x0079
+#define KBD_QUERYKBDHARDWAREID		0x007a
+#define KBD_QUERYKBDCODEPAGESUPPORT	0x007b
+
+#define PRT_QUERYJOBHANDLE		0x0021
+#define PRT_SETFRAMECTL			0x0042
+#define PRT_SETINFINITERETRY		0x0044
+#define PRT_INITPRINTER			0x0046
+#define PRT_ACTIVATEFONT		0x0048
+#define PRT_SETPRINTJOBTITLE		0x004d
+#define PRT_SETIRQTIMEOUT		0x004e
+#define PRT_GETFRAMECTL			0x0062
+#define PRT_GETINFINITERETRY		0x0064
+#define PRT_GETPRINTERSTATUS		0x0066
+#define PRT_QUERYACTIVEFONT		0x0069
+#define PRT_VERIFYFONT			0x006a
+#define PRT_QUERYIRQTIMEOUT		0x006e
+
+#define MOU_ALLOWPTRDRAW		0x0050
+#define MOU_UPDATEDISPLAYMODE		0x0051
+#define MOU_SCREENSWITCH		0x0052
+#define MOU_SETSCALEFACTORS		0x0053
+#define MOU_SETEVENTMASK		0x0054
+#define MOU_SETHOTKEYBUTTON		0x0055
+#define MOU_REASSIGNTHRESHOLDVALUES	0x0055 /* ? */
+#define MOU_SETPTRSHAPE			0x0056
+#define MOU_DRAWPTR			0x0057
+#define MOU_UNMARKCOLLISIONAREA		0x0057 /* ? */
+#define MOU_REMOVEPTR			0x0058
+#define MOU_MARKCOLLISIONAREA		0x0058 /* ? */
+#define MOU_SETPTRPOS			0x0059
+#define MOU_SETPROTDRAWADDRESS		0x005a
+#define MOU_SETREALDRAWADDRESS		0x005b
+#define MOU_SETMOUSTATUS		0x005c
+#define MOU_DISPLAYMODECHANGE		0x005d
+#define MOU_GETBUTTONCOUNT		0x0060
+#define MOU_GETMICKEYCOUNT		0x0061
+#define MOU_GETMOUSTATUS		0x0062
+#define MOU_READEVENTQUE		0x0063
+#define MOU_GETQUESTATUS		0x0064
+#define MOU_GETEVENTMASK		0x0065
+#define MOU_GETSCALEFACTORS		0x0066
+#define MOU_GETPTRPOS			0x0067
+#define MOU_GETPTRSHAPE			0x0068
+#define MOU_GETHOTKEYBUTTON		0x0069
+#define MOU_QUERYTHRESHOLDVALUES	0x0069 /* ? */
+#define MOU_VER				0x006a
+#define MOU_QUERYPOINTERID		0x006b /* ? */
+
+#define DSK_LOCKDRIVE			0x0000
+#define DSK_UNLOCKDRIVE			0x0001
+#define DSK_REDETERMINEMEDIA		0x0002
+#define DSK_SETLOGICALMAP		0x0003
+#define DSK_BEGINFORMAT			0x0004
+#define DSK_BLOCKREMOVABLE		0x0020
+#define DSK_GETLOGICALMAP		0x0021
+#define DSK_UNLOCKEJECTMEDIA		0x0040
+#define DSK_SETDEVICEPARAMS		0x0043
+#define DSK_WRITETRACK			0x0044
+#define DSK_FORMATVERIFY		0x0045
+#define DSK_DISKETTECONTROL		0x005d
+#define DSK_QUERYMEDIASENSE		0x0060
+#define DSK_GETDEVICEPARAMS		0x0063
+#define DSK_READTRACK			0x0064
+#define DSK_VERIFYTRACK			0x0065
+#define DSK_GETLOCKSTATUS		0x0066
+
+#define PDSK_LOCKPHYSDRIVE		0x0000
+#define PDSK_UNLOCKPHYSDRIVE		0x0001
+#define PDSK_WRITEPHYSTRACK		0x0044
+#define PDSK_GETPHYSDEVICEPARAMS	0x0063
+#define PDSK_READPHYSTRACK		0x0064
+#define PDSK_VERIFYPHYSTRACK		0x0065
+
+#define POWER_SENDPOWEREVENT		0x0040
+#define POWER_SETPOWEREVENTRES		0x0041
+#define POWER_GETPOWERSTATUS		0x0060
+#define POWER_GETPOWEREVENT		0x0061
+#define POWER_GETPOWERINFO		0x0062
+
+#define OEMHLP_GETOEMADAPTIONINFO	0x0000
+#define OEMHLP_GETMACHINEINFO		0x0001
+#define OEMHLP_GETDISPLAYCOMBCODE	0x0002
+#define OEMHLP_GETVIDEOFONTS		0x0003
+#define OEMHLP_READEISACONFIGINFO	0x0004
+#define OEMHLP_GETROMBIOSINFO		0x0005
+#define OEMHLP_GETMISCVIDEOINFO		0x0006
+#define OEMHLP_GETVIDEOADAPTER		0x0007
+#define OEMHLP_GETSVGAINFO		0x0008
+#define OEMHLP_GETMEMINFO		0x0009
+#define OEMHLP_GETDMQSINFO		0x000a
+#define OEMHLP_PCI			0x000b
+
+#define TESTCFG_SYS_GETBIOSADAPTER	0x0040
+#define TESTCFG_SYS_ISSUEINIOINSTR	0x0041
+#define TESTCFG_SYS_ISSUEOUTIOINSTR	0x0042
+#define TESTCFG_SYS_GETBUSARCH		0x0060
+#define TESTCFG_SYS_GETALLPOSIDS	0x0061
+#define TESTCFG_SYS_GETALLEISAIDS	0x0062
+
+#define CDROMDISK_RESETDRIVE		0x0040
+#define CDROMDISK_EJECTDISK		0x0044
+#define CDROMDISK_LOCKUNLOCKDOOR	0x0046
+#define CDROMDISK_SEEK			0x0050
+#define CDROMDISK_DEVICESTATUS		0x0060
+#define CDROMDISK_GETDRIVER		0x0061
+#define CDROMDISK_GETSECTORSIZE		0x0063
+#define CDROMDISK_GETHEADLOC		0x0070
+#define CDROMDISK_READLONG		0x0072
+#define CDROMDISK_GETVOLUMESIZE		0x0078
+#define CDROMDISK_GETUPC		0x0079
+
+#define CDROMAUDIO_SETCHANNELCTRL	0x0040
+#define CDROMAUDIO_PLAYAUDIO		0x0050
+#define CDROMAUDIO_STOPAUDIO		0x0051
+#define CDROMAUDIO_RESUMEAUDIO		0x0052
+#define CDROMAUDIO_GETCHANNEL		0x0060
+#define CDROMAUDIO_GETAUDIODISK		0x0061
+#define CDROMAUDIO_GETAUDIOTRACK	0x0062
+#define CDROMAUDIO_GETSUBCHANNELQ	0x0063
+#define CDROMAUDIO_GETAUDIOSTATUS	0x0065
+
+#define TOUCH_DEVDEP_SETCALIBCONST	0x0052
+#define TOUCH_DEVDEP_READDATA		0x0053
+#define TOUCH_DEVDEP_SETDATAMODE	0x0054
+#define TOUCH_DEVDEP_SETCLICKLOCK	0x0055
+#define TOUCH_DEVDEP_SETTOUCHTHRESHOLD	0x0056
+#define TOUCH_DEVDEP_SETEMULXY		0x0057
+#define TOUCH_DEVDEP_SETDATAREPORTRATE	0x0058
+#define TOUCH_DEVDEP_SETLOWPASSFILTER	0x0059
+#define TOUCH_DEVDEP_WRITEMEMLOC	0x005a
+#define TOUCH_DEVDEP_GETCALIBCONST	0x0060
+#define TOUCH_DEVDEP_GETDATAMODE	0x0061
+#define TOUCH_DEVDEP_GETCLICKLOCK	0x0062
+#define TOUCH_DEVDEP_GETTOUCHTHRESHOLD	0x0063
+#define TOUCH_DEVDEP_GETEMULXY		0x0064
+#define TOUCH_DEVDEP_GETDATAREPORTRATE	0x0065
+#define TOUCH_DEVDEP_GETLOWPASSFILTER	0x0066
+#define TOUCH_DEVDEP_READMEMLOC		0x0067
+
+#define TOUCH_DEVINDEP_SETCOORDSYS	0x0050
+#define TOUCH_DEVINDEP_SETSELECTMECH	0x0052
+#define TOUCH_DEVINDEP_SETEVENTMASK	0x0053
+#define TOUCH_DEVINDEP_SETQUEUESIZE	0x0054
+#define TOUCH_DEVINDEP_SETEMULSTATE	0x0055
+#define TOUCH_DEVINDEP_GETCOORDSYS	0x0060
+#define TOUCH_DEVINDEP_GETSELECTMECH	0x0062
+#define TOUCH_DEVINDEP_GETEVENTMASK	0x0063
+#define TOUCH_DEVINDEP_GETQUEUESIZE	0x0064
+#define TOUCH_DEVINDEP_GETEMULSTATE	0x0065
+#define TOUCH_DEVINDEP_GETREADEVENTQUEUE 0x0066
+
+#define MON_REGISTERMONITOR		0x0040
+
+#define DEV_FLUSHINPUT			0x0001
+#define DEV_FLUSHOUTPUT			0x0002
+#define DEV_SYSTEMNOTIFYPDD		0x0041
+#define DEV_QUERYMONSUPPORT		0x0060
+
+#define RX_QUE_OVERRUN			0x0001
+#define RX_HARDWARE_OVERRUN		0x0002
+#define PARITY_ERROR			0x0004
+#define FRAMING_ERROR			0x0008
+
+#define CHAR_RECEIVED			0x0001
+#define LAST_CHAR_SENT			0x0004
+#define CTS_CHANGED			0x0008
+#define DSR_CHANGED			0x0010
+#define DCD_CHANGED			0x0020
+#define BREAK_DETECTED			0x0040
+#define ERROR_OCCURRED			0x0080
+#define RI_DETECTED			0x0100
+
+#define TX_WAITING_FOR_CTS		0x0001
+#define TX_WAITING_FOR_DSR		0x0002
+#define TX_WAITING_FOR_DCD		0x0004
+#define TX_WAITING_FOR_XON		0x0008
+#define TX_WAITING_TO_SEND_XON		0x0010
+#define TX_WAITING_WHILE_BREAK_ON	0x0020
+#define TX_WAITING_TO_SEND_IMM		0x0040
+#define RX_WAITING_FOR_DSR		0x0080
+
+#define WRITE_REQUEST_QUEUED		0x0001
+#define DATA_IN_TX_QUE			0x0002
+#define HARDWARE_TRANSMITTING		0x0004
+#define CHAR_READY_TO_SEND_IMM		0x0008
+#define WAITING_TO_SEND_XON		0x0010
+#define WAITING_TO_SEND_XOFF		0x0020
+
+#define CTS_ON				0x10
+#define DSR_ON				0x20
+#define RI_ON				0x40
+#define DCD_ON				0x80
+
+#define MODE_DTR_CONTROL		0x01
+#define MODE_DTR_HANDSHAKE		0x02
+#define MODE_CTS_HANDSHAKE		0x08
+#define MODE_DSR_HANDSHAKE		0x10
+#define MODE_DCD_HANDSHAKE		0x20
+#define MODE_DSR_SENSITIVITY		0x40
+
+#define MODE_AUTO_TRANSMIT		0x01
+#define MODE_AUTO_RECEIVE		0x02
+#define MODE_ERROR_CHAR			0x04
+#define MODE_NULL_STRIPPING		0x08
+#define MODE_BREAK_CHAR			0x10
+#define MODE_RTS_CONTROL		0x40
+#define MODE_RTS_HANDSHAKE		0x80
+#define MODE_TRANSMIT_TOGGLE		0xc0
+
+#define MODE_NO_WRITE_TIMEOUT		0x01
+#define MODE_READ_TIMEOUT		0x02
+#define MODE_WAIT_READ_TIMEOUT		0x04
+#define MODE_NOWAIT_READ_TIMEOUT	0x06
+
+#define DTR_ON				0x01
+#define RTS_ON				0x02
+
+#define DTR_OFF				0xfe
+#define RTS_OFF				0xfd
+
+#define ASCII_MODE			0x00
+#define BINARY_MODE			0x80
+
+#define CONVERSION_REQUEST		0x20
+#define INTERIM_CHAR			0x80
+
+#define HOTKEY_MAX_COUNT		0x0000
+#define HOTKEY_CURRENT_COUNT		0x0001
+
+#define KBD_DATA_RECEIVED		0x0001
+#define KBD_DATA_BINARY			0x8000
+
+#define KBD_READ_WAIT			0x0000
+#define KBD_READ_NOWAIT			0x8000
+
+#define SHIFT_REPORT_MODE		0x01
+
+#define RIGHTSHIFT			0x0001
+#define LEFTSHIFT			0x0002
+#define CONTROL				0x0004
+#define ALT				0x0008
+#define SCROLLLOCK_ON			0x0010
+#define NUMLOCK_ON			0x0020
+#define CAPSLOCK_ON			0x0040
+#define INSERT_ON			0x0080
+#define LEFTCONTROL			0x0100
+#define LEFTALT				0x0200
+#define RIGHTCONTROL			0x0400
+#define RIGHTALT			0x0800
+#define SCROLLLOCK			0x1000
+#define NUMLOCK				0x2000
+#define CAPSLOCK			0x4000
+#define SYSREQ				0x8000
+
+#define PRINTER_TIMEOUT			0x0001
+#define PRINTER_IO_ERROR		0x0008
+#define PRINTER_SELECTED		0x0010
+#define PRINTER_OUT_OF_PAPER		0x0020
+#define PRINTER_ACKNOWLEDGED		0x0040
+#define PRINTER_NOT_BUSY		0x0080
+
+#define MOUSE_MOTION			0x0001
+#define MOUSE_MOTION_WITH_BN1_DOWN	0x0002
+#define MOUSE_BN1_DOWN			0x0004
+#define MOUSE_MOTION_WITH_BN2_DOWN	0x0008
+#define MOUSE_BN2_DOWN			0x0010
+#define MOUSE_MOTION_WITH_BN3_DOWN	0x0020
+#define MOUSE_BN3_DOWN			0x0040
+
+#define MHK_BUTTON1			0x0001
+#define MHK_BUTTON2			0x0002
+#define MHK_BUTTON3			0x0004
+
+#define MOU_NOWAIT			0x0000
+#define MOU_WAIT			0x0001
+
+#define MHK_NO_HOTKEY			0x0000
+
+#define MOUSE_QUEUEBUSY			0x0001
+#define MOUSE_BLOCKREAD			0x0002
+#define MOUSE_FLUSH			0x0004
+#define MOUSE_UNSUPPORTED_MODE		0x0008
+#define MOUSE_DISABLED			0x0100
+#define MOUSE_MICKEYS			0x0200
+
+#define BUILD_BPB_FROM_MEDIUM		0x00
+#define REPLACE_BPB_FOR_DEVICE		0x01
+#define REPLACE_BPB_FOR_MEDIUM		0x02
+
+#define DEVTYPE_48TPI			0x0000
+#define DEVTYPE_96TPI			0x0001
+#define DEVTYPE_35			0x0002
+#define DEVTYPE_8SD			0x0003
+#define DEVTYPE_8DD			0x0004
+#define DEVTYPE_FIXED			0x0005
+#define DEVTYPE_TAPE			0x0006
+#define DEVTYPE_UNKNOWN			0x0007
+
+#define SCREENDD_GETCURRENTBANK		0x00
+#define SCREENDD_SETCURRENTBANK		0x01
+#define SCREENDD_SVGA_ID		0x08
+#define SCREENDD_SVGA_OEM		0x09
+#define SCREENDD_UPDATEMEMORY		0x0a
+#define SCREENDD_GETLINEARACCESS	0x0b
+#define SCREENDD_GETGLOBALACCESS	0x0c
+#define SCREENDD_FREEGLOBALACCESS	0x0d
+#define SCREENDD_REGISTER_RING0_CALLER	0x0e
+#define SCREENDD_WAIT_ON_RING0_CALLER	0x0f
+#define SCREENDD_CATEGORY		0x80
+#define SCREENDD_NAME			"SCREEN$"
+
+#define GETLINEAR_FLAG_MAPPHYSICAL	0x00000010
+#define GETLINEAR_FLAG_MAPPROCESS	0x00000020
+#define GETLINEAR_FLAG_MAPSHARED	0x00000400
+#define GETLINEAR_FLAG_MAPATTACH	0x80000000
+
+#define EGA_BIT				4
+#define VGA_BIT				8
+#define EGAVGA_BIT			(EGA_BIT|VGA_BIT)
+
+#define READ_BANK			0
+#define WRITE_BANK			1
+#define MODE_TEXT			0
+#define MODE_PLANAR			1
+#define MODE_LINEAR			2
+
+typedef struct _DCBINFO
+{
+  USHORT usWriteTimeout;
+  USHORT usReadTimeout;
+  BYTE	 fbCtlHndShake;
+  BYTE	 fbFlowReplace;
+  BYTE	 fbTimeout;
+  BYTE	 bErrorReplacementChar;
+  BYTE	 bBreakReplacementChar;
+  BYTE	 bXONChar;
+  BYTE	 bXOFFChar;
+} DCBINFO;
+typedef DCBINFO *PDCBINFO;
+
+typedef struct _LINECONTROL
+{
+  BYTE bDataBits;
+  BYTE bParity;
+  BYTE bStopBits;
+  BYTE fTransBreak;
+} LINECONTROL;
+typedef LINECONTROL *PLINECONTROL;
+
+typedef struct _MODEMSTATUS
+{
+  BYTE fbModemOn;
+  BYTE fbModemOff;
+} MODEMSTATUS;
+typedef MODEMSTATUS *PMODEMSTATUS;
+
+typedef struct _KBDTYPE
+{
+  USHORT usType;
+  USHORT reserved1;
+  USHORT reserved2;
+} KBDTYPE;
+typedef KBDTYPE *PKBDTYPE;
+
+typedef struct _RATEDELAY
+{
+  USHORT usDelay;
+  USHORT usRate;
+} RATEDELAY;
+typedef RATEDELAY *PRATEDELAY;
+
+typedef struct _CODEPAGEINFO
+{
+  PBYTE	 pbTransTable;
+  USHORT idCodePage;
+  USHORT idTable;
+} CODEPAGEINFO;
+typedef CODEPAGEINFO *PCODEPAGEINFO;
+
+typedef struct _CPID
+{
+  USHORT idCodePage;
+  USHORT Reserved;
+} CPID;
+typedef CPID *PCPID;
+
+typedef struct _SHIFTSTATE
+{
+  USHORT fsState;
+  BYTE	 fNLS;
+} SHIFTSTATE;
+typedef SHIFTSTATE *PSHIFTSTATE;
+
+typedef struct _HOTKEY
+{
+  USHORT fsHotKey;
+  UCHAR	 uchScancodeMake;
+  UCHAR	 uchScancodeBreak;
+  USHORT idHotKey;
+} HOTKEY;
+typedef HOTKEY *PHOTKEY;
+
+typedef struct _PTRDRAWFUNCTION
+{
+  USHORT usReturnCode;
+  PFN	 pfnDraw;
+  PCH	 pchDataSeg;
+} PTRDRAWFUNCTION;
+typedef PTRDRAWFUNCTION *PPTRDRAWFUNCTION;
+
+typedef struct _PTRDRAWADDRESS
+{
+  USHORT	  reserved;
+  PTRDRAWFUNCTION ptrdfnc;
+} PTRDRAWADDRESS;
+typedef PTRDRAWADDRESS *PPTRDRAWADDRESS;
+
+typedef struct _PTRDRAWDATA
+{
+  USHORT cb;
+  USHORT usConfig;
+  USHORT usFlag;
+} PTRDRAWDATA;
+typedef PTRDRAWDATA *PPTRDRAWDATA;
+
+typedef struct _TRACKLAYOUT
+{
+  BYTE	 bCommand;
+  USHORT usHead;
+  USHORT usCylinder;
+  USHORT usFirstSector;
+  USHORT cSectors;
+  struct
+    {
+      USHORT usSectorNumber;
+      USHORT usSectorSize;
+    } TrackTable[1];
+} TRACKLAYOUT;
+typedef TRACKLAYOUT *PTRACKLAYOUT;
+
+typedef struct _TRACKFORMAT
+{
+  BYTE	 bCommand;
+  USHORT usHead;
+  USHORT usCylinder;
+  USHORT usReserved;
+  USHORT cSectors;
+  struct
+    {
+      BYTE bCylinder;
+      BYTE bHead;
+      BYTE idSector;
+      BYTE bBytesSector;
+    } FormatTable[1];
+} TRACKFORMAT;
+typedef TRACKFORMAT *PTRACKFORMAT;
+
+typedef struct _BIOSPARAMETERBLOCK
+{
+  USHORT usBytesPerSector;
+  BYTE	 bSectorsPerCluster;
+  USHORT usReservedSectors;
+  BYTE	 cFATs;
+  USHORT cRootEntries;
+  USHORT cSectors;
+  BYTE	 bMedia;
+  USHORT usSectorsPerFAT;
+  USHORT usSectorsPerTrack;
+  USHORT cHeads;
+  ULONG	 cHiddenSectors;
+  ULONG	 cLargeSectors;
+  BYTE	 abReserved[6];
+  USHORT cCylinders;
+  BYTE	 bDeviceType;
+  USHORT fsDeviceAttr;
+} BIOSPARAMETERBLOCK;
+typedef BIOSPARAMETERBLOCK *PBIOSPARAMETERBLOCK;
+
+typedef struct _DEVICEPARAMETERBLOCK
+{
+  USHORT reserved1;
+  USHORT cCylinders;
+  USHORT cHeads;
+  USHORT cSectorsPerTrack;
+  USHORT reserved2;
+  USHORT reserved3;
+  USHORT reserved4;
+  USHORT reserved5;
+} DEVICEPARAMETERBLOCK;
+typedef DEVICEPARAMETERBLOCK *PDEVICEPARAMETERBLOCK;
+
+typedef struct _MONITORPOSITION
+{
+  USHORT fPosition;
+  USHORT index;
+  ULONG	 pbInBuf;
+  USHORT offOutBuf;
+} MONITORPOSITION;
+typedef MONITORPOSITION *PMONITORPOSITION;
+
+typedef struct _FRAME
+{
+  BYTE bCharsPerLine;
+  BYTE bLinesPerInch;
+} FRAME;
+typedef FRAME *PFRAME;
+
+typedef struct _LDTADDRINFO
+{
+  PULONG pulPhysAddr;
+  USHORT cb;
+} LDTADDRINFO;
+typedef LDTADDRINFO *PLDTADDRINFO;
+
+typedef struct _SCREENGROUP
+{
+  USHORT idScreenGrp;
+  USHORT fTerminate;
+} SCREENGROUP;
+typedef SCREENGROUP *PSCREENGROUP;
+
+typedef struct _RXQUEUE
+{
+  USHORT cch;
+  USHORT cb;
+} RXQUEUE;
+typedef RXQUEUE *PRXQUEUE;
+
+typedef struct _GETLINIOCTLDATA
+{
+  ULONG PacketLength;
+  ULONG PhysicalAddress;
+  ULONG ApertureSize;
+  PBYTE LinearAddress;
+  ULONG LinearFlags;
+} GETLINIOCTLDATA;
+typedef GETLINIOCTLDATA *PGETLINIOCTLDATA;
+
+typedef struct _BANKINFO
+{
+  ULONG	 ulBankLength;
+  USHORT usBank;
+  USHORT usVideoModeType;
+  USHORT usReadWriteMode;
+} BANKINFO;
+
+typedef struct _GLOBALIOCTLDATA
+{
+  ULONG ProcessAddress;
+  ULONG AddressLength;
+  ULONG GlobalAddress;
+} GLOBALIOCTLDATA;
+
+typedef struct _OEMSVGAINFO
+{
+  USHORT AdapterType;
+  USHORT ChipType;
+  ULONG	 Memory;
+} OEMSVGAINFO;
+
+typedef struct _OEMINFO
+{
+  ULONG	 OEMLength;
+  USHORT Manufacturer;
+  ULONG	 ManufacturerData;
+} OEMINFO;
+
+typedef struct _GETGLOBALPACKET
+{
+  ULONG		  GlobalPktLength;
+  GLOBALIOCTLDATA GlobalPktData[1];
+} GETGLOBALPACKET;
+
+#endif /* INCL_DOSDEVIOCTL */
+
+/* -------------------- NATIONAL LANGUAGE SUPPORT ------------------------- */
+
+#if defined (INCL_DOSNLS)
+
+typedef struct _COUNTRYCODE
+{
+  ULONG country;
+  ULONG codepage;
+} COUNTRYCODE;
+typedef COUNTRYCODE *PCOUNTRYCODE;
+
+typedef struct _COUNTRYINFO
+{
+  ULONG	 country;
+  ULONG	 codepage;
+  ULONG	 fsDateFmt;
+  CHAR	 szCurrency[5];
+  CHAR	 szThousandsSeparator[2];
+  CHAR	 szDecimal[2];
+  CHAR	 szDateSeparator[2];
+  CHAR	 szTimeSeparator[2];
+  UCHAR	 fsCurrencyFmt;
+  UCHAR	 cDecimalPlace;
+  UCHAR	 fsTimeFmt;
+  USHORT abReserved1[2];
+  CHAR	 szDataSeparator[2];
+  USHORT abReserved2[5];
+} COUNTRYINFO;
+typedef COUNTRYINFO *PCOUNTRYINFO;
+
+
+ULONG DosMapCase (ULONG ulLength, __const__ COUNTRYCODE *pCountryCode,
+    PCHAR pchString);
+ULONG DosQueryCollate (ULONG ulLength, __const__ COUNTRYCODE *pCountryCode,
+    PCHAR pchBuffer, PULONG pulDataLength);
+ULONG DosQueryCp (ULONG ulLength, PULONG pCodePageList, PULONG pDataLength);
+ULONG DosQueryCtryInfo (ULONG ulLength, PCOUNTRYCODE pCountryCode,
+    PCOUNTRYINFO pCountryInfo, PULONG pulDataLength);
+ULONG DosQueryDBCSEnv (ULONG ulLength, PCOUNTRYCODE pCountryCode, PCHAR pBuf);
+ULONG DosSetProcessCp (ULONG ulCodePage);
+
+#endif /* INCL_DOSNLS */
+
+/* -------------------------- DYNAMIC LINKING ----------------------------- */
+
+#if defined (INCL_DOSMODULEMGR)
+
+#define PT_16BIT		0
+#define PT_32BIT		1
+
+
+ULONG DosFreeModule (HMODULE hmod);
+ULONG DosLoadModule (PSZ pszObject, ULONG uObjectLen, PCSZ pszModule,
+    PHMODULE phmod);
+ULONG DosQueryModuleHandle (PCSZ pszModname, PHMODULE phmod);
+ULONG DosQueryModuleName (HMODULE hmod, ULONG ulNameLength, PCHAR pNameBuf);
+ULONG DosQueryProcAddr (HMODULE hmod, ULONG ulOrdinal, PCSZ pszProcName,
+    PPFN pProcAddr);
+ULONG DosQueryProcType (HMODULE hmod, ULONG ulOrdinal, PCSZ pszProcName,
+     PULONG pulProcType);
+
+#endif /* INCL_DOSMODULEMGR */
+
+/* ----------------------------- RESOURCES -------------------------------- */
+
+#if defined (INCL_DOSRESOURCES) || !defined (INCL_NOCOMMON)
+
+#define RT_POINTER		1
+#define RT_BITMAP		2
+#define RT_MENU			3
+#define RT_DIALOG		4
+#define RT_STRING		5
+#define RT_FONTDIR		6
+#define RT_FONT			7
+#define RT_ACCELTABLE		8
+#define RT_RCDATA		9
+#define RT_MESSAGE		10
+#define RT_DLGINCLUDE		11
+#define RT_VKEYTBL		12
+#define RT_KEYTBL		13
+#define RT_CHARTBL		14
+#define RT_DISPLAYINFO		15
+#define RT_FKASHORT		16
+#define RT_FKALONG		17
+#define RT_HELPTABLE		18
+#define RT_HELPSUBTABLE		19
+#define RT_FDDIR		20
+#define RT_FD			21
+#define RT_MAX			22
+
+#define RF_ORDINALID		0x80000000L
+
+
+ULONG DosFreeResource (PVOID pResAddr);
+ULONG DosGetResource (HMODULE hmod, ULONG ulTypeID, ULONG ulNameID,
+    PPVOID pOffset);
+ULONG DosQueryResourceSize (HMODULE hmod, ULONG ulTypeID, ULONG ulNameID,
+    PULONG pulSize);
+
+#endif /* INCL_DOSRESOURCES || !INCL_NOCOMMON */
+
+/* -------------------------------- TASKS --------------------------------- */
+
+#if defined (INCL_DOSPROCESS) || !defined (INCL_NOCOMMON)
+
+#define EXIT_THREAD		0
+#define EXIT_PROCESS		1
+
+ULONG DosBeep (ULONG ulFrequency, ULONG ulDuration);
+VOID DosExit (ULONG ulAction, ULONG ulResult) __attribute__ ((__noreturn__));
+
+#endif /* INCL_DOSPROCESS || !defined (INCL_NOCOMMON) */
+
+
+#if defined (INCL_DOSPROCESS)
+
+#define CREATE_READY		0
+#define CREATE_SUSPENDED	1
+
+#define STACK_SPARSE		0
+#define STACK_COMMITTED		2
+
+#define DCWA_PROCESS		0
+#define DCWA_PROCESSTREE	1
+
+#define DCWW_WAIT		0
+#define DCWW_NOWAIT		1
+
+#define DKP_PROCESSTREE		0
+#define DKP_PROCESS		1
+
+#define EXEC_SYNC		0
+#define EXEC_ASYNC		1
+#define EXEC_ASYNCRESULT	2
+#define EXEC_TRACE		3
+#define EXEC_BACKGROUND		4
+#define EXEC_LOAD		5
+#define EXEC_ASYNCRESULTDB	6
+
+#define EXLST_ADD		1
+#define EXLST_REMOVE		2
+#define EXLST_EXIT		3
+
+#define PRTYC_NOCHANGE		0
+#define PRTYC_IDLETIME		1
+#define PRTYC_REGULAR		2
+#define PRTYC_TIMECRITICAL	3
+#define PRTYC_FOREGROUNDSERVER	4
+
+#define PRTYD_MINIMUM		(-31)
+#define PRTYD_MAXIMUM		31
+
+#define PRTYS_PROCESS		0
+#define PRTYS_PROCESSTREE	1
+#define PRTYS_THREAD		2
+
+#define TC_EXIT			0
+#define TC_HARDERROR		1
+#define TC_TRAP			2
+#define TC_KILLPROCESS		3
+#define TC_EXCEPTION		4
+
+
+typedef struct _RESULTCODES
+{
+  ULONG codeTerminate;
+  ULONG codeResult;
+} RESULTCODES;
+typedef RESULTCODES *PRESULTCODES;
+
+typedef struct tib2_s
+{
+  ULONG	 tib2_ultid;
+  ULONG	 tib2_ulpri;
+  ULONG	 tib2_version;
+  USHORT tib2_usMCCount;
+  USHORT tib2_fMCForceFlag;
+} TIB2;
+typedef TIB2 *PTIB2;
+
+typedef struct tib_s
+{
+  PVOID tib_pexchain;
+  PVOID tib_pstack;
+  PVOID tib_pstacklimit;
+  PTIB2 tib_ptib2;
+  ULONG tib_version;
+  ULONG tib_ordinal;
+} TIB;
+typedef TIB *PTIB;
+
+typedef struct pib_s
+{
+  ULONG pib_ulpid;
+  ULONG pib_ulppid;
+  ULONG pib_hmte;
+  PCHAR pib_pchcmd;
+  PCHAR pib_pchenv;
+  ULONG pib_flstatus;
+  ULONG pib_ultype;
+} PIB;
+typedef PIB *PPIB;
+
+typedef VOID (*PFNTHREAD)(ULONG ulThreadArg);
+typedef VOID (*PFNEXITLIST)(ULONG ulArg);
+
+
+ULONG DosAllocThreadLocalMemory (ULONG cb, PULONG *p);
+ULONG DosCreateThread (PTID ptidThreadID, PFNTHREAD pfnThreadAddr,
+    ULONG ulThreadArg, ULONG ulFlags, ULONG ulStackSize);
+ULONG DosEnterCritSec (VOID);
+ULONG DosExecPgm (PCHAR pObjname, LONG lObjnameLength, ULONG ulFlagS,
+    PCSZ pszArg, PCSZ pszEnv, PRESULTCODES pReturnCodes, PCSZ pszName);
+ULONG DosExitCritSec (VOID);
+ULONG DosExitList (ULONG ulOrder, PFNEXITLIST pfn);
+ULONG DosFreeThreadLocalMemory (ULONG *p);
+ULONG DosGetInfoBlocks (PTIB *ptib, PPIB *ppib);
+ULONG DosKillProcess (ULONG ulAction, PID pid);
+ULONG DosKillThread (TID tid);
+ULONG DosResumeThread (TID tid);
+ULONG DosSetPriority (ULONG ulScope, ULONG ulClass, LONG lDelta, ULONG ulID);
+ULONG DosSleep (ULONG ulInterval);
+ULONG DosSuspendThread (TID tid);
+ULONG DosVerifyPidTid (PID pid, TID tid);
+ULONG DosWaitChild (ULONG ulAction, ULONG ulWait, PRESULTCODES pReturnCodes,
+    PPID ppidOut, PID pidIn);
+ULONG DosWaitThread (PTID ptid, ULONG ulWait);
+
+#endif /* INCL_DOSPROCESS */
+
+/* ------------------------------ SESSIONS -------------------------------- */
+
+#if defined (INCL_DOSSESMGR) || defined (INCL_DOSFILEMGR)
+
+#define FAPPTYP_NOTSPEC		0x0000
+#define FAPPTYP_NOTWINDOWCOMPAT 0x0001
+#define FAPPTYP_WINDOWCOMPAT	0x0002
+#define FAPPTYP_WINDOWAPI	0x0003
+#define FAPPTYP_BOUND		0x0008
+#define FAPPTYP_DLL		0x0010
+#define FAPPTYP_DOS		0x0020
+#define FAPPTYP_PHYSDRV		0x0040
+#define FAPPTYP_VIRTDRV		0x0080
+#define FAPPTYP_PROTDLL		0x0100
+#define FAPPTYP_WINDOWSREAL	0x0200
+#define FAPPTYP_WINDOWSPROT	0x0400
+#define FAPPTYP_WINDOWSPROT31	0x1000
+#define FAPPTYP_32BIT		0x4000
+#define FAPPTYP_EXETYPE		0x0003
+#define FAPPTYP_RESERVED	(~(FAPPTYP_WINDOWAPI | FAPPTYP_BOUND | \
+				   FAPPTYP_DLL | FAPPTYP_DOS | \
+				   FAPPTYP_PHYSDRV | FAPPTYP_VIRTDRV | \
+				   FAPPTYP_PROTDLL | FAPPTYP_32BIT))
+
+#endif /* INCL_DOSSESMGR || INCL_DOSFILEMGR */
+
+#if defined (INCL_DOSSESMGR)
+
+#define SET_SESSION_UNCHANGED	       0
+#define SET_SESSION_SELECTABLE	       1
+#define SET_SESSION_NON_SELECTABLE     2
+#define SET_SESSION_BOND	       1
+#define SET_SESSION_NO_BOND	       2
+
+#define SSF_RELATED_INDEPENDENT 0
+#define SSF_RELATED_CHILD	1
+
+#define SSF_FGBG_FORE		0
+#define SSF_FGBG_BACK		1
+
+#define SSF_TRACEOPT_NONE	0
+#define SSF_TRACEOPT_TRACE	1
+#define SSF_TRACEOPT_TRACEALL	2
+
+#define SSF_INHERTOPT_SHELL	0
+#define SSF_INHERTOPT_PARENT	1
+
+#define SSF_TYPE_DEFAULT	0
+#define SSF_TYPE_FULLSCREEN	1
+#define SSF_TYPE_WINDOWABLEVIO	2
+#define SSF_TYPE_PM		3
+#define SSF_TYPE_VDM		4
+#define SSF_TYPE_GROUP		5
+#define SSF_TYPE_DLL		6
+#define SSF_TYPE_WINDOWEDVDM	7
+#define SSF_TYPE_PDD		8
+#define SSF_TYPE_VDD		9
+
+#define SSF_CONTROL_VISIBLE	0x0000
+#define SSF_CONTROL_INVISIBLE	0x0001
+#define SSF_CONTROL_MAXIMIZE	0x0002
+#define SSF_CONTROL_MINIMIZE	0x0004
+#define SSF_CONTROL_NOAUTOCLOSE 0x0008
+#define SSF_CONTROL_SETPOS	0x8000
+
+#define STOP_SESSION_SPECIFIED	       0
+#define STOP_SESSION_ALL	       1
+
+typedef struct _STARTDATA
+{
+  USHORT Length;
+  USHORT Related;
+  USHORT FgBg;
+  USHORT TraceOpt;
+  PSZ	 PgmTitle;
+  PSZ	 PgmName;
+  PBYTE	 PgmInputs;
+  PBYTE	 TermQ;
+  PBYTE	 Environment;
+  USHORT InheritOpt;
+  USHORT SessionType;
+  PSZ	 IconFile;
+  ULONG	 PgmHandle;
+  USHORT PgmControl;
+  USHORT InitXPos;
+  USHORT InitYPos;
+  USHORT InitXSize;
+  USHORT InitYSize;
+  USHORT Reserved;
+  PSZ	 ObjectBuffer;
+  ULONG	 ObjectBuffLen;
+} STARTDATA;
+typedef STARTDATA *PSTARTDATA;
+
+typedef struct _STATUSDATA
+{
+  USHORT Length;
+  USHORT SelectInd;
+  USHORT BondInd;
+} STATUSDATA;
+typedef STATUSDATA *PSTATUSDATA;
+
+ULONG DosQueryAppType (PCSZ pszName, PULONG pulFlags);
+ULONG DosSelectSession (ULONG ulIDSession);
+ULONG DosSetSession (ULONG ulIDSession, PSTATUSDATA psd);
+ULONG DosStartSession (PSTARTDATA psd, PULONG pulIDSession, PPID ppid);
+ULONG DosStopSession (ULONG ulScope, ULONG ulIDSession);
+
+#endif /* INCL_DOSSESMGR */
+
+/* ----------------------------- SEMAPHORES ------------------------------- */
+
+#if defined (INCL_DOSSEMAPHORES) || !defined (INCL_NOCOMMON)
+
+#define DC_SEM_SHARED		0x01
+#define DCMW_WAIT_ANY		0x02
+#define DCMW_WAIT_ALL		0x04
+
+#define SEM_INDEFINITE_WAIT	((ULONG)-1)
+#define SEM_IMMEDIATE_RETURN	0
+
+typedef ULONG HEV;
+typedef HEV *PHEV;
+
+typedef struct _PSEMRECORD	/* Note 1 */
+{
+  HSEM	hsemCur;
+  ULONG ulUser;
+} SEMRECORD;
+typedef SEMRECORD *PSEMRECORD;
+
+#endif /* INCL_DOSSEMAPHORES || !INCL_NOCOMMON */
+
+#if defined (INCL_DOSSEMAPHORES)
+
+ULONG DosCloseEventSem (HEV hev);
+ULONG DosCreateEventSem (PCSZ pszName, PHEV phev, ULONG ulAttr, BOOL32 fState);
+ULONG DosOpenEventSem (PCSZ pszName, PHEV phev);
+ULONG DosPostEventSem (HEV hev);
+ULONG DosQueryEventSem (HEV hev, PULONG pulCount);
+ULONG DosResetEventSem (HEV hev, PULONG pulCount);
+ULONG DosWaitEventSem (HEV hev, ULONG ulTimeout);
+
+ULONG DosCloseMutexSem (HMTX hmtx);
+ULONG DosCreateMutexSem (PCSZ pszName, PHMTX phmtx, ULONG ulAttr,
+    BOOL32 fState);
+ULONG DosOpenMutexSem (PCSZ pszName, PHMTX phmtx);
+ULONG DosQueryMutexSem (HMTX hmtx, PPID ppid, PTID ptid, PULONG pulCount);
+ULONG DosReleaseMutexSem (HMTX hmtx);
+ULONG DosRequestMutexSem (HMTX hmtx, ULONG ulTimeout);
+
+ULONG DosAddMuxWaitSem (HMUX hmux, PSEMRECORD pSemRec);
+ULONG DosCloseMuxWaitSem (HMUX hmux);
+ULONG DosCreateMuxWaitSem (PCSZ pszName, PHMUX phmux, ULONG ulcSemRec,
+    PSEMRECORD pSemRec, ULONG ulAttr);
+ULONG DosDeleteMuxWaitSem (HMUX hmux, HSEM hSem);
+ULONG DosOpenMuxWaitSem (PCSZ pszName, PHMUX phmux);
+ULONG DosQueryMuxWaitSem (HMUX hmux, PULONG pulcSemRec, PSEMRECORD pSemRec,
+    PULONG pulAttr);
+ULONG DosWaitMuxWaitSem (HMUX hmux, ULONG ulTimeout, PULONG pulUser);
+
+#endif /* INCL_DOSSEMAPHORES */
+
+/* ---------------------------- NAMED PIPES ------------------------------- */
+
+#define NP_INDEFINITE_WAIT	((ULONG)-1)
+#define NP_DEFAULT_WAIT		0
+
+#define NP_STATE_DISCONNECTED	1
+#define NP_STATE_LISTENING	2
+#define NP_STATE_CONNECTED	3
+#define NP_STATE_CLOSING	4
+
+#define NP_ACCESS_INBOUND	0x0000
+#define NP_ACCESS_OUTBOUND	0x0001
+#define NP_ACCESS_DUPLEX	0x0002
+#define NP_INHERIT		0x0000
+#define NP_NOINHERIT		0x0080
+#define NP_WRITEBEHIND		0x0000
+#define NP_NOWRITEBEHIND	0x4000
+
+#define NP_READMODE_BYTE	0x0000
+#define NP_READMODE_MESSAGE	0x0100
+#define NP_TYPE_BYTE		0x0000
+#define NP_TYPE_MESSAGE		0x0400
+#define NP_END_CLIENT		0x0000
+#define NP_END_SERVER		0x4000
+#define NP_WAIT			0x0000
+#define NP_NOWAIT		0x8000
+#define NP_UNLIMITED_INSTANCES	0x00ff
+
+#define NP_NBLK			NO_WAIT
+#define NP_SERVER		NP_END_SERVER
+#define NP_WMESG		NP_TYPE_MESSAGE
+#define NP_RMESG		NP_READMODE_MESSAGE
+#define NP_ICOUNT		0x00ff
+
+#define NPSS_EOI		0
+#define NPSS_RDATA		1
+#define NPSS_WSPACE		2
+#define NPSS_CLOSE		3
+
+#define NPSS_WAIT		0x0001
+
+typedef struct _AVAILDATA
+{
+  USHORT cbpipe;
+  USHORT cbmessage;
+} AVAILDATA;
+typedef AVAILDATA *PAVAILDATA;
+
+typedef struct _PIPEINFO
+{
+  USHORT cbOut;
+  USHORT cbIn;
+  BYTE	 cbMaxInst;
+  BYTE	 cbCurInst;
+  BYTE	 cbName;
+  CHAR	 szName[1];
+} PIPEINFO;
+typedef PIPEINFO *PPIPEINFO;
+
+typedef struct _PIPESEMSTATE
+{
+  BYTE	 fStatus;
+  BYTE	 fFlag;
+  USHORT usKey;
+  USHORT usAvail;
+} PIPESEMSTATE;
+typedef PIPESEMSTATE *PPIPESEMSTATE;
+
+ULONG DosCallNPipe (PCSZ pszName, PVOID pInbuf, ULONG ulInbufLength,
+    PVOID pOutbuf, ULONG ulOutbufSize, PULONG pulActualLength,
+    ULONG ulTimeout);
+ULONG DosConnectNPipe (HPIPE hpipe);
+ULONG DosCreateNPipe (PCSZ pszName, PHPIPE phpipe, ULONG ulOpenMode,
+    ULONG ulPipeMode, ULONG ulInbufLength, ULONG ulOutbufLength,
+    ULONG ulTimeout);
+ULONG DosDisConnectNPipe (HPIPE hpipe);
+ULONG DosPeekNPipe (HPIPE hpipe, PVOID pBuf, ULONG ulBufLength,
+    PULONG pulActualLength, PAVAILDATA pAvail, PULONG pulState);
+ULONG DosQueryNPHState (HPIPE hpipe, PULONG pulState);
+ULONG DosQueryNPipeInfo (HPIPE hpipe, ULONG ulInfoLevel, PVOID pBuf,
+    ULONG ulBufLength);
+ULONG DosQueryNPipeSemState (HSEM hsem, PPIPESEMSTATE pState,
+    ULONG ulBufLength);
+ULONG DosRawReadNPipe (PCSZ pszName, ULONG ulCount, PULONG pulLength,
+    PVOID pBuf);
+ULONG DosRawWriteNPipe (PCSZ pszName, ULONG ulCount);
+ULONG DosSetNPHState (HPIPE hpipe, ULONG ulState);
+ULONG DosSetNPipeSem (HPIPE hpipe, HSEM hsem, ULONG ulKey);
+ULONG DosTransactNPipe (HPIPE hpipe, PVOID pOutbuf, ULONG ulOutbufLength,
+    PVOID pInbuf, ULONG ulInbufLength, PULONG pulBytesRead);
+ULONG DosWaitNPipe (PCSZ pszName, ULONG ulTimeout);
+
+/* ------------------------------- QUEUES --------------------------------- */
+
+#if defined (INCL_DOSQUEUES)
+
+#define QUE_FIFO			0x0000
+#define QUE_LIFO			0x0001
+#define QUE_PRIORITY			0x0002
+#define QUE_NOCONVERT_ADDRESS		0x0000
+#define QUE_CONVERT_ADDRESS		0x0004
+
+typedef struct _REQUESTDATA
+{
+  PID	pid;
+  ULONG ulData;
+} REQUESTDATA;
+typedef REQUESTDATA *PREQUESTDATA;
+
+ULONG DosCreatePipe (PHFILE phfReadHandle, PHFILE phfWriteHandle,
+    ULONG ulPipeSize);
+
+ULONG DosCloseQueue (HQUEUE hq);
+ULONG DosCreateQueue (PHQUEUE phq, ULONG ulPriority, PCSZ pszName);
+ULONG DosOpenQueue (PPID ppid, PHQUEUE phq, PCSZ pszName);
+ULONG DosPeekQueue (HQUEUE hq, PREQUESTDATA pRequest, PULONG pulDataLength,
+    PPVOID pDataAddress, PULONG pulElement, BOOL32 fNowait, PBYTE pPriority,
+    HEV hsem);
+ULONG DosPurgeQueue (HQUEUE hq);
+ULONG DosQueryQueue (HQUEUE hq, PULONG pulCount);
+ULONG DosReadQueue (HQUEUE hq, PREQUESTDATA pRequest, PULONG pulDataLength,
+    PPVOID pDataAddress, ULONG pulElement, BOOL32 fNowait, PBYTE pPriority,
+    HEV hsem);
+ULONG DosWriteQueue (HQUEUE hq, ULONG ulRequest, ULONG ulDataLength,
+    PVOID pData, ULONG ulPriority);
+
+#endif /* INCL_DOSQUEUES */
+
+/* --------------------------- EXCEPTIONS --------------------------------- */
+
+#if defined (INCL_DOSEXCEPTIONS)
+
+#define CONTEXT_CONTROL			0x0001
+#define CONTEXT_INTEGER			0x0002
+#define CONTEXT_SEGMENTS		0x0004
+#define CONTEXT_FLOATING_POINT		0x0008
+#define CONTEXT_FULL			(CONTEXT_CONTROL | CONTEXT_INTEGER | \
+				  CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT)
+
+#define EH_NONCONTINUABLE		0x0001
+#define EH_UNWINDING			0x0002
+#define EH_EXIT_UNWIND			0x0004
+#define EH_STACK_INVALID		0x0008
+#define EH_NESTED_CALL			0x0010
+
+#define SIG_UNSETFOCUS			0
+#define SIG_SETFOCUS			1
+
+#define UNWIND_ALL			0
+
+#define XCPT_CONTINUE_SEARCH		0x00000000
+#define XCPT_CONTINUE_EXECUTION		0xffffffff
+#define XCPT_CONTINUE_STOP		0x00716668
+
+#define XCPT_SIGNAL_INTR		1
+#define XCPT_SIGNAL_KILLPROC		3
+#define XCPT_SIGNAL_BREAK		4
+
+#define XCPT_FATAL_EXCEPTION		0xc0000000
+#define XCPT_SEVERITY_CODE		0xc0000000
+#define XCPT_CUSTOMER_CODE		0x20000000
+#define XCPT_FACILITY_CODE		0x1fff0000
+#define XCPT_EXCEPTION_CODE		0x0000ffff
+
+#define XCPT_UNKNOWN_ACCESS		0x00000000
+#define XCPT_READ_ACCESS		0x00000001
+#define XCPT_WRITE_ACCESS		0x00000002
+#define XCPT_EXECUTE_ACCESS		0x00000004
+#define XCPT_SPACE_ACCESS		0x00000008
+#define XCPT_LIMIT_ACCESS		0x00000010
+#define XCPT_DATA_UNKNOWN		0xffffffff
+
+#define XCPT_GUARD_PAGE_VIOLATION	0x80000001
+#define XCPT_UNABLE_TO_GROW_STACK	0x80010001
+#define XCPT_ACCESS_VIOLATION		0xc0000005
+#define XCPT_IN_PAGE_ERROR		0xc0000006
+#define XCPT_ILLEGAL_INSTRUCTION	0xc000001c
+#define XCPT_INVALID_LOCK_SEQUENCE	0xc000001d
+#define XCPT_NONCONTINUABLE_EXCEPTION	0xc0000024
+#define XCPT_INVALID_DISPOSITION	0xc0000025
+#define XCPT_UNWIND			0xc0000026
+#define XCPT_BAD_STACK			0xc0000027
+#define XCPT_INVALID_UNWIND_TARGET	0xc0000028
+#define XCPT_ARRAY_BOUNDS_EXCEEDED	0xc0000093
+#define XCPT_FLOAT_DENORMAL_OPERAND	0xc0000094
+#define XCPT_FLOAT_DIVIDE_BY_ZERO	0xc0000095
+#define XCPT_FLOAT_INEXACT_RESULT	0xc0000096
+#define XCPT_FLOAT_INVALID_OPERATION	0xc0000097
+#define XCPT_FLOAT_OVERFLOW		0xc0000098
+#define XCPT_FLOAT_STACK_CHECK		0xc0000099
+#define XCPT_FLOAT_UNDERFLOW		0xc000009a
+#define XCPT_INTEGER_DIVIDE_BY_ZERO	0xc000009b
+#define XCPT_INTEGER_OVERFLOW		0xc000009c
+#define XCPT_PRIVILEGED_INSTRUCTION	0xc000009d
+#define XCPT_DATATYPE_MISALIGNMENT	0xc000009e
+#define XCPT_BREAKPOINT			0xc000009f
+#define XCPT_SINGLE_STEP		0xc00000a0
+#define XCPT_PROCESS_TERMINATE		0xc0010001
+#define XCPT_ASYNC_PROCESS_TERMINATE	0xc0010002
+#define XCPT_SIGNAL			0xc0010003
+
+typedef struct _fpreg		/* Note 1 */
+{
+  ULONG	 losig;
+  ULONG	 hisig;
+  USHORT signexp;
+} FPREG;
+typedef FPREG *PFPREG;
+
+typedef struct _CONTEXT		/* Note 1 */
+{
+  ULONG ContextFlags;
+  ULONG ctx_env[7];
+  FPREG ctx_stack[8];
+  ULONG ctx_SegGs;
+  ULONG ctx_SegFs;
+  ULONG ctx_SegEs;
+  ULONG ctx_SegDs;
+  ULONG ctx_RegEdi;
+  ULONG ctx_RegEsi;
+  ULONG ctx_RegEax;
+  ULONG ctx_RegEbx;
+  ULONG ctx_RegEcx;
+  ULONG ctx_RegEdx;
+  ULONG ctx_RegEbp;
+  ULONG ctx_RegEip;
+  ULONG ctx_SegCs;
+  ULONG ctx_EFlags;
+  ULONG ctx_RegEsp;
+  ULONG ctx_SegSs;
+} CONTEXTRECORD;
+typedef CONTEXTRECORD *PCONTEXTRECORD;
+
+#define EXCEPTION_MAXIMUM_PARAMETERS 4
+
+typedef struct _EXCEPTIONREPORTRECORD
+{
+  ULONG				  ExceptionNum;
+  ULONG				  fHandlerFlags;
+  struct _EXCEPTIONREPORTRECORD * NestedExceptionReportRecord;
+  PVOID				  ExceptionAddress;
+  ULONG				  cParameters;
+  ULONG				  ExceptionInfo[EXCEPTION_MAXIMUM_PARAMETERS];
+} EXCEPTIONREPORTRECORD;
+typedef EXCEPTIONREPORTRECORD *PEXCEPTIONREPORTRECORD;
+
+struct _EXCEPTIONREGISTRATIONRECORD;
+
+typedef ULONG _ERR (PEXCEPTIONREPORTRECORD pReport,
+		    struct _EXCEPTIONREGISTRATIONRECORD *pRegistration,
+		    PCONTEXTRECORD pContext, PVOID pWhatever);
+typedef _ERR *ERR;
+
+typedef struct _EXCEPTIONREGISTRATIONRECORD
+{
+  struct _EXCEPTIONREGISTRATIONRECORD * __volatile__ prev_structure;
+  ERR __volatile__				     ExceptionHandler;
+} EXCEPTIONREGISTRATIONRECORD;
+typedef EXCEPTIONREGISTRATIONRECORD *PEXCEPTIONREGISTRATIONRECORD;
+
+#define END_OF_CHAIN		((PEXCEPTIONREGISTRATIONRECORD)(-1))
+
+ULONG DosAcknowledgeSignalException (ULONG ulSignal);
+ULONG DosEnterMustComplete (PULONG pulNesting);
+ULONG DosExitMustComplete (PULONG pulNesting);
+ULONG DosQueryThreadContext (TID tid, ULONG ulLevel, PCONTEXTRECORD pContext);
+ULONG DosRaiseException (PEXCEPTIONREPORTRECORD pXRepRec);
+ULONG DosSendSignalException (PID pid, ULONG ulSignal);
+ULONG DosSetExceptionHandler (PEXCEPTIONREGISTRATIONRECORD pXRegRec);
+ULONG DosSetSignalExceptionFocus (BOOL32 flag, PULONG pulTimes);
+ULONG DosUnsetExceptionHandler (PEXCEPTIONREGISTRATIONRECORD pXRegRec);
+ULONG DosUnwindException (PEXCEPTIONREGISTRATIONRECORD pXRegRec,
+    PVOID pJumpThere, PEXCEPTIONREPORTRECORD pXRepRec);
+
+#endif /* INCL_DOSEXCEPTIONS */
+
+/* --------------------------- INFORMATION -------------------------------- */
+
+#if defined (INCL_DOSMISC)
+
+#define QSV_MAX_PATH_LENGTH		1
+#define QSV_MAX_TEXT_SESSIONS		2
+#define QSV_MAX_PM_SESSIONS		3
+#define QSV_MAX_VDM_SESSIONS		4
+#define QSV_BOOT_DRIVE			5
+#define QSV_DYN_PRI_VARIATION		6
+#define QSV_MAX_WAIT			7
+#define QSV_MIN_SLICE			8
+#define QSV_MAX_SLICE			9
+#define QSV_PAGE_SIZE			10
+#define QSV_VERSION_MAJOR		11
+#define QSV_VERSION_MINOR		12
+#define QSV_VERSION_REVISION		13
+#define QSV_MS_COUNT			14
+#define QSV_TIME_LOW			15
+#define QSV_TIME_HIGH			16
+#define QSV_TOTPHYSMEM			17
+#define QSV_TOTRESMEM			18
+#define QSV_TOTAVAILMEM			19
+#define QSV_MAXPRMEM			20
+#define QSV_MAXSHMEM			21
+#define QSV_TIMER_INTERVAL		22
+#define QSV_MAX_COMP_LENGTH		23
+#define QSV_FOREGROUND_FS_SESSION	24
+#define QSV_FOREGROUND_PROCESS		25
+#define QSV_MAX				QSV_FOREGROUND_PROCESS
+
+#define SIS_MMIOADDR			0
+#define SIS_MEC_TABLE			1
+#define SIS_SYS_LOG			2
+
+ULONG DosQuerySysInfo (ULONG ulStart, ULONG ulLast, PVOID pBuf,
+    ULONG ulBufLength);
+ULONG DosScanEnv (PCSZ pszName, PSZ *pszValue);
+ULONG DosQueryRASInfo (ULONG Index, PPVOID Addr);
+
+#endif /* INCL_DOSMISC */
+
+/* ---------------------------- TIMERS ------------------------------------ */
+
+#if defined (INCL_DOSDATETIME) || !defined (INCL_NOCOMMON)
+
+typedef struct _DATETIME
+{
+  UCHAR	 hours;
+  UCHAR	 minutes;
+  UCHAR	 seconds;
+  UCHAR	 hundredths;
+  UCHAR	 day;
+  UCHAR	 month;
+  USHORT year;
+  SHORT	 timezone;
+  UCHAR	 weekday;
+} DATETIME;
+typedef DATETIME *PDATETIME;
+
+ULONG DosGetDateTime (PDATETIME pdt);
+ULONG DosSetDateTime (__const__ DATETIME *pdt);
+
+#endif /* INCL_DOSDATETIME || !INCL_NOCOMMON */
+
+
+#if defined (INCL_DOSDATETIME)
+
+typedef LHANDLE HTIMER;
+typedef HTIMER	*PHTIMER;
+
+ULONG DosAsyncTimer (ULONG ulMilliSec, HSEM hsem, PHTIMER phtimer);
+ULONG DosStartTimer (ULONG ulMilliSec, HSEM hsem, PHTIMER phtimer);
+ULONG DosStopTimer (HTIMER htimer);
+
+#endif /* INCL_DOSDATETIME */
+
+#if defined (INCL_DOSPROFILE)
+
+typedef struct _QWORD
+{
+  ULONG ulLo;
+  ULONG ulHi;
+} QWORD;
+typedef QWORD *PQWORD;
+
+ULONG DosTmrQueryFreq (PULONG pulTmrFreq);
+ULONG DosTmrQueryTime (PQWORD pqwTmrTime);
+
+#endif /* INCL_DOSPROFILE */
+
+/* ---------------------- VIRTUAL DOS MACHINES----------------------------- */
+
+typedef USHORT SGID;
+
+#if defined (INCL_DOSMVDM)
+
+typedef LHANDLE HVDD;
+typedef HVDD *PHVDD;
+
+ULONG DosCloseVDD (HVDD hvdd);
+ULONG DosOpenVDD (PCSZ pszVDD, PHVDD phvdd);
+ULONG DosQueryDOSProperty (SGID sgidSesssionID, PCSZ pszName,
+    ULONG ulBufferLength, PSZ pBuffer);
+ULONG DosRequestVDD (HVDD hvdd, SGID sgidSessionID, ULONG ulCommand,
+    ULONG ulInputBufferLength, PVOID pInputBuffer,
+    ULONG ulOutputBufferLength, PVOID pOutputBuffer);
+ULONG DosSetDOSProperty (SGID sgidSessionID, PCSZ pszName,
+    ULONG ulBufferLength, PCSZ pBuffer);
+
+#endif /* INCL_DOSMVDM */
+
+/* --------------------------- DEBUGGING ---------------------------------- */
+
+#if defined (INCL_DOSPROCESS)
+
+#define DBG_C_Null			0
+#define DBG_C_ReadMem			1
+#define DBG_C_ReadMem_I			1
+#define DBG_C_ReadMem_D			2
+#define DBG_C_ReadReg			3
+#define DBG_C_WriteMem			4
+#define DBG_C_WriteMem_I		4
+#define DBG_C_WriteMem_D		5
+#define DBG_C_WriteReg			6
+#define DBG_C_Go			7
+#define DBG_C_Term			8
+#define DBG_C_SStep			9
+#define DBG_C_Stop			10
+#define DBG_C_Freeze			11
+#define DBG_C_Resume			12
+#define DBG_C_NumToAddr			13
+#define DBG_C_ReadCoRegs		14
+#define DBG_C_WriteCoRegs		15
+#define DBG_C_ThrdStat			17
+#define DBG_C_MapROAlias		18
+#define DBG_C_MapRWAlias		19
+#define DBG_C_UnMapAlias		20
+#define DBG_C_Connect			21
+#define DBG_C_ReadMemBuf		22
+#define DBG_C_WriteMemBuf		23
+#define DBG_C_SetWatch			24
+#define DBG_C_ClearWatch		25
+#define DBG_C_RangeStep			26
+#define DBG_C_Continue			27
+#define DBG_C_AddrToObject		28
+#define DBG_C_XchngOpcode		29
+#define DBG_C_LinToSel			30
+#define DBG_C_SelToLin			31
+
+#define DBG_N_Success			0
+#define DBG_N_Error			(-1)
+#define DBG_N_ProcTerm			(-6)
+#define DBG_N_Exception			(-7)
+#define DBG_N_ModuleLoad		(-8)
+#define DBG_N_CoError			(-9)
+#define DBG_N_ThreadTerm		(-10)
+#define DBG_N_AsyncStop			(-11)
+#define DBG_N_NewProc			(-12)
+#define DBG_N_AliasFree			(-13)
+#define DBG_N_Watchpoint		(-14)
+#define DBG_N_ThreadCreate		(-15)
+#define DBG_N_ModuleFree		(-16)
+#define DBG_N_RangeStep			(-17)
+
+#define DBG_D_Thawed			0
+#define DBG_D_Frozen			1
+
+#define DBG_T_Runnable			0
+#define DBG_T_Suspended			1
+#define DBG_T_Blocked			2
+#define DBG_T_CritSec			3
+
+#define DBG_L_386			1
+
+#define DBG_LEN_387			108
+
+#define DBG_CO_387			1
+
+#define DBG_O_OBJMTE			0x10000000
+
+#define DBG_W_Global			0x00000001
+#define DBG_W_Local			0x00000002
+#define DBG_W_Execute			0x00010000
+#define DBG_W_Write			0x00020000
+#define DBG_W_ReadWrite			0x00030000
+
+#define DBG_X_PRE_FIRST_CHANCE		0x00000000
+#define DBG_X_FIRST_CHANCE		0x00000001
+#define DBG_X_LAST_CHANCE		0x00000002
+#define DBG_X_STACK_INVALID		0x00000003
+
+typedef struct _TStat
+{
+  UCHAR	 DbgState;
+  UCHAR	 TState;
+  USHORT TPriority;
+} TStat_t;
+
+typedef struct _uDB
+{
+  ULONG	 Pid;
+  ULONG	 Tid;
+  LONG	 Cmd;
+  LONG	 Value;
+  ULONG	 Addr;
+  ULONG	 Buffer;
+  ULONG	 Len;
+  ULONG	 Index;
+  ULONG	 MTE;
+  ULONG	 EAX;
+  ULONG	 ECX;
+  ULONG	 EDX;
+  ULONG	 EBX;
+  ULONG	 ESP;
+  ULONG	 EBP;
+  ULONG	 ESI;
+  ULONG	 EDI;
+  ULONG	 EFlags;
+  ULONG	 EIP;
+  ULONG	 CSLim;
+  ULONG	 CSBase;
+  UCHAR	 CSAcc;
+  UCHAR	 CSAtr;
+  USHORT CS;
+  ULONG	 DSLim;
+  ULONG	 DSBase;
+  UCHAR	 DSAcc;
+  UCHAR	 DSAtr;
+  USHORT DS;
+  ULONG	 ESLim;
+  ULONG	 ESBase;
+  UCHAR	 ESAcc;
+  UCHAR	 ESAtr;
+  USHORT ES;
+  ULONG	 FSLim;
+  ULONG	 FSBase;
+  UCHAR	 FSAcc;
+  UCHAR	 FSAtr;
+  USHORT FS;
+  ULONG	 GSLim;
+  ULONG	 GSBase;
+  UCHAR	 GSAcc;
+  UCHAR	 GSAtr;
+  USHORT GS;
+  ULONG	 SSLim;
+  ULONG	 SSBase;
+  UCHAR	 SSAcc;
+  UCHAR	 SSAtr;
+  USHORT SS;
+} uDB_t;
+
+ULONG DosDebug (uDB_t *pDebugBuffer);
+
+#endif /* INCL_DOSPROCESS */
+
+/* ---------------------------- MESSAGES ---------------------------------- */
+
+#if defined (INCL_DOSMISC)
+
+ULONG DosGetMessage (PCHAR *pTable, ULONG ulTableEntries,
+    PCHAR pBuffer, ULONG ulBufferLengthMax, ULONG ulMsgnNumber,
+    PCSZ pszFile, PULONG pulBufferLength);
+ULONG DosInsertMessage (PCHAR *pTable, ULONG ulCount, PCSZ pszMsg,
+    ULONG ulMsgLength, PCHAR pBuffer, ULONG ulBufferLengthMax,
+    PULONG pulBufferLength);
+ULONG DosPutMessage (HFILE hfile, ULONG ulMessageLength, PCHAR pMessage);
+ULONG DosQueryMessageCP (PCHAR pBuffer, ULONG ulBufferLengthMax,
+    PCSZ pszFilename, PULONG pulBufferLength);
+
+#endif /* INCL_DOSMISC */
+
+/* ----------------------------- RAS -------------------------------------- */
+
+#if defined (INCL_DOSRAS)
+
+#define DDP_DISABLEPROCDUMP		0
+#define DDP_ENABLEPROCDUMP		1
+#define DDP_PERFORMPROCDUMP		2
+
+#define LF_LOGENABLE			0x0001
+#define LF_LOGAVAILABLE			0x0002
+
+#define SIS_MMIOADDR			0
+#define SIS_MEC_TABLE			1
+#define SIS_SYS_LOG			2
+
+#define SPU_DISABLESUPPRESSION		0
+#define SPU_ENABLESUPPRESSION		1
+
+ULONG DosDumpProcess (ULONG ulFlag, ULONG ulDrive, PID pid);
+ULONG DosForceSystemDump (ULONG ulReserved);
+ULONG DosQueryRASInfo (ULONG ulIndex, PPVOID addr);
+ULONG DosSuppressPopUps (ULONG ulFlag, ULONG ulDrive);
+
+#endif /* INCL_DOSRAS */
+
+/* ---------------------------- REXX -------------------------------------- */
+
+#if defined (INCL_RXSUBCOM) || defined (INCL_RXSHV) || defined (INCL_RXFUNC) || defined (INCL_RXSYSEXIT) || defined (INCL_RXMACRO) || defined (INCL_RXARI)
+
+#define RXAUTOBUFLEN			256
+
+typedef struct _RXSTRING
+{
+  ULONG strlength;
+  PCH	strptr;
+} RXSTRING;
+typedef RXSTRING *PRXSTRING;
+
+typedef struct _RXSYSEXIT
+{
+  PSZ  sysexit_name;
+  LONG sysexit_code;
+} RXSYSEXIT;
+typedef RXSYSEXIT *PRXSYSEXIT;
+
+#define RXNULLSTRING(r)		((r).strptr == (PCH)0)
+#define RXZEROLENSTRING(r)	((r).strptr != (PCH)0 && (r).strlength == 0)
+#define RXVALIDSTRING(r)	((r).strptr != (PCH)0 && (r).strlength != 0)
+#define RXSTRLEN(r)		(RXNULLSTRING(r) ? 0 : (r).strlength)
+#define RXSTRPTR(r)		(r).strptr
+#define MAKERXSTRING(r,p,l) \
+    ((r).strptr = (PCH)p, (r).strlength = (ULONG)l)
+
+#define RXCOMMAND			0
+#define RXSUBROUTINE			1
+#define RXFUNCTION			2
+
+#endif /* INCL_RX* */
+
+#if defined (INCL_RXSUBCOM)
+
+#define RXSUBCOM_DROPPABLE		0x0000
+#define RXSUBCOM_NONDROP		0x0001
+
+#define RXSUBCOM_ISREG			0x0001
+#define RXSUBCOM_ERROR			0x0001
+#define RXSUBCOM_FAILURE		0x0002
+
+#define RXSUBCOM_BADENTRY		1001
+#define RXSUBCOM_NOEMEM			1002
+#define RXSUBCOM_BADTYPE		1003
+#define RXSUBCOM_NOTINIT		1004
+
+#define RXSUBCOM_OK			0
+#define RXSUBCOM_DUP			10
+#define RXSUBCOM_MAXREG			20
+#define RXSUBCOM_NOTREG			30
+#define RXSUBCOM_NOCANDROP		40
+#define RXSUBCOM_LOADERR		50
+#define RXSUBCOM_NOPROC			127
+
+typedef ULONG RexxSubcomHandler (PRXSTRING prxCommand, PUSHORT pusFlags,
+    PRXSTRING prxResult);
+
+ULONG RexxDeregisterSubcom (PCSZ pszEnvName, PCSZ pszModuleName);
+ULONG RexxQuerySubcom (PCSZ pszEnvName, PCSZ pszModuleName, PUSHORT pusFlags,
+    PUCHAR pUserWord);
+ULONG RexxRegisterSubcomDll (PCSZ pszEnvName, PCSZ pszModuleName,
+    PCSZ pszEntryPoint, PUCHAR pUserArea, ULONG ulDropAuth);
+ULONG RexxRegisterSubcomExe (PCSZ pszEnvName, PFN pfnEntryPoint,
+    PUCHAR pUserArea);
+
+#define REXXDEREGISTERSUBCOM  RexxDeregisterSubcom
+#define REXXREGISTERSUBCOMDLL		RexxRegisterSubcomDll
+#define REXXREGISTERSUBCOMEXE		RexxRegisterSubcomExe
+#define REXXQUERYSUBCOM			RexxQuerySubcom
+
+#endif /* INCL_RXSUBCOM */
+
+#if defined (INCL_RXSHV)
+
+#define RXSHV_SET			0x0000
+#define RXSHV_FETCH			0x0001
+#define RXSHV_DROPV			0x0002
+#define RXSHV_SYSET			0x0003
+#define RXSHV_SYFET			0x0004
+#define RXSHV_SYDRO			0x0005
+#define RXSHV_NEXTV			0x0006
+#define RXSHV_PRIV			0x0007
+#define RXSHV_EXIT			0x0008
+
+#define RXSHV_NOAVL			144
+
+#define RXSHV_OK			0x0000
+#define RXSHV_NEWV			0x0001
+#define RXSHV_LVAR			0x0002
+#define RXSHV_TRUNC			0x0004
+#define RXSHV_BADN			0x0008
+#define RXSHV_MEMFL			0x0010
+#define RXSHV_BADF			0x0080
+
+typedef struct _SHVBLOCK
+{
+  struct _SHVBLOCK *shvnext;
+  RXSTRING	    shvname;
+  RXSTRING	    shvvalue;
+  ULONG		    shvnamelen;
+  ULONG		    shvvaluelen;
+  UCHAR		    shvcode;
+  UCHAR		    shvret;
+} SHVBLOCK;
+typedef SHVBLOCK *PSHVBLOCK;
+
+ULONG RexxVariablePool (PSHVBLOCK pRequest);
+
+#define REXXVARIABLEPOOL		RexxVariablePool
+
+#endif /* INCL_RXSHV */
+
+#if defined (INCL_RXFUNC)
+
+#define RXFUNC_DYNALINK			1
+#define RXFUNC_CALLENTRY		2
+
+#define RXFUNC_OK			0
+#define RXFUNC_DEFINED			10
+#define RXFUNC_NOMEM			20
+#define RXFUNC_NOTREG			30
+#define RXFUNC_MODNOTFND		40
+#define RXFUNC_ENTNOTFND		50
+#define RXFUNC_NOTINIT			60
+#define RXFUNC_BADTYPE			70
+
+typedef ULONG RexxFunctionHandler (PCSZ pszName, ULONG ulArgCount,
+    PRXSTRING prxArgList, PCSZ pszQueueName, PRXSTRING prxResult);
+
+ULONG RexxDeregisterFunction (PCSZ pszFuncName);
+ULONG RexxQueryFunction (PCSZ pszFuncName);
+ULONG RexxRegisterFunctionDll (PCSZ pszFuncName, PCSZ pszModuleName,
+    PCSZ pszEntryPoint);
+ULONG RexxRegisterFunctionExe (PCSZ pszFuncName,
+    RexxFunctionHandler *pfnEntryPoint);
+
+#define REXXDEREGISTERFUNCTION	RexxDeregisterFunction
+#define REXXQUERYFUNCTION  RexxQueryFunction
+#define REXXREGISTERFUNCTIONDLL		RexxRegisterFunctionDll
+#define REXXREGISTERFUNCTIONEXE		RexxRegisterFunctionExe
+
+#endif /* INCL_RXFUNC */
+
+#if defined (INCL_RXSYSEXIT)
+
+#define RXEXIT_DROPPABLE		0x0000
+#define RXEXIT_NONDROP			0x0001
+
+#define RXEXIT_HANDLED			0
+#define RXEXIT_NOT_HANDLED		1
+#define RXEXIT_RAISE_ERROR		(-1)
+
+#define RXEXIT_ISREG			0x0001
+#define RXEXIT_ERROR			0x0001
+#define RXEXIT_FAILURE			0x0002
+
+#define RXEXIT_BADENTRY			1001
+#define RXEXIT_NOEMEM			1002
+#define RXEXIT_BADTYPE			1003
+#define RXEXIT_NOTINIT			1004
+
+#define RXEXIT_OK			0
+#define RXEXIT_DUP			10
+#define RXEXIT_MAXREG			20
+#define RXEXIT_NOTREG			30
+#define RXEXIT_NOCANDROP		40
+#define RXEXIT_LOADERR			50
+#define RXEXIT_NOPROC			127
+
+#define RXENDLST			0
+
+#define RXFNC				2
+#define RXFNCCAL			1
+
+#define RXCMD				3
+#define RXCMDHST			1
+
+#define RXMSQ				4
+#define RXMSQPLL			1
+#define RXMSQPSH			2
+#define RXMSQSIZ			3
+#define RXMSQNAM			20
+
+#define RXSIO				5
+#define RXSIOSAY			1
+#define RXSIOTRC			2
+#define RXSIOTRD			3
+#define RXSIODTR			4
+#define RXSIOTLL			5
+
+#define RXHLT				7
+#define RXHLTCLR			1
+#define RXHLTTST			2
+
+#define RXTRC				8
+#define RXTRCTST			1
+
+#define RXINI				9
+#define RXINIEXT			1
+
+#define RXTER				10
+#define RXTEREXT			1
+
+#define RXNOOFEXITS			11
+
+typedef PUCHAR PEXIT;
+
+typedef struct _RXFNC_FLAGS
+{
+  ULONG rxfferr	 : 1;
+  ULONG rxffnfnd : 1;
+  ULONG rxffsub	 : 1;
+} RXFNC_FLAGS;
+
+typedef struct _RXFNCCAL_PARM
+{
+  RXFNC_FLAGS rxfnc_flags;
+  PUCHAR      rxfnc_name;
+  USHORT      rxfnc_namel;
+  PUCHAR      rxfnc_que;
+  USHORT      rxfnc_quel;
+  USHORT      rxfnc_argc;
+  PRXSTRING   rxfnc_argv;
+  RXSTRING    rxfnc_retc;
+} RXFNCCAL_PARM;
+
+typedef struct _RXCMD_FLAGS
+{
+  ULONG rxfcfail : 1;
+  ULONG rxfcerr	 : 1;
+} RXCMD_FLAGS;
+
+typedef struct _RXCMDHST_PARM
+{
+  RXCMD_FLAGS rxcmd_flags;
+  PUCHAR      rxcmd_address;
+  USHORT      rxcmd_addressl;
+  PUCHAR      rxcmd_dll;
+  USHORT      rxcmd_dll_len;
+  RXSTRING    rxcmd_command;
+  RXSTRING    rxcmd_retc;
+} RXCMDHST_PARM;
+
+typedef struct _RXMSQPLL_PARM
+{
+  RXSTRING rxmsq_retc;
+} RXMSQPLL_PARM;
+
+typedef struct _RXMSQ_FLAGS
+{
+  ULONG rxfmlifo : 1;
+} RXMSQ_FLAGS;
+
+typedef struct _RXMSQPSH_PARM
+{
+  RXMSQ_FLAGS rxmsq_flags;
+  RXSTRING    rxmsq_value;
+} RXMSQPSH_PARM;
+
+typedef struct _RXMSQSIZ_PARM
+{
+  ULONG rxmsq_size;
+} RXMSQSIZ_PARM;
+
+typedef struct _RXMSQNAM_PARM
+{
+  RXSTRING rxmsq_name;
+} RXMSQNAM_PARM;
+
+typedef struct _RXSIOSAY_PARM
+{
+  RXSTRING rxsio_string;
+} RXSIOSAY_PARM;
+
+typedef struct _RXSIOTRC_PARM
+{
+  RXSTRING rxsio_string;
+} RXSIOTRC_PARM;
+
+typedef struct _RXSIOTRD_PARM
+{
+  RXSTRING rxsiotrd_retc;
+} RXSIOTRD_PARM;
+
+typedef struct _RXSIODR_PARM
+{
+  RXSTRING rxsiodtr_retc;
+} RXSIODTR_PARM;
+
+typedef struct _RXHLT_FLAGS
+{
+  ULONG rxfhhalt : 1;
+} RXHLT_FLAGS;
+
+typedef struct _RXHLTTST_PARM
+{
+  RXHLT_FLAGS rxhlt_flags;
+} RXHLTTST_PARM;
+
+typedef struct _RXTRC_FLAGS
+{
+  ULONG rxftrace : 1;
+} RXTRC_FLAGS;
+
+typedef struct _RXTRCTST_PARM
+{
+  RXTRC_FLAGS rxtrc_flags;
+} RXTRCTST_PARM;
+
+typedef LONG RexxExitHandler (LONG lExitNumber, LONG lSubfunction,
+    PEXIT pParmBlock);
+
+ULONG RexxDeregisterExit (PCSZ pszEnvName, PCSZ pszModuleName);
+ULONG RexxQueryExit (PCSZ pszEnvName, PCSZ pszModuleName, PUSHORT pusFlag,
+    PUCHAR pUserWord);
+ULONG RexxRegisterExitDll (PCSZ pszEnvName, PCSZ pszModuleName,
+    PCSZ pszEntryName, PUCHAR pUserArea, ULONG ulDropAuth);
+ULONG RexxRegisterExitExe (PCSZ pszEnvName, PFN pfnEntryPoint,
+    PUCHAR pUserArea);
+
+#define REXXDEREGISTEREXIT		RexxDeregisterExit
+#define REXXQUERYEXIT			RexxQueryExit
+#define REXXREGISTEREXITDLL		RexxRegisterExitDll
+#define REXXREGISTEREXITEXE		RexxRegisterExitExe
+
+#endif /* INCL_RXSYSEXIT */
+
+#if defined (INCL_RXARI)
+
+#define RXARI_OK			0
+#define RXARI_NOT_FOUND			1
+#define RXARI_PROCESSING_ERROR		2
+
+ULONG RexxResetTrace (PID pid, TID tid);
+ULONG RexxSetHalt (PID pid, TID tid);
+ULONG RexxSetTrace (PID pid, TID tid);
+
+#define REXXRESETTRACE			RexxResetTrace
+#define REXXSETHALT			RexxSetHalt
+#define REXXSETTRACE			RexxSetTrace
+
+#endif /* INCL_RXARI */
+
+#if defined (INCL_RXMACRO)
+
+#define RXMACRO_SEARCH_BEFORE		1
+#define RXMACRO_SEARCH_AFTER		2
+
+#define RXMACRO_OK			0
+#define RXMACRO_NO_STORAGE		1
+#define RXMACRO_NOT_FOUND		2
+#define RXMACRO_EXTENSION_REQUIRED	3
+#define RXMACRO_ALREADY_EXISTS		4
+#define RXMACRO_FILE_ERROR		5
+#define RXMACRO_SIGNATURE_ERROR		6
+#define RXMACRO_SOURCE_NOT_FOUND	7
+#define RXMACRO_INVALID_POSITION	8
+#define RXMACRO_NOT_INIT		9
+
+ULONG RexxAddMacro (PCSZ pszFuncName, PCSZ pszSourceFile, ULONG ulPosition);
+ULONG RexxClearMacroSpace (VOID);
+ULONG RexxDropMacro (PCSZ pszFuncName);
+ULONG RexxLoadMacroSpace (ULONG ulFuncCout, PCSZ *apszFuncNames,
+    PCSZ pszMacroLibFile);
+ULONG RexxQueryMacro (PCSZ pszFuncName, PUSHORT pusPosition);
+ULONG RexxReorderMacro(PCSZ pszFuncName, ULONG ulPosition);
+ULONG RexxSaveMacroSpace (ULONG ulFuncCount, PCSZ *apszFuncNames,
+    PCSZ pszMacroLibFile);
+
+#define REXXADDMACRO			RexxAddMacro
+#define REXXCLEARMACROSPACE		RexxClearMacroSpace
+#define REXXDROPMACRO			RexxDropMacro
+#define REXXSAVEMACROSPACE		RexxSaveMacroSpace
+#define REXXLOADMACROSPACE		RexxLoadMacroSpace
+#define REXXQUERYMACRO			RexxQueryMacro
+#define REXXREORDERMACRO		RexxReorderMacro
+
+#endif /* INCL_RXMACRO	*/
+
+#if defined (INCL_RXSUBCOM) || defined (INCL_RXSHV) || defined (INCL_RXFUNC) || defined (INCL_RXSYSEXIT) || defined (INCL_RXMACRO) || defined (INCL_RXARI)
+
+LONG RexxStart (LONG lArgCount, PRXSTRING prxArgList, PCSZ pszProgramName,
+    PRXSTRING prxInstore, PCSZ pszEnvName, LONG lCallType, PRXSYSEXIT pExits,
+    PSHORT psReturnCode, PRXSTRING prxResult);
+
+#define REXXSTART			RexxStart
+
+#endif /* INCL_RX* */
+
+/* ----------------------- PRESENTATION MANAGER --------------------------- */
+
+#define	 CTLS_WM_BIDI_FIRST		0x390
+#define	 CTLS_WM_BIDI_LAST		0x39f
+
+#if defined (INCL_NLS)
+#define WM_DBCSFIRST			0x00b0
+#define WM_DBCSLAST			0x00cf
+#endif /* INCL_NLS */
+
+#define WC_FRAME			((PSZ)0xffff0001)
+#define WC_COMBOBOX			((PSZ)0xffff0002)
+#define WC_BUTTON			((PSZ)0xffff0003)
+#define WC_MENU				((PSZ)0xffff0004)
+#define WC_STATIC			((PSZ)0xffff0005)
+#define WC_ENTRYFIELD			((PSZ)0xffff0006)
+#define WC_LISTBOX			((PSZ)0xffff0007)
+#define WC_SCROLLBAR			((PSZ)0xffff0008)
+#define WC_TITLEBAR			((PSZ)0xffff0009)
+#define WC_MLE				((PSZ)0xffff000a)
+#define WC_APPSTAT			((PSZ)0xffff0010)
+#define WC_KBDSTAT			((PSZ)0xffff0011)
+#define WC_PECIC			((PSZ)0xffff0012)
+#define WC_DBE_KKPOPUP			((PSZ)0xffff0013)
+#define WC_SPINBUTTON			((PSZ)0xffff0020)
+#define WC_CONTAINER			((PSZ)0xffff0025)
+#define WC_SLIDER			((PSZ)0xffff0026)
+#define WC_VALUESET			((PSZ)0xffff0027)
+#define WC_NOTEBOOK			((PSZ)0xffff0028)
+#define WC_PENFIRST			((PSZ)0xffff0029)
+#define WC_PENLAST			((PSZ)0xffff002c)
+#define WC_MMPMFIRST			((PSZ)0xffff0040)
+#define WC_CIRCULARSLIDER		((PSZ)0xffff0041)
+#define WC_MMPMLAST			((PSZ)0xffff004f)
+
+#define WS_VISIBLE			0x80000000
+#define WS_DISABLED			0x40000000
+#define WS_CLIPCHILDREN			0x20000000
+#define WS_CLIPSIBLINGS			0x10000000
+#define WS_PARENTCLIP			0x08000000
+#define WS_SAVEBITS			0x04000000
+#define WS_SYNCPAINT			0x02000000
+#define WS_MINIMIZED			0x01000000
+#define WS_MAXIMIZED			0x00800000
+#define WS_ANIMATE			0x00400000
+#define WS_GROUP			0x00010000
+#define WS_TABSTOP			0x00020000
+#define WS_MULTISELECT			0x00040000
+
+#define CS_MOVENOTIFY			0x00000001
+#define CS_SIZEREDRAW			0x00000004
+#define CS_HITTEST			0x00000008
+#define CS_PUBLIC			0x00000010
+#define CS_FRAME			0x00000020
+#define CS_CLIPCHILDREN			0x20000000
+#define CS_CLIPSIBLINGS			0x10000000
+#define CS_PARENTCLIP			0x08000000
+#define CS_SAVEBITS			0x04000000
+#define CS_SYNCPAINT			0x02000000
+
+#define MID_NONE			(-1)
+#define MID_ERROR			(-1)
+
+#define DB_PATCOPY			0x0000
+#define DB_PATINVERT			0x0001
+#define DB_DESTINVERT			0x0002
+#define DB_AREAMIXMODE			0x0003
+
+#define DB_ROP				0x0007
+#define DB_INTERIOR			0x0008
+#define DB_AREAATTRS			0x0010
+#define DB_STANDARD			0x0100
+#define DB_DLGBORDER			0x0200
+
+#define DBM_NORMAL			0x0000
+#define DBM_INVERT			0x0001
+#define DBM_HALFTONE			0x0002
+#define DBM_STRETCH			0x0004
+#define DBM_IMAGEATTRS			0x0008
+
+#define DT_LEFT				0x00000000
+#define DT_QUERYEXTENT			0x00000002
+#define DT_UNDERSCORE			0x00000010
+#define DT_STRIKEOUT			0x00000020
+#define DT_TEXTATTRS			0x00000040
+#define DT_EXTERNALLEADING		0x00000080
+#define DT_CENTER			0x00000100
+#define DT_RIGHT			0x00000200
+#define DT_TOP				0x00000000
+#define DT_VCENTER			0x00000400
+#define DT_BOTTOM			0x00000800
+#define DT_HALFTONE			0x00001000
+#define DT_MNEMONIC			0x00002000
+#define DT_WORDBREAK			0x00004000
+#define DT_ERASERECT			0x00008000
+
+#define QW_NEXT				0
+#define QW_PREV				1
+#define QW_TOP				2
+#define QW_BOTTOM			3
+#define QW_OWNER			4
+#define QW_PARENT			5
+#define QW_NEXTTOP			6
+#define QW_PREVTOP			7
+#define QW_FRAMEOWNER			8
+
+#define SWP_SIZE			0x0001
+#define SWP_MOVE			0x0002
+#define SWP_ZORDER			0x0004
+#define SWP_SHOW			0x0008
+#define SWP_HIDE			0x0010
+#define SWP_NOREDRAW			0x0020
+#define SWP_NOADJUST			0x0040
+#define SWP_ACTIVATE			0x0080
+#define SWP_DEACTIVATE			0x0100
+#define SWP_EXTSTATECHANGE		0x0200
+#define SWP_MINIMIZE			0x0400
+#define SWP_MAXIMIZE			0x0800
+#define SWP_RESTORE			0x1000
+#define SWP_FOCUSACTIVATE		0x2000
+#define SWP_FOCUSDEACTIVATE		0x4000
+#define SWP_NOAUTOCLOSE			0x8000
+
+#define AWP_MINIMIZED			0x00010000
+#define AWP_MAXIMIZED			0x00020000
+#define AWP_RESTORED			0x00040000
+#define AWP_ACTIVATE			0x00080000
+#define AWP_DEACTIVATE			0x00100000
+
+#define HWND_DESKTOP			((HWND)1)
+#define HWND_OBJECT			((HWND)2)
+#define HWND_TOP			((HWND)3)
+#define HWND_BOTTOM			((HWND)4)
+#define HWND_THREADCAPTURE		((HWND)5)
+
+#define EAF_DEFAULTOWNER		0x0001
+#define EAF_UNCHANGEABLE		0x0002
+#define EAF_REUSEICON			0x0004
+
+#define ICON_FILE			1
+#define ICON_RESOURCE			2
+#define ICON_DATA			3
+#define ICON_CLEAR			4
+
+#define SZDDEFMT_RTF			"Rich Text Format"
+#define SZDDEFMT_PTRPICT		"Printer_Picture"
+
+#define STR_DLLNAME			"keyremap"
+
+#if defined (INCL_WINERRORS)
+
+#define PMERR_INVALID_HWND		0x1001
+#define PMERR_INVALID_HMQ		0x1002
+#define PMERR_PARAMETER_OUT_OF_RANGE	0x1003
+#define PMERR_WINDOW_LOCK_UNDERFLOW	0x1004
+#define PMERR_WINDOW_LOCK_OVERFLOW	0x1005
+#define PMERR_BAD_WINDOW_LOCK_COUNT	0x1006
+#define PMERR_WINDOW_NOT_LOCKED		0x1007
+#define PMERR_INVALID_SELECTOR		0x1008
+#define PMERR_CALL_FROM_WRONG_THREAD	0x1009
+#define PMERR_RESOURCE_NOT_FOUND	0x100a
+#define PMERR_INVALID_STRING_PARM	0x100b
+#define PMERR_INVALID_HHEAP		0x100c
+#define PMERR_INVALID_HEAP_POINTER	0x100d
+#define PMERR_INVALID_HEAP_SIZE_PARM	0x100e
+#define PMERR_INVALID_HEAP_SIZE		0x100f
+#define PMERR_INVALID_HEAP_SIZE_WORD	0x1010
+#define PMERR_HEAP_OUT_OF_MEMORY	0x1011
+#define PMERR_HEAP_MAX_SIZE_REACHED	0x1012
+#define PMERR_INVALID_HATOMTBL		0x1013
+#define PMERR_INVALID_ATOM		0x1014
+#define PMERR_INVALID_ATOM_NAME		0x1015
+#define PMERR_INVALID_INTEGER_ATOM	0x1016
+#define PMERR_ATOM_NAME_NOT_FOUND	0x1017
+#define PMERR_QUEUE_TOO_LARGE		0x1018
+#define PMERR_INVALID_FLAG		0x1019
+#define PMERR_INVALID_HACCEL		0x101a
+#define PMERR_INVALID_HPTR		0x101b
+#define PMERR_INVALID_HENUM		0x101c
+#define PMERR_INVALID_SRC_CODEPAGE	0x101d
+#define PMERR_INVALID_DST_CODEPAGE	0x101e
+#define PMERR_UNKNOWN_COMPONENT_ID	0x101f
+#define PMERR_UNKNOWN_ERROR_CODE	0x1020
+#define PMERR_SEVERITY_LEVELS		0x1021
+#define PMERR_INVALID_RESOURCE_FORMAT	0x1034
+#define PMERR_NO_MSG_QUEUE		0x1036
+#define PMERR_CANNOT_SET_FOCUS		0x1037
+#define PMERR_QUEUE_FULL		0x1038
+#define PMERR_LIBRARY_LOAD_FAILED	0x1039
+#define PMERR_PROCEDURE_LOAD_FAILED	0x103a
+#define PMERR_LIBRARY_DELETE_FAILED	0x103b
+#define PMERR_PROCEDURE_DELETE_FAILED	0x103c
+#define PMERR_ARRAY_TOO_LARGE		0x103d
+#define PMERR_ARRAY_TOO_SMALL		0x103e
+#define PMERR_DATATYPE_ENTRY_BAD_INDEX	0x103f
+#define PMERR_DATATYPE_ENTRY_CTL_BAD	0x1040
+#define PMERR_DATATYPE_ENTRY_CTL_MISS	0x1041
+#define PMERR_DATATYPE_ENTRY_INVALID	0x1042
+#define PMERR_DATATYPE_ENTRY_NOT_NUM	0x1043
+#define PMERR_DATATYPE_ENTRY_NOT_OFF	0x1044
+#define PMERR_DATATYPE_INVALID		0x1045
+#define PMERR_DATATYPE_NOT_UNIQUE	0x1046
+#define PMERR_DATATYPE_TOO_LONG		0x1047
+#define PMERR_DATATYPE_TOO_SMALL	0x1048
+#define PMERR_DIRECTION_INVALID		0x1049
+#define PMERR_INVALID_HAB		0x104a
+#define PMERR_INVALID_HSTRUCT		0x104d
+#define PMERR_LENGTH_TOO_SMALL		0x104e
+#define PMERR_MSGID_TOO_SMALL		0x104f
+#define PMERR_NO_HANDLE_ALLOC		0x1050
+#define PMERR_NOT_IN_A_PM_SESSION	0x1051
+#define PMERR_MSG_QUEUE_ALREADY_EXISTS	0x1052
+#define PMERR_SEND_MSG_TIMEOUT		0x1053
+#define PMERROR_SEND_MSG_FAILED		0x1054
+#define PMERR_OLD_RESOURCE		0x1055
+#define PMERR_WPDSERVER_IS_ACTIVE	0x1056
+#define PMERR_WPDSERVER_NOT_STARTED	0x1057
+#define PMERR_SOMDD_IS_ACTIVE		0x1058
+#define PMERR_SOMDD_NOT_STARTED		0x1059
+
+#define PMERR_BIDI_FIRST		0x10f0
+#define PMERR_BIDI_LAST			0x10ff
+
+#endif /* INCL_WINERRORS */
+
+#if defined (INCL_SHLERRORS)
+
+#define PMERR_INVALID_PIB		0x1101
+#define PMERR_INSUFF_SPACE_TO_ADD	0x1102
+#define PMERR_INVALID_GROUP_HANDLE	0x1103
+#define PMERR_DUPLICATE_TITLE		0x1104
+#define PMERR_INVALID_TITLE		0x1105
+#define PMERR_HANDLE_NOT_IN_GROUP	0x1107
+#define PMERR_INVALID_TARGET_HANDLE	0x1106
+#define PMERR_INVALID_PATH_STATEMENT	0x1108
+#define PMERR_NO_PROGRAM_FOUND		0x1109
+#define PMERR_INVALID_BUFFER_SIZE	0x110a
+#define PMERR_BUFFER_TOO_SMALL		0x110b
+#define PMERR_PL_INITIALISATION_FAIL	0x110c
+#define PMERR_CANT_DESTROY_SYS_GROUP	0x110d
+#define PMERR_INVALID_TYPE_CHANGE	0x110e
+#define PMERR_INVALID_PROGRAM_HANDLE	0x110f
+#define PMERR_NOT_CURRENT_PL_VERSION	0x1110
+#define PMERR_INVALID_CIRCULAR_REF	0x1111
+#define PMERR_MEMORY_ALLOCATION_ERR	0x1112
+#define PMERR_MEMORY_DEALLOCATION_ERR	0x1113
+#define PMERR_TASK_HEADER_TOO_BIG	0x1114
+#define PMERR_INVALID_INI_FILE_HANDLE	0x1115
+#define PMERR_MEMORY_SHARE		0x1116
+#define PMERR_OPEN_QUEUE		0x1117
+#define PMERR_CREATE_QUEUE		0x1118
+#define PMERR_WRITE_QUEUE		0x1119
+#define PMERR_READ_QUEUE		0x111a
+#define PMERR_CALL_NOT_EXECUTED		0x111b
+#define PMERR_UNKNOWN_APIPKT		0x111c
+#define PMERR_INITHREAD_EXISTS		0x111d
+#define PMERR_CREATE_THREAD		0x111e
+#define PMERR_NO_HK_PROFILE_INSTALLED	0x111f
+#define PMERR_INVALID_DIRECTORY		0x1120
+#define PMERR_WILDCARD_IN_FILENAME	0x1121
+#define PMERR_FILENAME_BUFFER_FULL	0x1122
+#define PMERR_FILENAME_TOO_LONG		0x1123
+#define PMERR_INI_FILE_IS_SYS_OR_USER	0x1124
+#define PMERR_BROADCAST_PLMSG		0x1125
+#define PMERR_190_INIT_DONE		0x1126
+#define PMERR_HMOD_FOR_PMSHAPI		0x1127
+#define PMERR_SET_HK_PROFILE		0x1128
+#define PMERR_API_NOT_ALLOWED		0x1129
+#define PMERR_INI_STILL_OPEN		0x112a
+#define PMERR_PROGDETAILS_NOT_IN_INI	0x112b
+#define PMERR_PIBSTRUCT_NOT_IN_INI	0x112c
+#define PMERR_INVALID_DISKPROGDETAILS	0x112d
+#define PMERR_PROGDETAILS_READ_FAILURE	0x112e
+#define PMERR_PROGDETAILS_WRITE_FAILURE 0x112f
+#define PMERR_PROGDETAILS_QSIZE_FAILURE 0x1130
+#define PMERR_INVALID_PROGDETAILS	0x1131
+#define PMERR_SHEPROFILEHOOK_NOT_FOUND	0x1132
+#define PMERR_190PLCONVERTED		0x1133
+#define PMERR_FAILED_TO_CONVERT_INI_PL	0x1134
+#define PMERR_PMSHAPI_NOT_INITIALISED	0x1135
+#define PMERR_INVALID_SHELL_API_HOOK_ID 0x1136
+#define PMERR_DOS_ERROR			0x1200
+#define PMERR_NO_SPACE			0x1201
+#define PMERR_INVALID_SWITCH_HANDLE	0x1202
+#define PMERR_NO_HANDLE			0x1203
+#define PMERR_INVALID_PROCESS_ID	0x1204
+#define PMERR_NOT_SHELL			0x1205
+#define PMERR_INVALID_WINDOW		0x1206
+#define PMERR_INVALID_POST_MSG		0x1207
+#define PMERR_INVALID_PARAMETERS	0x1208
+#define PMERR_INVALID_PROGRAM_TYPE	0x1209
+#define PMERR_NOT_EXTENDED_FOCUS	0x120a
+#define PMERR_INVALID_SESSION_ID	0x120b
+#define PMERR_SMG_INVALID_ICON_FILE	0x120c
+#define PMERR_SMG_ICON_NOT_CREATED	0x120d
+#define PMERR_SHL_DEBUG			0x120e
+#define PMERR_OPENING_INI_FILE		0x1301
+#define PMERR_INI_FILE_CORRUPT		0x1302
+#define PMERR_INVALID_PARM		0x1303
+#define PMERR_NOT_IN_IDX		0x1304
+#define PMERR_NO_ENTRIES_IN_GROUP	0x1305
+#define PMERR_INI_WRITE_FAIL		0x1306
+#define PMERR_IDX_FULL			0x1307
+#define PMERR_INI_PROTECTED		0x1308
+#define PMERR_MEMORY_ALLOC		0x1309
+#define PMERR_INI_INIT_ALREADY_DONE	0x130a
+#define PMERR_INVALID_INTEGER		0x130b
+#define PMERR_INVALID_ASCIIZ		0x130c
+#define PMERR_CAN_NOT_CALL_SPOOLER	0x130d
+#define PMERR_VALIDATION_REJECTED	0x130d /*!*/
+#define PMERR_WARNING_WINDOW_NOT_KILLED 0x1401
+#define PMERR_ERROR_INVALID_WINDOW	0x1402
+#define PMERR_ALREADY_INITIALIZED	0x1403
+#define PMERR_MSG_PROG_NO_MOU		0x1405
+#define PMERR_MSG_PROG_NON_RECOV	0x1406
+#define PMERR_WINCONV_INVALID_PATH	0x1407
+#define PMERR_PI_NOT_INITIALISED	0x1408
+#define PMERR_PL_NOT_INITIALISED	0x1409
+#define PMERR_NO_TASK_MANAGER		0x140a
+#define PMERR_SAVE_NOT_IN_PROGRESS	0x140b
+#define PMERR_NO_STACK_SPACE		0x140c
+#define PMERR_INVALID_COLR_FIELD	0x140d
+#define PMERR_INVALID_COLR_VALUE	0x140e
+#define PMERR_COLR_WRITE		0x140f
+#define PMERR_TARGET_FILE_EXISTS	0x1501
+#define PMERR_SOURCE_SAME_AS_TARGET	0x1502
+#define PMERR_SOURCE_FILE_NOT_FOUND	0x1503
+#define PMERR_INVALID_NEW_PATH		0x1504
+#define PMERR_TARGET_FILE_NOT_FOUND	0x1505
+#define PMERR_INVALID_DRIVE_NUMBER	0x1506
+#define PMERR_NAME_TOO_LONG		0x1507
+#define PMERR_NOT_ENOUGH_ROOM_ON_DISK	0x1508
+#define PMERR_NOT_ENOUGH_MEM		0x1509
+#define PMERR_LOG_DRV_DOES_NOT_EXIST	0x150b
+#define PMERR_INVALID_DRIVE		0x150c
+#define PMERR_ACCESS_DENIED		0x150d
+#define PMERR_NO_FIRST_SLASH		0x150e
+#define PMERR_READ_ONLY_FILE		0x150f
+#define PMERR_GROUP_PROTECTED		0x151f
+#define PMERR_INVALID_PROGRAM_CATEGORY	0x152f
+#define PMERR_INVALID_APPL		0x1530
+#define PMERR_CANNOT_START		0x1531
+#define PMERR_STARTED_IN_BACKGROUND	0x1532
+#define PMERR_INVALID_HAPP		0x1533
+#define PMERR_CANNOT_STOP		0x1534
+#define PMERR_INVALID_FREE_MESSAGE_ID	0x1630
+#define PMERR_FUNCTION_NOT_SUPPORTED	0x1641
+#define PMERR_INVALID_ARRAY_COUNT	0x1642
+#define PMERR_INVALID_LENGTH		0x1643
+#define PMERR_INVALID_BUNDLE_TYPE	0x1644
+#define PMERR_INVALID_PARAMETER		0x1645
+#define PMERR_INVALID_NUMBER_OF_PARMS	0x1646
+#define PMERR_GREATER_THAN_64K		0x1647
+#define PMERR_INVALID_PARAMETER_TYPE	0x1648
+#define PMERR_NEGATIVE_STRCOND_DIM	0x1649
+#define PMERR_INVALID_NUMBER_OF_TYPES	0x164a
+#define PMERR_INCORRECT_HSTRUCT		0x164b
+#define PMERR_INVALID_ARRAY_SIZE	0x164c
+#define PMERR_INVALID_CONTROL_DATATYPE	0x164d
+#define PMERR_INCOMPLETE_CONTROL_SEQU	0x164e
+#define PMERR_INVALID_DATATYPE		0x164f
+#define PMERR_INCORRECT_DATATYPE	0x1650
+#define PMERR_NOT_SELF_DESCRIBING_DTYP	0x1651
+#define PMERR_INVALID_CTRL_SEQ_INDEX	0x1652
+#define PMERR_INVALID_TYPE_FOR_LENGTH	0x1653
+#define PMERR_INVALID_TYPE_FOR_OFFSET	0x1654
+#define PMERR_INVALID_TYPE_FOR_MPARAM	0x1655
+#define PMERR_INVALID_MESSAGE_ID	0x1656
+#define PMERR_C_LENGTH_TOO_SMALL	0x1657
+#define PMERR_APPL_STRUCTURE_TOO_SMALL	0x1658
+#define PMERR_INVALID_ERRORINFO_HANDLE	0x1659
+#define PMERR_INVALID_CHARACTER_INDEX	0x165a
+
+#endif /* INCL_SHLERRORS */
+
+#if defined (INCL_GPIERRORS)
+
+#define PMERR_OK			0x0000
+#define PMERR_ALREADY_IN_AREA		0x2001
+#define PMERR_ALREADY_IN_ELEMENT	0x2002
+#define PMERR_ALREADY_IN_PATH		0x2003
+#define PMERR_ALREADY_IN_SEG		0x2004
+#define PMERR_AREA_INCOMPLETE		0x2005
+#define PMERR_BASE_ERROR		0x2006
+#define PMERR_BITBLT_LENGTH_EXCEEDED	0x2007
+#define PMERR_BITMAP_IN_USE		0x2008
+#define PMERR_BITMAP_IS_SELECTED	0x2009
+#define PMERR_BITMAP_NOT_FOUND		0x200a
+#define PMERR_BITMAP_NOT_SELECTED	0x200b
+#define PMERR_BOUNDS_OVERFLOW		0x200c
+#define PMERR_CALLED_SEG_IS_CHAINED	0x200d
+#define PMERR_CALLED_SEG_IS_CURRENT	0x200e
+#define PMERR_CALLED_SEG_NOT_FOUND	0x200f
+#define PMERR_CANNOT_DELETE_ALL_DATA	0x2010
+#define PMERR_CANNOT_REPLACE_ELEMENT_0	0x2011
+#define PMERR_COL_TABLE_NOT_REALIZABLE	0x2012
+#define PMERR_COL_TABLE_NOT_REALIZED	0x2013
+#define PMERR_COORDINATE_OVERFLOW	0x2014
+#define PMERR_CORR_FORMAT_MISMATCH	0x2015
+#define PMERR_DATA_TOO_LONG		0x2016
+#define PMERR_DC_IS_ASSOCIATED		0x2017
+#define PMERR_DESC_STRING_TRUNCATED	0x2018
+#define PMERR_DEVICE_DRIVER_ERROR_1	0x2019
+#define PMERR_DEVICE_DRIVER_ERROR_2	0x201a
+#define PMERR_DEVICE_DRIVER_ERROR_3	0x201b
+#define PMERR_DEVICE_DRIVER_ERROR_4	0x201c
+#define PMERR_DEVICE_DRIVER_ERROR_5	0x201d
+#define PMERR_DEVICE_DRIVER_ERROR_6	0x201e
+#define PMERR_DEVICE_DRIVER_ERROR_7	0x201f
+#define PMERR_DEVICE_DRIVER_ERROR_8	0x2020
+#define PMERR_DEVICE_DRIVER_ERROR_9	0x2021
+#define PMERR_DEVICE_DRIVER_ERROR_10	0x2022
+#define PMERR_DEV_FUNC_NOT_INSTALLED	0x2023
+#define PMERR_DOSOPEN_FAILURE		0x2024
+#define PMERR_DOSREAD_FAILURE		0x2025
+#define PMERR_DRIVER_NOT_FOUND		0x2026
+#define PMERR_DUP_SEG			0x2027
+#define PMERR_DYNAMIC_SEG_SEQ_ERROR	0x2028
+#define PMERR_DYNAMIC_SEG_ZERO_INV	0x2029
+#define PMERR_ELEMENT_INCOMPLETE	0x202a
+#define PMERR_ESC_CODE_NOT_SUPPORTED	0x202b
+#define PMERR_EXCEEDS_MAX_SEG_LENGTH	0x202c
+#define PMERR_FONT_AND_MODE_MISMATCH	0x202d
+#define PMERR_FONT_FILE_NOT_LOADED	0x202e
+#define PMERR_FONT_NOT_LOADED		0x202f
+#define PMERR_FONT_TOO_BIG		0x2030
+#define PMERR_HARDWARE_INIT_FAILURE	0x2031
+#define PMERR_HBITMAP_BUSY		0x2032
+#define PMERR_HDC_BUSY			0x2033
+#define PMERR_HRGN_BUSY			0x2034
+#define PMERR_HUGE_FONTS_NOT_SUPPORTED	0x2035
+#define PMERR_ID_HAS_NO_BITMAP		0x2036
+#define PMERR_IMAGE_INCOMPLETE		0x2037
+#define PMERR_INCOMPAT_COLOR_FORMAT	0x2038
+#define PMERR_INCOMPAT_COLOR_OPTIONS	0x2039
+#define PMERR_INCOMPATIBLE_BITMAP	0x203a
+#define PMERR_INCOMPATIBLE_METAFILE	0x203b
+#define PMERR_INCORRECT_DC_TYPE		0x203c
+#define PMERR_INSUFFICIENT_DISK_SPACE	0x203d
+#define PMERR_INSUFFICIENT_MEMORY	0x203e
+#define PMERR_INV_ANGLE_PARM		0x203f
+#define PMERR_INV_ARC_CONTROL		0x2040
+#define PMERR_INV_AREA_CONTROL		0x2041
+#define PMERR_INV_ARC_POINTS		0x2042
+#define PMERR_INV_ATTR_MODE		0x2043
+#define PMERR_INV_BACKGROUND_COL_ATTR	0x2044
+#define PMERR_INV_BACKGROUND_MIX_ATTR	0x2045
+#define PMERR_INV_BITBLT_MIX		0x2046
+#define PMERR_INV_BITBLT_STYLE		0x2047
+#define PMERR_INV_BITMAP_DIMENSION	0x2048
+#define PMERR_INV_BOX_CONTROL		0x2049
+#define PMERR_INV_BOX_ROUNDING_PARM	0x204a
+#define PMERR_INV_CHAR_ANGLE_ATTR	0x204b
+#define PMERR_INV_CHAR_DIRECTION_ATTR	0x204c
+#define PMERR_INV_CHAR_MODE_ATTR	0x204d
+#define PMERR_INV_CHAR_POS_OPTIONS	0x204e
+#define PMERR_INV_CHAR_SET_ATTR		0x204f
+#define PMERR_INV_CHAR_SHEAR_ATTR	0x2050
+#define PMERR_INV_CLIP_PATH_OPTIONS	0x2051
+#define PMERR_INV_CODEPAGE		0x2052
+#define PMERR_INV_COLOR_ATTR		0x2053
+#define PMERR_INV_COLOR_DATA		0x2054
+#define PMERR_INV_COLOR_FORMAT		0x2055
+#define PMERR_INV_COLOR_INDEX		0x2056
+#define PMERR_INV_COLOR_OPTIONS		0x2057
+#define PMERR_INV_COLOR_START_INDEX	0x2058
+#define PMERR_INV_COORD_OFFSET		0x2059
+#define PMERR_INV_COORD_SPACE		0x205a
+#define PMERR_INV_COORDINATE		0x205b
+#define PMERR_INV_CORRELATE_DEPTH	0x205c
+#define PMERR_INV_CORRELATE_TYPE	0x205d
+#define PMERR_INV_CURSOR_BITMAP		0x205e
+#define PMERR_INV_DC_DATA		0x205f
+#define PMERR_INV_DC_TYPE		0x2060
+#define PMERR_INV_DEVICE_NAME		0x2061
+#define PMERR_INV_DEV_MODES_OPTIONS	0x2062
+#define PMERR_INV_DRAW_CONTROL		0x2063
+#define PMERR_INV_DRAW_VALUE		0x2064
+#define PMERR_INV_DRAWING_MODE		0x2065
+#define PMERR_INV_DRIVER_DATA		0x2066
+#define PMERR_INV_DRIVER_NAME		0x2067
+#define PMERR_INV_DRAW_BORDER_OPTION	0x2068
+#define PMERR_INV_EDIT_MODE		0x2069
+#define PMERR_INV_ELEMENT_OFFSET	0x206a
+#define PMERR_INV_ELEMENT_POINTER	0x206b
+#define PMERR_INV_END_PATH_OPTIONS	0x206c
+#define PMERR_INV_ESC_CODE		0x206d
+#define PMERR_INV_ESCAPE_DATA		0x206e
+#define PMERR_INV_EXTENDED_LCID		0x206f
+#define PMERR_INV_FILL_PATH_OPTIONS	0x2070
+#define PMERR_INV_FIRST_CHAR		0x2071
+#define PMERR_INV_FONT_ATTRS		0x2072
+#define PMERR_INV_FONT_FILE_DATA	0x2073
+#define PMERR_INV_FOR_THIS_DC_TYPE	0x2074
+#define PMERR_INV_FORMAT_CONTROL	0x2075
+#define PMERR_INV_FORMS_CODE		0x2076
+#define PMERR_INV_FONTDEF		0x2077
+#define PMERR_INV_GEOM_LINE_WIDTH_ATTR	0x2078
+#define PMERR_INV_GETDATA_CONTROL	0x2079
+#define PMERR_INV_GRAPHICS_FIELD	0x207a
+#define PMERR_INV_HBITMAP		0x207b
+#define PMERR_INV_HDC			0x207c
+#define PMERR_INV_HJOURNAL		0x207d
+#define PMERR_INV_HMF			0x207e
+#define PMERR_INV_HPS			0x207f
+#define PMERR_INV_HRGN			0x2080
+#define PMERR_INV_ID			0x2081
+#define PMERR_INV_IMAGE_DATA_LENGTH	0x2082
+#define PMERR_INV_IMAGE_DIMENSION	0x2083
+#define PMERR_INV_IMAGE_FORMAT		0x2084
+#define PMERR_INV_IN_AREA		0x2085
+#define PMERR_INV_IN_CALLED_SEG		0x2086
+#define PMERR_INV_IN_CURRENT_EDIT_MODE	0x2087
+#define PMERR_INV_IN_DRAW_MODE		0x2088
+#define PMERR_INV_IN_ELEMENT		0x2089
+#define PMERR_INV_IN_IMAGE		0x208a
+#define PMERR_INV_IN_PATH		0x208b
+#define PMERR_INV_IN_RETAIN_MODE	0x208c
+#define PMERR_INV_IN_SEG		0x208d
+#define PMERR_INV_IN_VECTOR_SYMBOL	0x208e
+#define PMERR_INV_INFO_TABLE		0x208f
+#define PMERR_INV_JOURNAL_OPTION	0x2090
+#define PMERR_INV_KERNING_FLAGS		0x2091
+#define PMERR_INV_LENGTH_OR_COUNT	0x2092
+#define PMERR_INV_LINE_END_ATTR		0x2093
+#define PMERR_INV_LINE_JOIN_ATTR	0x2094
+#define PMERR_INV_LINE_TYPE_ATTR	0x2095
+#define PMERR_INV_LINE_WIDTH_ATTR	0x2096
+#define PMERR_INV_LOGICAL_ADDRESS	0x2097
+#define PMERR_INV_MARKER_BOX_ATTR	0x2098
+#define PMERR_INV_MARKER_SET_ATTR	0x2099
+#define PMERR_INV_MARKER_SYMBOL_ATTR	0x209a
+#define PMERR_INV_MATRIX_ELEMENT	0x209b
+#define PMERR_INV_MAX_HITS		0x209c
+#define PMERR_INV_METAFILE		0x209d
+#define PMERR_INV_METAFILE_LENGTH	0x209e
+#define PMERR_INV_METAFILE_OFFSET	0x209f
+#define PMERR_INV_MICROPS_DRAW_CONTROL	0x20a0
+#define PMERR_INV_MICROPS_FUNCTION	0x20a1
+#define PMERR_INV_MICROPS_ORDER		0x20a2
+#define PMERR_INV_MIX_ATTR		0x20a3
+#define PMERR_INV_MODE_FOR_OPEN_DYN	0x20a4
+#define PMERR_INV_MODE_FOR_REOPEN_SEG	0x20a5
+#define PMERR_INV_MODIFY_PATH_MODE	0x20a6
+#define PMERR_INV_MULTIPLIER		0x20a7
+#define PMERR_INV_NESTED_FIGURES	0x20a8
+#define PMERR_INV_OR_INCOMPAT_OPTIONS	0x20a9
+#define PMERR_INV_ORDER_LENGTH		0x20aa
+#define PMERR_INV_ORDERING_PARM		0x20ab
+#define PMERR_INV_OUTSIDE_DRAW_MODE	0x20ac
+#define PMERR_INV_PAGE_VIEWPORT		0x20ad
+#define PMERR_INV_PATH_ID		0x20ae
+#define PMERR_INV_PATH_MODE		0x20af
+#define PMERR_INV_PATTERN_ATTR		0x20b0
+#define PMERR_INV_PATTERN_REF_PT_ATTR	0x20b1
+#define PMERR_INV_PATTERN_SET_ATTR	0x20b2
+#define PMERR_INV_PATTERN_SET_FONT	0x20b3
+#define PMERR_INV_PICK_APERTURE_OPTION	0x20b4
+#define PMERR_INV_PICK_APERTURE_POSN	0x20b5
+#define PMERR_INV_PICK_APERTURE_SIZE	0x20b6
+#define PMERR_INV_PICK_NUMBER		0x20b7
+#define PMERR_INV_PLAY_METAFILE_OPTION	0x20b8
+#define PMERR_INV_PRIMITIVE_TYPE	0x20b9
+#define PMERR_INV_PS_SIZE		0x20ba
+#define PMERR_INV_PUTDATA_FORMAT	0x20bb
+#define PMERR_INV_QUERY_ELEMENT_NO	0x20bc
+#define PMERR_INV_RECT			0x20bd
+#define PMERR_INV_REGION_CONTROL	0x20be
+#define PMERR_INV_REGION_MIX_MODE	0x20bf
+#define PMERR_INV_REPLACE_MODE_FUNC	0x20c0
+#define PMERR_INV_RESERVED_FIELD	0x20c1
+#define PMERR_INV_RESET_OPTIONS		0x20c2
+#define PMERR_INV_RGBCOLOR		0x20c3
+#define PMERR_INV_SCAN_START		0x20c4
+#define PMERR_INV_SEG_ATTR		0x20c5
+#define PMERR_INV_SEG_ATTR_VALUE	0x20c6
+#define PMERR_INV_SEG_CH_LENGTH		0x20c7
+#define PMERR_INV_SEG_NAME		0x20c8
+#define PMERR_INV_SEG_OFFSET		0x20c9
+#define PMERR_INV_SETID			0x20ca
+#define PMERR_INV_SETID_TYPE		0x20cb
+#define PMERR_INV_SET_VIEWPORT_OPTION	0x20cc
+#define PMERR_INV_SHARPNESS_PARM	0x20cd
+#define PMERR_INV_SOURCE_OFFSET		0x20ce
+#define PMERR_INV_STOP_DRAW_VALUE	0x20cf
+#define PMERR_INV_TRANSFORM_TYPE	0x20d0
+#define PMERR_INV_USAGE_PARM		0x20d1
+#define PMERR_INV_VIEWING_LIMITS	0x20d2
+#define PMERR_JFILE_BUSY		0x20d3
+#define PMERR_JNL_FUNC_DATA_TOO_LONG	0x20d4
+#define PMERR_KERNING_NOT_SUPPORTED	0x20d5
+#define PMERR_LABEL_NOT_FOUND		0x20d6
+#define PMERR_MATRIX_OVERFLOW		0x20d7
+#define PMERR_METAFILE_INTERNAL_ERROR	0x20d8
+#define PMERR_METAFILE_IN_USE		0x20d9
+#define PMERR_METAFILE_LIMIT_EXCEEDED	0x20da
+#define PMERR_NAME_STACK_FULL		0x20db
+#define PMERR_NOT_CREATED_BY_DEVOPENDC	0x20dc
+#define PMERR_NOT_IN_AREA		0x20dd
+#define PMERR_NOT_IN_DRAW_MODE		0x20de
+#define PMERR_NOT_IN_ELEMENT		0x20df
+#define PMERR_NOT_IN_IMAGE		0x20e0
+#define PMERR_NOT_IN_PATH		0x20e1
+#define PMERR_NOT_IN_RETAIN_MODE	0x20e2
+#define PMERR_NOT_IN_SEG		0x20e3
+#define PMERR_NO_BITMAP_SELECTED	0x20e4
+#define PMERR_NO_CURRENT_ELEMENT	0x20e5
+#define PMERR_NO_CURRENT_SEG		0x20e6
+#define PMERR_NO_METAFILE_RECORD_HANDLE 0x20e7
+#define PMERR_ORDER_TOO_BIG		0x20e8
+#define PMERR_OTHER_SET_ID_REFS		0x20e9
+#define PMERR_OVERRAN_SEG		0x20ea
+#define PMERR_OWN_SET_ID_REFS		0x20eb
+#define PMERR_PATH_INCOMPLETE		0x20ec
+#define PMERR_PATH_LIMIT_EXCEEDED	0x20ed
+#define PMERR_PATH_UNKNOWN		0x20ee
+#define PMERR_PEL_IS_CLIPPED		0x20ef
+#define PMERR_PEL_NOT_AVAILABLE		0x20f0
+#define PMERR_PRIMITIVE_STACK_EMPTY	0x20f1
+#define PMERR_PROLOG_ERROR		0x20f2
+#define PMERR_PROLOG_SEG_ATTR_NOT_SET	0x20f3
+#define PMERR_PS_BUSY			0x20f4
+#define PMERR_PS_IS_ASSOCIATED		0x20f5
+#define PMERR_RAM_JNL_FILE_TOO_SMALL	0x20f6
+#define PMERR_REALIZE_NOT_SUPPORTED	0x20f7
+#define PMERR_REGION_IS_CLIP_REGION	0x20f8
+#define PMERR_RESOURCE_DEPLETION	0x20f9
+#define PMERR_SEG_AND_REFSEG_ARE_SAME	0x20fa
+#define PMERR_SEG_CALL_RECURSIVE	0x20fb
+#define PMERR_SEG_CALL_STACK_EMPTY	0x20fc
+#define PMERR_SEG_CALL_STACK_FULL	0x20fd
+#define PMERR_SEG_IS_CURRENT		0x20fe
+#define PMERR_SEG_NOT_CHAINED		0x20ff
+#define PMERR_SEG_NOT_FOUND		0x2100
+#define PMERR_SEG_STORE_LIMIT_EXCEEDED	0x2101
+#define PMERR_SETID_IN_USE		0x2102
+#define PMERR_SETID_NOT_FOUND		0x2103
+#define PMERR_STARTDOC_NOT_ISSUED	0x2104
+#define PMERR_STOP_DRAW_OCCURRED	0x2105
+#define PMERR_TOO_MANY_METAFILES_IN_USE 0x2106
+#define PMERR_TRUNCATED_ORDER		0x2107
+#define PMERR_UNCHAINED_SEG_ZERO_INV	0x2108
+#define PMERR_UNSUPPORTED_ATTR		0x2109
+#define PMERR_UNSUPPORTED_ATTR_VALUE	0x210a
+#define PMERR_ENDDOC_NOT_ISSUED		0x210b
+#define PMERR_PS_NOT_ASSOCIATED		0x210c
+#define PMERR_INV_FLOOD_FILL_OPTIONS	0x210d
+#define PMERR_INV_FACENAME		0x210e
+#define PMERR_PALETTE_SELECTED		0x210f
+#define PMERR_NO_PALETTE_SELECTED	0x2110
+#define PMERR_INV_HPAL			0x2111
+#define PMERR_PALETTE_BUSY		0x2112
+#define PMERR_START_POINT_CLIPPED	0x2113
+#define PMERR_NO_FILL			0x2114
+#define PMERR_INV_FACENAMEDESC		0x2115
+#define PMERR_INV_BITMAP_DATA		0x2116
+#define PMERR_INV_CHAR_ALIGN_ATTR	0x2117
+#define PMERR_INV_HFONT			0x2118
+#define PMERR_HFONT_IS_SELECTED		0x2119
+#define PMERR_DRVR_NOT_SUPPORTED	0x2120
+#define PMERR_INV_INKPS_FUNCTION	0x2121
+
+#endif /* INCL_GPIERRORS */
+
+#if defined (INCL_WPERRORS)
+
+#define WPERR_PROTECTED_CLASS		0x1700
+#define WPERR_INVALID_CLASS		0x1701
+#define WPERR_INVALID_SUPERCLASS	0x1702
+#define WPERR_NO_MEMORY			0x1703
+#define WPERR_SEMAPHORE_ERROR		0x1704
+#define WPERR_BUFFER_TOO_SMALL		0x1705
+#define WPERR_CLSLOADMOD_FAILED		0x1706
+#define WPERR_CLSPROCADDR_FAILED	0x1707
+#define WPERR_OBJWORD_LOCATION		0x1708
+#define WPERR_INVALID_OBJECT		0x1709
+#define WPERR_MEMORY_CLEANUP		0x170a
+#define WPERR_INVALID_MODULE		0x170b
+#define WPERR_INVALID_OLDCLASS		0x170c
+#define WPERR_INVALID_NEWCLASS		0x170d
+#define WPERR_NOT_IMMEDIATE_CHILD	0x170e
+#define WPERR_NOT_WORKPLACE_CLASS	0x170f
+#define WPERR_CANT_REPLACE_METACLS	0x1710
+#define WPERR_INI_FILE_WRITE		0x1711
+#define WPERR_INVALID_FOLDER		0x1712
+#define WPERR_BUFFER_OVERFLOW		0x1713
+#define WPERR_OBJECT_NOT_FOUND		0x1714
+#define WPERR_INVALID_HFIND		0x1715
+#define WPERR_INVALID_COUNT		0x1716
+#define WPERR_INVALID_BUFFER		0x1717
+#define WPERR_ALREADY_EXISTS		0x1718
+#define WPERR_INVALID_FLAGS		0x1719
+#define WPERR_INVALID_OBJECTID		0x1720
+#define WPERR_INVALID_TARGET_OBJECT	0x1721
+
+#endif /* INCL_WPERRORS */
+
+#if defined (INCL_SPLERRORS)
+
+#define PMERR_SPL_DRIVER_ERROR		0x4001
+#define PMERR_SPL_DEVICE_ERROR		0x4002
+#define PMERR_SPL_DEVICE_NOT_INSTALLED	0x4003
+#define PMERR_SPL_QUEUE_ERROR		0x4004
+#define PMERR_SPL_INV_HSPL		0x4005
+#define PMERR_SPL_NO_DISK_SPACE		0x4006
+#define PMERR_SPL_NO_MEMORY		0x4007
+#define PMERR_SPL_PRINT_ABORT		0x4008
+#define PMERR_SPL_SPOOLER_NOT_INSTALLED 0x4009
+#define PMERR_SPL_INV_FORMS_CODE	0x400a
+#define PMERR_SPL_INV_PRIORITY		0x400b
+#define PMERR_SPL_NO_FREE_JOB_ID	0x400c
+#define PMERR_SPL_NO_DATA		0x400d
+#define PMERR_SPL_INV_TOKEN		0x400e
+#define PMERR_SPL_INV_DATATYPE		0x400f
+#define PMERR_SPL_PROCESSOR_ERROR	0x4010
+#define PMERR_SPL_INV_JOB_ID		0x4011
+#define PMERR_SPL_JOB_NOT_PRINTING	0x4012
+#define PMERR_SPL_JOB_PRINTING		0x4013
+#define PMERR_SPL_QUEUE_ALREADY_EXISTS	0x4014
+#define PMERR_SPL_INV_QUEUE_NAME	0x4015
+#define PMERR_SPL_QUEUE_NOT_EMPTY	0x4016
+#define PMERR_SPL_DEVICE_ALREADY_EXISTS 0x4017
+#define PMERR_SPL_DEVICE_LIMIT_REACHED	0x4018
+#define PMERR_SPL_STATUS_STRING_TRUNC	0x4019
+#define PMERR_SPL_INV_LENGTH_OR_COUNT	0x401a
+#define PMERR_SPL_FILE_NOT_FOUND	0x401b
+#define PMERR_SPL_CANNOT_OPEN_FILE	0x401c
+#define PMERR_SPL_DRIVER_NOT_INSTALLED	0x401d
+#define PMERR_SPL_INV_PROCESSOR_DATTYPE 0x401e
+#define PMERR_SPL_INV_DRIVER_DATATYPE	0x401f
+#define PMERR_SPL_PROCESSOR_NOT_INST	0x4020
+#define PMERR_SPL_NO_SUCH_LOG_ADDRESS	0x4021
+#define PMERR_SPL_PRINTER_NOT_FOUND	0x4022
+#define PMERR_SPL_DD_NOT_FOUND		0x4023
+#define PMERR_SPL_QUEUE_NOT_FOUND	0x4024
+#define PMERR_SPL_MANY_QUEUES_ASSOC	0x4025
+#define PMERR_SPL_NO_QUEUES_ASSOCIATED	0x4026
+#define PMERR_SPL_INI_FILE_ERROR	0x4027
+#define PMERR_SPL_NO_DEFAULT_QUEUE	0x4028
+#define PMERR_SPL_NO_CURRENT_FORMS_CODE 0x4029
+#define PMERR_SPL_NOT_AUTHORISED	0x402a
+#define PMERR_SPL_TEMP_NETWORK_ERROR	0x402b
+#define PMERR_SPL_HARD_NETWORK_ERROR	0x402c
+#define PMERR_DEL_NOT_ALLOWED		0x402d
+#define PMERR_CANNOT_DEL_QP_REF		0x402e
+#define PMERR_CANNOT_DEL_QNAME_REF	0x402f
+#define PMERR_CANNOT_DEL_PRINTER_DD_REF 0x4030
+#define PMERR_CANNOT_DEL_PRN_NAME_REF	0x4031
+#define PMERR_CANNOT_DEL_PRN_ADDR_REF	0x4032
+#define PMERR_SPOOLER_QP_NOT_DEFINED	0x4033
+#define PMERR_PRN_NAME_NOT_DEFINED	0x4034
+#define PMERR_PRN_ADDR_NOT_DEFINED	0x4035
+#define PMERR_PRINTER_DD_NOT_DEFINED	0x4036
+#define PMERR_PRINTER_QUEUE_NOT_DEFINED 0x4037
+#define PMERR_PRN_ADDR_IN_USE		0x4038
+#define PMERR_SPL_TOO_MANY_OPEN_FILES	0x4039
+#define PMERR_SPL_CP_NOT_REQD		0x403a
+#define PMERR_SPL_PORT_SHUTDOWN		0x403b
+#define PMERR_SPL_NOT_HANDLED		0x403c
+#define PMERR_SPL_CNV_NOT_INIT		0x403d
+#define PMERR_SPL_INIT_IN_PROGRESS	0x403e
+#define PMERR_SPL_TYPE_NOT_AVAIL	0x403f
+#define PMERR_UNABLE_TO_CLOSE_DEVICE	0x4040
+#define PMERR_SPL_SESSION_TERM		0x4041
+#define PMERR_SPL_NOT_REGISTERED	0x4042
+
+#endif /* INCL_SPLERRORS */
+
+#if defined (INCL_PICERRORS)
+
+#define PMERR_INV_TYPE			0x5001
+#define PMERR_INV_CONV			0x5002
+#define PMERR_INV_SEGLEN		0x5003
+#define PMERR_DUP_SEGNAME		0x5004
+#define PMERR_INV_XFORM			0x5005
+#define PMERR_INV_VIEWLIM		0x5006
+#define PMERR_INV_3DCOORD		0x5007
+#define PMERR_SMB_OVFLOW		0x5008
+#define PMERR_SEG_OVFLOW		0x5009
+#define PMERR_PIC_DUP_FILENAME		0x5010
+
+#endif /* INCL_PICERRORS */
+
+#if defined (INCL_WINERRORS)
+
+#define WINDBG_HWND_NOT_DESTROYED	0x1022
+#define WINDBG_HPTR_NOT_DESTROYED	0x1023
+#define WINDBG_HACCEL_NOT_DESTROYED	0x1024
+#define WINDBG_HENUM_NOT_DESTROYED	0x1025
+#define WINDBG_VISRGN_SEM_BUSY		0x1026
+#define WINDBG_USER_SEM_BUSY		0x1027
+#define WINDBG_DC_CACHE_BUSY		0x1028
+#define WINDBG_HOOK_STILL_INSTALLED	0x1029
+#define WINDBG_WINDOW_STILL_LOCKED	0x102a
+#define WINDBG_UPDATEPS_ASSERTION_FAIL	0x102b
+#define WINDBG_SENDMSG_WITHIN_USER_SEM	0x102c
+#define WINDBG_USER_SEM_NOT_ENTERED	0x102d
+#define WINDBG_PROC_NOT_EXPORTED	0x102e
+#define WINDBG_BAD_SENDMSG_HWND		0x102f
+#define WINDBG_ABNORMAL_EXIT		0x1030
+#define WINDBG_INTERNAL_REVISION	0x1031
+#define WINDBG_INITSYSTEM_FAILED	0x1032
+#define WINDBG_HATOMTBL_NOT_DESTROYED	0x1033
+#define WINDBG_WINDOW_UNLOCK_WAIT	0x1035
+
+#endif /* INCL_WINERRORS */
+
+
+#define WRECT	RECTL
+#define PWRECT	PRECTL
+
+#define WPOINT	POINTL
+#define PWPOINT PPOINTL
+
+
+typedef LHANDLE HACCEL;
+
+typedef LHANDLE HRGN;
+typedef HRGN *PHRGN;
+
+typedef VOID *MRESULT;
+typedef MRESULT *PMRESULT;
+
+typedef VOID *MPARAM;
+typedef MPARAM *PMPARAM;
+
+typedef LHANDLE HPOINTER;
+
+typedef HMODULE HLIB;
+typedef HLIB *PHLIB;
+
+typedef LONG COLOR;
+typedef COLOR *PCOLOR;
+
+typedef LHANDLE HAB;
+typedef HAB *PHAB;
+
+typedef LHANDLE HPS;
+typedef HPS *PHPS;
+
+typedef LHANDLE HDC;
+typedef HDC *PHDC;
+
+typedef LHANDLE HWND;
+typedef HWND *PHWND;
+
+typedef LHANDLE HMQ;
+
+typedef LHANDLE HPAL;
+typedef HPAL *PHPAL;
+
+typedef LHANDLE HBITMAP;
+typedef HBITMAP *PHBITMAP;
+
+typedef ULONG ERRORID;
+typedef ERRORID *PERRORID;
+
+typedef MRESULT FNWP (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+typedef FNWP *PFNWP;
+
+#define ERRORIDERROR(errid)		(LOUSHORT (errid))
+#define ERRORIDSEV(errid)		(HIUSHORT (errid))
+#define MAKEERRORID(sev,error)		(ERRORID)(MAKEULONG ((error), (sev)))
+
+typedef struct _POINTL
+{
+  LONG x;
+  LONG y;
+} POINTL;
+typedef POINTL *PPOINTL;
+
+typedef struct _POINTS
+{
+  SHORT x;
+  SHORT y;
+} POINTS;
+typedef POINTS *PPOINTS;
+
+typedef struct _RECTL
+{
+  LONG xLeft;
+  LONG yBottom;
+  LONG xRight;
+  LONG yTop;
+} RECTL;
+typedef RECTL *PRECTL;
+
+#if defined (INCL_WINMESSAGEMGR) || !defined (INCL_NOCOMMON)
+
+#define WM_NULL				0x0000
+#define WM_CREATE			0x0001
+#define WM_DESTROY			0x0002
+#define WM_ENABLE			0x0004
+#define WM_SHOW				0x0005
+#define WM_MOVE				0x0006
+#define WM_SIZE				0x0007
+#define WM_ADJUSTWINDOWPOS		0x0008
+#define WM_CALCVALIDRECTS		0x0009
+#define WM_SETWINDOWPARAMS		0x000a
+#define WM_QUERYWINDOWPARAMS		0x000b
+#define WM_HITTEST			0x000c
+#define WM_ACTIVATE			0x000d
+#define WM_SETFOCUS			0x000f
+#define WM_SETSELECTION			0x0010
+#define WM_PPAINT			0x0011
+#define WM_PSETFOCUS			0x0012
+#define WM_PSYSCOLORCHANGE		0x0013
+#define WM_PSIZE			0x0014
+#define WM_PACTIVATE			0x0015
+#define WM_PCONTROL			0x0016
+#define WM_COMMAND			0x0020
+#define WM_SYSCOMMAND			0x0021
+#define WM_HELP				0x0022
+#define WM_PAINT			0x0023
+#define WM_TIMER			0x0024
+#define WM_SEM1				0x0025
+#define WM_SEM2				0x0026
+#define WM_SEM3				0x0027
+#define WM_SEM4				0x0028
+#define WM_CLOSE			0x0029
+#define WM_QUIT				0x002a
+#define WM_SYSCOLORCHANGE		0x002b
+#define WM_SYSVALUECHANGED		0x002d
+#define WM_APPTERMINATENOTIFY		0x002e
+#define WM_PRESPARAMCHANGED		0x002f
+#define WM_CONTROL			0x0030
+#define WM_VSCROLL			0x0031
+#define WM_HSCROLL			0x0032
+#define WM_INITMENU			0x0033
+#define WM_MENUSELECT			0x0034
+#define WM_MENUEND			0x0035
+#define WM_DRAWITEM			0x0036
+#define WM_MEASUREITEM			0x0037
+#define WM_CONTROLPOINTER		0x0038
+#define WM_QUERYDLGCODE			0x003a
+#define WM_INITDLG			0x003b
+#define WM_SUBSTITUTESTRING		0x003c
+#define WM_MATCHMNEMONIC		0x003d
+#define WM_SAVEAPPLICATION		0x003e
+
+#define WM_HELPBASE			0x0f00
+#define WM_HELPTOP			0x0fff
+
+#define WM_USER				0x1000
+
+#define CMDSRC_OTHER			0
+#define CMDSRC_PUSHBUTTON		1
+#define CMDSRC_MENU			2
+#define CMDSRC_ACCELERATOR		3
+#define CMDSRC_FONTDLG			4
+#define CMDSRC_FILEDLG			5
+#define CMDSRC_PRINTDLG			6
+#define CMDSRC_COLORDLG			7
+
+#define PM_NOREMOVE			0x0000
+#define PM_REMOVE			0x0001
+
+#define RUM_IN				1
+#define RUM_OUT				2
+#define RUM_INOUT			3
+
+#define SMD_DELAYED			0x0001
+#define SMD_IMMEDIATE			0x0002
+
+#define SSM_SYNCHRONOUS			0x0001
+#define SSM_ASYNCHRONOUS		0x0002
+#define SSM_MIXED			0x0003
+
+#define WLI_NOBUTTONUP			0x0002
+
+#if defined (INCL_WINTYPES)
+
+#define DTYP_USER			16384
+
+#define DTYP_CTL_ARRAY			1
+#define DTYP_CTL_PARRAY			(-1)
+#define DTYP_CTL_OFFSET			2
+#define DTYP_CTL_LENGTH			3
+
+#define DTYP_ACCEL			28
+#define DTYP_ACCELTABLE			29
+#define DTYP_ARCPARAMS			38
+#define DTYP_AREABUNDLE			139
+#define DTYP_ATOM			90
+#define DTYP_BITMAPINFO			60
+#define DTYP_BITMAPINFOHEADER		61
+#define DTYP_BITMAPINFO2		170
+#define DTYP_BITMAPINFOHEADER2		171
+#define DTYP_BIT16			20
+#define DTYP_BIT32			21
+#define DTYP_BIT8			19
+#define DTYP_BOOL			18
+#define DTYP_BTNCDATA			35
+#define DTYP_BYTE			13
+#define DTYP_CATCHBUF			141
+#define DTYP_CHAR			15
+#define DTYP_CHARBUNDLE			135
+#define DTYP_CLASSINFO			95
+#define DTYP_COUNT2			93
+#define DTYP_COUNT2B			70
+#define DTYP_COUNT2CH			82
+#define DTYP_COUNT4			152
+#define DTYP_COUNT4B			42
+#define DTYP_CPID			57
+#define DTYP_CREATESTRUCT		98
+#define DTYP_CURSORINFO			34
+#define DTYP_DEVOPENSTRUC		124
+#define DTYP_DLGTEMPLATE		96
+#define DTYP_DLGTITEM			97
+#define DTYP_ENTRYFDATA			127
+#define DTYP_ERRORID			45
+#define DTYP_FATTRS			75
+#define DTYP_FFDESCS			142
+#define DTYP_FIXED			99
+#define DTYP_FONTMETRICS		74
+#define DTYP_FRAMECDATA			144
+#define DTYP_GRADIENTL			48
+#define DTYP_HAB			10
+#define DTYP_HACCEL			30
+#define DTYP_HAPP			146
+#define DTYP_HATOMTBL			91
+#define DTYP_HBITMAP			62
+#define DTYP_HCINFO			46
+#define DTYP_HDC			132
+#define DTYP_HENUM			117
+#define DTYP_HHEAP			109
+#define DTYP_HINI			53
+#define DTYP_HLIB			147
+#define DTYP_HMF			85
+#define DTYP_HMQ			86
+#define DTYP_HPOINTER			106
+#define DTYP_HPROGRAM			131
+#define DTYP_HPS			12
+#define DTYP_HRGN			116
+#define DTYP_HSEM			140
+#define DTYP_HSPL			32
+#define DTYP_HSWITCH			66
+#define DTYP_HVPS			58
+#define DTYP_HWND			11
+#define DTYP_IDENTITY			133
+#define DTYP_IDENTITY4			169
+#define DTYP_IMAGEBUNDLE		136
+#define DTYP_INDEX2			81
+#define DTYP_IPT			155
+#define DTYP_KERNINGPAIRS		118
+#define DTYP_LENGTH2			68
+#define DTYP_LENGTH4			69
+#define DTYP_LINEBUNDLE			137
+#define DTYP_LONG			25
+#define DTYP_MARKERBUNDLE		138
+#define DTYP_MATRIXLF			113
+#define DTYP_MLECTLDATA			161
+#define DTYP_MLEMARGSTRUCT		157
+#define DTYP_MLEOVERFLOW		158
+#define DTYP_OFFSET2B			112
+#define DTYP_OWNERITEM			154
+#define DTYP_PID			92
+#define DTYP_PIX			156
+#define DTYP_POINTERINFO		105
+#define DTYP_POINTL			77
+#define DTYP_PROGCATEGORY		129
+#define DTYP_PROGRAMENTRY		128
+#define DTYP_PROGTYPE			130
+#define DTYP_PROPERTY2			88
+#define DTYP_PROPERTY4			89
+#define DTYP_QMSG			87
+#define DTYP_RECTL			121
+#define DTYP_RESID			125
+#define DTYP_RGB			111
+#define DTYP_RGNRECT			115
+#define DTYP_SBCDATA			159
+#define DTYP_SEGOFF			126
+#define DTYP_SHORT			23
+#define DTYP_SIZEF			101
+#define DTYP_SIZEL			102
+#define DTYP_STRL			17
+#define DTYP_STR16			40
+#define DTYP_STR32			37
+#define DTYP_STR64			47
+#define DTYP_STR8			33
+#define DTYP_SWBLOCK			63
+#define DTYP_SWCNTRL			64
+#define DTYP_SWENTRY			65
+#define DTYP_SWP			31
+#define DTYP_TID			104
+#define DTYP_TIME			107
+#define DTYP_TRACKINFO			73
+#define DTYP_UCHAR			22
+#define DTYP_ULONG			26
+#define DTYP_USERBUTTON			36
+#define DTYP_USHORT			24
+#define DTYP_WIDTH4			108
+#define DTYP_WNDPARAMS			83
+#define DTYP_WNDPROC			84
+#define DTYP_WPOINT			59
+#define DTYP_WRECT			55
+#define DTYP_XYWINSIZE			52
+
+#define DTYP_PACCEL			(-28)
+#define DTYP_PACCELTABLE		(-29)
+#define DTYP_PARCPARAMS			(-38)
+#define DTYP_PAREABUNDLE		(-139)
+#define DTYP_PATOM			(-90)
+#define DTYP_PBITMAPINFO		(-60)
+#define DTYP_PBITMAPINFOHEADER		(-61)
+#define DTYP_PBITMAPINFO2		(-170)
+#define DTYP_PBITMAPINFOHEADER2		(-171)
+#define DTYP_PBIT16			(-20)
+#define DTYP_PBIT32			(-21)
+#define DTYP_PBIT8			(-19)
+#define DTYP_PBOOL			(-18)
+#define DTYP_PBTNCDATA			(-35)
+#define DTYP_PBYTE			(-13)
+#define DTYP_PCATCHBUF			(-141)
+#define DTYP_PCHAR			(-15)
+#define DTYP_PCHARBUNDLE		(-135)
+#define DTYP_PCLASSINFO			(-95)
+#define DTYP_PCOUNT2			(-93)
+#define DTYP_PCOUNT2B			(-70)
+#define DTYP_PCOUNT2CH			(-82)
+#define DTYP_PCOUNT4			(-152)
+#define DTYP_PCOUNT4B			(-42)
+#define DTYP_PCPID			(-57)
+#define DTYP_PCREATESTRUCT		(-98)
+#define DTYP_PCURSORINFO		(-34)
+#define DTYP_PDEVOPENSTRUC		(-124)
+#define DTYP_PDLGTEMPLATE		(-96)
+#define DTYP_PDLGTITEM			(-97)
+#define DTYP_PENTRYFDATA		(-127)
+#define DTYP_PERRORID			(-45)
+#define DTYP_PFATTRS			(-75)
+#define DTYP_PFFDESCS			(-142)
+#define DTYP_PFIXED			(-99)
+#define DTYP_PFONTMETRICS		(-74)
+#define DTYP_PFRAMECDATA		(-144)
+#define DTYP_PGRADIENTL			(-48)
+#define DTYP_PHAB			(-10)
+#define DTYP_PHACCEL			(-30)
+#define DTYP_PHAPP			(-146)
+#define DTYP_PHATOMTBL			(-91)
+#define DTYP_PHBITMAP			(-62)
+#define DTYP_PHCINFO			(-46)
+#define DTYP_PHDC			(-132)
+#define DTYP_PHENUM			(-117)
+#define DTYP_PHHEAP			(-109)
+#define DTYP_PHINI			(-53)
+#define DTYP_PHLIB			(-147)
+#define DTYP_PHMF			(-85)
+#define DTYP_PHMQ			(-86)
+#define DTYP_PHPOINTER			(-106)
+#define DTYP_PHPROGRAM			(-131)
+#define DTYP_PHPS			(-12)
+#define DTYP_PHRGN			(-116)
+#define DTYP_PHSEM			(-140)
+#define DTYP_PHSPL			(-32)
+#define DTYP_PHSWITCH			(-66)
+#define DTYP_PHVPS			(-58)
+#define DTYP_PHWND			(-11)
+#define DTYP_PIDENTITY			(-133)
+#define DTYP_PIDENTITY4			(-169)
+#define DTYP_PIMAGEBUNDLE		(-136)
+#define DTYP_PINDEX2			(-81)
+#define DTYP_PIPT			(-155)
+#define DTYP_PKERNINGPAIRS		(-118)
+#define DTYP_PLENGTH2			(-68)
+#define DTYP_PLENGTH4			(-69)
+#define DTYP_PLINEBUNDLE		(-137)
+#define DTYP_PLONG			(-25)
+#define DTYP_PMARKERBUNDLE		(-138)
+#define DTYP_PMATRIXLF			(-113)
+#define DTYP_PMLECTLDATA		(-161)
+#define DTYP_PMLEMARGSTRUCT		(-157)
+#define DTYP_PMLEOVERFLOW		(-158)
+#define DTYP_POFFSET2B			(-112)
+#define DTYP_POWNERITEM			(-154)
+#define DTYP_PPID			(-92)
+#define DTYP_PPIX			(-156)
+#define DTYP_PPOINTERINFO		(-105)
+#define DTYP_PPOINTL			(-77)
+#define DTYP_PPROGCATEGORY		(-129)
+#define DTYP_PPROGRAMENTRY		(-128)
+#define DTYP_PPROGTYPE			(-130)
+#define DTYP_PPROPERTY2			(-88)
+#define DTYP_PPROPERTY4			(-89)
+#define DTYP_PQMSG			(-87)
+#define DTYP_PRECTL			(-121)
+#define DTYP_PRESID			(-125)
+#define DTYP_PRGB			(-111)
+#define DTYP_PRGNRECT			(-115)
+#define DTYP_PSBCDATA			(-159)
+#define DTYP_PSEGOFF			(-126)
+#define DTYP_PSHORT			(-23)
+#define DTYP_PSIZEF			(-101)
+#define DTYP_PSIZEL			(-102)
+#define DTYP_PSTRL			(-17)
+#define DTYP_PSTR16			(-40)
+#define DTYP_PSTR32			(-37)
+#define DTYP_PSTR64			(-47)
+#define DTYP_PSTR8			(-33)
+#define DTYP_PSWBLOCK			(-63)
+#define DTYP_PSWCNTRL			(-64)
+#define DTYP_PSWENTRY			(-65)
+#define DTYP_PSWP			(-31)
+#define DTYP_PTID			(-104)
+#define DTYP_PTIME			(-107)
+#define DTYP_PTRACKINFO			(-73)
+#define DTYP_PUCHAR			(-22)
+#define DTYP_PULONG			(-26)
+#define DTYP_PUSERBUTTON		(-36)
+#define DTYP_PUSHORT			(-24)
+#define DTYP_PWIDTH4			(-108)
+#define DTYP_PWNDPARAMS			(-83)
+#define DTYP_PWNDPROC			(-84)
+#define DTYP_PWPOINT			(-59)
+#define DTYP_PWRECT			(-55)
+#define DTYP_PXYWINSIZE			(-52)
+
+#endif /* INCL_WINTYPES */
+
+typedef struct _QMSG
+{
+  HWND	 hwnd;
+  ULONG	 msg;
+  MPARAM mp1;
+  MPARAM mp2;
+  ULONG	 time;
+  POINTL ptl;
+  ULONG	 reserved;
+} QMSG;
+typedef QMSG *PQMSG;
+
+typedef struct _COMMANDMSG
+{
+  USHORT cmd;
+  USHORT unused;
+  USHORT source;
+  USHORT fMouse;
+} CMDMSG;
+typedef CMDMSG *PCMDMSG;
+
+typedef struct _MQINFO
+{
+  ULONG cb;
+  PID	pid;
+  TID	tid;
+  ULONG cmsgs;
+  PVOID pReserved;
+} MQINFO;
+typedef MQINFO *PMQINFO;
+
+#define COMMANDMSG(pmsg)	((PCMDMSG)((PBYTE)pmsg + sizeof (ULONG)))
+
+
+BOOL WinCancelShutdown (HMQ hmq, BOOL fCancelAlways);
+HMQ WinCreateMsgQueue (HAB hab, LONG cmsg);
+BOOL WinDestroyMsgQueue (HMQ hmq);
+MRESULT WinDispatchMsg (HAB hab, PQMSG pqmsg);
+BOOL WinGetMsg (HAB hab, PQMSG pqmsg, HWND hwndFilter, ULONG msgFilterFirst,
+    ULONG msgFilterLast);
+BOOL WinLockInput (HMQ hmq, ULONG fLock);
+BOOL WinPeekMsg (HAB hab, PQMSG pqmsg, HWND hwndFilter, ULONG msgFilterFirst,
+    ULONG msgFilterLast, ULONG fl);
+BOOL WinPostMsg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+HMQ WinQueueFromID (HAB hab, PID pid, TID tid);
+BOOL WinQueryQueueInfo (HMQ hmq, PMQINFO pmqi, ULONG cbCopy);
+HMQ WinQuerySendMsg (HAB hab, HMQ hmqSender, HMQ hmqReceiver, PQMSG pqmsg);
+BOOL WinRegisterUserDatatype (HAB hab, LONG datatype, LONG count, PLONG types);
+BOOL WinRegisterUserMsg (HAB hab, ULONG msgid, LONG datatype1, LONG dir1,
+    LONG datatype2, LONG dir2, LONG datatyper);
+BOOL WinReplyMsg (HAB hab, HMQ hmqSender, HMQ hmqReceiver, MRESULT mresult);
+MRESULT WinSendMsg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+BOOL WinSetMsgMode (HAB hab, PCSZ classname, LONG control);
+BOOL WinSetSynchroMode (HAB hab, LONG mode);
+BOOL WinThreadAssocQueue (HAB hab, HMQ hmq);
+BOOL WinWakeThread (HMQ hmq);
+
+#endif /* INCL_WINMESSAGEMGR || !INCL_NOCOMMON */
+
+typedef struct _SWP
+{
+  ULONG fl;
+  LONG	cy;
+  LONG	cx;
+  LONG	y;
+  LONG	x;
+  HWND	hwndInsertBehind;
+  HWND	hwnd;
+  ULONG ulReserved1;
+  ULONG ulReserved2;
+} SWP;
+typedef SWP *PSWP;
+
+typedef struct _ICONINFO
+{
+   ULONG   cb;
+   ULONG   fFormat;
+   PSZ	   pszFileName;
+   HMODULE hmod;
+   ULONG   resid;
+   ULONG   cbIconData;
+   PVOID   pIconData;
+} ICONINFO;
+typedef ICONINFO *PICONINFO;
+
+
+#define MPVOID			((MPARAM)0)
+
+#define MPFROMP(x)		((MPARAM)((ULONG)(x)))
+#define MPFROMHWND(x)		((MPARAM)(HWND)(x))
+#define MPFROMCHAR(x)		((MPARAM)(ULONG)(USHORT)(x))
+#define MPFROMSHORT(x)		((MPARAM)(ULONG)(USHORT)(x))
+#define MPFROM2SHORT(x1,x2)	((MPARAM)MAKELONG (x1, x2))
+#define MPFROMSH2CH(s,c1,c2)	((MPARAM)MAKELONG (s, MAKESHORT (c1, c2)))
+#define MPFROMLONG(x)		((MPARAM)(ULONG)(x))
+
+#define PVOIDFROMMP(mp)		((PVOID)(mp))
+#define HWNDFROMMP(mp)		((HWND)(mp))
+#define CHAR1FROMMP(mp)		((UCHAR)(ULONG)(mp))
+#define CHAR2FROMMP(mp)		((UCHAR)((ULONG)mp >> 8))
+#define CHAR3FROMMP(mp)		((UCHAR)((ULONG)mp >> 16))
+#define CHAR4FROMMP(mp)		((UCHAR)((ULONG)mp >> 24))
+#define SHORT1FROMMP(mp)	((USHORT)(ULONG)(mp))
+#define SHORT2FROMMP(mp)	((USHORT)((ULONG)mp >> 16))
+#define LONGFROMMP(mp)		((ULONG)(mp))
+
+#define MRFROMP(x)		((MRESULT)(PVOID)(x))
+#define MRFROMSHORT(x)		((MRESULT)(ULONG)(USHORT)(x))
+#define MRFROM2SHORT(x1,x2)	((MRESULT)MAKELONG (x1, x2))
+#define MRFROMLONG(x)		((MRESULT)(ULONG)(x))
+
+#define PVOIDFROMMR(mr)		((VOID *)(mr))
+#define SHORT1FROMMR(mr)	((USHORT)((ULONG)mr))
+#define SHORT2FROMMR(mr)	((USHORT)((ULONG)mr >> 16))
+#define LONGFROMMR(mr)		((ULONG)(mr))
+
+
+HWND WinCreateWindow (HWND hwndParent, PCSZ pszClass, PCSZ pszName,
+    ULONG flStyle, LONG x, LONG y, LONG cx, LONG cy, HWND hwndOwner,
+    HWND hwndInsertBehind, ULONG id, PVOID pCtlData, PVOID pPresParams);
+BOOL WinDrawBitmap (HPS hpsDst, HBITMAP hbm, __const__ RECTL *pwrcSrc,
+    __const__ POINTL *pptlDst, LONG clrFore, LONG clrBack, ULONG fl);
+BOOL WinDrawBorder (HPS hps, __const__ RECTL *prcl, LONG cx, LONG cy,
+    LONG clrFore, LONG clrBack, ULONG flCmd);
+LONG WinDrawText (HPS hps, LONG cchText, PCCH lpchText, PRECTL prcl,
+    LONG clrFore, LONG clrBack, ULONG flCmd);
+BOOL WinEnableWindow (HWND hwnd, BOOL fEnable);
+BOOL WinEnableWindowUpdate (HWND hwnd, BOOL fEnable);
+BOOL WinInvalidateRect (HWND hwnd, __const__ RECTL *prcl,
+    BOOL fIncludeChildren);
+BOOL WinInvalidateRegion (HWND hwnd, HRGN hrgn, BOOL fIncludeChildren);
+BOOL WinInvertRect (HPS hps, __const__ RECTL *prcl);
+BOOL WinIsChild (HWND hwnd, HWND hwndParent);
+BOOL WinIsWindow (HAB hab, HWND hwnd);
+BOOL WinIsWindowEnabled (HWND hwnd);
+BOOL WinIsWindowVisible (HWND hwnd);
+LONG WinLoadMessage (HAB hab, HMODULE hmod, ULONG id, LONG cchMax,
+    PSZ pchBuffer);
+LONG WinLoadString (HAB hab, HMODULE hmod, ULONG id, LONG cchMax,
+    PSZ pchBuffer);
+LONG WinMultWindowFromIDs (HWND hwndParent, PHWND prghwnd, ULONG idFirst,
+    ULONG idLast);
+HWND WinQueryDesktopWindow (HAB hab, HDC hdc);
+HWND WinQueryObjectWindow (HWND hwndDesktop);
+HPOINTER WinQueryPointer (HWND hwndDesktop);
+HWND WinQueryWindow (HWND hwnd, LONG cmd);
+BOOL WinQueryWindowPos (HWND hwnd, PSWP pswp);
+BOOL WinQueryWindowProcess (HWND hwnd, PPID ppid, PTID ptid);
+LONG WinQueryWindowText (HWND hwnd, LONG cchBufferMax, PCH pchBuffer);
+LONG WinQueryWindowTextLength (HWND hwnd);
+BOOL WinSetMultWindowPos (HAB hab, __const__ SWP *pswp, ULONG cswp);
+BOOL WinSetOwner (HWND hwnd, HWND hwndNewOwner);
+BOOL WinSetParent (HWND hwnd, HWND hwndNewParent, BOOL fRedraw);
+BOOL WinSetWindowPos (HWND hwnd, HWND hwndInsertBehind, LONG x, LONG y,
+    LONG cx, LONG cy, ULONG fl);
+BOOL WinSetWindowText (HWND hwnd, PCSZ pszText);
+BOOL WinUpdateWindow (HWND hwnd);
+HWND WinWindowFromID (HWND hwndParent, ULONG id);
+
+
+#if defined (INCL_WINFRAMEMGR) || !defined (INCL_NOCOMMON)
+
+#define FCF_TITLEBAR			0x00000001
+#define FCF_SYSMENU			0x00000002
+#define FCF_MENU			0x00000004
+#define FCF_SIZEBORDER			0x00000008
+#define FCF_MINBUTTON			0x00000010
+#define FCF_MAXBUTTON			0x00000020
+#define FCF_MINMAX			(FCF_MINBUTTON|FCF_MAXBUTTON)
+#define FCF_VERTSCROLL			0x00000040
+#define FCF_HORZSCROLL			0x00000080
+#define FCF_DLGBORDER			0x00000100
+#define FCF_BORDER			0x00000200
+#define FCF_SHELLPOSITION		0x00000400
+#define FCF_TASKLIST			0x00000800
+#define FCF_NOBYTEALIGN			0x00001000
+#define FCF_NOMOVEWITHOWNER		0x00002000
+#define FCF_ICON			0x00004000
+#define FCF_ACCELTABLE			0x00008000
+#define FCF_SYSMODAL			0x00010000
+#define FCF_SCREENALIGN			0x00020000
+#define FCF_MOUSEALIGN			0x00040000
+#define FCF_PALETTE_NORMAL		0x00080000
+#define FCF_PALETTE_HELP		0x00100000
+#define FCF_PALETTE_POPUPODD		0x00200000
+#define FCF_PALETTE_POPUPEVEN		0x00400000
+#define FCF_HIDEBUTTON			0x01000000
+#define FCF_HIDEMAX			0x01000020
+#define FCF_AUTOICON			0x40000000
+#if defined (INCL_NLS)
+#define FCF_DBE_APPSTAT			0x80000000
+#endif /* INCL_NLS */
+
+#define FCF_STANDARD			0x0000cc3f
+
+#define FF_FLASHWINDOW			0x0001
+#define FF_ACTIVE			0x0002
+#define FF_FLASHHILITE			0x0004
+#define FF_OWNERHIDDEN			0x0008
+#define FF_DLGDISMISSED			0x0010
+#define FF_OWNERDISABLED		0x0020
+#define FF_SELECTED			0x0040
+#define FF_NOACTIVATESWP		0x0080
+#define FF_DIALOGBOX			0x0100
+
+#define FS_ICON				0x00000001
+#define FS_ACCELTABLE			0x00000002
+#define FS_SHELLPOSITION		0x00000004
+#define FS_TASKLIST			0x00000008
+#define FS_NOBYTEALIGN			0x00000010
+#define FS_NOMOVEWITHOWNER		0x00000020
+#define FS_SYSMODAL			0x00000040
+#define FS_DLGBORDER			0x00000080
+#define FS_BORDER			0x00000100
+#define FS_SCREENALIGN			0x00000200
+#define FS_MOUSEALIGN			0x00000400
+#define FS_SIZEBORDER			0x00000800
+#define FS_AUTOICON			0x00001000
+#if defined (INCL_NLS)
+#define FS_DBE_APPSTAT			0x00008000
+#endif /* INCL_NLS */
+
+#define FS_STANDARD			0x0000000f
+
+typedef struct _FRAMECDATA
+{
+  USHORT cb;
+  ULONG	 flCreateFlags;
+  USHORT hmodResources;
+  USHORT idResources;
+} FRAMECDATA;
+typedef FRAMECDATA *PFRAMECDATA;
+
+HWND WinCreateStdWindow (HWND hwndParent, ULONG flStyle,
+    PULONG pflCreateFlags, PCSZ pszClientClass, PCSZ pszTitle,
+    ULONG styleClient, HMODULE hmod, ULONG idResources, PHWND phwndClient);
+
+#endif /* INCL_WINFRAMEMGR || !INCL_NOCOMMON */
+
+#if defined (INCL_WINFRAMEMGR)
+
+#define WM_FLASHWINDOW			0x0040
+#define WM_FORMATFRAME			0x0041
+#define WM_UPDATEFRAME			0x0042
+#define WM_FOCUSCHANGE			0x0043
+#define WM_SETBORDERSIZE		0x0044
+#define WM_TRACKFRAME			0x0045
+#define WM_MINMAXFRAME			0x0046
+#define WM_SETICON			0x0047
+#define WM_QUERYICON			0x0048
+#define WM_SETACCELTABLE		0x0049
+#define WM_QUERYACCELTABLE		0x004a
+#define WM_TRANSLATEACCEL		0x004b
+#define WM_QUERYTRACKINFO		0x004c
+#define WM_QUERYBORDERSIZE		0x004d
+#define WM_NEXTMENU			0x004e
+#define WM_ERASEBACKGROUND		0x004f
+#define WM_QUERYFRAMEINFO		0x0050
+#define WM_QUERYFOCUSCHAIN		0x0051
+#define WM_OWNERPOSCHANGE		0x0052
+#define WM_CALCFRAMERECT		0x0053
+#define WM_WINDOWPOSCHANGED		0x0055
+#define WM_ADJUSTFRAMEPOS		0x0056
+#define WM_QUERYFRAMECTLCOUNT		0x0059
+#define WM_QUERYHELPINFO		0x005b
+#define WM_SETHELPINFO			0x005c
+#define WM_ERROR			0x005d
+#define WM_REALIZEPALETTE		0x005e
+
+#define FI_FRAME			0x00000001
+#define FI_OWNERHIDE			0x00000002
+#define FI_ACTIVATEOK			0x00000004
+#define FI_NOMOVEWITHOWNER		0x00000008
+
+#define FID_SYSMENU			0x8002
+#define FID_TITLEBAR			0x8003
+#define FID_MINMAX			0x8004
+#define FID_MENU			0x8005
+#define FID_VERTSCROLL			0x8006
+#define FID_HORZSCROLL			0x8007
+#define FID_CLIENT			0x8008
+#define FID_DBE_APPSTAT			0x8010
+#define FID_DBE_KBDSTAT			0x8011
+#define FID_DBE_PECIC			0x8012
+#define FID_DBE_KKPOPUP			0x8013
+
+#define SC_SIZE				0x8000
+#define SC_MOVE				0x8001
+#define SC_MINIMIZE			0x8002
+#define SC_MAXIMIZE			0x8003
+#define SC_CLOSE			0x8004
+#define SC_NEXT				0x8005
+#define SC_APPMENU			0x8006
+#define SC_SYSMENU			0x8007
+#define SC_RESTORE			0x8008
+#define SC_NEXTFRAME			0x8009
+#define SC_NEXTWINDOW			0x8010
+#define SC_TASKMANAGER			0x8011
+#define SC_HELPKEYS			0x8012
+#define SC_HELPINDEX			0x8013
+#define SC_HELPEXTENDED			0x8014
+#define SC_SWITCHPANELIDS		0x8015
+#define SC_DBE_FIRST			0x8018
+#define SC_DBE_LAST			0x801f
+#define SC_BEGINDRAG			0x8020
+#define SC_ENDDRAG			0x8021
+#define SC_SELECT			0x8022
+#define SC_OPEN				0x8023
+#define SC_CONTEXTMENU			0x8024
+#define SC_CONTEXTHELP			0x8025
+#define SC_TEXTEDIT			0x8026
+#define SC_BEGINSELECT			0x8027
+#define SC_ENDSELECT			0x8028
+#define SC_WINDOW			0x8029
+#define SC_HIDE				0x802a
+
+typedef LHANDLE HSAVEWP;
+
+BOOL WinCalcFrameRect (HWND hwndFrame, PRECTL prcl, BOOL fClient);
+BOOL WinCreateFrameControls (HWND hwndFrame, PFRAMECDATA pfcdata,
+    PCSZ pszTitle);
+BOOL WinFlashWindow (HWND hwndFrame, BOOL fFlash);
+BOOL WinGetMaxPosition (HWND hwnd, PSWP pswp);
+BOOL WinGetMinPosition (HWND hwnd, PSWP pswp, __const__ POINTL *pptl);
+BOOL WinSaveWindowPos (HSAVEWP hsvwp, PSWP pswp, ULONG cswp);
+
+#endif /* INCL_WINFRAMEMGR */
+
+
+#if defined (INCL_WINWINDOWMGR) || !defined (INCL_NOCOMMON)
+
+#define PSF_LOCKWINDOWUPDATE		0x0001
+#define PSF_CLIPUPWARDS			0x0002
+#define PSF_CLIPDOWNWARDS		0x0004
+#define PSF_CLIPSIBLINGS		0x0008
+#define PSF_CLIPCHILDREN		0x0010
+#define PSF_PARENTCLIP			0x0020
+
+#define QV_OS2				0x0000
+#define QV_CMS				0x0001
+#define QV_TSO				0x0002
+#define QV_TSOBATCH			0x0003
+#define QV_OS400			0x0004
+
+#define SW_SCROLLCHILDREN		0x0001
+#define SW_INVALIDATERGN		0x0002
+
+
+typedef struct _QVERSDATA
+{
+  USHORT environment;
+  USHORT version;
+} QVERSDATA;
+typedef QVERSDATA *PQVERSDATA;
+
+
+HPS WinBeginPaint (HWND hwnd, HPS hps, PRECTL prclPaint);
+MRESULT WinDefWindowProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+BOOL WinDestroyWindow (HWND hwnd);
+BOOL WinEndPaint (HPS hps);
+BOOL WinFillRect (HPS hps, __const__ RECTL *prcl, LONG lColor);
+HPS WinGetClipPS (HWND hwnd, HWND hwndClip, ULONG fl);
+HPS WinGetPS (HWND hwnd);
+HAB WinInitialize (ULONG fsOptions);
+BOOL WinIsWindowShowing (HWND hwnd);
+HDC WinOpenWindowDC (HWND hwnd);
+HAB WinQueryAnchorBlock (HWND hwnd);
+ULONG WinQueryVersion (HAB hab);
+BOOL WinQueryWindowRect (HWND hwnd, PRECTL prclDest);
+BOOL WinRegisterClass (HAB hab, PCSZ pszClassName, PFNWP pfnWndProc,
+    ULONG flStyle, ULONG cbWindowData);
+BOOL WinReleasePS (HPS hps);
+LONG WinScrollWindow (HWND hwnd, LONG dx, LONG dy, __const__ RECTL *prclScroll,
+    __const__ RECTL *prclClip, HRGN hrgnUpdate, PRECTL prclUpdate,
+    ULONG rgfsw);
+BOOL WinSetActiveWindow (HWND hwndDesktop, HWND hwnd);
+BOOL WinShowWindow (HWND hwnd, BOOL fShow);
+BOOL WinTerminate (HAB hab);
+
+#endif /* INCL_WINWINDOWMGR || !INCL_NOCOMMON */
+
+#if defined (INCL_WINWINDOWMGR)
+
+#define WM_QUERYCONVERTPOS		0x00b0
+
+#define QCP_CONVERT			0x0001
+#define QCP_NOCONVERT			0x0000
+
+#define QWS_USER			0
+#define QWS_ID				(-1)
+#define QWS_MIN				(-1)
+
+#define QWL_USER			0
+#define QWL_STYLE			(-2)
+#define QWP_PFNWP			(-3)
+#define QWL_HMQ				(-4)
+#define QWL_RESERVED			(-5)
+#define QWL_PENDATA			(-7)
+#define QWL_BD_ATTR			(-9)
+#define QWL_BD_STAT			(-10)
+#define QWL_KBDLAYER			(-11)
+#define QWL_MIN				(-11)
+
+#define QWL_HHEAP			0x0004
+#define QWL_HWNDFOCUSSAVE		0x0018
+#define QWL_DEFBUTTON			0x0040
+#define QWL_PSSCBLK			0x0048
+#define QWL_PFEPBLK			0x004c
+#define QWL_PSTATBLK			0x0050
+
+#define QWS_FLAGS			0x0008
+#define QWS_RESULT			0x000a
+#define QWS_XRESTORE			0x000c
+#define QWS_YRESTORE			0x000e
+#define QWS_CXRESTORE			0x0010
+#define QWS_CYRESTORE			0x0012
+#define QWS_XMINIMIZE			0x0014
+#define QWS_YMINIMIZE			0x0016
+
+
+typedef struct _CLASSINFO
+{
+  ULONG flClassStyle;
+  PFNWP pfnWindowProc;
+  ULONG cbWindowData;
+} CLASSINFO;
+typedef CLASSINFO *PCLASSINFO;
+
+typedef struct _CREATESTRUCT
+{
+  PVOID pPresParams;
+  PVOID pCtlData;
+  ULONG id;
+  HWND	hwndInsertBehind;
+  HWND	hwndOwner;
+  LONG	cy;
+  LONG	cx;
+  LONG	y;
+  LONG	x;
+  ULONG flStyle;
+  PSZ	pszText;
+  PSZ	pszClass;
+  HWND	hwndParent;
+} CREATESTRUCT;
+typedef CREATESTRUCT *PCREATESTRUCT;
+
+typedef LHANDLE HENUM;
+
+
+HENUM WinBeginEnumWindows (HWND hwnd);
+BOOL WinEndEnumWindows (HENUM henum);
+LONG WinExcludeUpdateRegion (HPS hps, HWND hwnd);
+HWND WinGetNextWindow (HENUM henum);
+HPS WinGetScreenPS (HWND hwndDesktop);
+BOOL WinIsThreadActive (HAB hab);
+BOOL WinLockVisRegions (HWND hwndDesktop, BOOL fLock);
+BOOL WinLockWindowUpdate (HWND hwndDesktop, HWND hwndLockUpdate);
+BOOL WinMapWindowPoints (HWND hwndFrom, HWND hwndTo, PPOINTL prgptl,
+    LONG cwpt);
+HWND WinQueryActiveWindow (HWND hwndDesktop);
+BOOL WinQueryClassInfo (HAB hab, PCSZ pszClassName, PCLASSINFO pClassInfo);
+LONG WinQueryClassName (HWND hwnd, LONG cchMax, PCH pch);
+BOOL WinQueryUpdateRect (HWND hwnd, PRECTL prcl);
+LONG WinQueryUpdateRegion (HWND hwnd, HRGN hrgn);
+HWND WinQuerySysModalWindow (HWND hwndDesktop);
+HDC WinQueryWindowDC (HWND hwnd);
+PVOID WinQueryWindowPtr (HWND hwnd, LONG index);
+ULONG WinQueryWindowULong (HWND hwnd, LONG index);
+USHORT WinQueryWindowUShort (HWND hwnd, LONG index);
+BOOL WinSetSysModalWindow (HWND hwndDesktop, HWND hwnd);
+BOOL WinSetWindowBits (HWND hwnd, LONG index, ULONG flData, ULONG flMask);
+BOOL WinSetWindowPtr (HWND hwnd, LONG index, PVOID p);
+BOOL WinSetWindowULong (HWND hwnd, LONG index, ULONG ul);
+BOOL WinSetWindowUShort (HWND hwnd, LONG index, USHORT us);
+PFNWP WinSubclassWindow (HWND hwnd, PFNWP pfnwp);
+BOOL WinValidateRect (HWND hwnd, __const__ RECTL *prcl, BOOL fIncludeChildren);
+BOOL WinValidateRegion (HWND hwnd, HRGN hrgn, BOOL fIncludeChildren);
+HWND WinWindowFromDC (HDC hdc);
+HWND WinWindowFromPoint (HWND hwnd, __const__ POINTL *pptl, BOOL fChildren);
+
+#endif /* INCL_WINWINDOWMGR */
+
+
+#if defined (INCL_WINACCELERATORS)
+
+#define AF_CHAR				0x0001
+#define AF_VIRTUALKEY			0x0002
+#define AF_SCANCODE			0x0004
+#define AF_SHIFT			0x0008
+#define AF_CONTROL			0x0010
+#define AF_ALT				0x0020
+#define AF_LONEKEY			0x0040
+#define AF_SYSCOMMAND			0x0100
+#define AF_HELP				0x0200
+
+typedef struct _ACCEL
+{
+  USHORT fs;
+  USHORT key;
+  USHORT cmd;
+} ACCEL;
+typedef ACCEL *PACCEL;
+
+typedef struct _ACCELTABLE
+{
+  USHORT cAccel;
+  USHORT codepage;
+  ACCEL	 aaccel[1];
+} ACCELTABLE;
+typedef ACCELTABLE *PACCELTABLE;
+
+ULONG WinCopyAccelTable (HACCEL haccel, PACCELTABLE pAccelTable,
+    ULONG cbCopyMax);
+HACCEL WinCreateAccelTable (HAB hab, PACCELTABLE pAccelTable);
+BOOL WinDestroyAccelTable (HACCEL haccel);
+HACCEL WinLoadAccelTable (HAB hab, HMODULE hmod, ULONG idAccelTable);
+HACCEL WinQueryAccelTable (HAB hab, HWND hwndFrame);
+BOOL WinSetAccelTable (HAB hab, HACCEL haccel, HWND hwndFrame);
+BOOL WinTranslateAccel (HAB hab, HWND hwnd, HACCEL haccel, PQMSG pqmsg);
+
+#endif /* INCL_WINACCELERATORS */
+
+
+#if defined (INCL_WINATOM)
+
+typedef LHANDLE HATOMTBL;
+typedef ULONG ATOM;
+
+#define MAKEINTATOM(x)		((PCH)MAKEULONG (x, 0xffff))
+
+ATOM WinAddAtom (HATOMTBL hAtomTbl, PCSZ pszAtomName);
+HATOMTBL WinCreateAtomTable (ULONG cbInitial, ULONG cBuckets);
+ATOM WinDeleteAtom (HATOMTBL hAtomTbl, ATOM atom);
+HATOMTBL WinDestroyAtomTable (HATOMTBL hAtomTbl);
+ATOM WinFindAtom (HATOMTBL hAtomTbl, PCSZ pszAtomName);
+ULONG WinQueryAtomLength (HATOMTBL hAtomTbl, ATOM atom);
+ULONG WinQueryAtomName (HATOMTBL hAtomTbl, ATOM atom, PSZ pchBuffer,
+    ULONG cchBufferMax);
+ULONG WinQueryAtomUsage (HATOMTBL hAtomTbl, ATOM atom);
+HATOMTBL WinQuerySystemAtomTable (VOID);
+
+#endif /* INCL_WINATOM */
+
+
+#if defined (INCL_WINBUTTONS)
+
+#define BDS_HILITED			0x0100
+#define BDS_DISABLED			0x0200
+#define BDS_DEFAULT			0x0400
+
+#define BM_CLICK			0x0120
+#define BM_QUERYCHECKINDEX		0x0121
+#define BM_QUERYHILITE			0x0122
+#define BM_SETHILITE			0x0123
+#define BM_QUERYCHECK			0x0124
+#define BM_SETCHECK			0x0125
+#define BM_SETDEFAULT			0x0126
+
+#define BN_CLICKED			1
+#define BN_DBLCLICKED			2
+#define BN_PAINT			3
+
+#define BS_PUSHBUTTON			0
+#define BS_CHECKBOX			1
+#define BS_AUTOCHECKBOX			2
+#define BS_RADIOBUTTON			3
+#define BS_AUTORADIOBUTTON		4
+#define BS_3STATE			5
+#define BS_AUTO3STATE			6
+#define BS_USERBUTTON			7
+
+#define BS_PRIMARYSTYLES		0x000f
+#define BS_TEXT				0x0010
+#define BS_MINIICON			0x0020
+#define BS_BITMAP			0x0040
+#define BS_ICON				0x0080
+#define BS_HELP				0x0100
+#define BS_SYSCOMMAND			0x0200
+#define BS_DEFAULT			0x0400
+#define BS_NOPOINTERFOCUS		0x0800
+#define BS_NOBORDER			0x1000
+#define BS_NOCURSORSELECT		0x2000
+#define BS_AUTOSIZE			0x4000
+
+typedef struct _BTNCDATA
+{
+  USHORT  cb;
+  USHORT  fsCheckState;
+  USHORT  fsHiliteState;
+  LHANDLE hImage;
+} BTNCDATA;
+typedef BTNCDATA *PBTNCDATA;
+
+typedef struct _USERBUTTON
+{
+  HWND	hwnd;
+  HPS	hps;
+  ULONG fsState;
+  ULONG fsStateOld;
+} USERBUTTON;
+typedef USERBUTTON *PUSERBUTTON;
+
+
+#endif /* INCL_WINBUTTONS */
+
+
+#if defined (INCL_WINCLIPBOARD) || defined (INCL_WINDDE)
+
+#define WM_RENDERFMT			0x0060
+#define WM_RENDERALLFMTS		0x0061
+#define WM_DESTROYCLIPBOARD		0x0062
+#define WM_PAINTCLIPBOARD		0x0063
+#define WM_SIZECLIPBOARD		0x0064
+#define WM_HSCROLLCLIPBOARD		0x0065
+#define WM_VSCROLLCLIPBOARD		0x0066
+#define WM_DRAWCLIPBOARD		0x0067
+
+#define CF_TEXT				1
+#define CF_BITMAP			2
+#define CF_DSPTEXT			3
+#define CF_DSPBITMAP			4
+#define CF_METAFILE			5
+#define CF_DSPMETAFILE			6
+#define CF_PALETTE			9
+#define CF_MMPMFIRST			10
+#define CF_MMPMLAST			19
+
+#define SZFMT_TEXT			"#1"
+#define SZFMT_BITMAP			"#2"
+#define SZFMT_DSPTEXT			"#3"
+#define SZFMT_DSPBITMAP			"#4"
+#define SZFMT_METAFILE			"#5"
+#define SZFMT_DSPMETAFILE		"#6"
+#define SZFMT_PALETTE			"#9"
+#define SZFMT_SYLK			"Sylk"
+#define SZFMT_DIF			"Dif"
+#define SZFMT_TIFF			"Tiff"
+#define SZFMT_OEMTEXT			"OemText"
+#define SZFMT_DIB			"Dib"
+#define SZFMT_OWNERDISPLAY		"OwnerDisplay"
+#define SZFMT_LINK			"Link"
+#define SZFMT_METAFILEPICT		"MetaFilePict"
+#define SZFMT_DSPMETAFILEPICT		"DspMetaFilePict"
+#define SZFMT_CPTEXT			"Codepage Text"
+
+typedef struct _CPTEXT
+{
+  USHORT idCountry;
+  USHORT usCodepage;
+  USHORT usLangID;
+  USHORT usSubLangID;
+  BYTE	 abText[1];
+} CPTEXT;
+typedef CPTEXT *PCPTEXT;
+
+typedef struct _MFP
+{
+  POINTL sizeBounds;
+  POINTL sizeMM;
+  ULONG	 cbLength;
+  USHORT mapMode;
+  USHORT reserved;
+  BYTE	 abData[1];
+} MFP;
+typedef MFP *PMFP;
+
+#endif /* INCL_WINCLIPBOARD || INCL_WINDDE */
+
+#if defined (INCL_WINCLIPBOARD)
+
+#define CFI_OWNERFREE			0x0001
+#define CFI_OWNERDISPLAY		0x0002
+#define CFI_HANDLE			0x0200
+#define CFI_POINTER			0x0400
+
+BOOL WinCloseClipbrd (HAB hab);
+BOOL WinEmptyClipbrd (HAB hab);
+ULONG WinEnumClipbrdFmts (HAB hab, ULONG fmt);
+BOOL WinOpenClipbrd (HAB hab);
+ULONG WinQueryClipbrdData (HAB hab, ULONG fmt);
+BOOL WinQueryClipbrdFmtInfo (HAB hab, ULONG fmt, PULONG prgfFmtInfo);
+HWND WinQueryClipbrdOwner (HAB hab);
+HWND WinQueryClipbrdViewer (HAB hab);
+BOOL WinSetClipbrdData (HAB hab, ULONG ulData, ULONG fmt, ULONG rgfFmtInfo);
+BOOL WinSetClipbrdOwner (HAB hab, HWND hwnd);
+BOOL WinSetClipbrdViewer (HAB hab, HWND hwndNewClipViewer);
+
+#endif /* INCL_WINCLIPBOARD */
+
+
+#if defined (INCL_WINDDE)
+
+#define WM_DDE_FIRST			0x00a0
+#define WM_DDE_INITIATE			0x00a0
+#define WM_DDE_REQUEST			0x00a1
+#define WM_DDE_ACK			0x00a2
+#define WM_DDE_DATA			0x00a3
+#define WM_DDE_ADVISE			0x00a4
+#define WM_DDE_UNADVISE			0x00a5
+#define WM_DDE_POKE			0x00a6
+#define WM_DDE_EXECUTE			0x00a7
+#define WM_DDE_TERMINATE		0x00a8
+#define WM_DDE_INITIATEACK		0x00a9
+#define WM_DDE_LAST			0x00af
+
+#define DDE_FACK			0x0001
+#define DDE_FBUSY			0x0002
+#define DDE_FNODATA			0x0004
+#define DDE_FACKREQ			0x0008
+#define DDE_FRESPONSE			0x0010
+#define DDE_NOTPROCESSED		0x0020
+#define DDE_FRESERVED			0x00c0
+#define DDE_FAPPSTATUS			0xff00
+
+#define DDECTXT_CASESENSITIVE		0x0001
+
+#define DDEFMT_TEXT			0x0001
+
+#define DDEPM_RETRY			0x0001
+#define DDEPM_NOFREE			0x0002
+
+#define SZDDESYS_TOPIC			"System"
+#define SZDDESYS_ITEM_TOPICS		"Topics"
+#define SZDDESYS_ITEM_SYSITEMS		"SysItems"
+#define SZDDESYS_ITEM_RTNMSG		"ReturnMessage"
+#define SZDDESYS_ITEM_STATUS		"Status"
+#define SZDDESYS_ITEM_FORMATS		"Formats"
+#define SZDDESYS_ITEM_SECURITY		"Security"
+#define SZDDESYS_ITEM_ITEMFORMATS	"ItemFormats"
+#define SZDDESYS_ITEM_HELP		"Help"
+#define SZDDESYS_ITEM_PROTOCOLS		"Protocols"
+#define SZDDESYS_ITEM_RESTART		"Restart"
+
+typedef struct _CONVCONTEXT
+{
+  ULONG cb;
+  ULONG fsContext;
+  ULONG idCountry;
+  ULONG usCodepage;
+  ULONG usLangID;
+  ULONG usSubLangID;
+} CONVCONTEXT;
+typedef CONVCONTEXT *PCONVCONTEXT;
+
+typedef struct _DDEINIT
+{
+  ULONG cb;
+  PSZ	pszAppName;
+  PSZ	pszTopic;
+  ULONG offConvContext;
+} DDEINIT;
+typedef DDEINIT *PDDEINIT;
+
+typedef struct _DDESTRUCT
+{
+  ULONG	 cbData;
+  USHORT fsStatus;
+  USHORT usFormat;
+  USHORT offszItemName;
+  USHORT offabData;
+} DDESTRUCT;
+typedef DDESTRUCT *PDDESTRUCT;
+
+#define DDES_PSZITEMNAME(pddes) \
+    (((PSZ)pddes) + ((PDDESTRUCT)pddes)->offszItemName)
+
+#define DDES_PABDATA(pddes) \
+    (((PBYTE)pddes) + ((PDDESTRUCT)pddes)->offabData)
+
+#define DDEI_PCONVCONTEXT(pddei) \
+    ((PCONVCONTEXT)((PBYTE)pddei + pddei->offConvContext))
+
+BOOL WinDdeInitiate (HWND hwndClient, PCSZ pszAppName, PCSZ pszTopicName,
+    __const__ CONVCONTEXT *pcctxt);
+BOOL WinDdePostMsg (HWND hwndTo, HWND hwndFrom, ULONG wm,
+    __const__ DDESTRUCT *pddest, ULONG flOptions);
+MRESULT WinDdeRespond (HWND hwndClient, HWND hwndServer, PCSZ pszAppName,
+    PCSZ pszTopicName, __const__ CONVCONTEXT *pcctxt);
+
+#endif /* INCL_WINDDE */
+
+
+#if defined (INCL_WINCOUNTRY)
+
+#define WCS_ERROR			0
+#define WCS_EQ				1
+#define WCS_LT				2
+#define WCS_GT				3
+
+ULONG WinCompareStrings (HAB hab, ULONG idcp, ULONG idcc, PCSZ psz1,
+    PCSZ psz2, ULONG reserved);
+UCHAR WinCpTranslateChar (HAB hab, ULONG cpSrc, UCHAR chSrc, ULONG cpDst);
+BOOL WinCpTranslateString (HAB hab, ULONG cpSrc, PCSZ pszSrc, ULONG cpDst,
+    ULONG cchDestMax, PSZ pchDest);
+PSZ WinNextChar (HAB hab, ULONG idcp, ULONG idcc, PCSZ psz);
+PSZ WinPrevChar (HAB hab, ULONG idcp, ULONG idcc, PCSZ pszStart,
+    PCSZ psz);
+ULONG WinQueryCp (HMQ hmq);
+ULONG WinQueryCpList (HAB hab, ULONG ccpMax, PULONG prgcp);
+BOOL WinSetCp (HMQ hmq, ULONG idCodePage);
+ULONG WinUpper (HAB hab, ULONG idcp, ULONG idcc, PSZ psz);
+ULONG WinUpperChar (HAB hab, ULONG idcp, ULONG idcc, ULONG c);
+
+#endif /* INCL_WINCOUNTRY */
+
+
+#if defined (INCL_WINCURSORS) || !defined (INCL_NOCOMMON)
+
+#define CURSOR_SOLID			0x0000
+#define CURSOR_HALFTONE			0x0001
+#define CURSOR_FRAME			0x0002
+#define CURSOR_FLASH			0x0004
+#define CURSOR_BIDI_FIRST		0x0100
+#define CURSOR_BIDI_LAST		0x0200
+#define CURSOR_SETPOS			0x8000
+
+BOOL WinCreateCursor (HWND hwnd, LONG x, LONG y, LONG cx, LONG cy,
+    ULONG fs, PRECTL prclClip);
+BOOL WinDestroyCursor (HWND hwnd);
+BOOL WinShowCursor (HWND hwnd, BOOL fShow);
+
+#endif /* INCL_WINCURSORS || !INCL_NOCOMMON */
+
+#if defined (INCL_WINCURSORS)
+
+typedef struct _CURSORINFO
+{
+  HWND	hwnd;
+  LONG	x;
+  LONG	y;
+  LONG	cx;
+  LONG	cy;
+  ULONG fs;
+  RECTL rclClip;
+} CURSORINFO;
+typedef CURSORINFO *PCURSORINFO;
+
+BOOL WinQueryCursorInfo (HWND hwndDesktop, PCURSORINFO pCursorInfo);
+
+#endif /* INCL_WINCURSORS */
+
+
+#if defined (INCL_WINDESKTOP)
+
+#define SDT_DESTROY			0x0001
+#define SDT_NOBKGND			0x0002
+#define SDT_TILE			0x0004
+#define SDT_SCALE			0x0008
+#define SDT_PATTERN			0x0010
+#define SDT_CENTER			0x0020
+#define SDT_RETAIN			0x0040
+#define SDT_LOADFILE			0x0080
+
+typedef struct _DESKTOP
+{
+  ULONG	  cbSize;
+  HBITMAP hbm;
+  LONG	  x;
+  LONG	  y;
+  ULONG	  fl;
+  LONG	  lTileCount;
+  CHAR	  szFile[260];
+} DESKTOP;
+typedef DESKTOP *PDESKTOP;
+
+BOOL WinQueryDesktopBkgnd (HWND hwndDesktop, PDESKTOP pdsk);
+HBITMAP WinSetDesktopBkgnd (HWND hwndDesktop, __const__ DESKTOP *pdskNew);
+
+#endif /* INCL_WINDESKTOP */
+
+
+#if defined (INCL_WINDIALOGS) || !defined (INCL_NOCOMMON)
+
+#define DID_OK				1
+#define DID_CANCEL			2
+#define DID_ERROR			0xffff
+
+#define MB_OK				0x0000
+#define MB_OKCANCEL			0x0001
+#define MB_RETRYCANCEL			0x0002
+#define MB_ABORTRETRYIGNORE		0x0003
+#define MB_YESNO			0x0004
+#define MB_YESNOCANCEL			0x0005
+#define MB_CANCEL			0x0006
+#define MB_ENTER			0x0007
+#define MB_ENTERCANCEL			0x0008
+
+#define MB_NOICON			0x0000
+#define MB_CUANOTIFICATION		0x0000
+#define MB_ICONQUESTION			0x0010
+#define MB_ICONEXCLAMATION		0x0020
+#define MB_CUAWARNING			0x0020
+#define MB_ICONASTERISK			0x0030
+#define MB_ICONHAND			0x0040
+#define MB_CUACRITICAL			0x0040
+#define MB_QUERY			MB_ICONQUESTION
+#define MB_WARNING			MB_CUAWARNING
+#define MB_INFORMATION			MB_ICONASTERISK
+#define MB_CRITICAL			MB_CUACRITICAL
+#define MB_ERROR			MB_CRITICAL
+#define MB_CUSTOMICON			0x0080
+
+#define MB_DEFBUTTON1			0x0000
+#define MB_DEFBUTTON2			0x0100
+#define MB_DEFBUTTON3			0x0200
+
+#define MB_APPLMODAL			0x0000
+#define MB_SYSTEMMODAL			0x1000
+#define MB_HELP				0x2000
+#define MB_MOVEABLE			0x4000
+#define MB_NONMODAL			0x8000
+
+#define MBID_OK				1
+#define MBID_CANCEL			2
+#define MBID_ABORT			3
+#define MBID_RETRY			4
+#define MBID_IGNORE			5
+#define MBID_YES			6
+#define MBID_NO				7
+#define MBID_HELP			8
+#define MBID_ENTER			9
+#define MBID_ERROR			0xffff
+
+#define WA_WARNING			0
+#define WA_NOTE				1
+#define WA_ERROR			2
+#define WA_CDEFALARMS			3
+
+#if 0 /* Multimedia */
+#define WA_WINDOWOPEN			3
+#define WA_WINDOWCLOSE			4
+#define WA_BEGINDRAG			5
+#define WA_ENDDRAG			6
+#define WA_STARTUP			7
+#define WA_SHUTDOWN			8
+#define WA_SHRED			9
+#define WA_CWINALARMS			13
+#endif /* 0 */
+
+#define MAX_MBDTEXT			70
+
+typedef struct _MB2D
+{
+  CHAR	achText[MAX_MBDTEXT+1];
+  CHAR	_pad[1];
+  ULONG idButton;
+  LONG	flStyle;
+} MB2D;
+typedef MB2D *PMB2D;
+
+typedef struct _MB2INFO
+{
+  ULONG	   cb;
+  HPOINTER hIcon;
+  ULONG	   cButtons;
+  ULONG	   flStyle;
+  HWND	   hwndNotify;
+  MB2D	   mb2d[1];
+} MB2INFO;
+
+typedef MB2INFO *PMB2INFO;
+
+
+#define WinCheckButton(hwndDlg,id,usCheckState) \
+    ((ULONG)WinSendDlgItemMsg (hwndDlg, id, BM_SETCHECK, \
+			       MPFROMSHORT (usCheckState), (MPARAM)NULL))
+
+#define WinEnableControl(hwndDlg,id,fEnable) \
+    WinEnableWindow (WinWindowFromID (hwndDlg, id), fEnable)
+
+#define WinIsControlEnabled(hwndDlg,id) \
+    ((BOOL)WinIsWindowEnabled (WinWindowFromID (hwndDlg, id)))
+
+#define WinQueryButtonCheckstate(hwndDlg,id) \
+    ((ULONG)WinSendDlgItemMsg (hwndDlg, id, BM_QUERYCHECK, \
+			       (MPARAM)NULL, (MPARAM)NULL))
+
+
+BOOL WinAlarm (HWND hwndDesktop, ULONG rgfType);
+MRESULT WinDefDlgProc (HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2);
+BOOL WinDismissDlg (HWND hwndDlg, ULONG usResult);
+ULONG WinDlgBox (HWND hwndParent, HWND hwndOwner, PFNWP pfnDlgProc,
+    HMODULE hmod, ULONG idDlg, PVOID pCreateParams);
+BOOL WinGetDlgMsg (HWND hwndDlg, PQMSG pqmsg);
+HWND WinLoadDlg (HWND hwndParent, HWND hwndOwner, PFNWP pfnDlgProc,
+    HMODULE hmod, ULONG idDlg, PVOID pCreateParams);
+ULONG WinMessageBox (HWND hwndParent, HWND hwndOwner, PCSZ pszText,
+    PCSZ pszCaption, ULONG idWindow, ULONG flStyle);
+ULONG WinMessageBox2 (HWND hwndParent, HWND hwndOwner, PCSZ pszText,
+    PCSZ pszCaption, ULONG idWindow, PMB2INFO pmb2info);
+BOOL WinQueryDlgItemShort (HWND hwndDlg, ULONG idItem, PSHORT pResult,
+    BOOL fSigned);
+ULONG WinQueryDlgItemText (HWND hwndDlg, ULONG idItem, LONG cchBufferMax,
+    PSZ pchBuffer);
+LONG WinQueryDlgItemTextLength (HWND hwndDlg, ULONG idItem);
+BOOL WinSetDlgItemShort (HWND hwndDlg, ULONG idItem, USHORT usValue,
+    BOOL fSigned);
+BOOL WinSetDlgItemText (HWND hwndDlg, ULONG idItem, PCSZ pszText);
+
+#endif /* INCL_WINDIALOGS || !defined (INCL_NOCOMMON) */
+
+
+#if defined (INCL_WINDIALOGS)
+
+#define DLGC_ENTRYFIELD			0x0001
+#define DLGC_BUTTON			0x0002
+#define DLGC_RADIOBUTTON		0x0004
+#define DLGC_STATIC			0x0008
+#define DLGC_DEFAULT			0x0010
+#define DLGC_PUSHBUTTON			0x0020
+#define DLGC_CHECKBOX			0x0040
+#define DLGC_SCROLLBAR			0x0080
+#define DLGC_MENU			0x0100
+#define DLGC_TABONCLICK			0x0200
+#define DLGC_MLE			0x0400
+
+#define EDI_FIRSTTABITEM		0
+#define EDI_LASTTABITEM			1
+#define EDI_NEXTTABITEM			2
+#define EDI_PREVTABITEM			3
+#define EDI_FIRSTGROUPITEM		4
+#define EDI_LASTGROUPITEM		5
+#define EDI_NEXTGROUPITEM		6
+#define EDI_PREVGROUPITEM		7
+
+typedef struct _DLGTITEM
+{
+  USHORT fsItemStatus;
+  USHORT cChildren;
+  USHORT cchClassName;
+  USHORT offClassName;
+  USHORT cchText;
+  USHORT offText;
+  ULONG	 flStyle;
+  SHORT	 x;
+  SHORT	 y;
+  SHORT	 cx;
+  SHORT	 cy;
+  USHORT id;
+  USHORT offPresParams;
+  USHORT offCtlData;
+} DLGTITEM;
+typedef DLGTITEM *PDLGTITEM;
+
+typedef struct _DLGTEMPLATE
+{
+  USHORT   cbTemplate;
+  USHORT   type;
+  USHORT   codepage;
+  USHORT   offadlgti;
+  USHORT   fsTemplateStatus;
+  USHORT   iItemFocus;
+  USHORT   coffPresParams;
+  DLGTITEM adlgti[1];
+} DLGTEMPLATE;
+typedef DLGTEMPLATE *PDLGTEMPLATE;
+
+
+HWND WinCreateDlg (HWND hwndParent, HWND hwndOwner, PFNWP pfnDlgProc,
+    PDLGTEMPLATE pdlgt, PVOID pCreateParams);
+HWND WinEnumDlgItem (HWND hwndDlg, HWND hwnd, ULONG code);
+BOOL WinMapDlgPoints (HWND hwndDlg, PPOINTL prgwptl, ULONG cwpt,
+    BOOL fCalcWindowCoords);
+ULONG WinProcessDlg (HWND hwndDlg);
+MRESULT WinSendDlgItemMsg (HWND hwndDlg, ULONG idItem, ULONG msg,
+    MPARAM mp1, MPARAM mp2);
+LONG WinSubstituteStrings (HWND hwnd, PCSZ pszSrc, LONG cchDstMax,
+    PSZ pszDst);
+
+#endif /* INCL_WINDIALOGS */
+
+
+#if defined (INCL_WINENTRYFIELDS)
+
+#define CBID_LIST			0x029a
+#define CBID_EDIT			0x029b
+
+#define CBM_SHOWLIST			0x0170
+#define CBM_HILITE			0x0171
+#define CBM_ISLISTSHOWING		0x0172
+
+#define CBN_EFCHANGE			1
+#define CBN_EFSCROLL			2
+#define CBN_MEMERROR			3
+#define CBN_LBSELECT			4
+#define CBN_LBSCROLL			5
+#define CBN_SHOWLIST			6
+#define CBN_ENTER			7
+
+#define CBS_SIMPLE			0x0001
+#define CBS_DROPDOWN			0x0002
+#define CBS_DROPDOWNLIST		0x0004
+#define CBS_COMPATIBLE			0x0008
+
+#define EM_QUERYCHANGED			0x0140
+#define EM_QUERYSEL			0x0141
+#define EM_SETSEL			0x0142
+#define EM_SETTEXTLIMIT			0x0143
+#define EM_CUT				0x0144
+#define EM_COPY				0x0145
+#define EM_CLEAR			0x0146
+#define EM_PASTE			0x0147
+#define EM_QUERYFIRSTCHAR		0x0148
+#define EM_SETFIRSTCHAR			0x0149
+#define EM_QUERYREADONLY		0x014a
+#define EM_SETREADONLY			0x014b
+#define EM_SETINSERTMODE		0x014c
+
+#define EN_SETFOCUS			0x0001
+#define EN_KILLFOCUS			0x0002
+#define EN_CHANGE			0x0004
+#define EN_SCROLL			0x0008
+#define EN_MEMERROR			0x0010
+#define EN_OVERFLOW			0x0020
+#define EN_INSERTMODETOGGLE		0x0040
+
+#define ES_LEFT				0x0000
+#define ES_CENTER			0x0001
+#define ES_RIGHT			0x0002
+#define ES_AUTOSCROLL			0x0004
+#define ES_MARGIN			0x0008
+#define ES_AUTOTAB			0x0010
+#define ES_READONLY			0x0020
+#define ES_COMMAND			0x0040
+#define ES_UNREADABLE			0x0080
+#define ES_AUTOSIZE			0x0200
+
+#if defined (INCL_NLS)
+#define ES_ANY				0x0000
+#define ES_SBCS				0x1000
+#define ES_DBCS				0x2000
+#define ES_MIXED			0x3000
+#endif /* INCL_NLS */
+
+typedef struct _COMBOCDATA
+{
+  ULONG cbSize;
+  ULONG reserved;
+  PVOID pHWXCtlData;
+} COMBOCDATA;
+typedef COMBOCDATA *PCOMBOCDATA;
+
+typedef struct _ENTRYFDATA
+{
+  USHORT cb;
+  USHORT cchEditLimit;
+  USHORT ichMinSel;
+  USHORT ichMaxSel;
+  PVOID	 pHWXCtlData;
+} ENTRYFDATA;
+typedef ENTRYFDATA *PENTRYFDATA;
+
+#endif /* INCL_WINENTRYFIELDS */
+
+
+#if defined (INCL_WINERRORS)
+
+typedef struct _ERRINFO
+{
+  ULONG	  cbFixedErrInfo;
+  ERRORID idError;
+  ULONG	  cDetailLevel;
+  ULONG	  offaoffszMsg;
+  ULONG	  offBinaryData;
+} ERRINFO;
+typedef ERRINFO *PERRINFO;
+
+ERRORID WinGetLastError (HAB hab);
+BOOL WinFreeErrorInfo (PERRINFO perrinfo);
+PERRINFO WinGetErrorInfo (HAB hab);
+
+#endif /* INCL_WINERRORS */
+
+
+#if defined (INCL_WINFRAMECTLS)
+
+#define TBM_SETHILITE			0x01e3
+#define TBM_QUERYHILITE			0x01e4
+
+#endif /* INCL_WINFRAMECTLS */
+
+
+#if defined (INCL_WINHOOKS)
+
+#define HK_SENDMSG			0
+#define HK_INPUT			1
+#define HK_MSGFILTER			2
+#define HK_JOURNALRECORD		3
+#define HK_JOURNALPLAYBACK		4
+#define HK_HELP				5
+#define HK_LOADER			6
+#define HK_REGISTERUSERMSG		7
+#define HK_MSGCONTROL			8
+#define HK_PLIST_ENTRY			9
+#define HK_PLIST_EXIT			10
+#define HK_FINDWORD			11
+#define HK_CODEPAGECHANGED		12
+#define HK_WINDOWDC			15
+#define HK_DESTROYWINDOW		16
+#define HK_CHECKMSGFILTER		20
+#define HK_MSGINPUT			21
+#define HK_ALARM			22
+#define HK_LOCKUP			23
+#define HK_FLUSHBUF			24
+
+#define HLPM_FRAME			(-1)
+#define HLPM_WINDOW			(-2)
+#define HLPM_MENU			(-3)
+
+#define HMQ_CURRENT		((HMQ)1)
+
+#define LHK_DELETEPROC			1
+#define LHK_DELETELIB			2
+#define LHK_LOADPROC			3
+#define LHK_LOADLIB			4
+
+#define MCHK_MSGINTEREST		1
+#define MCHK_CLASSMSGINTEREST		2
+#define MCHK_SYNCHRONISATION		3
+#define MCHK_MSGMODE			4
+
+#define MSGF_DIALOGBOX			1
+#define MSGF_MESSAGEBOX			2
+#define MSGF_DDEPOSTMSG			3
+#define MSGF_TRACK			8
+
+#define PM_MODEL_1X			0
+#define PM_MODEL_2X			1
+
+#define RUMHK_DATATYPE			1
+#define RUMHK_MSG			2
+
+
+typedef struct _SMHSTRUCT
+{
+  MPARAM mp2;
+  MPARAM mp1;
+  ULONG	 msg;
+  HWND	 hwnd;
+  ULONG	 model;
+} SMHSTRUCT;
+typedef SMHSTRUCT *PSMHSTRUCT;
+
+
+BOOL WinCallMsgFilter (HAB hab, PQMSG pqmsg, ULONG msgf);
+BOOL WinReleaseHook (HAB hab, HMQ hmq, LONG iHook, PFN pfnHook, HMODULE hmod);
+BOOL WinSetHook (HAB hab, HMQ hmq, LONG iHook, PFN pfnHook, HMODULE hmod);
+
+#endif /* INCL_WINHOOKS */
+
+
+#if defined (INCL_WININPUT) || !defined (INCL_NOCOMMON)
+
+#define FC_NOSETFOCUS			0x0001
+#define FC_NOBRINGTOTOP			0x0001 /*!*/
+#define FC_NOLOSEFOCUS			0x0002
+#define FC_NOBRINGTOPFIRSTWINDOW	0x0002 /*!*/
+#define FC_NOSETACTIVE			0x0004
+#define FC_NOLOSEACTIVE			0x0008
+#define FC_NOSETSELECTION		0x0010
+#define FC_NOLOSESELECTION		0x0020
+
+#define QFC_NEXTINCHAIN			0x0001
+#define QFC_ACTIVE			0x0002
+#define QFC_FRAME			0x0003
+#define QFC_SELECTACTIVE		0x0004
+#define QFC_PARTOFCHAIN			0x0005
+
+BOOL WinFocusChange (HWND hwndDesktop, HWND hwndSetFocus, ULONG flFocusChange);
+BOOL WinLockupSystem (HAB hab);
+BOOL WinSetFocus (HWND hwndDesktop, HWND hwndSetFocus);
+BOOL WinUnlockSystem (HAB hab, PCSZ pszPassword);
+
+#endif /* INCL_WININPUT || !INCL_NOCOMMON */
+
+
+#if defined (INCL_WININPUT)
+
+#define WM_MOUSEFIRST			0x0070
+#define WM_MOUSEMOVE			0x0070
+#define WM_BUTTONCLICKFIRST		0x0071
+#define WM_BUTTON1DOWN			0x0071
+#define WM_BUTTON1UP			0x0072
+#define WM_BUTTON1DBLCLK		0x0073
+#define WM_BUTTON2DOWN			0x0074
+#define WM_BUTTON2UP			0x0075
+#define WM_BUTTON2DBLCLK		0x0076
+#define WM_BUTTON3DOWN			0x0077
+#define WM_BUTTON3UP			0x0078
+#define WM_BUTTON3DBLCLK		0x0079
+#define WM_BUTTONCLICKLAST		0x0079
+#define WM_MOUSELAST			0x0079
+#define WM_CHAR				0x007a
+#define WM_VIOCHAR			0x007b
+#define WM_JOURNALNOTIFY		0x007c
+#define WM_MOUSEMAP			0x007d
+#define WM_VRNDISABLED			0x007e
+#define WM_VRNENABLED			0x007f
+
+#define WM_EXTMOUSEFIRST		0x0410
+#define WM_CHORD			0x0410
+#define WM_BUTTON1MOTIONSTART		0x0411
+#define WM_BUTTON1MOTIONEND		0x0412
+#define WM_BUTTON1CLICK			0x0413
+#define WM_BUTTON2MOTIONSTART		0x0414
+#define WM_BUTTON2MOTIONEND		0x0415
+#define WM_BUTTON2CLICK			0x0416
+#define WM_BUTTON3MOTIONSTART		0x0417
+#define WM_BUTTON3MOTIONEND		0x0418
+#define WM_BUTTON3CLICK			0x0419
+#define WM_EXTMOUSELAST			0x0419
+
+#define WM_MOUSETRANSLATEFIRST		0x0420
+#define WM_BEGINDRAG			0x0420
+#define WM_ENDDRAG			0x0421
+#define WM_SINGLESELECT			0x0422
+#define WM_OPEN				0x0423
+#define WM_CONTEXTMENU			0x0424
+#define WM_CONTEXTHELP			0x0425
+#define WM_TEXTEDIT			0x0426
+#define WM_BEGINSELECT			0x0427
+#define WM_ENDSELECT			0x0428
+#define WM_MOUSETRANSLATELAST		0x0428
+#define WM_PICKUP			0x0429
+
+#define WM_PENFIRST			0x0481
+#define WM_PENLAST			0x049f
+
+#define WM_MMPMFIRST			0x0500
+#define WM_MMPMLAST			0x05ff
+
+#define WM_BIDI_FIRST			0x0bd0
+#define WM_BIDI_LAST			0x0bff
+
+#define INP_NONE			0x0000
+#define INP_KBD				0x0001
+#define INP_MULT			0x0002
+#define INP_RES2			0x0004
+#define INP_SHIFT			0x0008
+#define INP_CTRL			0x0010
+#define INP_ALT				0x0020
+#define INP_RES3			0x0040
+#define INP_RES4			0x0080
+#define INP_IGNORE			0xffff
+
+#define JRN_QUEUESTATUS			0x0001
+#define JRN_PHYSKEYSTATE		0x0002
+
+#define KC_NONE				0x0000
+#define KC_CHAR				0x0001
+#define KC_VIRTUALKEY			0x0002
+#define KC_SCANCODE			0x0004
+#define KC_SHIFT			0x0008
+#define KC_CTRL				0x0010
+#define KC_ALT				0x0020
+#define KC_KEYUP			0x0040
+#define KC_PREVDOWN			0x0080
+#define KC_LONEKEY			0x0100
+#define KC_DEADKEY			0x0200
+#define KC_COMPOSITE			0x0400
+#define KC_INVALIDCOMP			0x0800
+#define KC_TOGGLE			0x1000
+#define KC_INVALIDCHAR			0x2000
+#define KC_DBCSRSRVD1			0x4000
+#define KC_DBCSRSRVD2			0x8000
+
+#define VK_BUTTON1			0x0001
+#define VK_BUTTON2			0x0002
+#define VK_BUTTON3			0x0003
+#define VK_BREAK			0x0004
+#define VK_BACKSPACE			0x0005
+#define VK_TAB				0x0006
+#define VK_BACKTAB			0x0007
+#define VK_NEWLINE			0x0008
+#define VK_SHIFT			0x0009
+#define VK_CTRL				0x000a
+#define VK_ALT				0x000b
+#define VK_ALTGRAF			0x000c
+#define VK_PAUSE			0x000d
+#define VK_CAPSLOCK			0x000e
+#define VK_ESC				0x000f
+#define VK_SPACE			0x0010
+#define VK_PAGEUP			0x0011
+#define VK_PAGEDOWN			0x0012
+#define VK_END				0x0013
+#define VK_HOME				0x0014
+#define VK_LEFT				0x0015
+#define VK_UP				0x0016
+#define VK_RIGHT			0x0017
+#define VK_DOWN				0x0018
+#define VK_PRINTSCRN			0x0019
+#define VK_INSERT			0x001a
+#define VK_DELETE			0x001b
+#define VK_SCRLLOCK			0x001c
+#define VK_NUMLOCK			0x001d
+#define VK_ENTER			0x001e
+#define VK_SYSRQ			0x001f
+#define VK_F1				0x0020
+#define VK_F2				0x0021
+#define VK_F3				0x0022
+#define VK_F4				0x0023
+#define VK_F5				0x0024
+#define VK_F6				0x0025
+#define VK_F7				0x0026
+#define VK_F8				0x0027
+#define VK_F9				0x0028
+#define VK_F10				0x0029
+#define VK_F11				0x002a
+#define VK_F12				0x002b
+#define VK_F13				0x002c
+#define VK_F14				0x002d
+#define VK_F15				0x002e
+#define VK_F16				0x002f
+#define VK_F17				0x0030
+#define VK_F18				0x0031
+#define VK_F19				0x0032
+#define VK_F20				0x0033
+#define VK_F21				0x0034
+#define VK_F22				0x0035
+#define VK_F23				0x0036
+#define VK_F24				0x0037
+#define VK_ENDDRAG			0x0038
+#define VK_CLEAR			0x0039
+#define VK_EREOF			0x003a
+#define VK_PA1				0x003b
+#define VK_ATTN				0x003c
+#define VK_CRSEL			0x003d
+#define VK_EXSEL			0x003e
+#define VK_COPY				0x003f
+#define VK_BLK1				0x0040
+#define VK_BLK2				0x0041
+
+#define VK_MENU				VK_F10
+
+#if defined (INCL_NLS)
+#define VK_DBCSFIRST			0x0080
+#define VK_DBCSLAST			0x00ff
+#define VK_BIDI_FIRST			0x00e0
+#define VK_BIDI_LAST			0x00ff
+#endif /* INCL_NLS */
+
+#define VK_USERFIRST			0x0100
+#define VK_USERLAST			0x01ff
+
+typedef struct _CHARMSG
+{
+  USHORT fs;
+  UCHAR	 cRepeat;
+  UCHAR	 scancode;
+  USHORT chr;
+  USHORT vkey;
+} CHRMSG;
+typedef CHRMSG *PCHRMSG;
+
+typedef struct _MOUSEMSG
+{
+  SHORT	 x;
+  SHORT	 y;
+  USHORT codeHitTest;
+  USHORT fsInp;
+} MSEMSG;
+typedef MSEMSG *PMSEMSG;
+
+#define CHARMSG(pmsg)		((PCHRMSG)((PBYTE)pmsg + sizeof (ULONG)))
+#define MOUSEMSG(pmsg)		((PMSEMSG)((PBYTE)pmsg + sizeof (ULONG)))
+
+BOOL WinCheckInput (HAB hab);
+BOOL WinEnablePhysInput (HWND hwndDesktop, BOOL fEnable);
+LONG WinGetKeyState (HWND hwndDesktop, LONG vkey);
+LONG WinGetPhysKeyState (HWND hwndDesktop, LONG sc);
+BOOL WinIsPhysInputEnabled (HWND hwndDesktop);
+HWND WinQueryCapture (HWND hwndDesktop);
+HWND WinQueryFocus (HWND hwndDesktop);
+ULONG WinQueryVisibleRegion (HWND hwnd, HRGN hrgn);
+BOOL WinSetCapture (HWND hwndDesktop, HWND hwnd);
+BOOL WinSetKeyboardStateTable (HWND hwndDesktop, PBYTE pKeyStateTable,
+    BOOL fSet);
+BOOL WinSetVisibleRegionNotify (HWND hwnd, BOOL fEnable);
+
+#endif /* INCL_WININPUT */
+
+
+#if defined (INCL_WINLISTBOXES)
+
+#define LS_MULTIPLESEL			0x0001
+#define LS_OWNERDRAW			0x0002
+#define LS_NOADJUSTPOS			0x0004
+#define LS_HORZSCROLL			0x0008
+#define LS_EXTENDEDSEL			0x0010
+
+#define LN_SELECT			1
+#define LN_SETFOCUS			2
+#define LN_KILLFOCUS			3
+#define LN_SCROLL			4
+#define LN_ENTER			5
+
+#define LM_QUERYITEMCOUNT		0x0160
+#define LM_INSERTITEM			0x0161
+#define LM_SETTOPINDEX			0x0162
+#define LM_DELETEITEM			0x0163
+#define LM_SELECTITEM			0x0164
+#define LM_QUERYSELECTION		0x0165
+#define LM_SETITEMTEXT			0x0166
+#define LM_QUERYITEMTEXTLENGTH		0x0167
+#define LM_QUERYITEMTEXT		0x0168
+#define LM_SETITEMHANDLE		0x0169
+#define LM_QUERYITEMHANDLE		0x016a
+#define LM_SEARCHSTRING			0x016b
+#define LM_SETITEMHEIGHT		0x016c
+#define LM_QUERYTOPINDEX		0x016d
+#define LM_DELETEALL			0x016e
+#define LM_INSERTMULTITEMS		0x016f
+#define LM_SETITEMWIDTH			0x0660 /* ? */
+
+#define LIT_CURSOR			(-4)
+#define LIT_ERROR			(-3)
+#define LIT_MEMERROR			(-2)
+#define LIT_NONE			(-1)
+#define LIT_FIRST			(-1)
+
+#define LIT_END				(-1)
+#define LIT_SORTASCENDING		(-2)
+#define LIT_SORTDESCENDING		(-3)
+
+#define LSS_SUBSTRING			0x0001
+#define LSS_PREFIX			0x0002
+#define LSS_CASESENSITIVE		0x0004
+
+
+typedef struct _LBOXINFO
+{
+  LONG	lItemIndex;
+  ULONG ulItemCount;
+  ULONG reserved;
+  ULONG reserved2;
+} LBOXINFO;
+typedef LBOXINFO *PLBOXINFO;
+
+
+#define WinDeleteLboxItem(hwndLbox,index) \
+    ((LONG)WinSendMsg (hwndLbox, LM_DELETEITEM, MPFROMLONG (index), \
+		       (MPARAM)NULL))
+
+#define WinInsertLboxItem(hwndLbox,index,psz) \
+    ((LONG)WinSendMsg (hwndLbox, LM_INSERTITEM, MPFROMLONG(index), \
+		       MPFROMP (psz)))
+
+#define WinQueryLboxCount(hwndLbox) \
+    ((LONG)WinSendMsg (hwndLbox, LM_QUERYITEMCOUNT, (MPARAM)NULL, \
+		       (MPARAM)NULL))
+
+#define WinQueryLboxItemText(hwndLbox,index,psz,cchMax) \
+    ((LONG)WinSendMsg (hwndLbox, LM_QUERYITEMTEXT, \
+		       MPFROM2SHORT((index), (cchMax)), MPFROMP (psz)))
+
+#define WinQueryLboxItemTextLength(hwndLbox,index) \
+    ((SHORT)WinSendMsg (hwndLbox, LM_QUERYITEMTEXTLENGTH, \
+			MPFROMSHORT (index), (MPARAM)NULL))
+
+#define WinQueryLboxSelectedItem(hwndLbox) \
+    ((LONG)WinSendMsg (hwndLbox, LM_QUERYSELECTION, MPFROMLONG (LIT_FIRST), \
+		       (MPARAM)NULL))
+
+#define WinSetLboxItemText(hwndLbox,index,psz) \
+    ((BOOL)WinSendMsg (hwndLbox, LM_SETITEMTEXT, \
+		       MPFROMLONG (index), MPFROMP (psz)))
+
+#endif /* INCL_WINLISTBOXES */
+
+
+#if defined (INCL_WINLOAD)
+
+BOOL WinDeleteLibrary (HAB hab, HLIB libhandle);
+BOOL WinDeleteProcedure (HAB hab, PFNWP wndproc);
+HLIB WinLoadLibrary (HAB hab, PCSZ libname);
+PFNWP WinLoadProcedure (HAB hab, HLIB libhandle, PSZ procname);
+
+#endif /* INCL_WINLOAD */
+
+
+#if defined (INCL_WINMENUS)
+
+#define MIA_NODISMISS			0x0020
+#define MIA_FRAMED			0x1000
+#define MIA_CHECKED			0x2000
+#define MIA_DISABLED			0x4000
+#define MIA_HILITED			0x8000
+
+#define MIS_TEXT			0x0001
+#define MIS_BITMAP			0x0002
+#define MIS_SEPARATOR			0x0004
+#define MIS_OWNERDRAW			0x0008
+#define MIS_SUBMENU			0x0010
+#define MIS_MULTMENU			0x0020
+#define MIS_SYSCOMMAND			0x0040
+#define MIS_HELP			0x0080
+#define MIS_STATIC			0x0100
+#define MIS_BUTTONSEPARATOR		0x0200
+#define MIS_BREAK			0x0400
+#define MIS_BREAKSEPARATOR		0x0800
+#define MIS_GROUP			0x1000
+#define MIS_SINGLE			0x2000
+
+#define MIT_END				(-1)
+#define MIT_NONE			(-1)
+#define MIT_MEMERROR			(-1)
+#define MIT_ERROR			(-1)
+#define MIT_FIRST			(-2)
+#define MIT_LAST			(-3)
+
+#define MM_INSERTITEM			0x0180
+#define MM_DELETEITEM			0x0181
+#define MM_QUERYITEM			0x0182
+#define MM_SETITEM			0x0183
+#define MM_QUERYITEMCOUNT		0x0184
+#define MM_STARTMENUMODE		0x0185
+#define MM_ENDMENUMODE			0x0186
+#define MM_REMOVEITEM			0x0188
+#define MM_SELECTITEM			0x0189
+#define MM_QUERYSELITEMID		0x018a
+#define MM_QUERYITEMTEXT		0x018b
+#define MM_QUERYITEMTEXTLENGTH		0x018c
+#define MM_SETITEMHANDLE		0x018d
+#define MM_SETITEMTEXT			0x018e
+#define MM_ITEMPOSITIONFROMID		0x018f
+#define MM_ITEMIDFROMPOSITION		0x0190
+#define MM_QUERYITEMATTR		0x0191
+#define MM_SETITEMATTR			0x0192
+#define MM_ISITEMVALID			0x0193
+#define MM_QUERYITEMRECT		0x0194
+
+#define MM_QUERYDEFAULTITEMID		0x0431
+#define MM_SETDEFAULTITEMID		0x0432
+
+#define MS_ACTIONBAR			0x0001
+#define MS_TITLEBUTTON			0x0002
+#define MS_VERTICALFLIP			0x0004
+#define MS_CONDITIONALCASCADE		0x0040
+
+#define PU_POSITIONONITEM		0x0001
+#define PU_HCONSTRAIN			0x0002
+#define PU_VCONSTRAIN			0x0004
+#define PU_NONE				0x0000
+#define PU_MOUSEBUTTON1DOWN		0x0008
+#define PU_MOUSEBUTTON2DOWN		0x0010
+#define PU_MOUSEBUTTON3DOWN		0x0018
+#define PU_SELECTITEM			0x0020
+#define PU_MOUSEBUTTON1			0x0040
+#define PU_MOUSEBUTTON2			0x0080
+#define PU_MOUSEBUTTON3			0x0100
+#define PU_KEYBOARD			0x0200
+
+typedef struct _MENUITEM
+{
+  SHORT	 iPosition;
+  USHORT afStyle;
+  USHORT afAttribute;
+  USHORT id;
+  HWND	 hwndSubMenu;
+  ULONG	 hItem;
+} MENUITEM;
+typedef MENUITEM *PMENUITEM;
+
+typedef struct _mti		/* Note 1 */
+{
+  USHORT afStyle;
+  USHORT pad;
+  USHORT idItem;
+  CHAR	 c[2];
+} MTI;
+
+typedef struct _mt		/* Note 1 */
+{
+  ULONG	 len;
+  USHORT codepage;
+  USHORT reserved;
+  USHORT cMti;
+  MTI	 rgMti[1];
+} MT;
+typedef MT *LPMT;
+
+typedef struct _OWNERITEM
+{
+  HWND	hwnd;
+  HPS	hps;
+  ULONG fsState;
+  ULONG fsAttribute;
+  ULONG fsStateOld;
+  ULONG fsAttributeOld;
+  RECTL rclItem;
+  LONG	idItem;
+  ULONG hItem;
+} OWNERITEM;
+typedef OWNERITEM *POWNERITEM;
+
+
+#define WinCheckMenuItem(hwndMenu,id,fcheck) \
+    ((BOOL)WinSendMsg (hwndMenu, MM_SETITEMATTR, \
+		       MPFROM2SHORT (id, TRUE), \
+		       MPFROM2SHORT (MIA_CHECKED, \
+				     ((USHORT)(fcheck) ? MIA_CHECKED : 0))))
+
+#define WinEnableMenuItem(hwndMenu,id,fEnable) \
+    ((BOOL)WinSendMsg (hwndMenu, MM_SETITEMATTR, MPFROM2SHORT (id, TRUE), \
+		       MPFROM2SHORT (MIA_DISABLED, \
+				     ((USHORT)(fEnable) ? 0 : MIA_DISABLED))))
+
+#define WinIsMenuItemChecked(hwndMenu,id) \
+    ((BOOL)WinSendMsg (hwndMenu, MM_QUERYITEMATTR, \
+		       MPFROM2SHORT (id, TRUE), \
+		       MPFROMLONG (MIA_CHECKED)))
+
+#define WinIsMenuItemEnabled(hwndMenu,id)  \
+    (!(BOOL)WinSendMsg (hwndMenu, MM_QUERYITEMATTR, \
+			MPFROM2SHORT (id, TRUE), \
+			MPFROMLONG (MIA_DISABLED)))
+
+#define WinIsMenuItemValid(hwndMenu,id) \
+    ((BOOL)WinSendMsg (hwndMenu, MM_ISITEMVALID, \
+		       MPFROM2SHORT (id, TRUE), MPFROMLONG (FALSE)))
+
+#define WinSetMenuItemText(hwndMenu,id,psz) \
+    ((BOOL)WinSendMsg (hwndMenu, MM_SETITEMTEXT, \
+		       MPFROMLONG (id), MPFROMP (psz)))
+
+
+HWND WinCreateMenu (HWND hwndParent, CPVOID lpmt);
+HWND WinLoadMenu (HWND hwndFrame, HMODULE hmod, ULONG idMenu);
+BOOL WinPopupMenu (HWND hwndParent, HWND hwndOwner, HWND hwndMenu,
+    LONG x, LONG y, LONG idItem, ULONG fs);
+
+#endif /* INCL_WINMENUS */
+
+
+#if defined (INCL_WINMESSAGEMGR)
+
+#define BMSG_POST			0x0000
+#define BMSG_SEND			0x0001
+#define BMSG_POSTQUEUE			0x0002
+#define BMSG_DESCENDANTS		0x0004
+#define BMSG_FRAMEONLY			0x0008
+
+#define CVR_ALIGNLEFT			0x0001
+#define CVR_ALIGNBOTTOM			0x0002
+#define CVR_ALIGNRIGHT			0x0004
+#define CVR_ALIGNTOP			0x0008
+#define CVR_REDRAW			0x0010
+
+#define HT_NORMAL			0
+#define HT_TRANSPARENT			(-1)
+#define HT_DISCARD			(-2)
+#define HT_ERROR			(-3)
+
+#define QS_KEY				0x0001
+#define QS_MOUSEBUTTON			0x0002
+#define QS_MOUSEMOVE			0x0004
+#define QS_MOUSE			0x0006
+#define QS_TIMER			0x0008
+#define QS_PAINT			0x0010
+#define QS_POSTMSG			0x0020
+#define QS_SEM1				0x0040
+#define QS_SEM2				0x0080
+#define QS_SEM3				0x0100
+#define QS_SEM4				0x0200
+#define QS_SENDMSG			0x0400
+#define QS_MSGINPUT			0x0800
+
+#define SMIM_ALL			0x0eff
+#define SMI_NOINTEREST			0x0001
+#define SMI_INTEREST			0x0002
+#define SMI_RESET			0x0004
+#define SMI_AUTODISPATCH		0x0008
+
+#define WPM_TEXT			0x0001
+#define WPM_CTLDATA			0x0002
+#define WPM_PRESPARAMS			0x0004
+#define WPM_CCHTEXT			0x0008
+#define WPM_CBCTLDATA			0x0010
+#define WPM_CBPRESPARAMS		0x0020
+
+
+typedef struct _WNDPARAMS
+{
+  ULONG fsStatus;
+  ULONG cchText;
+  PSZ	pszText;
+  ULONG cbPresParams;
+  PVOID pPresParams;
+  ULONG cbCtlData;
+  PVOID pCtlData;
+} WNDPARAMS;
+typedef WNDPARAMS *PWNDPARAMS;
+
+BOOL WinBroadcastMsg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2, ULONG rgf);
+BOOL WinInSendMsg (HAB hab);
+BOOL WinPostQueueMsg (HMQ hmq, ULONG msg, MPARAM mp1, MPARAM mp2);
+BOOL WinQueryMsgPos (HAB hab, PPOINTL pptl);
+ULONG WinQueryMsgTime (HAB hab);
+ULONG WinQueryQueueStatus (HWND hwndDesktop);
+ULONG WinRequestMutexSem (HMTX hmtx, ULONG ulTimeout);
+BOOL WinSetClassMsgInterest (HAB hab, PCSZ pszClassName, ULONG msg_class,
+    LONG control);
+BOOL WinSetMsgInterest (HWND hwnd, ULONG msg_class, LONG control);
+ULONG WinWaitEventSem (HEV hev, ULONG ulTimeout);
+BOOL WinWaitMsg (HAB hab, ULONG msgFirst, ULONG msgLast);
+ULONG WinWaitMuxWaitSem (HMUX hmux, ULONG ulTimeout, PULONG pulUser);
+
+#endif /* INCL_WINMESSAGEMGR */
+
+
+#if defined (INCL_WINPALETTE)
+
+LONG WinRealizePalette (HWND hwnd, HPS hps, PULONG pcclr);
+
+#endif /* INCL_WINPALETTE */
+
+
+#if defined (INCL_WINPOINTERS)
+
+#define DP_NORMAL			0x0000
+#define DP_HALFTONED			0x0001
+#define DP_INVERTED			0x0002
+#define DP_MINI				0x0004
+
+#define SBMP_OLD_SYSMENU		1
+#define SBMP_OLD_SBUPARROW		2
+#define SBMP_OLD_SBDNARROW		3
+#define SBMP_OLD_SBRGARROW		4
+#define SBMP_OLD_SBLFARROW		5
+#define SBMP_MENUCHECK			6
+#define SBMP_OLD_CHECKBOXES		7
+#define SBMP_BTNCORNERS			8
+#define SBMP_OLD_MINBUTTON		9
+#define SBMP_OLD_MAXBUTTON		10
+#define SBMP_OLD_RESTOREBUTTON		11
+#define SBMP_OLD_CHILDSYSMENU		12
+#define SBMP_DRIVE			15
+#define SBMP_FILE			16
+#define SBMP_FOLDER			17
+#define SBMP_TREEPLUS			18
+#define SBMP_TREEMINUS			19
+#define SBMP_PROGRAM			22
+#define SBMP_MENUATTACHED		23
+#define SBMP_SIZEBOX			24
+#define SBMP_SYSMENU			25
+#define SBMP_MINBUTTON			26
+#define SBMP_MAXBUTTON			27
+#define SBMP_RESTOREBUTTON		28
+#define SBMP_CHILDSYSMENU		29
+#define SBMP_SYSMENUDEP			30
+#define SBMP_MINBUTTONDEP		31
+#define SBMP_MAXBUTTONDEP		32
+#define SBMP_RESTOREBUTTONDEP		33
+#define SBMP_CHILDSYSMENUDEP		34
+#define SBMP_SBUPARROW			35
+#define SBMP_SBDNARROW			36
+#define SBMP_SBLFARROW			37
+#define SBMP_SBRGARROW			38
+#define SBMP_SBUPARROWDEP		39
+#define SBMP_SBDNARROWDEP		40
+#define SBMP_SBLFARROWDEP		41
+#define SBMP_SBRGARROWDEP		42
+#define SBMP_SBUPARROWDIS		43
+#define SBMP_SBDNARROWDIS		44
+#define SBMP_SBLFARROWDIS		45
+#define SBMP_SBRGARROWDIS		46
+#define SBMP_COMBODOWN			47
+#define SBMP_CHECKBOXES			48
+#define SBMP_HIDE			50
+#define SBMP_HIDEDEP			51
+#define SBMP_CLOSE			52
+#define SBMP_CLOSEDEP			53
+
+#define SPTR_ARROW			1
+#define SPTR_TEXT			2
+#define SPTR_WAIT			3
+#define SPTR_SIZE			4
+#define SPTR_MOVE			5
+#define SPTR_SIZENWSE			6
+#define SPTR_SIZENESW			7
+#define SPTR_SIZEWE			8
+#define SPTR_SIZENS			9
+#define SPTR_APPICON			10
+#define SPTR_ICONINFORMATION		11
+#define SPTR_ICONQUESTION		12
+#define SPTR_ICONERROR			13
+#define SPTR_ICONWARNING		14
+#define SPTR_ILLEGAL			18
+#define SPTR_FILE			19
+#define SPTR_FOLDER			20
+#define SPTR_MULTFILE			21
+#define SPTR_PROGRAM			22
+#define SPTR_DISPLAY_PTRS		22
+
+#define SPTR_PENFIRST			23
+#define SPTR_PENLAST			39
+#define SPTR_CPTR			39
+
+#define SPTR_HANDICON			SPTR_ICONERROR
+#define SPTR_QUESICON			SPTR_ICONQUESTION
+#define SPTR_BANGICON			SPTR_ICONWARNING
+#define SPTR_NOTEICON			SPTR_ICONINFORMATION
+
+typedef struct _POINTERINFO
+{
+  ULONG	  fPointer;
+  LONG	  xHotspot;
+  LONG	  yHotspot;
+  HBITMAP hbmPointer;
+  HBITMAP hbmColor;
+  HBITMAP hbmMiniPointer;
+  HBITMAP hbmMiniColor;
+} POINTERINFO;
+typedef POINTERINFO *PPOINTERINFO;
+
+
+HPOINTER WinCreatePointer (HWND hwndDesktop, HBITMAP hbmPointer, BOOL fPointer,
+    LONG xHotspot, LONG yHotspot);
+HPOINTER WinCreatePointerIndirect (HWND hwndDesktop,
+    __const__ POINTERINFO *pptri);
+BOOL WinDestroyPointer (HPOINTER hptr);
+BOOL WinDrawPointer (HPS hps, LONG x, LONG y, HPOINTER hptr, ULONG fs);
+HBITMAP WinGetSysBitmap (HWND hwndDesktop, ULONG ibm);
+HPOINTER WinLoadPointer (HWND hwndDesktop, HMODULE hmod, ULONG idres);
+BOOL WinLockPointerUpdate (HWND hwndDesktop, HPOINTER hptrNew,
+    ULONG ulTimeInterval);
+BOOL WinQueryPointerPos (HWND hwndDesktop, PPOINTL pptl);
+BOOL WinQueryPointerInfo (HPOINTER hptr, PPOINTERINFO pPointerInfo);
+HPOINTER WinQuerySysPointer (HWND hwndDesktop, LONG lId, BOOL fCopy);
+BOOL WinQuerySysPointerData (HWND hwndDesktop, ULONG ulId,
+    PICONINFO pIconInfo);
+BOOL WinSetPointer (HWND hwndDesktop, HPOINTER hptrNew);
+BOOL WinSetPointerOwner (HPOINTER hptr, PID pid, BOOL fDestroy);
+BOOL WinSetPointerPos (HWND hwndDesktop, LONG x, LONG y);
+BOOL WinSetSysPointerData (HWND hwndDesktop, ULONG ulId,
+    __const__ ICONINFO *pIconInfo);
+BOOL WinShowPointer (HWND hwndDesktop, BOOL fShow);
+
+#endif /* INCL_WINPOINTERS */
+
+
+#if defined (INCL_WINRECTANGLES)
+
+BOOL WinCopyRect (HAB hab, PRECTL prclDst, __const__ RECTL *prclSrc);
+BOOL WinEqualRect (HAB hab, __const__ RECTL *prcl1, __const__ RECTL *prcl2);
+BOOL WinInflateRect (HAB hab, PRECTL prcl, LONG cx, LONG cy);
+BOOL WinIntersectRect (HAB hab, PRECTL prclDst, __const__ RECTL *prclSrc1,
+    __const__ RECTL *prclSrc2);
+BOOL WinIsRectEmpty (HAB hab, __const__ RECTL *prcl);
+BOOL WinMakePoints (HAB hab, PPOINTL pwpt, ULONG cwpt);
+BOOL WinMakeRect (HAB hab, PRECTL pwrc);
+BOOL WinOffsetRect (HAB hab, PRECTL prcl, LONG cx, LONG cy);
+BOOL WinPtInRect (HAB hab, __const__ RECTL *prcl, __const__ POINTL *pptl);
+BOOL WinSetRect (HAB hab, PRECTL prcl, LONG xLeft, LONG yBottom, LONG xRight,
+    LONG yTop);
+BOOL WinSetRectEmpty (HAB hab, PRECTL prcl);
+BOOL WinSubtractRect (HAB hab, PRECTL prclDst, __const__ RECTL *prclSrc1,
+    __const__ RECTL *prclSrc2);
+BOOL WinUnionRect (HAB hab, PRECTL prclDst, __const__ RECTL *prclSrc1,
+    __const__ RECTL *prclSrc2);
+
+#endif /* INCL_WINRECTANGLES */
+
+
+#if defined (INCL_WINSCROLLBARS)
+
+#define SB_LINEUP			1
+#define SB_LINEDOWN			2
+#define SB_LINELEFT			1
+#define SB_LINERIGHT			2
+#define SB_PAGEUP			3
+#define SB_PAGEDOWN			4
+#define SB_PAGELEFT			3
+#define SB_PAGERIGHT			4
+#define SB_SLIDERTRACK			5
+#define SB_SLIDERPOSITION		6
+#define SB_ENDSCROLL			7
+
+#define SBM_SETSCROLLBAR		0x01a0
+#define SBM_SETPOS			0x01a1
+#define SBM_QUERYPOS			0x01a2
+#define SBM_QUERYRANGE			0x01a3
+#define SBM_SETTHUMBSIZE		0x01a6
+
+#define SBS_HORZ			0
+#define SBS_VERT			1
+#define SBS_THUMBSIZE			2
+#define SBS_AUTOTRACK			4
+#define SBS_AUTOSIZE			0x2000
+
+typedef struct _SBCDATA
+{
+  USHORT cb;
+  USHORT sHilite;
+  SHORT	 posFirst;
+  SHORT	 posLast;
+  SHORT	 posThumb;
+  SHORT	 cVisible;
+  SHORT	 cTotal;
+} SBCDATA;
+typedef SBCDATA *PSBCDATA;
+
+#endif /* INCL_WINSCROLLBARS */
+
+
+#if defined (INCL_WINSTATICS)
+
+#define SM_SETHANDLE			0x0100
+#define SM_QUERYHANDLE			0x0101
+
+#define SS_TEXT				0x0001
+#define SS_GROUPBOX			0x0002
+#define SS_ICON				0x0003
+#define SS_BITMAP			0x0004
+#define SS_FGNDRECT			0x0005
+#define SS_HALFTONERECT			0x0006
+#define SS_BKGNDRECT			0x0007
+#define SS_FGNDFRAME			0x0008
+#define SS_HALFTONEFRAME		0x0009
+#define SS_BKGNDFRAME			0x000a
+#define SS_SYSICON			0x000b
+#define SS_AUTOSIZE			0x0040
+
+#define WM_MSGBOXINIT			0x010e
+#define WM_MSGBOXDISMISS		0x010f
+
+#endif /* INCL_WINSTATICS */
+
+
+#if defined (INCL_WINSYS)
+
+#define CCF_GLOBAL			0x0000
+#define CCF_APPLICATION			0x0001
+#define CCF_COUNTCOLORS			0x0010
+#define CCF_ALLCOLORS			0x0020
+
+#define CCI_FOREGROUND			1
+#define CCI_FOREGROUNDREADONLY		2
+#define CCI_BACKGROUND			3
+#define CCI_BACKGROUNDDIALOG		4
+#define CCI_DISABLEDFOREGROUND		5
+#define CCI_DISABLEDFOREGROUNDREADONLY	6
+#define CCI_DISABLEDBACKGROUND		7
+#define CCI_DISABLEDBACKGROUNDDIALOG	8
+#define CCI_HIGHLIGHTFOREGROUND		9
+#define CCI_HIGHLIGHTBACKGROUND		10
+#define CCI_HIGHLIGHTBACKGROUNDDIALOG	11
+#define CCI_INACTIVEFOREGROUND		12
+#define CCI_INACTIVEFOREGROUNDDIALOG	13
+#define CCI_INACTIVEBACKGROUND		14
+#define CCI_INACTIVEBACKGROUNDTEXT	15
+#define CCI_ACTIVEFOREGROUND		16
+#define CCI_ACTIVEFOREGROUNDDIALOG	17
+#define CCI_ACTIVEBACKGROUND		18
+#define CCI_ACTIVEBACKGROUNDTEXT	19
+#define CCI_PAGEBACKGROUND		20
+#define CCI_PAGEFOREGROUND		21
+#define CCI_FIELDBACKGROUND		22
+#define CCI_BORDER			23
+#define CCI_BORDERLIGHT			24
+#define CCI_BORDERDARK			25
+#define CCI_BORDER2			26
+#define CCI_BORDER2LIGHT		27
+#define CCI_BORDER2DARK			28
+#define CCI_BORDERDEFAULT		29
+#define CCI_BUTTONBACKGROUND		30
+#define CCI_BUTTONFOREGROUND		31
+#define CCI_BUTTONBORDERLIGHT		32
+#define CCI_BUTTONBORDERDARK		33
+#define CCI_ARROW			34
+#define CCI_DISABLEDARROW		35
+#define CCI_ARROWBORDERLIGHT		36
+#define CCI_ARROWBORDERDARK		37
+#define CCI_CHECKLIGHT			38
+#define CCI_CHECKMIDDLE			39
+#define CCI_CHECKDARK			40
+#define CCI_ICONFOREGROUND		41
+#define CCI_ICONBACKGROUND		42
+#define CCI_ICONBACKGROUNDDESKTOP	43
+#define CCI_ICONHILITEFOREGROUND	44
+#define CCI_ICONHILITEBACKGROUND	45
+#define CCI_MAJORTABFOREGROUND		46
+#define CCI_MAJORTABBACKGROUND		47
+#define CCI_MINORTABFOREGROUND		48
+#define CCI_MINORTABBACKGROUND		49
+#define CCI_MAXINDEX			49
+
+#define CCT_STATIC			1
+#define CCT_STATICTEXT			2
+#define CCT_GROUPBOX			3
+#define CCT_PUSHBUTTON			4
+#define CCT_CHECKBOX			5
+#define CCT_RADIOBUTTON			6
+#define CCT_ENTRYFIELD			7
+#define CCT_LISTBOX			8
+#define CCT_COMBOBOX			9
+#define CCT_SCROLLBAR			10
+#define CCT_FRAME			11
+#define CCT_MENU			12
+#define CCT_TITLEBAR			13
+#define CCT_SPINBUTTON			14
+#define CCT_SLIDER			15
+#define CCT_CIRCULARSLIDER		16
+#define CCT_VALUESET			17
+#define CCT_MLE				18
+#define CCT_CONTAINER			19
+#define CCT_NOTEBOOK			20
+#define CCT_MAXTYPE			20
+
+#define CCV_NOTFOUND			(-1)
+#define CCV_IGNORE			(-2)
+#define CCV_DEFAULT			(-3)
+
+#define PP_FOREGROUNDCOLOR		1
+#define PP_FOREGROUNDCOLORINDEX		2
+#define PP_BACKGROUNDCOLOR		3
+#define PP_BACKGROUNDCOLORINDEX		4
+#define PP_HILITEFOREGROUNDCOLOR	5
+#define PP_HILITEFOREGROUNDCOLORINDEX	6
+#define PP_HILITEBACKGROUNDCOLOR	7
+#define PP_HILITEBACKGROUNDCOLORINDEX	8
+#define PP_DISABLEDFOREGROUNDCOLOR	9
+#define PP_DISABLEDFOREGROUNDCOLORINDEX 10
+#define PP_DISABLEDBACKGROUNDCOLOR	11
+#define PP_DISABLEDBACKGROUNDCOLORINDEX 12
+#define PP_BORDERCOLOR			13
+#define PP_BORDERCOLORINDEX		14
+#define PP_FONTNAMESIZE			15
+#define PP_FONTHANDLE			16
+#define PP_RESERVED			17
+#define PP_ACTIVECOLOR			18
+#define PP_ACTIVECOLORINDEX		19
+#define PP_INACTIVECOLOR		20
+#define PP_INACTIVECOLORINDEX		21
+#define PP_ACTIVETEXTFGNDCOLOR		22
+#define PP_ACTIVETEXTFGNDCOLORINDEX	23
+#define PP_ACTIVETEXTBGNDCOLOR		24
+#define PP_ACTIVETEXTBGNDCOLORINDEX	25
+#define PP_INACTIVETEXTFGNDCOLOR	26
+#define PP_INACTIVETEXTFGNDCOLORINDEX	27
+#define PP_INACTIVETEXTBGNDCOLOR	28
+#define PP_INACTIVETEXTBGNDCOLORINDEX	29
+#define PP_SHADOW			30
+#define PP_MENUFOREGROUNDCOLOR		31
+#define PP_MENUFOREGROUNDCOLORINDEX	32
+#define PP_MENUBACKGROUNDCOLOR		33
+#define PP_MENUBACKGROUNDCOLORINDEX	34
+#define PP_MENUHILITEFGNDCOLOR		35
+#define PP_MENUHILITEFGNDCOLORINDEX	36
+#define PP_MENUHILITEBGNDCOLOR		37
+#define PP_MENUHILITEBGNDCOLORINDEX	38
+#define PP_MENUDISABLEDFGNDCOLOR	39
+#define PP_MENUDISABLEDFGNDCOLORINDEX	40
+#define PP_MENUDISABLEDBGNDCOLOR	41
+#define PP_MENUDISABLEDBGNDCOLORINDEX	42
+#define PP_SHADOWTEXTCOLOR		43
+#define PP_SHADOWTEXTCOLORINDEX		44
+#define PP_SHADOWHILITEFGNDCOLOR	45
+#define PP_SHADOWHILITEFGNDCOLORINDEX	46
+#define PP_SHADOWHILITEBGNDCOLOR	47
+#define PP_SHADOWHILITEBGNDCOLORINDEX	48
+#define PP_ICONTEXTBACKGROUNDCOLOR	49
+#define PP_ICONTEXTBACKGROUNDCOLORINDEX	50
+#define PP_BORDERLIGHTCOLOR		51
+#define PP_BORDERDARKCOLOR		52
+#define PP_BORDER2COLOR			53
+#define PP_BORDER2LIGHTCOLOR		54
+#define PP_BORDER2DARKCOLOR		55
+#define PP_BORDERDEFAULTCOLOR		56
+#define PP_FIELDBACKGROUNDCOLOR		57
+#define PP_BUTTONBACKGROUNDCOLOR	58
+#define PP_BUTTONBORDERLIGHTCOLOR	59
+#define PP_BUTTONBORDERDARKCOLOR	60
+#define PP_ARROWCOLOR			61
+#define PP_ARROWBORDERLIGHTCOLOR	62
+#define PP_ARROWBORDERDARKCOLOR		63
+#define PP_ARROWDISABLEDCOLOR		64
+#define PP_CHECKLIGHTCOLOR		65
+#define PP_CHECKMIDDLECOLOR		66
+#define PP_CHECKDARKCOLOR		67
+#define PP_PAGEFOREGROUNDCOLOR		68
+#define PP_PAGEBACKGROUNDCOLOR		69
+#define PP_MAJORTABFOREGROUNDCOLOR	70
+#define PP_MAJORTABBACKGROUNDCOLOR	71
+#define PP_MINORTABFOREGROUNDCOLOR	72
+#define PP_MINORTABBACKGROUNDCOLOR	73
+
+#define PP_BIDI_FIRST			0x0100
+#define PP_BIDI_LAST			0x012f
+#define PP_USER				0x8000
+
+#define QPF_NOINHERIT			0x0001
+#define QPF_ID1COLORINDEX		0x0002
+#define QPF_ID2COLORINDEX		0x0004
+#define QPF_PURERGBCOLOR		0x0008
+#define QPF_VALIDFLAGS			0x000f
+
+#define SV_SWAPBUTTON			0
+#define SV_DBLCLKTIME			1
+#define SV_CXDBLCLK			2
+#define SV_CYDBLCLK			3
+#define SV_CXSIZEBORDER			4
+#define SV_CYSIZEBORDER			5
+#define SV_ALARM			6
+#define SV_CURSORRATE			9
+#define SV_FIRSTSCROLLRATE		10
+#define SV_SCROLLRATE			11
+#define SV_NUMBEREDLISTS		12
+#define SV_WARNINGFREQ			13
+#define SV_NOTEFREQ			14
+#define SV_ERRORFREQ			15
+#define SV_WARNINGDURATION		16
+#define SV_NOTEDURATION			17
+#define SV_ERRORDURATION		18
+#define SV_CXSCREEN			20
+#define SV_CYSCREEN			21
+#define SV_CXVSCROLL			22
+#define SV_CYHSCROLL			23
+#define SV_CYVSCROLLARROW		24
+#define SV_CXHSCROLLARROW		25
+#define SV_CXBORDER			26
+#define SV_CYBORDER			27
+#define SV_CXDLGFRAME			28
+#define SV_CYDLGFRAME			29
+#define SV_CYTITLEBAR			30
+#define SV_CYVSLIDER			31
+#define SV_CXHSLIDER			32
+#define SV_CXMINMAXBUTTON		33
+#define SV_CYMINMAXBUTTON		34
+#define SV_CYMENU			35
+#define SV_CXFULLSCREEN			36
+#define SV_CYFULLSCREEN			37
+#define SV_CXICON			38
+#define SV_CYICON			39
+#define SV_CXPOINTER			40
+#define SV_CYPOINTER			41
+#define SV_DEBUG			42
+#define SV_CMOUSEBUTTONS		43
+#define SV_CPOINTERBUTTONS		43
+#define SV_POINTERLEVEL			44
+#define SV_CURSORLEVEL			45
+#define SV_TRACKRECTLEVEL		46
+#define SV_CTIMERS			47
+#define SV_MOUSEPRESENT			48
+#define SV_CXBYTEALIGN			49
+#define SV_CXALIGN			49
+#define SV_CYBYTEALIGN			50
+#define SV_CYALIGN			50
+#define SV_DESKTOPWORKAREAYTOP		51
+#define SV_DESKTOPWORKAREAYBOTTOM	52
+#define SV_DESKTOPWORKAREAXRIGHT	53
+#define SV_DESKTOPWORKAREAXLEFT		54
+#define SV_NOTRESERVED			56
+#define SV_EXTRAKEYBEEP			57
+#define SV_SETLIGHTS			58
+#define SV_INSERTMODE			59
+#define SV_MENUROLLDOWNDELAY		64
+#define SV_MENUROLLUPDELAY		65
+#define SV_ALTMNEMONIC			66
+#define SV_TASKLISTMOUSEACCESS		67
+#define SV_CXICONTEXTWIDTH		68
+#define SV_CICONTEXTLINES		69
+#define SV_CHORDTIME			70
+#define SV_CXCHORD			71
+#define SV_CYCHORD			72
+#define SV_CXMOTIONSTART		73
+#define SV_CYMOTIONSTART		74
+#define SV_BEGINDRAG			75
+#define SV_ENDDRAG			76
+#define SV_SINGLESELECT			77
+#define SV_OPEN				78
+#define SV_CONTEXTMENU			79
+#define SV_CONTEXTHELP			80
+#define SV_TEXTEDIT			81
+#define SV_BEGINSELECT			82
+#define SV_ENDSELECT			83
+#define SV_BEGINDRAGKB			84
+#define SV_ENDDRAGKB			85
+#define SV_SELECTKB			86
+#define SV_OPENKB			87
+#define SV_CONTEXTMENUKB		88
+#define SV_CONTEXTHELPKB		89
+#define SV_TEXTEDITKB			90
+#define SV_BEGINSELECTKB		91
+#define SV_ENDSELECTKB			92
+#define SV_ANIMATION			93
+#define SV_ANIMATIONSPEED		94
+#define SV_MONOICONS			95
+#define SV_KBDALTERED			96
+#define SV_PRINTSCREEN			97
+#define SV_LOCKSTARTINPUT		98
+#define SV_DYNAMICDRAG			99
+#define SV_CSYSVALUES			100
+
+#define SYSCLR_SHADOWHILITEBGND		(-50)
+#define SYSCLR_SHADOWHILITEFGND		(-49)
+#define SYSCLR_SHADOWTEXT		(-48)
+#define SYSCLR_ENTRYFIELD		(-47)
+#define SYSCLR_MENUDISABLEDTEXT		(-46)
+#define SYSCLR_MENUHILITE		(-45)
+#define SYSCLR_MENUHILITEBGND		(-44)
+#define SYSCLR_PAGEBACKGROUND		(-43)
+#define SYSCLR_FIELDBACKGROUND		(-42)
+#define SYSCLR_BUTTONLIGHT		(-41)
+#define SYSCLR_BUTTONMIDDLE		(-40)
+#define SYSCLR_BUTTONDARK		(-39)
+#define SYSCLR_BUTTONDEFAULT		(-38)
+#define SYSCLR_TITLEBOTTOM		(-37)
+#define SYSCLR_SHADOW			(-36)
+#define SYSCLR_ICONTEXT			(-35)
+#define SYSCLR_DIALOGBACKGROUND		(-34)
+#define SYSCLR_HILITEFOREGROUND		(-33)
+#define SYSCLR_HILITEBACKGROUND		(-32)
+#define SYSCLR_INACTIVETITLETEXTBGND	(-31)
+#define SYSCLR_ACTIVETITLETEXTBGND	(-30)
+#define SYSCLR_INACTIVETITLETEXT	(-29)
+#define SYSCLR_ACTIVETITLETEXT		(-28)
+#define SYSCLR_OUTPUTTEXT		(-27)
+#define SYSCLR_WINDOWSTATICTEXT		(-26)
+#define SYSCLR_SCROLLBAR		(-25)
+#define SYSCLR_BACKGROUND		(-24)
+#define SYSCLR_ACTIVETITLE		(-23)
+#define SYSCLR_INACTIVETITLE		(-22)
+#define SYSCLR_MENU			(-21)
+#define SYSCLR_WINDOW			(-20)
+#define SYSCLR_WINDOWFRAME		(-19)
+#define SYSCLR_MENUTEXT			(-18)
+#define SYSCLR_WINDOWTEXT		(-17)
+#define SYSCLR_TITLETEXT		(-16)
+#define SYSCLR_ACTIVEBORDER		(-15)
+#define SYSCLR_INACTIVEBORDER		(-14)
+#define SYSCLR_APPWORKSPACE		(-13)
+#define SYSCLR_HELPBACKGROUND		(-12)
+#define SYSCLR_HELPTEXT			(-11)
+#define SYSCLR_HELPHILITE		(-10)
+
+#define SYSCLR_CSYSCOLORS		41
+
+#define WM_CTLCOLORCHANGE		0x0129
+#define WM_QUERYCTLTYPE			0x0130 /*0x012a?*/
+
+
+typedef struct _CTLCOLOR
+{
+  LONG clrIndex;
+  LONG clrValue;
+} CTLCOLOR;
+typedef CTLCOLOR *PCTLCOLOR;
+
+typedef struct _PARAM
+{
+  ULONG id;
+  ULONG cb;
+  BYTE	ab[1];
+} PARAM;
+typedef PARAM *NPPARAM;
+typedef PARAM *PPARAM;
+
+typedef struct _PRESPARAMS
+{
+  ULONG cb;
+  PARAM aparam[1];
+} PRESPARAMS;
+typedef PRESPARAMS *NPPRESPARAMS;
+typedef PRESPARAMS *PPRESPARAMS;
+
+
+LONG WinQueryControlColors (HWND hwnd, LONG clrType, ULONG flCtlColor,
+    ULONG cCtlColor, PCTLCOLOR pCtlColor);
+ULONG WinQueryPresParam (HWND hwnd, ULONG id1, ULONG id2, PULONG pulId,
+    ULONG cbBuf, PVOID pbBuf, ULONG fs);
+LONG WinQuerySysColor (HWND hwndDesktop, LONG clr, LONG lReserved);
+LONG WinQuerySysValue (HWND hwndDesktop, LONG iSysValue);
+BOOL WinRemovePresParam (HWND hwnd, ULONG id);
+LONG WinSetControlColors (HWND hwnd, LONG clrType, ULONG flCtlColor,
+    ULONG cCtlColor, PCTLCOLOR pCtlColor);
+BOOL WinSetPresParam (HWND hwnd, ULONG id, ULONG cbParam, PVOID pbParam);
+BOOL WinSetSysColors (HWND hwndDesktop, ULONG flOptions, ULONG flFormat,
+    LONG clrFirst, ULONG cclr, __const__ LONG *pclr);
+BOOL WinSetSysValue (HWND hwndDesktop, LONG iSysValue, LONG lValue);
+
+#endif /* INCL_WINSYS */
+
+
+#if defined (INCL_WINTHUNKAPI)
+
+PFN WinQueryClassThunkProc (PCSZ pszClassname);
+LONG WinQueryWindowModel (HWND hwnd);
+PFN WinQueryWindowThunkProc (HWND hwnd);
+BOOL WinSetClassThunkProc (PCSZ pszClassname, PFN pfnThunkProc);
+BOOL WinSetWindowThunkProc (HWND hwnd, PFN pfnThunkProc);
+
+#endif /* INCL_WINTHUNKAPI */
+
+
+#if defined (INCL_WINTIMER)
+
+#define TID_CURSOR			0xffff
+#define TID_SCROLL			0xfffe
+#define TID_FLASHWINDOW			0xfffd
+#define TID_USERMAX			0x7fff
+
+ULONG  WinGetCurrentTime (HAB hab);
+ULONG WinStartTimer (HAB hab, HWND hwnd, ULONG idTimer, ULONG dtTimeout);
+BOOL WinStopTimer (HAB hab, HWND hwnd, ULONG idTimer);
+
+#endif /* INCL_WINTIMER */
+
+#if defined (INCL_WINTRACKRECT)
+
+#define TF_LEFT				0x0001
+#define TF_TOP				0x0002
+#define TF_RIGHT			0x0004
+#define TF_BOTTOM			0x0008
+#define TF_SETPOINTERPOS		0x0010
+#define TF_GRID				0x0020
+#define TF_STANDARD			0x0040
+#define TF_ALLINBOUNDARY		0x0080
+#define TF_VALIDATETRACKRECT		0x0100
+#define TF_PARTINBOUNDARY		0x0200
+
+#define TF_MOVE				0x000f
+
+typedef struct _TRACKINFO
+{
+  LONG	 cxBorder;
+  LONG	 cyBorder;
+  LONG	 cxGrid;
+  LONG	 cyGrid;
+  LONG	 cxKeyboard;
+  LONG	 cyKeyboard;
+  RECTL	 rclTrack;
+  RECTL	 rclBoundary;
+  POINTL ptlMinTrackSize;
+  POINTL ptlMaxTrackSize;
+  ULONG	 fs;
+} TRACKINFO;
+typedef TRACKINFO *PTRACKINFO;
+
+BOOL WinShowTrackRect (HWND hwnd, BOOL fShow);
+BOOL WinTrackRect (HWND hwnd, HPS hps, PTRACKINFO pti);
+
+#endif /* INCL_WINTRACKRECT */
+
+/* -------------------- MULTIPLE LINE ENTRIES ----------------------------- */
+
+#if defined (INCL_WINMLE)
+
+#define MLS_WORDWRAP			0x0001
+#define MLS_BORDER			0x0002
+#define MLS_VSCROLL			0x0004
+#define MLS_HSCROLL			0x0008
+#define MLS_READONLY			0x0010
+#define MLS_IGNORETAB			0x0020
+#define MLS_DISABLEUNDO			0x0040
+
+#define MLFFMTRECT_FORMATRECT		0x0007
+#define MLFFMTRECT_LIMITHORZ		0x0001
+#define MLFFMTRECT_LIMITVERT		0x0002
+#define MLFFMTRECT_MATCHWINDOW		0x0004
+
+#define MLFIE_CFTEXT			0
+#define MLFIE_NOTRANS			1
+#define MLFIE_WINFMT			2
+#define MLFIE_RTF			3
+
+#define MLFEFR_RESIZE			0x0001
+#define MLFEFR_TABSTOP			0x0002
+#define MLFEFR_FONT			0x0004
+#define MLFEFR_TEXT			0x0008
+#define MLFEFR_WORDWRAP			0x0010
+#define MLFETL_TEXTBYTES		0x0020
+
+#define MLFMARGIN_LEFT			0x0001
+#define MLFMARGIN_BOTTOM		0x0002
+#define MLFMARGIN_RIGHT			0x0003
+#define MLFMARGIN_TOP			0x0004
+
+#define MLFQS_MINMAXSEL			0
+#define MLFQS_MINSEL			1
+#define MLFQS_MAXSEL			2
+#define MLFQS_ANCHORSEL			3
+#define MLFQS_CURSORSEL			4
+
+#define MLFCLPBD_TOOMUCHTEXT		0x0001
+#define MLFCLPBD_ERROR			0x0002
+
+#define MLFSEARCH_CASESENSITIVE		0x0001
+#define MLFSEARCH_SELECTMATCH		0x0002
+#define MLFSEARCH_CHANGEALL		0x0004
+
+#define MLM_SETTEXTLIMIT		0x01b0
+#define MLM_QUERYTEXTLIMIT		0x01b1
+#define MLM_SETFORMATRECT		0x01b2
+#define MLM_QUERYFORMATRECT		0x01b3
+#define MLM_SETWRAP			0x01b4
+#define MLM_QUERYWRAP			0x01b5
+#define MLM_SETTABSTOP			0x01b6
+#define MLM_QUERYTABSTOP		0x01b7
+#define MLM_SETREADONLY			0x01b8
+#define MLM_QUERYREADONLY		0x01b9
+
+#define MLM_QUERYCHANGED		0x01ba
+#define MLM_SETCHANGED			0x01bb
+#define MLM_QUERYLINECOUNT		0x01bc
+#define MLM_CHARFROMLINE		0x01bd
+#define MLM_LINEFROMCHAR		0x01be
+#define MLM_QUERYLINELENGTH		0x01bf
+#define MLM_QUERYTEXTLENGTH		0x01c0
+
+#define MLM_FORMAT			0x01c1
+#define MLM_SETIMPORTEXPORT		0x01c2
+#define MLM_IMPORT			0x01c3
+#define MLM_EXPORT			0x01c4
+#define MLM_DELETE			0x01c6
+#define MLM_QUERYFORMATLINELENGTH	0x01c7
+#define MLM_QUERYFORMATTEXTLENGTH	0x01c8
+#define MLM_INSERT			0x01c9
+
+#define MLM_SETSEL			0x01ca
+#define MLM_QUERYSEL			0x01cb
+#define MLM_QUERYSELTEXT		0x01cc
+
+#define MLM_QUERYUNDO			0x01cd
+#define MLM_UNDO			0x01ce
+#define MLM_RESETUNDO			0x01cf
+
+#define MLM_QUERYFONT			0x01d0
+#define MLM_SETFONT			0x01d1
+#define MLM_SETTEXTCOLOR		0x01d2
+#define MLM_QUERYTEXTCOLOR		0x01d3
+#define MLM_SETBACKCOLOR		0x01d4
+#define MLM_QUERYBACKCOLOR		0x01d5
+
+#define MLM_QUERYFIRSTCHAR		0x01d6
+#define MLM_SETFIRSTCHAR		0x01d7
+
+#define MLM_CUT				0x01d8
+#define MLM_COPY			0x01d9
+#define MLM_PASTE			0x01da
+#define MLM_CLEAR			0x01db
+
+#define MLM_ENABLEREFRESH		0x01dc
+#define MLM_DISABLEREFRESH		0x01dd
+
+#define MLM_SEARCH			0x01de
+#define MLM_QUERYIMPORTEXPORT		0x01df
+
+#define MLN_OVERFLOW			0x0001
+#define MLN_PIXHORZOVERFLOW		0x0002
+#define MLN_PIXVERTOVERFLOW		0x0003
+#define MLN_TEXTOVERFLOW		0x0004
+#define MLN_VSCROLL			0x0005
+#define MLN_HSCROLL			0x0006
+#define MLN_CHANGE			0x0007
+#define MLN_SETFOCUS			0x0008
+#define MLN_KILLFOCUS			0x0009
+#define MLN_MARGIN			0x000a
+#define MLN_SEARCHPAUSE			0x000b
+#define MLN_MEMERROR			0x000c
+#define MLN_UNDOOVERFLOW		0x000d
+#define MLN_CLPBDFAIL			0x000f
+
+
+typedef LONG IPT;
+typedef IPT *PIPT;
+typedef LONG PIX;
+typedef ULONG LINE;
+
+
+typedef struct _FORMATRECT	/* Note 1 */
+{
+  LONG cxFormat;
+  LONG cyFormat;
+} MLEFORMATRECT;
+typedef MLEFORMATRECT *PFORMATRECT;
+
+typedef struct _MLECTLDATA
+{
+  USHORT cbCtlData;
+  USHORT afIEFormat;
+  ULONG	 cchText;
+  IPT	 iptAnchor;
+  IPT	 iptCursor;
+  LONG	 cxFormat;
+  LONG	 cyFormat;
+  ULONG	 afFormatFlags;
+  PVOID	 pHWXCtlData;
+} MLECTLDATA;
+typedef MLECTLDATA *PMLECTLDATA;
+
+typedef struct _MLEOVERFLOW
+{
+  ULONG afErrInd;
+  LONG	nBytesOver;
+  LONG	pixHorzOver;
+  LONG	pixVertOver;
+} MLEOVERFLOW;
+typedef MLEOVERFLOW *POVERFLOW;
+
+typedef struct _MLEMARGSTRUCT
+{
+  USHORT afMargins;
+  USHORT usMouMsg;
+  IPT	 iptNear;
+} MLEMARGSTRUCT;
+typedef MLEMARGSTRUCT *PMARGSTRUCT;
+
+typedef struct _SEARCH		/* Note 1 */
+{
+  USHORT cb;
+  USHORT _pad;
+  PCHAR	 pchFind;
+  PCHAR	 pchReplace;
+  SHORT	 cchFind;
+  SHORT	 cchReplace;
+  IPT	 iptStart;
+  IPT	 iptStop;
+  USHORT cchFound;
+} MLE_SEARCHDATA;
+typedef MLE_SEARCHDATA *PMLE_SEARCHDATA;
+
+#endif /* INCL_WINMLE */
+
+/* --------------- GRAPHICS PROGRAMMING INTERFACE ------------------------- */
+
+#define GPI_ERROR			0
+#define GPI_OK				1
+#define GPI_ALTERROR			(-1)
+
+#define HRGN_ERROR			((HRGN)(-1))
+
+#define CLR_ERROR			(-255)
+#define CLR_NOINDEX			(-254)
+#define CLR_FALSE			(-5)
+#define CLR_TRUE			(-4)
+#define CLR_DEFAULT			(-3)
+#define CLR_WHITE			(-2)
+#define CLR_BLACK			(-1)
+#define CLR_BACKGROUND			0
+#define CLR_BLUE			1
+#define CLR_RED				2
+#define CLR_PINK			3
+#define CLR_GREEN			4
+#define CLR_CYAN			5
+#define CLR_YELLOW			6
+#define CLR_NEUTRAL			7
+#define CLR_DARKGRAY			8
+#define CLR_DARKBLUE			9
+#define CLR_DARKRED			10
+#define CLR_DARKPINK			11
+#define CLR_DARKGREEN			12
+#define CLR_DARKCYAN			13
+#define CLR_BROWN			14
+#define CLR_PALEGRAY			15
+
+#define RGB_ERROR			(-255)
+#define RGB_BLACK			0x00000000
+#define RGB_BLUE			0x000000ff
+#define RGB_GREEN			0x0000ff00
+#define RGB_CYAN			0x0000ffff
+#define RGB_RED				0x00ff0000
+#define RGB_PINK			0x00ff00ff
+#define RGB_YELLOW			0x00ffff00
+#define RGB_WHITE			0x00ffffff
+
+#define PRIM_LINE			1
+#define PRIM_CHAR			2
+#define PRIM_MARKER			3
+#define PRIM_AREA			4
+#define PRIM_IMAGE			5
+
+#define AM_ERROR			(-1)
+#define AM_PRESERVE			0
+#define AM_NOPRESERVE			1
+
+#define FM_ERROR			(-1)
+#define FM_DEFAULT			0
+#define FM_OR				1
+#define FM_OVERPAINT			2
+#define FM_LEAVEALONE			5
+
+#define FM_XOR				4
+#define FM_AND				6
+#define FM_SUBTRACT			7
+#define FM_MASKSRCNOT			8
+#define FM_ZERO				9
+#define FM_NOTMERGESRC			10
+#define FM_NOTXORSRC			11
+#define FM_INVERT			12
+#define FM_MERGESRCNOT			13
+#define FM_NOTCOPYSRC			14
+#define FM_MERGENOTSRC			15
+#define FM_NOTMASKSRC			16
+#define FM_ONE				17
+
+#define BM_ERROR			(-1)
+#define BM_DEFAULT			0
+#define BM_OR				1
+#define BM_OVERPAINT			2
+#define BM_LEAVEALONE			5
+
+#define BM_XOR				4
+#define BM_AND				6
+#define BM_SUBTRACT			7
+#define BM_MASKSRCNOT			8
+#define BM_ZERO				9
+#define BM_NOTMERGESRC			10
+#define BM_NOTXORSRC			11
+#define BM_INVERT			12
+#define BM_MERGESRCNOT			13
+#define BM_NOTCOPYSRC			14
+#define BM_MERGENOTSRC			15
+#define BM_NOTMASKSRC			16
+#define BM_ONE				17
+#define BM_SRCTRANSPARENT		18
+#define BM_DESTTRANSPARENT		19
+
+#define LINETYPE_ERROR			(-1)
+#define LINETYPE_DEFAULT		0
+#define LINETYPE_DOT			1
+#define LINETYPE_SHORTDASH		2
+#define LINETYPE_DASHDOT		3
+#define LINETYPE_DOUBLEDOT		4
+#define LINETYPE_LONGDASH		5
+#define LINETYPE_DASHDOUBLEDOT		6
+#define LINETYPE_SOLID			7
+#define LINETYPE_INVISIBLE		8
+#define LINETYPE_ALTERNATE		9
+
+#define LINEWIDTH_ERROR			(-1)
+#define LINEWIDTH_DEFAULT		0L
+#define LINEWIDTH_NORMAL		0x00010000
+#define LINEWIDTH_THICK			0x00020000
+
+#define LINEWIDTHGEOM_ERROR		(-1)
+
+#define LINEEND_ERROR			(-1)
+#define LINEEND_DEFAULT			0
+#define LINEEND_FLAT			1
+#define LINEEND_SQUARE			2
+#define LINEEND_ROUND			3
+
+#define LINEJOIN_ERROR			(-1)
+#define LINEJOIN_DEFAULT		0
+#define LINEJOIN_BEVEL			1
+#define LINEJOIN_ROUND			2
+#define LINEJOIN_MITRE			3
+
+#define CHDIRN_ERROR			(-1)
+#define CHDIRN_DEFAULT			0
+#define CHDIRN_LEFTRIGHT		1
+#define CHDIRN_TOPBOTTOM		2
+#define CHDIRN_RIGHTLEFT		3
+#define CHDIRN_BOTTOMTOP		4
+
+#define TA_NORMAL_HORIZ			0x0001
+#define TA_LEFT				0x0002
+#define TA_CENTER			0x0003
+#define TA_RIGHT			0x0004
+#define TA_STANDARD_HORIZ		0x0005
+#define TA_NORMAL_VERT			0x0100
+#define TA_TOP				0x0200
+#define TA_HALF				0x0300
+#define TA_BASE				0x0400
+#define TA_BOTTOM			0x0500
+#define TA_STANDARD_VERT		0x0600
+
+#define CM_ERROR			(-1)
+#define CM_DEFAULT			0
+#define CM_MODE1			1
+#define CM_MODE2			2
+#define CM_MODE3			3
+
+#define MARKSYM_ERROR			(-1)
+#define MARKSYM_DEFAULT			0
+#define MARKSYM_CROSS			1
+#define MARKSYM_PLUS			2
+#define MARKSYM_DIAMOND			3
+#define MARKSYM_SQUARE			4
+#define MARKSYM_SIXPOINTSTAR		5
+#define MARKSYM_EIGHTPOINTSTAR		6
+#define MARKSYM_SOLIDDIAMOND		7
+#define MARKSYM_SOLIDSQUARE		8
+#define MARKSYM_DOT			9
+#define MARKSYM_SMALLCIRCLE		10
+#define MARKSYM_BLANK			64
+
+#define TXTBOX_TOPLEFT			0
+#define TXTBOX_BOTTOMLEFT		1
+#define TXTBOX_TOPRIGHT			2
+#define TXTBOX_BOTTOMRIGHT		3
+#define TXTBOX_CONCAT			4
+#define TXTBOX_COUNT			5
+
+#define PVIS_ERROR			0
+#define PVIS_INVISIBLE			1
+#define PVIS_VISIBLE			2
+
+#define RVIS_ERROR			0
+#define RVIS_INVISIBLE			1
+#define RVIS_PARTIAL			2
+#define RVIS_VISIBLE			3
+
+#define FONT_DEFAULT			1
+#define FONT_MATCH			2
+
+#define LCIDT_FONT			6
+#define LCIDT_BITMAP			7
+
+#define LCID_ALL			(-1)
+
+#define CHS_OPAQUE			0x0001
+#define CHS_VECTOR			0x0002
+#define CHS_LEAVEPOS			0x0008
+#define CHS_CLIP			0x0010
+#define CHS_UNDERSCORE			0x0200
+#define CHS_STRIKEOUT			0x0400
+
+#define FWEIGHT_DONT_CARE		0
+#define FWEIGHT_ULTRA_LIGHT		1
+#define FWEIGHT_EXTRA_LIGHT		2
+#define FWEIGHT_LIGHT			3
+#define FWEIGHT_SEMI_LIGHT		4
+#define FWEIGHT_NORMAL			5
+#define FWEIGHT_SEMI_BOLD		6
+#define FWEIGHT_BOLD			7
+#define FWEIGHT_EXTRA_BOLD		8
+#define FWEIGHT_ULTRA_BOLD		9
+
+#define FWIDTH_DONT_CARE		0
+#define FWIDTH_ULTRA_CONDENSED		1
+#define FWIDTH_EXTRA_CONDENSED		2
+#define FWIDTH_CONDENSED		3
+#define FWIDTH_SEMI_CONDENSED		4
+#define FWIDTH_NORMAL			5
+#define FWIDTH_SEMI_EXPANDED		6
+#define FWIDTH_EXPANDED			7
+#define FWIDTH_EXTRA_EXPANDED		8
+#define FWIDTH_ULTRA_EXPANDED		9
+
+#define FTYPE_ITALIC			0x0001
+#define FTYPE_ITALIC_DONT_CARE		0x0002
+#define FTYPE_OBLIQUE			0x0004
+#define FTYPE_OBLIQUE_DONT_CARE		0x0008
+#define FTYPE_ROUNDED			0x0010
+#define FTYPE_ROUNDED_DONT_CARE		0x0020
+
+#define QFA_PUBLIC			1
+#define QFA_PRIVATE			2
+#define QFA_ERROR			GPI_ALTERROR
+
+#define QF_PUBLIC			0x0001
+#define QF_PRIVATE			0x0002
+#define QF_NO_GENERIC			0x0004
+#define QF_NO_DEVICE			0x0008
+
+#define QCD_LCT_FORMAT			0
+#define QCD_LCT_LOINDEX			1
+#define QCD_LCT_HIINDEX			2
+#define QCD_LCT_OPTIONS			3
+
+#define QLCT_ERROR			(-1)
+#define QLCT_RGB			(-2)
+
+#define QLCT_NOTLOADED			(-1)
+
+#define PAL_ERROR			(-1)
+
+#define PC_RESERVED			0x01
+#define PC_EXPLICIT			0x02
+#define PC_NOCOLLAPSE			0x04
+
+#define SCP_ALTERNATE			0
+#define SCP_WINDING			2
+#define SCP_AND				4
+#define SCP_RESET			0
+#define SCP_INCL			0
+#define SCP_EXCL			8
+
+#define MPATH_STROKE			6
+
+#define FPATH_ALTERNATE			0
+#define FPATH_WINDING			2
+#define FPATH_INCL			0
+#define FPATH_EXCL			8
+
+#define CVTC_WORLD			1
+#define CVTC_MODEL			2
+#define CVTC_DEFAULTPAGE		3
+#define CVTC_PAGE			4
+#define CVTC_DEVICE			5
+
+#define TRANSFORM_REPLACE		0
+#define TRANSFORM_ADD			1
+#define TRANSFORM_PREEMPT		2
+
+#define SEGEM_ERROR			0
+#define SEGEM_INSERT			1
+#define SEGEM_REPLACE			2
+
+#define POLYGON_NOBOUNDARY		0x0000
+#define POLYGON_BOUNDARY		0x0001
+
+#define POLYGON_ALTERNATE		0x0000
+#define POLYGON_WINDING			0x0002
+
+#define POLYGON_INCL			0x0000
+#define POLYGON_EXCL			0x0008
+
+#define POLYGON_FILL			0x0000
+#define POLYGON_NOFILL			0x0010
+
+#define LCOL_RESET			0x0001
+#define LCOL_REALIZABLE			0x0002
+#define LCOL_PURECOLOR			0x0004
+#define LCOL_OVERRIDE_DEFAULT_COLORS	0x0008
+#define LCOL_REALIZED			0x0010
+
+#define LCOLF_DEFAULT			0
+#define LCOLF_INDRGB			1
+#define LCOLF_CONSECRGB			2
+#define LCOLF_RGB			3
+#define LCOLF_PALETTE			4
+
+#define LCOLOPT_REALIZED		0x0001
+#define LCOLOPT_INDEX			0x0002
+
+#define BA_NOBOUNDARY			0
+#define BA_BOUNDARY			0x0001
+
+#define BA_ALTERNATE			0
+#define BA_WINDING			0x0002
+
+#define BA_INCL				0
+#define BA_EXCL				8
+
+#define DRO_FILL			1
+#define DRO_OUTLINE			2
+#define DRO_OUTLINEFILL			3
+
+#define PATSYM_ERROR			(-1)
+#define PATSYM_DEFAULT			0
+#define PATSYM_DENSE1			1
+#define PATSYM_DENSE2			2
+#define PATSYM_DENSE3			3
+#define PATSYM_DENSE4			4
+#define PATSYM_DENSE5			5
+#define PATSYM_DENSE6			6
+#define PATSYM_DENSE7			7
+#define PATSYM_DENSE8			8
+#define PATSYM_VERT			9
+#define PATSYM_HORIZ			10
+#define PATSYM_DIAG1			11
+#define PATSYM_DIAG2			12
+#define PATSYM_DIAG3			13
+#define PATSYM_DIAG4			14
+#define PATSYM_NOSHADE			15
+#define PATSYM_SOLID			16
+#define PATSYM_HALFTONE			17
+#define PATSYM_HATCH			18
+#define PATSYM_DIAGHATCH		19
+#define PATSYM_BLANK			64
+
+#define LCID_ERROR			(-1)
+#define LCID_DEFAULT			0
+
+#define CRGN_OR				1
+#define CRGN_COPY			2
+#define CRGN_XOR			4
+#define CRGN_AND			6
+#define CRGN_DIFF			7
+
+#define RGN_ERROR			0
+#define RGN_NULL			1
+#define RGN_RECT			2
+#define RGN_COMPLEX			3
+
+#define PRGN_ERROR			0
+#define PRGN_OUTSIDE			1
+#define PRGN_INSIDE			2
+
+#define RRGN_ERROR			0
+#define RRGN_OUTSIDE			1
+#define RRGN_PARTIAL			2
+#define RRGN_INSIDE			3
+
+#define EQRGN_ERROR			0
+#define EQRGN_NOTEQUAL			1
+#define EQRGN_EQUAL			2
+
+#define RECTDIR_LFRT_TOPBOT		1
+#define RECTDIR_RTLF_TOPBOT		2
+#define RECTDIR_LFRT_BOTTOP		3
+#define RECTDIR_RTLF_BOTTOP		4
+
+#define PMF_SEGBASE			0
+#define PMF_LOADTYPE			1
+#define PMF_RESOLVE			2
+#define PMF_LCIDS			3
+#define PMF_RESET			4
+#define PMF_SUPPRESS			5
+#define PMF_COLORTABLES			6
+#define PMF_COLORREALIZABLE		7
+#define PMF_DEFAULTS			8
+#define PMF_DELETEOBJECTS		9
+
+#define RS_DEFAULT			0
+#define RS_NODISCARD			1
+#define LC_DEFAULT			0
+#define LC_NOLOAD			1
+#define LC_LOADDISC			3
+#define LT_DEFAULT			0
+#define LT_NOMODIFY			1
+#define LT_ORIGINALVIEW			4
+#define RES_DEFAULT			0
+#define RES_NORESET			1
+#define RES_RESET			2
+#define SUP_DEFAULT			0
+#define SUP_NOSUPPRESS			1
+#define SUP_SUPPRESS			2
+#define CTAB_DEFAULT			0
+#define CTAB_NOMODIFY			1
+#define CTAB_REPLACE			3
+#define CTAB_REPLACEPALETTE		4
+#define CREA_DEFAULT			0
+#define CREA_REALIZE			1
+#define CREA_NOREALIZE			2
+#define CREA_DOREALIZE			3
+
+#define DDEF_DEFAULT			0
+#define DDEF_IGNORE			1
+#define DDEF_LOADDISC			3
+#define DOBJ_DEFAULT			0
+#define DOBJ_NODELETE			1
+#define DOBJ_DELETE			2
+#define RSP_DEFAULT			0
+#define RSP_NODISCARD			1
+
+#define LBB_COLOR			0x0001
+#define LBB_BACK_COLOR			0x0002
+#define LBB_MIX_MODE			0x0004
+#define LBB_BACK_MIX_MODE		0x0008
+#define LBB_WIDTH			0x0010
+#define LBB_GEOM_WIDTH			0x0020
+#define LBB_TYPE			0x0040
+#define LBB_END				0x0080
+#define LBB_JOIN			0x0100
+
+#define CBB_COLOR			0x0001
+#define CBB_BACK_COLOR			0x0002
+#define CBB_MIX_MODE			0x0004
+#define CBB_BACK_MIX_MODE		0x0008
+#define CBB_SET				0x0010
+#define CBB_MODE			0x0020
+#define CBB_BOX				0x0040
+#define CBB_ANGLE			0x0080
+#define CBB_SHEAR			0x0100
+#define CBB_DIRECTION			0x0200
+#define CBB_TEXT_ALIGN			0x0400
+#define CBB_EXTRA			0x0800
+#define CBB_BREAK_EXTRA			0x1000
+
+#define MBB_COLOR			0x0001
+#define MBB_BACK_COLOR			0x0002
+#define MBB_MIX_MODE			0x0004
+#define MBB_BACK_MIX_MODE		0x0008
+#define MBB_SET				0x0010
+#define MBB_SYMBOL			0x0020
+#define MBB_BOX				0x0040
+
+#define ABB_COLOR			0x0001
+#define ABB_BACK_COLOR			0x0002
+#define ABB_MIX_MODE			0x0004
+#define ABB_BACK_MIX_MODE		0x0008
+#define ABB_SET				0x0010
+#define ABB_SYMBOL			0x0020
+#define ABB_REF_POINT			0x0040
+
+#define IBB_COLOR			0x0001
+#define IBB_BACK_COLOR			0x0002
+#define IBB_MIX_MODE			0x0004
+#define IBB_BACK_MIX_MODE		0x0008
+
+
+typedef PVOID PBUNDLE;
+
+typedef LONG FIXED;
+typedef FIXED *PFIXED;
+
+typedef LHANDLE HMF;
+typedef HMF *PHMF;
+
+
+typedef struct _SIZEL
+{
+  LONG cx;
+  LONG cy;
+} SIZEL;
+typedef SIZEL *PSIZEL;
+
+typedef struct _RGNRECT
+{
+  ULONG ircStart;
+  ULONG crc;
+  ULONG crcReturned;
+  ULONG ulDirection;
+} RGNRECT;
+typedef RGNRECT *PRGNRECT;
+
+typedef struct _MATRIXLF
+{
+  FIXED fxM11;
+  FIXED fxM12;
+  LONG	lM13;
+  FIXED fxM21;
+  FIXED fxM22;
+  LONG	lM23;
+  LONG	lM31;
+  LONG	lM32;
+  LONG	lM33;
+} MATRIXLF;
+typedef MATRIXLF *PMATRIXLF;
+
+typedef struct _ARCPARAMS
+{
+  LONG lP;
+  LONG lQ;
+  LONG lR;
+  LONG lS;
+} ARCPARAMS;
+typedef ARCPARAMS *PARCPARAMS;
+
+typedef struct _SIZEF
+{
+  FIXED cx;
+  FIXED cy;
+} SIZEF;
+typedef SIZEF *PSIZEF;
+
+typedef struct _POLYGON
+{
+  ULONG	  ulPoints;
+  PPOINTL aPointl;
+} POLYGON;
+typedef POLYGON *PPOLYGON;
+
+typedef struct _POLYSET
+{
+  ULONG	  ulPolys;
+  POLYGON aPolygon[1];
+} POLYSET;
+typedef POLYSET *PPOLYSET;
+
+typedef struct _GRADIENTL
+{
+  LONG x;
+  LONG y;
+} GRADIENTL;
+typedef GRADIENTL *PGRADIENTL;
+
+typedef struct _KERNINGPAIRS
+{
+  SHORT sFirstChar;
+  SHORT sSecondChar;
+  LONG	lKerningAmount;
+} KERNINGPAIRS;
+typedef KERNINGPAIRS *PKERNINGPAIRS;
+
+typedef struct _FACENAMEDESC
+{
+  USHORT usSize;
+  USHORT usWeightClass;
+  USHORT usWidthClass;
+  USHORT usReserved;
+  ULONG	 flOptions;
+} FACENAMEDESC;
+typedef FACENAMEDESC *PFACENAMEDESC;
+
+typedef CHAR FFDESCS[2][FACESIZE];
+typedef FFDESCS *PFFDESCS;
+
+typedef struct _FFDESCS2
+{
+  ULONG cbLength;
+  ULONG cbFacenameOffset;
+  BYTE	abFamilyName[1];
+} FFDESCS2;
+typedef FFDESCS2 *PFFDESCS2;
+
+
+typedef struct _LINEBUNDLE
+{
+  LONG	 lColor;
+  LONG	 lBackColor;
+  USHORT usMixMode;
+  USHORT usBackMixMode;
+  FIXED	 fxWidth;
+  LONG	 lGeomWidth;
+  USHORT usType;
+  USHORT usEnd;
+  USHORT usJoin;
+  USHORT usReserved;
+} LINEBUNDLE;
+typedef LINEBUNDLE *PLINEBUNDLE;
+
+typedef struct _CHARBUNDLE
+{
+  LONG	 lColor;
+  LONG	 lBackColor;
+  USHORT usMixMode;
+  USHORT usBackMixMode;
+  USHORT usSet;
+  USHORT usPrecision;
+  SIZEF	 sizfxCell;
+  POINTL ptlAngle;
+  POINTL ptlShear;
+  USHORT usDirection;
+  USHORT usTextAlign;
+  FIXED	 fxExtra;
+  FIXED	 fxBreakExtra;
+} CHARBUNDLE;
+typedef CHARBUNDLE *PCHARBUNDLE;
+
+typedef struct _MARKERBUNDLE
+{
+  LONG	 lColor;
+  LONG	 lBackColor;
+  USHORT usMixMode;
+  USHORT usBackMixMode;
+  USHORT usSet;
+  USHORT usSymbol;
+  SIZEF	 sizfxCell;
+} MARKERBUNDLE;
+typedef MARKERBUNDLE *PMARKERBUNDLE;
+
+typedef struct _AREABUNDLE
+{
+  LONG	 lColor;
+  LONG	 lBackColor;
+  USHORT usMixMode;
+  USHORT usBackMixMode;
+  USHORT usSet;
+  USHORT usSymbol;
+  POINTL ptlRefPoint;
+} AREABUNDLE;
+typedef AREABUNDLE *PAREABUNDLE;
+
+typedef struct _IMAGEBUNDLE
+{
+  LONG	 lColor;
+  LONG	 lBackColor;
+  USHORT usMixMode;
+  USHORT usBackMixMode;
+} IMAGEBUNDLE;
+typedef IMAGEBUNDLE *PIMAGEBUNDLE;
+
+
+#define MAKEFIXED(i,f) MAKELONG(f,i)
+#define FIXEDFRAC(fx)  (LOUSHORT(fx))
+#define FIXEDINT(fx)   ((SHORT)HIUSHORT(fx))
+
+
+LONG GpiAnimatePalette (HPAL hpal, ULONG ulFormat, ULONG ulStart,
+    ULONG ulCount, __const__ ULONG *aulTable);
+BOOL GpiBeginArea (HPS hps, ULONG flOptions);
+BOOL GpiBeginElement (HPS hps, LONG lType, PCSZ pszDesc);
+BOOL GpiBeginPath (HPS hps, LONG lPath);
+LONG GpiBox (HPS hps, LONG lControl, __const__ POINTL *pptlPoint, LONG lHRound,
+    LONG lVRound);
+LONG GpiCallSegmentMatrix (HPS hps, LONG lSegment, LONG lCount,
+    __const__ MATRIXLF *pmatlfArray, LONG lOptions);
+LONG GpiCharString (HPS hps, LONG lCount, PCCH pchString);
+LONG GpiCharStringAt (HPS hps, __const__ POINTL *pptlPoint, LONG lCount,
+     PCCH pchString);
+LONG GpiCharStringPos (HPS hps, __const__ RECTL *prclRect, ULONG flOptions,
+    LONG lCount, PCCH pchString, __const__ LONG *alAdx);
+LONG  GpiCharStringPosAt (HPS hps, __const__ POINTL *pptlStart,
+    __const__ RECTL *prclRect, ULONG flOptions, LONG lCount, PCCH pchString,
+    __const__ LONG *alAdx);
+BOOL GpiCloseFigure (HPS hps);
+LONG GpiCombineRegion (HPS hps, HRGN hrgnDest, HRGN hrgnSrc1, HRGN hrgnSrc2,
+    LONG lMode);
+BOOL GpiComment (HPS hps, LONG lLength, __const__ BYTE *pbData);
+BOOL GpiConvert (HPS hps, LONG lSrc, LONG lTarg, LONG lCount,
+    PPOINTL aptlPoints);
+BOOL GpiConvertWithMatrix (HPS hps, LONG lCountp, PPOINTL aptlPoints,
+    LONG lCount, __const__ MATRIXLF *pmatlfArray);
+HMF GpiCopyMetaFile (HMF hmf);
+BOOL GpiCreateLogColorTable (HPS hps, ULONG flOptions, LONG lFormat,
+    LONG lStart, LONG lCount, __const__ LONG *alTable);
+LONG GpiCreateLogFont (HPS hps, __const__ STR8 *pName, LONG lLcid,
+    __const__ FATTRS *pfatAttrs);
+HPAL GpiCreatePalette (HAB hab, ULONG flOptions, ULONG ulFormat,
+    ULONG ulCount, __const__ ULONG *aulTable);
+HRGN GpiCreateRegion (HPS hps, LONG lCount, __const__ RECTL *arclRectangles);
+BOOL GpiDeleteElement (HPS hps);
+BOOL GpiDeleteElementRange (HPS hps, LONG lFirstElement, LONG lLastElement);
+BOOL GpiDeleteElementsBetweenLabels (HPS hps, LONG lFirstLabel,
+    LONG lLastLabel);
+BOOL GpiDeleteMetaFile (HMF hmf);
+BOOL GpiDeletePalette (HPAL hpal);
+BOOL GpiDeleteSetId (HPS hps, LONG lLcid);
+BOOL GpiDestroyRegion (HPS hps, HRGN hrgn);
+LONG GpiElement (HPS hps, LONG lType, PCSZ pszDesc, LONG lLength,
+    __const__ BYTE *pbData);
+LONG GpiEndArea (HPS hps);
+BOOL GpiEndElement (HPS hps);
+BOOL GpiEndPath (HPS hps);
+LONG GpiEqualRegion (HPS hps, HRGN hrgnSrc1, HRGN hrgnSrc2);
+LONG GpiExcludeClipRectangle (HPS hps, __const__ RECTL *prclRectangle);
+LONG GpiFillPath (HPS hps, LONG lPath, LONG lOptions);
+LONG GpiFrameRegion (HPS hps, HRGN hrgn, __const__ SIZEL *thickness);
+LONG GpiFullArc (HPS hps, LONG lControl, FIXED fxMultiplier);
+LONG GpiImage (HPS hps, LONG lFormat, __const__ SIZEL *psizlImageSize,
+    LONG lLength, __const__ BYTE *pbData);
+LONG GpiIntersectClipRectangle (HPS hps, __const__ RECTL *prclRectangle);
+BOOL GpiLabel (HPS hps, LONG lLabel);
+LONG GpiLine (HPS hps, __const__ POINTL *pptlEndPoint);
+BOOL GpiLoadFonts (HAB hab, PCSZ pszFilename);
+HMF GpiLoadMetaFile (HAB hab, PCSZ pszFilename);
+BOOL GpiLoadPublicFonts (HAB hab, PCSZ pszFileName);
+LONG GpiMarker (HPS hps, __const__ POINTL *pptlPoint);
+BOOL GpiModifyPath (HPS hps, LONG lPath, LONG lMode);
+BOOL GpiMove (HPS hps, __const__ POINTL *pptlPoint);
+LONG GpiOffsetClipRegion (HPS hps, __const__ POINTL *pptlPoint);
+BOOL GpiOffsetElementPointer (HPS hps, LONG loffset);
+BOOL GpiOffsetRegion (HPS hps, HRGN Hrgn, __const__ POINTL *pptlOffset);
+LONG GpiOutlinePath (HPS hps, LONG lPath, LONG lOptions);
+LONG GpiPaintRegion (HPS hps, HRGN hrgn);
+LONG GpiPartialArc (HPS hps, __const__ POINTL *pptlCenter, FIXED fxMultiplier,
+    FIXED fxStartAngle, FIXED fxSweepAngle);
+HRGN GpiPathToRegion (HPS GpiH, LONG lPath, LONG lOptions);
+LONG GpiPlayMetaFile (HPS hps, HMF hmf, LONG lCount1,
+    __const__ LONG *alOptarray, PLONG plSegCount, LONG lCount2, PSZ pszDesc);
+LONG GpiPointArc (HPS hps, __const__ POINTL *pptl2);
+LONG GpiPolyFillet (HPS hps, LONG lCount, __const__ POINTL *aptlPoints);
+LONG GpiPolyFilletSharp (HPS hps, LONG lCount, __const__ POINTL *aptlPoints,
+    __const__ FIXED *afxPoints);
+LONG GpiPolygons (HPS hps, ULONG ulCount, __const__ POLYGON *paplgn,
+    ULONG flOptions, ULONG flModel);
+LONG GpiPolyLine (HPS hps, LONG lCount, __const__ POINTL *aptlPoints);
+LONG GpiPolyLineDisjoint (HPS hps, LONG lCount, __const__ POINTL *aptlPoints);
+LONG GpiPolyMarker (HPS hps, LONG lCount, __const__ POINTL *aptlPoints);
+LONG GpiPolySpline (HPS hps, LONG lCount, __const__ POINTL *aptlPoints);
+BOOL GpiPop (HPS hps, LONG lCount);
+LONG GpiPtInRegion (HPS hps, HRGN hrgn, __const__ POINTL *pptlPoint);
+LONG GpiPtVisible (HPS hps, __const__ POINTL *pptlPoint);
+BOOL GpiQueryArcParams (HPS hps, PARCPARAMS parcpArcParams);
+LONG GpiQueryAttrMode (HPS hps);
+LONG GpiQueryAttrs (HPS hps, LONG lPrimType, ULONG flAttrMask,
+    PBUNDLE ppbunAttrs);
+LONG GpiQueryBackColor (HPS hps);
+LONG GpiQueryBackMix (HPS hps);
+BOOL GpiQueryCharAngle (HPS hps, PGRADIENTL pgradlAngle);
+BOOL GpiQueryCharBox (HPS hps, PSIZEF psizfxSize);
+BOOL GpiQueryCharBreakExtra (HPS hps, PFIXED BreakExtra);
+LONG GpiQueryCharDirection (HPS hps);
+BOOL GpiQueryCharExtra (HPS hps, PFIXED Extra);
+LONG GpiQueryCharMode (HPS hps);
+LONG GpiQueryCharSet (HPS hps);
+BOOL GpiQueryCharShear (HPS hps, PPOINTL pptlShear);
+BOOL GpiQueryCharStringPos (HPS hps, ULONG flOptions, LONG lCount,
+    PCCH pchString, PLONG alXincrements, PPOINTL aptlPositions);
+BOOL GpiQueryCharStringPosAt (HPS hps, PPOINTL pptlStart, ULONG flOptions,
+    LONG lCount, PCCH pchString, PLONG alXincrements, PPOINTL aptlPositions);
+LONG GpiQueryClipBox (HPS hps, PRECTL prclBound);
+HRGN GpiQueryClipRegion (HPS hps);
+LONG GpiQueryColor (HPS hps);
+BOOL GpiQueryColorData (HPS hps, LONG lCount, PLONG alArray);
+LONG GpiQueryColorIndex (HPS hps, ULONG flOptions, LONG lRgbColor);
+ULONG GpiQueryCp (HPS hps);
+BOOL GpiQueryCurrentPosition (HPS hps, PPOINTL pptlPoint);
+BOOL GpiQueryDefArcParams (HPS hps, PARCPARAMS parcpArcParams);
+BOOL GpiQueryDefAttrs (HPS hps, LONG lPrimType, ULONG flAttrMask,
+    PBUNDLE ppbunAttrs);
+BOOL GpiQueryDefCharBox (HPS hps, PSIZEL psizlSize);
+BOOL GpiQueryDefTag (HPS hps, PLONG plTag);
+BOOL GpiQueryDefViewingLimits (HPS hps, PRECTL prclLimits);
+BOOL GpiQueryDefaultViewMatrix (HPS hps, LONG lCount, PMATRIXLF pmatlfArray);
+LONG GpiQueryEditMode (HPS hps);
+LONG GpiQueryElement (HPS hps, LONG lOff, LONG lMaxLength, PBYTE pbData);
+LONG GpiQueryElementPointer (HPS hps);
+LONG GpiQueryElementType (HPS hps, PLONG plType, LONG lLength, PSZ pszData);
+ULONG GpiQueryFaceString (HPS PS, PCSZ FamilyName, PFACENAMEDESC attrs,
+    LONG length, PSZ CompoundFaceName);
+ULONG GpiQueryFontAction (HAB anchor, ULONG options);
+LONG GpiQueryFontFileDescriptions (HAB hab, PCSZ pszFilename, PLONG plCount,
+    PFFDESCS affdescsNames);
+BOOL GpiQueryFontMetrics (HPS hps, LONG lMetricsLength,
+    PFONTMETRICS pfmMetrics);
+LONG GpiQueryFonts (HPS hps, ULONG flOptions, PCSZ pszFacename,
+    PLONG plReqFonts, LONG lMetricsLength, PFONTMETRICS afmMetrics);
+LONG GpiQueryFullFontFileDescs (HAB hab, PCSZ pszFilename, PLONG plCount,
+    PVOID pNames, PLONG plNamesBuffLength);
+BOOL GpiQueryGraphicsField (HPS hps, PRECTL prclField);
+LONG GpiQueryKerningPairs (HPS hps, LONG lCount, PKERNINGPAIRS akrnprData);
+LONG GpiQueryLineEnd (HPS hps);
+LONG GpiQueryLineJoin (HPS hps);
+LONG GpiQueryLineType (HPS hps);
+FIXED GpiQueryLineWidth (HPS hps);
+LONG GpiQueryLineWidthGeom (HPS hps);
+LONG GpiQueryLogColorTable (HPS hps, ULONG flOptions, LONG lStart, LONG lCount,
+    PLONG alArray);
+BOOL GpiQueryLogicalFont (HPS PS, LONG lcid, PSTR8 name, PFATTRS attrs,
+    LONG length);
+LONG GpiQueryMarker (HPS hps);
+BOOL GpiQueryMarkerBox (HPS hps, PSIZEF psizfxSize);
+LONG GpiQueryMarkerSet (HPS hps);
+BOOL GpiQueryMetaFileBits (HMF hmf, LONG lOffset, LONG lLength, PBYTE pbData);
+LONG GpiQueryMetaFileLength (HMF hmf);
+LONG GpiQueryMix (HPS hps);
+BOOL GpiQueryModelTransformMatrix (HPS hps, LONG lCount,
+    PMATRIXLF pmatlfArray);
+LONG GpiQueryNearestColor (HPS hps, ULONG flOptions, LONG lRgbIn);
+LONG GpiQueryNumberSetIds (HPS hps);
+BOOL GpiQueryPageViewport (HPS hps, PRECTL prclViewport);
+HPAL GpiQueryPalette (HPS hps);
+LONG GpiQueryPaletteInfo (HPAL hpal, HPS  hps, ULONG flOptions,
+    ULONG ulStart, ULONG ulCount, PULONG aulArray);
+LONG GpiQueryPattern (HPS hps);
+BOOL GpiQueryPatternRefPoint (HPS hps, PPOINTL pptlRefPoint);
+LONG GpiQueryPatternSet (HPS hps);
+LONG GpiQueryRealColors (HPS hps, ULONG flOptions, LONG lStart, LONG lCount,
+    PLONG alColors);
+LONG GpiQueryRegionBox (HPS hps, HRGN hrgn, PRECTL prclBound);
+BOOL GpiQueryRegionRects (HPS hps, HRGN hrgn, PRECTL prclBound,
+    PRGNRECT prgnrcControl, PRECTL prclRect);
+LONG GpiQueryRGBColor (HPS hps, ULONG flOptions, LONG lColorIndex);
+BOOL GpiQuerySegmentTransformMatrix (HPS hps, LONG lSegid, LONG lCount,
+    PMATRIXLF pmatlfArray);
+BOOL GpiQuerySetIds (HPS hps, LONG lCount, PLONG alTypes, PSTR8 aNames,
+    PLONG allcids);
+BOOL GpiQueryTextAlignment (HPS hps, PLONG plHoriz, PLONG plVert);
+BOOL GpiQueryTextBox (HPS hps, LONG lCount1, PCH pchString, LONG lCount2,
+    PPOINTL aptlPoints);
+BOOL GpiQueryViewingLimits (HPS hps, PRECTL prclLimits);
+BOOL GpiQueryViewingTransformMatrix (HPS hps, LONG lCount,
+    PMATRIXLF pmatlfArray);
+BOOL GpiQueryWidthTable (HPS hps, LONG lFirstChar, LONG lCount, PLONG alData);
+LONG GpiRectInRegion (HPS hps, HRGN hrgn, __const__ RECTL *prclRect);
+LONG GpiRectVisible (HPS hps, __const__ RECTL *prclRectangle);
+BOOL GpiRotate (HPS hps, PMATRIXLF pmatlfArray, LONG lOptions, FIXED fxAngle,
+    __const__ POINTL *pptlCenter);
+BOOL GpiSaveMetaFile (HMF hmf, PCSZ pszFilename);
+BOOL GpiScale (HPS hps, PMATRIXLF pmfatlfArray, LONG lOptions,
+    __const__ FIXED *afxScale, __const__ POINTL *pptlCenter);
+HPAL GpiSelectPalette (HPS hps, HPAL hpal);
+BOOL GpiSetArcParams (HPS hps, __const__ ARCPARAMS *parcpArcParams);
+BOOL GpiSetAttrMode (HPS hps, LONG lMode);
+BOOL GpiSetAttrs (HPS hps, LONG lPrimType, ULONG flAttrMask, ULONG flDefMask,
+    __const__ VOID *ppbunAttrs);
+BOOL GpiSetBackColor (HPS hps, LONG lColor);
+BOOL GpiSetBackMix (HPS hps, LONG lMixMode);
+BOOL GpiSetCharAngle (HPS hps, __const__ GRADIENTL *pgradlAngle);
+BOOL GpiSetCharBox (HPS hps, __const__ SIZEF *psizfxBox);
+BOOL GpiSetCharBreakExtra (HPS hps, FIXED BreakExtra);
+BOOL GpiSetCharDirection (HPS hps, LONG lDirection);
+BOOL GpiSetCharExtra (HPS hps, FIXED  Extra);
+BOOL GpiSetCharMode (HPS hps, LONG lMode);
+BOOL GpiSetCharSet (HPS hps, LONG llcid);
+BOOL GpiSetCharShear (HPS hps, __const__ POINTL *pptlAngle);
+BOOL GpiSetClipPath (HPS hps, LONG lPath, LONG lOptions);
+LONG GpiSetClipRegion (HPS hps, HRGN hrgn, PHRGN phrgnOld);
+BOOL GpiSetColor (HPS hps, LONG lColor);
+BOOL GpiSetCp (HPS hps, ULONG ulCodePage);
+BOOL GpiSetCurrentPosition (HPS hps, __const__ POINTL *pptlPoint);
+BOOL GpiSetDefArcParams (HPS hps, __const__ ARCPARAMS *parcpArcParams);
+BOOL GpiSetDefAttrs (HPS hps, LONG lPrimType, ULONG flAttrMask,
+    __const__ VOID *ppbunAttrs);
+BOOL GpiSetDefaultViewMatrix (HPS hps, LONG lCount,
+    __const__ MATRIXLF *pmatlfarray, LONG lOptions);
+BOOL GpiSetDefTag (HPS hps, LONG lTag);
+BOOL GpiSetDefViewingLimits (HPS hps, __const__ RECTL *prclLimits);
+BOOL GpiSetEditMode (HPS hps, LONG lMode);
+BOOL GpiSetElementPointer (HPS hps, LONG lElement);
+BOOL GpiSetElementPointerAtLabel (HPS hps, LONG lLabel);
+BOOL GpiSetGraphicsField (HPS hps, __const__ RECTL *prclField);
+BOOL GpiSetLineEnd (HPS hps, LONG lLineEnd);
+BOOL GpiSetLineJoin (HPS hps, LONG lLineJoin);
+BOOL GpiSetLineType (HPS hps, LONG lLineType);
+BOOL GpiSetLineWidth (HPS hps, FIXED fxLineWidth);
+BOOL GpiSetLineWidthGeom (HPS hps, LONG lLineWidth);
+BOOL GpiSetMarker (HPS hps, LONG lSymbol);
+BOOL GpiSetMarkerBox (HPS hps, __const__ SIZEF *psizfxSize);
+BOOL GpiSetMarkerSet (HPS hps, LONG lSet);
+BOOL GpiSetMetaFileBits (HMF hmf, LONG lOffset, LONG lLength,
+    __const__ BYTE *pbBuffer);
+BOOL GpiSetMix (HPS hps, LONG lMixMode);
+BOOL GpiSetModelTransformMatrix (HPS hps, LONG lCount,
+    __const__ MATRIXLF *pmatlfArray, LONG lOptions);
+BOOL GpiSetPageViewport (HPS hps, __const__ RECTL *prclViewport);
+BOOL GpiSetPaletteEntries (HPAL hpal, ULONG ulFormat, ULONG ulStart,
+    ULONG ulCount, __const__ ULONG *aulTable);
+BOOL GpiSetPattern (HPS hps, LONG lPatternSymbol);
+BOOL GpiSetPatternRefPoint (HPS hps, __const__ POINTL *pptlRefPoint);
+BOOL GpiSetPatternSet (HPS hps, LONG lSet);
+BOOL GpiSetRegion (HPS hps, HRGN hrgn, LONG lcount,
+    __const__ RECTL *arclRectangles);
+BOOL GpiSetSegmentTransformMatrix (HPS hps, LONG lSegid, LONG lCount,
+    __const__ MATRIXLF *pmatlfarray, LONG lOptions);
+BOOL GpiSetTextAlignment (HPS hps, LONG lHoriz, LONG lVert);
+BOOL GpiSetViewingLimits (HPS hps, __const__ RECTL *prclLimits);
+BOOL GpiSetViewingTransformMatrix (HPS hps, LONG lCount,
+    __const__ MATRIXLF *pmatlfArray, LONG lOptions);
+LONG GpiStrokePath (HPS hps, LONG lPath, ULONG flOptions);
+BOOL GpiTranslate (HPS hps, PMATRIXLF pmatlfArray, LONG lOptions,
+    __const__ POINTL *pptlTranslation);
+BOOL GpiUnloadFonts (HAB hab, PCSZ pszFilename);
+BOOL GpiUnloadPublicFonts (HAB hab, PCSZ pszFilename);
+
+
+#if defined (INCL_GPIBITMAPS) || !defined (INCL_NOCOMMON)
+
+#define ROP_SRCCOPY			0x00cc
+#define ROP_SRCPAINT			0x00ee
+#define ROP_SRCAND			0x0088
+#define ROP_SRCINVERT			0x0066
+#define ROP_SRCERASE			0x0044
+#define ROP_NOTSRCCOPY			0x0033
+#define ROP_NOTSRCERASE			0x0011
+#define ROP_MERGECOPY			0x00c0
+#define ROP_MERGEPAINT			0x00bb
+#define ROP_PATCOPY			0x00f0
+#define ROP_PATPAINT			0x00fb
+#define ROP_PATINVERT			0x005a
+#define ROP_DSTINVERT			0x0055
+#define ROP_ZERO			0x0000
+#define ROP_ONE				0x00ff
+
+#define BBO_OR				0
+#define BBO_AND				1
+#define BBO_IGNORE			2
+#define BBO_PAL_COLORS			4
+#define BBO_NO_COLOR_INFO		8
+
+#define FF_BOUNDARY			0
+#define FF_SURFACE			1
+
+#define HBM_ERROR			((HBITMAP)(-1))
+
+
+LONG GpiBitBlt (HPS hpsTarget, HPS hpsSource, LONG lCount,
+    __const__ POINTL *aptlPoints, LONG lRop, ULONG flOptions);
+BOOL GpiDeleteBitmap (HBITMAP hbm);
+HBITMAP GpiLoadBitmap (HPS hps, HMODULE Resource, ULONG idBitmap,
+    LONG lWidth, LONG lHeight);
+HBITMAP GpiSetBitmap (HPS hps, HBITMAP hbm);
+LONG GpiWCBitBlt (HPS hpsTarget, HBITMAP hbmSource, LONG lCount,
+    __const__ POINTL *aptlPoints, LONG lRop, ULONG flOptions);
+
+#endif /* INCL_GPIBITMAPS */
+
+
+#if defined (INCL_GPIBITMAPS)
+
+#define BFT_ICON			0x4349
+#define BFT_BMAP			0x4d42
+#define BFT_POINTER			0x5450
+#define BFT_COLORICON			0x4943
+#define BFT_COLORPOINTER		0x5043
+#define BFT_BITMAPARRAY			0x4142
+
+#define CBD_BITS			0
+#define CBD_COMPRESSION			1
+#define CBD_DECOMPRESSION		2
+
+#define CBD_COLOR_CONVERSION		0x0001
+
+#define CBM_INIT			0x0004
+
+#define BCA_UNCOMP			0
+#define BCA_RLE8			1
+#define BCA_RLE4			2
+#define BCA_HUFFMAN1D			3
+#define BCA_RLE24			4
+
+#define BMB_ERROR			(-1)
+
+#define BRU_METRIC			0
+
+#define BRA_BOTTOMUP			0
+
+#define BRH_NOTHALFTONED		0
+#define BRH_ERRORDIFFUSION		1
+#define BRH_PANDA			2
+#define BRH_SUPERCIRCLE			3
+
+#define BCE_PALETTE			(-1)
+#define BCE_RGB				0
+
+
+typedef struct _RGB
+{
+  BYTE bBlue;
+  BYTE bGreen;
+  BYTE bRed;
+} RGB;
+
+typedef struct _RGB2
+{
+  BYTE bBlue;
+  BYTE bGreen;
+  BYTE bRed;
+  BYTE fcOptions;
+} RGB2;
+typedef RGB2 *PRGB2;
+
+typedef struct _BITMAPINFOHEADER
+{
+  ULONG	 cbFix;
+  USHORT cx;
+  USHORT cy;
+  USHORT cPlanes;
+  USHORT cBitCount;
+} BITMAPINFOHEADER;
+typedef BITMAPINFOHEADER *PBITMAPINFOHEADER;
+
+typedef struct _BITMAPINFO
+{
+  ULONG	 cbFix;
+  USHORT cx;
+  USHORT cy;
+  USHORT cPlanes;
+  USHORT cBitCount;
+  RGB	 argbColor[1];
+} BITMAPINFO;
+typedef BITMAPINFO *PBITMAPINFO;
+
+typedef struct _BITMAPINFO2
+{
+  ULONG	 cbFix;
+  ULONG	 cx;
+  ULONG	 cy;
+  USHORT cPlanes;
+  USHORT cBitCount;
+  ULONG	 ulCompression;
+  ULONG	 cbImage;
+  ULONG	 cxResolution;
+  ULONG	 cyResolution;
+  ULONG	 cclrUsed;
+  ULONG	 cclrImportant;
+  USHORT usUnits;
+  USHORT usReserved;
+  USHORT usRecording;
+  USHORT usRendering;
+  ULONG	 cSize1;
+  ULONG	 cSize2;
+  ULONG	 ulColorEncoding;
+  ULONG	 ulIdentifier;
+  RGB2	 argbColor[1];
+} BITMAPINFO2;
+typedef BITMAPINFO2 *PBITMAPINFO2;
+
+typedef struct _BITMAPINFOHEADER2
+{
+  ULONG	 cbFix;
+  ULONG	 cx;
+  ULONG	 cy;
+  USHORT cPlanes;
+  USHORT cBitCount;
+  ULONG	 ulCompression;
+  ULONG	 cbImage;
+  ULONG	 cxResolution;
+  ULONG	 cyResolution;
+  ULONG	 cclrUsed;
+  ULONG	 cclrImportant;
+  USHORT usUnits;
+  USHORT usReserved;
+  USHORT usRecording;
+  USHORT usRendering;
+  ULONG	 cSize1;
+  ULONG	 cSize2;
+  ULONG	 ulColorEncoding;
+  ULONG	 ulIdentifier;
+} BITMAPINFOHEADER2;
+typedef BITMAPINFOHEADER2 *PBITMAPINFOHEADER2;
+
+typedef struct _BITMAPFILEHEADER
+{
+  USHORT	   usType;
+  ULONG		   cbSize;
+  SHORT		   xHotspot;
+  SHORT		   yHotspot;
+  ULONG		   offBits;
+  BITMAPINFOHEADER bmp;
+} BITMAPFILEHEADER;
+typedef BITMAPFILEHEADER *PBITMAPFILEHEADER;
+
+typedef struct _BITMAPARRAYFILEHEADER
+{
+  USHORT	   usType;
+  ULONG		   cbSize;
+  ULONG		   offNext;
+  USHORT	   cxDisplay;
+  USHORT	   cyDisplay;
+  BITMAPFILEHEADER bfh;
+} BITMAPARRAYFILEHEADER;
+typedef BITMAPARRAYFILEHEADER *PBITMAPARRAYFILEHEADER;
+
+typedef struct _BITMAPFILEHEADER2
+{
+  USHORT	    usType;
+  ULONG		    cbSize;
+  SHORT		    xHotspot;
+  SHORT		    yHotspot;
+  ULONG		    offBits;
+  BITMAPINFOHEADER2 bmp2;
+} BITMAPFILEHEADER2;
+typedef BITMAPFILEHEADER2 *PBITMAPFILEHEADER2;
+
+typedef struct _BITMAPARRAYFILEHEADER2
+{
+  USHORT	    usType;
+  ULONG		    cbSize;
+  ULONG		    offNext;
+  USHORT	    cxDisplay;
+  USHORT	    cyDisplay;
+  BITMAPFILEHEADER2 bfh2;
+} BITMAPARRAYFILEHEADER2;
+typedef BITMAPARRAYFILEHEADER2 *PBITMAPARRAYFILEHEADER2;
+
+
+HBITMAP GpiCreateBitmap (HPS hps, __const__ BITMAPINFOHEADER2 *pbmpNew,
+    ULONG flOptions, __const__ BYTE *pbInitData,
+    __const__ BITMAPINFO2 *pbmiInfoTable);
+LONG GpiDrawBits (HPS hps, __const__ VOID *pBits,
+    __const__ BITMAPINFO2 *pbmiInfoTable, LONG lCount,
+    __const__ POINTL *aptlPoints, LONG lRop, ULONG flOptions);
+LONG GpiFloodFill (HPS hps, LONG lOptions, LONG lColor);
+LONG GpiQueryBitmapBits (HPS hps, LONG lScanStart, LONG lScans, PBYTE pbBuffer,
+    PBITMAPINFO2 pbmiInfoTable);
+BOOL GpiQueryBitmapDimension (HBITMAP hbm, PSIZEL psizlBitmapDimension);
+HBITMAP GpiQueryBitmapHandle (HPS hps, LONG lLcid);
+BOOL GpiQueryBitmapInfoHeader (HBITMAP hbm, PBITMAPINFOHEADER2 pbmpData);
+BOOL GpiQueryBitmapParameters (HBITMAP hbm, PBITMAPINFOHEADER pbmpData);
+BOOL GpiQueryDeviceBitmapFormats (HPS hps, LONG lCount, PLONG alArray);
+LONG  GpiSetBitmapBits (HPS hps, LONG lScanStart, LONG lScans,
+    __const__ BYTE *pbBuffer, __const__ BITMAPINFO2 *pbmiInfoTable);
+LONG GpiQueryPel (HPS hps, PPOINTL pptlPoint);
+BOOL GpiSetBitmapDimension (HBITMAP hbm,
+    __const__ SIZEL *psizlBitmapDimension);
+BOOL GpiSetBitmapId (HPS hps, HBITMAP hbm, LONG lLcid);
+LONG GpiSetPel (HPS hps, __const__ POINTL *pptlPoint);
+
+
+#endif /* INCL_GPIBITMAPS */
+
+
+#if defined (INCL_GPICONTROL) || !defined (INCL_NOCOMMON)
+
+#define GPIA_NOASSOC			0x0000
+#define GPIA_ASSOC			0x4000
+
+#define GPIF_DEFAULT			0x0000
+#define GPIF_SHORT			0x0100
+#define GPIF_LONG			0x0200
+
+#define GPIM_AREAEXCL			0x8000
+
+#define GPIT_NORMAL			0x0000
+#define GPIT_MICRO			0x1000
+#define GPIT_INK			0x2000
+
+#define HDC_ERROR			((HDC)(-1))
+
+#define PU_ARBITRARY			0x0004
+#define PU_PELS				0x0008
+#define PU_LOMETRIC			0x000c
+#define PU_HIMETRIC			0x0010
+#define PU_LOENGLISH			0x0014
+#define PU_HIENGLISH			0x0018
+#define PU_TWIPS			0x001c
+
+
+BOOL GpiAssociate (HPS hps, HDC hdc);
+HPS GpiCreatePS (HAB hab, HDC hdc, PSIZEL psizlSize, ULONG flOptions);
+BOOL GpiDestroyPS (HPS hps);
+BOOL GpiErase (HPS hps);
+HDC GpiQueryDevice (HPS hps);
+BOOL GpiRestorePS (HPS hps, LONG lPSid);
+LONG GpiSavePS (HPS hps);
+
+#endif /* INCL_GPICONTROL */
+
+
+#if defined (INCL_GPICONTROL)
+
+#define DCTL_ERASE			1
+#define DCTL_DISPLAY			2
+#define DCTL_BOUNDARY			3
+#define DCTL_DYNAMIC			4
+#define DCTL_CORRELATE			5
+
+#define DCTL_ERROR			(-1)
+#define DCTL_OFF			0
+#define DCTL_ON				1
+
+#define DM_ERROR			0
+#define DM_DRAW				1
+#define DM_RETAIN			2
+#define DM_DRAWANDRETAIN		3
+
+#define GPIE_SEGMENT			0
+#define GPIE_ELEMENT			1
+#define GPIE_DATA			2
+
+#define GRES_ATTRS			0x0001
+#define GRES_SEGMENTS			0x0002
+#define GRES_ALL			0x0004
+
+#define PS_UNITS			0x00fc
+#define PS_FORMAT			0x0f00
+#define PS_TYPE				0x1000
+#define PS_MODE				0x2000
+#define PS_ASSOCIATE			0x4000
+#define PS_NORESET			0x8000
+
+#define SDW_ERROR			(-1)
+#define SDW_OFF				0
+#define SDW_ON				1
+
+
+LONG GpiErrorSegmentData (HPS hps, PLONG plSegment, PLONG plContext);
+LONG GpiQueryDrawControl (HPS hps, LONG lControl);
+LONG GpiQueryDrawingMode (HPS hps);
+ULONG GpiQueryPS (HPS hps, PSIZEL psizlSize);
+BOOL GpiResetPS (HPS hps, ULONG flOptions);
+LONG GpiQueryStopDraw (HPS hps);
+BOOL GpiSetDrawControl (HPS hps, LONG lControl, LONG lValue);
+BOOL GpiSetDrawingMode (HPS hps, LONG lMode);
+BOOL GpiSetPS (HPS hps, __const__ SIZEL *psizlsize, ULONG flOptions);
+BOOL GpiSetStopDraw (HPS hps, LONG lValue);
+
+#endif /* INCL_GPICONTROL */
+
+
+#if defined (INCL_GPICORRELATION)
+
+#define GPI_HITS			2
+
+#define PICKAP_DEFAULT			0
+#define PICKAP_REC			2
+
+#define PICKSEL_VISIBLE			0
+#define PICKSEL_ALL			1
+
+
+LONG GpiCorrelateChain (HPS hps, LONG lType, __const__ POINTL *pptlPick,
+    LONG lMaxHits, LONG lMaxDepth, PLONG pl2);
+LONG GpiCorrelateFrom (HPS hps, LONG lFirstSegment, LONG lLastSegment,
+    LONG lType, __const__ POINTL *pptlPick, LONG lMaxHits, LONG lMaxDepth,
+    PLONG plSegTag);
+LONG GpiCorrelateSegment (HPS hps, LONG lSegment, LONG lType,
+    __const__ POINTL *pptlPick, LONG lMaxHits, LONG lMaxDepth, PLONG alSegTag);
+BOOL GpiQueryBoundaryData (HPS hps, PRECTL prclBoundary);
+BOOL GpiQueryPickAperturePosition (HPS hps, PPOINTL pptlPoint);
+BOOL GpiQueryPickApertureSize (HPS hps, PSIZEL psizlSize);
+BOOL GpiQueryTag (HPS hps, PLONG plTag);
+BOOL GpiResetBoundaryData (HPS hps);
+BOOL GpiSetPickAperturePosition (HPS hps, __const__ POINTL *pptlPick);
+BOOL GpiSetPickApertureSize (HPS hps, LONG lOptions,
+    __const__ SIZEL *psizlSize);
+BOOL GpiSetTag (HPS hps, LONG lTag);
+
+#endif /* INCL_GPICORRELATION */
+
+
+#if defined (INCL_GPIINK)
+
+#define PPE_KEEPPATH			0
+#define PPE_ERASEPATH			1
+
+#define PPS_INKMOVE			0
+#define PPS_INKDOWN			1
+#define PPS_INKUP			2
+
+
+BOOL GpiBeginInkPath (HPS hps, LONG lPath, ULONG flOptions);
+BOOL GpiEndInkPath (HPS hps, ULONG flOptions);
+LONG GpiStrokeInkPath (HPS hps, LONG lPath, LONG lCount,
+    __const__ POINTL *aptlPoints, ULONG flOptions);
+
+#endif /* INCL_GPIINK */
+
+
+#if defined (INCL_GPISEGMENTS)
+
+#define DFORM_NOCONV			0
+
+#define DFORM_S370SHORT			1
+#define DFORM_PCSHORT			2
+#define DFORM_PCLONG			4
+
+#define ATTR_ERROR			(-1)
+#define ATTR_DETECTABLE			1
+#define ATTR_VISIBLE			2
+#define ATTR_CHAINED			6
+#define ATTR_DYNAMIC			8
+#define ATTR_FASTCHAIN			9
+#define ATTR_PROP_DETECTABLE		10
+#define ATTR_PROP_VISIBLE		11
+
+#define ATTR_OFF			0
+#define ATTR_ON				1
+
+#define LOWER_PRI			(-1)
+#define HIGHER_PRI			1
+
+
+BOOL GpiCloseSegment (HPS hps);
+BOOL GpiDeleteSegment (HPS hps, LONG lSegid);
+BOOL GpiDeleteSegments (HPS hps, LONG lFirstSegment, LONG lLastSegment);
+BOOL GpiDrawChain (HPS hps);
+BOOL GpiDrawDynamics (HPS hps);
+BOOL GpiDrawFrom (HPS hps, LONG lFirstSegment, LONG lLastSegment);
+BOOL GpiDrawSegment (HPS hps, LONG lSegment);
+LONG GpiGetData (HPS hps, LONG lSegid, PLONG plOffset, LONG lFormat,
+    LONG lLength, PBYTE pbData);
+BOOL GpiOpenSegment (HPS hps, LONG lSegment);
+LONG GpiPutData (HPS hps, LONG lFormat, PLONG plCount, __const__ BYTE *pbData);
+LONG GpiQueryInitialSegmentAttrs (HPS hps, LONG lAttribute);
+LONG GpiQuerySegmentAttrs (HPS hps, LONG lSegid, LONG lAttribute);
+LONG GpiQuerySegmentNames (HPS hps, LONG lFirstSegid, LONG lLastSegid,
+    LONG lMax, PLONG alSegids);
+LONG GpiQuerySegmentPriority (HPS hps, LONG lRefSegid, LONG lOrder);
+BOOL GpiRemoveDynamics (HPS hps, LONG lFirstSegid, LONG lLastSegid);
+BOOL GpiSetInitialSegmentAttrs (HPS hps, LONG lAttribute, LONG lValue);
+BOOL GpiSetSegmentAttrs (HPS hps, LONG lSegid, LONG lAttribute, LONG lValue);
+BOOL GpiSetSegmentPriority (HPS hps, LONG lSegid, LONG lRefSegid, LONG lOrder);
+
+#endif /* INCL_GPISEGMENTS */
+
+
+/* ---------------------- DEVICE CONTEXTS --------------------------------- */
+
+#define DEV_ERROR			0
+#define DEV_OK				1
+#define DEV_BAD_PARAMETERS		2
+#define DEV_WARNING			3
+#define DEV_PROP_BUF_TOO_SMALL		4
+#define DEV_ITEM_BUF_TOO_SMALL		5
+#define DEV_INV_INP_JOBPROPERTIES	6
+
+#define ADDRESS				0
+#define DRIVER_NAME			1
+#define DRIVER_DATA			2
+#define DATA_TYPE			3
+#define COMMENT				4
+#define PROC_NAME			5
+#define PROC_PARAMS			6
+#define SPL_PARAMS			7
+#define NETWORK_PARAMS			8
+
+#define OD_SCREEN			0
+#define OD_QUEUED			2
+#define OD_DIRECT			5
+#define OD_INFO				6
+#define OD_METAFILE			7
+#define OD_MEMORY			8
+#define OD_METAFILE_NOQUERY		9
+
+#define CAPS_FAMILY			0
+#define CAPS_IO_CAPS			1
+#define CAPS_TECHNOLOGY			2
+#define CAPS_DRIVER_VERSION		3
+#define CAPS_WIDTH			4
+#define CAPS_HEIGHT			5
+#define CAPS_WIDTH_IN_CHARS		6
+#define CAPS_HEIGHT_IN_CHARS		7
+#define CAPS_HORIZONTAL_RESOLUTION	8
+#define CAPS_VERTICAL_RESOLUTION	9
+#define CAPS_CHAR_WIDTH			10
+#define CAPS_CHAR_HEIGHT		11
+#define CAPS_SMALL_CHAR_WIDTH		12
+#define CAPS_SMALL_CHAR_HEIGHT		13
+#define CAPS_COLORS			14
+#define CAPS_COLOR_PLANES		15
+#define CAPS_COLOR_BITCOUNT		16
+#define CAPS_COLOR_TABLE_SUPPORT	17
+#define CAPS_MOUSE_BUTTONS		18
+#define CAPS_FOREGROUND_MIX_SUPPORT	19
+#define CAPS_BACKGROUND_MIX_SUPPORT	20
+#define CAPS_DEVICE_WINDOWING		31
+#define CAPS_ADDITIONAL_GRAPHICS	32
+#define CAPS_VIO_LOADABLE_FONTS		21
+#define CAPS_WINDOW_BYTE_ALIGNMENT	22
+#define CAPS_BITMAP_FORMATS		23
+#define CAPS_RASTER_CAPS		24
+#define CAPS_MARKER_HEIGHT		25
+#define CAPS_MARKER_WIDTH		26
+#define CAPS_DEVICE_FONTS		27
+#define CAPS_GRAPHICS_SUBSET		28
+#define CAPS_GRAPHICS_VERSION		29
+#define CAPS_GRAPHICS_VECTOR_SUBSET	30
+#define CAPS_PHYS_COLORS		33
+#define CAPS_COLOR_INDEX		34
+#define CAPS_GRAPHICS_CHAR_WIDTH	35
+#define CAPS_GRAPHICS_CHAR_HEIGHT	36
+#define CAPS_HORIZONTAL_FONT_RES	37
+#define CAPS_VERTICAL_FONT_RES		38
+#define CAPS_DEVICE_FONT_SIM		39
+#define CAPS_LINEWIDTH_THICK		40
+#define CAPS_DEVICE_POLYSET_POINTS	41
+
+#define CAPS_IO_DUMMY			1
+#define CAPS_IO_SUPPORTS_OP		2
+#define CAPS_IO_SUPPORTS_IP		3
+#define CAPS_IO_SUPPORTS_IO		4
+
+#define CAPS_TECH_UNKNOWN		0
+#define CAPS_TECH_VECTOR_PLOTTER	1
+#define CAPS_TECH_RASTER_DISPLAY	2
+#define CAPS_TECH_RASTER_PRINTER	3
+#define CAPS_TECH_RASTER_CAMERA		4
+#define CAPS_TECH_POSTSCRIPT		5
+
+#define CAPS_COLTABL_RGB_8		0x0001
+#define CAPS_COLTABL_RGB_8_PLUS		0x0002
+#define CAPS_COLTABL_TRUE_MIX		0x0004
+#define CAPS_COLTABL_REALIZE		0x0008
+
+#define CAPS_FM_OR			0x0001
+#define CAPS_FM_OVERPAINT		0x0002
+#define CAPS_FM_XOR			0x0008
+#define CAPS_FM_LEAVEALONE		0x0010
+#define CAPS_FM_AND			0x0020
+#define CAPS_FM_GENERAL_BOOLEAN		0x0040
+
+#define CAPS_BM_OR			0x0001
+#define CAPS_BM_OVERPAINT		0x0002
+#define CAPS_BM_XOR			0x0008
+#define CAPS_BM_LEAVEALONE		0x0010
+#define CAPS_BM_AND			0x0020
+#define CAPS_BM_GENERAL_BOOLEAN		0x0040
+#define CAPS_BM_SRCTRANSPARENT		0x0080
+#define CAPS_BM_DESTTRANSPARENT		0x0100
+
+#define CAPS_DEV_WINDOWING_SUPPORT	0x0001
+
+#define CAPS_DEV_FONT_SIM_BOLD		0x0001
+#define CAPS_DEV_FONT_SIM_ITALIC	0x0002
+#define CAPS_DEV_FONT_SIM_UNDERSCORE	0x0004
+#define CAPS_DEV_FONT_SIM_STRIKEOUT	0x0008
+
+#define CAPS_VDD_DDB_TRANSFER		0x0001
+#define CAPS_GRAPHICS_KERNING_SUPPORT	0x0002
+#define CAPS_FONT_OUTLINE_DEFAULT	0x0004
+#define CAPS_FONT_IMAGE_DEFAULT		0x0008
+#define CAPS_SCALED_DEFAULT_MARKERS	0x0040
+#define CAPS_COLOR_CURSOR_SUPPORT	0x0080
+#define CAPS_PALETTE_MANAGER		0x0100
+#define CAPS_COSMETIC_WIDELINE_SUPPORT	0x0200
+#define CAPS_DIRECT_FILL		0x0400
+#define CAPS_REBUILD_FILLS		0x0800
+#define CAPS_CLIP_FILLS			0x1000
+#define CAPS_ENHANCED_FONTMETRICS	0x2000
+#define CAPS_TRANSFORM_SUPPORT		0x4000
+#define CAPS_EXTERNAL_16_BITCOUNT	0x8000
+
+#define CAPS_BYTE_ALIGN_REQUIRED	0
+#define CAPS_BYTE_ALIGN_RECOMMENDED	1
+#define CAPS_BYTE_ALIGN_NOT_REQUIRED	2
+
+#define CAPS_RASTER_BITBLT		0x0001
+#define CAPS_RASTER_BANDING		0x0002
+#define CAPS_RASTER_BITBLT_SCALING	0x0004
+#define CAPS_RASTER_SET_PEL		0x0010
+#define CAPS_RASTER_FONTS		0x0020
+#define CAPS_RASTER_FLOOD_FILL		0x0040
+
+#define DEVESC_ERROR			(-1)
+#define DEVESC_NOTIMPLEMENTED		0
+
+#define DEVESC_QUERYESCSUPPORT		0
+#define DEVESC_GETSCALINGFACTOR		1
+#define DEVESC_QUERYVIOCELLSIZES	2
+#define DEVESC_GETCP			8000
+#define DEVESC_STARTDOC			8150
+#define DEVESC_ENDDOC			8151
+#define DEVESC_NEXTBAND			8152
+#define DEVESC_ABORTDOC			8153
+#define DEVESC_GETJOBID			8160
+#define DEVESC_QUERY_RASTER		8161
+#define DEVESC_QUERYSIZE		8162
+#define DEVESC_QUERYJOBPROPERTIES	8163
+#define DEVESC_SETJOBPROPERTIES		8164
+#define DEVESC_DEFAULTJOBPROPERTIES	8165
+#define DEVESC_CHANGEOUTPUTPORT		8166
+#define DEVESC_NEWFRAME			16300
+#define DEVESC_DRAFTMODE		16301
+#define DEVESC_FLUSHOUTPUT		16302
+#define DEVESC_RAWDATA			16303
+#define DEVESC_SETMODE			16304
+#define DEVESC_SEP			16305
+#define DEVESC_MACRO			16307
+#define DEVESC_BEGIN_BITBLT		16309
+#define DEVESC_END_BITBLT		16310
+#define DEVESC_SEND_COMPDATA		16311
+#define DEVESC_DBE_FIRST		24450
+#define DEVESC_DBE_LAST			24455
+#define DEVESC_CHAR_EXTRA		16998
+#define DEVESC_BREAK_EXTRA		16999
+#define DEVESC_STD_JOURNAL		32600
+#define DEVESC_STARTDOC_WPROP		49150
+#define DEVESC_NEWFRAME_WPROP		49151
+
+#define DPDM_ERROR			(-1)
+#define DPDM_NONE			0
+
+#define DPDM_POSTJOBPROP		0
+#define DPDM_CHANGEPROP			1
+#define DPDM_QUERYJOBPROP		2
+
+#define DQHC_ERROR			(-1)
+
+#define HCAPS_CURRENT			1
+#define HCAPS_SELECTABLE		2
+
+
+typedef PSZ *PDEVOPENDATA;
+
+
+typedef struct _DRIVDATA
+{
+  LONG cb;
+  LONG lVersion;
+  CHAR szDeviceName[32];
+  CHAR abGeneralData[1];
+} DRIVDATA;
+typedef DRIVDATA *PDRIVDATA;
+
+typedef struct _DEVOPENSTRUC
+{
+  PSZ	    pszLogAddress;
+  PSZ	    pszDriverName;
+  PDRIVDATA pdriv;
+  PSZ	    pszDataType;
+  PSZ	    pszComment;
+  PSZ	    pszQueueProcName;
+  PSZ	    pszQueueProcParams;
+  PSZ	    pszSpoolerParams;
+  PSZ	    pszNetworkParams;
+} DEVOPENSTRUC;
+typedef DEVOPENSTRUC *PDEVOPENSTRUC;
+
+typedef struct _ESCMODE
+{
+  ULONG mode;
+  BYTE	modedata[1];
+} ESCMODE;
+typedef ESCMODE *PESCMODE;
+
+typedef struct _VIOSIZECOUNT
+{
+  LONG maxcount;
+  LONG count;
+} VIOSIZECOUNT;
+typedef VIOSIZECOUNT *PVIOSIZECOUNT;
+
+typedef struct _VIOFONTCELLSIZE
+{
+  LONG cx;
+  LONG cy;
+} VIOFONTCELLSIZE;
+typedef VIOFONTCELLSIZE *PVIOFONTCELLSIZE;
+
+typedef struct _SFACTORS
+{
+  LONG x;
+  LONG y;
+} SFACTORS;
+typedef SFACTORS *PSFACTORS;
+
+typedef struct _BANDRECT
+{
+  LONG xleft;
+  LONG ybottom;
+  LONG xright;
+  LONG ytop;
+} BANDRECT;
+typedef BANDRECT *PBANDRECT;
+
+typedef struct _HCINFO
+{
+  CHAR szFormname[32];
+  LONG cx;
+  LONG cy;
+  LONG xLeftClip;
+  LONG yBottomClip;
+  LONG xRightClip;
+  LONG yTopClip;
+  LONG xPels;
+  LONG yPels;
+  LONG flAttributes;
+} HCINFO;
+typedef HCINFO *PHCINFO;
+
+HMF DevCloseDC (HDC hdc);
+LONG DevEscape (HDC hdc, LONG lCode, LONG lInCount, PBYTE pbInData,
+    PLONG plOutCount, PBYTE pbOutData);
+HDC DevOpenDC (HAB hab, LONG lType, PCSZ pszToken, LONG lCount,
+    PDEVOPENDATA pdopData, HDC hdcComp);
+LONG DevPostDeviceModes (HAB hab, PDRIVDATA pdrivDriverData ,
+    PCSZ pszDriverName, PCSZ pszDeviceName, PCSZ pszName, ULONG flOptions);
+BOOL DevQueryCaps (HDC hdc, LONG lStart, LONG lCount, PLONG alArray);
+BOOL DevQueryDeviceNames (HAB hab, PCSZ pszDriverName, PLONG pldn,
+    PSTR32 aDeviceName, PSTR64 aDeviceDesc, PLONG pldt, PSTR16 aDataType);
+LONG DevQueryHardcopyCaps (HDC hdc, LONG lStartForm, LONG lForms,
+    PHCINFO phciHcInfo);
+
+/* ------------------ PRESENTATION MANAGER SHELL -------------------------- */
+
+#define MAXNAMEL			60
+
+#define HINI_PROFILE			(HINI)0
+#define HINI_USERPROFILE		(HINI)(-1)
+#define HINI_SYSTEMPROFILE		(HINI)(-2)
+#define HINI_USER			HINI_USERPROFILE
+#define HINI_SYSTEM			HINI_SYSTEMPROFILE
+
+typedef LHANDLE HSWITCH;
+typedef HSWITCH *PHSWITCH;
+
+typedef LHANDLE HPROGRAM;
+typedef HPROGRAM *PHPROGRAM;
+
+typedef LHANDLE HINI;
+typedef HINI *PHINI;
+
+typedef LHANDLE HAPP;
+
+
+typedef struct _PRFPROFILE
+{
+  ULONG cchUserName;
+  PSZ	pszUserName;
+  ULONG cchSysName;
+  PSZ	pszSysName;
+} PRFPROFILE;
+typedef PRFPROFILE *PPRFPROFILE;
+
+
+#if defined (INCL_WINPROGRAMLIST)
+
+#define MAXPATHL			128
+#define SGH_ROOT			(HPROGRAM)(-1L)
+
+#define PROG_DEFAULT			0
+#define PROG_FULLSCREEN			1
+#define PROG_WINDOWABLEVIO		2
+#define PROG_PM				3
+#define PROG_GROUP			5
+#define PROG_REAL			4
+#define PROG_VDM			4
+#define PROG_WINDOWEDVDM		7
+#define PROG_DLL			6
+#define PROG_PDD			8
+#define PROG_VDD			9
+#define PROG_WINDOW_REAL		10
+#define PROG_WINDOW_PROT		11
+#define PROG_WINDOW_AUTO		12
+#define PROG_SEAMLESSVDM		13
+#define PROG_SEAMLESSCOMMON		14
+#define PROG_30_STDSEAMLESSCOMMON	14
+#define PROG_31_STDSEAMLESSVDM		15
+#define PROG_31_STDSEAMLESSCOMMON	16
+#define PROG_31_ENHSEAMLESSVDM		17
+#define PROG_31_ENHSEAMLESSCOMMON	18
+#define PROG_31_ENH			19
+#define PROG_31_STD			20
+#define PROG_DOS_GAME			21
+#define PROG_WIN_GAME			22
+#define PROG_DOS_MODE			23
+#define PROG_RESERVED			255
+
+#define SAF_VALIDFLAGS			0x001f
+
+#define SAF_INSTALLEDCMDLINE		0x0001
+#define SAF_STARTCHILDAPP		0x0002
+#define SAF_MAXIMIZED			0x0004
+#define SAF_MINIMIZED			0x0008
+#define SAF_BACKGROUND			0x0010
+
+#define SHE_VISIBLE			0x00
+#define SHE_INVISIBLE			0x01
+#define SHE_RESERVED			0xff
+
+#define SHE_UNPROTECTED			0x00
+#define SHE_PROTECTED			0x02
+
+
+typedef ULONG PROGCATEGORY;
+typedef PROGCATEGORY *PPROGCATEGORY;
+
+typedef struct _HPROGARRAY
+{
+  HPROGRAM ahprog[1];
+} HPROGARRAY;
+typedef HPROGARRAY *PHPROGARRAY;
+
+typedef struct _PROGTYPE
+{
+  PROGCATEGORY progc;
+  ULONG	       fbVisible;
+} PROGTYPE;
+typedef PROGTYPE *PPROGTYPE;
+
+typedef struct _PROGTITLE
+{
+  HPROGRAM hprog;
+  PROGTYPE progt;
+  PSZ	   pszTitle;
+} PROGTITLE;
+typedef PROGTITLE *PPROGTITLE;
+
+typedef struct _PROGDETAILS
+{
+  ULONG	   Length;
+  PROGTYPE progt;
+  PSZ	   pszTitle;
+  PSZ	   pszExecutable;
+  PSZ	   pszParameters;
+  PSZ	   pszStartupDir;
+  PSZ	   pszIcon;
+  PSZ	   pszEnvironment;
+  SWP	   swpInitial;
+} PROGDETAILS;
+typedef PROGDETAILS *PPROGDETAILS;
+
+
+HPROGRAM PrfAddProgram (HINI hini, PPROGDETAILS pDetails, HPROGRAM hprogGroup);
+BOOL PrfChangeProgram (HINI hini, HPROGRAM hprog, PPROGDETAILS pDetails);
+HPROGRAM PrfCreateGroup (HINI hini, PCSZ pszTitle, UCHAR chVisibility);
+BOOL PrfDestroyGroup (HINI hini, HPROGRAM hprogGroup);
+PROGCATEGORY PrfQueryProgramCategory (HINI hini, PCSZ pszExe);
+ULONG PrfQueryProgramHandle (HINI hini, PCSZ pszExe,
+    PHPROGARRAY phprogArray, ULONG cchBufferMax, PULONG pulCount);
+ULONG PrfQueryProgramTitles (HINI hini, HPROGRAM hprogGroup,
+    PPROGTITLE pTitles, ULONG ulBufferLength, PULONG pulCount);
+ULONG PrfQueryDefinition (HINI hini, HPROGRAM hprog, PPROGDETAILS pDetails,
+    ULONG ulBufferLength);
+BOOL PrfRemoveProgram (HINI hini, HPROGRAM hprog);
+
+HAPP WinStartApp (HWND hwndNotify, PPROGDETAILS pDetails,
+    PCSZ pszParams, PVOID Reserved, ULONG fbOptions);
+BOOL WinTerminateApp (HAPP happ);
+
+#endif /* INCL_WINPROGRAMLIST */
+
+
+#if defined (INCL_WINSWITCHLIST) || !defined (INCL_NOCOMMON)
+
+#define SWL_INVISIBLE			0x01
+#define SWL_GRAYED			0x02
+#define SWL_VISIBLE			0x04
+
+#define SWL_NOTJUMPABLE			0x01
+#define SWL_JUMPABLE			0x02
+
+typedef struct _SWCNTRL
+{
+  HWND	   hwnd;
+  HWND	   hwndIcon;
+  HPROGRAM hprog;
+  PID	   idProcess;
+  ULONG	   idSession;
+  ULONG	   uchVisibility;
+  ULONG	   fbJump;
+  CHAR	   szSwtitle[MAXNAMEL+4];
+  ULONG	   bProgType;
+} SWCNTRL;
+typedef SWCNTRL *PSWCNTRL;
+
+HSWITCH WinAddSwitchEntry (__const__ SWCNTRL *pswctl);
+ULONG WinRemoveSwitchEntry (HSWITCH hsw);
+
+#endif /* INCL_WINSWITCHLIST || !INCL_NOCOMMON */
+
+#if defined (INCL_WINSWITCHLIST)
+
+typedef struct _SWENTRY
+{
+  HSWITCH hswitch;
+  SWCNTRL swctl;
+} SWENTRY;
+typedef SWENTRY *PSWENTRY;
+
+typedef struct _SWBLOCK
+{
+  ULONG	  cswentry;
+  SWENTRY aswentry[1];
+} SWBLOCK;
+typedef SWBLOCK *PSWBLOCK;
+
+
+ULONG WinChangeSwitchEntry (HSWITCH hsw, __const__ SWCNTRL *pswctl);
+HSWITCH WinCreateSwitchEntry (HAB hab, __const__ SWCNTRL *pswctl);
+ULONG WinQuerySessionTitle (HAB hab, ULONG usSession, PSZ pszTitle,
+    ULONG usTitlelen);
+ULONG WinQuerySwitchEntry (HSWITCH hsw, PSWCNTRL pswctl);
+HSWITCH WinQuerySwitchHandle (HWND hwnd, PID pid);
+ULONG WinQuerySwitchList (HAB hab, PSWBLOCK pswblk, ULONG usDataLength);
+ULONG WinQueryTaskSizePos (HAB hab, ULONG usScreenGroup, PSWP pswp);
+ULONG WinQueryTaskTitle (ULONG usSession, PSZ pszTitle, ULONG usTitlelen);
+ULONG WinSwitchToProgram (HSWITCH hsw);
+
+#endif /* INCL_WINSWITCHLIST */
+
+
+#if defined (INCL_WINSHELLDATA)
+
+#define PL_ALTERED			0x008e
+
+BOOL PrfCloseProfile (HINI hini);
+HINI PrfOpenProfile (HAB hab, PCSZ pszFileName);
+BOOL PrfQueryProfile (HAB hab, PPRFPROFILE pPrfProfile);
+BOOL PrfQueryProfileData (HINI hini, PCSZ pszApp, PCSZ pszKey, PVOID pBuffer,
+    PULONG pulBufferLength);
+LONG PrfQueryProfileInt (HINI hini, PCSZ pszApp, PCSZ pszKey, LONG  sDefault);
+BOOL PrfQueryProfileSize (HINI hini, PCSZ pszApp, PCSZ pszKey,
+    PULONG pulReqLen);
+ULONG PrfQueryProfileString (HINI hini, PCSZ pszApp, PCSZ pszKey,
+    PCSZ pszDefault, PVOID pBuffer, ULONG ulBufferLength);
+BOOL PrfReset (HAB hab, __const__ PRFPROFILE *pPrfProfile);
+BOOL PrfWriteProfileData (HINI hini, PCSZ pszApp, PCSZ pszKey,
+    CPVOID pData, ULONG ulDataLength);
+BOOL PrfWriteProfileString (HINI hini, PCSZ pszApp, PCSZ pszKey,
+    PCSZ pszData);
+
+#endif /* INCL_WINSHELLDATA */
+
+/* ------------------ STANDARD DIALOGS: FILE ------------------------------ */
+
+#if defined (INCL_WINSTDFILE)
+
+#define FDM_FILTER			(WM_USER+40)
+#define FDM_VALIDATE			(WM_USER+41)
+#define FDM_ERROR			(WM_USER+42)
+
+#define DID_FILE_DIALOG			256
+#define DID_FILENAME_TXT		257
+#define DID_FILENAME_ED			258
+#define DID_DRIVE_TXT			259
+#define DID_DRIVE_CB			260
+#define DID_FILTER_TXT			261
+#define DID_FILTER_CB			262
+#define DID_DIRECTORY_TXT		263
+#define DID_DIRECTORY_LB		264
+#define DID_FILES_TXT			265
+#define DID_FILES_LB			266
+#define DID_HELP_PB			267
+#define DID_APPLY_PB			268
+#define DID_READ_ONLY			269
+#define DID_DIRECTORY_SELECTED		270
+#define DID_OK_PB			DID_OK
+#define DID_CANCEL_PB			DID_CANCEL
+
+#define FDS_CENTER			0x00000001
+#define FDS_CUSTOM			0x00000002
+#define FDS_FILTERUNION			0x00000004
+#define FDS_HELPBUTTON			0x00000008
+#define FDS_APPLYBUTTON			0x00000010
+#define FDS_PRELOAD_VOLINFO		0x00000020
+#define FDS_MODELESS			0x00000040
+#define FDS_INCLUDE_EAS			0x00000080
+#define FDS_OPEN_DIALOG			0x00000100
+#define FDS_SAVEAS_DIALOG		0x00000200
+#define FDS_MULTIPLESEL			0x00000400
+#define FDS_ENABLEFILELB		0x00000800
+#define FDS_NATIONAL_LANGUAGE		0x80000000
+
+#define FDS_EFSELECTION			0
+#define FDS_LBSELECTION			1
+
+#define FDS_SUCCESSFUL			0
+#define FDS_ERR_DEALLOCATE_MEMORY	1
+#define FDS_ERR_FILTER_TRUNC		2
+#define FDS_ERR_INVALID_DIALOG		3
+#define FDS_ERR_INVALID_DRIVE		4
+#define FDS_ERR_INVALID_FILTER		5
+#define FDS_ERR_INVALID_PATHFILE	6
+#define FDS_ERR_OUT_OF_MEMORY		7
+#define FDS_ERR_PATH_TOO_LONG		8
+#define FDS_ERR_TOO_MANY_FILE_TYPES	9
+#define FDS_ERR_INVALID_VERSION		10
+#define FDS_ERR_INVALID_CUSTOM_HANDLE	11
+#define FDS_ERR_DIALOG_LOAD_ERROR	12
+#define FDS_ERR_DRIVE_ERROR		13
+
+#define IDS_FILE_ALL_FILES_SELECTOR	1000
+#define IDS_FILE_BACK_CUR_PATH		1001
+#define IDS_FILE_BACK_PREV_PATH		1002
+#define IDS_FILE_BACK_SLASH		1003
+#define IDS_FILE_BASE_FILTER		1004
+#define IDS_FILE_BLANK			1005
+#define IDS_FILE_COLON			1006
+#define IDS_FILE_DOT			1007
+#define IDS_FILE_DRIVE_LETTERS		1008
+#define IDS_FILE_FWD_CUR_PATH		1009
+#define IDS_FILE_FWD_PREV_PATH		1010
+#define IDS_FILE_FORWARD_SLASH		1011
+#define IDS_FILE_PARENT_DIR		1012
+#define IDS_FILE_Q_MARK			1013
+#define IDS_FILE_SPLAT			1014
+#define IDS_FILE_SPLAT_DOT		1015
+#define IDS_FILE_SAVEAS_TITLE		1016
+#define IDS_FILE_SAVEAS_FILTER_TXT	1017
+#define IDS_FILE_SAVEAS_FILENM_TXT	1018
+#define IDS_FILE_DUMMY_FILE_NAME	1019
+#define IDS_FILE_DUMMY_FILE_EXT		1020
+#define IDS_FILE_DUMMY_DRIVE		1021
+#define IDS_FILE_DUMMY_ROOT_DIR		1022
+#define IDS_FILE_PATH_PTR		1023
+#define IDS_FILE_VOLUME_PREFIX		1024
+#define IDS_FILE_VOLUME_SUFFIX		1025
+#define IDS_FILE_PATH_PTR2		1026
+#define IDS_FILE_INVALID_CHARS		1027
+#define IDS_FILE_ETC_BACK_SLASH		1028
+#define IDS_FILE_OPEN_PARENTHESIS	1029
+#define IDS_FILE_CLOSE_PARENTHESIS	1030
+#define IDS_FILE_SEMICOLON		1031
+#define IDS_FILE_BAD_DRIVE_NAME		1100
+#define IDS_FILE_BAD_DRIVE_OR_PATH_NAME 1101
+#define IDS_FILE_BAD_FILE_NAME		1102
+#define IDS_FILE_BAD_FQF		1103
+#define IDS_FILE_BAD_NETWORK_NAME	1104
+#define IDS_FILE_BAD_SUB_DIR_NAME	1105
+#define IDS_FILE_DRIVE_NOT_AVAILABLE	1106
+#define IDS_FILE_FQFNAME_TOO_LONG	1107
+#define IDS_FILE_OPEN_DIALOG_NOTE	1108
+#define IDS_FILE_PATH_TOO_LONG		1109
+#define IDS_FILE_SAVEAS_DIALOG_NOTE	1110
+#define IDS_FILE_DRIVE_DISK_CHANGE	1120
+#define IDS_FILE_DRIVE_NOT_READY	1122
+#define IDS_FILE_DRIVE_LOCKED		1123
+#define IDS_FILE_DRIVE_NO_SECTOR	1124
+#define IDS_FILE_DRIVE_SOME_ERROR	1125
+#define IDS_FILE_DRIVE_INVALID		1126
+#define IDS_FILE_INSERT_DISK_NOTE	1127
+#define IDS_FILE_OK_WHEN_READY		1128
+
+typedef PSZ APSZ[1];
+typedef APSZ *PAPSZ;
+
+typedef struct _FILEDLG
+{
+  ULONG	  cbSize;
+  ULONG	  fl;
+  ULONG	  ulUser;
+  LONG	  lReturn;
+  LONG	  lSRC;
+  PSZ	  pszTitle;
+  PSZ	  pszOKButton;
+  PFNWP	  pfnDlgProc;
+  PSZ	  pszIType;
+  PAPSZ	  papszITypeList;
+  PSZ	  pszIDrive;
+  PAPSZ	  papszIDriveList;
+  HMODULE hMod;
+  CHAR	  szFullFile[CCHMAXPATH];
+  PAPSZ	  papszFQFilename;
+  ULONG	  ulFQFCount;
+  USHORT  usDlgId;
+  SHORT	  x;
+  SHORT	  y;
+  SHORT	  sEAType;
+} FILEDLG;
+typedef FILEDLG *PFILEDLG;
+
+
+MRESULT WinDefFileDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+HWND WinFileDlg (HWND hwndP, HWND hwndO, PFILEDLG pfild);
+BOOL WinFreeFileDlgList (PAPSZ papszFQFilename);
+
+#endif /* INCL_WINSTDFILE */
+
+/* ------------------ STANDARD DIALOGS: FONT ------------------------------ */
+
+#if defined (INCL_WINSTDFONT)
+
+#define FNTM_FACENAMECHANGED		(WM_USER+50)
+#define FNTM_POINTSIZECHANGED		(WM_USER+51)
+#define FNTM_STYLECHANGED		(WM_USER+52)
+#define FNTM_COLORCHANGED		(WM_USER+53)
+#define FNTM_UPDATEPREVIEW		(WM_USER+54)
+#define FNTM_FILTERLIST			(WM_USER+55)
+
+#define FNTS_CENTER			0x00000001
+#define FNTS_CUSTOM			0x00000002
+#define FNTS_OWNERDRAWPREVIEW		0x00000004
+#define FNTS_HELPBUTTON			0x00000008
+#define FNTS_APPLYBUTTON		0x00000010
+#define FNTS_RESETBUTTON		0x00000020
+#define FNTS_MODELESS			0x00000040
+#define FNTS_INITFROMFATTRS		0x00000080
+#define FNTS_BITMAPONLY			0x00000100
+#define FNTS_VECTORONLY			0x00000200
+#define FNTS_FIXEDWIDTHONLY		0x00000400
+#define FNTS_PROPORTIONALONLY		0x00000800
+#define FNTS_NOSYNTHESIZEDFONTS		0x00001000
+#define FNTS_NATIONAL_LANGUAGE		0x80000000
+
+#define FNTF_NOVIEWSCREENFONTS		0x0001
+#define FNTF_NOVIEWPRINTERFONTS		0x0002
+#define FNTF_SCREENFONTSELECTED		0x0004
+#define FNTF_PRINTERFONTSELECTED	0x0008
+
+#define CLRC_FOREGROUND			1
+#define CLRC_BACKGROUND			2
+
+#define FNTI_BITMAPFONT			0x0001
+#define FNTI_VECTORFONT			0x0002
+#define FNTI_FIXEDWIDTHFONT		0x0004
+#define FNTI_PROPORTIONALFONT		0x0008
+#define FNTI_SYNTHESIZED		0x0010
+#define FNTI_DEFAULTLIST		0x0020
+#define FNTI_FAMILYNAME			0x0100
+#define FNTI_STYLENAME			0x0200
+#define FNTI_POINTSIZE			0x0400
+
+#define FNTS_SUCCESSFUL			0
+#define FNTS_ERR_INVALID_DIALOG		3
+#define FNTS_ERR_ALLOC_SHARED_MEM	4
+#define FNTS_ERR_INVALID_PARM		5
+#define FNTS_ERR_OUT_OF_MEMORY		7
+#define FNTS_ERR_INVALID_VERSION	10
+#define FNTS_ERR_DIALOG_LOAD_ERROR	12
+
+#define DID_FONT_DIALOG			300
+#define DID_NAME			301
+#define DID_STYLE			302
+#define DID_DISPLAY_FILTER		303
+#define DID_PRINTER_FILTER		304
+#define DID_SIZE			305
+#define DID_SAMPLE			306
+#define DID_OUTLINE			307
+#define DID_UNDERSCORE			308
+#define DID_STRIKEOUT			309
+#define DID_HELP_BUTTON			310
+#define DID_APPLY_BUTTON		311
+#define DID_RESET_BUTTON		312
+#define DID_OK_BUTTON			DID_OK
+#define DID_CANCEL_BUTTON		DID_CANCEL
+#define DID_NAME_PREFIX			313
+#define DID_STYLE_PREFIX		314
+#define DID_SIZE_PREFIX			315
+#define DID_SAMPLE_GROUPBOX		316
+#define DID_EMPHASIS_GROUPBOX		317
+#define DID_FONT_ISO_SUPPORT		318
+#define DID_FONT_ISO_UNTESTED		319
+
+#define IDS_FONT_SAMPLE			350
+#define IDS_FONT_BLANK			351
+#define IDS_FONT_KEY_0			352
+#define IDS_FONT_KEY_9			353
+#define IDS_FONT_KEY_SEP		354
+#define IDS_FONT_DISP_ONLY		355
+#define IDS_FONT_PRINTER_ONLY		356
+#define IDS_FONT_COMBINED		357
+#define IDS_FONT_WEIGHT1		358
+#define IDS_FONT_WEIGHT2		359
+#define IDS_FONT_WEIGHT3		360
+#define IDS_FONT_WEIGHT4		361
+#define IDS_FONT_WEIGHT5		362
+#define IDS_FONT_WEIGHT6		363
+#define IDS_FONT_WEIGHT7		364
+#define IDS_FONT_WEIGHT8		365
+#define IDS_FONT_WEIGHT9		366
+#define IDS_FONT_WIDTH1			367
+#define IDS_FONT_WIDTH2			368
+#define IDS_FONT_WIDTH3			369
+#define IDS_FONT_WIDTH4			370
+#define IDS_FONT_WIDTH5			371
+#define IDS_FONT_WIDTH6			372
+#define IDS_FONT_WIDTH7			373
+#define IDS_FONT_WIDTH8			374
+#define IDS_FONT_WIDTH9			375
+#define IDS_FONT_OPTION0		376
+#define IDS_FONT_OPTION1		377
+#define IDS_FONT_OPTION2		378
+#define IDS_FONT_OPTION3		379
+#define IDS_FONT_POINT_SIZE_LIST	380
+
+typedef struct _FONTDLG
+{
+  ULONG	  cbSize;
+  HPS	  hpsScreen;
+  HPS	  hpsPrinter;
+  PSZ	  pszTitle;
+  PSZ	  pszPreview;
+  PSZ	  pszPtSizeList;
+  PFNWP	  pfnDlgProc;
+  PSZ	  pszFamilyname;
+  FIXED	  fxPointSize;
+  ULONG	  fl;
+  ULONG	  flFlags;
+  ULONG	  flType;
+  ULONG	  flTypeMask;
+  ULONG	  flStyle;
+  ULONG	  flStyleMask;
+  LONG	  clrFore;
+  LONG	  clrBack;
+  ULONG	  ulUser;
+  LONG	  lReturn;
+  LONG	  lSRC;
+  LONG	  lEmHeight;
+  LONG	  lXHeight;
+  LONG	  lExternalLeading;
+  HMODULE hMod;
+  FATTRS  fAttrs;
+  SHORT	  sNominalPointSize;
+  USHORT  usWeight;
+  USHORT  usWidth;
+  SHORT	  x;
+  SHORT	  y;
+  USHORT  usDlgId;
+  USHORT  usFamilyBufLen;
+  USHORT  usReserved;
+} FONTDLG;
+typedef FONTDLG *PFONTDLG;
+
+typedef struct _STYLECHANGE
+{
+  USHORT usWeight;
+  USHORT usWeightOld;
+  USHORT usWidth;
+  USHORT usWidthOld;
+  ULONG	 flType;
+  ULONG	 flTypeOld;
+  ULONG	 flTypeMask;
+  ULONG	 flTypeMaskOld;
+  ULONG	 flStyle;
+  ULONG	 flStyleOld;
+  ULONG	 flStyleMask;
+  ULONG	 flStyleMaskOld;
+} STYLECHANGE;
+typedef STYLECHANGE *PSTYLECHANGE;
+
+HWND WinFontDlg (HWND hwndP, HWND hwndO, PFONTDLG pfntd);
+MRESULT WinDefFontDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+#endif /* INCL_WINSTDFONT */
+
+/* -------------------------- SPIN BUTTON --------------------------------- */
+
+#if defined (INCL_WINSTDSPIN)
+
+#define SPBS_ALLCHARACTERS		0x0000
+#define SPBS_NUMERICONLY		0x0001
+#define SPBS_READONLY			0x0002
+#define SPBS_SERVANT			0x0000
+#define SPBS_MASTER			0x0010
+#define SPBS_JUSTDEFAULT		0x0000
+#define SPBS_JUSTRIGHT			0x0004
+#define SPBS_JUSTLEFT			0x0008
+#define SPBS_JUSTCENTER			0x000c
+#define SPBS_NOBORDER			0x0020
+#define SPBS_PADWITHZEROS		0x0080
+#define SPBS_FASTSPIN			0x0100
+
+#define SPBM_OVERRIDESETLIMITS		0x0200
+#define SPBM_QUERYLIMITS		0x0201
+#define SPBM_SETTEXTLIMIT		0x0202
+#define SPBM_SPINUP			0x0203
+#define SPBM_SPINDOWN			0x0204
+#define SPBM_QUERYVALUE			0x0205
+#define SPBM_SETARRAY			0x0206
+#define SPBM_SETLIMITS			0x0207
+#define SPBM_SETCURRENTVALUE		0x0208
+#define SPBM_SETMASTER			0x0209
+
+#define SPBN_UPARROW			0x020a
+#define SPBN_DOWNARROW			0x020b
+#define SPBN_ENDSPIN			0x020c
+#define SPBN_CHANGE			0x020d
+#define SPBN_SETFOCUS			0x020e
+#define SPBN_KILLFOCUS			0x020f
+
+#define SPBQ_UPDATEIFVALID		0
+#define SPBQ_ALWAYSUPDATE		1
+#define SPBQ_DONOTUPDATE		3
+
+#endif /* INCL_WINSTDSPIN */
+
+/* ----------------------------- SLIDER ----------------------------------- */
+
+#if defined (INCL_WINSTDSLIDER)
+
+#define SLM_ADDDETENT			0x0369
+#define SLM_QUERYDETENTPOS		0x036a
+#define SLM_QUERYSCALETEXT		0x036b
+#define SLM_QUERYSLIDERINFO		0x036c
+#define SLM_QUERYTICKPOS		0x036d
+#define SLM_QUERYTICKSIZE		0x036e
+#define SLM_REMOVEDETENT		0x036f
+#define SLM_SETSCALETEXT		0x0370
+#define SLM_SETSLIDERINFO		0x0371
+#define SLM_SETTICKSIZE			0x0372
+
+#define SLN_CHANGE			1
+#define SLN_SLIDERTRACK			2
+#define SLN_SETFOCUS			3
+#define SLN_KILLFOCUS			4
+
+#define SLS_HORIZONTAL			0x0000
+#define SLS_VERTICAL			0x0001
+#define SLS_CENTER			0x0000
+#define SLS_BOTTOM			0x0002
+#define SLS_TOP				0x0004
+#define SLS_LEFT			0x0002
+#define SLS_RIGHT			0x0004
+#define SLS_SNAPTOINCREMENT		0x0008
+#define SLS_BUTTONSBOTTOM		0x0010
+#define SLS_BUTTONSTOP			0x0020
+#define SLS_BUTTONSLEFT			0x0010
+#define SLS_BUTTONSRIGHT		0x0020
+#define SLS_OWNERDRAW			0x0040
+#define SLS_READONLY			0x0080
+#define SLS_RIBBONSTRIP			0x0100
+#define SLS_HOMEBOTTOM			0x0000
+#define SLS_HOMETOP			0x0200
+#define SLS_HOMELEFT			0x0000
+#define SLS_HOMERIGHT			0x0200
+#define SLS_PRIMARYSCALE1		0x0000
+#define SLS_PRIMARYSCALE2		0x0400
+
+#define SMA_SCALE1			0x0001
+#define SMA_SCALE2			0x0002
+#define SMA_SHAFTDIMENSIONS		0x0000
+#define SMA_SHAFTPOSITION		0x0001
+#define SMA_SLIDERARMDIMENSIONS		0x0002
+#define SMA_SLIDERARMPOSITION		0x0003
+#define SMA_RANGEVALUE			0x0000
+#define SMA_INCREMENTVALUE		0x0001
+#define SMA_SETALLTICKS			0xffff
+
+#define SDA_RIBBONSTRIP			1
+#define SDA_SLIDERSHAFT			2
+#define SDA_BACKGROUND			3
+#define SDA_SLIDERARM			4
+
+#define PMERR_UPDATE_IN_PROGRESS	0x1f06
+#define SLDERR_INVALID_PARAMETERS	(-1)
+
+
+typedef struct _SLDCDATA
+{
+  ULONG	 cbSize;
+  USHORT usScale1Increments;
+  USHORT usScale1Spacing;
+  USHORT usScale2Increments;
+  USHORT usScale2Spacing;
+} SLDCDATA;
+typedef SLDCDATA *PSLDCDATA;
+
+#endif /* INCL_WINSTDSLIDER */
+
+/* ------------------------- CIRCULAR SLIDER ------------------------------ */
+
+#if defined (INCL_WINCIRCULARSLIDER)
+
+#define CSM_QUERYRANGE			0x053d
+#define CSM_SETRANGE			0x053e
+#define CSM_QUERYVALUE			0x053f
+#define CSM_SETVALUE			0x0540
+#define CSM_QUERYRADIUS			0x0541
+#define CSM_SETINCREMENT		0x0542
+#define CSM_QUERYINCREMENT		0x0543
+#define CSM_SETBITMAPDATA		0x0544
+#define CSN_SETFOCUS			0x0548
+#define CSN_CHANGED			0x0549
+#define CSN_TRACKING			0x054a
+#define CSN_QUERYBACKGROUNDCOLOR	0x054b
+
+#define CSS_NOBUTTON			0x0001
+#define CSS_NOTEXT			0x0002
+#define CSS_NONUMBER			0x0004
+#define CSS_POINTSELECT			0x0008
+#define CSS_360				0x0010
+#define CSS_MIDPOINT			0x0020
+#define CSS_PROPORTIONALTICKS		0x0040
+#define CSS_NOTICKS			0x0080
+#define CSS_CIRCULARVALUE		0x0100
+
+typedef struct _CSBITMAPDATA
+{
+  HBITMAP hbmLeftUp;
+  HBITMAP hbmLeftDown;
+  HBITMAP hbmRightUp;
+  HBITMAP hbmRightDown;
+} CSBITMAPDATA;
+typedef CSBITMAPDATA *PCSBITMAPDATA;
+
+#endif /* INCL_WINCIRCULARSLIDER */
+
+/* ---------------------------- NOTEBOOK ---------------------------------- */
+
+#if defined (INCL_WINSTDBOOK)
+
+#define BFA_PAGEDATA			0x0001
+#define BFA_PAGEFROMHWND		0x0002
+#define BFA_PAGEFROMDLGTEMPLATE		0x0004
+#define BFA_PAGEFROMDLGRES		0x0008
+#define BFA_STATUSLINE			0x0010
+#define BFA_MAJORTABBITMAP		0x0020
+#define BFA_MINORTABBITMAP		0x0040
+#define BFA_MAJORTABTEXT		0x0080
+#define BFA_MINORTABTEXT		0x0100
+#define BFA_BIDIINFO			0x0200
+
+#define BKM_CALCPAGERECT		0x0353
+#define BKM_DELETEPAGE			0x0354
+#define BKM_INSERTPAGE			0x0355
+#define BKM_INVALIDATETABS		0x0356
+#define BKM_TURNTOPAGE			0x0357
+#define BKM_QUERYPAGECOUNT		0x0358
+#define BKM_QUERYPAGEID			0x0359
+#define BKM_QUERYPAGEDATA		0x035a
+#define BKM_QUERYPAGEWINDOWHWND		0x035b
+#define BKM_QUERYTABBITMAP		0x035c
+#define BKM_QUERYTABTEXT		0x035d
+#define BKM_SETDIMENSIONS		0x035e
+#define BKM_SETPAGEDATA			0x035f
+#define BKM_SETPAGEWINDOWHWND		0x0360
+#define BKM_SETSTATUSLINETEXT		0x0361
+#define BKM_SETTABBITMAP		0x0362
+#define BKM_SETTABTEXT			0x0363
+#define BKM_SETNOTEBOOKCOLORS		0x0364
+#define BKM_QUERYPAGESTYLE		0x0365
+#define BKM_QUERYSTATUSLINETEXT		0x0366
+#define BKM_SETPAGEINFO			0x0367
+#define BKM_QUERYPAGEINFO		0x0368
+#define BKM_SETTABCOLOR			0x0374
+#define BKM_SETNOTEBOOKBUTTONS		0x0375
+
+#define BKN_PAGESELECTED		0x0082
+#define BKN_NEWPAGESIZE			0x0083
+#define BKN_HELP			0x0084
+#define BKN_PAGEDELETED			0x0085
+#define BKN_PAGESELECTEDPENDING		0x0086
+
+#define BKA_ALL				0x0001
+#define BKA_SINGLE			0x0002
+#define BKA_TAB				0x0004
+
+#define BKA_LAST			0x0002
+#define BKA_FIRST			0x0004
+#define BKA_NEXT			0x0008
+#define BKA_PREV			0x0010
+#define BKA_TOP				0x0020
+
+#define BKA_MAJORTAB			0x0001
+#define BKA_MINORTAB			0x0002
+#define BKA_PAGEBUTTON			0x0100
+
+#define BKA_STATUSTEXTON		0x0001
+#define BKA_MAJOR			0x0040
+#define BKA_MINOR			0x0080
+#define BKA_AUTOPAGESIZE		0x0100
+#define BKA_END				0x0200
+
+#define BKA_TEXT			0x0400
+#define BKA_BITMAP			0x0800
+
+#define BKA_AUTOCOLOR			(-1)
+#define BKA_MAXBUTTONID			7999
+
+#define BKS_BACKPAGESBR			0x0001
+#define BKS_BACKPAGESBL			0x0002
+#define BKS_BACKPAGESTR			0x0004
+#define BKS_BACKPAGESTL			0x0008
+
+#define BKS_MAJORTABRIGHT		0x0010
+#define BKS_MAJORTABLEFT		0x0020
+#define BKS_MAJORTABTOP			0x0040
+#define BKS_MAJORTABBOTTOM		0x0080
+
+#define BKS_SQUARETABS			0x0000
+#define BKS_ROUNDEDTABS			0x0100
+#define BKS_POLYGONTABS			0x0200
+
+#define BKS_SOLIDBIND			0x0000
+#define BKS_SPIRALBIND			0x0400
+
+#define BKS_STATUSTEXTLEFT		0x0000
+#define BKS_STATUSTEXTRIGHT		0x1000
+#define BKS_STATUSTEXTCENTER		0x2000
+
+#define BKS_TABTEXTLEFT			0x0000
+#define BKS_TABTEXTRIGHT		0x4000
+#define BKS_TABTEXTCENTER		0x8000
+
+#define BKS_BUTTONAREA			0x0200
+#define BKS_TABBEDDIALOG		0x0800
+
+#define BKA_BACKGROUNDPAGECOLORINDEX	0x0001
+#define BKA_BACKGROUNDPAGECOLOR		0x0002
+#define BKA_BACKGROUNDMAJORCOLORINDEX	0x0003
+#define BKA_BACKGROUNDMAJORCOLOR	0x0004
+#define BKA_BACKGROUNDMINORCOLORINDEX	0x0005
+#define BKA_BACKGROUNDMINORCOLOR	0x0006
+#define BKA_FOREGROUNDMAJORCOLORINDEX	0x0007
+#define BKA_FOREGROUNDMAJORCOLOR	0x0008
+#define BKA_FOREGROUNDMINORCOLORINDEX	0x0009
+#define BKA_FOREGROUNDMINORCOLOR	0x000a
+
+#define BOOKERR_INVALID_PARAMETERS	(-1)
+
+
+typedef struct _BOOKTEXT
+{
+  PSZ	pString;
+  ULONG textLen;
+} BOOKTEXT;
+typedef BOOKTEXT *PBOOKTEXT;
+
+typedef struct _NOTEBOOKBUTTON
+{
+  PSZ	  pszText;
+  ULONG	  idButton;
+  LHANDLE hImage;
+  LONG	  flStyle;
+} NOTEBOOKBUTTON;
+typedef NOTEBOOKBUTTON *PNOTEBOOKBUTTON;
+
+typedef struct _DELETENOTIFY
+{
+  HWND	  hwndBook;
+  HWND	  hwndPage;
+  ULONG	  ulAppPageData;
+  HBITMAP hbmTab;
+} DELETENOTIFY;
+typedef DELETENOTIFY *PDELETENOTIFY;
+
+typedef struct _PAGESELECTNOTIFY
+{
+  HWND	hwndBook;
+  ULONG ulPageIdCur;
+  ULONG ulPageIdNew;
+} PAGESELECTNOTIFY;
+typedef PAGESELECTNOTIFY *PPAGESELECTNOTIFY;
+
+typedef struct _BOOKPAGEINFO
+{
+  ULONG	       cb;
+  ULONG	       fl;
+  BOOL	       bLoadDlg;
+  ULONG	       ulPageData;
+  HWND	       hwndPage;
+  PFN	       pfnPageDlgProc;
+  ULONG	       idPageDlg;
+  HMODULE      hmodPageDlg;
+  PVOID	       pPageDlgCreateParams;
+  PDLGTEMPLATE pdlgtPage;
+  ULONG	       cbStatusLine;
+  PSZ	       pszStatusLine;
+  HBITMAP      hbmMajorTab;
+  HBITMAP      hbmMinorTab;
+  ULONG	       cbMajorTab;
+  PSZ	       pszMajorTab;
+  ULONG	       cbMinorTab;
+  PSZ	       pszMinorTab;
+  PVOID	       pBidiInfo;
+} BOOKPAGEINFO;
+typedef BOOKPAGEINFO *PBOOKPAGEINFO;
+
+#endif /* INCL_WINSTDBOOK */
+
+/* -------------------------- DRAG AND DROP ------------------------------- */
+
+#if defined (INCL_WINSTDDRAG)
+
+#define PMERR_NOT_DRAGGING		0x1f00
+#define PMERR_ALREADY_DRAGGING		0x1f01
+
+#define WM_DRAGFIRST			0x0310
+#define WM_DRAGLAST			0x032f
+
+#define DM_DROP				0x032f
+#define DM_DRAGOVER			0x032e
+#define DM_DRAGLEAVE			0x032d
+#define DM_DROPHELP			0x032c
+#define DM_ENDCONVERSATION		0x032b
+#define DM_PRINT			0x032a
+#define DM_RENDER			0x0329
+#define DM_RENDERCOMPLETE		0x0328
+#define DM_RENDERPREPARE		0x0327
+#define DM_DRAGFILECOMPLETE		0x0326
+#define DM_EMPHASIZETARGET		0x0325
+#define DM_DRAGERROR			0x0324
+#define DM_FILERENDERED			0x0323
+#define DM_RENDERFILE			0x0322
+#define DM_DRAGOVERNOTIFY		0x0321
+#define DM_PRINTOBJECT			0x0320
+#define DM_DISCARDOBJECT		0x031f
+#define DM_DROPNOTIFY			0x031e
+
+#define MSGF_DRAG			0x0010
+
+#define DC_OPEN				0x0001
+#define DC_REF				0x0002
+#define DC_GROUP			0x0004
+#define DC_CONTAINER			0x0008
+#define DC_PREPARE			0x0010
+#define DC_REMOVEABLEMEDIA		0x0020
+
+#define DF_MOVE				0x0001
+#define DF_SOURCE			0x0002
+#define DF_SUCCESSFUL			0x0004
+
+#define DFF_MOVE			1
+#define DFF_COPY			2
+#define DFF_DELETE			3
+
+#define DGS_DRAGINPROGRESS		0x0001
+#define DGS_LAZYDRAGINPROGRESS		0x0002
+
+#define DME_IGNOREABORT			1
+#define DME_IGNORECONTINUE		2
+#define DME_REPLACE			3
+#define DME_RETRY			4
+
+#define DMFL_TARGETSUCCESSFUL		0x0001
+#define DMFL_TARGETFAIL			0x0002
+#define DMFL_NATIVERENDER		0x0004
+#define DMFL_RENDERRETRY		0x0008
+#define DMFL_RENDEROK			0x0010
+#define DMFL_RENDERFAIL			0x0020
+
+#define DO_DEFAULT			0xbffe
+#define DO_UNKNOWN			0xbfff
+#define DO_COPYABLE			0x0001
+#define DO_MOVEABLE			0x0002
+#define DO_LINKABLE			0x0004
+#define DO_CREATEABLE			0x0008
+#define DO_CREATEPROGRAMOBJECTABLE	0x0010
+
+#define DO_COPY				0x0010
+#define DO_MOVE				0x0020
+#define DO_LINK				0x0018
+#define DO_CREATE			0x0040
+#define DO_CREATEPROGRAMOBJECT		0x0080
+
+#define DOR_NODROP			0x0000
+#define DOR_DROP			0x0001
+#define DOR_NODROPOP			0x0002
+#define DOR_NEVERDROP			0x0003
+
+#define DRG_ICON			0x0001
+#define DRG_BITMAP			0x0002
+#define DRG_POLYGON			0x0004
+#define DRG_STRETCH			0x0008
+#define DRG_TRANSPARENT			0x0010
+#define DRG_CLOSED			0x0020
+#define DRG_MINIBITMAP			0x0040
+
+#define DRR_SOURCE			1
+#define DRR_TARGET			2
+#define DRR_ABORT			3
+
+#define DRT_ASM				"Assembler Code"
+#define DRT_BASIC			"BASIC Code"
+#define DRT_BINDATA			"Binary Data"
+#define DRT_BITMAP			"Bitmap"
+#define DRT_C				"C Code"
+#define DRT_COBOL			"COBOL Code"
+#define DRT_DLL				"Dynamic Link Library"
+#define DRT_DOSCMD			"DOS Command File"
+#define DRT_EXE				"Executable"
+#define DRT_FORTRAN			"FORTRAN Code"
+#define DRT_ICON			"Icon"
+#define DRT_LIB				"Library"
+#define DRT_METAFILE			"Metafile"
+#define DRT_OS2CMD			"OS/2 Command File"
+#define DRT_PASCAL			"Pascal Code"
+#define DRT_RESOURCE			"Resource File"
+#define DRT_TEXT			"Plain Text"
+#define DRT_UNKNOWN			"Unknown"
+
+typedef LHANDLE HSTR;
+
+typedef struct _DRAGIMAGE
+{
+  USHORT  cb;
+  USHORT  cptl;
+  LHANDLE hImage;
+  SIZEL	  sizlStretch;
+  ULONG	  fl;
+  SHORT	  cxOffset;
+  SHORT	  cyOffset;
+} DRAGIMAGE;
+typedef DRAGIMAGE *PDRAGIMAGE;
+
+typedef struct _DRAGINFO
+{
+  ULONG	 cbDraginfo;
+  USHORT cbDragitem;
+  USHORT usOperation;
+  HWND	 hwndSource;
+  SHORT	 xDrop;
+  SHORT	 yDrop;
+  USHORT cditem;
+  USHORT usReserved;
+} DRAGINFO;
+typedef DRAGINFO *PDRAGINFO;
+
+typedef struct _DRAGITEM
+{
+  HWND	 hwndItem;
+  ULONG	 ulItemID;
+  HSTR	 hstrType;
+  HSTR	 hstrRMF;
+  HSTR	 hstrContainerName;
+  HSTR	 hstrSourceName;
+  HSTR	 hstrTargetName;
+  SHORT	 cxOffset;
+  SHORT	 cyOffset;
+  USHORT fsControl;
+  USHORT fsSupportedOps;
+} DRAGITEM;
+typedef DRAGITEM *PDRAGITEM;
+
+typedef struct _DRAGTRANSFER
+{
+  ULONG	    cb;
+  HWND	    hwndClient;
+  PDRAGITEM pditem;
+  HSTR	    hstrSelectedRMF;
+  HSTR	    hstrRenderToName;
+  ULONG	    ulTargetInfo;
+  USHORT    usOperation;
+  USHORT    fsReply;
+} DRAGTRANSFER;
+typedef DRAGTRANSFER *PDRAGTRANSFER;
+
+typedef struct _RENDERFILE
+{
+  HWND	 hwndDragFiles;
+  HSTR	 hstrSource;
+  HSTR	 hstrTarget;
+  USHORT fMove;
+  USHORT usRsvd;
+} RENDERFILE;
+typedef RENDERFILE *PRENDERFILE;
+
+
+BOOL DrgAcceptDroppedFiles (HWND hwnd, PCSZ pszPath, PCSZ pszTypes,
+    ULONG ulDefaultOp, ULONG ulReserved);
+BOOL DrgAccessDraginfo (PDRAGINFO pdinfo);
+HSTR DrgAddStrHandle (PCSZ psz);
+PDRAGINFO DrgAllocDraginfo (ULONG cDitem);
+PDRAGTRANSFER DrgAllocDragtransfer (ULONG cdxfer);
+BOOL DrgCancelLazyDrag (VOID);
+BOOL DrgDeleteDraginfoStrHandles (PDRAGINFO pdinfo);
+BOOL DrgDeleteStrHandle (HSTR hstr);
+HWND DrgDrag (HWND hwndSource, PDRAGINFO pdinfo, PDRAGIMAGE pdimg,
+    ULONG cdimg, LONG vkTerminate, PVOID pReserved);
+BOOL DrgDragFiles (HWND hwnd, PSZ *apszFiles, PSZ *apszTypes, PSZ *apszTargets,
+    ULONG cFiles, HPOINTER hptrDrag, ULONG vkTerm, BOOL fSourceRender,
+    ULONG ulReserved);
+BOOL DrgFreeDraginfo (PDRAGINFO pdinfo);
+BOOL DrgFreeDragtransfer (PDRAGTRANSFER pdxfer);
+HPS DrgGetPS (HWND hwnd);
+BOOL DrgLazyDrag (HWND hwndSource, PDRAGINFO pDraginfo, PDRAGIMAGE pdimg,
+    ULONG cdimg, PVOID pReserved);
+BOOL DrgLazyDrop (HWND hwndTarget, ULONG ulOperation, PPOINTL pptlDrop);
+BOOL DrgPostTransferMsg (HWND hwnd, ULONG msg, PDRAGTRANSFER pdxfer, ULONG fl,
+    ULONG ulReserved, BOOL fRetry);
+BOOL DrgPushDraginfo (PDRAGINFO pdinfo, HWND hwndDest);
+PDRAGINFO DrgQueryDraginfoPtr (PDRAGINFO pReserved);
+PDRAGINFO DrgQueryDraginfoPtrFromHwnd (HWND hwndSource);
+PDRAGINFO DrgQueryDraginfoPtrFromDragitem (__const__ DRAGITEM *pDragitem);
+BOOL DrgQueryDragitem (PDRAGINFO pdinfo, ULONG cbBuffer, PDRAGITEM pditem,
+    ULONG iItem);
+ULONG DrgQueryDragitemCount (PDRAGINFO pdinfo);
+PDRAGITEM DrgQueryDragitemPtr (PDRAGINFO pdinfo, ULONG ulIndex);
+ULONG DrgQueryDragStatus (VOID);
+BOOL DrgQueryNativeRMF (PDRAGITEM pditem, ULONG cbBuffer, PCHAR pBuffer);
+ULONG DrgQueryNativeRMFLen (PDRAGITEM pditem);
+ULONG DrgQueryStrName (HSTR hstr, ULONG cbBuffer, PSZ pBuffer);
+ULONG DrgQueryStrNameLen (HSTR hstr);
+BOOL DrgQueryTrueType (PDRAGITEM pditem, ULONG cbBuffer, PSZ pBuffer);
+ULONG DrgQueryTrueTypeLen (PDRAGITEM pditem);
+PDRAGINFO DrgReallocDraginfo (PDRAGINFO pDraginfoOld, ULONG cditem);
+BOOL DrgReleasePS (HPS hps);
+MRESULT DrgSendTransferMsg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+BOOL DrgSetDragImage (PDRAGINFO pdinfo, PDRAGIMAGE pdimg, ULONG cdimg,
+    PVOID pReserved);
+BOOL DrgSetDragitem (PDRAGINFO pdinfo, PDRAGITEM pditem, ULONG cbBuffer,
+    ULONG iItem);
+BOOL DrgSetDragPointer (PDRAGINFO pdinfo, HPOINTER hptr);
+BOOL DrgVerifyNativeRMF (PDRAGITEM pditem, PCSZ pszRMF);
+BOOL DrgVerifyRMF (PDRAGITEM pditem, PCSZ pszMech, PCSZ pszFmt);
+BOOL DrgVerifyTrueType (PDRAGITEM pditem, PCSZ pszType);
+BOOL DrgVerifyType (PDRAGITEM pditem, PCSZ pszType);
+BOOL DrgVerifyTypeSet (PDRAGITEM pditem, PCSZ pszType, ULONG cbMatch,
+    PSZ pszMatch);
+
+#endif /* INCL_WINSTDDRAG */
+
+/* -------------------------- VALUE SET ----------------------------------- */
+
+#if defined (INCL_WINSTDVALSET)
+
+#define VDA_ITEM			0x0001
+#define VDA_ITEMBACKGROUND		0x0002
+#define VDA_SURROUNDING			0x0003
+#define VDA_BACKGROUND			0x0004
+
+#define VIA_BITMAP			0x0001
+#define VIA_ICON			0x0002
+#define VIA_TEXT			0x0004
+#define VIA_RGB				0x0008
+#define VIA_COLORINDEX			0x0010
+#define VIA_OWNERDRAW			0x0020
+#define VIA_DISABLED			0x0040
+#define VIA_DRAGGABLE			0x0080
+#define VIA_DROPONABLE			0x0100
+
+#define VM_QUERYITEM			0x0375
+#define VM_QUERYITEMATTR		0x0376
+#define VM_QUERYMETRICS			0x0377
+#define VM_QUERYSELECTEDITEM		0x0378
+#define VM_SELECTITEM			0x0379
+#define VM_SETITEM			0x037a
+#define VM_SETITEMATTR			0x037b
+#define VM_SETMETRICS			0x037c
+
+#define VMA_ITEMSIZE			0x0001
+#define VMA_ITEMSPACING			0x0002
+
+#define VN_SELECT			0x0078
+#define VN_ENTER			0x0079
+#define VN_DRAGLEAVE			0x007a
+#define VN_DRAGOVER			0x007b
+#define VN_DROP				0x007c
+#define VN_DROPHELP			0x007d
+#define VN_INITDRAG			0x007e
+#define VN_SETFOCUS			0x007f
+#define VN_KILLFOCUS			0x0080
+#define VN_HELP				0x0081
+
+#define VS_BITMAP			0x0001
+#define VS_ICON				0x0002
+#define VS_TEXT				0x0004
+#define VS_RGB				0x0008
+#define VS_COLORINDEX			0x0010
+#define VS_BORDER			0x0020
+#define VS_ITEMBORDER			0x0040
+#define VS_SCALEBITMAPS			0x0080
+#define VS_RIGHTTOLEFT			0x0100
+#define VS_OWNERDRAW			0x0200
+
+#define VSERR_INVALID_PARAMETERS	(-1)
+
+
+typedef struct _VSCDATA
+{
+  ULONG	 cbSize;
+  USHORT usRowCount;
+  USHORT usColumnCount;
+} VSCDATA;
+typedef VSCDATA *PVSCDATA;
+
+typedef struct _VSDRAGINIT
+{
+  HWND	 hwnd;
+  LONG	 x;
+  LONG	 y;
+  LONG	 cx;
+  LONG	 cy;
+  USHORT usRow;
+  USHORT usColumn;
+} VSDRAGINIT;
+typedef VSDRAGINIT *PVSDRAGINIT;
+
+typedef struct _VSDRAGINFO
+{
+  PDRAGINFO pDragInfo;
+  USHORT    usRow;
+  USHORT    usColumn;
+} VSDRAGINFO;
+typedef VSDRAGINFO *PVSDRAGINFO;
+
+typedef struct _VSTEXT
+{
+  PSZ	pszItemText;
+  ULONG ulBufLen;
+} VSTEXT;
+typedef VSTEXT *PVSTEXT;
+
+#endif /* INCL_WINSTDVALSET */
+
+/* ---------------------------- CONTAINER --------------------------------- */
+
+#if defined (INCL_WINSTDCNR)
+
+#define CA_CONTAINERTITLE		0x00000200
+#define CA_TITLESEPARATOR		0x00000400
+#define CA_TITLELEFT			0x00000800
+#define CA_TITLERIGHT			0x00001000
+#define CA_TITLECENTER			0x00002000
+#define CA_OWNERDRAW			0x00004000
+#define CA_DETAILSVIEWTITLES		0x00008000
+#define CA_ORDEREDTARGETEMPH		0x00010000
+#define CA_DRAWBITMAP			0x00020000
+#define CA_DRAWICON			0x00040000
+#define CA_TITLEREADONLY		0x00080000
+#define CA_OWNERPAINTBACKGROUND		0x00100000
+#define CA_MIXEDTARGETEMPH		0x00200000
+#define CA_TREELINE			0x00400000
+
+#define CCS_EXTENDSEL			0x0001
+#define CCS_MULTIPLESEL			0x0002
+#define CCS_SINGLESEL			0x0004
+#define CCS_AUTOPOSITION		0x0008
+#define CCS_VERIFYPOINTERS		0x0010
+#define CCS_READONLY			0x0020
+#define CCS_MINIRECORDCORE		0x0040
+#define CCS_MINIICONS			0x0800
+#define CCS_NOCONTROLPTR		0x1000
+
+#define CFA_LEFT			0x00000001
+#define CFA_RIGHT			0x00000002
+#define CFA_CENTER			0x00000004
+#define CFA_TOP				0x00000008
+#define CFA_VCENTER			0x00000010
+#define CFA_BOTTOM			0x00000020
+#define CFA_INVISIBLE			0x00000040
+#define CFA_BITMAPORICON		0x00000100
+#define CFA_SEPARATOR			0x00000200
+#define CFA_HORZSEPARATOR		0x00000400
+#define CFA_STRING			0x00000800
+#define CFA_OWNER			0x00001000
+#define CFA_DATE			0x00002000
+#define CFA_TIME			0x00004000
+#define CFA_FIREADONLY			0x00008000
+#define CFA_FITITLEREADONLY		0x00010000
+#define CFA_ULONG			0x00020000
+#define CFA_RANGE			0x00040000
+#define CFA_NEWCOMP			0x00080000
+#define CFA_OBJECT			0x00100000
+#define CFA_LIST			0x00200000
+#define CFA_CLASS			0x00400000
+#define CFA_IGNORE			0x80000000
+
+#define CID_LEFTCOLTITLEWND		0x7ff0
+#define CID_RIGHTCOLTITLEWND		0x7ff1
+#define CID_BLANKBOX			0x7ff2
+#define CID_HSCROLL			0x7ff3
+#define CID_RIGHTHSCROLL		0x7ff4
+#define CID_CNRTITLEWND			0x7ff5
+#define CID_LEFTDVWND			0x7ff7
+#define CID_RIGHTDVWND			0x7ff8
+#define CID_VSCROLL			0x7ff9
+#define CID_MLE				0x7ffa
+
+#define CM_ALLOCDETAILFIELDINFO		0x0330
+#define CM_ALLOCRECORD			0x0331
+#define CM_ARRANGE			0x0332
+#define CM_ERASERECORD			0x0333
+#define CM_FILTER			0x0334
+#define CM_FREEDETAILFIELDINFO		0x0335
+#define CM_FREERECORD			0x0336
+#define CM_HORZSCROLLSPLITWINDOW	0x0337
+#define CM_INSERTDETAILFIELDINFO	0x0338
+#define CM_INSERTRECORD			0x0339
+#define CM_INVALIDATEDETAILFIELDINFO	0x033a
+#define CM_INVALIDATERECORD		0x033b
+#define CM_PAINTBACKGROUND		0x033c
+#define CM_QUERYCNRINFO			0x033d
+#define CM_QUERYDETAILFIELDINFO		0x033e
+#define CM_QUERYDRAGIMAGE		0x033f
+#define CM_QUERYRECORD			0x0340
+#define CM_QUERYRECORDEMPHASIS		0x0341
+#define CM_QUERYRECORDFROMRECT		0x0342
+#define CM_QUERYRECORDRECT		0x0343
+#define CM_QUERYVIEWPORTRECT		0x0344
+#define CM_REMOVEDETAILFIELDINFO	0x0345
+#define CM_REMOVERECORD			0x0346
+#define CM_SCROLLWINDOW			0x0347
+#define CM_SEARCHSTRING			0x0348
+#define CM_SETCNRINFO			0x0349
+#define CM_SETRECORDEMPHASIS		0x034a
+#define CM_SORTRECORD			0x034b
+#define CM_OPENEDIT			0x034c
+#define CM_CLOSEEDIT			0x034d
+#define CM_COLLAPSETREE			0x034e
+#define CM_EXPANDTREE			0x034f
+#define CM_QUERYRECORDINFO		0x0350
+#define CM_INSERTRECORDARRAY		0x0351
+#define CM_MOVETREE			0x0352
+#define CM_SETTEXTVISIBILITY		0x0353
+#define CM_SETGRIDINFO			0x0354
+#define CM_QUERYGRIDINFO		0x0355
+#define CM_SNAPTOGRID			0x0356
+
+#define CMA_TOP				0x0001
+#define CMA_BOTTOM			0x0002
+#define CMA_LEFT			0x0004
+#define CMA_RIGHT			0x0008
+#define CMA_PERIMETER			0x0010
+#define CMA_USER			0x0020
+
+#define CMA_FIRST			0x0010
+#define CMA_LAST			0x0020
+#define CMA_END				0x0040
+#define CMA_PREV			0x0080
+#define CMA_NEXT			0x0100
+
+#define CMA_HORIZONTAL			0x0200
+#define CMA_VERTICAL			0x0400
+#define CMA_ICON			0x0800
+#define CMA_TEXT			0x1000
+#define CMA_PARTIAL			0x2000
+#define CMA_COMPLETE			0x4000
+
+#define CMA_PARENT			0x0001
+#define CMA_FIRSTCHILD			0x0002
+#define CMA_LASTCHILD			0x0004
+
+#define CMA_CNRTITLE			0x0001
+#define CMA_DELTA			0x0002
+#define CMA_FLWINDOWATTR		0x0004
+#define CMA_LINESPACING			0x0008
+#define CMA_PFIELDINFOLAST		0x0010
+
+#define CMA_PSORTRECORD			0x0020
+#define CMA_PTLORIGIN			0x0040
+#define CMA_SLBITMAPORICON		0x0080
+#define CMA_XVERTSPLITBAR		0x0100
+#define CMA_PFIELDINFOOBJECT		0x0200
+
+#define CMA_TREEICON			0x0400
+#define CMA_TREEBITMAP			0x0800
+#define CMA_CXTREEINDENT		0x1000
+#define CMA_CXTREELINE			0x2000
+#define CMA_SLTREEBITMAPORICON		0x4000
+
+#define CMA_ITEMORDER			0x0001
+#define CMA_WINDOW			0x0002
+#define CMA_WORKSPACE			0x0004
+#define CMA_ZORDER			0x0008
+
+#define CMA_DELTATOP			0x0001
+#define CMA_DELTABOT			0x0002
+#define CMA_DELTAHOME			0x0004
+#define CMA_DELTAEND			0x0008
+
+#define CMA_NOREPOSITION		0x0001
+#define CMA_REPOSITION			0x0002
+#define CMA_TEXTCHANGED			0x0004
+#define CMA_ERASE			0x0008
+#define CMA_NOTEXTCHANGED		0x0010
+#define CMA_FILTER			0x1000
+
+#define CMA_FREE			0x0001
+#define CMA_INVALIDATE			0x0002
+
+#define CMA_ARRANGESTANDARD		0x0000
+#define CMA_ARRANGEGRID			0x0001
+#define CMA_ARRANGESELECTED		0x0002
+
+#define CMA_AVAIL			0x0001
+#define CMA_UNAVAIL			0x0002
+
+#define CN_DRAGAFTER			0x0065
+#define CN_DRAGLEAVE			0x0066
+#define CN_DRAGOVER			0x0067
+#define CN_DROP				0x0068
+#define CN_DROPHELP			0x0069
+#define CN_ENTER			0x006a
+#define CN_INITDRAG			0x006b
+#define CN_EMPHASIS			0x006c
+#define CN_KILLFOCUS			0x006d
+#define CN_SCROLL			0x006e
+#define CN_QUERYDELTA			0x006f
+#define CN_SETFOCUS			0x0070
+#define CN_REALLOCPSZ			0x0071
+#define CN_BEGINEDIT			0x0072
+#define CN_ENDEDIT			0x0073
+#define CN_COLLAPSETREE			0x0074
+#define CN_EXPANDTREE			0x0075
+#define CN_HELP				0x0076
+#define CN_CONTEXTMENU			0x0077
+#define CN_VERIFYEDIT			0x0086
+#define CN_PICKUP			0x0087
+#define CN_DROPNOTIFY			0x0088
+#define CN_GRIDRESIZED			0x0089
+
+#define CRA_SELECTED			0x00000001
+#define CRA_TARGET			0x00000002
+#define CRA_CURSORED			0x00000004
+#define CRA_INUSE			0x00000008
+#define CRA_FILTERED			0x00000010
+#define CRA_DROPONABLE			0x00000020
+#define CRA_RECORDREADONLY		0x00000040
+#define CRA_EXPANDED			0x00000080
+#define CRA_COLLAPSED			0x00000100
+#define CRA_PICKED			0x00000200
+#define CRA_LOCKED			0x00000400
+#define CRA_DISABLED			0x00001000
+#define CRA_SOURCE			0x00004000
+#define CRA_IGNORE			0x00008000
+#define CRA_OWNERFREE			0x00010000
+#define CRA_OWNERDRAW			0x00020000
+
+#define CV_TEXT				0x00000001
+#define CV_NAME				0x00000002
+#define CV_ICON				0x00000004
+#define CV_DETAIL			0x00000008
+#define CV_FLOW				0x00000010
+#define CV_MINI				0x00000020
+#define CV_TREE				0x00000040
+#define CV_GRID				0x00000080
+#define CV_EXACTLENGTH			0x10000000
+
+#define PMERR_NOFILTERED_ITEMS		0x1f02
+#define PMERR_COMPARISON_FAILED		0x1f03
+#define PMERR_RECORD_CURRENTLY_INSERTED 0x1f04
+#define PMERR_FI_CURRENTLY_INSERTED	0x1f05
+
+
+typedef struct _TREEITEMDESC
+{
+  HBITMAP  hbmExpanded;
+  HBITMAP  hbmCollapsed;
+  HPOINTER hptrExpanded;
+  HPOINTER hptrCollapsed;
+} TREEITEMDESC;
+typedef TREEITEMDESC *PTREEITEMDESC;
+
+typedef struct _FIELDINFO
+{
+  ULONG		    cb;
+  ULONG		    flData;
+  ULONG		    flTitle;
+  PVOID		    pTitleData;
+  ULONG		    offStruct;
+  PVOID		    pUserData;
+  struct _FIELDINFO *pNextFieldInfo;
+  ULONG		    cxWidth;
+} FIELDINFO;
+typedef FIELDINFO *PFIELDINFO;
+
+typedef struct _RECORDCORE
+{
+  ULONG		     cb;
+  ULONG		     flRecordAttr;
+  POINTL	     ptlIcon;
+  struct _RECORDCORE *preccNextRecord;
+  PSZ		     pszIcon;
+  HPOINTER	     hptrIcon;
+  HPOINTER	     hptrMiniIcon;
+  HBITMAP	     hbmBitmap;
+  HBITMAP	     hbmMiniBitmap;
+  PTREEITEMDESC	     pTreeItemDesc;
+  PSZ		     pszText;
+  PSZ		     pszName;
+  PSZ		     pszTree;
+} RECORDCORE;
+typedef RECORDCORE *PRECORDCORE;
+
+typedef struct _MINIRECORDCORE
+{
+  ULONG			 cb;
+  ULONG			 flRecordAttr;
+  POINTL		 ptlIcon;
+  struct _MINIRECORDCORE *preccNextRecord;
+  PSZ			 pszIcon;
+  HPOINTER		 hptrIcon;
+} MINIRECORDCORE;
+typedef MINIRECORDCORE *PMINIRECORDCORE;
+
+typedef struct _TREEMOVE
+{
+  PRECORDCORE preccMove;
+  PRECORDCORE preccNewParent;
+  PRECORDCORE pRecordOrder;
+  BOOL	      flMoveSiblings;
+} TREEMOVE;
+typedef TREEMOVE *PTREEMOVE;
+
+typedef struct _CNRINFO
+{
+  ULONG	     cb;
+  PVOID	     pSortRecord;
+  PFIELDINFO pFieldInfoLast;
+  PFIELDINFO pFieldInfoObject;
+  PSZ	     pszCnrTitle;
+  ULONG	     flWindowAttr;
+  POINTL     ptlOrigin;
+  ULONG	     cDelta;
+  ULONG	     cRecords;
+  SIZEL	     slBitmapOrIcon;
+  SIZEL	     slTreeBitmapOrIcon;
+  HBITMAP    hbmExpanded;
+  HBITMAP    hbmCollapsed;
+  HPOINTER   hptrExpanded;
+  HPOINTER   hptrCollapsed;
+  LONG	     cyLineSpacing;
+  LONG	     cxTreeIndent;
+  LONG	     cxTreeLine;
+  ULONG	     cFields;
+  LONG	     xVertSplitbar;
+} CNRINFO;
+typedef CNRINFO *PCNRINFO;
+
+typedef struct _GRIDSQUARE
+{
+  ULONG ulNumber;
+  ULONG ulState;
+  RECTL rctlSquare;
+} GRIDSQUARE;
+typedef GRIDSQUARE *PGRIDSQUARE;
+
+typedef struct _GRIDINFO
+{
+  ULONG cb;
+  SHORT cxGrid;
+  SHORT cyGrid;
+  SHORT sGridRows;
+  SHORT sGridCols;
+  LONG	cGridSquares;
+  PGRIDSQUARE pGrid;
+} GRIDINFO;
+typedef GRIDINFO *PGRIDINFO;
+
+typedef struct _CDATE
+{
+  UCHAR	 day;
+  UCHAR	 month;
+  USHORT year;
+} CDATE;
+typedef CDATE *PCDATE;
+
+typedef struct _CTIME
+{
+  UCHAR hours;
+  UCHAR minutes;
+  UCHAR seconds;
+  UCHAR ucReserved;
+} CTIME;
+typedef CTIME *PCTIME;
+
+typedef struct _CNRDRAGINIT
+{
+  HWND	      hwndCnr;
+  PRECORDCORE pRecord;
+  LONG	      x;
+  LONG	      y;
+  LONG	      cx;
+  LONG	      cy;
+} CNRDRAGINIT;
+typedef CNRDRAGINIT *PCNRDRAGINIT;
+
+typedef struct _FIELDINFOINSERT
+{
+  ULONG	     cb;
+  PFIELDINFO pFieldInfoOrder;
+  ULONG	     fInvalidateFieldInfo;
+  ULONG	     cFieldInfoInsert;
+} FIELDINFOINSERT;
+typedef FIELDINFOINSERT *PFIELDINFOINSERT;
+
+typedef struct _RECORDINSERT
+{
+  ULONG	      cb;
+  PRECORDCORE pRecordOrder;
+  PRECORDCORE pRecordParent;
+  ULONG	      fInvalidateRecord;
+  ULONG	      zOrder;
+  ULONG	      cRecordsInsert;
+} RECORDINSERT;
+typedef RECORDINSERT *PRECORDINSERT;
+
+typedef struct _QUERYRECFROMRECT
+{
+  ULONG cb;
+  RECTL rect;
+  ULONG fsSearch;
+} QUERYRECFROMRECT;
+typedef QUERYRECFROMRECT *PQUERYRECFROMRECT;
+
+typedef struct _QUERYRECORDRECT
+{
+  ULONG	      cb;
+  PRECORDCORE pRecord;
+  ULONG	      fRightSplitWindow;
+  ULONG	      fsExtent;
+} QUERYRECORDRECT;
+typedef QUERYRECORDRECT *PQUERYRECORDRECT;
+
+typedef struct _SEARCHSTRING
+{
+  ULONG cb;
+  PSZ	pszSearch;
+  ULONG fsPrefix;
+  ULONG fsCaseSensitive;
+  ULONG usView;
+} SEARCHSTRING;
+typedef SEARCHSTRING *PSEARCHSTRING;
+
+typedef struct _CNRDRAGINFO
+{
+  PDRAGINFO   pDragInfo;
+  PRECORDCORE pRecord;
+} CNRDRAGINFO;
+typedef CNRDRAGINFO *PCNRDRAGINFO;
+
+typedef struct _CNRLAZYDRAGINFO
+{
+  PDRAGINFO   pDragInfo;
+  PRECORDCORE pRecord;
+  HWND	      hwndTarget;
+} CNRLAZYDRAGINFO;
+typedef CNRLAZYDRAGINFO *PCNRLAZYDRAGINFO;
+
+typedef struct _NOTIFYRECORDEMPHASIS
+{
+  HWND	      hwndCnr;
+  PRECORDCORE pRecord;
+  ULONG	      fEmphasisMask;
+} NOTIFYRECORDEMPHASIS;
+typedef NOTIFYRECORDEMPHASIS *PNOTIFYRECORDEMPHASIS;
+
+typedef struct _NOTIFYRECORDENTER
+{
+  HWND	      hwndCnr;
+  ULONG	      fKey;
+  PRECORDCORE pRecord;
+} NOTIFYRECORDENTER;
+typedef NOTIFYRECORDENTER *PNOTIFYRECORDENTER;
+
+typedef struct _NOTIFYDELTA
+{
+  HWND	hwndCnr;
+  ULONG fDelta;
+} NOTIFYDELTA;
+typedef NOTIFYDELTA *PNOTIFYDELTA;
+
+typedef struct _NOTIFYSCROLL
+{
+  HWND	hwndCnr;
+  LONG	lScrollInc;
+  ULONG fScroll;
+} NOTIFYSCROLL;
+typedef NOTIFYSCROLL *PNOTIFYSCROLL;
+
+typedef struct _CNREDITDATA
+{
+  ULONG	      cb;
+  HWND	      hwndCnr;
+  PRECORDCORE pRecord;
+  PFIELDINFO  pFieldInfo;
+  PSZ	      *ppszText;
+  ULONG	      cbText;
+  ULONG	      id;
+} CNREDITDATA;
+typedef CNREDITDATA *PCNREDITDATA;
+
+typedef struct _OWNERBACKGROUND
+{
+  HWND	hwnd;
+  HPS	hps;
+  RECTL rclBackground;
+  LONG	idWindow;
+} OWNERBACKGROUND;
+typedef OWNERBACKGROUND *POWNERBACKGROUND;
+
+typedef struct _CNRDRAWITEMINFO
+{
+  PRECORDCORE pRecord;
+  PFIELDINFO  pFieldInfo;
+} CNRDRAWITEMINFO;
+typedef CNRDRAWITEMINFO *PCNRDRAWITEMINFO;
+
+#endif /* INCL_WINSTDCNR */
+
+/* ------------------------- WORKPLACE SHELL ------------------------------ */
+
+#if defined (INCL_WPCLASS) || !defined (INCL_NOCOMMON)
+
+#define CCHMAXCLASS			3
+
+#define QC_First			0
+#define QC_Next				1
+#define QC_Last				2
+#define QC_FIRST			QC_First
+#define QC_NEXT				QC_Next
+#define QC_LAST				QC_Last
+
+#define CO_FAILIFEXISTS			0
+#define CO_REPLACEIFEXISTS		1
+#define CO_UPDATEIFEXISTS		2
+
+#if !defined (LOCATION_DESKTOP)
+#define LOCATION_DESKTOP		((PSZ)0xffff0001)
+#endif
+
+typedef struct _OBJCLASS
+{
+  struct _OBJCLASS *pNext;
+  PSZ		    pszClassName;
+  PSZ		    pszModName;
+} OBJCLASS;
+typedef OBJCLASS *POBJCLASS;
+
+HOBJECT WinCopyObject (HOBJECT hObjectofObject, HOBJECT hObjectofDest,
+    ULONG ulReserved);
+HOBJECT WinCreateObject (PCSZ pszClassName, PCSZ pszTitle, PCSZ pszSetupString,
+    PCSZ pszLocation, ULONG ulFlags);
+HOBJECT WinCreateShadow (HOBJECT hObjectofObject, HOBJECT hObjectofDest,
+    ULONG ulReserved);
+BOOL WinDeregisterObjectClass (PCSZ pszClassName);
+BOOL WinDestroyObject (HOBJECT hObject);
+BOOL WinEnumObjectClasses (POBJCLASS pObjClass, PULONG pulSize);
+BOOL WinIsSOMDDReady (VOID);
+BOOL WinIsWPDServerReady (VOID);
+HOBJECT WinMoveObject (HOBJECT hObjectofObject, HOBJECT hObjectofDest,
+    ULONG ulReserved);
+BOOL WinOpenObject (HOBJECT hObject, ULONG ulView, BOOL fFlag);
+BOOL WinQueryActiveDesktopPathname (PSZ pszPathName, ULONG ulSize);
+HOBJECT WinQueryObject (PCSZ pszObjectID);
+BOOL WinQueryObjectPath (HOBJECT hobject, PSZ pszPathName, ULONG ulSize);
+BOOL WinRegisterObjectClass (PCSZ pszClassName, PCSZ pszModName);
+BOOL WinReplaceObjectClass (PCSZ pszOldClassName, PCSZ pszNewClassName,
+    BOOL fReplace);
+ULONG WinRestartSOMDD (BOOL fState);
+ULONG WinRestartWPDServer (BOOL fState);
+BOOL WinSaveObject (HOBJECT hObject, BOOL fAsync);
+BOOL WinSetObjectData (HOBJECT hObject, PCSZ pszSetupString);
+
+#endif /* INCL_WPCLASS || !INCL_NOCOMMON */
+
+#if !defined (INCL_NOCOMMON)
+
+BOOL WinFreeFileIcon (HPOINTER hptr);
+HPOINTER WinLoadFileIcon (PCSZ pszFileName, BOOL fPrivate);
+BOOL WinRestoreWindowPos (PCSZ pszAppName, PCSZ pszKeyName, HWND hwnd);
+#if defined (INCL_WINPOINTERS)
+BOOL WinSetFileIcon (PCSZ pszFileName, __const__ ICONINFO *pIconInfo);
+#endif
+BOOL WinShutdownSystem (HAB hab, HMQ hmq);
+BOOL WinStoreWindowPos (PCSZ pszAppName, PCSZ pszKeyName, HWND hwnd);
+
+#endif /* !INCL_NOCOMMON */
+
+/* ---------------------------- SPOOLER ----------------------------------- */
+
+#if defined (INCL_SPL)
+
+#define SPL_ERROR			0
+#define SPL_OK				1
+
+#define SPL_INI_SPOOLER			"PM_SPOOLER"
+#define SPL_INI_QUEUE			"PM_SPOOLER_QUEUE"
+#define SPL_INI_PRINTER			"PM_SPOOLER_PRINTER"
+#define SPL_INI_PRINTERDESCR		"PM_SPOOLER_PRINTER_DESCR"
+#define SPL_INI_QUEUEDESCR		"PM_SPOOLER_QUEUE_DESCR"
+#define SPL_INI_QUEUEDD			"PM_SPOOLER_QUEUE_DD"
+#define SPL_INI_QUEUEDDDATA		"PM_SPOOLER_QUEUE_DDDATA"
+
+#define SPLC_ABORT			1
+#define SPLC_PAUSE			2
+#define SPLC_CONTINUE			3
+
+#define SPLDATA_PRINTERJAM		0x0001
+#define SPLDATA_FORMCHGREQD		0x0002
+#define SPLDATA_CARTCHGREQD		0x0004
+#define SPLDATA_PENCHGREQD		0x0008
+#define SPLDATA_DATAERROR		0x0010
+#define SPLDATA_UNEXPECTERROR		0x0020
+#define SPLDATA_OTHER			0x8000
+
+#define SPLINFO_QPERROR			0x0001
+#define SPLINFO_DDERROR			0x0002
+#define SPLINFO_SPLERROR		0x0004
+#define SPLINFO_OTHERERROR		0x0080
+#define SPLINFO_INFORMATION		0x0100
+#define SPLINFO_WARNING			0x0200
+#define SPLINFO_ERROR			0x0400
+#define SPLINFO_SEVERE			0x0800
+#define SPLINFO_USERINTREQD		0x1000
+
+#define SPLPORT_VERSION_REGULAR		0
+#define SPLPORT_VERSION_VIRTUAL		1
+
+#define SSQL_ERROR			(-1)
+
+#define QP_RAWDATA_BYPASS		0x0001
+#define QP_PRINT_SEPARATOR_PAGE		0x0002
+
+#define QPDAT_ADDRESS			0
+#define QPDAT_DRIVER_NAME		1
+#define QPDAT_DRIVER_DATA		2
+#define QPDAT_DATA_TYPE			3
+#define QPDAT_COMMENT			4
+#define QPDAT_PROC_PARAMS		5
+#define QPDAT_SPL_PARAMS		6
+#define QPDAT_NET_PARAMS		7
+#define QPDAT_DOC_NAME			8
+#define QPDAT_QUEUE_NAME		9
+#define QPDAT_TOKEN			10
+#define QPDAT_JOBID			11
+
+typedef LHANDLE HSPL;
+typedef LHANDLE HSTD;
+typedef HSTD *PHSTD;
+typedef PSZ *PQMOPENDATA;
+typedef unsigned long SPLERR;
+
+typedef struct _SQPOPENDATA
+{
+  PSZ	    pszLogAddress;
+  PSZ	    pszDriverName;
+  PDRIVDATA pdriv;
+  PSZ	    pszDataType;
+  PSZ	    pszComment;
+  PSZ	    pszProcParams;
+  PSZ	    pszSpoolParams;
+  PSZ	    pszNetworkParams;
+  PSZ	    pszDocName;
+  PSZ	    pszQueueName;
+  PSZ	    pszToken;
+  USHORT    idJobId;
+} SQPOPENDATA;
+typedef SQPOPENDATA *PSQPOPENDATA;
+
+
+BOOL SplStdClose (HDC hdc);
+BOOL SplStdDelete (HSTD hMetaFile);
+BOOL SplStdGetBits (HSTD hMetaFile, LONG offData, LONG cbData, PCH pchData);
+BOOL SplStdOpen (HDC hdc);
+LONG SplStdQueryLength (HSTD hMetaFile);
+BOOL SplStdStart (HDC hdc);
+HSTD SplStdStop (HDC hdc);
+
+SPLERR SplControlDevice (PSZ pszComputerName, PSZ pszPortName,
+    ULONG ulControl);
+SPLERR SplCopyJob (PCSZ pszSrcComputerName, PCSZ pszSrcQueueName,
+    ULONG ulSrcJob, PCSZ pszTrgComputerName, PCSZ pszTrgQueueName,
+    PULONG pulTrgJob);
+SPLERR SplCreateDevice (PSZ pszComputerName, ULONG ulLevel, PVOID pBuf,
+    ULONG cbBuf);
+SPLERR SplCreatePort (PCSZ pszComputerName, PCSZ pszPortName,
+    PCSZ pszPortDriver, ULONG ulVersion, PVOID pBuf, ULONG cbBuf);
+SPLERR SplCreateQueue (PSZ pszComputerName, ULONG ulLevel, PVOID pBuf,
+    ULONG cbBuf);
+SPLERR SplDeleteDevice (PSZ pszComputerName, PSZ pszPrintDeviceName);
+SPLERR SplDeleteJob (PSZ pszComputerName, PSZ pszQueueName, ULONG ulJob);
+SPLERR SplDeletePort (PCSZ pszComputerName, PCSZ pszPortName);
+SPLERR SplDeleteQueue (PSZ pszComputerName, PSZ pszQueueName);
+SPLERR SplEnumDevice (PSZ pszComputerName, ULONG ulLevel, PVOID pBuf,
+    ULONG cbBuf, PULONG pcReturned, PULONG pcTotal, PULONG pcbNeeded,
+    PVOID pReserved);
+SPLERR SplEnumDriver (PSZ pszComputerName, ULONG ulLevel, PVOID pBuf,
+    ULONG cbBuf, PULONG pcReturned, PULONG pcTotal, PULONG pcbNeeded,
+    PVOID pReserved);
+SPLERR SplEnumJob (PSZ pszComputerName, PSZ pszQueueName, ULONG ulLevel,
+    PVOID pBuf, ULONG cbBuf, PULONG pcReturned, PULONG pcTotal,
+    PULONG pcbNeeded, PVOID pReserved);
+SPLERR SplEnumPort (PCSZ pszComputerName, ULONG ulLevel, PVOID pBuf,
+    ULONG cbBuf, PULONG pcReturned, PULONG pcTotal, PULONG pcbNeeded,
+    PVOID pReserved);
+SPLERR SplEnumPrinter (PSZ pszComputerName, ULONG uLevel, ULONG flType,
+    PVOID pBuf, ULONG cbbuf, PULONG pcReturned, PULONG pcTotal,
+    PULONG pcbNeeded, PVOID pReserved);
+SPLERR SplEnumQueue (PSZ pszComputerName, ULONG ulLevel, PVOID pBuf,
+    ULONG cbBuf, PULONG pcReturned, PULONG pcTotal, PULONG pcbNeeded,
+    PVOID pReserved);
+SPLERR SplEnumQueueProcessor (PSZ pszComputerName, ULONG ulLevel, PVOID pBuf,
+    ULONG cbBuf, PULONG pcReturned, PULONG pcTotal, PULONG pcbNeeded,
+    PVOID pReserved);
+SPLERR SplHoldJob (PCSZ pszComputerName, PCSZ pszQueueName, ULONG ulJob);
+SPLERR SplHoldQueue (PSZ pszComputerName, PSZ pszQueueName);
+SPLERR SplPurgeQueue (PSZ pszComputerName, PSZ pszQueueName);
+SPLERR SplQueryDevice (PSZ pszComputerName, PSZ pszPrintDeviceName,
+    ULONG ulLevel, PVOID pBuf, ULONG cbBuf, PULONG pcbNeeded);
+SPLERR SplQueryDriver (PCSZ pszComputerName, PCSZ pszDriverName,
+    PCSZ pszPrinterName, ULONG ulLevel, PVOID pBuf, ULONG cbBuf,
+    PULONG pcbNeeded);
+SPLERR SplQueryJob (PSZ pszComputerName, PSZ pszQueueName, ULONG ulJob,
+    ULONG ulLevel, PVOID pBuf, ULONG cbBuf, PULONG pcbNeeded);
+SPLERR SplQueryPort (PCSZ pszComputerName, PCSZ pszPortName, ULONG ulLevel,
+    PVOID pBuf, ULONG cbBuf, PULONG pcbNeeded);
+SPLERR SplQueryQueue (PSZ pszComputerName, PSZ pszQueueName, ULONG ulLevel,
+    PVOID pBuf, ULONG cbBuf, PULONG pcbNeeded);
+SPLERR SplReleaseJob (PCSZ pszComputerName, PCSZ pszQueueName, ULONG ulJob);
+SPLERR SplReleaseQueue (PSZ pszComputerName, PSZ pszQueueName);
+SPLERR SplSetDevice (PSZ pszComputerName, PSZ pszPrintDeviceName,
+    ULONG ulLevel, PVOID pBuf, ULONG cbBuf, ULONG ulParmNum);
+SPLERR SplSetDriver (PCSZ pszComputerName, PCSZ pszDriverName,
+    PCSZ pszPrinterName, ULONG ulLevel, PVOID pBuf, ULONG cbBuf,
+    ULONG ulParmNum);
+SPLERR SplSetJob (PSZ pszComputerName, PSZ pszQueueName, ULONG ulJob,
+    ULONG ulLevel, PVOID pBuf, ULONG cbBuf, ULONG ulParmNum);
+SPLERR SplSetPort (PCSZ pszComputerName, PCSZ pszPortName, ULONG ulLevel,
+    PVOID pBuf, ULONG cbBuf, ULONG ulParmNum);
+SPLERR SplSetQueue (PSZ pszComputerName, PSZ pszQueueName, ULONG ulLevel,
+    PVOID pBuf, ULONG cbBuf, ULONG ulParmNum);
+
+ULONG SplMessageBox (PSZ pszLogAddr, ULONG fErrInfo, ULONG fErrData,
+    PSZ pszText, PSZ pszCaption, ULONG idWindow, ULONG fStyle);
+BOOL SplQmAbort (HSPL hspl);
+BOOL SplQmAbortDoc (HSPL hspl);
+BOOL SplQmClose (HSPL hspl);
+BOOL SplQmEndDoc (HSPL hspl);
+ULONG SplQmGetJobID (HSPL hspl, ULONG ulLevel, PVOID pBuf, ULONG cbBuf,
+    PULONG pcbNeeded);
+BOOL SplQmNewPage (HSPL hspl, ULONG ulPageNumber);
+HSPL SplQmOpen (PSZ pszToken, LONG lCount, PQMOPENDATA pqmdopData);
+BOOL SplQmStartDoc (HSPL hspl, PSZ pszDocName);
+BOOL SplQmWrite (HSPL hspl, LONG lCount, PVOID pData);
+
+#if defined (INCL_SPLDOSPRINT)
+
+#define CNLEN				15
+#define DTLEN				9
+#define PDLEN				8
+#define QNLEN				12
+#define UNLEN				20
+
+#define DRIV_DEVICENAME_SIZE		31
+#define DRIV_NAME_SIZE			8
+#define FORMNAME_SIZE			31
+#define MAXCOMMENTSZ			48
+#define PRINTERNAME_SIZE		32
+#define QP_DATATYPE_SIZE		15
+
+#define PRD_STATUS_MASK			0x0003
+#define PRD_DEVSTATUS			0x0ffc
+
+#define PRD_ACTIVE			0
+#define PRD_PAUSED			1
+
+#define PRD_DELETE			0
+#define PRD_PAUSE			1
+#define PRD_CONT			2
+#define PRD_RESTART			3
+
+#define PRD_LOGADDR_PARMNUM		3
+#define PRD_COMMENT_PARMNUM		7
+#define PRD_DRIVERS_PARMNUM		8
+#define PRD_TIMEOUT_PARMNUM		10
+
+#define PRJ_NOTIFYNAME_PARMNUM		3
+#define PRJ_DATATYPE_PARMNUM		4
+#define PRJ_PARMS_PARMNUM		5
+#define PRJ_POSITION_PARMNUM		6
+#define PRJ_JOBFILEINUSE_PARMNUM	7
+#define PRJ_COMMENT_PARMNUM		11
+#define PRJ_DOCUMENT_PARMNUM		12
+#define PRJ_STATUSCOMMENT_PARMNUM	13
+#define PRJ_PRIORITY_PARMNUM		14
+#define PRJ_PROCPARMS_PARMNUM		16
+#define PRJ_DRIVERDATA_PARMNUM		18
+#define PRJ_SPOOLFILENAME_PARMNUM	19
+#define PRJ_PAGESSPOOLED_PARMNUM	20
+#define PRJ_PAGESSENT_PARMNUM		21
+#define PRJ_PAGESPRINTED_PARMNUM	22
+#define PRJ_TIMEPRINTED_PARMNUM		23
+#define PRJ_EXTENDSTATUS_PARMNUM	24
+#define PRJ_STARTPAGE_PARMNUM		25
+#define PRJ_ENDPAGE_PARMNUM		26
+#define PRJ_MAXPARMNUM			26
+
+#define PRJ_QSTATUS			0x0003
+#define PRJ_DEVSTATUS			0x0ffc
+
+#define PRJ_COMPLETE			0x0004
+#define PRJ_INTERV			0x0008
+#define PRJ_ERROR			0x0010
+#define PRJ_DESTOFFLINE			0x0020
+#define PRJ_DESTPAUSED			0x0040
+#define PRJ_NOTIFY			0x0080
+#define PRJ_DESTNOPAPER			0x0100
+#define PRJ_DESTFORMCHG			0x0200
+#define PRJ_DESTCRTCHG			0x0400
+#define PRJ_DESTPENCHG			0x0800
+#define PRJ_JOBFILEINUSE		0x4000
+#define PRJ_DELETED			0x8000
+
+#define PRJ_QS_QUEUED			0
+#define PRJ_QS_PAUSED			1
+#define PRJ_QS_SPOOLING			2
+#define PRJ_QS_PRINTING			3
+
+#define PRJ_MAX_PRIORITY		99
+#define PRJ_MIN_PRIORITY		1
+#define PRJ_NO_PRIORITY			0
+
+#define PRJ4_INPRINTER			0x0001
+#define PRJ4_STACKED			0x0002
+#define PRJ4_HELDINPRINTER		0x0004
+#define PRJ4_JOBSTARTED			0x0008
+
+#define PRPO_PORT_DRIVER		1
+#define PRPO_PROTOCOL_CNV		2
+#define PRPO_MODE			3
+#define PRPO_PRIORITY			4
+
+#define PRPORT_AUTODETECT		1
+#define PRPORT_DISABLE_BIDI		2
+#define PRPORT_ENABLE_BIDI		3
+
+#define PRQ_PRIORITY_PARMNUM		2
+#define PRQ_STARTTIME_PARMNUM		3
+#define PRQ_UNTILTIME_PARMNUM		4
+#define PRQ_SEPARATOR_PARMNUM		5
+#define PRQ_PROCESSOR_PARMNUM		6
+#define PRQ_DESTINATIONS_PARMNUM	7
+#define PRQ_PARMS_PARMNUM		8
+#define PRQ_COMMENT_PARMNUM		9
+#define PRQ_TYPE_PARMNUM		10
+#define PRQ_PRINTERS_PARMNUM		12
+#define PRQ_DRIVERNAME_PARMNUM		13
+#define PRQ_DRIVERDATA_PARMNUM		14
+#define PRQ_REMOTE_COMPUTER_PARMNUM	15
+#define PRQ_REMOTE_QUEUE_PARMNUM	16
+#define PRQ_MAXPARMNUM			16
+
+#define PRQ_MAX_PRIORITY		1
+#define PRQ_DEF_PRIORITY		5
+#define PRQ_MIN_PRIORITY		9
+#define PRQ_NO_PRIORITY			0
+
+#define PRQ_STATUS_MASK			3
+#define PRQ_ACTIVE			0
+#define PRQ_PAUSED			1
+#define PRQ_ERROR			2
+#define PRQ_PENDING			3
+
+#define PRQ3_PAUSED			0x0001
+#define PRQ3_PENDING			0x0002
+
+#define PRQ3_TYPE_RAW			0x0001
+#define PRQ3_TYPE_BYPASS		0x0002
+#define PRQ3_TYPE_APPDEFAULT		0x0004
+
+#define SPL_PR_QUEUE			0x0001
+#define SPL_PR_DIRECT_DEVICE		0x0002
+#define SPL_PR_QUEUED_DEVICE		0x0004
+#define SPL_PR_LOCAL_ONLY		0x0100
+
+typedef struct _DRIVPROPS
+{
+  PSZ	pszKeyName;
+  ULONG cbBuf;
+  PVOID pBuf;
+} DRIVPROPS;
+typedef DRIVPROPS *PDRIVPROPS;
+
+typedef struct _PRINTERINFO
+{
+  ULONG flType;
+  PSZ	pszComputerName;
+  PSZ	pszPrintDestinationName;
+  PSZ	pszDescription;
+  PSZ	pszLocalName;
+} PRINTERINFO;
+typedef PRINTERINFO *PPRINTERINFO;
+
+typedef struct _PRJINFO
+{
+  USHORT uJobId;
+  CHAR	 szUserName[UNLEN+1];
+  CHAR	 pad_1;
+  CHAR	 szNotifyName[CNLEN+1];
+  CHAR	 szDataType[DTLEN+1];
+  PSZ	 pszParms;
+  USHORT uPosition;
+  USHORT fsStatus;
+  PSZ	 pszStatus;
+  ULONG	 ulSubmitted;
+  ULONG	 ulSize;
+  PSZ	 pszComment;
+} PRJINFO;
+typedef PRJINFO *PPRJINFO;
+
+typedef struct _PRJINFO2
+{
+  USHORT uJobId;
+  USHORT uPriority;
+  PSZ	 pszUserName;
+  USHORT uPosition;
+  USHORT fsStatus;
+  ULONG	 ulSubmitted;
+  ULONG	 ulSize;
+  PSZ	 pszComment;
+  PSZ	 pszDocument;
+} PRJINFO2;
+typedef PRJINFO2 *PPRJINFO2;
+
+typedef struct _PRJINFO3
+{
+  USHORT    uJobId;
+  USHORT    uPriority;
+  PSZ	    pszUserName;
+  USHORT    uPosition;
+  USHORT    fsStatus;
+  ULONG	    ulSubmitted;
+  ULONG	    ulSize;
+  PSZ	    pszComment;
+  PSZ	    pszDocument;
+  PSZ	    pszNotifyName;
+  PSZ	    pszDataType;
+  PSZ	    pszParms;
+  PSZ	    pszStatus;
+  PSZ	    pszQueue;
+  PSZ	    pszQProcName;
+  PSZ	    pszQProcParms;
+  PSZ	    pszDriverName;
+  PDRIVDATA pDriverData;
+  PSZ	    pszPrinterName;
+} PRJINFO3;
+typedef PRJINFO3 *PPRJINFO3;
+
+typedef struct _PRJINFO4
+{
+  USHORT uJobId;
+  USHORT uPriority;
+  PSZ	 pszUserName;
+  USHORT uPosition;
+  USHORT fsStatus;
+  ULONG	 ulSubmitted;
+  ULONG	 ulSize;
+  PSZ	 pszComment;
+  PSZ	 pszDocument;
+  PSZ	 pszSpoolFileName;
+  PSZ	 pszPortName;
+  PSZ	 pszStatus;
+  ULONG	 ulPagesSpooled;
+  ULONG	 ulPagesSent;
+  ULONG	 ulPagesPrinted;
+  ULONG	 ulTimePrinted;
+  ULONG	 ulExtendJobStatus;
+  ULONG	 ulStartPage;
+  ULONG	 ulEndPage;
+} PRJINFO4;
+typedef PRJINFO4 *PPRJINFO4;
+
+typedef struct _PRDINFO
+{
+  CHAR	  szName[PDLEN+1];
+  CHAR	  szUserName[UNLEN+1];
+  USHORT  uJobId;
+  USHORT  fsStatus;
+  PSZ	  pszStatus;
+  USHORT  time;
+} PRDINFO;
+typedef PRDINFO *PPRDINFO;
+
+typedef struct _PRDINFO3
+{
+  PSZ	 pszPrinterName;
+  PSZ	 pszUserName;
+  PSZ	 pszLogAddr;
+  USHORT uJobId;
+  USHORT fsStatus;
+  PSZ	 pszStatus;
+  PSZ	 pszComment;
+  PSZ	 pszDrivers;
+  USHORT time;
+  USHORT usTimeOut;
+} PRDINFO3;
+typedef PRDINFO3 *PPRDINFO3;
+
+typedef struct _PRQINFO
+{
+  CHAR	 szName[QNLEN+1];
+  CHAR	 pad_1;
+  USHORT uPriority;
+  USHORT uStartTime;
+  USHORT uUntilTime;
+  PSZ	 pszSepFile;
+  PSZ	 pszPrProc;
+  PSZ	 pszDestinations;
+  PSZ	 pszParms;
+  PSZ	 pszComment;
+  USHORT fsStatus;
+  USHORT cJobs;
+} PRQINFO;
+typedef PRQINFO *PPRQINFO;
+
+typedef struct _PRQINFO3
+{
+  PSZ	    pszName;
+  USHORT    uPriority;
+  USHORT    uStartTime;
+  USHORT    uUntilTime;
+  USHORT    fsType;
+  PSZ	    pszSepFile;
+  PSZ	    pszPrProc;
+  PSZ	    pszParms;
+  PSZ	    pszComment;
+  USHORT    fsStatus;
+  USHORT    cJobs;
+  PSZ	    pszPrinters;
+  PSZ	    pszDriverName;
+  PDRIVDATA pDriverData;
+} PRQINFO3;
+typedef PRQINFO3 *PPRQINFO3;
+
+typedef struct _PRQINFO6
+{
+  PSZ	    pszName;
+  USHORT    uPriority;
+  USHORT    uStartTime;
+  USHORT    uUntilTime;
+  USHORT    fsType;
+  PSZ	    pszSepFile;
+  PSZ	    pszPrProc;
+  PSZ	    pszParms;
+  PSZ	    pszComment;
+  USHORT    fsStatus;
+  USHORT    cJobs;
+  PSZ	    pszPrinters;
+  PSZ	    pszDriverName;
+  PDRIVDATA pDriverData;
+  PSZ	    pszRemoteComputerName;
+  PSZ	    pszRemoteQueueName;
+} PRQINFO6;
+typedef PRQINFO6 *PPRQINFO6;
+
+typedef struct _PRIDINFO
+{
+  USHORT uJobId;
+  CHAR	 szComputerName[CNLEN+1];
+  CHAR	 szQueueName[QNLEN+1];
+  CHAR	 pad_1;
+} PRIDINFO;
+typedef PRIDINFO *PPRIDINFO;
+
+typedef struct _PRDRIVINFO
+{
+  CHAR szDrivName[DRIV_NAME_SIZE+1+DRIV_DEVICENAME_SIZE+1];
+} PRDRIVINFO;
+typedef PRDRIVINFO *PPRDRIVINFO;
+
+typedef struct _PRDRIVINFO2
+{
+  PSZ	 pszPrinterName;
+  PSZ	 pszDriverName;
+  USHORT usFlags;
+  USHORT cDriverProps;
+} PRDRIVINFO2;
+typedef PRDRIVINFO2 *PPRDRIVINFO2;
+
+typedef struct _PRQPROCINFO
+{
+  CHAR szQProcName[QNLEN+1];
+} PRQPROCINFO;
+typedef PRQPROCINFO *PPRQPROCINFO;
+
+typedef struct _PRPORTINFO
+{
+  CHAR szPortName[PDLEN+1];
+} PRPORTINFO;
+typedef PRPORTINFO *PPRPORTINFO;
+
+typedef struct _PRPORTINFO1
+{
+  PSZ pszPortName;
+  PSZ pszPortDriverName;
+  PSZ pszPortDriverPathName;
+} PRPORTINFO1;
+typedef PRPORTINFO1 *PPRPORTINFO1;
+
+typedef struct _PRPORTINFO2
+{
+  PSZ	pszPortName;
+  PSZ	pszPortDriver;
+  PSZ	pszProtocolConverter;
+  ULONG ulReserved;
+  ULONG ulMode;
+  ULONG ulPriority;
+} PRPORTINFO2;
+typedef PRPORTINFO2 *PPRPORTINFO2;
+
+typedef struct _QMJOBINFO
+{
+  ULONG ulJobID;
+  PSZ	pszComputerName;
+  PSZ	pszQueueName;
+} QMJOBINFO;
+typedef QMJOBINFO *PQMJOBINFO;
+
+#endif /* INCL_SPLDOSPRINT */
+#endif /* INCL_SPL */
+
+/* -------------------------- HELP MANAGER -------------------------------- */
+
+#if defined (INCL_WINHELP)
+
+#define CMIC_HIDE_PANEL_ID		0x0000
+#define CMIC_SHOW_PANEL_ID		0x0001
+#define CMIC_TOGGLE_PANEL_ID		0x0002
+
+#define CTRL_PREVIOUS_ID		((USHORT)0x0001)
+#define CTRL_SEARCH_ID			((USHORT)0x0002)
+#define CTRL_PRINT_ID			((USHORT)0x0003)
+#define CTRL_INDEX_ID			((USHORT)0x0004)
+#define CTRL_CONTENTS_ID		((USHORT)0x0005)
+#define CTRL_BACK_ID			((USHORT)0x0006)
+#define CTRL_FORWARD_ID			((USHORT)0x0007)
+#define CTRL_TUTORIAL_ID		((USHORT)0x00ff)
+#define CTRL_USER_ID_BASE		((USHORT)0x0101)
+
+#define HM_MSG_BASE			0x0220
+#define HM_DISMISS_WINDOW		0x0221
+#define HM_DISPLAY_HELP			0x0222
+#define HM_EXT_HELP			0x0223
+#define HM_GENERAL_HELP			0x0223 /*!*/
+#define HM_SET_ACTIVE_WINDOW		0x0224
+#define HM_LOAD_HELP_TABLE		0x0225
+#define HM_CREATE_HELP_TABLE		0x0226
+#define HM_SET_HELP_WINDOW_TITLE	0x0227
+#define HM_SET_SHOW_PANEL_ID		0x0228
+#define HM_REPLACE_HELP_FOR_HELP	0x0229
+#define HM_REPLACE_USING_HELP		0x0229 /*!*/
+#define HM_HELP_INDEX			0x022a
+#define HM_HELP_CONTENTS		0x022b
+#define HM_KEYS_HELP			0x022c
+#define HM_SET_HELP_LIBRARY_NAME	0x022d
+#define HM_ERROR			0x022e
+#define HM_HELPSUBITEM_NOT_FOUND	0x022f
+#define HM_QUERY_KEYS_HELP		0x0230
+#define HM_TUTORIAL			0x0231
+#define HM_EXT_HELP_UNDEFINED		0x0232
+#define HM_GENERAL_HELP_UNDEFINED	0x0232 /*!*/
+#define HM_ACTIONBAR_COMMAND		0x0233
+#define HM_INFORM			0x0234
+#define HM_SET_OBJCOM_WINDOW		0x0238
+#define HM_UPDATE_OBJCOM_WINDOW_CHAIN	0x0239
+#define HM_QUERY_DDF_DATA		0x023a
+#define HM_INVALIDATE_DDF_DATA		0x023b
+#define HM_QUERY			0x023c
+#define HM_SET_COVERPAGE_SIZE		0x023d
+#define HM_NOTIFY			0x0242
+#define HM_SET_USERDATA			0x0243
+#define HM_CONTROL			0x0244
+
+#define HM_RESOURCEID			0
+#define HM_PANELNAME			1
+
+#define HMERR_NO_FRAME_WND_IN_CHAIN	0x1001
+#define HMERR_INVALID_ASSOC_APP_WND	0x1002
+#define HMERR_INVALID_ASSOC_HELP_INST	0x1003
+#define HMERR_INVALID_DESTROY_HELP_INST 0x1004
+#define HMERR_NO_HELP_INST_IN_CHAIN	0x1005
+#define HMERR_INVALID_HELP_INSTANCE_HDL 0x1006
+#define HMERR_INVALID_QUERY_APP_WND	0x1007
+#define HMERR_HELP_INST_CALLED_INVALID	0x1008
+#define HMERR_HELPTABLE_UNDEFINE	0x1009
+#define HMERR_HELP_INSTANCE_UNDEFINE	0x100a
+#define HMERR_HELPITEM_NOT_FOUND	0x100b
+#define HMERR_INVALID_HELPSUBITEM_SIZE	0x100c
+#define HMERR_HELPSUBITEM_NOT_FOUND	0x100d
+
+#define HMERR_INDEX_NOT_FOUND		0x2001
+#define HMERR_CONTENT_NOT_FOUND		0x2002
+#define HMERR_OPEN_LIB_FILE		0x2003
+#define HMERR_READ_LIB_FILE		0x2004
+#define HMERR_CLOSE_LIB_FILE		0x2005
+#define HMERR_INVALID_LIB_FILE		0x2006
+#define HMERR_NO_MEMORY			0x2007
+#define HMERR_ALLOCATE_SEGMENT		0x2008
+#define HMERR_FREE_MEMORY		0x2009
+#define HMERR_PANEL_NOT_FOUND		0x2010
+#define HMERR_DATABASE_NOT_OPEN		0x2011
+#define HMERR_LOAD_DLL			0x2013
+
+#define HMPANELTYPE_NUMBER		0
+#define HMPANELTYPE_NAME		1
+
+#define HMQVP_NUMBER			0x0001
+#define HMQVP_NAME			0x0002
+#define HMQVP_GROUP			0x0003
+
+#define HMQW_COVERPAGE			0x0001
+#define HMQW_INDEX			0x0002
+#define HMQW_TOC			0x0003
+#define HMQW_SEARCH			0x0004
+#define HMQW_VIEWPAGES			0x0005
+#define HMQW_LIBRARY			0x0006
+#define HMQW_VIEWPORT			0x0007
+#define HMQW_OBJCOM_WINDOW		0x0008
+#define HMQW_INSTANCE			0x0009
+#define HMQW_ACTIVEVIEWPORT		0x000a
+#define CONTROL_SELECTED		0x000b
+
+#define HMQW_GROUP_VIEWPORT		0x00f1
+#define HMQW_RES_VIEWPORT		0x00f2
+#define USERDATA			0x00f3
+
+#define HWND_PARENT			(HWND)NULL
+
+#define OPEN_COVERPAGE			0x0001
+#define OPEN_PAGE			0x0002
+#define SWAP_PAGE			0x0003
+#define OPEN_TOC			0x0004
+#define OPEN_INDEX			0x0005
+#define OPEN_HISTORY			0x0006
+#define OPEN_SEARCH_HIT_LIST		0x0007
+#define OPEN_LIBRARY			0x0008
+
+
+typedef USHORT HELPSUBTABLE;
+typedef HELPSUBTABLE *PHELPSUBTABLE;
+
+
+typedef struct _ACVP
+{
+  ULONG cb;
+  HAB	hAB;
+  HMQ	hmq;
+  ULONG ObjectID;
+  HWND	hWndParent;
+  HWND	hWndOwner;
+  HWND	hWndACVP;
+} ACVP;
+typedef ACVP *PACVP;
+
+typedef struct _HELPTABLE
+{
+  USHORT	idAppWindow;
+  PHELPSUBTABLE phstHelpSubTable;
+  USHORT	idExtPanel;
+} HELPTABLE;
+typedef HELPTABLE *PHELPTABLE;
+
+typedef struct _HELPINIT
+{
+  ULONG	     cb;
+  ULONG	     ulReturnCode;
+  PSZ	     pszTutorialName;
+  PHELPTABLE phtHelpTable;
+  HMODULE    hmodHelpTableModule;
+  HMODULE    hmodAccelActionBarModule;
+  ULONG	     idAccelTable;
+  ULONG	     idActionBar;
+  PSZ	     pszHelpWindowTitle;
+  ULONG	     fShowPanelId;
+  PSZ	     pszHelpLibraryName;
+} HELPINIT;
+typedef HELPINIT *PHELPINIT;
+
+BOOL WinAssociateHelpInstance (HWND hwndHelpInstance, HWND hwndApp);
+HWND WinCreateHelpInstance (HAB hab, PHELPINIT phinitHMInitStructure);
+BOOL WinCreateHelpTable (HWND hwndHelpInstance,
+    __const__ HELPTABLE *phtHelpTable);
+BOOL WinDestroyHelpInstance (HWND hwndHelpInstance);
+BOOL WinLoadHelpTable (HWND hwndHelpInstance, ULONG idHelpTable,
+    HMODULE Module);
+HWND WinQueryHelpInstance (HWND hwndApp);
+
+#endif /* INCL_WINHELP */
+
+
+#if defined (INCL_DDF)
+
+#define ART_RUNIN			0x0010
+#define ART_LEFT			0x0001
+#define ART_RIGHT			0x0002
+#define ART_CENTER			0x0004
+
+#define CLR_UNCHANGED			(-6)
+
+#define HMBT_NONE			1
+#define HMBT_ALL			2
+#define HMBT_FIT			3
+
+#define HMERR_DDF_MEMORY		0x3001
+#define HMERR_DDF_ALIGN_TYPE		0x3002
+#define HMERR_DDF_BACKCOLOR		0x3003
+#define HMERR_DDF_FORECOLOR		0x3004
+#define HMERR_DDF_FONTSTYLE		0x3005
+#define HMERR_DDF_REFTYPE		0x3006
+#define HMERR_DDF_LIST_UNCLOSED		0x3007
+#define HMERR_DDF_LIST_UNINITIALIZED	0x3008
+#define HMERR_DDF_LIST_BREAKTYPE	0x3009
+#define HMERR_DDF_LIST_SPACING		0x300A
+#define HMERR_DDF_HINSTANCE		0x300B
+#define HMERR_DDF_EXCEED_MAX_LENGTH	0x300C
+#define HMERR_DDF_EXCEED_MAX_INC	0x300D
+#define HMERR_DDF_INVALID_DDF		0x300E
+#define HMERR_DDF_FORMAT_TYPE		0x300F
+#define HMERR_DDF_INVALID_PARM		0x3010
+#define HMERR_DDF_INVALID_FONT		0x3011
+#define HMERR_DDF_SEVERE		0x3012
+
+#define HMLS_SINGLELINE			1
+#define HMLS_DOUBLELINE			2
+
+#define REFERENCE_BY_ID			0
+#define REFERENCE_BY_RES		1
+
+typedef VOID *HDDF;
+
+BOOL DdfBeginList (HDDF hddf, ULONG ulWidthDT, ULONG fBreakType,
+    ULONG fSpacing);
+BOOL DdfBitmap (HDDF hddf, HBITMAP hbm, ULONG fAlign);
+BOOL DdfEndList (HDDF hddf);
+BOOL DdfHyperText (HDDF hddf, PCSZ pszText, PCSZ pszReference,
+    ULONG fReferenceType);
+BOOL DdfInform (HDDF hddf, PCSZ pszText, ULONG resInformNumber);
+HDDF DdfInitialize (HWND hwndHelpInstance, ULONG cbBuffer, ULONG ulIncrement);
+BOOL DdfListItem (HDDF hddf, PCSZ pszTerm, PCSZ pszDescription);
+BOOL DdfMetafile (HDDF hddf, HMF hmf, __const__ RECTL *prclRect);
+BOOL DdfPara (HDDF hddf);
+BOOL DdfSetColor (HDDF hddf, COLOR fBackColor, COLOR fForColor);
+BOOL DdfSetFont (HDDF hddf, PCSZ pszFaceName, ULONG ulWidth, ULONG ulHeight);
+BOOL DdfSetFontStyle (HDDF hddf, ULONG fFontStyle);
+BOOL DdfSetFormat (HDDF hddf, ULONG fFormatType);
+BOOL DdfSetTextAlign (HDDF hddf, ULONG fAlign);
+BOOL DdfText (HDDF hddf, PCSZ pszText);
+
+#endif /* INCL_DDF */
+
+/* ---------------------- Advanced Video ---------------------------------- */
+
+#if defined (INCL_FONTFILEFORMAT)
+
+#define FONTDEFFONT1			0x0047
+#define FONTDEFFONT2			0x0042
+#define FONTDEFFONT3			0x0042
+#define FONTDEFCHAR1			0x0081
+#define FONTDEFCHAR2			0x0081
+#define FONTDEFCHAR3			0x00b8
+#define FONTDEFDEVFONT			0x2000
+#define FONTDEFFOCA32			0x4000
+#define SPACE_UNDEF			0x8000
+
+#define FONT_SIGNATURE			0xfffffffe
+#define FONT_METRICS			0x00000001
+#define FONT_DEFINITION			0x00000002
+#define FONT_KERNPAIRS			0x00000003
+#define FONT_ADDITIONALMETRICS		0x00000004
+#define FONT_ENDRECORD			0xffffffff
+
+#define QUERY_PUBLIC_FONTS		0x0001
+#define QUERY_PRIVATE_FONTS		0x0002
+
+#define CDEF_GENERIC			0x0001
+#define CDEF_BOLD			0x0002
+#define CDEF_ITALIC			0x0004
+#define CDEF_UNDERSCORE			0x0008
+#define CDEF_STRIKEOUT			0x0010
+#define CDEF_OUTLINE			0x0020
+
+typedef struct _FOCAMETRICS
+{
+  ULONG	 ulIdentity;
+  ULONG	 ulSize;
+  CHAR	 szFamilyname[32];
+  CHAR	 szFacename[32];
+  SHORT	 usRegistryId;
+  SHORT	 usCodePage;
+  SHORT	 yEmHeight;
+  SHORT	 yXHeight;
+  SHORT	 yMaxAscender;
+  SHORT	 yMaxDescender;
+  SHORT	 yLowerCaseAscent;
+  SHORT	 yLowerCaseDescent;
+  SHORT	 yInternalLeading;
+  SHORT	 yExternalLeading;
+  SHORT	 xAveCharWidth;
+  SHORT	 xMaxCharInc;
+  SHORT	 xEmInc;
+  SHORT	 yMaxBaselineExt;
+  SHORT	 sCharSlope;
+  SHORT	 sInlineDir;
+  SHORT	 sCharRot;
+  USHORT usWeightClass;
+  USHORT usWidthClass;
+  SHORT	 xDeviceRes;
+  SHORT	 yDeviceRes;
+  SHORT	 usFirstChar;
+  SHORT	 usLastChar;
+  SHORT	 usDefaultChar;
+  SHORT	 usBreakChar;
+  SHORT	 usNominalPointSize;
+  SHORT	 usMinimumPointSize;
+  SHORT	 usMaximumPointSize;
+  SHORT	 fsTypeFlags;
+  SHORT	 fsDefn;
+  SHORT	 fsSelectionFlags;
+  SHORT	 fsCapabilities;
+  SHORT	 ySubscriptXSize;
+  SHORT	 ySubscriptYSize;
+  SHORT	 ySubscriptXOffset;
+  SHORT	 ySubscriptYOffset;
+  SHORT	 ySuperscriptXSize;
+  SHORT	 ySuperscriptYSize;
+  SHORT	 ySuperscriptXOffset;
+  SHORT	 ySuperscriptYOffset;
+  SHORT	 yUnderscoreSize;
+  SHORT	 yUnderscorePosition;
+  SHORT	 yStrikeoutSize;
+  SHORT	 yStrikeoutPosition;
+  SHORT	 usKerningPairs;
+  SHORT	 sFamilyClass;
+  PSZ	 pszDeviceNameOffset;
+} FOCAMETRICS;
+typedef FOCAMETRICS *PFOCAMETRICS;
+
+typedef struct _FONTFILEMETRICS
+{
+  ULONG	 ulIdentity;
+  ULONG	 ulSize;
+  CHAR	 szFamilyname[32];
+  CHAR	 szFacename[32];
+  SHORT	 usRegistryId;
+  SHORT	 usCodePage;
+  SHORT	 yEmHeight;
+  SHORT	 yXHeight;
+  SHORT	 yMaxAscender;
+  SHORT	 yMaxDescender;
+  SHORT	 yLowerCaseAscent;
+  SHORT	 yLowerCaseDescent;
+  SHORT	 yInternalLeading;
+  SHORT	 yExternalLeading;
+  SHORT	 xAveCharWidth;
+  SHORT	 xMaxCharInc;
+  SHORT	 xEmInc;
+  SHORT	 yMaxBaselineExt;
+  SHORT	 sCharSlope;
+  SHORT	 sInlineDir;
+  SHORT	 sCharRot;
+  USHORT usWeightClass;
+  USHORT usWidthClass;
+  SHORT	 xDeviceRes;
+  SHORT	 yDeviceRes;
+  SHORT	 usFirstChar;
+  SHORT	 usLastChar;
+  SHORT	 usDefaultChar;
+  SHORT	 usBreakChar;
+  SHORT	 usNominalPointSize;
+  SHORT	 usMinimumPointSize;
+  SHORT	 usMaximumPointSize;
+  SHORT	 fsTypeFlags;
+  SHORT	 fsDefn;
+  SHORT	 fsSelectionFlags;
+  SHORT	 fsCapabilities;
+  SHORT	 ySubscriptXSize;
+  SHORT	 ySubscriptYSize;
+  SHORT	 ySubscriptXOffset;
+  SHORT	 ySubscriptYOffset;
+  SHORT	 ySuperscriptXSize;
+  SHORT	 ySuperscriptYSize;
+  SHORT	 ySuperscriptXOffset;
+  SHORT	 ySuperscriptYOffset;
+  SHORT	 yUnderscoreSize;
+  SHORT	 yUnderscorePosition;
+  SHORT	 yStrikeoutSize;
+  SHORT	 yStrikeoutPosition;
+  SHORT	 usKerningPairs;
+  SHORT	 sFamilyClass;
+  ULONG	 ulReserved;
+  PANOSE panose;
+} FONTFILEMETRICS;
+typedef FONTFILEMETRICS *PFONTFILEMETRICS;
+
+typedef struct _FONTDEFINITIONHEADER
+{
+  ULONG ulIdentity;
+  ULONG ulSize;
+  SHORT fsFontdef;
+  SHORT fsChardef;
+  SHORT usCellSize;
+  SHORT xCellWidth;
+  SHORT yCellHeight;
+  SHORT xCellIncrement;
+  SHORT xCellA;
+  SHORT xCellB;
+  SHORT xCellC;
+  SHORT pCellBaseOffset;
+} FONTDEFINITIONHEADER;
+typedef FONTDEFINITIONHEADER *PFONTDEFINITIONHEADER;
+
+typedef struct _FONTSIGNATURE
+{
+  ULONG ulIdentity;
+  ULONG ulSize;
+  CHAR	achSignature[12];
+} FONTSIGNATURE;
+typedef FONTSIGNATURE *PFONTSIGNATURE;
+
+typedef struct _ADDITIONALMETRICS
+{
+  ULONG	 ulIdentity;
+  ULONG	 ulSize;
+  PANOSE panose;
+} ADDITIONALMETRICS;
+typedef ADDITIONALMETRICS *PADDITIONALMETRICS;
+
+typedef struct _FOCAFONT
+{
+  FONTSIGNATURE	       fsSignature;
+  FOCAMETRICS	       fmMetrics;
+  FONTDEFINITIONHEADER fdDefinitions;
+} FOCAFONT;
+typedef FOCAFONT *PFOCAFONT;
+
+typedef FOCAFONT FOCAFONT32;
+typedef FOCAFONT32 *PFOCAFONT32;
+
+#endif /* INCL_FONTFILEFORMAT */
+
+/* ---------------------- Advanced Video ---------------------------------- */
+
+#if defined (INCL_AVIO)
+
+#define FORMAT_CGA			0x0001
+#define FORMAT_4BYTE			0x0003
+
+#define VQF_PUBLIC			0x0001
+#define VQF_PRIVATE			0x0002
+
+typedef USHORT HVPS;
+typedef HVPS *PHVPS;
+
+USHORT VioAssociate (HDC hdc, HVPS hvps);
+USHORT VioCreateLogFont (PFATTRS pfatattrs, LONG llcid, PSTR8 pName,
+    HVPS hvps);
+USHORT VioCreatePS (PHVPS phvps, SHORT sDepth, SHORT sWidth, SHORT sFormat,
+    SHORT sAttrs, HVPS hvpsReserved);
+USHORT VioDeleteSetId (LONG llcid, HVPS hvps);
+USHORT VioDestroyPS (HVPS hvps);
+USHORT VioGetDeviceCellSize (PSHORT psHeight, PSHORT psWidth, HVPS hvps);
+USHORT VioGetOrg (PSHORT psRow, PSHORT psColumn, HVPS hvps);
+USHORT VioQueryFonts (PLONG plRemfonts, PFONTMETRICS afmMetrics,
+    LONG lMetricsLength, PLONG plFonts, PSZ pszFacename, ULONG flOptions,
+    HVPS hvps);
+USHORT VioQuerySetIds (PLONG allcids, PSTR8 pNames, PLONG alTypes, LONG lcount,
+    HVPS hvps);
+USHORT VioSetDeviceCellSize (SHORT sHeight, SHORT sWidth, HVPS hvps);
+USHORT VioSetOrg (SHORT sRow, SHORT sColumn, HVPS hvps);
+USHORT VioShowPS (SHORT sDepth, SHORT sWidth, SHORT soffCell, HVPS hvps);
+
+MRESULT WinDefAVioWindowProc (HWND hwnd, USHORT msg, ULONG mp1, ULONG mp2);
+
+#endif /* INCL_AVIO */
+
+/* --------------------------- MONITORS ----------------------------------- */
+
+#if defined (INCL_DOSMONITORS)
+
+#define MONITOR_DEFAULT		0x0000
+#define MONITOR_BEGIN		0x0001
+#define MONITOR_END		0x0002
+
+typedef SHANDLE HMONITOR;
+typedef HMONITOR *PHMONITOR;
+
+typedef struct _MONIN
+{
+  USHORT cb;
+  BYTE	 abReserved[18];
+  BYTE	 abBuffer[108];
+} MONIN;
+typedef MONIN *PMONIN;
+
+typedef struct _MONOUT
+{
+  USHORT cb;
+  UCHAR	 buffer[18];
+  BYTE	 abBuf[108];
+} MONOUT;
+typedef MONOUT *PMONOUT;
+
+USHORT DosMonOpen (PSZ pszDevName, PHMONITOR phmon);
+USHORT DosMonClose (HMONITOR hmon);
+USHORT DosMonReg (HMONITOR hmon, PBYTE pbInBuf, PBYTE pbOutBuf,
+    USHORT fPosition, USHORT usIndex);
+USHORT DosMonRead (PBYTE pbInBuf, USHORT fWait, PBYTE pbDataBuf,
+    PUSHORT pcbData);
+USHORT DosMonWrite (PBYTE pbOutBuf, PBYTE pbDataBuf, USHORT cbData);
+
+#endif /* INCL_DOSMONITORS */
+
+/* -------------------------- SUBSYSTEMS ---------------------------------- */
+
+#if defined (INCL_KBD)
+
+#define IO_WAIT				0
+#define IO_NOWAIT			1
+
+#define KBDSTF_RIGHTSHIFT		0x0001
+#define KBDSTF_LEFTSHIFT		0x0002
+#define KBDSTF_CONTROL			0x0004
+#define KBDSTF_ALT			0x0008
+#define KBDSTF_SCROLLLOCK_ON		0x0010
+#define KBDSTF_NUMLOCK_ON		0x0020
+#define KBDSTF_CAPSLOCK_ON		0x0040
+#define KBDSTF_INSERT_ON		0x0080
+#define KBDSTF_LEFTCONTROL		0x0100
+#define KBDSTF_LEFTALT			0x0200
+#define KBDSTF_RIGHTCONTROL		0x0400
+#define KBDSTF_RIGHTALT			0x0800
+#define KBDSTF_SCROLLLOCK		0x1000
+#define KBDSTF_NUMLOCK			0x2000
+#define KBDSTF_CAPSLOCK			0x4000
+#define KBDSTF_SYSREQ			0x8000
+
+#define KBDTRF_SHIFT_KEY_IN		0x01
+#define KBDTRF_EXTENDED_CODE		0x02
+#define KBDTRF_CONVERSION_REQUEST	0x20
+#define KBDTRF_FINAL_CHAR_IN		0x40
+#define KBDTRF_INTERIM_CHAR_IN		0x80
+
+#define KEYBOARD_ECHO_ON		0x0001
+#define KEYBOARD_ECHO_OFF		0x0002
+#define KEYBOARD_BINARY_MODE		0x0004
+#define KEYBOARD_ASCII_MODE		0x0008
+#define KEYBOARD_MODIFY_STATE		0x0010
+#define KEYBOARD_MODIFY_INTERIM		0x0020
+#define KEYBOARD_MODIFY_TURNAROUND	0x0040
+#define KEYBOARD_2B_TURNAROUND		0x0080
+#define KEYBOARD_SHIFT_REPORT		0x0100
+
+#define KR_KBDCHARIN			0x00000001
+#define KR_KBDPEEK			0x00000002
+#define KR_KBDFLUSHBUFFER		0x00000004
+#define KR_KBDGETSTATUS			0x00000008
+#define KR_KBDSETSTATUS			0x00000010
+#define KR_KBDSTRINGIN			0x00000020
+#define KR_KBDOPEN			0x00000040
+#define KR_KBDCLOSE			0x00000080
+#define KR_KBDGETFOCUS			0x00000100
+#define KR_KBDFREEFOCUS			0x00000200
+#define KR_KBDGETCP			0x00000400
+#define KR_KBDSETCP			0x00000800
+#define KR_KBDXLATE			0x00001000
+#define KR_KBDSETCUSTXT			0x00002000
+
+typedef USHORT HKBD;
+typedef HKBD *PHKBD;
+
+typedef struct _KBDKEYINFO
+{
+  UCHAR	 chChar;
+  UCHAR	 chScan;
+  UCHAR	 fbStatus;
+  UCHAR	 bNlsShift;
+  USHORT fsState;
+  ULONG	 time;
+} KBDKEYINFO;
+typedef KBDKEYINFO *PKBDKEYINFO;
+
+typedef struct _KBDINFO
+{
+  USHORT cb;
+  USHORT fsMask;
+  USHORT chTurnAround;
+  USHORT fsInterim;
+  USHORT fsState;
+} KBDINFO;
+typedef KBDINFO *PKBDINFO;
+
+typedef struct _KBDHWID
+{
+  USHORT cb;
+  USHORT idKbd;
+  USHORT usReserved1;
+  USHORT usReserved2;
+} KBDHWID;
+typedef KBDHWID *PKBDHWID;
+
+typedef struct _KBDTRANS
+{
+  UCHAR	 chChar;
+  UCHAR	 chScan;
+  UCHAR	 fbStatus;
+  UCHAR	 bNlsShift;
+  USHORT fsState;
+  ULONG	 time;
+  USHORT fsDD;
+  USHORT fsXlate;
+  USHORT fsShift;
+  USHORT sZero;
+} KBDTRANS;
+typedef KBDTRANS *PKBDTRANS;
+
+typedef struct _STRINGINBUF
+{
+  USHORT cb;
+  USHORT cchIn;
+} STRINGINBUF;
+typedef STRINGINBUF *PSTRINGINBUF;
+
+USHORT KbdCharIn (PKBDKEYINFO pkbci, USHORT fWait, HKBD hkbd);
+USHORT KbdClose (HKBD hkbd);
+USHORT KbdDeRegister (VOID);
+USHORT KbdFlushBuffer (HKBD hkbd);
+USHORT KbdFreeFocus (HKBD hkbd);
+USHORT KbdGetCp (ULONG ulReserved, PUSHORT pidCP, HKBD hkbd);
+USHORT KbdGetFocus (USHORT fWait, HKBD hkbd);
+USHORT KbdGetHWID (PKBDHWID pkbdhwid, HKBD hkbd);
+USHORT KbdGetStatus (PKBDINFO pkbdinfo, HKBD hkbd);
+USHORT KbdOpen (PHKBD phkbd);
+USHORT KbdPeek (PKBDKEYINFO pkbci, HKBD hkbd);
+USHORT KbdRegister (PCSZ pszModName, PCSZ pszEntryName, ULONG ulFunMask);
+USHORT KbdSetCp (USHORT usReserved, USHORT idCP, HKBD hkbd);
+USHORT KbdSetCustXt (PUSHORT pusCodePage, HKBD hkbd);
+USHORT KbdSetFgnd (VOID);
+USHORT KbdSetHWID (PKBDHWID pkbdhwid, HKBD hkbd);
+USHORT KbdSetStatus (PKBDINFO pkbdinfo, HKBD hkbd);
+USHORT KbdStringIn (PCH pch, PSTRINGINBUF pchIn, USHORT fWait, HKBD hkbd);
+USHORT KbdSynch (USHORT fWait);
+USHORT KbdXlate (PKBDTRANS pkbdtrans, HKBD hkbd);
+
+#endif /* INCL_KBD */
+
+#if defined (INCL_VIO)
+
+#define ANSI_OFF			0
+#define ANSI_ON				1
+
+#define COLORS_2			0x01
+#define COLORS_4			0x02
+#define COLORS_16			0x04
+
+#define VGMT_OTHER			0x01
+#define VGMT_GRAPHICS			0x02
+#define VGMT_DISABLEBURST		0x04
+
+#define VP_NOWAIT			0x0000
+#define VP_WAIT				0x0001
+#define VP_OPAQUE			0x0000
+#define VP_TRANSPARENT			0x0002
+
+#define VMWR_POPUP			0
+#define VMWN_POPUP			0
+
+#define VSRWI_SAVEANDREDRAW		0
+#define VSRWI_REDRAW			1
+
+#define VSRWN_SAVE			0
+#define VSRWN_REDRAW			1
+
+#define UNDOI_GETOWNER			0
+#define UNDOI_RELEASEOWNER		1
+
+#define UNDOK_ERRORCODE			0
+#define UNDOK_TERMINATE			1
+
+#define LOCKIO_NOWAIT			0
+#define LOCKIO_WAIT			1
+
+#define LOCK_SUCCESS			0
+#define LOCK_FAIL			1
+
+#define VCC_SBCSCHAR			0
+#define VCC_DBCSFULLCHAR		1
+#define VCC_DBCS1STHALF			2
+#define VCC_DBCS2NDHALF			3
+
+#define VGFI_GETCURFONT			0
+#define VGFI_GETROMFONT			1
+
+#define VIO_CONFIG_CURRENT		0
+#define VIO_CONFIG_PRIMARY		1
+#define VIO_CONFIG_SECONDARY		2
+
+#define DISPLAY_MONOCHROME		0
+#define DISPLAY_CGA			1
+#define DISPLAY_EGA			2
+#define DISPLAY_VGA			3
+#define DISPLAY_8514A			7
+#define DISPLAY_IMAGEADAPTER		8
+#define DISPLAY_XGA			9
+
+#define MONITOR_MONOCHROME		0x0000
+#define MONITOR_COLOR			0x0001
+#define MONITOR_ENHANCED		0x0002
+#define MONITOR_8503			0x0003
+#define MONITOR_851X_COLOR		0x0004
+#define MONITOR_8514			0x0009
+#define MONITOR_FLATPANEL		0x000a
+#define MONITOR_8507_8604		0x000b
+#define MONITOR_8515			0x000c
+#define MONITOR_9515			0x000f
+#define MONITOR_9517			0x0011
+#define MONITOR_9518			0x0012
+
+#define VR_VIOGETCURPOS			0x00000001
+#define VR_VIOGETCURTYPE		0x00000002
+#define VR_VIOGETMODE			0x00000004
+#define VR_VIOGETBUF			0x00000008
+#define VR_VIOGETPHYSBUF		0x00000010
+#define VR_VIOSETCURPOS			0x00000020
+#define VR_VIOSETCURTYPE		0x00000040
+#define VR_VIOSETMODE			0x00000080
+#define VR_VIOSHOWBUF			0x00000100
+#define VR_VIOREADCHARSTR		0x00000200
+#define VR_VIOREADCELLSTR		0x00000400
+#define VR_VIOWRTNCHAR			0x00000800
+#define VR_VIOWRTNATTR			0x00001000
+#define VR_VIOWRTNCELL			0x00002000
+#define VR_VIOWRTTTY			0x00004000
+#define VR_VIOWRTCHARSTR		0x00008000
+#define VR_VIOWRTCHARSTRATT		0x00010000
+#define VR_VIOWRTCELLSTR		0x00020000
+#define VR_VIOSCROLLUP			0x00040000
+#define VR_VIOSCROLLDN			0x00080000
+#define VR_VIOSCROLLLF			0x00100000
+#define VR_VIOSCROLLRT			0x00200000
+#define VR_VIOSETANSI			0x00400000
+#define VR_VIOGETANSI			0x00800000
+#define VR_VIOPRTSC			0x01000000
+#define VR_VIOSCRLOCK			0x02000000
+#define VR_VIOSCRUNLOCK			0x04000000
+#define VR_VIOSAVREDRAWWAIT		0x08000000
+#define VR_VIOSAVREDRAWUNDO		0x10000000
+#define VR_VIOPOPUP			0x20000000
+#define VR_VIOENDPOPUP			0x40000000
+#define VR_VIOPRTSCTOGGLE		0x80000000
+
+#define VR_VIOMODEWAIT			0x00000001
+#define VR_VIOMODEUNDO			0x00000002
+#define VR_VIOGETFONT			0x00000004
+#define VR_VIOGETCONFIG			0x00000008
+#define VR_VIOSETCP			0x00000010
+#define VR_VIOGETCP			0x00000020
+#define VR_VIOSETFONT			0x00000040
+#define VR_VIOGETSTATE			0x00000080
+#define VR_VIOSETSTATE			0x00000100
+
+
+typedef USHORT HVIO;
+typedef HVIO *PHVIO;
+
+
+typedef struct _VIOMODEINFO
+{
+  USHORT cb;
+  UCHAR	 fbType;
+  UCHAR	 color;
+  USHORT col;
+  USHORT row;
+  USHORT hres;
+  USHORT vres;
+  UCHAR	 fmt_ID;
+  UCHAR	 attrib;
+  ULONG	 buf_addr;
+  ULONG	 buf_length;
+  ULONG	 full_length;
+  ULONG	 partial_length;
+  PCH	 ext_data_addr;
+} VIOMODEINFO;
+typedef VIOMODEINFO *PVIOMODEINFO;
+
+typedef struct _VIOCONFIGINFO
+{
+  USHORT cb;
+  USHORT adapter;
+  USHORT display;
+  ULONG	 cbMemory;
+  USHORT Configuration;
+  USHORT VDHVersion;
+  USHORT Flags;
+  ULONG	 HWBufferSize;
+  ULONG	 FullSaveSize;
+  ULONG	 PartSaveSize;
+  USHORT EMAdaptersOFF;
+  USHORT EMDisplaysOFF;
+} VIOCONFIGINFO;
+typedef VIOCONFIGINFO *PVIOCONFIGINFO;
+
+typedef struct _VIOPHYSBUF
+{
+  PBYTE pBuf;
+  ULONG cb;
+  SEL	asel[1];
+} VIOPHYSBUF;
+typedef VIOPHYSBUF *PVIOPHYSBUF;
+
+typedef struct _VIOPALSTATE
+{
+  USHORT cb;
+  USHORT type;
+  USHORT iFirst;
+  USHORT acolor[1];
+} VIOPALSTATE;
+typedef VIOPALSTATE *PVIOPALSTATE;
+
+typedef struct _VIOOVERSCAN
+{
+  USHORT cb;
+  USHORT type;
+  USHORT color;
+} VIOOVERSCAN;
+typedef VIOOVERSCAN *PVIOOVERSCAN;
+
+typedef struct _VIOINTENSITY
+{
+  USHORT cb;
+  USHORT type;
+  USHORT fs;
+} VIOINTENSITY;
+typedef VIOINTENSITY *PVIOINTENSITY;
+
+typedef struct _VIOCOLORREG
+{
+  USHORT cb;
+  USHORT type;
+  USHORT firstcolorreg;
+  USHORT numcolorregs;
+  PCH	 colorregaddr;
+} VIOCOLORREG;
+typedef VIOCOLORREG *PVIOCOLORREG;
+
+typedef struct _VIOSETULINELOC
+{
+  USHORT cb;
+  USHORT type;
+  USHORT scanline;
+} VIOSETULINELOC;
+typedef VIOSETULINELOC *PVIOSETULINELOC;
+
+typedef struct _VIOSETTARGET
+{
+  USHORT cb;
+  USHORT type;
+  USHORT defaultalgorithm;
+} VIOSETTARGET;
+typedef VIOSETTARGET *PVIOSETTARGET;
+
+typedef struct _VIOCURSORINFO
+{
+  USHORT yStart;
+  USHORT cEnd;
+  USHORT cx;
+  USHORT attr;
+} VIOCURSORINFO;
+typedef VIOCURSORINFO *PVIOCURSORINFO;
+
+typedef struct _VIOFONTINFO
+{
+  USHORT cb;
+  USHORT type;
+  USHORT cxCell;
+  USHORT cyCell;
+  ULONG	 pbData;		/* PVOID16 / _far16ptr */
+  USHORT cbData;
+} VIOFONTINFO;
+typedef VIOFONTINFO *PVIOFONTINFO;
+
+
+USHORT VioCheckCharType (PUSHORT pType, USHORT usRow, USHORT usColumn,
+    HVIO hvio);
+USHORT VioDeRegister (VOID);
+USHORT VioEndPopUp (HVIO hvio);
+USHORT VioGetAnsi (PUSHORT pfAnsi, HVIO hvio);
+USHORT VioGetBuf (PULONG pLVB, PUSHORT pcbLVB, HVIO hvio);
+USHORT VioGetConfig (USHORT usConfigId, PVIOCONFIGINFO pvioin, HVIO hvio);
+USHORT VioGetCp (USHORT usReserved, PUSHORT pusCodePage, HVIO hvio);
+USHORT VioGetCurPos (PUSHORT pusRow, PUSHORT pusColumn, HVIO hvio);
+USHORT VioGetCurType (PVIOCURSORINFO pvioCursorInfo, HVIO hvio);
+USHORT VioGetFont (PVIOFONTINFO pviofi, HVIO hvio);
+USHORT VioGetMode (PVIOMODEINFO pvioModeInfo, HVIO hvio);
+USHORT VioGetPhysBuf (PVIOPHYSBUF pvioPhysBuf, USHORT usReserved);
+USHORT VioGetState (PVOID pState, HVIO hvio);
+USHORT VioGlobalReg (PCSZ pszModName, PCSZ pszEntryName, ULONG ulFunMask1,
+    ULONG ulFunMask2, USHORT usReturn);
+USHORT VioModeUndo (USHORT usOwnerInd, USHORT usKillInd, USHORT usReserved);
+USHORT VioModeWait (USHORT usReqType, PUSHORT pNotifyType, USHORT usReserved);
+USHORT VioPopUp (PUSHORT pfWait, HVIO hvio);
+USHORT VioPrtSc (HVIO hvio);
+USHORT VioPrtScToggle (HVIO hvio);
+USHORT VioReadCellStr (PCH pchCellStr, PUSHORT pcb, USHORT usRow,
+    USHORT usColumn, HVIO hvio);
+USHORT VioReadCharStr (PCH pch, PUSHORT pcb, USHORT usRow, USHORT usColumn,
+    HVIO hvio);
+USHORT VioRegister (PCSZ pszModName, PCSZ pszEntryName, ULONG ulFunMask1,
+    ULONG ulFunMask2);
+USHORT VioSavRedrawUndo (USHORT usOwnerInd, USHORT usKillInd,
+    USHORT usReserved);
+USHORT VioSavRedrawWait (USHORT usRedrawInd, PUSHORT pusNotifyType,
+    USHORT usReserved);
+USHORT VioScrLock (USHORT fWait, PUCHAR pfNotLocked, HVIO hvio);
+USHORT VioScrollDn (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbLines, PBYTE pCell, HVIO hvio);
+USHORT VioScrollLf (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbCol, PBYTE pCell, HVIO hvio);
+USHORT VioScrollRt (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbCol, PBYTE pCell, HVIO hvio);
+USHORT VioScrollUp (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbLines, PBYTE pCell, HVIO hvio);
+USHORT VioScrUnLock (HVIO hvio);
+USHORT VioSetAnsi (USHORT fAnsi, HVIO hvio);
+USHORT VioSetCp (USHORT usReserved, USHORT usCodePage, HVIO hvio);
+USHORT VioSetCurPos (USHORT usRow, USHORT usColumn, HVIO hvio);
+USHORT VioSetCurType (PVIOCURSORINFO pvioCursorInfo, HVIO hvio);
+USHORT VioSetFont (PVIOFONTINFO pviofi, HVIO hvio);
+USHORT VioSetMode (PVIOMODEINFO pvioModeInfo, HVIO hvio);
+USHORT VioSetState (CPVOID pState, HVIO hvio);
+USHORT VioShowBuf (USHORT offLVB, USHORT cb, HVIO hvio);
+USHORT VioWrtCellStr (PCCH pchCellStr, USHORT cb, USHORT usRow,
+    USHORT usColumn, HVIO hvio);
+USHORT VioWrtCharStr (PCCH pch, USHORT cb, USHORT usRow, USHORT usColumn,
+    HVIO hvio);
+USHORT VioWrtCharStrAtt (PCCH pch, USHORT cb, USHORT usRow, USHORT usColumn,
+    PBYTE pAttr, HVIO hvio);
+USHORT VioWrtNAttr (__const__ BYTE *pAttr, USHORT cb, USHORT usRow,
+    USHORT usColumn, HVIO hvio);
+USHORT VioWrtNCell (__const__ BYTE *pCell, USHORT cb, USHORT usRow,
+    USHORT usColumn, HVIO hvio);
+USHORT VioWrtNChar (PCCH pch, USHORT cb, USHORT usRow, USHORT usColumn,
+    HVIO hvio);
+USHORT VioWrtTTY (PCCH pch, USHORT cb, HVIO hvio);
+
+#endif /* INCL_VIO */
+
+#if defined (INCL_MOU)
+
+#define MHK_BUTTON1			0x0001
+#define MHK_BUTTON2			0x0002
+#define MHK_BUTTON3			0x0004
+
+#define MOU_NOWAIT			0x0000
+#define MOU_WAIT			0x0001
+
+#define MOUSE_MOTION			0x0001
+#define MOUSE_MOTION_WITH_BN1_DOWN	0x0002
+#define MOUSE_BN1_DOWN			0x0004
+#define MOUSE_MOTION_WITH_BN2_DOWN	0x0008
+#define MOUSE_BN2_DOWN			0x0010
+#define MOUSE_MOTION_WITH_BN3_DOWN	0x0020
+#define MOUSE_BN3_DOWN			0x0040
+
+#define MOUSE_QUEUEBUSY			0x0001
+#define MOUSE_BLOCKREAD			0x0002
+#define MOUSE_FLUSH			0x0004
+#define MOUSE_UNSUPPORTED_MODE		0x0008
+#define MOUSE_DISABLED			0x0100
+#define MOUSE_MICKEYS			0x0200
+
+#define MOU_NODRAW			0x0001
+#define MOU_DRAW			0x0000
+#define MOU_MICKEYS			0x0002
+#define MOU_PELS			0x0000
+
+#define MR_MOUGETNUMBUTTONS		0x00000001
+#define MR_MOUGETNUMMICKEYS		0x00000002
+#define MR_MOUGETDEVSTATUS		0x00000004
+#define MR_MOUGETNUMQUEEL		0x00000008
+#define MR_MOUREADEVENTQUE		0x00000010
+#define MR_MOUGETSCALEFACT		0x00000020
+#define MR_MOUGETEVENTMASK		0x00000040
+#define MR_MOUSETSCALEFACT		0x00000080
+#define MR_MOUSETEVENTMASK		0x00000100
+#define MR_MOUOPEN			0x00000800
+#define MR_MOUCLOSE			0x00001000
+#define MR_MOUGETPTRSHAPE		0x00002000
+#define MR_MOUSETPTRSHAPE		0x00004000
+#define MR_MOUDRAWPTR			0x00008000
+#define MR_MOUREMOVEPTR			0x00010000
+#define MR_MOUGETPTRPOS			0x00020000
+#define MR_MOUSETPTRPOS			0x00040000
+#define MR_MOUINITREAL			0x00080000
+#define MR_MOUSETDEVSTATUS		0x00100000
+
+
+typedef USHORT HMOU;
+typedef HMOU *PHMOU;
+
+
+typedef struct _MOUEVENTINFO
+{
+  USHORT fs;
+  ULONG	 time;
+  SHORT	 row;
+  SHORT	 col;
+} MOUEVENTINFO;
+typedef MOUEVENTINFO *PMOUEVENTINFO;
+
+typedef struct _MOUQUEINFO
+{
+  USHORT cEvents;
+  USHORT cmaxEvents;
+} MOUQUEINFO;
+typedef MOUQUEINFO *PMOUQUEINFO;
+
+typedef struct _PTRLOC
+{
+  USHORT row;
+  USHORT col;
+} PTRLOC;
+typedef PTRLOC *PPTRLOC;
+
+typedef struct _NOPTRRECT
+{
+  USHORT row;
+  USHORT col;
+  USHORT cRow;
+  USHORT cCol;
+} NOPTRRECT;
+typedef NOPTRRECT *PNOPTRRECT;
+
+typedef struct _PTRSHAPE
+{
+  USHORT cb;
+  USHORT col;
+  USHORT row;
+  USHORT colHot;
+  USHORT rowHot;
+} PTRSHAPE;
+typedef PTRSHAPE *PPTRSHAPE;
+
+typedef struct _SCALEFACT
+{
+  USHORT rowScale;
+  USHORT colScale;
+} SCALEFACT;
+typedef SCALEFACT *PSCALEFACT;
+
+typedef struct _THRESHOLD
+{
+  USHORT Length;
+  USHORT Level1;
+  USHORT Lev1Mult;
+  USHORT Level2;
+  USHORT lev2Mult;
+} THRESHOLD;
+typedef THRESHOLD *PTHRESHOLD;
+
+
+USHORT MouClose (HMOU hmou);
+USHORT MouDeRegister (VOID);
+USHORT MouDrawPtr (HMOU hmou);
+USHORT MouFlushQue (HMOU hmou);
+USHORT MouGetDevStatus (PUSHORT pfsDevStatus, HMOU hmou);
+USHORT MouGetEventMask (PUSHORT pfsEvents, HMOU hmou);
+USHORT MouGetNumButtons (PUSHORT pcButtons, HMOU hmou);
+USHORT MouGetNumMickeys (PUSHORT pcMickeys, HMOU hmou);
+USHORT MouGetNumQueEl (PMOUQUEINFO qmouqi, HMOU hmou);
+USHORT MouGetPtrPos (PPTRLOC pmouLoc, HMOU hmou);
+USHORT MouGetPtrShape (PBYTE pBuf, PPTRSHAPE pmoupsInfo, HMOU hmou);
+USHORT MouGetScaleFact (PSCALEFACT pmouscFactors, HMOU hmou);
+USHORT MouGetThreshold (PTHRESHOLD pthreshold, HMOU hmou);
+USHORT MouInitReal (PCSZ pszDriverName);
+USHORT MouOpen (PCSZ pszDvrName, PHMOU phmou);
+USHORT MouReadEventQue (PMOUEVENTINFO pmouevEvent, PUSHORT pfWait, HMOU hmou);
+USHORT MouRegister (PCSZ pszModName, PCSZ pszEntryName, ULONG ulFunMask);
+USHORT MouRemovePtr (PNOPTRRECT pmourtRect, HMOU hmou);
+USHORT MouSetDevStatus (PUSHORT pfsDevStatus, HMOU hmou);
+USHORT MouSetEventMask (PUSHORT pfsEvents, HMOU hmou);
+USHORT MouSetPtrPos (PPTRLOC pmouLoc, HMOU hmou);
+USHORT MouSetPtrShape (PBYTE pBuf, PPTRSHAPE pmoupsInfo, HMOU hmou);
+USHORT MouSetScaleFact (PSCALEFACT pmouscFactors, HMOU hmou);
+USHORT MouSetThreshold (PTHRESHOLD pthreshold, HMOU hmou);
+USHORT MouSynch (USHORT fWait);
+
+#endif /* INCL_MOU */
+
+/* ------------------------------ THE END --------------------------------- */
+
+#pragma pack(4)
+
+#endif /* not _OS2EMX_H */
+
+/* Note 1:
+
+   There are some inconsistencies in the structure names defined in
+   the header files of the IBM Developer's Toolkit for OS/2.  To make
+   C++ modules compiled with those headers linkable with C++ modules
+   compiled with this header, we have to use the same (questionable)
+   structure names. */
+
+/*
+ * Local variables:
+ * indent-tabs-mode: t
+ * end:
+ */
Index: trunk/src/emx/include/os2thunk.h
===================================================================
--- trunk/src/emx/include/os2thunk.h	(revision 18)
+++ trunk/src/emx/include/os2thunk.h	(revision 18)
@@ -0,0 +1,63 @@
+/* os2thunk.h (emx+gcc) */
+
+#ifndef _OS2THUNK_H
+#define _OS2THUNK_H
+
+typedef unsigned long _far16ptr;
+
+_far16ptr _emx_32to16 (void *ptr);
+void *_emx_16to32 (_far16ptr ptr);
+
+unsigned long _emx_thunk1 (void *args, void *fun);
+
+#define _THUNK_PASCAL_PROLOG(SIZE) \
+  ({ char _tb[(SIZE)+4]; void *_tp = _tb + sizeof (_tb); \
+       *(unsigned long *)_tb = (SIZE);
+#define _THUNK_PASCAL_CHAR(ARG)     _THUNK_PASCAL_SHORT (ARG)
+#define _THUNK_PASCAL_SHORT(ARG)    (*--((unsigned short *)_tp) = (ARG))
+#define _THUNK_PASCAL_LONG(ARG)     (*--((unsigned long *)_tp) = (ARG))
+#define _THUNK_PASCAL_FLAT(ARG)     _THUNK_PASCAL_LONG (_emx_32to16 (ARG))
+#define _THUNK_PASCAL_FAR16(ARG)    _THUNK_PASCAL_LONG (ARG)
+#define _THUNK_PASCAL_FUNCTION(FUN) _16_##FUN
+#define _THUNK_PASCAL_CALL(FUN)     _emx_thunk1 (_tb, (void *)(_16_##FUN)); })
+#define _THUNK_PASCAL_CALLI(FUN)    _emx_thunk1 (_tb, (void *)(FUN)); })
+
+#define _THUNK_C_PROLOG(SIZE) \
+  ({ char _tb[(SIZE)+4]; void *_tp = _tb + sizeof (unsigned long); \
+       *(unsigned long *)_tb = (SIZE);
+#define _THUNK_C_CHAR(ARG)     _THUNK_C_SHORT (ARG)
+#define _THUNK_C_SHORT(ARG)    (*((unsigned short *)_tp)++ = (ARG))
+#define _THUNK_C_LONG(ARG)     (*((unsigned long *)_tp)++ = (ARG))
+#define _THUNK_C_FLAT(ARG)     _THUNK_C_LONG (_emx_32to16 (ARG))
+#define _THUNK_C_FAR16(ARG)    _THUNK_C_LONG (ARG)
+#define _THUNK_C_FUNCTION(FUN) _16__##FUN
+#define _THUNK_C_CALL(FUN)     _emx_thunk1 (_tb, (void *)(_16__##FUN)); })
+#define _THUNK_C_CALLI(FUN)    _emx_thunk1 (_tb, (void *)(FUN)); })
+
+#define _THUNK_PROLOG(SIZE)  _THUNK_PASCAL_PROLOG (SIZE)
+#define _THUNK_CHAR(ARG)     _THUNK_PASCAL_CHAR (ARG)
+#define _THUNK_SHORT(ARG)    _THUNK_PASCAL_SHORT (ARG)
+#define _THUNK_LONG(ARG)     _THUNK_PASCAL_LONG (ARG)
+#define _THUNK_FLAT(ARG)     _THUNK_PASCAL_FLAT (ARG)
+#define _THUNK_FAR16(ARG)    _THUNK_PASCAL_FAR16 (ARG)
+#define _THUNK_FUNCTION(FUN) _THUNK_PASCAL_FUNCTION (FUN)
+#define _THUNK_CALL(FUN)     _THUNK_PASCAL_CALL (FUN)
+#define _THUNK_CALLI(FUN)    _THUNK_PASCAL_CALLI (FUN)
+
+#define MAKE16P(sel,off)   ((_far16ptr)((sel) << 16 | (off)))
+#define MAKEP(sel,off)     _emx_16to32 (MAKE16P (sel, off))
+#define SELECTOROF(farptr) ((SEL)((farptr) >> 16))
+#define OFFSETOF(farptr)   ((USHORT)(farptr))
+
+/* Return true iff the block of SIZE bytes at PTR does not cross a
+   64Kbyte boundary. */
+
+#define _THUNK_PTR_SIZE_OK(ptr,size) \
+  (((ULONG)(ptr) & ~0xffff) == (((ULONG)(ptr) + (size) - 1) & ~0xffff))
+
+/* Return true iff the structure pointed to by PTR does not cross a
+   64KByte boundary. */
+
+#define _THUNK_PTR_STRUCT_OK(ptr) _THUNK_PTR_SIZE_OK ((ptr), sizeof (*(ptr)))
+
+#endif /* not _OS2THUNK_H */
Index: trunk/src/emx/include/os2tk.h
===================================================================
--- trunk/src/emx/include/os2tk.h	(revision 18)
+++ trunk/src/emx/include/os2tk.h	(revision 18)
@@ -0,0 +1,148 @@
+/* os2tk.h (emx+gcc) */
+
+#ifndef __OS2_H__
+#define __OS2_H__
+
+#define OS2_INCLUDED
+
+#include <os2def.h>
+
+#if !defined (INCL_NOBASEAPI)
+
+#if defined (INCL_BASE) || defined (INCL_SUB) || defined (INCL_KBD)
+
+#define KBD16CHARIN             KbdCharIn
+#define KBD16CLOSE              KbdClose
+#define KBD16DEREGISTER         KbdDeRegister
+#define KBD16FLUSHBUFFER        KbdFlushBuffer
+#define KBD16FREEFOCUS          KbdFreeFocus
+#define KBD16GETCP              KbdGetCp
+#define KBD16GETFOCUS           KbdGetFocus
+#define KBD16GETHWID            KbdGetHWID
+#define KBD16GETSTATUS          KbdGetStatus
+#define KBD16OPEN               KbdOpen
+#define KBD16PEEK               KbdPeek
+#define KBD16REGISTER           KbdRegister
+#define KBD16SETCP              KbdSetCp
+#define KBD16SETCUSTXT          KbdSetCustXt
+#define KBD16SETFGND            KbdSetFgnd
+#define KBD16SETHWID            KbdSetHWID
+#define KBD16SETSTATUS          KbdSetStatus
+#define KBD16STRINGIN           KbdStringIn
+#define KBD16SYNCH              KbdSynch
+#define KBD16XLATE              KbdXlate
+
+#endif
+
+#if defined (INCL_BASE) || defined (INCL_SUB) || defined (INCL_VIO)
+
+#define VIO16CHECKCHARTYPE      VioCheckCharType
+#define VIO16DEREGISTER         VioDeRegister
+#define VIO16ENDPOPUP           VioEndPopUp
+#define VIO16GETANSI            VioGetAnsi
+#define VIO16GETBUF             VioGetBuf
+#define VIO16GETCONFIG          VioGetConfig
+#define VIO16GETCP              VioGetCp
+#define VIO16GETCURPOS          VioGetCurPos
+#define VIO16GETCURTYPE         VioGetCurType
+#define VIO16GETFONT            VioGetFont
+#define VIO16GETMODE            VioGetMode
+#define VIO16GETPHYSBUF         VioGetPhysBuf
+#define VIO16GETSTATE           VioGetState
+#define VIO16MODEUNDO           VioModeUndo
+#define VIO16MODEWAIT           VioModeWait
+#define VIO16POPUP              VioPopUp
+#define VIO16PRTSC              VioPrtSc
+#define VIO16PRTSCTOGGLE        VioPrtScToggle
+#define VIO16READCELLSTR        VioReadCellStr
+#define VIO16READCHARSTR        VioReadCharStr
+#define VIO16REDRAWSIZE         VioRedrawSize
+#define VIO16REGISTER           VioRegister
+#define VIO16SAVREDRAWUNDO      VioSavRedrawUndo
+#define VIO16SAVREDRAWWAIT      VioSavRedrawWait
+#define VIO16SCRLOCK            VioScrLock
+#define VIO16SCRUNLOCK          VioScrUnLock
+#define VIO16SCROLLDN           VioScrollDn
+#define VIO16SCROLLLF           VioScrollLf
+#define VIO16SCROLLRT           VioScrollRt
+#define VIO16SCROLLUP           VioScrollUp
+#define VIO16SETANSI            VioSetAnsi
+#define VIO16SETCP              VioSetCp
+#define VIO16SETCURPOS          VioSetCurPos
+#define VIO16SETCURTYPE         VioSetCurType
+#define VIO16SETFONT            VioSetFont
+#define VIO16SETMODE            VioSetMode
+#define VIO16SETSTATE           VioSetState
+#define VIO16SHOWBUF            VioShowBuf
+#define VIO16WRTCELLSTR         VioWrtCellStr
+#define VIO16WRTCHARSTR         VioWrtCharStr
+#define VIO16WRTCHARSTRATT      VioWrtCharStrAtt
+#define VIO16WRTNATTR           VioWrtNAttr
+#define VIO16WRTNCELL           VioWrtNCell
+#define VIO16WRTNCHAR           VioWrtNChar
+#define VIO16WRTTTY             VioWrtTTY
+
+#endif
+
+#if defined (INCL_BASE) || defined (INCL_SUB) || defined (INCL_MOU)
+
+#define MOU16CLOSE              MouClose
+#define MOU16DEREGISTER         MouDeRegister
+#define MOU16DRAWPTR            MouDrawPtr
+#define MOU16FLUSHQUE           MouFlushQue
+#define MOU16GETDEVSTATUS       MouGetDevStatus
+#define MOU16GETEVENTMASK       MouGetEventMask
+#define MOU16GETNUMBUTTONS      MouGetNumButtons
+#define MOU16GETNUMMICKEYS      MouGetNumMickeys
+#define MOU16GETNUMQUEEL        MouGetNumQueEl
+#define MOU16GETPTRPOS          MouGetPtrPos
+#define MOU16GETPTRSHAPE        MouGetPtrShape
+#define MOU16GETSCALEFACT       MouGetScaleFact
+#define MOU16GETTHRESHOLD       MouGetThreshold
+#define MOU16INITREAL           MouInitReal
+#define MOU16OPEN               MouOpen
+#define MOU16READEVENTQUE       MouReadEventQue
+#define MOU16REGISTER           MouRegister
+#define MOU16REMOVEPTR          MouRemovePtr
+#define MOU16SETDEVSTATUS       MouSetDevStatus
+#define MOU16SETEVENTMASK       MouSetEventMask
+#define MOU16SETPTRPOS          MouSetPtrPos
+#define MOU16SETPTRSHAPE        MouSetPtrShape
+#define MOU16SETSCALEFACT       MouSetScaleFact
+#define MOU16SETTHRESHOLD       MouSetThreshold
+#define MOU16SYNCH              MouSynch
+
+#endif
+
+#include <bse.h>
+#endif
+
+#if !defined (INCL_NOPMAPI)
+
+#if defined (INCL_PM) || defined (INCL_AVIO)
+
+#define VIO16ASSOCIATE          VioAssociate
+#define VIO16CREATELOGFONT      VioCreateLogFont
+#define VIO16CREATEPS           VioCreatePS
+#define VIO16DELETESETID        VioDeleteSetId
+#define VIO16DESTROYPS          VioDestroyPS
+#define VIO16GETDEVICECELLSIZE  VioGetDeviceCellSize
+#define VIO16GETORG             VioGetOrg
+#define VIO16QUERYFONTS         VioQueryFonts
+#define VIO16QUERYSETIDS        VioQuerySetIds
+#define VIO16SETDEVICECELLSIZE  VioSetDeviceCellSize
+#define VIO16SETORG             VioSetOrg
+#define VIO16SHOWPS             VioShowPS
+#define WIN16DEFAVIOWINDOWPROC  WinDefAVioWindowProc
+
+#endif
+
+#include <pm.h>
+#endif
+
+#undef MAKE16P
+#undef MAKEP
+#undef SELECTOROF
+#undef OFFSETOF
+
+#endif /* not __OS2_H__ */
Index: trunk/src/emx/include/process.h
===================================================================
--- trunk/src/emx/include/process.h	(revision 18)
+++ trunk/src/emx/include/process.h	(revision 18)
@@ -0,0 +1,6 @@
+/* process.h (emx+gcc) */
+
+#ifndef _PROCESS_H
+#define _PROCESS_H
+#include <sys/process.h>
+#endif /* not _PROCESS_H */
Index: trunk/src/emx/include/pwd.h
===================================================================
--- trunk/src/emx/include/pwd.h	(revision 18)
+++ trunk/src/emx/include/pwd.h	(revision 18)
@@ -0,0 +1,63 @@
+/* pwd.h (emx+gcc) */
+
+#ifndef _PWD_H
+#define _PWD_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_PASSWORD_LEN)
+#define	_PASSWORD_LEN 128
+#endif
+
+#if !defined (_GID_T)
+#define _GID_T
+typedef int gid_t;
+#endif
+
+#if !defined (_UID_T)
+#define _UID_T
+typedef int uid_t;
+#endif
+
+struct passwd
+{
+  char *pw_name;
+  char *pw_passwd;
+  uid_t pw_uid;
+  gid_t pw_gid;
+  char *pw_age;
+  char *pw_comment;
+  char *pw_gecos;
+  char *pw_dir;
+  char *pw_shell;
+};
+
+char *getpass (__const__ char *);
+char *_getpass1 (__const__ char *);
+char *_getpass2 (__const__ char *, int);
+
+struct passwd *getpwuid (uid_t);
+struct passwd *getpwnam (__const__ char *);
+
+struct passwd *_getpwuid (uid_t);
+struct passwd *_getpwnam (__const__ char *);
+
+#if !defined (_POSIX_SOURCE)
+
+struct passwd *getpwent (void);
+void setpwent (void);
+void endpwent (void);
+
+struct passwd *_getpwent (void);
+void _setpwent (void);
+void _endpwent (void);
+
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _PWD_H */
Index: trunk/src/emx/include/regexp.h
===================================================================
--- trunk/src/emx/include/regexp.h	(revision 18)
+++ trunk/src/emx/include/regexp.h	(revision 18)
@@ -0,0 +1,35 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+
+#ifndef _REGEXP_H
+#define _REGEXP_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define NSUBEXP  10
+typedef struct regexp {
+	char *startp[NSUBEXP];
+	char *endp[NSUBEXP];
+	char regstart;		/* Internal use only. */
+	char reganch;		/* Internal use only. */
+	char *regmust;		/* Internal use only. */
+	int regmlen;		/* Internal use only. */
+	char program[1];	/* Unwarranted chumminess with compiler. */
+} regexp;
+
+extern regexp *regcomp();
+extern int regexec();
+extern void regsub();
+extern void regerror();
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _REGEXP_H */
Index: trunk/src/emx/include/resolv.h
===================================================================
--- trunk/src/emx/include/resolv.h	(revision 18)
+++ trunk/src/emx/include/resolv.h	(revision 18)
@@ -0,0 +1,119 @@
+/* Modified for EMX by hv 1994,1996
+ *
+ * Copyright (c) 1983, 1987, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)resolv.h	5.15 (Berkeley) 4/3/91
+ *	resolv.h,v 1.1 2003/04/16 15:53:07 bird Exp
+ */
+
+#ifndef _RESOLV_H_
+#define	_RESOLV_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#pragma pack(4)
+
+/*
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * inital name server(s) to query and the domain search list.
+ */
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF        "/tcpip/etc/resolv.conf"
+#endif
+
+/*
+ * Global defines and variables for resolver stub.
+ */
+#define	MAXNS			3	/* max # name servers we'll track */
+#define	MAXDFLSRCH		3	/* # default domain levels to try */
+#define	MAXDNSRCH		6	/* max # domains in search path */
+#define	LOCALDOMAINPARTS	2	/* min levels in name that is "local" */
+#define	MAXDNSLUS		4	/* max # of host lookup types */
+
+#define	RES_TIMEOUT		5	/* min. seconds between retries */
+
+#pragma pack(4)
+struct state {
+	int	retrans;	 	/* retransmition time interval */
+	int	retry;			/* number of times to retransmit */
+	long	options;		/* option flags - see below. */
+	int	nscount;		/* number of name servers */
+	struct	sockaddr_in nsaddr_list[MAXNS];	/* address of name server */
+#define	nsaddr	nsaddr_list[0]		/* for backward compatibility */
+	u_short	id;			/* current packet id */
+	char	defdname[MAXDNAME];	/* default domain */
+	char	*dnsrch[MAXDNSRCH+1];	/* components of domain to search */
+/*	char	lookups[MAXDNSLUS];*/	/* not in OS/2 */
+};
+#pragma pack(1)
+
+/*
+ * Resolver options
+ */
+#define RES_INIT	0x0001		/* address initialized */
+#define RES_DEBUG	0x0002		/* print debug messages */
+#define RES_AAONLY	0x0004		/* authoritative answers only */
+#define RES_USEVC	0x0008		/* use virtual circuit */
+#define RES_PRIMARY	0x0010		/* query primary server only */
+#define RES_IGNTC	0x0020		/* ignore trucation errors */
+#define RES_RECURSE	0x0040		/* recursion desired */
+#define RES_DEFNAMES	0x0080		/* use default domain name */
+#define RES_STAYOPEN	0x0100		/* Keep TCP socket open */
+#define RES_DNSRCH	0x0200		/* search up local domain tree */
+
+#define RES_DEFAULT	(RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
+
+extern	struct state _res;
+
+/* Private routines shared between libc/net, named, nslookup and others. */
+int	dn_skipname (__const__ u_char *, __const__ u_char *);
+void	putlong (u_long, u_char *);
+void	putshort (u_short, u_char *);
+
+/* public routines */
+int	dn_comp(__const__ u_char *, u_char *, int, u_char **, u_char **);
+int	dn_expand(__const__ u_char *, __const__ u_char *, __const__ u_char *,
+			u_char *, int);
+int	res_init(void);
+int	res_mkquery(int, __const__ char *, int, int, __const__ char *, int,
+			__const__ struct rrec *, char *, int);
+int	res_send(__const__ char *, int, char *, int);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_RESOLV_H_ */
Index: trunk/src/emx/include/setjmp.h
===================================================================
--- trunk/src/emx/include/setjmp.h	(revision 18)
+++ trunk/src/emx/include/setjmp.h	(revision 18)
@@ -0,0 +1,34 @@
+/* setjmp.h (emx+gcc) */
+
+#ifndef _SETJMP_H
+#define _SETJMP_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* ANSI X3.159-1989 */
+
+typedef int jmp_buf[12];
+
+int setjmp (jmp_buf);
+void longjmp (jmp_buf, int) __attribute__ ((__noreturn__));
+
+
+#if !defined (__STRICT_ANSI__)
+
+/* POSIX.1 */
+
+typedef int sigjmp_buf[14];
+
+int sigsetjmp (sigjmp_buf, int);
+void siglongjmp (sigjmp_buf, int) __attribute__ ((__noreturn__));
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SETJMP_H */
Index: trunk/src/emx/include/sgtty.h
===================================================================
--- trunk/src/emx/include/sgtty.h	(revision 18)
+++ trunk/src/emx/include/sgtty.h	(revision 18)
@@ -0,0 +1,3 @@
+/* sgtty.h (emx+gcc) */
+
+/* empty */
Index: trunk/src/emx/include/share.h
===================================================================
--- trunk/src/emx/include/share.h	(revision 18)
+++ trunk/src/emx/include/share.h	(revision 18)
@@ -0,0 +1,11 @@
+/* share.h (emx+gcc) */
+
+#ifndef _SHARE_H
+#define _SHARE_H
+
+#define SH_DENYRW       0x10
+#define SH_DENYWR       0x20
+#define SH_DENYRD       0x30
+#define SH_DENYNO       0x40
+
+#endif /* not _SHARE_H */
Index: trunk/src/emx/include/short.cmd
===================================================================
--- trunk/src/emx/include/short.cmd	(revision 18)
+++ trunk/src/emx/include/short.cmd	(revision 18)
@@ -0,0 +1,37 @@
+/* short.cmd */
+
+'@echo off'
+
+call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
+call SysLoadFuncs
+
+if SysSearchPath('PATH', 'sed.exe') == '' then do
+  say 'sed.exe not found -- see INSTALL.DOC'
+  exit
+end
+
+do while lines('longshrt.ls2')
+  file = translate(linein('longshrt.ls2'), '\', '/')
+  if stream(file, 'C', 'QUERY EXISTS') \= '' then do
+    say 'Patching' file
+    'sed -f short.sed >tmp' file
+    if rc \= 0 then do
+      say 'sed failed!'
+      exit
+    end
+    'touch -r' file 'tmp'
+    'del' file
+    'move tmp' file '>nul'
+  end
+end
+
+say 'Renaming files'
+do while lines('longshrt.ls1')
+  line = linein('longshrt.ls1')
+  parse var line long short
+  file = translate(long, '\', '/')
+  if stream(file, 'C', 'QUERY EXISTS') \= '' then
+    'ren' file short
+end
+
+say 'Done'
Index: trunk/src/emx/include/short.sed
===================================================================
--- trunk/src/emx/include/short.sed	(revision 18)
+++ trunk/src/emx/include/short.sed	(revision 18)
@@ -0,0 +1,49 @@
+/^#[ 	]*include/s|\([<"/]\)algorithm\([">]\)|\1algorith\2|
+/^#[ 	]*include/s|\([<"/]\)AllocRing\.h\([">]\)|\1AllocRin\.h\2|
+/^#[ 	]*include/s|\([<"/]\)BitString\.h\([">]\)|\1BitStrin\.h\2|
+/^#[ 	]*include/s|\([<"/]\)builtinbuf\.h\([">]\)|\1builtinb\.h\2|
+/^#[ 	]*include/s|\([<"/]\)exception\([">]\)|\1exceptio\2|
+/^#[ 	]*include/s|\([<"/]\)functional\([">]\)|\1function\2|
+/^#[ 	]*include/s|\([<"/]\)SplayNode\.ccP\([">]\)|\1SplayNod\.ccP\2|
+/^#[ 	]*include/s|\([<"/]\)SplayNode\.hP\([">]\)|\1SplayNod\.hP\2|
+/^#[ 	]*include/s|\([<"/]\)getpagesize\.h\([">]\)|\1getpages\.h\2|
+/^#[ 	]*include/s|\([<"/]\)hashtable\.h\([">]\)|\1hashtabl\.h\2|
+/^#[ 	]*include/s|\([<"/]\)Incremental\.h\([">]\)|\1Incremen\.h\2|
+/^#[ 	]*include/s|\([<"/]\)indstream\.h\([">]\)|\1indstrea\.h\2|
+/^#[ 	]*include/s|\([<"/]\)parsestream\.h\([">]\)|\1parsestr\.h\2|
+/^#[ 	]*include/s|\([<"/]\)ldcomplex\.h\([">]\)|\1ldcomple\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stdexcept\([">]\)|\1stdexcep\2|
+/^#[ 	]*include/s|\([<"/]\)stdiostream\.h\([">]\)|\1stdiostr\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_algobase\.h\([">]\)|\1stl_algb\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_alloc\.h\([">]\)|\1stl_allo\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_bvector\.h\([">]\)|\1stl_bvec\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_config\.h\([">]\)|\1stl_conf\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_construct\.h\([">]\)|\1stl_cons\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_deque\.h\([">]\)|\1stl_dequ\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_function\.h\([">]\)|\1stl_func\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_hashtable\.h\([">]\)|\1stl_htab\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_hash_fun\.h\([">]\)|\1stl_hfun\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_hash_map\.h\([">]\)|\1stl_hmap\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_hash_set\.h\([">]\)|\1stl_hset\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_iterator\.h\([">]\)|\1stl_iter\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_multimap\.h\([">]\)|\1stl_mmap\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_multiset\.h\([">]\)|\1stl_mset\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_numeric\.h\([">]\)|\1stl_nume\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_queue\.h\([">]\)|\1stl_queu\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_raw_storage_iter\.h\([">]\)|\1stl_raw_\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_relops\.h\([">]\)|\1stl_relo\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_slist\.h\([">]\)|\1stl_slis\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_stack\.h\([">]\)|\1stl_stac\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_tempbuf\.h\([">]\)|\1stl_temp\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_uninitialized\.h\([">]\)|\1stl_unin\.h\2|
+/^#[ 	]*include/s|\([<"/]\)stl_vector\.h\([">]\)|\1stl_vect\.h\2|
+/^#[ 	]*include/s|\([<"/]\)streambuf\.h\([">]\)|\1streambu\.h\2|
+/^#[ 	]*include/s|\([<"/]\)strstream\([">]\)|\1strstrea\2|
+/^#[ 	]*include/s|\([<"/]\)strstream\.h\([">]\)|\1strstrea\.h\2|
+/^#[ 	]*include/s|\([<"/]\)typemacros\.h\([">]\)|\1typemacr\.h\2|
+/^#[ 	]*include/s|\([<"/]\)type_traits\.h\([">]\)|\1type_tra\.h\2|
+/^#[ 	]*include/s|\([<"/]\)_G_config\.h\([">]\)|\1_G_confi\.h\2|
+/^#[ 	]*include/s|\([<"/]\)NXConstStr\.h\([">]\)|\1NXConstS\.h\2|
+/^#[ 	]*include/s|\([<"/]\)objc-list\.h\([">]\)|\1objc-lis\.h\2|
+/^#[ 	]*include/s|\([<"/]\)typedstream\.h\([">]\)|\1typedstr\.h\2|
+/^#[ 	]*include/s|\([<"/]\)unchecked\.h\([">]\)|\1unchecke\.h\2|
Index: trunk/src/emx/include/signal.h
===================================================================
--- trunk/src/emx/include/signal.h	(revision 18)
+++ trunk/src/emx/include/signal.h	(revision 18)
@@ -0,0 +1,6 @@
+/* signal.h (emx+gcc) */
+
+#ifndef _SIGNAL_H
+#define _SIGNAL_H
+#include <sys/signal.h>
+#endif /* not _SIGNAL_H */
Index: trunk/src/emx/include/stdarg.h
===================================================================
--- trunk/src/emx/include/stdarg.h	(revision 18)
+++ trunk/src/emx/include/stdarg.h	(revision 18)
@@ -0,0 +1,25 @@
+/* stdarg.h (emx+gcc) */
+
+#ifndef _STDARG_H
+#define _STDARG_H
+
+#if !defined (_VA_LIST)
+#define _VA_LIST
+typedef char *va_list;
+#endif
+
+#define _VA_ROUND(t) ((sizeof (t) + 3) & -4)
+
+#if !defined (va_start)
+#define va_start(ap,v) ap = (va_list)&v + ((sizeof (v) + 3) & -4)
+#define va_end(ap) (ap = 0, (void)0)
+#define __std_va_arg(ap,t) (ap += _VA_ROUND (t), *(t *)(ap - _VA_ROUND (t)))
+#endif
+
+#ifdef __BOUNDS_CHECKING_ON
+#include <fix-args.h>
+#else
+#define va_arg(ap,t) __std_va_arg(ap,t)
+#endif
+
+#endif /* not _STDARG_H */
Index: trunk/src/emx/include/stddef.h
===================================================================
--- trunk/src/emx/include/stddef.h	(revision 18)
+++ trunk/src/emx/include/stddef.h	(revision 18)
@@ -0,0 +1,48 @@
+/* stddef.h (emx+gcc) */
+
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_PTRDIFF_T)
+#define _PTRDIFF_T
+typedef long ptrdiff_t;
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (_WCHAR_T) && !defined (__cplusplus)
+#define _WCHAR_T
+typedef unsigned short wchar_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#define	offsetof(type, member)  ((size_t)&((type *)0)->member)
+
+
+#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)) \
+    || defined (_WITH_UNDERSCORE)
+
+unsigned *__threadid (void);
+#define _threadid (__threadid ())
+
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _STDDEF_H */
Index: trunk/src/emx/include/stdio.h
===================================================================
--- trunk/src/emx/include/stdio.h	(revision 18)
+++ trunk/src/emx/include/stdio.h	(revision 18)
@@ -0,0 +1,273 @@
+/* stdio.h (emx+gcc) */
+
+#ifndef _STDIO_H
+#define _STDIO_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#if !defined (BUFSIZ)
+#define BUFSIZ 5120
+#endif
+
+#if !defined (_FILE_T)
+#define _FILE_T
+#define _FILE_MEMBERS_HAVE_UNDERSCORE
+struct _file2;
+struct _FILE
+{
+  char * _ptr;
+  char * _buffer;
+  int    _rcount;
+  int    _wcount;
+  int    _handle;
+  int    _flags;
+  int    _buf_size;
+  int    _tmpidx;
+  int    _pid;
+  char   _char_buf;
+  unsigned char _ungetc_count;
+  short  _mbstate;
+  int    (*_flush)(struct _FILE *, int);
+  struct _file2 *_more;
+};
+
+typedef struct _FILE FILE;
+
+extern FILE _streamv[];
+
+#define stdin  (&_streamv[0])
+#define stdout (&_streamv[1])
+#define stderr (&_streamv[2])
+
+#endif
+
+#if !defined (SEEK_SET)
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#if !defined (EOF)
+#define EOF (-1)
+#endif
+
+#if !defined (_IOREAD)
+#define _IOREAD 0x01
+#define _IOWRT  0x02
+#define _IORW   0x04
+#define _IOEOF  0x08
+#define _IOERR  0x10
+#define _IOFBF  0x00
+#define _IOLBF  0x20
+#define _IONBF  0x40
+#endif
+
+#if !defined (FOPEN_MAX)
+#define	FOPEN_MAX       14
+#endif
+
+#if !defined (FILENAME_MAX)
+#define	FILENAME_MAX    260
+#endif
+
+#if !defined (TMP_MAX)
+#define TMP_MAX         1000
+#endif
+
+#if !defined (P_tmpdir)
+#define P_tmpdir "."
+#define L_tmpnam (sizeof (P_tmpdir) + 13)
+#endif
+
+#if !defined (L_cuserid)
+#define L_cuserid       9
+#endif
+
+#if !defined (_FPOS_T)
+#define _FPOS_T
+typedef struct
+{
+  long _pos;
+  long _reserved1;
+  short _mbstate;
+  short _reserved2;
+} fpos_t;
+#endif
+
+#if !defined (_VA_LIST)
+#define _VA_LIST
+typedef char *va_list;
+#endif
+
+void clearerr (FILE *);
+int fclose (FILE *);
+int feof (FILE *);
+int ferror (FILE *);
+int fflush (FILE *);
+int fgetc (FILE *);
+int fgetpos (FILE *, fpos_t *);
+char *fgets (char *, int, FILE *);
+FILE *fopen (__const__ char *, __const__ char *);
+int fprintf (FILE *, __const__ char *, ...);
+int fputc (int, FILE *);
+int fputs (__const__ char *, FILE *);
+size_t fread (void *, size_t, size_t, FILE *);
+FILE *freopen (__const__ char *, __const__ char *, FILE *);
+int fscanf (FILE *, __const__ char *, ...);
+int fseek (FILE *, long, int);
+int fsetpos (FILE *, __const__ fpos_t *);
+long ftell (FILE *);
+size_t fwrite (__const__ void *, size_t, size_t, FILE *);
+int getchar (void);
+char *gets (char *);
+void perror (__const__ char *);
+int printf (__const__ char *, ...);
+int putchar (int);
+int puts (__const__ char *);
+int remove (__const__ char *);
+int rename (__const__ char *, __const__ char *);
+void rewind (FILE *);
+int scanf (__const__ char *, ...);
+int setbuf (FILE *, char *);
+int setvbuf (FILE *, char *, int, size_t);
+int sprintf (char *, __const__ char *, ...);
+int sscanf (__const__ char *, __const__ char *, ...);
+FILE *tmpfile (void);
+char *tmpnam (char *);
+int ungetc (int, FILE *);
+int vfprintf (FILE *, __const__ char *, va_list);
+int vprintf (__const__ char *, va_list);
+int vsprintf (char *, __const__ char *, va_list);
+
+int _fill (FILE *);
+int _flush (int, FILE *);
+int _rmtmp (void);
+
+int _getc_inline (FILE *);
+int _putc_inline (int, FILE *);
+
+extern __inline__ int feof (FILE *_s)
+{
+  return (_s->_flags & _IOEOF ? 1 : 0);
+}
+
+extern __inline__ int ferror (FILE *_s)
+{
+  return (_s->_flags & _IOERR ? 1 : 0);
+}
+
+/* Do not use this function in application programs! */
+
+extern __inline__ int _getc_inline (FILE *_s)
+{
+  return (--_s->_rcount >= 0
+          ? (unsigned char)*_s->_ptr++
+          : _fill (_s));
+}
+
+/* Do not use this function in application programs! */
+
+extern __inline__ int _putc_inline (int _c, FILE *_s)
+{
+  return (--_s->_wcount >= 0 && (_c != '\n' || !(_s->_flags & _IOLBF))
+          ? (unsigned char)(*_s->_ptr++ = (char)_c)
+          : _flush (_c, _s));
+}
+
+#if defined (__MT__)
+
+#define getc(s)   fgetc(s)
+#define putc(c,s) fputc(c,s)
+
+#else
+
+#define getc(s)   _getc_inline(s)
+#define putc(c,s) _putc_inline(c,s)
+
+#endif
+
+extern __inline__ int getchar (void) { return getc (stdin); }
+extern __inline__ int putchar (int _c) { return putc (_c, stdout); }
+
+
+#if !defined (__STRICT_ANSI__)
+
+/* POSIX.1 */
+
+/* ctermid() */
+FILE *fdopen (int, __const__ char *);
+int fileno (FILE *);
+
+extern __inline__ int fileno (FILE *_s) { return _s->_handle; }
+
+#endif
+
+
+#if !defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)
+
+char *cuserid (char *);
+int getw (FILE *);
+int fcloseall (void);
+int fgetchar (void);
+int flushall (void);
+int fputchar (int);
+int pclose (FILE *);
+FILE *popen (__const__ char *, __const__ char *);
+int putw (int, FILE *);
+int setbuffer (FILE *, char *, size_t);
+int snprintf (char *, size_t, __const__ char *, ...);
+char *tempnam (__const__ char *, __const__ char *);
+int vfscanf (FILE *, __const__ char *, va_list);
+int vscanf (__const__ char *, va_list);
+int vsnprintf (char *, size_t, __const__ char *, va_list);
+int vsscanf (__const__ char *, __const__ char *, va_list);
+
+#endif
+
+
+#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)) \
+    || defined (_WITH_UNDERSCORE)
+
+int _fcloseall (void);
+FILE *_fassign (FILE *, FILE *);
+FILE *_fdopen (int, __const__ char *);
+int _fgetchar (void);
+int _flushall (void);
+int _fputchar (int);
+int _fseek_hdr (FILE *);
+int _fsetmode (FILE *, __const__ char *);
+FILE *_fsopen (__const__ char *, __const__ char *, int);
+int _getw (FILE *);
+char *_mfclose (FILE *);
+FILE *_mfopen (char *, __const__ char *, size_t, int);
+int _pclose (FILE *);
+FILE *_popen (__const__ char *, __const__ char *);
+int _putw (int, FILE *);
+int _setbuffer (FILE *, char *, size_t);
+int _snprintf (char *, size_t, __const__ char *, ...);
+char *_tempnam (__const__ char *, __const__ char *);
+int _vsnprintf (char *, size_t, __const__ char *, va_list);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _STDIO_H */
Index: trunk/src/emx/include/stdlib.h
===================================================================
--- trunk/src/emx/include/stdlib.h	(revision 18)
+++ trunk/src/emx/include/stdlib.h	(revision 18)
@@ -0,0 +1,282 @@
+/* stdlib.h (emx+gcc) */
+
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (_WCHAR_T) && !defined (__cplusplus)
+#define _WCHAR_T
+typedef unsigned short wchar_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#if !defined (_DIV_T)
+#define _DIV_T
+typedef struct _div_t
+{
+  int quot;
+  int rem;
+} div_t;
+typedef struct _ldiv_t
+{
+  long quot;
+  long rem;
+} ldiv_t;
+#endif
+
+#if !defined (RAND_MAX)
+#define RAND_MAX 0x7fff
+#endif
+
+#if !defined (EXIT_SUCCESS)
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#endif
+
+#if !defined (MB_CUR_MAX)
+extern int _mb_cur_max;
+#define MB_CUR_MAX _mb_cur_max
+#endif
+
+#if !defined (_MAX_PATH)
+#define _MAX_PATH   260
+#define _MAX_DRIVE    3
+#define _MAX_DIR    256
+#define _MAX_FNAME  256
+#define _MAX_EXT    256
+#endif
+
+
+void abort (void) __attribute__ ((__noreturn__));
+int atexit (void (*)(void));
+double atof (__const__ char *);
+int atoi (__const__ char *);
+long atol (__const__ char *);
+void *bsearch (__const__ void *, __const__ void *, size_t, size_t,
+    int (*)(__const__ void *, __const__ void *));
+div_t div (int, int);
+void exit (int) __attribute__ ((__noreturn__));
+char *getenv (__const__ char *);
+ldiv_t ldiv (long, long);
+int mblen (__const__ char *, size_t);
+size_t mbstowcs (wchar_t *, __const__ char *, size_t);
+int mbtowc (wchar_t *, __const__ char *, size_t);
+void qsort (void *, size_t, size_t,
+    int (*)(__const__ void *, __const__ void *));
+int rand (void);
+void srand (unsigned);
+double strtod (__const__ char *, char **);
+long strtol (__const__ char *, char **, int);
+unsigned long strtoul (__const__ char *, char **, int);
+int system (__const__ char *);
+size_t wcstombs (char *, __const__ wchar_t *, size_t);
+int wctomb (char *, wchar_t);
+
+#if !defined (_ABS)                                      /* see also math.h */
+#define _ABS
+#if !defined (__GNUC__) || __GNUC__ >= 2
+extern int abs (int);
+extern long labs (long);
+#else
+extern __inline__ int abs (int _n) { return (_n < 0 ? -_n : _n); }
+extern __inline__ long labs (long _n) { return (_n < 0 ? -_n : _n); }
+#endif
+#endif
+
+#if !defined (__NO_C9X)
+
+float strtof (__const__ char *, char **);
+long double strtold (__const__ char *, char **);
+
+#endif
+
+
+#if !defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)
+
+#if !defined (OS2_MODE)
+#define DOS_MODE 0
+#define OS2_MODE 1
+#endif
+
+#if !defined (_ERRNO)
+#define _ERRNO
+#if defined (__MT__) || defined (__ST_MT_ERRNO__)
+extern int *_errno (void);
+#define errno (*_errno ())
+#else
+extern int errno;
+#endif
+#endif
+
+#if !defined (_ULDIV_T)
+#define _ULDIV_T
+typedef struct
+{
+  unsigned long quot;
+  unsigned long rem;
+} _uldiv_t;
+typedef struct
+{
+  long long quot;
+  long long rem;
+} _lldiv_t;
+typedef struct
+{
+  unsigned long long quot;
+  unsigned long long rem;
+} _ulldiv_t;
+#endif
+
+extern char **environ;
+
+extern __const__ char * __const__ sys_errlist[];
+extern __const__ int sys_nerr;
+
+extern __const__ unsigned int _emx_vcmp;
+extern __const__ unsigned int _emx_env;
+extern __const__ unsigned int _emx_rev;
+extern __const__ unsigned char _osminor;
+extern __const__ unsigned char _osmajor;
+extern __const__ unsigned char _osmode;
+extern __const__ char _emx_vprt[5];
+
+
+unsigned alarm (unsigned);
+void *brk (void *);
+int chdir (__const__ char *);
+char *gcvt (double, int, char *);
+char *getcwd (char *, size_t);
+int getpagesize (void);
+char *getwd (char *);
+int mkdir (__const__ char *, long);
+void perror (__const__ char *);
+int putenv (__const__ char *);
+int rmdir (__const__ char *);
+void *sbrk (int);
+unsigned sleep (unsigned);
+void swab (__const__ void *, void *, size_t);
+long ulimit (int, ...);
+
+int heapsort (void *, size_t, size_t,
+    int (*)(__const__ void *, __const__ void *));       /* BSD */
+char *initstate (unsigned, char *, int);                /* BSD */
+long random (void);                                     /* BSD */
+char *setstate (char *);                                /* BSD */
+void srandom (unsigned);                                /* BSD */
+
+#endif
+
+
+#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)) \
+    || defined (_WITH_UNDERSCORE)
+
+extern char **_environ;
+extern __const__ char * __const__ _sys_errlist[];
+extern __const__ int _sys_nerr;
+
+unsigned _alarm (unsigned);
+void *_brk (void *);
+int _chdir (__const__ char *);
+char *_gcvt (double, int, char *);
+char *_getcwd (char *, size_t);
+int _getpagesize (void);
+char *_getwd (char *);
+int _mkdir (__const__ char *, long);
+int _putenv (__const__ char *);
+int _rmdir (__const__ char *);
+void *_sbrk (int);
+unsigned _sleep (unsigned);
+void _swab (__const__ void *, void *, size_t);
+long _ulimit (int, ...);
+
+int _abspath (char *, __const__ char *, int);
+long long _atoll (__const__ char *);
+long double _atofl (__const__ char *);
+int _chdir2 (__const__ char *);
+int _chdrive (char);
+int _core (int);
+void _defext (char *, __const__ char *);
+void _envargs (int *, char ***, __const__ char *);
+int _execname (char *, size_t);
+void _exit (int) __attribute__ ((__noreturn__));
+int _filesys (__const__ char *, char *, size_t);
+int _fncmp (__const__ unsigned char *, __const__ unsigned char *);
+char **_fnexplode (__const__ char *);
+void _fnexplodefree (char **);
+char _fngetdrive (__const__ char *);
+int _fnisabs (__const__ char *);
+int _fnisrel (__const__ char *);
+void _fnlwr (char *);
+void _fnlwr2 (char *, __const__ char *);
+char *_fnslashify (char *);
+int _fullpath (char *, __const__ char *, int);
+int _getcwd1 (char *, char);
+char *_getcwd2 (char *, int);
+char _getdrive (void);
+char *_getext (__const__ char *);
+char *_getext2 (__const__ char *);
+char *_getname (__const__ char *);
+int _getsockhandle (int);
+int _gettid (void);
+char *_getvol (char);
+char *_itoa (int, char *, int);
+_lldiv_t _lldiv (long long, long long);
+char *_lltoa (long long, char *, int);
+char *_ltoa (long, char *, int);
+void _makepath (char *, __const__ char *, __const__ char *,
+    __const__ char *, __const__ char *);
+int _path (char *, __const__ char *);
+int _read_kbd (int, int, int);
+void _remext (char *);
+void _rfnlwr (void);
+void _response (int *, char ***);
+void _scrsize (int *);
+void _searchenv (__const__ char *, __const__ char *, char *);
+int _setsyserrno (int);
+void _sfnlwr (__const__ char *);
+unsigned _sleep2 (unsigned);
+char ** _splitargs (char *, int *);
+void _splitpath (__const__ char *, char *, char *, char *, char *);
+float _strtof (__const__ char *, char **);
+long double _strtold (__const__ char *, char **);
+long long _strtoll (__const__ char *, char **, int);
+unsigned long long _strtoull (__const__ char *, char **, int);
+char _swchar (void);
+int _syserrno (void);
+_uldiv_t _uldiv (unsigned long, unsigned long);
+_ulldiv_t _ulldiv (unsigned long long, unsigned long long);
+char *_ulltoa (unsigned long long, char *, int);
+char *_ultoa (unsigned long, char *, int);
+void _wildcard (int *, char ***);
+
+#if defined (__MT__)
+int _beginthread (void (*)(void *), void *, unsigned, void *);
+void _endthread (void);
+void **_threadstore (void);
+#endif
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#include <malloc.h>
+
+#endif /* not _STDLIB_H */
Index: trunk/src/emx/include/string.h
===================================================================
--- trunk/src/emx/include/string.h	(revision 18)
+++ trunk/src/emx/include/string.h	(revision 18)
@@ -0,0 +1,100 @@
+/* string.h (emx+gcc) */
+
+#ifndef _STRING_H
+#define _STRING_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+void *memchr (__const__ void *, int, size_t);
+int memcmp (__const__ void *, __const__ void *, size_t);
+void *memcpy (void *, __const__ void *, size_t);
+void *memmove (void *, __const__ void *, size_t);
+void *memset (void *, int, size_t);
+
+char *strcat (char *, __const__ char *);
+char *strchr (__const__ char *, int);
+int strcmp (__const__ char *, __const__ char *);
+int strcoll (__const__ char *, __const__ char *);
+char *strcpy (char *, __const__ char *);
+size_t strcspn (__const__ char *, __const__ char *);
+char *strerror (int);
+size_t strlen (__const__ char *);
+char *strncat (char *, __const__ char *, size_t);
+int strncmp (__const__ char *, __const__ char *, size_t);
+char *strncpy (char *, __const__ char *, size_t);
+char *strpbrk (__const__ char *, __const__ char *);
+char *strrchr (__const__ char *, int);
+size_t strspn (__const__ char *, __const__ char *);
+char *strstr (__const__ char *, __const__ char *);
+char *strtok (char *, __const__ char *);
+size_t strxfrm (char *, __const__ char *, size_t);
+
+
+#if !defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)
+
+#if !defined (_MEMDIF_EQ)
+#define _MEMDIF_EQ 0xffffffff
+#endif
+
+
+void *memccpy (void *, __const__ void *, int, size_t);
+int memicmp (__const__ void *, __const__ void *, size_t);
+
+char *strdup (__const__ char *);
+int stricmp (__const__ char *, __const__ char *);
+char *strlwr (char *);
+int strnicmp (__const__ char *, __const__ char *, size_t);
+char *strnset (char *, int, size_t);
+char *strrev (char *);
+char *strset (char *, int);
+char *strupr (char *);
+
+char *strsep (char **, __const__ char *); /* BSD */
+
+#endif
+
+
+#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)) \
+    || defined (_WITH_UNDERSCORE)
+
+size_t _memcount (__const__ void *, int, size_t);
+size_t _memdif (__const__ void *, __const__ void *, size_t);
+void *_memrchr (__const__ void *, int, size_t);
+void _memswap (void *, void *, size_t);
+char *_strncpy (char *, __const__ char *, size_t);
+
+void *_memccpy (void *, __const__ void *, int, size_t);
+int _memicmp (__const__ void *, __const__ void *, size_t);
+char *_strdup (__const__ char *);
+int _stricmp (__const__ char *, __const__ char *);
+char *_strlwr (char *);
+int _strnicmp (__const__ char *, __const__ char *, size_t);
+char *_strnset (char *, int, size_t);
+char *_strrev (char *);
+char *_strset (char *, int);
+char *_strupr (char *);
+char *_strsep (char **, __const__ char *);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _STRING_H */
Index: trunk/src/emx/include/strings.h
===================================================================
--- trunk/src/emx/include/strings.h	(revision 18)
+++ trunk/src/emx/include/strings.h	(revision 18)
@@ -0,0 +1,24 @@
+/* strings.h (emx+gcc) */
+
+#ifndef _STRINGS_H
+#define _STRINGS_H
+
+#include <string.h>
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+int  bcmp (__const__ void *, __const__ void *, size_t);
+void bcopy (__const__ void *, void *, size_t);
+void bzero (void *, size_t);
+int ffs (int i);
+char *index (__const__ char *, int);
+char *rindex (__const__ char *, int);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _STRINGS_H */
Index: trunk/src/emx/include/sys/builtin.h
===================================================================
--- trunk/src/emx/include/sys/builtin.h	(revision 18)
+++ trunk/src/emx/include/sys/builtin.h	(revision 18)
@@ -0,0 +1,8 @@
+/* sys/builtin.h (emx+gcc) */
+
+#ifndef _SYS_BUILTIN_H
+#define _SYS_BUILTIN_H
+
+#include <386/builtin.h>
+
+#endif /* not _SYS_BUILTIN_H */
Index: trunk/src/emx/include/sys/cdefs.h
===================================================================
--- trunk/src/emx/include/sys/cdefs.h	(revision 18)
+++ trunk/src/emx/include/sys/cdefs.h	(revision 18)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)cdefs.h	8.7 (Berkeley) 1/21/94
+ */
+
+#ifndef	_CDEFS_H_
+#define	_CDEFS_H_
+
+#if defined(__cplusplus)
+#define	__BEGIN_DECLS	extern "C" {
+#define	__END_DECLS	};
+#else
+#define	__BEGIN_DECLS
+#define	__END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments.  __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define	__P(protos)	protos		/* full-blown ANSI C */
+#define	__CONCAT(x,y)	x ## y
+#define	__STRING(x)	#x
+
+#define	__const		const		/* define reserved names to standard */
+#define	__signed	signed
+#define	__volatile	volatile
+#if defined(__cplusplus)
+#define	__inline	inline		/* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define	__inline			/* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else	/* !(__STDC__ || __cplusplus) */
+#define	__P(protos)	()		/* traditional C preprocessor */
+#define	__CONCAT(x,y)	x/**/y
+#define	__STRING(x)	"x"
+
+#ifndef __GNUC__
+#define	__const				/* delete pseudo-ANSI C keywords */
+#define	__inline
+#define	__signed
+#define	__volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef	NO_ANSI_KEYWORDS
+#define	const				/* delete ANSI C keywords */
+#define	inline
+#define	signed
+#define	volatile
+#endif
+#endif	/* !__GNUC__ */
+#endif	/* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2 uses a new, peculiar __attribute__((attrs)) style.  All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
+#define	__attribute__(x)	/* delete __attribute__ if non-gcc or gcc1 */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define	__dead		__volatile
+#define	__pure		__const
+#endif
+#endif
+
+/* Delete pseudo-keywords wherever they are not available or needed. */
+#ifndef __dead
+#define	__dead
+#define	__pure
+#endif
+
+#endif /* !_CDEFS_H_ */
Index: trunk/src/emx/include/sys/dir.h
===================================================================
--- trunk/src/emx/include/sys/dir.h	(revision 18)
+++ trunk/src/emx/include/sys/dir.h	(revision 18)
@@ -0,0 +1,77 @@
+/* sys/dir.h (emx+gcc) */
+
+#ifndef _SYS_DIR_H
+#define _SYS_DIR_H
+
+#if !defined (_SYS_TYPES_H)
+#warning <sys/dir.h> requires <sys/types.h>
+#include <sys/types.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (MAXNAMLEN)
+#define MAXNAMLEN  260
+#endif
+
+#if !defined (MAXPATHLEN)
+#define MAXPATHLEN 260
+#endif
+
+#if !defined (A_RONLY)
+#define A_RONLY   0x01
+#define A_HIDDEN  0x02
+#define A_SYSTEM  0x04
+#define A_LABEL   0x08
+#define A_DIR     0x10
+#define A_ARCHIVE 0x20
+#endif
+
+#define _DIRECT_D_MODE_RENAMED_D_ATTR
+
+struct direct
+{
+  ino_t          d_ino;                 /* Almost not used           */
+  int            d_reclen;              /* Almost not used           */
+  int            d_namlen;              /* Length of d_name          */
+  char           d_name[MAXNAMLEN + 1]; /* File name, 0 terminated   */
+  long           d_size;                /* File size (bytes)         */
+  unsigned short d_attr;                /* OS file attributes        */
+  unsigned short d_time;                /* OS file modification time */
+  unsigned short d_date;                /* OS file modification date */
+};
+
+struct _dircontents
+{
+  char *                _d_entry;
+  long                  _d_size;
+  unsigned short        _d_attr;
+  unsigned short        _d_time;
+  unsigned short        _d_date;
+  struct _dircontents * _d_next;
+};
+
+struct _dirdesc
+{
+  int                   dd_id;
+  long                  dd_loc;
+  struct _dircontents * dd_contents;
+  struct _dircontents * dd_cp;
+};
+
+typedef struct _dirdesc DIR;
+
+DIR *opendir (__const__ char *name);
+struct direct *readdir (DIR *dirp);
+void seekdir (DIR *dirp, long off);
+long telldir (DIR *dirp);
+int closedir (DIR *dirp);
+void rewinddir (DIR *dirp);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not SYS_DIR_H */
Index: trunk/src/emx/include/sys/dirent.h
===================================================================
--- trunk/src/emx/include/sys/dirent.h	(revision 18)
+++ trunk/src/emx/include/sys/dirent.h	(revision 18)
@@ -0,0 +1,42 @@
+/* sys/dirent.h (emx+gcc) */
+
+#ifndef _SYS_DIRENT_H
+#define _SYS_DIRENT_H
+
+#if !defined (_SYS_TYPES_H)
+#warning <sys/dirent.h> requires <sys/types.h>
+#include <sys/types.h>
+#endif
+
+#if !defined (MAXNAMLEN)
+#define MAXNAMLEN  260
+#endif
+
+#if !defined (MAXPATHLEN)
+#define MAXPATHLEN 260
+#endif
+
+#if !defined (A_RONLY)
+#define A_RONLY   0x01
+#define A_HIDDEN  0x02
+#define A_SYSTEM  0x04
+#define A_LABEL   0x08
+#define A_DIR     0x10
+#define A_ARCHIVE 0x20
+#endif
+
+#define _DIRENT_D_MODE_RENAMED_D_ATTR
+
+struct dirent
+{
+  ino_t          d_ino;                 /* Almost not used           */
+  int            d_reclen;              /* Almost not used           */
+  int            d_namlen;              /* Length of d_name          */
+  char           d_name[MAXNAMLEN + 1]; /* File name, 0 terminated   */
+  long           d_size;                /* File size (bytes)         */
+  unsigned short d_attr;                /* OS file attributes        */
+  unsigned short d_time;                /* OS file modification time */
+  unsigned short d_date;                /* OS file modification date */
+};
+
+#endif /* not SYS_DIRENT_H */
Index: trunk/src/emx/include/sys/dirtree.h
===================================================================
--- trunk/src/emx/include/sys/dirtree.h	(revision 18)
+++ trunk/src/emx/include/sys/dirtree.h	(revision 18)
@@ -0,0 +1,46 @@
+/* sys/dirtree.h (emx+gcc) */
+
+#ifndef _SYS_DIRTREE_H
+#define _SYS_DIRTREE_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_TIME_T)
+#define _TIME_T
+typedef unsigned long time_t;
+#endif
+
+struct _dt_node
+{
+  struct _dt_node *next;   /* Pointer to next entry of same level */
+  struct _dt_node *sub;    /* Pointer to next level (child) */
+  char *name;              /* Name */
+  long size;               /* File size */
+  long user;               /* Available for user */
+  time_t mtime;            /* Timestamp for last update */
+  unsigned char attr;      /* Attributes */
+};
+
+
+struct _dt_tree
+{
+  struct _dt_node *tree;
+  char *strings;
+};
+
+#define _DT_TREE     0x4000
+#define _DT_NOCPDIR  0x8000
+
+void _dt_free (struct _dt_tree *dt);
+struct _dt_tree *_dt_read (__const__ char *dir, __const__ char *mask,
+    unsigned flags);
+void _dt_sort (struct _dt_tree *dt, __const__ char *spec);
+int _dt_split (__const__ char *src, char *dir, char *mask);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_DIRTREE_H */
Index: trunk/src/emx/include/sys/ea.h
===================================================================
--- trunk/src/emx/include/sys/ea.h	(revision 18)
+++ trunk/src/emx/include/sys/ea.h	(revision 18)
@@ -0,0 +1,26 @@
+/* sys/ea.h (emx+gcc) */
+
+#ifndef _SYS_EA_H
+#define _SYS_EA_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+struct _ea
+{
+  int flags;
+  int size;
+  void *value;
+};
+
+void _ea_free (struct _ea *);
+int _ea_get (struct _ea *, __const__ char *, int, __const__ char *);
+int _ea_put (struct _ea *, __const__ char *, int, __const__ char *);
+int _ea_remove (__const__ char *, int, __const__ char *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_EA_H */
Index: trunk/src/emx/include/sys/ead.h
===================================================================
--- trunk/src/emx/include/sys/ead.h	(revision 18)
+++ trunk/src/emx/include/sys/ead.h	(revision 18)
@@ -0,0 +1,41 @@
+/* sys/ead.h (emx+gcc) */
+
+#ifndef _SYS_EAD_H
+#define _SYS_EAD_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define _EAD_MERGE       0x0001
+
+typedef struct _ead_data *_ead;
+
+int _ead_add (_ead, __const__ char *, int, __const__ void *, int);
+void _ead_clear (_ead);
+int _ead_copy (_ead, _ead, int);
+int _ead_count (_ead);
+_ead _ead_create (void);
+int _ead_delete (_ead, int);
+void _ead_destroy (_ead);
+int _ead_fea2list_size (_ead);
+void *_ead_fea2list_to_fealist (__const__ void *);
+void *_ead_fealist_to_fea2list (__const__ void *);
+int _ead_find (_ead, __const__ char *);
+__const__ void *_ead_get_fea2list (_ead);
+int _ead_get_flags (_ead, int);
+__const__ char *_ead_get_name (_ead, int);
+__const__ void *_ead_get_value (_ead, int);
+int _ead_name_len (_ead, int);
+int _ead_read (_ead, __const__ char *, int, int);
+int _ead_replace (_ead, int, int, __const__ void *, int);
+void _ead_sort (_ead);
+int _ead_use_fea2list (_ead, __const__ void *);
+int _ead_value_size (_ead, int);
+int _ead_write (_ead, __const__ char *, int, int);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_EAD_H */
Index: trunk/src/emx/include/sys/emxload.h
===================================================================
--- trunk/src/emx/include/sys/emxload.h	(revision 18)
+++ trunk/src/emx/include/sys/emxload.h	(revision 18)
@@ -0,0 +1,33 @@
+/* sys/emxload.h (emx+gcc) */
+
+#ifndef _SYS_EMXLOAD_H
+#define _SYS_EMXLOAD_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#define _EMXLOAD_INDEFINITE     (-1)
+
+int _emxload_env (const char *envname);
+int _emxload_this (int seconds);
+int _emxload_prog (const char *name, int seconds);
+int _emxload_unload (const char *name, int wait_flag);
+
+int _emxload_list_start (void);
+int _emxload_list_get (char *buf, size_t buf_size, int *pseconds);
+
+int _emxload_connect (void);
+int _emxload_disconnect (void);
+int _emxload_stop (int wait_flag);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_EMXLOAD_H */
Index: trunk/src/emx/include/sys/errno.h
===================================================================
--- trunk/src/emx/include/sys/errno.h	(revision 18)
+++ trunk/src/emx/include/sys/errno.h	(revision 18)
@@ -0,0 +1,103 @@
+/* sys/errno.h (emx+gcc) */
+
+#ifndef _SYS_ERRNO_H
+#define _SYS_ERRNO_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (__ASSEMBLER__) && !defined (_ERRNO)
+#define _ERRNO
+#if defined (__MT__) || defined (__ST_MT_ERRNO__)
+extern int *_errno (void);
+#define errno (*_errno ())
+#else
+extern int errno;
+#endif
+#endif
+
+#define EPERM           1   /* Operation not permitted              */
+#define ENOENT          2   /* No such file or directory            */
+#define ESRCH           3   /* No such process                      */
+#define EINTR           4   /* Interrupted system call              */
+#define EIO             5   /* I/O error                            */
+#define ENXIO           6   /* No such device or address            */
+#define E2BIG           7   /* Arguments or environment too big     */
+#define ENOEXEC         8   /* Invalid executable file format       */
+#define EBADF           9   /* Bad file number                      */
+#define ECHILD          10  /* No child processes                   */
+#define EAGAIN          11  /* Resource temporarily unavailable     */
+#define ENOMEM          12  /* Not enough memory                    */
+#define EACCES          13  /* Permission denied                    */
+#define EFAULT          14  /* Bad address                          */
+#define ENOLCK          15  /* No locks available                   */
+#define EBUSY           16  /* Resource busy                        */
+#define EEXIST          17  /* File exists                          */
+#define EXDEV           18  /* Cross-device link                    */
+#define ENODEV          19  /* No such device                       */
+#define ENOTDIR         20  /* Not a directory                      */
+#define EISDIR          21  /* Is a directory                       */
+#define EINVAL          22  /* Invalid argument                     */
+#define ENFILE          23  /* Too many open files in system        */
+#define EMFILE          24  /* Too many open files                  */
+#define ENOTTY          25  /* Inappropriate ioctl                  */
+#define EDEADLK         26  /* Resource deadlock avoided            */
+#define EFBIG           27  /* File too large                       */
+#define ENOSPC          28  /* Disk full                            */
+#define ESPIPE          29  /* Invalid seek                         */
+#define EROFS           30  /* Read-only file system                */
+#define EMLINK          31  /* Too many links                       */
+#define EPIPE           32  /* Broken pipe                          */
+#define EDOM            33  /* Domain error                         */
+#define ERANGE          34  /* Result too large                     */
+#define ENOTEMPTY       35  /* Directory not empty                  */
+#define EINPROGRESS     36  /* Operation now in progress            */
+#define ENOSYS          37  /* Function not implemented             */
+#define ENAMETOOLONG    38  /* File name too long                   */
+#define EDESTADDRREQ    39  /* Destination address required         */
+#define EMSGSIZE        40  /* Message too long                     */
+#define EPROTOTYPE      41  /* Protocol wrong type for socket       */
+#define ENOPROTOOPT     42  /* Option not supported by protocol     */
+#define EPROTONOSUPPORT 43  /* Protocol not supported               */
+#define ESOCKTNOSUPPORT 44  /* Socket type not supported            */
+#define EOPNOTSUPP      45  /* Operation not supported on socket    */
+#define EPFNOSUPPORT    46  /* Protocol family not supported        */
+#define EAFNOSUPPORT    47  /* Address family not supported by protocol family */
+#define EADDRINUSE      48  /* Address already in use               */
+#define EADDRNOTAVAIL   49  /* Can't assigned requested address     */
+#define ENETDOWN        50  /* Network is down                      */
+#define ENETUNREACH     51  /* Network is unreachable               */
+#define ENETRESET       52  /* Network dropped connection on reset  */
+#define ECONNABORTED    53  /* Software caused connection abort     */
+#define ECONNRESET      54  /* Connection reset by peer             */
+#define ENOBUFS         55  /* No buffer space available            */
+#define EISCONN         56  /* Socket is already connected          */
+#define ENOTCONN        57  /* Socket is not connected              */
+#define ESHUTDOWN       58  /* Can't send after socket shutdown     */
+#define ETOOMANYREFS    59  /* Too many references: can't splice    */
+#define ETIMEDOUT       60  /* Connection timed out                 */
+#define ECONNREFUSED    61  /* Connection refused                   */
+#define ELOOP           62  /* Too many levels of symbolic links    */
+#define ENOTSOCK        63  /* Socket operation on non-socket       */
+#define EHOSTDOWN       64  /* Host is down                         */
+#define EHOSTUNREACH    65  /* No route to host                     */
+#define EALREADY        66  /* Operation already in progress        */
+
+#define EWOULDBLOCK     EAGAIN
+
+#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)) \
+    || defined (_WITH_UNDERSCORE)
+
+#if !defined (__ASSEMBLER__)
+int *_errno (void);
+#endif
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_ERRNO_H */
Index: trunk/src/emx/include/sys/fcntl.h
===================================================================
--- trunk/src/emx/include/sys/fcntl.h	(revision 18)
+++ trunk/src/emx/include/sys/fcntl.h	(revision 18)
@@ -0,0 +1,88 @@
+/* sys/fcntl.h (emx+gcc) */
+
+#ifndef _SYS_FCNTL_H
+#define _SYS_FCNTL_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* Don't forget to update /emx/src/dos/termio.inc when changing this! */
+
+#if !defined (O_RDONLY)
+#define O_ACCMODE       0x03    /* mask */
+#define O_RDONLY        0x00
+#define O_WRONLY        0x01
+#define O_RDWR          0x02
+#define O_NONBLOCK      0x04
+#define O_APPEND        0x08
+#define O_TEXT          0x10
+
+#define O_BINARY        0x0100
+#define O_CREAT         0x0200
+#define O_TRUNC         0x0400
+#define O_EXCL          0x0800
+#define O_SYNC          0x2000
+#define O_NOCTTY        0x4000
+#define O_SIZE          0x8000
+
+#if !defined (_POSIX_SOURCE)
+#define O_NDELAY        O_NONBLOCK
+#define O_NOINHERIT     0x1000
+#endif
+
+#endif
+
+#if !defined (F_OK)
+#define F_OK 0
+#define X_OK 1
+#define W_OK 2
+#define R_OK 4
+#endif
+
+#if !defined (F_GETFL)
+#define F_GETFL     1
+#define F_SETFL     2
+#define F_GETFD     3
+#define F_SETFD     4
+#define F_DUPFD     5
+#define F_GETOSFD   6           /* RSXNT */
+#endif
+
+#if !defined (FD_CLOEXEC)
+#define FD_CLOEXEC  0x01
+#endif
+
+int creat (__const__ char *, int);
+int fcntl (int, int, ...);
+int open (__const__ char *, int, ...);
+
+#if !defined (_POSIX_SOURCE)
+
+#if !defined (LOCK_SH)
+#define LOCK_SH     0x01
+#define LOCK_EX     0x02
+#define LOCK_NB     0x04
+#define LOCK_UN     0x08
+#endif
+
+int flock (int, int);
+
+#endif
+
+
+#if !defined (_POSIX_SOURCE) || defined (_WITH_UNDERSCORE)
+
+int _creat (__const__ char *, int);
+int _fcntl (int, int, ...);
+int _flock (int, int);
+int _open (__const__ char *, int, ...);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_FCNTL_H */
Index: trunk/src/emx/include/sys/file.h
===================================================================
--- trunk/src/emx/include/sys/file.h	(revision 18)
+++ trunk/src/emx/include/sys/file.h	(revision 18)
@@ -0,0 +1,6 @@
+/* sys/file.h (emx+gcc) */
+
+#ifndef _SYS_FILE_H
+#define _SYS_FILE_H
+#include <sys/fcntl.h>
+#endif /* not _SYS_FILE_H */
Index: trunk/src/emx/include/sys/fmutex.h
===================================================================
--- trunk/src/emx/include/sys/fmutex.h	(revision 18)
+++ trunk/src/emx/include/sys/fmutex.h	(revision 18)
@@ -0,0 +1,92 @@
+/* sys/fmutex.h (emx+gcc) */
+
+/* Fast mutex semaphores. */
+
+/* This header requires <sys/builtin.h>. */
+
+#ifndef _SYS_FMUTEX_H
+#define _SYS_FMUTEX_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* Constants for _fmutex.fs.  See _fmutex_available() for ordering. */
+
+#define _FMS_UNINIT       0
+#define _FMS_AVAILABLE    1
+#define _FMS_OWNED_SIMPLE 2
+#define _FMS_OWNED_HARD   3
+
+/* Constants for _fmutex_create() */
+
+#define _FMC_SHARED     0x01
+
+/* Constants for _fmutex_request() */
+
+#define _FMR_IGNINT     0x01
+#define _FMR_NOWAIT     0x02
+
+/* We cannot use __attribute__ ((__packed__)) because G++ does not
+   support this. */
+
+#pragma pack(1)
+typedef struct
+{
+  unsigned long hev;            /* HEV */
+  __volatile__ signed char fs;  /* Status */
+} _fmutex;
+#pragma pack()
+
+
+unsigned __fmutex_request_internal (_fmutex *, unsigned, signed char);
+unsigned __fmutex_create_internal (_fmutex *, unsigned);
+unsigned __fmutex_release_internal (_fmutex *);
+
+
+static __inline__ unsigned _fmutex_request (_fmutex *sem, unsigned flags)
+{
+  signed char fs;
+
+  fs = __cxchg (&sem->fs, _FMS_OWNED_SIMPLE);
+  if (fs == _FMS_AVAILABLE)
+    return 0;
+  else
+    return __fmutex_request_internal (sem, flags, fs);
+}
+
+
+static __inline__ unsigned _fmutex_release (_fmutex *sem)
+{
+  signed char fs;
+
+  fs = __cxchg (&sem->fs, _FMS_AVAILABLE);
+  if (fs == _FMS_OWNED_HARD)
+    return __fmutex_release_internal (sem);
+  else
+    return 0;
+}
+
+
+static __inline__ int _fmutex_available (_fmutex *sem)
+{
+  return sem->fs <= _FMS_AVAILABLE;
+}
+
+
+unsigned _fmutex_create (_fmutex *, unsigned);
+unsigned _fmutex_open (_fmutex *);
+unsigned _fmutex_close (_fmutex *);
+void _fmutex_dummy (_fmutex *);
+
+void _fmutex_checked_close (_fmutex *);
+void _fmutex_checked_create (_fmutex *, unsigned);
+void _fmutex_checked_open (_fmutex *);
+void _fmutex_checked_release (_fmutex *);
+void _fmutex_checked_request (_fmutex *, unsigned);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_FMUTEX_H */
Index: trunk/src/emx/include/sys/hw.h
===================================================================
--- trunk/src/emx/include/sys/hw.h	(revision 18)
+++ trunk/src/emx/include/sys/hw.h	(revision 18)
@@ -0,0 +1,38 @@
+/* sys/hw.h (emx+gcc) */
+
+#ifndef _SYS_HW_H
+#define _SYS_HW_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+void *_memaccess (unsigned, unsigned, int);
+int _portaccess (unsigned, unsigned);
+
+unsigned _inp8 (unsigned);
+unsigned _inp16 (unsigned);
+unsigned _inp32 (unsigned);
+void _inps8 (unsigned, unsigned char *, unsigned);
+void _inps16 (unsigned, unsigned short *, unsigned);
+void _inps32 (unsigned, unsigned long *, unsigned);
+
+void _outp8 (unsigned, unsigned value);
+void _outp16 (unsigned, unsigned value);
+void _outp32 (unsigned, unsigned value);
+void _outps8 (unsigned, __const__ unsigned char *, unsigned);
+void _outps16 (unsigned, __const__ unsigned short *, unsigned);
+void _outps32 (unsigned, __const__ unsigned long *, unsigned);
+void _outpt (__const__ void *);
+void _outps8dac (unsigned, __const__ unsigned char *, unsigned);
+
+void _wait0 (unsigned, unsigned);
+void _wait1 (unsigned, unsigned);
+void _wait01 (unsigned, unsigned);
+void _wait10 (unsigned, unsigned);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not SYS_HW_H */
Index: trunk/src/emx/include/sys/ioctl.h
===================================================================
--- trunk/src/emx/include/sys/ioctl.h	(revision 18)
+++ trunk/src/emx/include/sys/ioctl.h	(revision 18)
@@ -0,0 +1,57 @@
+/* ioctl.h (emx+gcc) */
+
+#ifndef _SYS_IOCTL_H
+#define _SYS_IOCTL_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined (_EMX_TCPIP)
+#include <sys/so_ioctl.h>
+#endif
+
+#if !defined (TCGETA)
+#define TCGETA      1
+#define TCSETA      2
+#define TCSETAW     3
+#define TCSETAF     4
+#define TCFLSH      5
+#define TCSBRK      6
+#define TCXONC      7
+#endif
+
+#define _TCGA       8           /* Used internally for tcgetattr() */
+#define _TCSANOW    9           /* Used internally for tcsetattr() */
+#define _TCSADRAIN  10          /* Used internally for tcsetattr() */
+#define _TCSAFLUSH  11          /* Used internally for tcsetattr() */
+
+#if !defined (FIONREAD)
+#define FIONREAD   16
+#endif
+
+#if !defined (FGETHTYPE)
+#define FGETHTYPE  32
+#endif
+
+#if !defined (HT_FILE)
+#define HT_FILE         0
+#define HT_UPIPE        1
+#define HT_NPIPE        2
+#define HT_DEV_OTHER    3
+#define HT_DEV_NUL      4
+#define HT_DEV_CON      5
+#define HT_DEV_CLK      7
+#define HT_SOCKET       8
+#define HT_ISDEV(n)     ((n) >= HT_DEV_OTHER && (n) <= HT_DEV_CLK)
+#endif
+
+int ioctl (int, int, ...);
+
+int _ioctl (int, int, ...);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_IOCTL_H */
Index: trunk/src/emx/include/sys/ipc.h
===================================================================
--- trunk/src/emx/include/sys/ipc.h	(revision 18)
+++ trunk/src/emx/include/sys/ipc.h	(revision 18)
@@ -0,0 +1,38 @@
+/* sys/ipc.h (emx+gcc) */
+
+#ifndef _SYS_IPC_H
+#define _SYS_IPC_H
+
+#if !defined (_KEY_T)
+#define _KEY_T
+typedef long key_t;
+#endif
+
+#if !defined (_IPC_PERM)
+#define _IPC_PERM
+struct ipc_perm
+{
+  unsigned short uid;
+  unsigned short gid;
+  unsigned short cuid;
+  unsigned short cgid;
+  unsigned short mode;
+  unsigned short seq;
+  key_t key;
+};
+#endif
+
+#if !defined (IPC_CREAT)
+#define IPC_CREAT   0x0200
+#define IPC_EXCL    0x0400
+#define IPC_NOWAIT  0x0800
+#define IPC_ALLOC   0x8000
+
+#define IPC_PRIVATE (key_t)0
+
+#define IPC_RMID    0
+#define IPC_SET     1
+#define IPC_STAT    2
+#endif
+
+#endif /* not SYS_IPC_H */
Index: trunk/src/emx/include/sys/kbdscan.h
===================================================================
--- trunk/src/emx/include/sys/kbdscan.h	(revision 18)
+++ trunk/src/emx/include/sys/kbdscan.h	(revision 18)
@@ -0,0 +1,158 @@
+/* sys/kbdscan.h (emx+gcc) */
+
+#ifndef _SYS_KBDSCAN_H
+#define _SYS_KBDSCAN_H
+
+/* [DOS]: DOS only */
+/* [OS2]: OS/2 only */
+
+#define K_ALT_ESC               0x01   /* <Alt>+<Esc>    [DOS]*/
+#define K_CTRL_SPACE            0x02   /* <Ctrl>+<Space> [OS2]*/
+#define K_CTRL_AT               0x03   /* <Ctrl>+<@> */
+#define K_SHIFT_INS             0x04   /* <Shift>+<Ins>  [OS2]*/
+#define K_SHIFT_DEL             0x05   /* <Shift>+<Del>  [OS2]*/
+#define K_ALT_BACKSPACE         0x0e   /* <Alt>+<Backspace> */
+#define K_BACKTAB               0x0f   /* <Shift>+<Tab> */
+#define K_ALT_Q                 0x10   /* <Alt>+<Q> */
+#define K_ALT_W                 0x11   /* <Alt>+<W> */
+#define K_ALT_E                 0x12   /* <Alt>+<E> */
+#define K_ALT_R                 0x13   /* <Alt>+<R> */
+#define K_ALT_T                 0x14   /* <Alt>+<T> */
+#define K_ALT_Y                 0x15   /* <Alt>+<Y> */
+#define K_ALT_U                 0x16   /* <Alt>+<U> */
+#define K_ALT_I                 0x17   /* <Alt>+<I> */
+#define K_ALT_O                 0x18   /* <Alt>+<O> */
+#define K_ALT_P                 0x19   /* <Alt>+<P> */
+#define K_ALT_LEFT_BRACKET      0x1a   /* <Alt>+<[> */
+#define K_ALT_RIGHT_BRACKET     0x1b   /* <Alt>+<]> */
+#define K_ALT_RETURN            0x1c   /* <Alt>+<Return> */
+#define K_ALT_A                 0x1e   /* <Alt>+<A> */
+#define K_ALT_S                 0x1f   /* <Alt>+<S> */
+#define K_ALT_D                 0x20   /* <Alt>+<D> */
+#define K_ALT_F                 0x21   /* <Alt>+<F> */
+#define K_ALT_G                 0x22   /* <Alt>+<G> */
+#define K_ALT_H                 0x23   /* <Alt>+<H> */
+#define K_ALT_J                 0x24   /* <Alt>+<J> */
+#define K_ALT_K                 0x25   /* <Alt>+<K> */
+#define K_ALT_L                 0x26   /* <Alt>+<L> */
+#define K_ALT_SEMICOLON         0x27   /* <Alt>+<;> */
+#define K_ALT_RIGHT_QUOTE       0x28   /* <Alt>+<'> */
+#define K_ALT_LEFT_QUOTE        0x29   /* <Alt>+<`> */
+#define K_ALT_BACKSLASH         0x2b   /* <Alt>+<\> */
+#define K_ALT_Z                 0x2c   /* <Alt>+<Z> */
+#define K_ALT_X                 0x2d   /* <Alt>+<X> */
+#define K_ALT_C                 0x2e   /* <Alt>+<C> */
+#define K_ALT_V                 0x2f   /* <Alt>+<V> */
+#define K_ALT_B                 0x30   /* <Alt>+<B> */
+#define K_ALT_N                 0x31   /* <Alt>+<N> */
+#define K_ALT_M                 0x32   /* <Alt>+<M> */
+#define K_ALT_COMMA             0x33   /* <Alt>+<,> */
+#define K_ALT_PERIOD            0x34   /* <Alt>+<.> */
+#define K_ALT_SLASH             0x35   /* <Alt>+</> */
+#define K_ALT_PAD_ASTERISK      0x37   /* <Alt>+<*> (numeric keypad) */
+#define K_ALT_SPACE             0x39   /* <Alt>+<Space>  [OS2] */
+#define K_F1                    0x3b   /* <F1> */
+#define K_F2                    0x3c   /* <F2> */
+#define K_F3                    0x3d   /* <F3> */
+#define K_F4                    0x3e   /* <F4> */
+#define K_F5                    0x3f   /* <F5> */
+#define K_F6                    0x40   /* <F6> */
+#define K_F7                    0x41   /* <F7> */
+#define K_F8                    0x42   /* <F8> */
+#define K_F9                    0x43   /* <F9> */
+#define K_F10                   0x44   /* <F10> */
+#define K_HOME                  0x47   /* <Home> */
+#define K_UP                    0x48   /* <Up arrow> */
+#define K_PAGEUP                0x49   /* <Page up> */
+#define K_ALT_PAD_MINUS         0x4a   /* <Alt>+<-> (numeric keypad) */
+#define K_LEFT                  0x4b   /* <Left arrow> */
+#define K_CENTER                0x4c   /* Center cursor */
+#define K_RIGHT                 0x4d   /* <Right arrow> */
+#define K_ALT_PAD_PLUS          0x4e   /* <Alt>+<+> (numeric keypad) */
+#define K_END                   0x4f   /* <End> */
+#define K_DOWN                  0x50   /* <Down arrow> */
+#define K_PAGEDOWN              0x51   /* <Page down> */
+#define K_INS                   0x52   /* <Ins> */
+#define K_DEL                   0x53   /* <Del> */
+#define K_SHIFT_F1              0x54   /* <Shift>+<F1> */
+#define K_SHIFT_F2              0x55   /* <Shift>+<F2> */
+#define K_SHIFT_F3              0x56   /* <Shift>+<F3> */
+#define K_SHIFT_F4              0x57   /* <Shift>+<F4> */
+#define K_SHIFT_F5              0x58   /* <Shift>+<F5> */
+#define K_SHIFT_F6              0x59   /* <Shift>+<F6> */
+#define K_SHIFT_F7              0x5a   /* <Shift>+<F7> */
+#define K_SHIFT_F8              0x5b   /* <Shift>+<F8> */
+#define K_SHIFT_F9              0x5c   /* <Shift>+<F9> */
+#define K_SHIFT_F10             0x5d   /* <Shift>+<F10> */
+#define K_CTRL_F1               0x5e   /* <Ctrl>+<F1> */
+#define K_CTRL_F2               0x5f   /* <Ctrl>+<F2> */
+#define K_CTRL_F3               0x60   /* <Ctrl>+<F3> */
+#define K_CTRL_F4               0x61   /* <Ctrl>+<F4> */
+#define K_CTRL_F5               0x62   /* <Ctrl>+<F5> */
+#define K_CTRL_F6               0x63   /* <Ctrl>+<F6> */
+#define K_CTRL_F7               0x64   /* <Ctrl>+<F7> */
+#define K_CTRL_F8               0x65   /* <Ctrl>+<F8> */
+#define K_CTRL_F9               0x66   /* <Ctrl>+<F9> */
+#define K_CTRL_F10              0x67   /* <Ctrl>+<F10> */
+#define K_ALT_F1                0x68   /* <Alt>+<F1> */
+#define K_ALT_F2                0x69   /* <Alt>+<F2> */
+#define K_ALT_F3                0x6a   /* <Alt>+<F3> */
+#define K_ALT_F4                0x6b   /* <Alt>+<F4> */
+#define K_ALT_F5                0x6c   /* <Alt>+<F5> */
+#define K_ALT_F6                0x6d   /* <Alt>+<F6> */
+#define K_ALT_F7                0x6e   /* <Alt>+<F7> */
+#define K_ALT_F8                0x6f   /* <Alt>+<F8> */
+#define K_ALT_F9                0x70   /* <Alt>+<F9> */
+#define K_ALT_F10               0x71   /* <Alt>+<F10> */
+#define K_CTRL_PRTSC            0x72   /* <Ctrl>+<PrtSc> */
+#define K_CTRL_LEFT             0x73   /* <Ctrl>+<Left arrow> */
+#define K_CTRL_RIGHT            0x74   /* <Ctrl>+<Right arrow> */
+#define K_CTRL_END              0x75   /* <Ctrl>+<End> */
+#define K_CTRL_PAGEDOWN         0x76   /* <Ctrl>+<Page down> */
+#define K_CTRL_HOME             0x77   /* <Ctrl>+<Home> */
+#define K_ALT_1                 0x78   /* <Alt>+<1> */
+#define K_ALT_2                 0x79   /* <Alt>+<2> */
+#define K_ALT_3                 0x7a   /* <Alt>+<3> */
+#define K_ALT_4                 0x7b   /* <Alt>+<4> */
+#define K_ALT_5                 0x7c   /* <Alt>+<5> */
+#define K_ALT_6                 0x7d   /* <Alt>+<6> */
+#define K_ALT_7                 0x7e   /* <Alt>+<7> */
+#define K_ALT_8                 0x7f   /* <Alt>+<8> */
+#define K_ALT_9                 0x80   /* <Alt>+<9> */
+#define K_ALT_0                 0x81   /* <Alt>+<0> */
+#define K_ALT_MINUS             0x82   /* <Alt>+<-> */
+#define K_ALT_EQUAL             0x83   /* <Alt>+<=> */
+#define K_CTRL_PAGEUP           0x84   /* <Ctrl>+<Page up> */
+#define K_F11                   0x85   /* <F11> */
+#define K_F12                   0x86   /* <F12> */
+#define K_SHIFT_F11             0x87   /* <Shift>+<F11> */
+#define K_SHIFT_F12             0x88   /* <Shift>+<F12> */
+#define K_CTRL_F11              0x89   /* <Ctrl>+<F11> */
+#define K_CTRL_F12              0x8a   /* <Ctrl>+<F12> */
+#define K_ALT_F11               0x8b   /* <Alt>+<F11> */
+#define K_ALT_F12               0x8c   /* <Alt>+<F12> */
+#define K_CTRL_UP               0x8d   /* <Ctrl>+<Up arrow> */
+#define K_CTRL_PAD_MINUS        0x8e   /* <Ctrl>+<-> (numeric keypad) */
+#define K_CTRL_CENTER           0x8f   /* <Ctrl>+<Center> */
+#define K_CTRL_PAD_PLUS         0x90   /* <Ctrl>+<+> (numeric keypad) */
+#define K_CTRL_DOWN             0x91   /* <Ctrl>+<Down arrow> */
+#define K_CTRL_INS              0x92   /* <Ctrl>+<Ins> */
+#define K_CTRL_DEL              0x93   /* <Ctrl>+<Del> */
+#define K_CTRL_TAB              0x94   /* <Ctrl>+<Tab> */
+#define K_CTRL_PAD_SLASH        0x95   /* <Ctrl>+</> (numeric keypad) */
+#define K_CTRL_PAD_ASTERISK     0x96   /* <Ctrl>+<*> (numeric keypad) */
+#define K_ALT_HOME              0x97   /* <Alt>+<Home> */
+#define K_ALT_UP                0x98   /* <Alt>+<Up arrow> */
+#define K_ALT_PAGEUP            0x99   /* <Alt>+<Page up> */
+#define K_ALT_LEFT              0x9b   /* <Alt>+<Left arrow> */
+#define K_ALT_RIGHT             0x9d   /* <Alt>+<Right arrow> */
+#define K_ALT_END               0x9f   /* <Alt>+<End> */
+#define K_ALT_DOWN              0xa0   /* <Alt>+<Down arrow> */
+#define K_ALT_PAGEDOWN          0xa1   /* <Alt>+<Page down> */
+#define K_ALT_INS               0xa2   /* <Alt>+<Ins> */
+#define K_ALT_DEL               0xa3   /* <Alt>+<Del> */
+#define K_ALT_PAD_SLASH         0xa4   /* <Alt>+</> (numeric keypad) */
+#define K_ALT_TAB               0xa5   /* <Alt>+<Tab>  [DOS] */
+#define K_ALT_PAD_ENTER         0xa6   /* <Alt>+<Enter> (numeric keypad) */
+
+#endif /* not SYS_KBDSCAN_H */
Index: trunk/src/emx/include/sys/moddef.h
===================================================================
--- trunk/src/emx/include/sys/moddef.h	(revision 18)
+++ trunk/src/emx/include/sys/moddef.h	(revision 18)
@@ -0,0 +1,201 @@
+/* sys/moddef.h (emx+gcc) */
+
+#ifndef _SYS_MODDEF_H
+#define _SYS_MODDEF_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+struct _md;
+
+#define _MDT_DEFAULT            0
+#define _MDT_WINDOWAPI          1
+#define _MDT_WINDOWCOMPAT       2
+#define _MDT_NOTWINDOWCOMPAT    3
+
+#define _MDIT_DEFAULT           0
+#define _MDIT_INSTANCE          1
+#define _MDIT_GLOBAL            2
+
+#define _MDS_ALIAS              0x000001
+#define _MDS_CONFORMING         0x000002
+#define _MDS_DISCARDABLE        0x000004
+#define _MDS_EXECUTEONLY        0x000008
+#define _MDS_EXECUTEREAD        0x000010
+#define _MDS_FIXED              0x000020
+#define _MDS_INVALID            0x000040
+#define _MDS_IOPL               0x000080
+#define _MDS_LOADONCALL         0x000100
+#define _MDS_MIXED1632          0x000200
+#define _MDS_MOVEABLE           0x000400
+#define _MDS_MULTIPLE           0x000800
+#define _MDS_NOIOPL             0x001000
+#define _MDS_NONCONFORMING      0x002000
+#define _MDS_NONDISCARDABLE     0x004000
+#define _MDS_NONE               0x008000
+#define _MDS_NONSHARED          0x010000
+#define _MDS_PRELOAD            0x020000
+#define _MDS_READONLY           0x040000
+#define _MDS_READWRITE          0x080000
+#define _MDS_SHARED             0x100000
+#define _MDS_SINGLE             0x200000
+
+#define _MDX_DEFAULT            0
+#define _MDX_UNKNOWN            1
+#define _MDX_OS2                2
+#define _MDX_WINDOWS            3
+
+#define _MDEP_ORDINAL           0x0001
+#define _MDEP_RESIDENTNAME      0x0002
+#define _MDEP_NONAME            0x0004
+#define _MDEP_NODATA            0x0008
+#define _MDEP_PWORDS            0x0010
+
+#define _MDIP_ORDINAL           0x0001
+
+typedef enum
+{
+  _MD_ALIAS, _MD_BASE, _MD_CLASS, _MD_CODE, _MD_CONFORMING,
+  _MD_CONTIGUOUS, _MD_DATA, _MD_DESCRIPTION, _MD_DEV386, _MD_DEVICE,
+  _MD_DISCARDABLE, _MD_DOS4, _MD_DYNAMIC, _MD_EXECUTEONLY,
+  _MD_EXECUTEREAD, _MD_EXETYPE, _MD_EXPANDDOWN, _MD_EXPORTS,
+  _MD_FIXED, _MD_HEAPSIZE, _MD_HUGE, _MD_IMPORTS, _MD_IMPURE,
+  _MD_INCLUDE, _MD_INITGLOBAL, _MD_INITINSTANCE, _MD_INVALID,
+  _MD_IOPL, _MD_LIBRARY, _MD_LOADONCALL, _MD_MAXVAL, _MD_MIXED1632,
+  _MD_MOVEABLE, _MD_MULTIPLE, _MD_NAME, _MD_NEWFILES, _MD_NODATA,
+  _MD_NOEXPANDDOWN, _MD_NOIOPL, _MD_NONAME, _MD_NONCONFORMING,
+  _MD_NONDISCARDABLE, _MD_NONE, _MD_NONPERMANENT, _MD_NONSHARED,
+  _MD_NOTWINDOWCOMPAT, _MD_OBJECTS, _MD_OLD, _MD_ORDER, _MD_OS2,
+  _MD_PERMANENT, _MD_PHYSICAL, _MD_PRELOAD, _MD_PRIVATE,
+  _MD_PRIVATELIB, _MD_PROTECT, _MD_PROTMODE, _MD_PURE, _MD_READONLY,
+  _MD_READWRITE, _MD_REALMODE, _MD_RESIDENT, _MD_RESIDENTNAME,
+  _MD_SEGMENTS, _MD_SHARED, _MD_SINGLE, _MD_STACKSIZE, _MD_STUB,
+  _MD_SWAPPABLE, _MD_TERMGLOBAL, _MD_TERMINSTANCE, _MD_UNKNOWN,
+  _MD_VIRTUAL, _MD_WINDOWAPI, _MD_WINDOWCOMPAT, _MD_WINDOWS,
+  /* The following tokens are no keywords: */
+  _MD_dot, _MD_at, _MD_equal, _MD_quote, _MD_number, _MD_word,
+  _MD_eof, _MD_ioerror, _MD_missingquote,
+  /* Special `token' for _md_parse() callback: */
+  _MD_parseerror
+} _md_token;
+
+typedef enum
+{
+  _MDE_IO_ERROR,
+  _MDE_MISSING_QUOTE,
+  _MDE_EMPTY,
+  _MDE_NAME_EXPECTED,
+  _MDE_STRING_EXPECTED,
+  _MDE_NUMBER_EXPECTED,
+  _MDE_DEVICE_EXPECTED,
+  _MDE_EQUAL_EXPECTED,
+  _MDE_DOT_EXPECTED,
+  _MDE_STRING_TOO_LONG,
+  _MDE_INVALID_ORDINAL,
+  _MDE_INVALID_STMT
+} _md_error;
+
+typedef union
+{
+  struct
+    {
+      _md_error code;
+      _md_token stmt;
+    } error;                    /* Error */
+  struct
+    {
+      unsigned long addr;
+    } base;                     /* BASE */
+  struct
+    {
+      char string[256];
+    } descr;                    /* DESCRIPTION */
+  struct
+    {
+      char name[256];
+    } device;                   /* PHYSICAL DEVICE and VIRTUAL DEVICE */
+  struct
+    {
+      int type;
+      int minor_version;
+      int major_version;
+    } exetype;                  /* EXETYPE */
+  struct
+    {
+      char entryname[256];
+      char internalname[256];
+      int ordinal;
+      int pwords;
+      unsigned flags;
+    } export;                   /* EXPORTS */
+  struct
+    {
+      char entryname[256];
+      char internalname[256];
+      char modulename[256];
+      int ordinal;
+      unsigned flags;
+    } import;                   /* IMPORTS */
+  struct
+    {
+      unsigned long size;
+      int maxval;
+    } heapsize;                 /* HEAPSIZE */
+  struct
+    {
+      char name[256];
+      int init;
+      int term;
+    } library;                  /* LIBRARY */
+  struct
+    {
+      char name[256];
+      int pmtype;
+      int newfiles;
+    } name;                     /* NAME */
+  struct
+    {
+      char name[256];
+    } old;                      /* OLD */
+  struct
+    {
+      char segname[256];
+      char classname[256];
+      unsigned attr;
+    } segment;                  /* SEGMENTS, CODE, DATA */
+  struct
+    {
+      unsigned long size;
+    } stacksize;                /* STACKSIZE */
+  struct
+    {
+      char name[256];
+      int none;
+    } stub;                     /* STUB */
+} _md_stmt;
+
+
+long _md_get_linenumber (const struct _md *md);
+long _md_get_number (const struct _md *md);
+const char *_md_get_string (const struct _md *md);
+_md_token _md_get_token (const struct _md *md);
+
+_md_token _md_next_token (struct _md *md);
+
+int _md_close (struct _md *md);
+struct _md *_md_open (const char *fname);
+struct _md *_md_use_file (FILE *f);
+
+int _md_parse (struct _md *md,
+               int (*callback)(struct _md *md, const _md_stmt *stmt,
+                               _md_token token, void *arg),
+               void *arg);
+
+const char *_md_errmsg (_md_error code);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_MODDEF_H */
Index: trunk/src/emx/include/sys/msg.h
===================================================================
--- trunk/src/emx/include/sys/msg.h	(revision 18)
+++ trunk/src/emx/include/sys/msg.h	(revision 18)
@@ -0,0 +1,69 @@
+/* sys/msg.h (emx+gcc) */
+
+#ifndef _SYS_MSG_H
+#define _SYS_MSG_H
+
+#if !defined (_MSG)
+#define _MSG
+struct msg
+{
+  struct msg *msg_next;
+  long msg_type;
+  short msg_ts;
+  short msg_spot;
+};
+#endif
+
+#if !defined (_MSQID_DS)
+#define _MSQID_DS
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;
+  struct msg *msg_first;
+  struct msg *msg_last;
+  unsigned short msg_cbytes;
+  unsigned short msg_qnum;
+  unsigned short msg_qbytes;
+  unsigned short msg_lspid;
+  unsigned short msg_lrpid;
+  time_t msg_stime;
+  time_t msg_rtime;
+  time_t msg_ctime;
+};
+#endif
+
+#if !defined (_MSGBUF)
+#define _MSGBUF
+struct msgbuf
+{
+  long mtype;
+  char mtext[1];
+};
+#endif
+
+#if !defined (_MSGINFO)
+#define _MSGINFO
+struct msginfo
+{
+  int msgmap;
+  int msgmax;
+  int msgmnb;
+  int msgmni;
+  int msgssz;
+  int msgtql;
+  unsigned short msgseg;
+};
+#endif
+
+#if !defined (MSG_R)
+#define MSG_R       0400
+#define MSG_W       0200
+
+#define	MSG_RWAIT   0x0200
+#define	MSG_WWAIT   0x0400
+
+#define	MSG_NOERROR 0x1000
+
+#endif
+
+#endif /* not SYS_MSG_H */
Index: trunk/src/emx/include/sys/nls.h
===================================================================
--- trunk/src/emx/include/sys/nls.h	(revision 18)
+++ trunk/src/emx/include/sys/nls.h	(revision 18)
@@ -0,0 +1,29 @@
+/* sys/nls.h (emx+gcc) */
+
+#ifndef _SYS_NLS_H
+#define _SYS_NLS_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define _NLS_DBCS_LEAD  0x01
+
+extern unsigned char _nls_toupper_tab[256];
+extern unsigned char _nls_tolower_tab[256];
+extern unsigned char _nls_ctype_tab[256];
+
+#define _nls_tolower(c) _nls_tolower_tab[c]
+#define _nls_toupper(c) _nls_toupper_tab[c]
+
+#define _nls_is_dbcs_lead(c) _nls_ctype_tab[c]
+
+void _nls_init (void);
+unsigned char *_nls_strlwr (unsigned char *string);
+unsigned char *_nls_strupr (unsigned char *string);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_NLS_H */
Index: trunk/src/emx/include/sys/omflib.h
===================================================================
--- trunk/src/emx/include/sys/omflib.h	(revision 18)
+++ trunk/src/emx/include/sys/omflib.h	(revision 18)
@@ -0,0 +1,70 @@
+/* sys/omflib.h (emx+gcc) */
+
+/* Public header file for the emx OMFLIB library. */
+
+#ifndef _SYS_OMFLIB_H
+#define _SYS_OMFLIB_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#if !defined (THEADR)
+
+#define THEADR 0x80
+#define LHEADR 0x82
+#define COMENT 0x88
+#define MODEND 0x8a
+#define PUBDEF 0x90
+#define ALIAS  0xc6
+#define LIBHDR 0xf0
+#define LIBEND 0xf1
+
+#define REC32  0x01
+
+#endif
+
+/* Comment classes */
+
+#if !defined (IMPDEF_CLASS)
+
+#define IMPDEF_CLASS    0xa0
+#define LIBMOD_CLASS    0xa3
+
+#define IMPDEF_SUBTYPE  0x01
+
+#endif
+
+struct omflib;
+
+struct omflib *omflib_open (const char *fname, char *error);
+struct omflib *omflib_create (const char *fname, int page_size, char *error);
+int omflib_close (struct omflib *p, char *error);
+int omflib_module_name (char *dst, const char *src);
+int omflib_find_module (struct omflib *p, const char *name, char *error);
+int omflib_mark_deleted (struct omflib *p, const char *name, char *error);
+int omflib_pubdef_walk (struct omflib *p, word page,
+    int (*walker)(const char *name, char *error), char *error);
+int omflib_extract (struct omflib *p, const char *name, char *error);
+int omflib_add_module (struct omflib *p, const char *fname, char *error);
+int omflib_module_count (struct omflib *p, char *error);
+int omflib_module_info (struct omflib *p, int n, char *name, int *page,
+    char *error);
+int omflib_copy_lib (struct omflib *dst, struct omflib *src, char *error);
+int omflib_finish (struct omflib *p, char *error);
+int omflib_write_record (struct omflib *p, byte rec_type, word rec_len,
+    const byte *buffer, int chksum, char *error);
+int omflib_write_module (struct omflib *p, const char *name, word *pagep,
+    char *error);
+int omflib_add_pub (struct omflib *p, const char *name, word page,
+    char *error);
+int omflib_header (struct omflib *p, char *error);
+int omflib_find_symbol (struct omflib *p, const char *name, char *error);
+long omflib_page_pos (struct omflib *p, int page);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_OMFLIB_H */
Index: trunk/src/emx/include/sys/param.h
===================================================================
--- trunk/src/emx/include/sys/param.h	(revision 18)
+++ trunk/src/emx/include/sys/param.h	(revision 18)
@@ -0,0 +1,42 @@
+/* sys/param.h (emx+gcc) */
+
+#ifndef _SYS_PARAM_H
+#define _SYS_PARAM_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (PAGE_SIZE)
+#define PAGE_SIZE 0x1000
+#endif
+
+#if !defined (HZ)
+#define HZ        100
+#endif
+
+#if !defined (MAXNAMLEN)
+#define MAXNAMLEN  260
+#endif
+
+#if !defined (MAXPATHLEN)
+#define MAXPATHLEN 260
+#endif
+
+/* Don't try to do this inline for now */
+
+#if !defined (htonl)
+#define htonl(X) _swapl(X)
+#define ntohl(X) _swapl(X)
+#define htons(X) _swaps(X)
+#define ntohs(X) _swaps(X)
+#endif
+
+unsigned short _swaps (unsigned short _x);
+unsigned long _swapl (unsigned long _x);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_PARAM_H */
Index: trunk/src/emx/include/sys/process.h
===================================================================
--- trunk/src/emx/include/sys/process.h	(revision 18)
+++ trunk/src/emx/include/sys/process.h	(revision 18)
@@ -0,0 +1,94 @@
+/* sys/process.h (emx+gcc) */
+
+#ifndef _SYS_PROCESS_H
+#define _SYS_PROCESS_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (P_WAIT)
+#define P_WAIT    0
+#define P_NOWAIT  1
+#define P_OVERLAY 2
+#define P_DEBUG   3
+#define P_SESSION 4
+#define P_DETACH  5
+#define P_PM      6
+
+#define P_DEFAULT    0x0000
+#define P_MINIMIZE   0x0100
+#define P_MAXIMIZE   0x0200
+#define P_FULLSCREEN 0x0300
+#define P_WINDOWED   0x0400
+
+#define P_FOREGROUND 0x0000
+#define P_BACKGROUND 0x1000
+
+#define P_NOCLOSE    0x2000
+#define P_NOSESSION  0x4000
+
+/* Note: 0x8000 is used internally. */
+
+#define P_QUOTE      0x10000
+#define P_TILDE      0x20000
+#define P_UNRELATED  0x40000
+#define P_DEBUGDESC  0x80000
+
+#endif
+
+void abort (void)  __attribute__ ((__noreturn__));
+int atexit (void (*)(void));
+int execl (__const__ char *, __const__ char *, ...);
+int execle (__const__ char *, __const__ char *, ...);
+int execlp (__const__ char *, __const__ char *, ...);
+int execlpe (__const__ char *, __const__ char *, ...);
+int execv (__const__ char *, char * __const__ *);
+int execve (__const__ char *, char * __const__ *, char * __const__ *);
+int execvp (__const__ char *, char * __const__ *);
+int execvpe (__const__ char *, char * __const__ *, char * __const__ *);
+void exit (int) __attribute__ ((__noreturn__));
+void _exit (int) __attribute__ ((__noreturn__));
+int fork (void);
+int getpid (void);
+int getppid (void);
+int spawnl (int, __const__ char *, __const__ char *, ...);
+int spawnle (int, __const__ char *, __const__ char *, ...);
+int spawnlp (int, __const__ char *, __const__ char *, ...);
+int spawnlpe (int, __const__ char *, __const__ char *, ...);
+int spawnv (int, __const__ char *, char * __const__ *);
+int spawnve (int, __const__ char *, char * __const__ *, char * __const__ *);
+int spawnvp (int, __const__ char *, char * __const__ *);
+int spawnvpe (int, __const__ char *, char * __const__ *, char * __const__ *);
+int system (__const__ char *);
+int wait (int *);
+int waitpid (int, int *, int);
+
+int _execl (__const__ char *, __const__ char *, ...);
+int _execle (__const__ char *, __const__ char *, ...);
+int _execlp (__const__ char *, __const__ char *, ...);
+int _execlpe (__const__ char *, __const__ char *, ...);
+int _execv (__const__ char *, char * __const__ *);
+int _execve (__const__ char *, char * __const__ *, char * __const__ *);
+int _execvp (__const__ char *, char * __const__ *);
+int _execvpe (__const__ char *, char * __const__ *, char * __const__ *);
+int _fork (void);
+int _getpid (void);
+int _getppid (void);
+int _spawnl (int, __const__ char *, __const__ char *, ...);
+int _spawnle (int, __const__ char *, __const__ char *, ...);
+int _spawnlp (int, __const__ char *, __const__ char *, ...);
+int _spawnlpe (int, __const__ char *, __const__ char *, ...);
+int _spawnv (int, __const__ char *, char * __const__ *);
+int _spawnve (int, __const__ char *, char * __const__ *, char * __const__ *);
+int _spawnvp (int, __const__ char *, char * __const__ *);
+int _spawnvpe (int, __const__ char *, char * __const__ *, char * __const__ *);
+int _wait (int *);
+int _waitpid (int, int *, int);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_PROCESS_H */
Index: trunk/src/emx/include/sys/ptrace.h
===================================================================
--- trunk/src/emx/include/sys/ptrace.h	(revision 18)
+++ trunk/src/emx/include/sys/ptrace.h	(revision 18)
@@ -0,0 +1,87 @@
+/* sys/ptrace.h (emx+gcc) */
+
+#ifndef _SYS_PTRACE_H
+#define _SYS_PTRACE_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define PTRACE_TRACEME          0 /* not used by emx */
+#define PTRACE_PEEKTEXT         1
+#define PTRACE_PEEKDATA         2
+#define PTRACE_PEEKUSER         3
+#define PTRACE_POKETEXT         4
+#define PTRACE_POKEDATA         5
+#define PTRACE_POKEUSER         6
+#define PTRACE_RESUME           7
+#define PTRACE_EXIT             8
+#define PTRACE_STEP             9
+#define PTRACE_SESSION          10
+#define PTRACE_NOTIFICATION     11
+#define PTRACE_CONT             12
+#define PTRACE_THAW             13
+#define PTRACE_FREEZE           14
+#define PTRACE_ATTACH           15
+#define PTRACE_DETACH           16
+
+#define PTN_NONE                0
+#define PTN_THREAD_NEW          1
+#define PTN_THREAD_END          2
+#define PTN_MODULE_LOAD         3
+#define PTN_MODULE_FREE         4
+#define PTN_PROC_NEW            5
+
+#define PTNMOD_DLL              0x0001
+#define PTNMOD_AOUT             0x0002
+
+#define PTNPROC_FORK            0x0001
+#define PTNPROC_AOUT            0x0002
+
+#define PTRACE_GETPID(x)        ((unsigned)(x) & 0xffff)
+#define PTRACE_GETTID(x)        (((unsigned)(x) >> 16) & 0xffff)
+#define PTRACE_PIDTID(pid,tid)  (((unsigned)(tid) << 16) | (unsigned)(pid))
+
+struct ptn_thread
+{
+  unsigned tid;
+  unsigned long reserved[31];
+};
+
+struct ptn_module
+{
+  unsigned long hmte;
+  unsigned long text_start;
+  unsigned long text_size;
+  unsigned long data_start;
+  unsigned long data_size;
+  unsigned long bss_start;
+  unsigned long bss_size;
+  unsigned long flags;
+  unsigned long reserved[24];
+  char name[260];
+};
+
+struct ptn_proc
+{
+  unsigned pid;
+  unsigned long flags;
+  unsigned long fork_addr;
+  unsigned long reserved[29];
+  char name[260];
+};
+
+union ptn_data
+{
+  struct ptn_thread thread;
+  struct ptn_module module;
+  struct ptn_proc proc;
+};
+
+int ptrace (int, int, int, int);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_PTRACE_H */
Index: trunk/src/emx/include/sys/reg.h
===================================================================
--- trunk/src/emx/include/sys/reg.h	(revision 18)
+++ trunk/src/emx/include/sys/reg.h	(revision 18)
@@ -0,0 +1,8 @@
+/* sys/reg.h (emx+gcc) */
+
+#ifndef _SYS_REG_H
+#define _SYS_REG_H
+
+#include <386/reg.h>
+
+#endif /* not _SYS_REG_H */
Index: trunk/src/emx/include/sys/resource.h
===================================================================
--- trunk/src/emx/include/sys/resource.h	(revision 18)
+++ trunk/src/emx/include/sys/resource.h	(revision 18)
@@ -0,0 +1,1 @@
+/* sys/resource.h (emx+gcc) */
Index: trunk/src/emx/include/sys/rmutex.h
===================================================================
--- trunk/src/emx/include/sys/rmutex.h	(revision 18)
+++ trunk/src/emx/include/sys/rmutex.h	(revision 18)
@@ -0,0 +1,75 @@
+/* sys/rmutex.h (emx+gcc) */
+
+/* _rmutex semaphores are registered _fmutex semaphores.  They are a
+   bit bigger than _fmutex metaphores but they are inherited by child
+   processes created with fork().  Shared _rmutex semaphores behave
+   like _fmutex semaphores, ie, they are not registered and therefore
+   not inherited by child processes created with fork().  (As malloc()
+   uses _rmutex semaphores, we have to support shared semaphores
+   anyway.) */
+
+/* This header requires <sys/builtin.h> and <sys/fmutex.h>. */
+
+#ifndef _SYS_RMUTEX_H
+#define _SYS_RMUTEX_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* See also <emx/io.h> and /emx/test/internal.c. */
+typedef struct __rmutex
+{
+  struct __rmutex *next;
+  struct __rmutex *prev;
+  _fmutex fm;
+  unsigned char flags;
+  unsigned short count;
+} _rmutex;
+
+
+static __inline__ unsigned _rmutex_request (_rmutex *sem, unsigned flags)
+{
+  return _fmutex_request (&sem->fm, flags);
+}
+
+
+static __inline__ unsigned _rmutex_release (_rmutex *sem)
+{
+  return _fmutex_release (&sem->fm);
+}
+
+
+static __inline__ int _rmutex_available (_rmutex *sem)
+{
+  return _fmutex_available (&sem->fm);
+}
+
+
+unsigned _rmutex_close (_rmutex *);
+unsigned _rmutex_create (_rmutex *, unsigned);
+unsigned _rmutex_open (_rmutex *);
+void _rmutex_dummy (_rmutex *);
+
+
+static __inline__ void _rmutex_checked_release (_rmutex *sem)
+{
+  _fmutex_checked_release (&sem->fm);
+}
+
+
+static __inline__ void _rmutex_checked_request (_rmutex *sem, unsigned flags)
+{
+  _fmutex_checked_request (&sem->fm, flags);
+}
+
+
+void _rmutex_checked_close (_rmutex *);
+void _rmutex_checked_create (_rmutex *, unsigned);
+void _rmutex_checked_open (_rmutex *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_RMUTEX_H */
Index: trunk/src/emx/include/sys/select.h
===================================================================
--- trunk/src/emx/include/sys/select.h	(revision 18)
+++ trunk/src/emx/include/sys/select.h	(revision 18)
@@ -0,0 +1,45 @@
+/* sys/select.h (emx+gcc) */
+
+#ifndef _SYS_SELECT_H
+#define _SYS_SELECT_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (FD_SETSIZE)
+#define	FD_SETSIZE      256
+#elif FD_SETSIZE < 256
+#error FD_SETSIZE must be at least 256
+#endif
+
+#if !defined (_FD_SET_T)
+#define _FD_SET_T
+
+typedef struct _fd_set
+{
+  unsigned long fds_bits[(FD_SETSIZE+31) / 32];
+} fd_set;
+
+#endif
+
+#define	FD_SET(n,s)    ((s)->fds_bits[(n)/32] |=  (1L << ((n) & 0x1f)))
+#define	FD_CLR(n,s)    ((s)->fds_bits[(n)/32] &= ~(1L << ((n) & 0x1f)))
+#define	FD_ISSET(n,s)  ((s)->fds_bits[(n)/32] &   (1L << ((n) & 0x1f)))
+#define FD_ZERO(s)     (void)memset (s, 0, sizeof (*(s)))
+
+struct timeval;
+
+int select (int, struct _fd_set *, struct _fd_set *, struct _fd_set *,
+    struct timeval *);
+
+int _select (int, struct _fd_set *, struct _fd_set *, struct _fd_set *,
+    struct timeval *);
+
+void *memset (void *, int, size_t); /* Used by FD_ZERO */
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_SELECT_H */
Index: trunk/src/emx/include/sys/signal.h
===================================================================
--- trunk/src/emx/include/sys/signal.h	(revision 18)
+++ trunk/src/emx/include/sys/signal.h	(revision 18)
@@ -0,0 +1,122 @@
+/* sys/signal.h (emx+gcc) */
+
+#ifndef _SYS_SIGNAL_H
+#define _SYS_SIGNAL_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef int sig_atomic_t;
+
+#define SIGHUP    1 /* Hangup */
+#define SIGINT    2 /* Interrupt (Ctrl-C) */
+#define SIGQUIT   3 /* Quit */
+#define SIGILL    4 /* Illegal instruction */
+#define SIGTRAP   5 /* Single step (debugging) */
+#define SIGABRT   6 /* abort () */
+#define SIGEMT    7 /* EMT instruction */
+#define SIGFPE    8 /* Floating point */
+#define SIGKILL   9 /* Kill process */
+#define SIGBUS   10 /* Bus error */
+#define SIGSEGV  11 /* Segmentation fault */
+#define SIGSYS   12 /* Invalid argument to system call */
+#define SIGPIPE  13 /* Broken pipe */
+#define SIGALRM  14 /* Alarm */
+#define SIGTERM  15 /* Termination, process killed */
+#define SIGUSR1  16 /* User-defined signal #1 */
+#define SIGUSR2  17 /* User-defined signal #2 */
+#define SIGCHLD  18 /* Death of a child process */
+#define SIGBREAK 21 /* Break (Ctrl-Break) */
+#define SIGWINCH 28 /* Window size change (not implemented) */
+
+#define SIGPTRACENOTIFY 128     /* Notification from ptrace() */
+
+#define SIGCLD   SIGCHLD
+
+#define SIG_DFL ((void (*)(int))0)
+#define SIG_IGN ((void (*)(int))1)
+#define SIG_ERR ((void (*)(int))-1)
+
+void (*signal (int, void (*)(int)))(int);
+int raise (int);
+
+
+#if !defined (__STRICT_ANSI__)
+
+#define NSIG 29
+
+#define SA_NOCLDSTOP    0x0001
+
+#define SIG_BLOCK       1
+#define SIG_UNBLOCK     2
+#define SIG_SETMASK     3
+
+#if !defined (_SIGSET_T)
+#define _SIGSET_T
+typedef unsigned long sigset_t;
+#endif
+
+struct sigaction
+{
+  void (*sa_handler)(int);
+  sigset_t sa_mask;
+  int sa_flags;
+};
+
+
+int kill (int, int);
+int pause (void);
+
+int sigaction (int, __const__ struct sigaction *, struct sigaction *);
+int sigpending (sigset_t *);
+int sigprocmask (int, __const__ sigset_t *, sigset_t *);
+int sigsuspend (__const__ sigset_t *);
+
+int sigaddset (sigset_t *, int);
+int sigdelset (sigset_t *, int);
+int sigemptyset (sigset_t *);
+int sigfillset (sigset_t *);
+int sigismember (__const__ sigset_t *, int);
+
+#define _SIGMASK(sig) ((sigset_t)1 << ((sig) - 1))
+#define __sigaddset(set,sig)   (*(set) |= _SIGMASK (sig), 0)
+#define __sigdelset(set,sig)   (*(set) &= ~_SIGMASK (sig), 0)
+#define __sigemptyset(set)     (*(set) = 0, 0)
+#define __sigfillset(set)      (*(set) = ~(sigset_t)0, 0)
+#define __sigismember(set,sig) ((*(set) & _SIGMASK (sig)) ? 1 : 0)
+
+int _kill (int, int);
+int _pause (void);
+
+int _sigaction (int, __const__ struct sigaction *, struct sigaction *);
+int _sigpending (sigset_t *);
+int _sigprocmask (int, __const__ sigset_t *, sigset_t *);
+int _sigsuspend (__const__ sigset_t *);
+
+int _sigaddset (sigset_t *, int);
+int _sigdelset (sigset_t *, int);
+int _sigemptyset (sigset_t *);
+int _sigfillset (sigset_t *);
+int _sigismember (__const__ sigset_t *, int);
+
+#endif
+
+
+#if !defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)
+
+#define SIG_ACK ((void (*)(int))4)
+
+#define SA_SYSV         0x0002  /* Reset to SIG_DFL */
+#define SA_ACK          0x0004  /* Don't unblock automatically */
+
+#define SIGTY void
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_SIGNAL_H */
Index: trunk/src/emx/include/sys/smutex.h
===================================================================
--- trunk/src/emx/include/sys/smutex.h	(revision 18)
+++ trunk/src/emx/include/sys/smutex.h	(revision 18)
@@ -0,0 +1,48 @@
+/* sys/smutex.h (emx+gcc) */
+
+/* Simple mutex semaphores.  These semaphores need not be created and
+   destroyed, _smutex objects just have to be initialized to zero.
+   _smutex semaphores are implemented with looping and DosSleep.
+   Therefore, they should be used only if a collision is very
+   unlikely, for instance, during initializing.  In all other cases,
+   _fmutex or HMTX semaphores should be used. */
+
+/* This header requires <sys/builtin.h>. */
+
+#ifndef _SYS_SMUTEX_H
+#define _SYS_SMUTEX_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef signed char _smutex;
+
+
+void __smutex_request_internal (__volatile__ _smutex *);
+
+
+static __inline__ void _smutex_request (__volatile__ _smutex *sem)
+{
+  if (__cxchg (sem, 1) != 0)
+    __smutex_request_internal (sem);
+}
+
+
+static __inline__ void _smutex_release (__volatile__ _smutex *sem)
+{
+  *sem = 0;
+}
+
+
+static __inline__ int _smutex_available (__volatile__ _smutex *sem)
+{
+  return *sem == 0;
+}
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_SMUTEX_H */
Index: trunk/src/emx/include/sys/so_ioctl.h
===================================================================
--- trunk/src/emx/include/sys/so_ioctl.h	(revision 18)
+++ trunk/src/emx/include/sys/so_ioctl.h	(revision 18)
@@ -0,0 +1,104 @@
+/* so_ioctl.h derived from BSD's ioctl.h by hv and em 1994,1996
+ *
+ * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)ioctl.h	7.19 (Berkeley) 6/26/91
+ */
+
+#if !defined (_SYS_SO_IOCTL_H)
+#define _SYS_SO_IOCTL_H
+
+#define _IOC(a,b) ((a<<8)|b)
+#define _IOW(a,b,c) _IOC(a,b)
+#define _IOR(a,b,c) _IOC(a,b)
+#define _IOWR(a,b,c) _IOC(a,b)
+
+#define _TCPIP_FIONREAD  _IOC('f', 127)
+#define FIONBIO         _IOC('f', 126)
+#define FIOASYNC        _IOC('f', 125)
+#define FIOTCPCKSUM     _IOC('f', 128)
+#define FIONSTATUS      _IOC('f', 120)
+#define FIONURG         _IOC('f', 121)
+#define	FIOBSTATUS	_IOC('f', 122)
+
+/* socket i/o controls */
+#define SIOCSHIWAT      _IOW('s',  0, int)	/* set high watermark */
+#define SIOCGHIWAT      _IOR('s',  1, int)	/* get high watermark */
+#define SIOCSLOWAT      _IOW('s',  2, int)	/* set low watermark */
+#define SIOCGLOWAT      _IOR('s',  3, int)	/* get low watermark */
+#define SIOCATMARK      _IOR('s',  7, int)	/* at oob mark? */
+#define SIOCSPGRP       _IOW('s',  8, int)	/* set process group */
+#define SIOCGPGRP       _IOR('s',  9, int)	/* get process group */
+#define	SIOCSHOSTID	_IOW('s', 10, int)	/* set hostid */
+
+/*hv Netbios IOCtls excluded here - no docs about them */
+
+#define SIOCADDRT       _IOW('r', 10, struct ortentry)	/* add route */
+#define SIOCDELRT       _IOW('r', 11, struct ortentry)	/* delete route */
+
+/* hv SIOMETRIC*RT excluded here - no docs about them (routing, nonportable) */
+/* hv SIOCREG* excluded here - no docs about them (routing, nonportable) */
+
+#define SIOCSIFADDR     _IOW('i', 12, struct ifreq)	/* set ifnet address */
+#define SIOCGIFADDR     _IOWR('i',13, struct ifreg)	/* get ifnet addres */
+#define OSIOCGIFADDR	SIOCGIFADDR
+#define SIOCSIFDSTADDR  _IOW('i', 14, struct ifreq)	/* set p-p address */
+#define SIOCGIFDSTADDR  _IOWR('i',15, struct ifreq)	/* get p-p address */
+#define OSIOCGIFDSTADDR	SIOCGIFDSTADDR
+#define SIOCSIFFLAGS    _IOW('i', 16, struct ifreq)	/* set ifnet flags */
+#define SIOCGIFFLAGS    _IOWR('i',17, struct ifreq)	/* get ifnet flags */
+#define SIOCGIFBRDADDR  _IOWR('i',18, struct ifreq)	/* get broadcast addr */
+#define OSIOCGIFBRDADDR	SIOCGIFBRDADDR
+#define SIOCSIFBRDADDR  _IOW('i', 19, struct ifreq)	/* set broadcast addr */
+#define SIOCGIFCONF     _IOWR('i',20, struct ifreq)	/* get ifnet list */
+#define OSIOCGIFCONF	SIOCGIFCONF
+#define SIOCGIFNETMASK  _IOWR('i',21, struct ifreq)	/* get net addr mask */
+#define OSIOCGIFNETMASK	SIOCGIFNETMASK
+#define SIOCSIFNETMASK  _IOW('i', 22, struct ifreq)	/* set net addr mask */
+#define SIOCGIFMETRIC   _IOWR('i',23, struct ifreq)	/* get if metric */
+#define SIOCSIFMETRIC   _IOW('i', 24, struct ifreq)	/* set if metric */
+
+#define SIOCSARP        _IOW('i', 30, struct arpreq)	/* set arp entry */
+#define SIOCGARP        _IOWR('i',31, struct arpreq)	/* get arp entry */
+#define OSIOCGARP	SIOCGARP
+#define SIOCDARP        _IOW('i', 32, struct arpreq)	/* delete arp entry */
+
+/*hv: several SIOC* excluded - no docs, nonportable */
+
+#define	SIOCADDMULTI	_IOW('i', 51, struct ifreq)	/* add m'cast addr */
+#define	SIOCDELMULTI	_IOW('i', 52, struct ifreq)	/* del m'cast addr */
+#define	SIOCMULTISBC	_IOC('i', 61)			/* use broadcast for MC */
+#define	SIOCMULTISFA	_IOC('i', 62)			/* use functional addr for MC */
+
+/* various more ioctls (netstat, slstat, iptrace) excluded, no docs */
+
+#endif /* !defined (_SYS_SO_IOCTL_H) */
Index: trunk/src/emx/include/sys/socket.h
===================================================================
--- trunk/src/emx/include/sys/socket.h	(revision 18)
+++ trunk/src/emx/include/sys/socket.h	(revision 18)
@@ -0,0 +1,319 @@
+/* Modified for emx by hv and em 1994-1997
+ *
+ * Copyright (c) 1982,1985,1986,1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)socket.h	7.13 (Berkeley) 4/20/91
+ *	$Id: socket.h,v 1.5 1993/06/27 05:59:06 andrew Exp $
+ */
+
+#ifndef _SYS_SOCKET_H_
+#define _SYS_SOCKET_H_
+
+#if !defined (_SYS_TYPES_H)
+#warning <sys/socket.h> requires <sys/types.h>
+#include <sys/types.h>
+#endif
+
+#include <sys/uio.h>
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#ifndef _EMX_TCPIP
+#define _EMX_TCPIP
+#endif
+
+/*
+ * Definitions related to sockets: types, address families, options.
+ */
+
+/*
+ * Types
+ */
+#define	SOCK_STREAM	1		/* stream socket */
+#define	SOCK_DGRAM	2		/* datagram socket */
+#define	SOCK_RAW	3		/* raw-protocol interface */
+#define	SOCK_RDM	4		/* reliably-delivered message */
+#define	SOCK_SEQPACKET	5		/* sequenced packet stream */
+
+/*
+ * Option flags per-socket.
+ */
+#define	SO_DEBUG	0x0001		/* turn on debugging info recording */
+#define	SO_ACCEPTCONN	0x0002		/* socket has had listen() */
+#define	SO_REUSEADDR	0x0004		/* allow local address reuse */
+#define	SO_KEEPALIVE	0x0008		/* keep connections alive */
+#define	SO_DONTROUTE	0x0010		/* just use interface addresses */
+#define	SO_BROADCAST	0x0020		/* permit sending of broadcast msgs */
+#define	SO_USELOOPBACK	0x0040		/* bypass hardware when possible */
+#define	SO_LINGER	0x0080		/* linger on close if data present */
+#define	SO_OOBINLINE	0x0100		/* leave received OOB data in line */
+#define	SO_L_BROADCAST	0x0200		/* limited broadcast sent on all IFs*/
+#define	SO_RCV_SHUTDOWN	0x0400		/* set if shut down called for rcv */
+#define	SO_SND_SHUTDOWN	0x0800		/* set if shutdown called for send */
+
+/*
+ * Additional options, not kept in so_options.
+ */
+#define SO_SNDBUF	0x1001		/* send buffer size */
+#define SO_RCVBUF	0x1002		/* receive buffer size */
+#define SO_SNDLOWAT	0x1003		/* send low-water mark */
+#define SO_RCVLOWAT	0x1004		/* receive low-water mark */
+#define SO_SNDTIMEO	0x1005		/* send timeout */
+#define SO_RCVTIMEO	0x1006		/* receive timeout */
+#define	SO_ERROR	0x1007		/* get error status and clear */
+#define	SO_TYPE		0x1008		/* get socket type */
+#define	SO_OPTIONS	0x1010		/* get socket options */
+
+/*
+ * Structure used for manipulating linger option.
+ */
+struct	linger {
+#ifdef __RSXNT__
+	short	l_onoff;		/* option on/off */
+	short	l_linger;		/* linger time */
+#else
+	int	l_onoff;		/* option on/off */
+	int	l_linger;		/* linger time */
+#endif
+};
+
+/*
+ * Level number for (get/set)sockopt() to apply to socket itself.
+ */
+#define	SOL_SOCKET	0xffff		/* options for socket level */
+
+/*
+ * Address families.
+ */
+#define	AF_UNSPEC	0		/* unspecified */
+#define	AF_UNIX		1		/* local to host (pipes, portals) */
+#define	AF_INET		2		/* internetwork: UDP, TCP, etc. */
+#define	AF_IMPLINK	3		/* arpanet imp addresses */
+#define	AF_PUP		4		/* pup protocols: e.g. BSP */
+#define	AF_CHAOS	5		/* mit CHAOS protocols */
+#define	AF_NS		6		/* XEROX NS protocols */
+#define	AF_NBS		7		/* IBM: nbs protocols */
+					/* (hv: I think IBM is outdated here */
+#define	AF_ISO		7		/* ISO protocols */
+#define	AF_OSI		AF_ISO
+#define	AF_ECMA		8		/* european computer manufacturers */
+#define	AF_DATAKIT	9		/* datakit protocols */
+#define	AF_CCITT	10		/* CCITT protocols, X.25 etc */
+#define	AF_SNA		11		/* IBM SNA */
+#define AF_DECnet	12		/* DECnet */
+#define AF_DLI		13		/* DEC Direct data link interface */
+#define AF_LAT		14		/* LAT */
+#define	AF_HYLINK	15		/* NSC Hyperchannel */
+#define	AF_APPLETALK	16		/* Apple Talk */
+#define	AF_NB		17		/* Netbios */
+#define	AF_NETBIOS	AF_NB
+
+#define	AF_OS2		AF_UNIX
+
+#define	AF_MAX		18
+
+/*
+ * Structure used by kernel to store most
+ * addresses.
+ * is called struct osockaddr in 4.4BSD
+ */
+struct sockaddr {
+	u_short	sa_family;		/* address family */
+	char	sa_data[14];		/* up to 14 bytes of direct address */
+};
+
+/*
+ * Structure used by kernel to pass protocol
+ * information in raw sockets.
+ */
+struct sockproto {
+	u_short	sp_family;		/* address family */
+	u_short	sp_protocol;		/* protocol */
+};
+
+/*
+ * Protocol families, same as address families for now.
+ */
+#define	PF_UNSPEC	AF_UNSPEC
+#define	PF_UNIX		AF_UNIX
+#define	PF_INET		AF_INET
+#define	PF_IMPLINK	AF_IMPLINK
+#define	PF_PUP		AF_PUP
+#define	PF_CHAOS	AF_CHAOS
+#define	PF_NS		AF_NS
+#define	PF_NBS		AF_NBS
+#define	PF_ISO		AF_ISO
+#define	PF_OSI		AF_ISO
+#define	PF_ECMA		AF_ECMA
+#define	PF_DATAKIT	AF_DATAKIT
+#define	PF_CCITT	AF_CCITT
+#define	PF_SNA		AF_SNA
+#define PF_DECnet	AF_DECnet
+#define PF_DLI		AF_DLI
+#define PF_LAT		AF_LAT
+#define	PF_HYLINK	AF_HYLINK
+#define	PF_APPLETALK	AF_APPLETALK
+#define	PF_NB		AF_NB
+#define	PF_NETBIOS	AF_NB
+#define	PF_OS2		AF_UNIX
+#define	PF_MAX		AF_MAX
+
+/*
+ * Maximum queue length specifiable by listen.
+ */
+#define	SOMAXCONN	5
+
+/*
+ * 4.3-compat message header (move to compat file later).
+ * is called omsghdr in 4.4BSD
+ */
+struct msghdr {
+	caddr_t	msg_name;		/* optional address */
+	int	msg_namelen;		/* size of address */
+	struct	iovec *msg_iov;		/* scatter/gather array */
+	int	msg_iovlen;		/* # elements in msg_iov */
+	caddr_t	msg_accrights;		/* access rights sent/received */
+	int	msg_accrightslen;
+};
+
+#define	MSG_OOB		0x1		/* process out-of-band data */
+#define	MSG_PEEK	0x2		/* peek at incoming message */
+#define	MSG_DONTROUTE	0x4		/* send without using routing tables */
+#define	MSG_EOR		0x8		/* data completes record */
+#define	MSG_TRUNC	0x10		/* data discarded before delivery */
+#define	MSG_CTRUNC	0x20		/* control data lost before delivery */
+#define	MSG_WAITALL	0x40		/* wait for full request or error */
+
+#define	MSG_MAXIOVLEN	16
+
+/*
+ * Header for ancillary data objects in msg_control buffer.
+ * Used for additional information with/about a datagram
+ * not expressible by flags.  The format is a sequence
+ * of message elements headed by cmsghdr structures.
+ */
+struct cmsghdr {
+	u_int	cmsg_len;		/* data byte count, including hdr */
+	int	cmsg_level;		/* originating protocol */
+	int	cmsg_type;		/* protocol-specific type */
+/* followed by	u_char  cmsg_data[]; */
+};
+
+/* given pointer to struct adatahdr, return pointer to data */
+#define	CMSG_DATA(cmsg)		((u_char *)((cmsg) + 1))
+
+/* given pointer to struct adatahdr, return pointer to next adatahdr */
+#define	CMSG_NXTHDR(mhdr, cmsg)	\
+	(((caddr_t)(cmsg) + (cmsg)->cmsg_len + sizeof(struct cmsghdr) > \
+	    (mhdr)->msg_control + (mhdr)->msg_controllen) ? \
+	    (struct cmsghdr *)NULL : \
+	    (struct cmsghdr *)((caddr_t)(cmsg) + ALIGN((cmsg)->cmsg_len)))
+
+#define	CMSG_FIRSTHDR(mhdr)	((struct cmsghdr *)(mhdr)->msg_control)
+
+/* "Socket"-level control message types: */
+#define	SCM_RIGHTS	0x01		/* access rights (array of int) */
+
+extern	int	accept (int, struct sockaddr *, int *);
+extern	int	bind (int, __const__ struct sockaddr *, int);
+extern	int	connect (int, __const__ struct sockaddr *, int);
+extern	int	gethostid (void);
+extern	int	getpeername (int, struct sockaddr *, int *);
+extern	int	getsockname (int, struct sockaddr *, int *);
+extern	int	getsockopt (int, int, int, void *, int *);
+extern	int	listen (int, int);
+extern	int	recv (int, void *, int, int);
+extern	int	recvfrom (int, void *, int, int, struct sockaddr *, int *);
+extern	int	recvmsg (int, struct msghdr *, int);
+extern	int	send (int, __const__ void *, int, int);
+extern	int	sendto (int, __const__ void *, int, int, __const__ struct sockaddr *, int);
+extern	int	sendmsg (int, __const__ struct msghdr *, int);
+extern	int	setsockopt (int, int, int, __const__ void *, int);
+extern	int	shutdown (int, int);
+extern	int	socket (int, int, int);
+extern	int	socketpair (int, int, int, int *);
+
+extern	int	_impsockhandle (int, int);
+
+/* special IBM prototypes 
+ * hv: warning: usage of these routines may interfere with EMX operation
+ * usage is not recommended.
+ */
+extern	void	psock_errno(__const__ char*);
+extern	int	soabort(int);
+extern	int	soclose(int);
+extern	int	sock_init(void);
+extern	int	sock_errno(void);
+extern	int	so_cancel(int);
+extern	int	getinetversion(char*);
+
+/* hv: these are new TCPIPV4 data structures. Consult IBM doc on that */
+#ifdef TCPIPV4
+#define	MT_FREE		0
+#define	MT_DATA		1
+#define	MT_HEADER	2
+#define	MT_SOCKET	3
+#define	MT_PCB		4
+#define	MT_RTABLE	5
+#define	MT_HTABLE	6
+#define	MT_ATABLE	7
+#define	MT_SONAME	8
+#define	MT_ZOMBIE	9
+#define	MT_SOOPTS	10
+#define	MT_FTABLE	11
+#define	MT_RIGHTS	12
+#define	MT_IFADDR	13
+
+struct mbstat {
+	u_short		m_mbufs;
+	u_short		m_clusters;
+	u_short		m_clfree;
+	u_short		m_drops;
+	u_long		m_wait;
+	u_short		m_mtypes[256];
+};
+
+#define MAXSOCKETS	2048
+
+struct sostats {
+	short count;
+	short socketdata[9*MAXSOCKETS];
+};
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_SYS_SOCKET_H_ */
Index: trunk/src/emx/include/sys/sockio.h
===================================================================
--- trunk/src/emx/include/sys/sockio.h	(revision 18)
+++ trunk/src/emx/include/sys/sockio.h	(revision 18)
@@ -0,0 +1,12 @@
+/* Copyright (c)1996 by Holger Veit
+ * May be freely used with EMX 
+ */
+
+/* BSD uses this to declare some more ioctls */
+
+#ifndef _SYS_SOCKIO_H_
+#define _SYS_SOCKIO_H_
+
+#include <sys/so_ioctl.h>
+
+#endif /* !_SYS_SOCKIO_H_ */
Index: trunk/src/emx/include/sys/stat.h
===================================================================
--- trunk/src/emx/include/sys/stat.h	(revision 18)
+++ trunk/src/emx/include/sys/stat.h	(revision 18)
@@ -0,0 +1,104 @@
+/* sys/stat.h (emx+gcc) */
+
+#ifndef _SYS_STAT_H
+#define _SYS_STAT_H
+
+#if !defined (_SYS_TYPES_H)
+#warning <sys/stat.h> requires <sys/types.h>
+#include <sys/types.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_STAT)
+#define _STAT
+struct stat
+{
+  dev_t   st_dev;
+  ino_t   st_ino;
+  mode_t  st_mode;
+  nlink_t st_nlink;
+  uid_t   st_uid;
+  gid_t   st_gid;
+  dev_t   st_rdev;
+  off_t   st_size;
+  time_t  st_atime;
+  time_t  st_mtime;
+  time_t  st_ctime;
+  long    st_attr;
+  long    st_reserved;
+};
+#endif
+
+#if !defined (S_IRUSR)
+#define S_IRWXU 00700
+#define S_IRUSR 00400
+#define S_IWUSR 00200
+#define S_IXUSR 00100
+
+#define S_IRWXG 00070
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+
+#define S_IRWXO 00007
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+
+#define	S_ISGID 02000
+#define	S_ISUID 04000
+#endif
+
+#if !defined (S_IFMT)
+#define S_IFMT   0170000  /* Mask for file type */
+#define S_IFIFO  0010000  /* Pipe */
+#define S_IFCHR  0020000  /* Character device */
+#define S_IFDIR  0040000  /* Directory */
+#define S_IFREG  0100000  /* Regular file */
+#define S_IFSOCK 0140000  /* Socket */
+
+/* S_ISBLK */
+#define S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
+#define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
+#define S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
+#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#endif
+
+int chmod (__const__ char *, int);
+int fstat (int, struct stat *);
+int mkdir (__const__ char *, long);
+/* mkfifo() */
+int stat (__const__ char *, struct stat *);
+int umask (int);
+
+
+#if !defined (_POSIX_SOURCE)
+
+#if !defined (S_IREAD)
+#define S_IREAD  0400     /* Owner: read */
+#define S_IWRITE 0200     /* Owner: write */
+#define S_IEXEC  0100     /* Owner: exec */
+#endif
+
+#endif
+
+#if !defined (_POSIX_SOURCE) || defined (_WITH_UNDERSCORE)
+
+int _chmod (__const__ char *, int);
+int _fstat (int, struct stat *);
+int _mkdir (__const__ char *, long);
+/* _mkfifo() */
+int _stat (__const__ char *, struct stat *);
+int _umask (int);
+
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not SYS_STAT_H */
Index: trunk/src/emx/include/sys/statfs.h
===================================================================
--- trunk/src/emx/include/sys/statfs.h	(revision 18)
+++ trunk/src/emx/include/sys/statfs.h	(revision 18)
@@ -0,0 +1,22 @@
+/* sys/statfs.h (emx+gcc) */
+
+#ifndef _SYS_STATFS_H
+#define _SYS_STATFS_H
+
+#if !defined (_STATFS)
+#define _STATFS
+struct statfs
+{
+  short f_fstyp;
+  long f_bsize;
+  long f_frsize;
+  long f_blocks;
+  long f_bfree;
+  long f_files;
+  long f_ffree;
+  char f_fname[6];
+  char f_fpack[6];
+};
+#endif
+
+#endif /* not SYS_STATFS_H */
Index: trunk/src/emx/include/sys/termio.h
===================================================================
--- trunk/src/emx/include/sys/termio.h	(revision 18)
+++ trunk/src/emx/include/sys/termio.h	(revision 18)
@@ -0,0 +1,156 @@
+/* sys/termio.h (emx+gcc) */
+
+#ifndef _SYS_TERMIO_H
+#define _SYS_TERMIO_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* Request codes */
+
+#if !defined (TCGETA)
+#define TCGETA      1
+#define TCSETA      2
+#define TCSETAW     3
+#define TCSETAF     4
+#define TCFLSH      5
+#define TCSBRK      6
+#define TCXONC      7
+#endif
+
+/* c_cc indexes */
+
+#if !defined (VINTR)            /* Symbols common to termio.h and termios.h */
+#define VINTR       0
+#define VQUIT       1
+#define VERASE      2
+#define VKILL       3
+#define VEOF        4
+#define VEOL        5
+#define VMIN        6
+#define VTIME       7
+#endif
+
+#define NCC         8           /* Number of the above */
+
+/* c_iflag, emx ignores most of the following bits */
+
+#if !defined (IGNBRK)           /* Symbols common to termio.h and termios.h */
+#define IGNBRK      0x0001
+#define BRKINT      0x0002
+#define IGNPAR      0x0004
+#define PARMRK      0x0008
+#define INPCK       0x0010
+#define ISTRIP      0x0020
+#define INLCR       0x0040
+#define IGNCR       0x0080
+#define ICRNL       0x0100
+#define IUCLC       0x0200
+#define IXON        0x0400
+#define IXANY       0x0800
+#define IXOFF       0x1000
+#define IDELETE     0x8000      /* Extension (emx) */
+#endif
+
+/* c_oflag, emx ignores all of the following bits */
+
+#if !defined (OPOST)            /* Symbols common to termio.h and termios.h */
+#define OPOST       0x0001
+#endif
+#define OLCUC       0x0002
+#define ONLCR       0x0004
+#define OCRNL       0x0008
+#define ONOCR       0x0010
+#define ONLRET      0x0020
+#define OFILL       0x0040
+#define OFDEL       0x0080
+#define NLDLY       0x0100      /* Mask */
+#define NL0         0x0000
+#define NL1         0x0100
+#define CRDLY       0x0600      /* Mask */
+#define CR0         0x0000
+#define CR1         0x0200
+#define CR2         0x0400
+#define CR3         0x0600
+#define TABDLY      0x1800      /* Mask */
+#define TAB0        0x0000
+#define TAB1        0x0800
+#define TAB2        0x1000
+#define TAB3        0x1800
+#define BSDLY       0x2000      /* Mask */
+#define BS0         0x0000
+#define BS1         0x2000
+#define VTDLY       0x4000      /* Mask */
+#define VT0         0x0000
+#define VT1         0x4000
+#define FFDLY       0x8000      /* Mask */
+#define FF0         0x0000
+#define FF1         0x8000
+
+/* c_cflag, emx ignores all of the following bits */
+
+#if !defined (CBAUD)
+#define CBAUD       0x000f      /* Mask */
+#endif
+#if !defined (B0)               /* Symbols common to termio.h and termios.h */
+#define B0          0x0000
+#define B50         0x0001
+#define B75         0x0002
+#define B110        0x0003
+#define B134        0x0004
+#define B150        0x0005
+#define B200        0x0006
+#define B300        0x0007
+#define B600        0x0008
+#define B1200       0x0009
+#define B1800       0x000a
+#define B2400       0x000b
+#define B4800       0x000c
+#define B9600       0x000d
+#define B19200      0x000e
+#define B38400      0x000f
+#define CSIZE       0x0030      /* Mask */
+#define CS5         0x0000
+#define CS6         0x0010
+#define CS7         0x0020
+#define CS8         0x0030
+#define CSTOPB      0x0040
+#define CREAD       0x0080
+#define PARENB      0x0100
+#define PARODD      0x0200
+#define HUPCL       0x0400
+#define CLOCAL      0x0800
+#define LOBLK       0x1000
+#endif
+
+/* c_lflag, emx ignores some of the following bits */
+
+#if !defined (ISIG)             /* Symbols common to termio.h and termios.h */
+#define ISIG        0x0001
+#define ICANON      0x0002
+#define XCASE       0x0004
+#define ECHO        0x0008
+#define ECHOE       0x0010
+#define ECHOK       0x0020
+#define ECHONL      0x0040
+#define NOFLSH      0x0080
+#define IDEFAULT    0x8000      /* Extension (emx) */
+#endif
+
+
+struct termio
+{
+  unsigned int  c_iflag;
+  unsigned int  c_oflag;
+  unsigned int  c_cflag;
+  unsigned int  c_lflag;
+  unsigned int  c_line;
+  unsigned char c_cc[NCC];
+};
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_TERMIO_H */
Index: trunk/src/emx/include/sys/time.h
===================================================================
--- trunk/src/emx/include/sys/time.h	(revision 18)
+++ trunk/src/emx/include/sys/time.h	(revision 18)
@@ -0,0 +1,43 @@
+/* sys/time.h (emx+gcc) */
+
+#ifndef _SYS_TIME_H
+#define _SYS_TIME_H
+
+#include <time.h>
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_TIMEVAL)
+#define _TIMEVAL
+struct timeval
+{
+  long tv_sec;
+  long tv_usec;
+};
+#endif
+
+#if !defined (_TIMEZONE)
+#define _TIMEZONE
+struct timezone
+{
+  int tz_minuteswest;
+  int tz_dsttime;
+};
+#endif
+
+int utimes (__const__ char *, __const__ struct timeval *);
+int gettimeofday (struct timeval *, struct timezone *);
+int settimeofday (__const__ struct timeval *, __const__ struct timezone *);
+
+
+int _utimes (__const__ char *, __const__ struct timeval *);
+int _gettimeofday (struct timeval *, struct timezone *);
+int _settimeofday (__const__ struct timeval *, __const__ struct timezone *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_TIME_H */
Index: trunk/src/emx/include/sys/timeb.h
===================================================================
--- trunk/src/emx/include/sys/timeb.h	(revision 18)
+++ trunk/src/emx/include/sys/timeb.h	(revision 18)
@@ -0,0 +1,31 @@
+/* sys/timeb.h (emx+gcc) */
+
+#ifndef _SYS_TIMEB_H
+#define _SYS_TIMEB_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_TIME_T)
+#define _TIME_T
+typedef unsigned long time_t;
+#endif
+
+struct timeb
+{
+  time_t   time;
+  unsigned millitm;
+  int      timezone;
+  int      dstflag;
+};
+
+void ftime (struct timeb *);
+
+void _ftime (struct timeb *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_TIMEB_H */
Index: trunk/src/emx/include/sys/times.h
===================================================================
--- trunk/src/emx/include/sys/times.h	(revision 18)
+++ trunk/src/emx/include/sys/times.h	(revision 18)
@@ -0,0 +1,29 @@
+/* sys/times.h (emx+gcc) */
+
+#ifndef _SYS_TIMES_H
+#define _SYS_TIMES_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_CLOCK_T)
+#define _CLOCK_T
+typedef long clock_t;
+#endif
+
+struct tms
+{
+  clock_t tms_utime;
+  clock_t tms_stime;
+  clock_t tms_cutime;
+  clock_t tms_cstime;
+};
+
+long times (struct tms *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_TIMES_H */
Index: trunk/src/emx/include/sys/types.h
===================================================================
--- trunk/src/emx/include/sys/types.h	(revision 18)
+++ trunk/src/emx/include/sys/types.h	(revision 18)
@@ -0,0 +1,96 @@
+/* sys/types.h (emx+gcc) */
+
+#ifndef _SYS_TYPES_H
+#define _SYS_TYPES_H
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (_SSIZE_T)
+#define _SSIZE_T
+typedef int ssize_t;
+#endif
+
+#if !defined (_TIME_T)
+#define _TIME_T
+typedef unsigned long time_t;
+#endif
+
+#if !defined (_INO_T)
+#define _INO_T
+typedef int ino_t;
+#endif
+
+#if !defined (_DEV_T)
+#define _DEV_T
+typedef int dev_t;
+#endif
+
+#if !defined (_OFF_T)
+#define _OFF_T
+typedef long off_t;
+#endif
+
+#if !defined (_MODE_T)
+#define _MODE_T
+typedef int mode_t;
+#endif
+
+#if !defined (_NLINK_T)
+#define _NLINK_T
+typedef int nlink_t;
+#endif
+
+#if !defined (_UID_T)
+#define _UID_T
+typedef int uid_t;
+#endif
+
+#if !defined (_PID_T)
+#define _PID_T
+typedef int pid_t;
+#endif
+
+#if !defined (_GID_T)
+#define _GID_T
+typedef int gid_t;
+#endif
+
+#if !defined (_POSIX_SOURCE)
+
+#if !defined (FD_SETSIZE)
+#define	FD_SETSIZE      256
+#elif FD_SETSIZE < 256
+#error FD_SETSIZE must be at least 256
+#endif
+
+#if !defined (_FD_SET_T)
+#define _FD_SET_T
+
+typedef struct _fd_set
+{
+  unsigned long fds_bits[(FD_SETSIZE+31) / 32];
+} fd_set;
+
+#endif
+
+#define	FD_SET(n,s)    ((s)->fds_bits[(n)/32] |=  (1L << ((n) & 0x1f)))
+#define	FD_CLR(n,s)    ((s)->fds_bits[(n)/32] &= ~(1L << ((n) & 0x1f)))
+#define	FD_ISSET(n,s)  ((s)->fds_bits[(n)/32] &   (1L << ((n) & 0x1f)))
+#define FD_ZERO(s)     (void)memset (s, 0, sizeof (*(s)))
+
+#endif
+
+#if !defined (_POSIX_SOURCE)
+
+typedef	unsigned char u_char;
+typedef	unsigned short u_short;
+typedef	unsigned u_int;
+typedef	unsigned long u_long;
+typedef char *caddr_t;
+
+#endif
+
+#endif /* not _SYS_TYPES_H */
Index: trunk/src/emx/include/sys/uflags.h
===================================================================
--- trunk/src/emx/include/sys/uflags.h	(revision 18)
+++ trunk/src/emx/include/sys/uflags.h	(revision 18)
@@ -0,0 +1,35 @@
+/* sys/uflags.h (emx+gcc) */
+
+#ifndef _SYS_UFLAGS_H
+#define _SYS_UFLAGS_H
+
+/* Constants for _uflags() */
+
+#define _UF_SIG_MODEL           0x0003  /* Mask */
+#define _UF_SIG_EMX             0x0000
+#define _UF_SIG_SYSV            0x0001
+#define _UF_SIG_BSD             0x0002
+#define _UF_SIG_RESERVED        0x0003
+
+#define _UF_SBRK_MODEL          0x000c  /* Mask */
+#define _UF_SBRK_CONTIGUOUS     0x0000
+#define _UF_SBRK_MONOTONOUS     0x0004
+#define _UF_SBRK_ARBITRARY      0x0008
+#define _UF_SBRK_RESERVED1      0x000c
+
+#define _UF_PTRACE_MODEL        0x0030  /* Mask */
+#define _UF_PTRACE_STANDARD     0x0000
+#define _UF_PTRACE_NOTIFY       0x0010
+#define _UF_PTRACE_MULTITHREAD  0x0020
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+int _uflags (int, int);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_UFLAGS_H */
Index: trunk/src/emx/include/sys/uio.h
===================================================================
--- trunk/src/emx/include/sys/uio.h	(revision 18)
+++ trunk/src/emx/include/sys/uio.h	(revision 18)
@@ -0,0 +1,40 @@
+/* sys/uio.h (emx+gcc) */
+
+#ifndef _SYS_UIO_H
+#define _SYS_UIO_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+struct iovec
+{
+  caddr_t iov_base;
+  int     iov_len;
+};
+
+/* needed for sys\socket.h TCPIPV4 now */
+#ifdef TCPIPV4
+struct uio {
+	struct iovec	*uio_iov;
+	int		uio_iovcnt;
+	off_t		uio_offset;
+	int		uio_segflg;
+	unsigned int	uio_resid;
+};
+enum	uio_rw { UIO_READ, UIO_WRITE };
+#define FREAD   1
+#define FWRITE  2
+#endif
+
+int readv (int, __const__ struct iovec *, int);
+int writev (int, __const__ struct iovec *, int);
+
+int _readv (int, __const__ struct iovec *, int);
+int _writev (int, __const__ struct iovec *, int);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_UIO_H */
Index: trunk/src/emx/include/sys/ulimit.h
===================================================================
--- trunk/src/emx/include/sys/ulimit.h	(revision 18)
+++ trunk/src/emx/include/sys/ulimit.h	(revision 18)
@@ -0,0 +1,12 @@
+/* sys/ulimit.h (emx+gcc) */
+
+#ifndef _SYS_ULIMIT_H
+#define _SYS_ULIMIT_H
+
+#define UL_GFILLIM      1
+#define UL_SFILLIM      2
+#define UL_GMEMLIM      3
+#define UL_NOFILES      4
+#define UL_OBJREST      81
+
+#endif /* not _SYS_ULIMIT_H */
Index: trunk/src/emx/include/sys/un.h
===================================================================
--- trunk/src/emx/include/sys/un.h	(revision 18)
+++ trunk/src/emx/include/sys/un.h	(revision 18)
@@ -0,0 +1,13 @@
+/* Copyright (c)1996 by Holger Veit
+ * May be freely used with EMX 
+ */
+
+#ifndef _SYS_UN_H_
+#define _SYS_UN_H_
+
+struct  sockaddr_un {
+	u_short	sun_family;	/* socket family: AF_UNIX */
+	char	sun_path[108];	/* path name (not used) */
+};
+
+#endif /* !_SYS_UN_H_ */
Index: trunk/src/emx/include/sys/user.h
===================================================================
--- trunk/src/emx/include/sys/user.h	(revision 18)
+++ trunk/src/emx/include/sys/user.h	(revision 18)
@@ -0,0 +1,53 @@
+/* user.h (emx+gcc) */
+
+#ifndef _SYS_USER_H
+#define _SYS_USER_H
+
+#define UMAGIC 0x10f
+
+struct fpstate
+{
+  unsigned long state[27];
+  unsigned long status;
+};
+
+struct user
+{
+  unsigned short u_magic;
+  unsigned short u_reserved1;
+  unsigned long  u_data_base;
+  unsigned long  u_data_end;
+  unsigned long  u_data_off;
+  unsigned long  u_heap_base;
+  unsigned long  u_heap_end;
+  unsigned long  u_heap_off;
+  unsigned long  u_heap_brk;
+  unsigned long  u_stack_base;
+  unsigned long  u_stack_end;
+  unsigned long  u_stack_off;
+  unsigned long  u_stack_low;
+  int *          u_ar0;
+  char           u_fpvalid;
+  char           u_reserved2[3];
+  struct fpstate u_fpstate;
+  char           u_module[8];
+  unsigned long  u_heapobjs_off;
+  unsigned long  u_reserved3[20];
+  unsigned long  u_regs[19];
+};
+
+struct _user_heapobj
+{
+  unsigned long  u_base;
+  unsigned long  u_end;
+  unsigned long  u_off;
+  unsigned long  u_brk;
+};
+
+struct _user_heapobjs
+{
+  unsigned long u_count;
+  struct _user_heapobj u_objs[255];
+};
+
+#endif /* not _SYS_USER_H */
Index: trunk/src/emx/include/sys/utime.h
===================================================================
--- trunk/src/emx/include/sys/utime.h	(revision 18)
+++ trunk/src/emx/include/sys/utime.h	(revision 18)
@@ -0,0 +1,32 @@
+/* sys/utime.h (emx+gcc) */
+
+#ifndef _SYS_UTIME_H
+#define _SYS_UTIME_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_TIME_T)
+#define _TIME_T
+typedef unsigned long time_t;
+#endif
+
+#if !defined (_UTIMBUF)
+#define _UTIMBUF
+struct utimbuf
+{
+  time_t actime;
+  time_t modtime;
+};
+#endif
+
+int utime (__const__ char *, __const__ struct utimbuf *);
+
+int _utime (__const__ char *, __const__ struct utimbuf *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_UTIME_H */
Index: trunk/src/emx/include/sys/utsname.h
===================================================================
--- trunk/src/emx/include/sys/utsname.h	(revision 18)
+++ trunk/src/emx/include/sys/utsname.h	(revision 18)
@@ -0,0 +1,27 @@
+/* sys/utsname.h (emx+gcc) */
+
+#ifndef _SYS_UTSNAME_H
+#define _SYS_UTSNAME_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define _UN_LEN         16
+
+struct utsname
+{
+  char sysname[_UN_LEN];
+  char nodename[_UN_LEN];
+  char release[_UN_LEN];
+  char version[_UN_LEN];
+  char machine[_UN_LEN];
+};
+
+int uname (struct utsname *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not SYS_UTSNAME_H */
Index: trunk/src/emx/include/sys/video.h
===================================================================
--- trunk/src/emx/include/sys/video.h	(revision 18)
+++ trunk/src/emx/include/sys/video.h	(revision 18)
@@ -0,0 +1,122 @@
+/* sys/video.h (emx+gcc) */
+
+#ifndef _SYS_VIDEO_H
+#define _SYS_VIDEO_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (__GNUC__)
+#if !defined (__const__)
+#define __const__ const
+#endif
+#endif
+
+#if !defined (B_BLACK)
+
+/* Background colors */
+
+#define B_BLACK      0x00
+#define B_BLUE       0x10
+#define B_GREEN      0x20
+#define B_CYAN       0x30
+#define B_RED        0x40
+#define B_MAGENTA    0x50
+#define B_YELLOW     0x60
+#define B_BROWN      0x60
+#define B_WHITE      0x70
+
+/* Foreground colors */
+
+#define F_BLACK      0x00
+#define F_BLUE       0x01
+#define F_GREEN      0x02
+#define F_CYAN       0x03
+#define F_RED        0x04
+#define F_MAGENTA    0x05
+#define F_YELLOW     0x06
+#define F_BROWN      0x06
+#define F_WHITE      0x07
+
+/* Other attributes */
+
+#define INTENSITY    0x08
+#define BLINK        0x80
+
+/* black and white attributes */
+
+#define BW_BLANK     0x00
+#define BW_UNDERLINE 0x01
+#define BW_NORMAL    0x07
+#define BW_REVERSE   0x70
+
+#endif
+
+/* v_hardware() return values */
+
+#define V_COLOR_8    1
+#define V_COLOR_12   2
+#define V_MONOCHROME 3
+
+/* v_scroll() */
+
+#define V_SCROLL_UP    0
+#define V_SCROLL_DOWN  1
+#define V_SCROLL_LEFT  2
+#define V_SCROLL_RIGHT 3
+#define V_SCROLL_CLEAR 4
+
+struct _FILE;
+
+void v_attrib (int a);
+void v_backsp (int count);
+void v_clear (void);
+void v_clreol (void);
+void v_ctype (int start, int end);
+void v_delline (int count);
+void v_dimen (int *width, int *height);
+int v_fclose (struct _FILE *stream);
+struct _FILE *v_fopen (void);
+int v_getattr (void);
+void v_getctype (int *start, int *end);
+void v_getline (char *dst, int x, int y, int count);
+void v_getxy (int *x, int *y);
+void v_gotoxy (int x, int y);
+int v_hardware (void);
+void v_hidecursor (void);
+int v_init (void);
+void v_insline (int count);
+void v_putc (char c);
+void v_putline (__const__ char *src, int x, int y, int count);
+void v_putm (__const__ char *str, int len);
+void v_putmask (__const__ char *src, __const__ char *mask, int x, int y,
+    int count);
+void v_putn (char c, int count);
+void v_puts (__const__ char *str);
+void v_scroll (int tl_x, int tl_y, int br_x, int br_y, int count, int flag);
+void v_scrollup (void);
+
+#if defined (__EMX__)
+
+#if !defined (_VA_LIST)
+#define _VA_LIST
+typedef char *va_list;
+#endif
+
+#if defined (__GNUC__)
+int v_printf (__const__ char *fmt, ...)
+        __attribute__ ((__format__ (__printf__, 1, 2)));
+int v_vprintf (__const__ char *fmt, va_list arg_ptr)
+        __attribute__ ((__format__ (__printf__, 1, 0)));
+#else
+int v_printf (__const__ char *fmt, ...);
+int v_vprintf (__const__ char *fmt, va_list arg_ptr);
+#endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_VIDEO_H */
Index: trunk/src/emx/include/sys/wait.h
===================================================================
--- trunk/src/emx/include/sys/wait.h	(revision 18)
+++ trunk/src/emx/include/sys/wait.h	(revision 18)
@@ -0,0 +1,35 @@
+/* sys/wait.h (emx+gcc) */
+
+#ifndef _SYS_WAIT_H
+#define _SYS_WAIT_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define WNOHANG         1
+#define WUNTRACED       2
+
+#define WIFEXITED(st)   (((st) & 0x7f) == 0)
+#define WIFSIGNALED(st) (((st) & 0x7f) != 0x7f && ((st) & 0x7f) != 0)
+#define WIFSTOPPED(st)  (((st) & 0x7f) == 0x7f)
+
+#define WEXITSTATUS(st) ((st) >> 8)
+#define WTERMSIG(st)    ((st) & 0x7f)
+#define WSTOPSIG(st)    ((st) >> 8)
+
+int wait (int *);
+int waitpid (int, int *, int);
+
+#if !defined (_POSIX_SOURCE) || defined (_WITH_UNDERSCORE)
+
+int _wait (int *);
+int _waitpid (int, int *, int);
+
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not SYS_WAIT_H */
Index: trunk/src/emx/include/sys/winmgr.h
===================================================================
--- trunk/src/emx/include/sys/winmgr.h	(revision 18)
+++ trunk/src/emx/include/sys/winmgr.h	(revision 18)
@@ -0,0 +1,137 @@
+/* sys/winmgr.h (emx+gcc) */
+
+#ifndef _SYS_WINMGR_H
+#define _SYS_WINMGR_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (__GNUC__)
+#if !defined (__const__)
+#define __const__ const
+#endif
+#endif
+
+#if !defined (B_BLACK)
+
+/* Background colors */
+
+#define B_BLACK      0x00
+#define B_BLUE       0x10
+#define B_GREEN      0x20
+#define B_CYAN       0x30
+#define B_RED        0x40
+#define B_MAGENTA    0x50
+#define B_YELLOW     0x60
+#define B_BROWN      0x60
+#define B_WHITE      0x70
+
+/* Foreground colors */
+
+#define F_BLACK      0x00
+#define F_BLUE       0x01
+#define F_GREEN      0x02
+#define F_CYAN       0x03
+#define F_RED        0x04
+#define F_MAGENTA    0x05
+#define F_YELLOW     0x06
+#define F_BROWN      0x06
+#define F_WHITE      0x07
+
+/* Other attributes */
+
+#define INTENSITY    0x08
+#define BLINK        0x80
+
+/* black and white attributes */
+
+#define BW_BLANK     0x00
+#define BW_UNDERLINE 0x01
+#define BW_NORMAL    0x07
+#define BW_REVERSE   0x70
+
+#endif
+
+struct _FILE;
+
+typedef struct _wm_window *wm_handle;
+
+void wm_attrib (wm_handle wh, int a);
+void wm_attrib_all (wm_handle wh, int a);
+void wm_backsp (wm_handle wh, int count);
+void wm_border (wm_handle wh, int bflag, int battr, __const__ char *title,
+    int tflag, int tattr);
+void wm_bottom (wm_handle wh);
+void wm_chide (int flag);
+void wm_clear (wm_handle wh);
+void wm_close (wm_handle wh);
+void wm_close_all (void);
+void wm_clr_eol (wm_handle wh, int x, int y);
+wm_handle wm_create (int x0, int y0, int x1, int y1, int border, int battr,
+    int wattr);
+void wm_ctype (wm_handle wh, int start, int end);
+void wm_cursor (wm_handle wh);
+void wm_cvis (wm_handle wh, int flag);
+void wm_del_char (wm_handle wh, int x, int y, int count);
+void wm_del_line (wm_handle wh, int y, int count);
+void wm_delete (wm_handle wh);
+void wm_dimen (wm_handle wh, int *width, int *height);
+void wm_down (wm_handle wh);
+void wm_exit (void);
+wm_handle wm_find (int x, int y);
+int wm_get_attrib (wm_handle wh);
+wm_handle wm_get_cursor (void);
+void wm_get_pos (wm_handle wh, int *x, int *y);
+int wm_getx (wm_handle wh);
+void wm_getxy (wm_handle wh, int *x, int *y);
+int wm_gety (wm_handle wh);
+void wm_gotoxy (wm_handle wh, int x, int y);
+void wm_ins_char (wm_handle wh, int x, int y, int count);
+void wm_ins_line (wm_handle wh, int y, int count);
+int wm_init (int n);
+void wm_move (wm_handle wh, int x, int y);
+void wm_open (wm_handle wh);
+void wm_puta_at (wm_handle wh, int x, int y, int a, int count);
+void wm_putc (wm_handle wh, char c);
+void wm_putc_at (wm_handle wh, int x, int y, char c);
+void wm_putca (wm_handle wh, char c, int a);
+void wm_putca_at (wm_handle wh, int x, int y, char c, int a);
+void wm_puts (wm_handle wh, __const__ char *str);
+void wm_puts_at (wm_handle wh, int x, int y, __const__ char *str);
+void wm_putsn (wm_handle wh, __const__ char *str, int len);
+void wm_putsa (wm_handle wh, __const__ char *str, int len);
+void wm_putsa_at (wm_handle wh, int x, int y, __const__ char *str, int len);
+void wm_scroll (wm_handle wh, int count);
+void wm_top (wm_handle wh);
+void wm_up (wm_handle wh);
+void wm_update (wm_handle wh, int flag);
+void wm_wrap (wm_handle wh, int wrap_flag);
+
+
+#if defined (__EMX__)
+
+#if !defined (_VA_LIST)
+#define _VA_LIST
+typedef char *va_list;
+#endif
+
+int wm_fclose (struct _FILE *stream);
+struct _FILE *wm_fopen (wm_handle wh);
+
+#if defined (__GNUC__)
+int wm_printf (wm_handle wh, __const__ char *fmt, ...)
+        __attribute__ ((__format__ (__printf__, 2, 3)));
+int wm_vprintf (wm_handle wh, __const__ char *fmt, va_list arg_ptr)
+        __attribute__ ((__format__ (__printf__, 2, 0)));
+#else
+int wm_printf (wm_handle wh, __const__ char *fmt, ...);
+int wm_vprintf (wm_handle wh, __const__ char *fmt, va_list arg_ptr);
+#endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _SYS_WINMGR_H */
Index: trunk/src/emx/include/termcap.h
===================================================================
--- trunk/src/emx/include/termcap.h	(revision 18)
+++ trunk/src/emx/include/termcap.h	(revision 18)
@@ -0,0 +1,1 @@
+#include <gnu/termcap.h>
Index: trunk/src/emx/include/termio.h
===================================================================
--- trunk/src/emx/include/termio.h	(revision 18)
+++ trunk/src/emx/include/termio.h	(revision 18)
@@ -0,0 +1,6 @@
+/* termio.h (emx+gcc) */
+
+#ifndef _TERMIO_H
+#define _TERMIO_H
+#include <sys/termio.h>
+#endif /* not _TERMIO_H */
Index: trunk/src/emx/include/termios.h
===================================================================
--- trunk/src/emx/include/termios.h	(revision 18)
+++ trunk/src/emx/include/termios.h	(revision 18)
@@ -0,0 +1,157 @@
+/* termios.h (emx+gcc) */
+
+#ifndef _TERMIOS_H
+#define _TERMIOS_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* tcsetattr() */
+
+#define TCSANOW     0
+#define TCSADRAIN   1
+#define TCSAFLUSH   2
+
+/* tcflush() */
+
+#define	TCIFLUSH    0
+#define	TCOFLUSH    1
+#define TCIOFLUSH   2
+
+/* tcflow() */
+
+#define	TCOOFF	    0
+#define	TCOON	    1
+#define TCIOFF	    2
+#define TCION	    3
+
+/* c_cc indexes */
+
+#if !defined (VINTR)            /* Symbols common to termio.h and termios.h */
+#define VINTR       0
+#define VQUIT       1
+#define VERASE      2
+#define VKILL       3
+#define VEOF        4
+#define VEOL        5
+#define VMIN        6
+#define VTIME       7
+#endif
+#define VSUSP       8
+#define VSTOP       9
+#define VSTART      10
+
+#define NCCS        11          /* Number of the above */
+
+/* c_iflag, emx ignores most of the following bits */
+
+#if !defined (IGNBRK)           /* Symbols common to termio.h and termios.h */
+#define IGNBRK      0x0001
+#define BRKINT      0x0002
+#define IGNPAR      0x0004
+#define PARMRK      0x0008
+#define INPCK       0x0010
+#define ISTRIP      0x0020
+#define INLCR       0x0040
+#define IGNCR       0x0080
+#define ICRNL       0x0100
+#define IXON        0x0400
+#define IXOFF       0x1000
+#if !defined (_POSIX_SOURCE)
+#define IUCLC       0x0200      /* Extension */
+#define IXANY       0x0800      /* Extension */
+#define IDELETE     0x8000      /* Extension (emx) */
+#endif
+#endif
+
+/* c_oflag, emx ignores all of the following bits */
+
+#if !defined (OPOST)            /* Symbols common to termio.h and termios.h */
+#define OPOST       0x0001
+#endif
+
+/* c_cflag, emx ignores all of the following bits */
+
+#if !defined (B0)               /* Symbols common to termio.h and termios.h */
+#define B0          0x0000
+#define B50         0x0001
+#define B75         0x0002
+#define B110        0x0003
+#define B134        0x0004
+#define B150        0x0005
+#define B200        0x0006
+#define B300        0x0007
+#define B600        0x0008
+#define B1200       0x0009
+#define B1800       0x000a
+#define B2400       0x000b
+#define B4800       0x000c
+#define B9600       0x000d
+#define B19200      0x000e
+#define B38400      0x000f
+#define CSIZE       0x0030      /* Mask */
+#define CS5         0x0000
+#define CS6         0x0010
+#define CS7         0x0020
+#define CS8         0x0030
+#define CSTOPB      0x0040
+#define CREAD       0x0080
+#define PARENB      0x0100
+#define PARODD      0x0200
+#define HUPCL       0x0400
+#define CLOCAL      0x0800
+#if !defined (_POSIX_SOURCE)
+#define LOBLK       0x1000      /* Extension */
+#endif
+#endif
+
+/* c_lflag, emx ignores some of the following bits */
+
+#if !defined (ISIG)             /* Symbols common to termio.h and termios.h */
+#define ISIG        0x0001
+#define ICANON      0x0002
+#define ECHO        0x0008
+#define ECHOE       0x0010
+#define ECHOK       0x0020
+#define ECHONL      0x0040
+#define NOFLSH      0x0080
+#if !defined (_POSIX_SOURCE)
+#define XCASE       0x0004      /* Extension */
+#endif
+#endif
+#define IEXTEN      0x0100
+#define TOSTOP      0x0200
+
+
+typedef unsigned char cc_t;
+typedef unsigned int tcflag_t;
+typedef unsigned int speed_t;
+
+struct termios
+{
+  tcflag_t c_iflag;
+  tcflag_t c_oflag;
+  tcflag_t c_cflag;
+  tcflag_t c_lflag;
+  cc_t c_cc[NCCS];
+  int c_reserved[4];
+};
+
+
+speed_t cfgetispeed (__const__ struct termios *);
+speed_t cfgetospeed (__const__ struct termios *);
+int cfsetispeed (struct termios *, speed_t);
+int cfsetospeed (struct termios *, speed_t);
+int tcdrain (int);
+int tcflow (int, int);
+int tcflush (int, int);
+int tcgetattr (int, struct termios *);
+int tcsendbreak (int, int);
+int tcsetattr (int, int, __const__ struct termios *);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _TERMIOS_H */
Index: trunk/src/emx/include/time.h
===================================================================
--- trunk/src/emx/include/time.h	(revision 18)
+++ trunk/src/emx/include/time.h	(revision 18)
@@ -0,0 +1,105 @@
+/* time.h (emx+gcc) */
+
+#ifndef _TIME_H
+#define _TIME_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#if !defined (_TIME_T)
+#define _TIME_T
+typedef unsigned long time_t;
+#endif
+
+#if !defined (_CLOCK_T)
+#define _CLOCK_T
+typedef long clock_t;
+#endif
+
+#if !defined (_TM)
+#define _TM
+struct tm         /* cf. <emx/thread.h> */
+{
+  int tm_sec;     /* 0..59 */
+  int tm_min;     /* 0..59 */
+  int tm_hour;    /* 0..23 */
+  int tm_mday;    /* 1..31 */
+  int tm_mon;     /* 0..11 */
+  int tm_year;    /* 0(:=1900).. */
+  int tm_wday;    /* 0..6 */
+  int tm_yday;    /* 0..365 */
+  int tm_isdst;   /* 0 */
+};
+#endif
+
+#if !defined (CLOCKS_PER_SEC)
+#define CLOCKS_PER_SEC 100
+#endif
+
+char *asctime (__const__ struct tm *);
+char *ctime (__const__ time_t *);
+clock_t clock (void);
+double difftime (time_t, time_t);
+struct tm *gmtime (__const__ time_t *);
+struct tm *localtime (__const__ time_t *);
+time_t mktime (struct tm *);
+size_t strftime (char *, size_t, __const__ char *, __const__ struct tm *);
+time_t time (time_t *);
+
+
+#if !defined (__STRICT_ANSI__)
+
+/* POSIX.1 */
+
+void tzset (void);
+
+#endif
+
+
+#if !defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)
+
+#if !defined (CLK_TCK)
+#define CLK_TCK 100
+#endif
+
+extern int daylight;
+extern long timezone;
+extern char *tzname[2];
+
+char *strptime (__const__ char *, __const__ char *, struct tm *);
+
+#endif
+
+
+#if (!defined (__STRICT_ANSI__) && !defined (_POSIX_SOURCE)) \
+    || defined (_WITH_UNDERSCORE)
+
+extern int _daylight;
+extern long _timezone;
+extern char *_tzname[2];
+
+char *_strptime (__const__ char *, __const__ char *, struct tm *);
+void _tzset (void);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _TIME_H */
Index: trunk/src/emx/include/ulimit.h
===================================================================
--- trunk/src/emx/include/ulimit.h	(revision 18)
+++ trunk/src/emx/include/ulimit.h	(revision 18)
@@ -0,0 +1,20 @@
+/* ulimit.h (emx+gcc) */
+
+#ifndef _ULIMIT_H
+#define _ULIMIT_H
+
+#include <sys/ulimit.h>
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+long ulimit (int, ...);
+
+long _ulimit (int, ...);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _ULIMIT_H */
Index: trunk/src/emx/include/umalloc.h
===================================================================
--- trunk/src/emx/include/umalloc.h	(revision 18)
+++ trunk/src/emx/include/umalloc.h	(revision 18)
@@ -0,0 +1,102 @@
+/* umalloc.h (emx+gcc) */
+
+#ifndef _UMALLOC_H
+#define _UMALLOC_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+struct _uheap;
+typedef struct _uheap *Heap_t;
+
+typedef struct
+{
+  size_t _provided;
+  size_t _used;
+  size_t _tiled;
+  size_t _shared;
+  size_t _max_free;
+  size_t _segments;
+  size_t _crates;
+  size_t _reserved1;
+  size_t _reserved2;
+  size_t _reserved3;
+  size_t _reserved4;
+  size_t _reserved5;
+  size_t _reserved6;
+  size_t _reserved7;
+  size_t _reserved8;
+  size_t _reserved9;
+} _HEAPSTATS;
+
+#define _HEAP_REGULAR   0x01
+#define _HEAP_TILED     0x02
+#define _HEAP_SHARED    0x04
+
+#define _BLOCK_CLEAN    1
+#define _FORCE          1
+#define _HEAP_MIN_SIZE  512
+#define _RUNTIME_HEAP   _um_regular_heap
+
+#if !defined (_HEAPOK)
+#define _HEAPOK       0
+#define _HEAPEMPTY    1
+#define _HEAPBADBEGIN 2
+#define _HEAPBADNODE  3
+#define _HEAPBADEND   4
+#define _HEAPBADROVER 5
+#endif
+#define _FREEENTRY    6
+#define _USEDENTRY    7
+
+extern Heap_t _um_regular_heap;
+
+Heap_t _mheap (__const__ void *);
+Heap_t _uaddmem (Heap_t, void *, size_t, int);
+void *_ucalloc (Heap_t, size_t, size_t);
+int _uclose (Heap_t);
+Heap_t _ucreate (void *, size_t, int, unsigned,
+    void *(*)(Heap_t, size_t *, int *),
+    void (*)(Heap_t, void *, size_t));
+Heap_t _ucreate2 (void *, size_t, int, unsigned,
+    void *(*)(Heap_t, size_t *, int *),
+    void (*)(Heap_t, void *, size_t),
+    int (*)(Heap_t, void *, size_t, size_t *, int *),
+    void (*)(Heap_t, void *, size_t, size_t *));
+Heap_t _udefault (Heap_t);
+int _udestroy (Heap_t, int);
+int _uheapchk (Heap_t);
+int _uheapmin (Heap_t);
+int _uheapset (Heap_t, unsigned);
+unsigned _uheap_type (Heap_t);
+int _uheap_walk (Heap_t, int (*)(__const__ void *, size_t, int, int,
+                                 __const__ char *, size_t));
+int _uheap_walk2 (Heap_t, int (*)(Heap_t, __const__ void *, size_t, int, int,
+                                  __const__ char *, size_t, void *), void *);
+void *_umalloc (Heap_t, size_t);
+int _uopen (Heap_t);
+int _ustats (Heap_t, _HEAPSTATS *);
+void *_utcalloc (Heap_t, size_t, size_t);
+Heap_t _utdefault (Heap_t);
+void *_utmalloc (Heap_t, size_t);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _UMALLOC_H */
Index: trunk/src/emx/include/unchecke.h
===================================================================
--- trunk/src/emx/include/unchecke.h	(revision 18)
+++ trunk/src/emx/include/unchecke.h	(revision 18)
@@ -0,0 +1,86 @@
+/*----------------------------------------------------------------------*
+ * Bounds Checking for GCC.						*
+ * Copyright (C) 1995 Richard W.M. Jones <rwmj@doc.ic.ac.uk>.		*
+ *----------------------------------------------------------------------*
+ * This program is free software; you can redistribute it and/or modify	*
+ * it under the terms of the GNU General Public License as published by	*
+ * the Free Software Foundation; either version 2 of the License, or	*
+ * (at your option) any later version.					*
+ *									*
+ * This program is distributed in the hope that it will be useful,	*
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of	*
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	*
+ * GNU General Public License for more details.				*
+ *									*
+ * You should have received a copy of the GNU General Public License	*
+ * along with this program; if not, write to the Free Software		*
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		*
+ *----------------------------------------------------------------------*
+ * File:
+ *	run-includes/unchecked.h
+ * Summary:
+ *	Macros to allow per-pointer and per-use unchecked pointers.
+ * Other notes:
+ *	
+ * Author      	Date		Notes
+ * RWMJ		23/1/95		Initial implementation.
+ * RWMJ         17/6/95         Added miscellaneous features.
+ *----------------------------------------------------------------------*/
+
+#ifndef _bounds_unchecked_h
+#define _bounds_unchecked_h
+
+#if defined(__GNUC__) && defined(__BOUNDS_CHECKING_ON)
+
+/* Make pointer operations unchecked on each use.
+*/
+#define UNCHECKED_PTR_DIFF(p,q) ((ptrdiff_t)(((unsigned)(p))-((unsigned)(q))/sizeof (*p)))
+#define UNCHECKED_PTR_PLUS_INT(p,i) ((typeof(p))((unsigned)(p))+(i)*(sizeof *p))
+#define UNCHECKED_PTR_MINUS_INT(p,i) ((typeof(p))((unsigned)(p))-(i)*(sizeof *p))
+
+/* How to switch checking off over a region of the program. You will need
+ * 'DEBUG_FEATURES' set in the library. You do:
+ *     ..
+ *    BOUNDS_CHECKING_OFF;
+ *     .. strange pointer operations here ..
+ *    BOUNDS_CHECKING_ON;
+ */
+#define BOUNDS_CHECKING_OFF do {extern int __bounds_debug_no_checking; \
+                                __bounds_debug_no_checking = 1;} while(0)
+#define BOUNDS_CHECKING_ON  do {extern int __bounds_debug_no_checking; \
+                                __bounds_debug_no_checking = 0;} while(0)
+
+/* Switch bounds checking off in a single statement. You do:
+ *    BOUNDS_CHECKING_OFF_DURING (stmt);
+ * This works for most 'ordinary' statements, ie. not returns, or gotos, etc.
+ * For expressions, use:
+ *    BOUNDS_CHECKING_OFF_IN_EXPR (expr)
+ */
+#define BOUNDS_CHECKING_OFF_DURING(stmt) \
+  do { extern int __bounds_debug_no_checking; \
+       __bounds_debug_no_checking = 1; \
+       stmt; \
+       __bounds_debug_no_checking = 0; \
+  } while (0)
+#define BOUNDS_CHECKING_OFF_IN_EXPR(expr) \
+  ({ extern int __bounds_debug_no_checking; \
+     typeof(expr) __value; \
+     __bounds_debug_no_checking = 1; \
+     __value = (expr); \
+     __bounds_debug_no_checking = 0; \
+     __value; })
+
+#else /* not __GNUC__ or not __BOUNDS_CHECKING_ON */
+
+#define UNCHECKED_PTR_DIFF(p,q) ((p)-(q))
+#define UNCHECKED_PTR_PLUS_INT(p,i) ((p)+(i))
+#define UNCHECKED_PTR_MINUS_INT(p,i) ((p)-(i))
+
+#define BOUNDS_CHECKING_OFF
+#define BOUNDS_CHECKING_ON
+
+#define BOUNDS_CHECKING_OFF_DURING(stmt) stmt
+#define BOUNDS_CHECKING_OFF_IN_EXPR(expr) expr
+
+#endif /* __GNUC__, __BOUNDS_CHECKING_ON */
+#endif /* _bounds_unchecked_h */
Index: trunk/src/emx/include/unistd.h
===================================================================
--- trunk/src/emx/include/unistd.h	(revision 18)
+++ trunk/src/emx/include/unistd.h	(revision 18)
@@ -0,0 +1,228 @@
+/* unistd.h (emx+gcc) */
+
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined (_POSIX_C_SOURCE) && !defined (_POSIX_SOURCE)
+#define _POSIX_SOURCE
+#endif
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#if !defined (_SSIZE_T)
+#define _SSIZE_T
+typedef int ssize_t;
+#endif
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#if !defined (STDIN_FILENO)
+#define STDIN_FILENO    0
+#define STDOUT_FILENO   1
+#define STDERR_FILENO   2
+#endif
+
+#if !defined (F_OK)
+#define F_OK 0
+#define X_OK 1
+#define W_OK 2
+#define R_OK 4
+#endif
+
+#if !defined (SEEK_SET)
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#if !defined (_PC_LINK_MAX)
+#define _PC_LINK_MAX            1
+#define _PC_MAX_CANON           2
+#define _PC_MAX_INPUT           3
+#define _PC_NAME_MAX            4
+#define _PC_PATH_MAX            5
+#define _PC_PIPE_BUF            6
+#define _PC_CHOWN_RESTRICTED    7
+#define _PC_NO_TRUNC            8
+#define _PC_VDISABLE            9
+#endif
+
+#if !defined (_SC_ARG_MAX)
+#define _SC_ARG_MAX             1
+#define _SC_CHILD_MAX           2
+#define _SC_CLK_TCK             3
+#define _SC_NGROUPS_MAX         4
+#define _SC_OPEN_MAX            5
+#define _SC_STREAM_MAX          6
+#define _SC_TZNAME_MAX          7
+#define _SC_JOB_CONTROL         8
+#define _SC_SAVED_IDS           9
+#define _SC_VERSION             10
+#endif
+
+#if !defined (_POSIX_VERSION)
+#define _POSIX_VERSION          199009L
+#endif
+
+
+int access (__const__ char *, int);
+unsigned alarm (unsigned);
+int chdir (__const__ char *);
+/* chown() */
+int close (int);
+/* ctermid() */
+char *cuserid (char *);
+int dup (int);
+int dup2 (int, int);
+int execl (__const__ char *, __const__ char *, ...);
+int execle (__const__ char *, __const__ char *, ...);
+int execlp (__const__ char *, __const__ char *, ...);
+int execv (__const__ char *, char * __const__ *);
+int execve (__const__ char *, char * __const__ *, char * __const__ *);
+int execvp (__const__ char *, char * __const__ *);
+void _exit (int) __attribute__ ((__noreturn__));
+int fork (void);
+long fpathconf (int, int);
+char *getcwd (char *, size_t);
+int getegid (void);             /* gid_t getegid (void); */
+int geteuid (void);             /* uid_t geteuid (void); */
+int getgid (void);              /* gid_t getgid (void); */
+int getgroups (int, int *);     /* int getgroups (int, gid_t *); */
+char *getlogin (void);
+int getpgrp (void);             /* pid_t getpgrp (void); */
+int getpid (void);              /* pid_t getpid (void); */
+int getppid (void);             /* pid_t getppid (void); */
+int getuid (void);              /* uid_t getuid (void); */
+int isatty (int);
+/* link() */
+long lseek (int, long, int);
+long pathconf (__const__ char *, int);
+int pause (void);
+int pipe (int *);
+int read (int, void *, size_t);
+int rmdir (__const__ char *);
+int setgid (int);               /* int setsid (gid_t); */
+int setpgid (int, int);         /* int setpgid (gid_t, gid_t); */
+int setsid (void);              /* pid_t setsid (void); */
+int setuid (int);               /* setuid (uid_t); */
+unsigned sleep (unsigned);
+long sysconf (int);
+int tcgetpgrp (int);            /* pid_t tcgetpgrp (int); */
+int tcsetpgrp (int, int);       /* int tcsetpgrp (int, pid_t) */
+char *ttyname (int);
+int unlink (__const__ char *);
+int write (int, __const__ void *, size_t);
+
+
+#if !defined (_POSIX_SOURCE)
+
+void *brk (void *);
+char *getpass (__const__ char *);
+char *_getpass1 (__const__ char *);
+char *_getpass2 (__const__ char *, int);
+int mkstemp (char *);
+char *mktemp (char *);
+int profil (void *, unsigned, unsigned, unsigned);
+void *sbrk (int);
+
+#endif
+
+
+#if !defined (_POSIX_SOURCE) || _POSIX_C_SOURCE >= 2
+
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+/* Note: The 2nd argument is not const as GETOPT_ANY reorders the
+   array pointed to. */
+
+int getopt (int, char **, __const__ char *);
+
+#endif
+
+
+#if !defined (_POSIX_SOURCE) || defined (_WITH_UNDERSCORE)
+
+extern char *_optarg;
+extern int _optind;
+extern int _opterr;
+extern int _optopt;
+
+int _getopt (int, char **, __const__ char *);
+
+int _access (__const__ char *, int);
+unsigned _alarm (unsigned);
+int _chdir (__const__ char *);
+int _close (int);
+char *_cuserid (char *);
+int _dup (int);
+int _dup2 (int, int);
+int _execl (__const__ char *, __const__ char *, ...);
+int _execle (__const__ char *, __const__ char *, ...);
+int _execlp (__const__ char *, __const__ char *, ...);
+int _execv (__const__ char *, char * __const__ *);
+int _execve (__const__ char *, char * __const__ *, char * __const__ *);
+int _execvp (__const__ char *, char * __const__ *);
+int _fork (void);
+long _fpathconf (int, int);
+char *_getcwd (char *, size_t);
+int _getegid (void);
+int _geteuid (void);
+int _getgid (void);
+int _getgroups (int, int *);
+char *_getlogin (void);
+int _getpgrp (void);
+int _getpid (void);
+int _getppid (void);
+int _getuid (void);
+int _isatty (int);
+long _lseek (int, long, int);
+long _pathconf (__const__ char *, int);
+int _pause (void);
+int _pipe (int *);
+int _read (int, void *, size_t);
+int _rmdir (__const__ char *);
+int _setgid (int);
+int _setpgid (int, int);
+int _setsid (void);
+int _setuid (int);
+unsigned _sleep (unsigned);
+long _sysconf (int);
+int _tcgetpgrp (int);
+int _tcsetpgrp (int, int);
+char *_ttyname (int);
+int _unlink (__const__ char *);
+int _write (int, __const__ void *, size_t);
+
+void *_brk (void *);
+char *_getpass (__const__ char *);
+char *_getpass1 (__const__ char *);
+char *_getpass2 (__const__ char *, int);
+int _mkstemp (char *);
+char *_mktemp (char *);
+int _profil (void *, unsigned, unsigned, unsigned);
+void *_brk (void *);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _UNISTD_H */
Index: trunk/src/emx/include/utime.h
===================================================================
--- trunk/src/emx/include/utime.h	(revision 18)
+++ trunk/src/emx/include/utime.h	(revision 18)
@@ -0,0 +1,6 @@
+/* utime.h (emx+gcc) */
+
+#ifndef _UTIME_H
+#define _UTIME_H
+#include <sys/utime.h>
+#endif /* not _UTIME_H */
Index: trunk/src/emx/include/varargs.h
===================================================================
--- trunk/src/emx/include/varargs.h	(revision 18)
+++ trunk/src/emx/include/varargs.h	(revision 18)
@@ -0,0 +1,33 @@
+/* varargs.h (emx+gcc) */
+
+#ifndef _VARARGS_H
+#define _VARARGS_H
+
+#if !defined (NULL)
+#if defined (__cplusplus)
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#define _VA_LIST
+
+#define _VA_ROUND(type) ((sizeof (type) + 3) & -4)
+
+#define va_alist __builtin_va_alist
+#define va_dcl int __builtin_va_alist;
+#define va_list char *
+
+#define va_start(alist) alist = (char *)&__builtin_va_alist
+#define va_end(alist) (alist = 0, (void)0)
+#define __std_va_arg(alist,t) (alist += _VA_ROUND (t), \
+                               *((t *)(alist - _VA_ROUND (t))))
+
+#ifdef __BOUNDS_CHECKING_ON
+#include <fix-args.h>
+#else
+#define va_arg(alist,t) __std_va_arg(alist,t)
+#endif
+
+#endif /* not _VARARGS_H */
Index: trunk/src/emx/src/doc/emxbook.sed
===================================================================
--- trunk/src/emx/src/doc/emxbook.sed	(revision 18)
+++ trunk/src/emx/src/doc/emxbook.sed	(revision 18)
@@ -0,0 +1,4 @@
+1i\
+EXTENSIONS: *\
+DESCRIPTION: Global index for emx 0.9d on-line books
+s/^(\(.*\), view .* ~)$/(\1, view emxbook ~)/p
Index: trunk/src/emx/src/doc/emxbsd.src
===================================================================
--- trunk/src/emx/src/doc/emxbsd.src	(revision 18)
+++ trunk/src/emx/src/doc/emxbsd.src	(revision 18)
@@ -0,0 +1,167 @@
+þtext
+===============================================================================
+emxbsd.doc        emx 0.9d     BSD LIBRARIES INFORMATION            21-Dec-1998
+===============================================================================
+þendtext
+
+þtitle BSD Libraries Information
+
+þformat bold emx
+
+þformat tty bsd.a bsd.lib curses.a curses.lib termcap.a termcap.lib
+þformat tty db.a db.lib btermcap.a btermcap.lib
+þformat tty -lbsd -lcurses -ltermcap -lbtermcap -ldb
+þformat tty heapsort() random() strsep() dbopen()
+
+þif text
+þh= Table of Contents
+þtoc
+þendif
+
+
+þh1 Introduction to BSD Libraries Information
+þipf
+:font facename=Helv size=24x14.:hp2.BSD Libraries Information
+:ehp2.
+:font facename=default size=0x0.
+:p.
+þendipf
+
+  BSD curses has been ported to emx by Kai Uwe Rommel.
+
+  As BSD curses has a few bugs, you might want to use PD curses
+  instead:
+
+þexample
+ftp-os2.cdrom.com: /pub/os2/dev16/pdcurs21.zip
+ftp.leo.org:       /pub/comp/os/os2/libraries/pdcurs21.zip
+þendexample
+
+  The BSD database library provides B-tree and hashing access methods
+  for files.
+
+  The emx C library is complemented by the BSD C library: The
+  heapsort(), random() and strsep() functions are in the libraries
+  bsd.a and bsd.lib.
+
+þipfminitoc
+
+þh1 bsd.a and bsd.lib
+þindex bsd.a
+þindex bsd.lib
+þindex heapsort()
+þindex initstate()
+þindex random()
+þindex setstate()
+þindex srandom()
+þindex strsep()
+þkeyword bsd.a
+þkeyword bsd.lib
+þkeyword heapsort()
+þkeyword initstate()
+þkeyword random()
+þkeyword setstate()
+þkeyword srandom()
+þkeyword strsep()
+
+  bsd.a and bsd.lib contain the following functions:
+
+þexample
+heapsort()
+initstate()
+random()
+setstate()
+srandom()
+strsep()
+þendexample
+
+  Use -lbsd to link with this library.  You have to obey the BSD
+  license, see þtt{/emx/doc/COPYING.BSD}.
+
+  You'll find manual pages in þtt{/emx/bsd/man}.
+
+
+þh1 btermcap.a and btermcap.lib
+þindex btermcap.a
+þindex btermcap.lib
+þkeyword btermcap.a
+þkeyword btermcap.lib
+
+  The BSD termcap library provides functions for using display
+  terminals in a terminal-independent manner.  You have to obey the
+  BSD license, see þtt{/emx/doc/COPYING.BSD}.
+
+  See þtt{/emx/bsd/man/termcap.3} and þtt{/emx/bsd/man/termcap.5} for
+  more information on BSD termcap.
+
+  emx comes with both the GNU and the BSD termcap libraries.  By
+  default, the GNU termcap library is used.  To switch to the BSD
+  termcap library, replace `þtt{gnu}' in þtt{/emx/include/termcap.h}
+  with `þtt{bsd}' and use -lbtermcap instead of -ltermcap.
+
+þh1 curses.a and curses.lib
+þindex curses.a
+þindex curses.lib
+þkeyword curses.a
+þkeyword curses.lib
+
+  The BSD curses library provides functions for updating screens.  You
+  have to obey the BSD license, see þtt{/emx/doc/COPYING.BSD}.  In
+  addition to curses.a or curses.lib (-lcurses), you have to link with
+  a termcap library.  You can use either the BSD termcap library
+  (-lbtermcap) or the GNU termcap library (-ltermcap).  If you use the
+  GNU termcap library, you have to obey the GNU General Public
+  License, see þtt{/emx/doc/COPYING}.
+
+  See þtt{/emx/bsd/man/curses.3} for a short list of library
+  functions.  See the the files in þtt{/emx/bsd/curses/doc} for a
+  complete manual (you might want to use þtt{groff} for formatting).
+
+  Use `þtt{-lcurses -lbtermcap}' for linking programs that use BSD
+  curses.
+
+  Here's how to compile and run a sample program:
+
+þtypewriter
+cd \emx\samples þbreak
+copy \emx\bsd\curses\doc\twinkle1.c þbreak
+[þsl{use an editor to remove the first 33 lines of twinkle1.c}] þbreak
+gcc twinkle1.c -lcurses -lbtermcap
+twinkle1
+þendtypewriter
+
+  Note: þtt{twinkle1.c} is the only complete program in
+  þtt{/emx/bsd/curses/doc}.
+
+þh1 db.a and db.lib
+þindex db.a
+þindex db.lib
+þindex dbopen()
+
+  The BSD database library provides B-tree and hashing access methods
+  for files.  Note that this version of that library is obsolete and
+  has some bugs which cannot be fixed without changing the file
+  formats.
+
+  Use the dbopen() function to open or create a database
+  file.  See þtt{dbopen.3}, þtt{btree.3}, þtt{hash.3}, þtt{recno.3},
+  and þtt{mpool.3} in þtt{/emx/bsd/man} for details.  Use the -ldb
+  option to link with the BSD database library.  You have to obey the
+  BSD license, see þtt{/emx/doc/COPYING.BSD}.
+
+  Here's how to compile and run a sample program:
+
+þexample
+cd \emx\samples
+dmake wordref.exe
+wordref                       -- Show how to run the sample program
+wordref add \emx\doc\*.doc    -- This will take quite a while and 6 MByte
+wordref find database
+þendexample
+
+  Type `þtt{wordref clear}' to delete the database.
+
+þtext
+
+--------------------------- END OF EMXBSD.DOC ------------------------------
+þendtext
Index: trunk/src/emx/src/doc/emxdev.src
===================================================================
--- trunk/src/emx/src/doc/emxdev.src	(revision 18)
+++ trunk/src/emx/src/doc/emxdev.src	(revision 18)
@@ -0,0 +1,4551 @@
+þtext
+===============================================================================
+emxdev.doc        emx 0.9d     APPLICATION DEVELOPER'S GUIDE        21-Dec-1998
+===============================================================================
+                                     Copyright (c) 1990-1998 by Eberhard Mattes
+þendtext
+
+þtitle emx 0.9d Application Developer's Guide
+
+þformat bold emx emxbind emxcat emximp emxomf emxomfar emxomfld 0.8f 9.9c 0.9d
+þformat bold emxload emxrev listomf emxexp emxaout emxtsf updt dmake
+þformat bold GCC GCOV GDB ld nm rc objdump GPPDEMID gprof TRCUST TRACE TRACEFMT
+
+þformat tty .a .bak .def .dll .exe .imp .lib .map .o .obj .res .s .tsf
+þformat tty build.doc
+þformat tty os2.h os2emx.h os2tk.h emx.h
+þformat tty cmd.exe command.com
+þformat tty emx.exe emxd.exe emxl.exe emxload.exe emxomf.exe emxomfld.exe
+þformat tty emx.dll emxio.dll emxlibcm.dll emxlibcs.dll
+þformat tty emxwrap.dll gppdemid.dll
+þformat tty strip.exe gcc.exe cpp.exe cc1.exe cc1plus.exe cc1obj.exe
+þformat tty crt0.s crt0.o gcrt0.o
+þformat tty c_import.a os2.a c_static.a c_static.lib
+þformat tty c.lib c_app.lib c_dllemx.lib c_dllsys.lib c_import.lib
+þformat tty os2.lib emx.lib emx2.lib sys.lib gcc.lib
+þformat tty emxio crt0 dll0
+þformat tty myprog.exe himem.sys config.sys
+þformat tty test.dll test.exe test.def test.res test1.obj test2.obj
+þformat tty /emx/bin/emxl.exe
+þformat tty stdio.c iodata.c gmon.out
+þformat tty <ctype.h> <dirent.h> <float.h> <io.h> <locale.h> <malloc.h>
+þformat tty <math.h> <process.h> <pwd.h> <signal.h> <stdio.h>
+þformat tty <stdlib.h> <string.h> <strings.h> <sys/emxload.h> <sys/fmutex.h>
+þformat tty <termios.h> <time.h> <umalloc.h> <unistd.h>
+
+þformat tty -mprobe -T -nostdlib -lwrap -lc -los2 -pg -pn
+þformat tty -Zmap[=<map_file>] -Zsysv-signals -Zbsd-signals -Zmt -Zso -Zcrtdll
+þformat tty -Zdll -Zomf -Zmtd -Zmts -Zsys -Zexe -Zstack -Zlinker
+
+þformat tty O_BINARY P_DEBUG P_NOSESSION SIGQUIT SIGILL SIGCLD SIGTRAP
+þformat tty SIGABRT SIGEMT SIGFPE SIGBUS SIGSEGV SIGSYS SIG_ACK
+þformat tty c_lflag VEOF VEOL VMIN VTIME IDEFAULT
+þformat tty __MT__ __.SYMDEF __.IMPORT
+
+þformat tty alarm() brk() fork() exec*() exit() fdopen() fopen() freopen()
+þformat tty fseek() main() malloc() open() popen() sbrk() select() abort()
+þformat tty sleep() spawn*() strcpy() system() wait() memcpy() ftell()
+þformat tty _abspath() _beginthread() _core() _emx_16to32() _emx_32to16()
+þformat tty _fseek_hdr() _fsetmode() _fullpath() _memaccess() _portaccess()
+þformat tty _read_kbd() _seek_hdr() _sleep2() _tmalloc() _inp8()
+þformat tty _CRT_init() _CRT_term() _DLL_InitTerm() _errno()
+þformat tty __open()
+þformat tty _tp __os2_bad __os2dll _16_ #define #include errno
+þformat tty argc argv "b" stdin stdout stderr
+þformat tty _pascal _cdecl
+þformat tty _THUNK_FUNCTION _THUNK_PROLOG _THUNK_CALL _THUNK_CALLI _THUNK
+þformat tty _THUNK_PASCAL_*** _THUNK_C_*** _THUNK_*** _THUNK_C_FUNCTION
+
+þformat tty DosSelectSession _DosSelectSession DosCreateThread DosSetMaxFH
+þformat tty DosLoadModule DosQueryProcAddr DosKillThread
+
+þformat tty -a -b -c -d -e -f -g -i -k -l -m -n -o -p -q -r -s -t -u -v -w -x
+þformat tty -D -E -F -I -K -L -O -P -R -S -X
+þformat tty -ac -am -aw -ai -aim -aciw -bs
+þformat tty -m1 -m2 -m3 -s8 -rd -s524288 -s8192 -S1 -S2 -qw -uw
+
+þformat syntax -a* -h# -m# -r* -p# -s# -C# -S# -V -Z
+þformat syntax <emxbind_options> -c[<core_file>] -d<def_file> -E<dll>
+þformat syntax -r<res_file> -h<heap_size> -k<stack_size> <def_file> <dll>
+þformat syntax <emx>[.exe] <input_file> <output_file>[.exe] <emx_options>
+þformat syntax -c[<core_file>] -d[<def_file>] <res_file> <file> <dir> <drive>
+þformat syntax <output_file> <program_file> <emx> <page_size> <options>
+þformat syntax <core_file> <symbol> <default_lib> <source_file> <target_file>
+þformat syntax <library_file> <command> <emx_options> <program> <arguments>
+þformat syntax <internalname> =<internalname> <entryname> <ordinal> @<ordinal>
+þformat syntax <libraryname> <number> <initialization> <termination>
+þformat syntax <appname> <apptype> <input_file>.imp <input_file>.lib
+þformat syntax <output_file>.lib <output_file>.a <input_file>.def
+þformat syntax <idmdll> <dataseg> -m<limit> -s<limit> <libdir> <directory>
+þformat syntax <address> <range> <value> <register> <condition> <list>
+þformat syntax <response_file> <option> <map_file> -m<map_file>
+þformat syntax <tss_file> <dll_name> <level>
+þformat syntax LIBRARY INITGLOBAL INITINSTANCE TERMGLOBAL TERMINSTANCE
+þformat syntax NEWFILES LONGNAMES EXPORTS RESIDENTNAME DESCRIPTION NONAME
+þformat syntax NOTWINDOWCOMPAT WINDOWAPI WINDOWCOMPAT NAME STUB STACKSIZE
+
+þformat abbrev etc.
+
+þif text
+þh= Table of Contents
+þtoc
+þendif
+
+þh1 Introduction to the emx Application Developer's Guide
+þlabel introduction
+þipf
+:font facename=Helv size=24x14.:hp2.emx 0.9d APPLICATION DEVELOPER'S GUIDE
+:ehp2.
+:p.
+:font facename=Helv size=16x10.      Copyright (c) 1990-1998 by Eberhard Mattes
+:font facename=default size=0x0.
+:p.
+þendipf
+
+  This document describes how to use emx utilities to create programs
+  running under emx and how to create OS/2 programs with the emx
+  utilities.  In this document, OS/2 stands for OS/2 2.x and later.
+
+  The GNU utilities are described in þtt{/emx/doc/emxgnu.doc} and
+  þtt{/emx/book/emxgnu.inf}.
+
+  There are three methods for creating executable files:
+
+þdescription
+þitem (E1)
+
+        using þhpt{ld} and þhpt{emxbind}
+
+þitem (E2)
+
+        using þhpt{emxomf}, þhpt{emxomfld} and LINK386, the program
+        will use the emx.dll dynamic link library for performing
+        system calls
+
+þitem (E3)
+
+        using emxomf, emxomfld and LINK386, the program will be linked
+        with a system call library (creating a stand-alone application
+        or DLL)
+
+þenddescription
+
+  The assembler creates a Unix-style a.out object file (.o file).
+  When using method (E1), .o files created by the assembler are linked
+  by a Unix-style linker with Unix-style libraries (.a files) to
+  create a Unix-style a.out file.  Then, emxbind is used to turn this
+  file into an .exe file that can be executed under both OS/2 and
+  DOS.  Using method (E1) enables core dumps and þhpt{fork()}.
+  Moreover, programs created with method (E1) can be debugged using
+  þhpt{GDB}, the GNU debugger.  Programs created using method (E1) use
+  emx (emx.dll under OS/2, emx.exe under DOS) for system calls.
+
+  When using method (E2), the .o files created by the assembler are
+  converted to Object Module Format files (.obj files).  These files
+  are linked with the OS/2 linker LINK386.  The libraries are .lib
+  files.  emxomfld is a front end to LINK386 which converts the ld
+  command line to a LINK386 command line.  Programs created with
+  method (E2) cannot create core dumps, cannot call fork() and cannot
+  be debugged with GDB.  Method (E2) works only under OS/2 and creates
+  programs that work only under OS/2.  You can use IBM's IPMD and
+  SD386 debuggers to debug programs created with methods (E2) and
+  (E3).  Files created with method (E2) are usually smaller.  The
+  emx.dll dynamic link library is used for system calls.  The
+  þhpt{-Zomf} option of þhpt{GCC} selects method (E2).
+
+  When using method (E3), the program won't call the emx.dll dynamic
+  link library.  A system call library (emx emulator) is linked to the
+  program.  The system call library maps system calls to OS/2 API
+  calls.  Only a subset of the emx system calls is available with
+  method (E3).  For instance, the þhpt{general terminal interface} is
+  not available.  Functions which are not available or are limited
+  with method (E3) are marked [*] in the library reference.  Use a
+  þhpt{module definition file} and the þhpt{STACKSIZE statement} to
+  set the stack size.  Alternatively, you can use the þhpt{-Zstack}
+  option of GCC.  The default stack size is 0x8000 bytes.  Note that
+  the command line arguments and environment pointers are copied
+  to the stack on startup.
+
+  The following table summarizes the methods for creating executable
+  files.
+
+þverbatim
+  Method                         ³  (E1)        ³  (E2)       ³  (E3)
+  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+  GCC options                    ³              ³ -Zomf       ³ -Zomf -Zsys
+  Object file format             ³ a.out        ³ OMF         ³ OMF
+  Object file name extension     ³ .o           ³ .obj        ³ .obj
+  Library file name extension    ³ .a           ³ .lib        ³ .lib
+  Executable file format         ³ LX & a.out   ³ LX          ³ LX
+  Object files converted by      ³ N/A          ³ emxomf      ³ emxomf
+  Executable files converted by  ³ emxbind      ³ N/A         ³ N/A
+  Linker                         ³ ld           ³ LINK386     ³ LINK386
+  Librarian                      ³ ar           ³ emxomfar    ³ emxomfar
+  Minimal set of libraries       ³ c gcc        ³ c gcc       ³ c gcc
+                                 ³              ³ emx emx2    ³ sys os2
+  Methods for importing          ³ (I1) (I2)    ³ (I3)        ³ (I3)
+  Can link with OMF libraries    ³ NO (note 1)  ³ NO (note 1) ³ YES
+  Debugger                       ³ GDB          ³ IPMD, SD386 ³ IPMD, SD386
+  emx.dll required at run time   ³ YES          ³ YES         ³ NO
+  Library support                ³ +++          ³ ++          ³ +
+  Core dumps                     ³ YES          ³ NO          ³ NO
+  Size overhead                  ³ big          ³ none        ³ (note 2)
+  Programs run under DOS         ³ YES          ³ NO          ³ NO
+  Can create DLLs                ³ YES (note 3) ³ YES         ³ YES
+  EMXOPT environment variable    ³ YES          ³ YES         ³ NO
+  -Zmt supported                 ³ YES          ³ YES         ³ YES
+  -Zcrtdll supported             ³ YES          ³ YES         ³ NO
+þendverbatim
+
+þdescription
+þitem Note 1:
+
+  import libraries can be used after conversion with þhpt{emximp}
+
+þitem Note 2:
+
+  depends on the set of syscalls used by the program
+
+þitem Note 3:
+
+  not recommended unless you want to debug the DLL with GDB
+
+þenddescription
+
+  See also section `þhpt{Startup modules and libraries}' of
+  þtt{emxgnu.doc}.
+
+  Programs created with method (E1) or (E2) can use emxlibcm.dll or
+  emxlibcs.dll, dynamic link libraries containing the C library.  Use
+  the -Zcrtdll option to make a program that uses emxlibcm.dll
+  (multithread library) or emxlibcs.dll (single-thread library).
+  Programs which use emxlibcm.dll or emxlibcs.dll don't run under DOS.
+  For running the application, either emxlibcm.dll or emlibcs.dll
+  (depending on whether the application is a single-thread or
+  multithread program) and emx.dll are required.  There are three
+  advantages of using emxlibcm.dll and emxlibcs.dll:
+
+þitemize
+þitem
+    reduced executable size
+þitem
+    reduced memory requirements
+þitem
+    programs don't have to be re-linked when the C library is changed.
+þenditemize
+
+  Use -Zomf -Zcrtdll -lwrap -s to minimize the size of the executable
+  file.
+
+  Please note that you should change the name of emxlibcm.dll or
+  emxlibcs.dll if you want to distribute your program with modified
+  versions of those dynamic link libraries.
+
+  For using floating point arithmetic, a coprocessor is required
+  (80387 or i486).  All exceptions are masked, that is, computation
+  continues with +#INF, -#INF, +#NAN or -#NAN after an error.
+
+  A 387 coprocessor is not required for doing floating point
+  arithmetic under OS/2.  Under DOS, a 387 coprocessor (or i486)
+  is required for doing floating point arithmetic.
+
+  A core dump file will be written if a program is terminated by
+  signal SIGSEGV (protection violation), SIGILL (illegal instruction),
+  SIGABRT (abort()), SIGFPE (floating point exception), SIGTRAP
+  (breakpoint), SIGBUS, SIGEMT, SIGQUIT, or SIGSYS.  You can later
+  debug the program using the .exe file and the core dump file.  The
+  name of the core dump file is þtt{core}, and it is put into the
+  current working directory.  Use the -c emx option to suppress
+  writing a core dump file.  When linking a program using method (E2)
+  or (E3), core dump files are not written by that program.
+
+  OS/2 and DOS support both the forward slash and the backslash for
+  separating directories.  Unix utilities usually treat the backslash
+  character specially, therefore you should use the forward slash.
+  This document uses forward slash unless an OS/2 or DOS command is
+  shown (cmd.exe and command.com use backslashes).
+
+
+  File name extensions (the list is incomplete):
+
+þexample
+a                       Unix-style library (archive)
+bat                     DOS batch file
+c                       C source file
+cc                      C++ source file
+cmd                     OS/2 batch file
+cpp                     C++ source file
+cxx                     C++ source file
+def                     Module definition file
+doc                     Documentation file
+dll                     Dynamic link library
+dvi                     Device independent file, created by TeX
+exe                     Executable file
+h                       C include file (header file)
+i<digits>               Split GNU info file
+imp                     emx import list file
+inf                     GNU info file (use `info' for reading) or
+                        OS/2 on-line book (use `VIEW' for reading)
+lib                     OMF library
+m                       Objective C source file
+map                     Map file, created by LINK386 or emxbind
+o                       Object file (Unix style, a.out)
+obj                     Object file (OMF)
+rc                      Resource script file
+res                     Binary resource file
+s                       Assembler source file
+tex                     TeX (or texinfo) source file
+þendexample
+
+  Directories:
+
+þexample
+/emx                    Main directory, contains no files
+/emx/bin                Executable files and batch files
+/emx/dll                DLLs for OS/2
+/emx/doc                Documentation
+/emx/include            Header files (C language)
+/emx/lib                Libraries
+/emx/lib/mt             Multithread libraries
+/emx/lib/st             Single-thread libraries
+/emx/new                New .exe files created by the makebin batch file
+/emx/samples            Sample programs
+/emx/src                Source code
+/emx/test               Test programs
+þendexample
+
+þh1 Managing bound .exe files with emxbind
+þlabel emxbind
+þi1 emxbind
+þkeyword emxbind
+
+  The emxbind utility is used to create and modify bound .exe files
+  using method (E1).  The action to be performed is specified by a
+  command letter which looks like a command line option.
+
+þif ipf
+
+  The following emxbind commands are available:
+
+þdescription
+þitem -b
+
+    þhpt{Create an .exe file from an a.out file}
+
+þitem -s
+
+    þhpt{Change the type of an .exe file}
+
+þitem -x
+
+    þhpt{Extract the a.out file from a bound .exe file}
+
+þitem -a
+
+    þhpt{Change the emx options of a bound .exe file}
+
+þitem -i
+
+    þhpt{Display the emx options of a bound .exe file}
+
+þitem -u
+
+    þhpt{Update emx.exe in a bound .exe file}
+
+þitem -s
+
+    þhpt{Strip the symbol table from a bound .exe file}
+
+þenddescription
+þendif
+
+þh2 Creating an .exe file
+þlabel Create an .exe file from an a.out file
+þlabel -b command
+þi2 -b command
+
+  emxbind binds emx.exe and an emx executable file into one executable
+  file which runs both under OS/2 2.0 (or later) and DOS.
+
+þipfminitoc
+
+þh3 Important notes
+
+  The bound program does not run under DOS versions prior to 3.0.  emx
+  options cannot be put onto the command line; use EMXOPT instead.
+
+  Do not compress the bound executable with a program like TINYPROG,
+  PKLITE, or LZEXE, which makes the program uncompress itself when
+  started.
+
+  emx can be used for running bound .exe files created using the same
+  version of emx.  þhpt{spawn*()} and þhpt{exec*()} also work on bound
+  .exe files.
+
+  The GNU programs þhpt{GDB}, þbf{nm}, þbf{objdump} and þbf{size}
+  (but not þhpt{strip}) have been modified to work with bound .exe
+  files.
+
+  You can use the emx loader emxl.exe to save disk space.  When the
+  bound executable is run, emxl.exe will load emx.exe to run the
+  program.  There is a small speed penalty due to locating and loading
+  emx.exe.
+
+  If the EMX environment variable is set, emxl.exe first tries to load
+  the file specified by that variable.  Use
+
+þexample
+SET EMX=c:\emx\bin\emx.exe
+þendexample
+
+  to speed up locating emx.exe.  You can also use emxd.exe this way.
+
+  If the EMX environment variable is not set or the emx.exe file
+  specified by EMX could not be loaded, emxl.exe will try emx.exe in
+  the current working directory, then emx.exe in all directories
+  listed in the PATH environment variable.
+
+þh3 Invoking emxbind to create an .exe file
+
+  There are two ways to invoke emxbind to create an .exe file.  The
+  first one is used if you want to use the default emxl.exe:
+
+þindent
+  þsy{emxbind [-b] [<emxbind_options>] [-o <output_file>[.exe]]} þbreak
+  þsy{        <input_file> [<emx_options>]}
+þendindent
+
+  The second one is used if you want to specifiy the path name of the
+  emx executable (emxl.exe, emx.exe, or emxd.exe) to use:
+
+þindent
+  þsy{emxbind [-b] [<emxbind_options>]} þbreak
+  þsy{        <emx>[.exe] <input_file> [<output_file>[.exe]] [<emx_options>]}
+þendindent
+
+  The command line consists of the following elements:
+
+þlist
+þitem <emxbind_options>
+
+  The following options can be given to emxbind.  They must appear at
+  the beginning of the emxbind arguments.
+
+þdescription
+þitem -b (optional)
+
+    this emxbind command means `bind' and is the default.  If you want
+    to use the -s option (strip symbol table), -b cannot be omitted,
+    that is, you should type -bs (otherwise, emxbind would perform the
+    þhpt{-s command} described below)
+
+þitem -c[<core_file>]
+
+    combine an a.out file and a core dump file created for that a.out
+    file into one program.  This can be used to create a a program
+    with preloaded data.  Note that the .exe file will waste a lot of
+    disk space.  If you don't enter <core_file>, þtt{core} will be
+    used.  The core dump file must not contain multiple heap objects
+
+þitem -d[<def_file>]
+
+    read the module definition file <def_file>.  The default extension
+    is .def.  If <def_file> is omitted, <input_file> with .def
+    extension is used instead.  See section þref{module definition
+    files} for details on þhpt{module definition files}
+
+þitem -E<dll>
+
+    use <dll>þtt{.dll} instead of emx.dll.  This option is used for
+    referencing an alternate, renamed emx.dll.  If -E<dll> is not
+    used, emxbind takes the name of the DLL from the EMXBIND_DLL
+    environment variable.  For instance, to use þtt{myx.dll} instead
+    of emx.dll, use the following command:
+þexample
+set emxbind_dll=myx
+þendexample
+    If both -E<dll> and EMXBIND_DLL are not set, emxbind uses emx.dll
+
+þitem -f
+
+    set application type to `full screen'.  See also the þhpt{-e
+    command}
+
+þitem -h<heap_size>
+þlabel -h<heap_size> option of emxbind
+
+    set heap size for OS/2.  This is the space available for
+    allocation by þhpt{malloc()} and þhpt{_tmalloc()}.  For emx 0.9c
+    and later, the heap size specifies the size of the initial heap
+    object; malloc() may allocate additional heap objects so that the
+    total size of the heap is no longer limited by the size of the
+    initial heap object.  The number is given in decimal, octal or
+    hexadecimal, using C notation.  The heap size is specified in
+    megabytes (0 through 512).  The default value is 32.  For DOS, the
+    heap size is controlled by the þhpt{-s# emx option} (see section
+    þref{Using emx options})
+
+þitem -k<stack_size>
+þlabel -k<stack_size> option of emxbind
+
+    set the size of the stack object of the executable file.  The
+    number is given in decimal, octal or hexadecimal, using C
+    notation.  The stack size set by this option is used under OS/2.
+    The stack size is given in KByte, the default is 8192 (8 MByte).
+    The stack size must be between 20 and 524288 (512 MByte).  The
+    stack size should not be less than 32 KByte.  You should not use
+    -k without -b, as a -k command is planned for a future version of
+    emxbind
+
+þitem -m<map_file>
+
+    write the map file <map_file>.  The format is simular to that of
+    map files written by LINK386.  The default extension is
+    `þtt{map}'.
+
+þitem -p
+
+    set application type to `Presentation Manager'.  See also the
+    þhpt{-e command}
+
+þitem -q
+
+    don't display emxbind banner line
+
+þitem -r<res_file>
+
+    put resources from binary resource file <res_file> (no default
+    extension) into the .exe file.  Use þtt{rc -r} to create the
+    binary resource file.  Do not use rc to put the resources into the
+    .exe file
+
+þitem -s
+
+    strip symbols (requires -b).  You can also strip the symbol table
+    before creating the .exe file by calling
+þif ipf
+    þhpt{strip}
+þelse
+    strip.exe
+þendif
+    or after
+    creating the .exe file by using the þhpt{-s command} of emxbind
+
+þitem -v
+
+    display more information: list resources, display path name of
+    emxl.exe unless given on command line, display the statements in
+    the module definition file that are ignored
+
+þitem -w
+
+    set application type to `windowed' (default).  See also the
+    þhpt{-e command}
+
+þenddescription
+
+    Only one of the options -f, -p and -w can be used.  If none of
+    these options is used, the application type is taken from the NAME
+    statement of the module definition file (-d option).  If no module
+    definition file is used, -w is the default.
+
+þitem þsy{[-o <output_file>[.exe]]}
+
+    path name of the bound executable file.  The default extension is
+    .exe unless the LIBRARY statement is used in the module definition
+    file.  If LIBRARY is used in the module definition file (that is,
+    when you are creating a dynamic link library), the default
+    extension is .dll.  If the <output_file> parameter is omitted, the
+    <input_file> parameter will be used instead (do not specify an
+    extension for the input file to avoid overwriting the input
+    file!).  Moreover, the output file name (or <input_file>, if
+    <output_file> is omitted) sans directory part and extension is
+    used as module name for the .exe file unless a module name is
+    defined with a NAME or LIBRARY statement in the module definition
+    file.
+
+    The -o option can be used only if there is exactly one file name
+    (which is not the argument of an option) given
+
+þitem <emx> (optional if no <output_file> is given)
+
+    path name of emx (default extension: .exe), that is emx.exe,
+    emxd.exe or emxl.exe.  Using þtt{emxl.exe} is recommended.  If
+    this argument is omitted (in this case the <output_file> argument
+    must be omitted as well), the filename from the STUB statement of
+    the module definition file is used.  emxbind searches the
+    directories listed in the EMXPATH and PATH environment variables
+    for that file.  If no module definition file is used or if the
+    STUB statement isn't used, the file /emx/bin/emxl.exe will be
+    used.  If that file doesn't exist, emxbind searches the
+    directories listed in the EMXPATH and PATH environment variables
+    for emxl.exe.  If that fails, emxl.exe is taken from the current
+    working directory.  If the -v option is given, the path name of
+    emxl.exe will be displayed unless a STUB statement is present
+
+þitem <input_file>
+
+    path name of the a.out file to be read
+
+þitem <output_file> (optional)
+
+    path name of the bound executable file.  The default extension is
+    .exe unless the LIBRARY statement is used in the module definition
+    file.  If LIBRARY is used in the module definition file (that is,
+    when you are creating a dynamic link library), the default
+    extension is .dll.  If the <output_file> parameter is omitted, the
+    <input_file> parameter will be used instead (do not specify an
+    extension for the input file to avoid overwriting the input
+    file!).  Moreover, the output file name (or <input_file>, if
+    <output_file> is omitted) sans directory part and extension is
+    used as module name for the .exe file unless a module name is
+    defined with a NAME or LIBRARY statement in the module definition
+    file.
+
+    Use <output_file> instead of the -o option if you need to specify
+    <emx>
+
+þitem <emx_options> (optional)
+
+    emx options to be used when running the bound program.  These
+    options will be examined before those given in EMXOPT.  emxbind
+    does not completely check the validity of the options.  See
+þif ipf
+    þhpt{Using emx options}
+þelse
+    section þref{Using emx options}
+þendif
+    for details.
+
+þdescription
+þitem -a*
+        [DOS] Enable dangerous features
+
+þitem -c
+        Disable core dumps caused by signals and exceptions
+
+þitem -d
+        [DOS] Don't use extended memory
+
+þitem -e
+        [DOS] Redirect standard error to standard output
+
+þitem -h#
+        Set file handle limit
+
+þitem -n
+        [OS/2] Suppress exception popups
+
+þitem -o
+        [DOS] Send the register dump of an exception to stdout instead of
+        the þtt{CON} device
+
+þitem -p
+        [DOS] Don't use low memory (lower Megabyte)
+
+þitem -q
+        Quote all arguments passed to child processes
+
+þitem -s#
+        [DOS] Set stack size (KByte)
+
+þitem -t
+        Truncate file names to 8.3 format
+
+þitem -x
+        [OS/2] Don't suppress wildcard expansion and response files if the
+        `MKS Korn shell' method of passing command line arguments is
+        used
+
+þitem -C#
+        [DOS] Commit memory
+
+þitem -E
+        Run debuggee in same session
+
+þitem -K
+        Avoid using DosKillThread
+
+þitem -L
+        [DOS] Disable preloading of pages from the executable file
+
+þitem -Z
+        [DOS] Don't zero-fill pages.  This option is used for testing
+þenddescription
+þendlist
+
+þh3 Examples
+
+þexample
+emxbind \emx\bin\emxl myprog -s16384 -p
+þendexample
+
+  This example will bind þtt{myprog} and emxl.exe into myprog.exe.
+  The stack size will be set to 16384 KByte (under DOS) if this value
+  is not overridden by EMXOPT when myprog.exe is run.  The program
+  will be able to run DOS programs.  This example can be abbreviated
+  to
+
+þexample
+emxbind myprog -s16384 -p
+þendexample
+
+  To create an .exe file whose base name is different from the base
+  name of the a.out file, invoke emxbind this way:
+
+þexample
+emxbind \emx\bin\emxl myprog testprog -s16384 -p
+þendexample
+
+  This example will create þtt{testprog.exe}.  This example can be
+  abbreviated t6o
+
+þexample
+emxbind -o testprog myprog -s16384 -p
+þendexample
+
+
+þh2 Changing the type of an .exe file
+þlabel -e command
+þlabel Change the type of an .exe file
+þi2 -e command
+
+  You can change the application type after creating an .exe file with
+  emxbind.  For instance, this can be used after creating an .exe file
+  with GCC.  Exactly one of the options -f, -p and -w must be given.
+  Note that you can set the application type while creating an .exe
+  file with the -b command.
+
+  þbf{Usage:}
+
+þindent
+  þsy{emxbind -e <emxbind_options> <program_file>[.exe]}
+þendindent
+
+þlist
+þitem <emxbind_options>
+
+  The following options can be given to emxbind.  They must appear at
+  the beginning of the emxbind arguments.
+
+þdescription
+þitem -e
+
+    change the type of an .exe file
+
+þitem -f
+
+    set application type to `full screen'
+
+þitem -p
+
+    set application type to `Presentation Manager'
+
+þitem -q
+
+    don't display emxbind banner line
+
+þitem -w
+
+    set application type to `windowed'
+
+þenddescription
+
+    Exactly one of the options -f, -p and -w must be given.
+
+þitem <program_file>
+
+    path name of the bound .exe file to be changed.  The default
+    extension is .exe
+
+þendlist
+
+  Example:
+
+þexample
+gcc -o myprog.exe myprog.c
+emxbind -ep myprog
+þendexample
+
+  Alternatively, you can create a file named myprog.def containing
+
+þexample
+NAME WINDOWAPI
+þendexample
+
+  and invoke GCC with the following command line:
+
+þexample
+gcc -o myprog.exe myprog.def
+þendexample
+
+þh2 Extracting the a.out file from a bound .exe file
+þlabel Extract the a.out file from a bound .exe file
+þi2 -x command
+
+  þbf{Usage:}
+
+þindent
+  þsy{emxbind -x [<emxbind_options>] <input_file>[.exe] <output_file>}
+þendindent
+
+þlist
+þitem <emxbind_options>
+
+  The following options can be given to emxbind.  They must appear at
+  the beginning of the emxbind arguments.
+
+þdescription
+þitem -q
+
+    don't display emxbind banner line
+
+þitem -x
+
+    extract a.out file
+
+þenddescription
+
+þitem <input_file>
+
+    path name of a bound .exe file to be read.  The default extension
+    is .exe
+
+þitem <output_file>
+
+    path name of the a.out file to be created
+
+þendlist
+
+  After extracting the a.out file from an .exe file which was created
+  using a core dump file, you should not use that file for creating an
+  .exe file.  Use the -u command if you want to replace emx.exe,
+  emxl.exe or emxd.exe contained in a bound .exe file.
+
+  The relocation information is removed by emxbind while binding an
+  .exe file.  Therefore, the a.out file extracted from a bound .exe
+  file does not include relocation information.  This applies to
+  dynamic link libraries and a.out files linked with the -R option of
+  þhpt{ld}.  Import information will be lost.
+
+þh2 Displaying and changing the emx options of a bound .exe file
+þlabel Change the emx options of a bound .exe file
+þlabel Display the emx options of a bound .exe file
+þi2 -a command
+þi2 -i command
+
+  emxbind also can display or change the emx options of a bound .exe
+  file.  Note that the -i option was called -s in previous versions of
+  emxbind.
+
+  þbf{Usage (showing options):}
+
+þindent
+  þsy{emxbind -i [<emxbind_options>] <program_file>[.exe]}
+þendindent
+
+  þbf{Usage (altering options):}
+
+þindent
+  þsy{emxbind -a [<emxbind_options>] <program_file>[.exe] [<emx_options>]}
+þendindent
+
+þlist
+þitem <emxbind_options>
+
+  The following options can be given to emxbind.  They must appear at
+  the beginning of the emxbind arguments.
+
+þdescription
+þitem -a
+
+    change emx options
+
+þitem -q
+
+    don't display emxbind banner line
+
+þenddescription
+
+þitem <program_file>
+
+    path name of a bound .exe file to be read or changed,
+    respectively.  The default extension is .exe
+
+þitem <emx_options>
+
+    remove the options if empty, otherwise put these options into the
+    .exe file (see also the þhpt{-b command})
+þendlist
+
+
+þh2 Updating emx.exe in a bound .exe file
+þlabel Update emx.exe in a bound .exe file
+þi2 -u command
+
+  emxbind also can replace the DOS loader in an existing bound .exe
+  file.  You should use this only if you can't rebuild the .exe file
+  because you don't have the a.out file.  Note that you usually have
+  to re-link your program when using a new release of emx due to
+  differences in the system interface.
+
+  þbf{Usage:}
+
+þindent
+  þsy{emxbind -u [<emxbind_options>] <emx>[.exe] <program_file>[.exe]}
+þendindent
+
+þlist
+þitem <emxbind_options>
+
+  The following options can be given to emxbind.  They must appear at
+  the beginning of the emxbind arguments.
+
+þdescription
+þitem -q
+
+    don't display emxbind banner line
+
+þitem -u
+
+    replace DOS loader
+
+þenddescription
+
+þitem <emx>
+
+    path name of emxd.exe, emx.exe or emxl.exe.  This DOS loader is
+    copied to the <program_file>.  The default extension is .exe.
+
+þitem <program_file>
+
+    path name of the bound .exe file to be changed.  The default
+    extension is .exe.  Better make a backup copy of the file before
+    using þtt{emxbind -u}.
+
+þendlist
+
+
+þh2 Stripping the symbol table from a bound .exe file
+þlabel Strip the symbol table from a bound .exe file
+þi2 -s command
+þlabel -s command
+
+  emxbind can also be used to remove the symbol table from a bound
+  .exe file
+þif ipf
+  (þhpt{strip}
+þelse
+  strip.exe
+þendif
+  cannot be used on .exe files).  You can also
+  strip the symbol table while creating the .exe file by using the -s
+  option with the -b command.
+
+  þbf{Usage:}
+
+þindent
+  þsy{emxbind -s [<emxbind_options>] <program_file>[.exe]}
+þendindent
+
+þlist
+þitem <emxbind_options>
+
+  The following options can be given to emxbind.  They must appear at
+  the beginning of the emxbind arguments.
+
+þdescription
+þitem -q
+
+    don't display emxbind banner line
+
+þitem -s
+
+    strip symbol table
+
+þenddescription
+
+þitem <program_file>
+
+    path name of the bound .exe file to be changed.  The default
+    extension is .exe.  If you cannot recreate the .exe file, make a
+    backup copy of the file before using þtt{emxbind -s}.
+þendlist
+
+þi1
+
+þh2 Module definition files
+þlabel module definition file
+þlabel module definition files
+
+  emxbind reads LINK386 compatible module definition files.  In the
+  following list of available þhpt{module definition statements},
+  optional parts are enclosed in brackets.  Case is ignored for
+  keywords (though IBM says you should use upper case for keywords).
+  See below a list of þhpt{reserved words}.  You cannot use keywords
+  for function names, module names etcþ.  In case of a conflict,
+  enclose the offending name in single or double quotes.  Quotes are
+  also required if a name contains a special character such as blank,
+  tab, `@', `=', `.' or `;'.  Lines starting with a semicolon are
+  treated as comment lines and are completely ignored.  Numbers can be
+  given in decimal, octal or hexadecimal, using C syntax.
+
+þh3 Module definition statements
+þlabel module definition statements
+
+þlist
+þitem þsy{CODE ...}
+þkeyword CODE
+
+    Define default attributes for code segments.  Ignored by emxbind.
+
+þitem þsy{DATA ...}
+þkeyword DATA
+
+    Define default attributes for data segments.  Ignored by emxbind.
+
+þitem þsy{DESCRIPTION '<text>'}
+þkeyword DESCRIPTION
+
+    Put a text into the .exe or .dll file.  The text must be enclosed
+    in single or double quotes.  To include a single quote in single
+    quotes or a double quote in double quotes, simply enter the quote
+    twice.  The text will be put at the start of the nonresident name
+    table, which is put at the end of the .exe or .dll file.
+    Typically, DESCRIPTION is used to insert a copyright message.
+
+    Example:
+
+þexample
+DESCRIPTION 'HAL9000 -- Copyright (c) 2001 by Space Odyssey Inc.'
+þendexample
+
+þitem þsy{EXETYPE ...}
+þkeyword EXETYPE
+
+    Identifies the operating system.  Ignored by emxbind (the
+    operating system is always OS/2).
+
+þitem þsy{EXPORTS <entryname> [=<internalname>] [@<ordinal> [RESIDENTNAME|NONAME]]}
+þkeyword EXPORTS
+
+    Make functions and variables visible outside the .exe or .dll
+    file.  All entry points of a dynamic link library must be exported
+    using EXPORTS.  Exporting entry points of .exe files is less
+    common.
+
+    Following the EXPORTS keyword, you can enter any number of
+
+þindent
+  þsy{<entryname> [=<internalname>] [@<ordinal> [RESIDENTNAME|NONAME]]}
+þendindent
+
+    lines, one for each entrypoint.  <entryname> is the name of the
+    function as made visible outside of the .exe or .dll file.
+    <entryname> is always converted to upper case.  <internalname> is
+    the name of the function as defined in your program.  If
+    =<internalname> is omitted, it is assumed to be identical to
+    <entryname>.  <internalname> is case sensitive.  Exported
+    functions not only have a name (<entryname>), they also have an
+    ordinal number, the position within the name table.  Using ordinal
+    numbers when importing saves space and is supposed to be faster.
+    You can assign a specific ordinal number to an exported function
+    by entering @<ordinal>.  <ordinal> is the ordinal number to be
+    used (1 through 65535).  If @<ordinal> is not given, emxbind chooses an
+    unused ordinal number, but you won't know the ordinal number and
+    therefore cannot use it for importing.  If @<ordinal> is
+    specified, <entryname> is by default put into the nonresident name
+    table, which is not kept in memory while the .exe or .dll file is
+    running or loaded, respectively.  This saves space.  To put
+    <entryname> into the resident name table, enter RESIDENTNAME.
+    Then, OS/2 will keep <entryname> in memory while the .exe or .dll
+    file is running or loaded, respectively.  This saves time.
+    Example:
+
+þexample
+EXPORTS my_qsort=qsort1 @1 RESIDENTNAME
+        my_hsort
+þendexample
+
+    Use NONAME to avoid putting <entryname> into the name tables.
+    This may be required for dynamic link libraries which export many
+    functions and variables.
+
+þitem þsy{HEAPSIZE <number>}
+þkeyword HEAPSIZE
+
+    Set the size of the local heap.  <number> can be þtt{MAXVAL} as
+    well.  Ignored by emxbind.
+
+þitem þsy{IMPORTS [<internalname>=]<modulename>.<entry>}
+þkeyword IMPORTS
+
+    Define imported symbols.  Ignored by emxbind.  Use emximp
+    instead.
+
+þitem þsy{LIBRARY [<libraryname>] [<initialization>] [<termination>]}
+þkeyword LIBRARY INITGLOBAL INITINSTANCE TERMGLOBAL TERMINSTANCE
+
+    Create dynamic link library (.dll file).  If LIBRARY is used, it
+    must be the first statement of the module definition file.
+    <libraryname> is the name of the module.  The name is the first
+    entry of the resident name table and must match the base name of
+    the .dll file.  If <libraryname> is not specified, the name of the
+    output file sans directory and extension is used.
+    <initialization> can be either INITGLOBAL or INITINSTANCE.
+    INITGLOBAL causes the library initialization function to be called
+    when the DLL is initially loaded into memory.  INITINSTANCE causes
+    the library initialization function to be called each time a
+    process loads the DLL and each time a process referencing the DLL
+    is started.  <termination> can be either TERMGLOBAL or
+    TERMINSTANCE.  TERMGLOBAL causes the library termination function
+    to be called when the DLL is no longer used by any process.
+    TERMINSTANCE causes the library termination function to be called
+    each time a process frees the DLL and each time a process
+    referencing the DLL terminates.
+
+    Currently, TERMGLOBAL seems to cause the termination function not to
+    be called at all.
+
+    See þhpt{_DLL_InitTerm()} for details about the library
+    initialization function and the library termination function.
+
+    If <initialization> and <termination> are omitted, INITGLOBAL and
+    TERMGLOBAL are used.  If one of <initialization> and <termination>
+    is specified, the other one defaults to an appropriate value, as
+    shown by the following table:
+
+þexample
+                      ³ (no termination) ³ TERMGLOBAL   ³ TERMINSTANCE
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄ
+  (no initialization) ³ INITGLOBAL       ³ INITGLOBAL   ³ INITINSTANCE
+                      ³ TERMGLOBAL       ³ TERMGLOBAL   ³ TERMINSTANCE
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄ
+  INITGLOBAL          ³ INITGLOBAL       ³ INITGLOBAL   ³ INITGLOBAL
+                      ³ TERMGLOBAL       ³ TERMGLOBAL   ³ TERMINSTANCE
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄ
+  INITINSTANCE        ³ INITINSTANCE     ³ INITINSTANCE ³ INITINSTANCE
+                      ³ TERMINSTANCE     ³ TERMGLOBAL   ³ TERMINSTANCE
+þendexample
+
+    Examples:
+
+þexample
+LIBRARY
+LIBRARY INITINSTANCE
+LIBRARY mylib
+LIBRARY mylib INITINSTANCE TERMGLOBAL
+þendexample
+
+þitem þsy{NAME [<appname>] [<apptype>] [NEWFILES]}
+þkeyword NAME NOTWINDOWCOMPAT WINDOWAPI WINDOWCOMPAT NEWFILES LONGNAMES
+
+    Create an .exe file.  If NAME is used, it must be the first
+    statement.  <appname> is the name of the module.  The name is the
+    first entry of the resident name table.  If <appname> is not
+    specified, the name of the output file sans directory and
+    extension is used.  <apptype> can be one of the following
+    keywords:
+
+þdescription
+þitem NOTWINDOWCOMPAT
+
+        the program will run full-screen
+
+þitem WINDOWAPI
+
+        the program is a Presentation Manager application
+
+þitem WINDOWCOMPAT
+
+        the program will run in a text window
+
+þenddescription
+
+    The default is WINDOWCOMPAT.  <apptype> can be overridden on the
+    emxbind command line with the -f, -p and -w options.
+
+    The NEWFILES keyword (LONGNAMES is an alias) is ignored, emx
+    applications always use long file names.  Examples:
+
+þexample
+NAME WINDOWAPI
+NAME myprog
+NAME myprog NOTWINDOWCOMPAT
+þendexample
+
+þitem þsy{OLD '<library>'}
+þkeyword OLD
+
+    Preserve import information.  Ignored by emxbind.
+
+þitem þsy{PROTMODE}
+þkeyword PROTMODE
+
+    Executable runs only in protected mode.  Ignored by emxbind.
+
+þitem þsy{SEGMENTS ...}
+þkeyword SEGMENTS
+
+    Set segment attributes.  Ignored by emxbind.
+
+þitem þsy{STACKSIZE <number>}
+þlabel STACKSIZE statement
+þkeyword STACKSIZE
+
+    Set the stack size for OS/2 programs.  Always use this statement
+    as the default is too small.  The stack size should be 32768 or
+    more.  The stack size for DOS programs is controlled by the
+    þhpt{-s# emx option}.
+
+þitem þsy{STUB '<program>'}
+þkeyword STUB
+
+    Use <program> as DOS executable file.  This program is run if the
+    .exe or .dll file is started under DOS.  <program> is sought in
+    the directories listed in the EMXPATH and PATH environment
+    variables unless the filename includes a directory.  If the <emx>
+    argument is given on the emxbind command line, the STUB statement
+    is ignored.  If <emx> is not given and the STUB statement is not
+    present, þtt{\emx\bin\emxl.exe} is used.  If that file does not
+    exist, emxbind searches the directories listed in the EMXPATH and
+    PATH environment variables and the current working directory for
+    emxl.exe.  Example:
+
+þexample
+STUB 'emx.exe'
+þendexample
+þendlist
+
+
+þh3 Reserved words
+þlabel reserved words
+
+  The following words are reserved.  You cannot use them as function
+  names, module names, etc. unless enclosed in quotes.
+
+þexample
+ALIAS                    INVALID                  PHYSICAL
+BASE                     IOPL                     PRELOAD
+CLASS                    LIBRARY                  PRIVATE
+CODE                     LOADONCALL               PRIVATELIB
+CONFORMING               LONGNAMES                PROTECT
+CONTIGUOUS               MAXVAL                   PROTMODE
+DATA                     MIXED1632                PURE
+DESCRIPTION              MOVABLE                  READONLY
+DEV386                   MOVEABLE                 READWRITE
+DEVICE                   MULTIPLE                 REALMODE
+DISCARDABLE              NAME                     RESIDENT
+DOS4                     NEWFILES                 RESIDENTNAME
+DYNAMIC                  NODATA                   SEGMENTS
+EXECUTEONLY              NOEXPANDDOWN             SHARED
+EXECUTE-ONLY             NOIOPL                   SINGLE
+EXECUTEREAD              NONAME                   STACKSIZE
+EXETYPE                  NONCONFORMING            STUB
+EXPANDDOWN               NONDISCARDABLE           SWAPPABLE
+EXPORTS                  NONE                     TERMGLOBAL
+FIXED                    NONPERMANENT             TERMINSTANCE
+HEAPSIZE                 NONSHARED                UNKNOWN
+HUGE                     NOTWINDOWCOMPAT          VIRTUAL
+IMPORTS                  OBJECTS                  WINDOWAPI
+IMPURE                   OLD                      WINDOWCOMPAT
+INCLUDE                  ORDER                    WINDOWS
+INITGLOBAL               OS2
+INITINSTANCE             PERMANENT
+þendexample
+
+
+þh1 Using emx options
+þlabel Using emx options
+
+  Under DOS, emx options can be given on the emx command line:
+
+þindent
+  þsy{emx [<options>] <program> [<arguments>]}
+þendindent
+
+  where <program> is either a bound .exe file or an a.out file.
+  Options marked [*] for DOS below affect only the emx program given on
+  the command line.  All other options are `sticky' and apply to all
+  processes started by that instance of emx.  Options of this type put
+  by emxbind into the executable file are ignored when running an emx
+  program by running emx.  If you need one of these options, put them
+  on the emx command line.
+
+  Under OS/2 and DOS, emx options can also be given in the EMXOPT
+  environment variable.  These options apply to all processes.
+
+  Moreover, you can use emxbind to put emx options into the executable
+  file (see above for restrictions).  In this case, options marked [*]
+  below apply only to the program for which they have been set.  All
+  other options are `sticky' and apply to all processes started by the
+  current instance of emx (unless you are running emx manually as shown
+  above).
+
+  Options given on the emx command line override options given in
+  EMXOPT.  Options given in EMXOPT override options stored in the
+  executable file.
+
+  The following emx options are available:
+
+þdescription
+þitem -a*
+
+     [DOS*] Enable dangerous features: -ac makes data and the stack
+     executable, -am enables þhpt{_memaccess()}, -aw enables write
+     access to all memory areas, -ai enables þhpt{_portaccess()}.  By
+     default, only the .text section is executable, _memaccess() and
+     _portaccess() are disabled.  You can combine letters: for
+     instance, -aim enables both _memaccess() and _portaccess(), -aciw
+     enables all dangerous features.  Note: -ac is automatically set
+     in programs run with P_DEBUG mode of þhpt{spawn*()}.  This is
+     used to be able to call functions of the debuggee by putting code
+     into the stack.
+
+þitem -c
+
+     [*] Disable core dumps caused by signals.  Core dumps created by
+     þhpt{_core()} are not disabled by -c.
+
+þitem -d
+
+     [DOS] Don't use extended memory.  Only low memory (below 1 MByte)
+     will be used.  Use this if you suspect a bug in the extended
+     memory management of emx or a bug in an extended memory manager.
+
+þitem -e
+
+     [DOS*] Redirect the standard error handle (2) to standard output
+     (1)
+
+þitem -h#
+þlabel -h# emx option
+
+     [DOS, OS/2*] Set file handle limit.  Under DOS, the DOS file
+     handle limit for the emx process is set to þsy{#}.  The number
+     þsy{#} must be between 10 and 255.  This option is ignored for
+     DOS versions earlier than 3.30.  This option does not change the
+     emx limit for the number of files per process -- that limit is
+     always 40.  Under OS/2, the file handle limit for the current
+     process is set to þsy{#}.  The number þsy{#} must be between 10
+     and 65536.
+
+þitem -m#
+
+     [DOS] Select machine.  -m1 selects Fujitsu FMR70 (not implemented
+     yet), -m2 selects NEC PC-98 (not implemented yet), -m3 selects
+     Inboard 386/PC.
+
+þitem -o
+
+     [DOS] Send the register dump of an exception to stdout.  Without
+     -o, the register dump is sent to the CON device.  You need -o for
+     redirecting the register dump to a file.
+
+þitem -p
+
+     [DOS] Don't use low memory (lower Megabyte); use this if the
+     program runs a DOS program; not required for running emx programs
+     (either a.out and bound .exe) unless command.com is called to run
+     the programs (as done by the þhpt{system()} library function).
+     If -p is not given, low memory will be used and there won't be
+     enough low memory for running DOS programs.
+
+þitem -q
+
+     [*] All command line arguments passed to child processes will be
+     quoted unconditionally, that is, wildcard expansion and response
+     files won't work in child processes of processes for which the -q
+     option is in effect.
+
+þitem -r*
+
+     [*] Prepend drive letter * to absolute path names.  If a path
+     name starts with þtt{/} but does not start with þtt{//},
+     þtt{/dev/} or þtt{/pipe/}, * followed by a colon will be
+     prepended.  If -rd has been given, the filename þtt{\mydir\abc}
+     will be translated to þtt{d:\mydir\abc}.  Note: this option can
+     cause unexpected effects.
+
+þitem -s#
+þlabel -s# emx option
+
+     [DOS*] Set stack size (KByte), minimum: -s8, maximum: -s524288,
+     default: -s8192.  Note that under DOS, the heap and the stack
+     share the same memory area.  The pages not used by the stack are
+     available for the heap.  Therefore, you should use -s# if you
+     need more than 8 MByte of heap and stack.
+
+þitem -t
+
+    [*] Truncate file names to 8.3 format.  Each part of a pathname is
+    truncated to 8.3 format by taking the first 8 characters before
+    the dot and the first 3 characters after the dot.  This is useful
+    to compile programs on a FAT filesystem with minimal changes.
+
+    Without argument, -t enables truncation on all drives and for UNC
+    pathnames.
+
+    The -t option takes an optional argument, listing the names of the
+    drives on which file names should be truncated.  The special drive
+    name `þtt{/}' controls whether to truncate UNC pathnames.  With
+    `þtt{-tc/}', for instance, file names on drive C and UNC pathnames
+    will be truncated.
+
+    If the argument of the -t option is `þtt{-}', truncation is
+    disabled for all drives and for UNC pathnames.  This is the
+    default setting.  If the argument starts with `þtt{-}', truncation
+    is disabled on all drives listed.  With `þtt{-t -t-d}', for instance,
+    UNC pathnames and file names on all drives except
+    drive D will be truncated.
+
+þitem -x
+
+     [OS/2] Don't suppress wildcard expansion and response files if
+     the `MKS Korn shell' method of passing command line arguments is
+     used.
+
+þitem -C#
+þlabel -C# emx option
+
+     [DOS*] Commit memory.  By default, memory is allocated as soon as
+     a page is accessed.  If there isn't enough memory (and swap
+     space), the process is terminated.  With -C#, memory is allocated
+     when creating the process and when enlarging the data segment
+     with þhpt{brk()} and þhpt{sbrk()}.  If there isn't enough memory
+     (and swap space), the process brk(), sbrk(), þhpt{malloc()}
+     etc. return an error.  The number þsy{#} specifies how many KByte
+     should be allocated for the stack.  If þsy{#} is omitted, 0 is
+     used.  The -C# option is not yet completely implemented -- if an
+     allocation request succeeds partly, the allocated pages are not
+     freed.
+
+þitem -E
+
+     [OS/2*] Run debuggee in same session.  By default, a debugger for
+     emx (such as GDB) runs the child process in a separate session.
+     The P_NOSESSION flag of þhpt{spawn*()} has the same effect as
+     -E.
+
+     [DOS] Don't check for 387 coprocessor.  Assume no coprocessor is
+     present.  This option is used for testing.
+
+þitem -F
+
+     [DOS] Use fast A20 switching.  By default, the standard method
+     for switching A20 is used.  A faster method is available on some
+     machines.  That method will be used if the -F option is present.
+
+þitem -K
+
+     [OS/2*] Don't use DosKillThread.  Due to bugs in OS/2,
+     DosKillThread may cause problems.  emx.dll automatically avoids
+     using DosKillThread for OS/2 2.1 and older.  For OS/2 2.11 and
+     later, you can use the -K option to disable usage of
+     DosKillThread.  Currently, DosKillThread is not used by emx.dll
+     and this option does not have any effect.
+
+þitem -L
+
+     [DOS*] Disable preloading of pages from the executable file.  By
+     default, the complete code and data areas are read into memory
+     before a program is started.  If there is not enough memory, no
+     pages are preloaded.  With -L (or if not enough memory is
+     available), pages are loaded as soon as they are accessed.
+
+þitem -O
+
+     [DOS] Override XMS version check.  By default, emx checks for XMS
+     version number 2.00 or later and for XMS driver revision 2.06 or
+     later, as older himem.sys drivers don't work correctly.  You can
+     override this check by giving the -O option (for drivers using a
+     different revision numbering scheme), but emx may not work with
+     your XMS driver, anyway.  Actually, emx has not been tested with
+     himem.sys 2.05; 2.04 fails, 2.06 works.
+
+þitem -P
+
+     [DOS] Use patched code for A20 switching.  There is a patch area
+     in emx.exe where you can put alternate code for switching A20.
+     The -P option enables the code in the patch area.
+
+þitem -S#
+
+     [DOS] Enable the þhpt{emx kernel debugger}.  Use the -S option to
+     operate the debugger through the keyboard and display.  If you
+     want to debug using a terminal, enter -S1 to use COM1, -S2 to use
+     COM2.
+
+þitem -V
+
+     Display emx version.  On program start, the emx version will be
+     displayed.
+
+þitem -Z
+
+     [DOS*] Don't zero-fill pages.  This option is used for testing.
+
+þenddescription
+
+þh1 More emx utilities
+
+þif ipf
+
+þdescription
+þitem þhpt{emxaout}
+
+  Convert .obj files to .o files
+
+þitem þhpt{emxcat}
+
+  Concatenate source files
+
+þitem þhpt{emxexp}
+
+  Create export list from object files and libraries
+
+þitem þhpt{emximp}
+
+  Create import libraries
+
+þitem þhpt{emxload}
+
+  Preload executables to speed up compilation
+
+þitem þhpt{emxomf}
+
+  Convert .o files to .obj files
+
+þitem þhpt{emxomfar}
+
+  Manage .lib files
+
+þitem þhpt{emxomfld}
+
+  Call LINK386 like ld
+
+þitem þhpt{emxrev}
+
+  Display emx revision index
+
+þitem þhpt{emxtsf}
+
+  Create .tsf files for TRCUST
+
+þitem þhpt{listomf}
+
+  List an .obj or .lib file
+
+þitem þhpt{updt}
+
+  Update files
+
+þenddescription
+þendif
+
+þh2 emxaout
+þlabel emxaout
+þindex emxaout
+þkeyword emxaout
+
+  The emxaout tool converts OMF object files (.obj files) to a.out
+  object files (.o files).  The converted files can be used with the
+  Unix-style linker þhpt{ld}.  By using emxaout, you can create .o
+  files with MASM 6.0.
+
+þindent
+  þsy{emxaout [-u] [-o <output_file>] <input_file>}
+þendindent
+
+  Convert the OMF file <input_file> to a.out format.  The default
+  extension for <input_file> is .obj.  If the -o option is used, the
+  a.out file is written to <output_file>.  Otherwise, the name of the
+  output file is constructed by replacing the extension of
+  <input_file> with .o.
+
+  The following option is available:
+
+þlist
+þitem -u
+
+    Don't add leading underscores to symbol names.  By default,
+    emxaout prepends an underscore to every symbol name.
+
+    When using the þtt{PROC C}, þtt{PROTO C} and þtt{EXTERNDEF C}
+    directives of MASM 6.0, you should use the -u option of emxaout
+    because MASM prepends an underscore to symbols defined with those
+    directives.
+
+þendlist
+
+  The OMF file must have 32-bit OS/2 format, that is, you should use
+  the following MASM directives:
+
+þexample
+.386
+.MODEL FLAT
+þendexample
+
+  emxaout discards debugging information.
+
+
+þh2 emxcat
+þlabel emxcat
+þindex emxcat
+þkeyword emxcat
+
+  The emxcat tool concatenates assembler or C source files.  This is
+  used for building emxwrap.dll.
+
+þindent
+  þsy{emxcat [-D<symbol>]... -o <output_file> <input_file>...}
+þendindent
+
+  All the þsy{<input_file>}s are concatenated and written to
+  <output_file>.  If the output file is included in the input files,
+  it is not copied; emxcat simply compares the filenames, therefore
+  it's possible to fool emxcat and make it copying until the disk is
+  full.
+
+  Your code should not depend on the order in which the files are
+  copied to the output file.  A different version of emxcat may copy
+  the files files in a different order.
+
+  At the very beginning of the output file, the symbols given on the
+  command line are defined.  Note that there must not be a space
+  between -D and the name of the symbol.
+
+  #include statements are collected at the start of the output file.
+  The (partial) order of the include files is maintained.  If there is
+  an inconsistency in the order of include files in different input
+  files, emxomf prints a warning message.  For instance, this happens
+  for the following three input files:
+
+þexample
+/* file1.c */
+#include "a.h"
+#include "b.h"
+
+/* file2.c */
+#include "b.h"
+#include "c.h"
+
+/* file3.c */
+#include "c.h"
+#include "a.h"
+þendexample
+
+  The statement
+
+þexample
+#include <sys/emx.h>
+þendexample
+
+  is treated specially: it always precedes all other #include
+  statements if present in one of the input files.  (The
+  þtt{<sys/emx.h>} header no longer exists; it had to be included
+  before any other headers.)
+
+  When concatenating .s files, lines starting with þtt{CONST_} are
+  omitted if already copied to the output file -- only the first
+  instance is retained.
+
+  All macros þtt{#define}d by an input file are #undefined after
+  copying the input file.  Constants starting with þtt{INCL_} are an
+  exception and are collected at the start of the output file, before
+  the #include statements.
+
+  emxcat leaves alone #define and #include statements which do not
+  start at the first column of the line.  If you put blanks before
+  #define and #include, emxcat copies these statements to the output
+  file without treating them specially.
+
+
+þh2 emxexp
+þlabel emxexp
+þindex emxexp
+þkeyword emxexp
+
+  The emxexp tool creates an export list for a module definition file
+  from object files and libraries.  This is used for building dynamic
+  link libraries written in C++.
+
+þindent
+  þsy{emxexp [-n] [-u] [-o[<ordinal>]] <input_file>...}
+þendindent
+
+  For each public symbol (except for uninitialized variables unless
+  the -u option is given) of the
+  input files (which can be .o, .a, .obj or .lib files), emxexp prints
+  to the standard output an export definition for the EXPORTS
+  statement of a module definition file.  For mangled names, a comment
+  is generated which shows the demangled name.  The following options
+  are available:
+
+þlist
+þitem þsy{-n}
+
+  Add the NONAME keyword to each export definition to keep LINK386
+  from putting the name into the name tables.  This is required for
+  dynamic link libraries which export too many names.
+
+þitem þsy{-o[<ordinal>]}
+
+  Add ordinal numbers to the export definitions.  If <ordinal> is
+  given, ordinal numbers will start with that number.  Otherwise,
+  ordinal numbers will start with 1.
+
+þitem þsy{-u}
+
+  Also export unitialized variables.  Each uninitialized variable
+  encountered in the input files is exported only once.  If you
+  concatenate export lists created by multiple runs of emxexp, you
+  have to remove duplicate exports of uninitialized variables
+  yourself.  Therefore, it is recommended to give all the input files
+  on the command line of a single emxexp invocation.  By default,
+  uninitialized variables are not exported.
+
+þendlist
+
+
+þh2 emximp
+þlabel emximp
+þlabel (I1)
+þlabel (I2)
+þindex emximp
+þkeyword emximp
+
+  emximp manages files required for importing functions from dynamic
+  link libraries.
+
+  Three different methods for importing are used for the two methods
+  of creating executable files.  When using ld and emxbind, there are
+  two methods for importing:
+
+þdescription
+þitem (I1)
+
+      The import library contains a small piece of code for each
+      function which loads the AL register with the number of argument
+      words and jumps to the imported function.  Information on
+      imported functions is stored in tables in the text segment of
+      the program.  þhpt{emxbind} reads these tables to create
+      appropriate fixups in the .exe file.  When an imported function
+      is called while running the resulting program under DOS, an
+      error message will be displayed and the program will be
+      terminated.  Data cannot be imported with method (I1).  You have
+      to use the -R option of þhpt{ld}.
+
+þitem (I2)
+
+      The import library does not contain code for import definitions.
+      Instead, it contains special symbol table entries, which are
+      copied to the a.out file.  One of these entries makes ld create
+      a relocatable output file.  emxbind reads the symbol table and
+      creates appropriate fixups in the .exe file.  The AL register
+      isn't loaded with the number of argument words.  The program
+      will be aborted (protection violation) when an imported function
+      is called under DOS.  The -R option of ld is automatically
+      turned on when referencing an import definition of type (I2).
+
+þenddescription
+
+  When using emxomf and LINK386, the standard OS/2 method is used:
+
+þdescription
+þitem (I3)
+
+      LINK386 reads a .lib import library or a module definition file
+      to create appropriate fixups.  The AL register isn't loaded with
+      the number of argument words.  The program won't run under DOS.
+
+þenddescription
+
+  Methods (I2) and (I3) are recommended unless the dynamic link
+  library requires the AL register to be loaded with the number of
+  argument words.  os2.a uses method (I2).
+
+  emximp is used to create appropriate files for all these methods.
+  Information on functions exported by dynamic link libraries is
+  provided in emx import list files.
+
+  The following table summarizes the features of the three methods:
+
+þexample
+Method               ³  (I1)  ³   (I2)  ³   (I3)
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄ
+Linker               ³  ld    ³   ld    ³ LINK386
+Import by name       ³  YES   ³   NO    ³ YES
+Load AL register     ³  YES   ³   NO    ³ NO
+Code overhead        ³  YES   ³   NO    ³ NO
+Catch call under DOS ³  YES   ³   NO    ³ NO
+Import library type  ³ .o .a  ³   .a    ³ .lib .def
+Can import functions ³  YES   ³   YES   ³ YES
+Can import data      ³  NO    ³   YES   ³ YES
+Additive fixups      ³  NO    ³   YES   ³ YES
+Linker options       ³  -R    ³         ³
+þendexample
+
+þipfminitoc
+
+þh3 What is an emx import list file?
+
+  An emx import list file defines how functions can be imported from
+  dynamic link libraries.  For each function, the import list file
+  defines the name of the function, the module name (that's the name
+  of the dynamic link library exporting the function), either the
+  ordinal number or the name of the function as exported by the
+  dynamic link library, and the number of argument 32-bit words
+  expected by the function (this is the number of arguments unless
+  structures are passed by value).
+
+  For method (I1), emximp is used to turn an import list file into an
+  .a import library which can be linked to a program using the
+  þhpt{ld} linker.  emximp either creates assembler source files (.s)
+  or automatically calls the assembler to create object files (.o).
+  The object files can be packed into a library with the þbf{ar}
+  program.
+
+  For method (I2), emximp is used to turn an import list file (.imp
+  file), an OMF import library (.lib file), or a module definition
+  file (.def file) directly into an .a import library which can be
+  linked to a program using the ld linker.
+
+  For method (I3), emximp can convert an import list file into a
+  module definition file or an OMF import library.  emximp can also
+  convert a module definition file (.def file) into an OMF import
+  library.
+
+  Comments in an import list file are started with a semicolon.  Empty
+  lines are ignored.
+
+  For each function you have to put one line into the import list
+  file. Here's an example of an import list file:
+
+þexample
+; myimport.imp
+DosStartTimer       doscalls 351 3
+DosStopTimer        doscalls 290 1
+þendexample
+
+  Such a line consists of four components which are separated by one
+  or more blanks.  The first word is the name of the function, as used
+  in C programs.  The second word is the name of the DLL.  The third
+  word is either the ordinal number of the DLL entry or the name of
+  the DLL entry.  You have to use ordinal numbers for OS/2 API
+  functions.  The fourth word is the number of 32-bit words of
+  arguments expected by the function.  This is the number of arguments
+  unless structures are passed by value.
+
+  A question mark used as forth word is equivalent to using the number
+  0.  A question mark should be used if the number of arguments is
+  unknown or if the entry point is not a function (data can also be
+  exported).  Using a question mark causes a warning when creating
+  files for method (I1).
+
+  An þtt{R} used as forth word causes the AL register not to be loaded
+  with method (I1) -- this is used for functions which expect an
+  argument in the EAX register.
+
+  An þtt{F} used as forth word specifies a 16-bit function.  emximp
+  adds _16_ in front of the function name to notify þhpt{emxbind} and
+  þhpt{emxomf} of the 16-bitness of the function.  References to
+  symbols starting with _16_ are fixed up by 16:16 far pointers.
+
+
+þh3 Creating an emx import list file from an OMF import library
+
+  To create an emx import list file from an OMF import library, type
+
+þindent
+  þsy{emximp -o <output_file>.imp <input_file>.lib ...}
+þendindent
+
+  <output_file> is the name of the emx import list file to be
+  created.  The name must end with .imp.  <input_file> is the name of
+  an existing import library file.  The name must end with .lib.  You
+  can give one or more input filenames on the command line.
+
+  As the number of argument words of the functions cannot be derived
+  from the import library, a question mark instead of a number for the
+  number of argument words is written to the import list file.
+
+  When encountering a module with static code or data, emximp displays
+  a warning message.
+
+þh3 Creating an emx import list file from a module definition file
+
+  To create an emx import list file from a module definition file, type
+
+þindent
+  þsy{emximp -o <output_file>.imp <input_file>.def ...}
+þendindent
+
+  <output_file> is the name of the emx import list file to be created.
+  The name must end with .imp.  <input_file> is the name of an
+  existing module definition file.  The name must end with .def.  You
+  can give one or more input filenames on the command line.
+
+  As the number of argument words of the functions cannot be derived
+  from the module definition file, a question mark instead of a number
+  for the number of argument words is written to the import list
+  file.
+
+
+þh3 Creating an emx import library for method (I1)
+
+  To create an emx import library for method (I1), type
+
+þindent
+  þsy{emximp [-a<assembler>] [-b<base_name>|<prefix_length>] [-p<module>]...} þbreak
+  þsy{       [-s] <input_file>.imp ...}
+þendindent
+
+  <input_file> is the name of the import list file.  The name must end
+  with .imp.  You can give one or more input filenames on the command
+  line.
+
+  The names of the output files are either taken from the import list
+  file or automatically generated by emximp.  A line in starting with
+  `+' starts a new assembly language file or object file (module).
+  The name of the output file is given after the `+':
+
+þexample
++os2mem1.s          ; start a new output file
+þendexample
+
+  This feature is used only for method (I1).  All the functions
+  defined in one module are linked if at least one of the functions is
+  referenced.
+
+  It's possible to let emximp automatically write one file per
+  function.  The output filenames are constructed by appending the
+  ordinal number or a sequential number to a fixed prefix or to a
+  prefix of the DLL name.  To let emximp automatically choose output
+  filenames, use the -b command line option.  If -b is given, the
+  import list file must not contain lines starting with `+'.  The
+  argument of the -b option is either a number or a string.  If the
+  argument is a string, that string is used as base name of the output
+  files.  If the argument is a number, that many characters are taken
+  from the start of each DLL name to create the base name of the
+  output file.  A number is appended to the base name.  If -s is
+  given, a sequential number is appended, starting with the number 1.
+  The number is incremented for each output file.  If -s is not given,
+  the ordinal number of the function is appended; giving entry names
+  instead of ordinal numbers in the import list file is not allowed
+  for that reason.  Note that appending ordinal numbers to the names
+  may cause problems (output for different functions written to the
+  same file) if multiple DLLs are used in the import list file and the
+  argument of the -b option is a string (or too small a number to make
+  the prefixes unique).  These problems also occur if the import list
+  file defines multiple functions to refer to the same entry point.
+  The extension of the output files is .o if the -a option is used, .s
+  otherwise.
+
+  By default, emximp creates assembler source files.  emximp can
+  automatically call an assembler to assemble the output files.  This
+  feature is turned on by the -a command line option.  The argument of
+  the -a option is the name of the assembler (there must be no blanks
+  between -a and the argument).  If the argument is omitted,
+  þtt{as.exe} is used.  The default extension is .exe, the program
+  will be sought in the directories listed in the PATH environment
+  variable.
+
+  The object files will have the same name as the assembler source
+  files, with the .s extension replaced by .o.
+
+  Under OS/2, the assembly language files are not actually written, a
+  pipe is used instead.  Under DOS, the assembly language files
+  created by emximp will be deleted automatically after running the
+  assembler.
+
+  To save space in the executable file, DLL names which are often used
+  should be put into separate files, see above for an example.  Use
+  the -p option of emximp to use separate files for the DLL names.
+  The argument of the -p option is the name of the DLL.  emximp
+  prepends þtt{__os2_} to the DLL name for making the label used for
+  referencing the DLL name.  You can use multiple -p options.  Here's
+  how to write a separate file which defines a DLL name:
+
+þexample
+        .globl  __os2_pmgpi
+        .text
+__os2_pmgpi:
+        .asciz  "PMGPI"
+þendexample
+
+  This file declares the DLL name PMGPI.  Use the þtt{-p pmgpi} option
+  of emximp to tell emximp to create code that references this file.
+
+
+  þbf{Technical details:}
+
+  Let's examine the .s file created by emximp for the DosSelectSession
+  function.
+
+þexample
+1)              .globl  _DosSelectSession
+2)              .align  2, 144
+3)      _DosSelectSession:
+4)              movb    $1, %al
+5)      1:      jmp     __os2_bad
+6)      2:      .long   1, 1b+1, L1, 38
+7)      L1:     .asciz  "sesmgr"
+8)              .stabs  "__os2dll", 23, 0, 0, 2b
+þendexample
+
+  Line 1 is obvious: it exports _DosSelectSession from os2.a so
+  that þhpt{ld} will link this module when _DosSelectSession is
+  referenced.
+
+  Line 2 is a speed hack: the 386 performs much better when jumping to
+  an address which is an integral multiple of 4.
+
+  Line 3 declares _DosSelectSession.  Your program calls this code
+  when calling DosSelectSession.
+
+  Line 4 stores the number of arguments in the AL register (or rather,
+  the number of argument 32-bit words).
+
+  Line 5 jumps to __os2_bad which displays an error message and stops
+  execution.  This is what happens if you run the program on DOS.
+
+  Line 6 creates a small table which is read by þhpt{emxbind}: It
+  consists of four words:
+
+þitemize
+þitem
+
+   a word of flag bits.  Currently, only bit 0 is defined: it's 0 for
+   import by name, 1 for import by ordinal.
+
+þitem
+
+   the address of the word to be fixed up for referencing the DLL.
+   `þtt{1b+1}' means `local label 1, looking backwards, add one to
+   address'.  Therefore, the address used by the þtt{JMP} instruction
+   is used.
+
+þitem
+
+   a pointer to the name of the module (null-terminated ASCII string).
+   For often used names the pointer should point to a string in a
+   separate, common module to save space, see the -p option.
+
+þitem
+
+   the ordinal number or a pointer to the name of the entry point
+   (null-terminated ASCII string), respectively, depending on bit 0 of
+   the flags word.
+
+þenditemize
+
+  Line 7 defines the module name pointed to by the table.
+
+  Line 8 is the tricky part: it contains a special symbol table entry
+  to make ld build a table named __os2dll which contains pointers to
+  all the small tables (þtt{2b} is the address of the small table).
+  See also crt0.s, where the table is initialized.  crt0 contains a
+  pointer to the table in a fixed location so that emxbind can find
+  the table of pointers, read all the small tables (as described
+  above) and create the necessary OS/2 fixups.
+
+
+þh3 Creating an a.out import library for method (I2)
+
+  To create an a.out import library for method (I2), type
+
+þindent
+  þsy{emximp [-m] -o <output_file>.a <input_file>.def ...} þbreak
+  þsy{emximp [-m] -o <output_file>.a <input_file>.imp ...} þbreak
+  þsy{emximp [-m] -o <output_file>.a <input_file>.lib ...} þbreak
+þendindent
+
+  <output_file>.a is the name of the archive file to be created.  The
+  name must end with .a.
+
+  <input_file>.def is the name of a module definition file containing
+  one or more EXPORTS statements.
+
+  <input_file>.imp is the name of an emx import list file.  The name
+  must end with .imp.
+
+  <input_file>.lib is the name of an import library (OMF).  The name
+  must end with .lib.  Modules in the input files which are not import
+  definitions are ignored.
+
+  You can give one or more input filenames on the command line; all
+  input file must be of the same type, either .imp or .lib.
+
+  All import records of the input files are converted to import
+  modules for method (I2).  After creating the output file, you should
+  run þtt{ar s} on the output file to increase linking efficiency.
+
+  When encountering a module with static code or data in a .lib file,
+  emximp displays a warning message.  You may have to extract those
+  modules from the library, convert them with þhpt{emxaout}, and add
+  them to the target library with þhpt{emxomfar}.
+
+  The -m option directs emximp to add code which calls the
+  þtt{_mcount} function.  This is used for profiling; þtt{os2_p.a} is
+  created with the -m option of emximp.
+
+  þbf{Technical details:}
+
+  A member named __.IMPORT is added to the archive.  GNU þhpt{ld} (the
+  one ported to emx) has been patched to turn on relocatable output if
+  it finds a member named __.IMPORT in a library.  As only the
+  __.SYMDEF member is scanned if present, __.IMPORT defines the
+  special symbol þtt{__IMPORT!}.  When patched GNU ld finds the
+  definition of a symbol named þtt{__IMPORT!} in the __.SYMDEF member,
+  relocatable output is turned on.  (Relocatable output can also be
+  turned on by using the -R option of þbf{ld}.)
+
+  For each function in the input files, emximp adds an a.out-type
+  module to the output file.  Such a module defines two symbols
+  (unless the -m option is used).  One symbol defines the entry point,
+  the other symbol gives information on the DLL name and the ordinal
+  number or procedure name.  For instance, for
+
+þexample
+LIBRARY doscalls
+EXPORTS DosBeep @286
+þendexample
+
+  the two symbols `þtt{_DosBeep}' and `þtt{_DosBeep=doscalls.286}' are
+  defined.  The symbol types 0x69 and 0x6b are used, respectively.
+  GNU ld has been patched to keep references to symbols of type 0x69
+  in the relocation table.
+
+  þhpt{emxbind} scans the relocation table for references to symbols
+  of type 0x69 and scans the symbol table for a matching symbol of
+  type 0x6b which defines the entry point.
+
+þh3 Creating an OMF import library for method (I3)
+
+  To create an OMF import library for method (I3), use one of the
+  following invokations of emximp, depending on the input format:
+
+þindent
+  þsy{emximp [-p#] -o <output_file>.lib <input_file>.def ...} þbreak
+  þsy{emximp [-p#] -o <output_file>.lib <input_file>.imp ...}
+þendindent
+
+  <output_file>.lib is the name of the import library file to be
+  created.  The name must end with .lib.
+
+  <input_file>.def is the name of a module definition file containing
+  one or more EXPORTS statements.
+
+  <input_file>.imp is the name of an emx import list file.
+
+  You can give one or more input filenames on the command line.
+
+  All the import list files must define functions that are in the same
+  dynamic link library.  Lines start with `+' are ignored.
+
+  The number of argument words is lost after that conversion, that is,
+  you cannot recreated the import list file using emximp.
+
+  The -p# option sets the page size to # bytes (16, 32, 64, ...,
+  32768).  If -p is not given, a page size of 16 bytes will be used.
+  Increase the page size if emximp complains about too big a library.
+  If emximp doesn't complain, you shouldn't increase the page size to
+  save disk space.
+
+þh3 Creating a module definition file for method (I3)
+
+  To create a þhpt{module definition file} for method (I3), type
+
+þindent
+  þsy{emximp -o <output_file>.def <input_file>.imp ...}
+þendindent
+
+  <output_file> is the name of the module definition file to be
+  created.  The name must end with .def.
+
+  <input_file> is the name of an emx import list file.  The name must
+  end with .imp.  You can give one or more input filenames on the
+  command line.
+
+  All the import list files must define functions that are in the same
+  dynamic link library.  Lines start with `+' are ignored.
+
+  The number of argument words is lost after that conversion, that is,
+  you cannot recreated the import list file using emximp.
+
+
+þh3 emximp options
+
+  The -q option suppresses warnings about `impure' import libraries,
+  that is, import libraries which also contain code.
+
+
+þh2 emxload
+þlabel emxload
+þindex emxload
+þkeyword emxload
+
+  The emxload tool preloads OS/2 programs.  Preloading programs speeds
+  up loading these programs if you have enough memory.  If you have
+  too little memory, preloading may degrade performance.  Preloading
+  is especially useful with a compiler such as GCC which runs many
+  processes to complete its task.
+
+  emxload starts the emxload server process (emxload.exe contains both
+  the client program described here and the server program).  The
+  server process runs until stopped with the -q option of emxload.
+
+  When using emxload to load a program which is already preloaded by
+  emxload, the expiry time of that program will be reset to the new
+  value.
+
+  There are library functions for using the emxload server in your
+  programs.  See þhpt{_emxload_prog()} etc. for details.
+
+  The GNU C compiler keeps itself in memory for þpa{N} minutes if the
+  environment variable GCCLOAD is set to þpa{N}.  For example, to keep
+  the passes of GCC in memory for 5 minutes, type
+
+þexample
+SET GCCLOAD=5
+þendexample
+
+  The following programs use GCCLOAD: gcc.exe, cpp.exe, cc1.exe,
+  cc1plus.exe, cc1obj.exe, as.exe, and emxomf.exe.
+
+
+þindent
+ þsy{emxload [-m<limit>] [-s<limit>] [-e] [-u[w]]} þbreak
+ þsy{        [-gcc] [-g++] [-gobjc] [-gnat] [-omf] <program>...}
+þendindent
+
+  All the þsy{<program>}s are preloaded.  The default extension is
+  .exe.  There are shortcuts for preloading the GNU C compiler:
+
+þlist
+þitem þsy{-gcc}
+
+  This option preloads the complete GNU C compiler for compiling C
+  programs and generating a.out-style output.  The following programs
+  will be preloaded: þtt{gcc.exe}, þtt{cpp.exe}, þtt{cc1.exe},
+  þtt{as.exe}, þtt{ld.exe}, and þtt{emxbind.exe}.
+
+þitem þsy{-g++}
+
+  This option preloads the complete GNU C compiler for compiling C++
+  programs and generating a.out-style output.  The following programs
+  will be preloaded: þtt{gcc.exe}, þtt{cpp.exe}, þtt{cc1plus.exe},
+  þtt{as.exe}, þtt{ld.exe}, and þtt{emxbind.exe}.
+
+þitem þsy{-gobjc}
+
+  This option preloads the complete GNU C compiler for compiling
+  programs written in the Objective C programming language and
+  generating a.out-style output.  The following programs
+  will be preloaded: þtt{gcc.exe}, þtt{cpp.exe}, þtt{cc1obj.exe},
+  þtt{as.exe}, þtt{ld.exe}, and þtt{emxbind.exe}.
+
+þitem þsy{-gnat}
+
+  This option preloads the complete GNU Ada translator (GNAT) for
+  generating a.out-style output.  The following programs
+  will be preloaded: þtt{gcc.exe}, þtt{gnat1.exe},
+  þtt{as.exe}, þtt{ld.exe}, þtt{gnatbind.exe}, and þtt{emxbind.exe}.
+
+þitem þsy{-omf}
+
+  Use this option in addition to one of the options for preloading GCC
+  to preload the programs used for generating OMF-style output.  The
+  following programs will be preloaded: emxomf.exe, emxomfld.exe,
+  and þtt{link386.exe}.
+
+þendlist
+
+  You can use one or more of the above options.  For instance, if you
+  want to compile C and C++ programs, use
+
+þexample
+emxload -gcc -g++
+þendexample
+
+  This will preload þtt{gcc.exe}, þtt{cpp.exe}, þtt{cc1.exe},
+  þtt{cc1plus.exe}, þtt{as.exe}, þtt{ld.exe}, and þtt{emxbind.exe}.
+
+  There are additional options for controlling the operation of emxload:
+
+þlist
+þitem -m<limit>
+
+  Automatically unload the specified programs after þsy{<limit>}
+  minutes.  This option overrides the -s<limit> option.  By default,
+  programs are unloaded after 10 minutes.
+
+þitem -s<limit>
+
+  Automatically unload the specified programs after þsy{<limit>}
+  seconds.  This option overrides the -m<limit> option. By default,
+  programs are unloaded after 600 seconds.
+
+þitem -e
+
+  Don't unload the specified programs automatically.  This option
+  overrides the -m<limit> and -s<limit> options.  By default, emxload
+  unloads a program after 10 minutes.
+
+þitem -u
+
+  Unload the specified programs.  By default, emxload preloads the
+  specified programs.  With the -u option, all specified programs will
+  be unloaded.  Don't wait until the server has unloaded the programs.
+
+þitem -uw
+
+  Like -u, but wait until the server has unloaded the programs.
+
+þendlist
+
+  Two special calling sequences are available:
+
+þindent
+ þsy{emxload -l}
+þendindent
+
+  List the preloaded programs with the number of minutes and seconds
+  left until automatic unloading.
+
+þindent
+ þsy{emxload -q[w]}
+þendindent
+
+  Stop the emxload server process.  All preloaded programs will be
+  unloaded.  Use -qw to wait until the server is stopped.  -q doesn't
+  wait.
+
+
+þh2 emxomf
+þlabel emxomf
+þindex emxomf
+þkeyword emxomf
+
+  The emxomf tool converts a.out object files (.o files) to Object
+  Module Formats (.obj files).  The converted files can be used with
+  the OS/2 linker link386.exe.
+
+  emxomf keeps itself in memory for þpa{N} minutes if the environment
+  variable GCCLOAD is set to þpa{N}.
+
+þindent
+  þsy{emxomf [-d] [-l[<symbol>]] [-g] [-q] [-s] [-u] [-p <page_size>]} þbreak
+  þsy{       [-m <symbol>] [-i <default_lib>] [-I <idmdll>] [-D <dataseg>]} þbreak
+  þsy{       -o <output_file> <input_file>}
+þendindent
+
+  Convert a single .o or .a file (<input_file>) to an .obj or .lib
+  file (<output_file>).  There are no default extensions.  If the -d
+  option is given, the input file is deleted after successful
+  conversion.  If the input file is an archive, it is not deleted.
+
+þindent
+  þsy{emxomf [-d] [-l[<symbol>]] [-g] [-q] [-s] [-u] [-x] [-p <page_size>]} þbreak
+  þsy{       [-m <symbol>] [-O <directory>] [-r|R<response_file>]} þbreak
+  þsy{       [-i <default_lib>] [-I <idmdll>] [-D <dataseg>] <input_file>...}
+þendindent
+
+  Convert multiple .o and .a files to .obj and .lib files (more than
+  one <input_file> can be given on the command line).  The names of
+  the output files are constructed by replacing the extension of the
+  þsy{<input_file>}s with .obj or .lib, respectively.  If the -x
+  option is given, all members (which must be a.out modules) of
+  archives (.a files) are converted to .obj files.  The names of the
+  output files are constructed by replacing the extension of the
+  member names with .obj.  If the -x option is not given, archives (.a
+  files) are converted to libraries (.lib files).  If the -O option is
+  given, the output files are written to the directory <directory>.  A
+  þbf{LIB} response file <response_file> is created if you use the -r
+  or -R option.  When using -r, the response file will contain
+  commands to add the modules to a library file, when using -R, it
+  will contain commands to replace the modules in a library file.  If
+  the -d option is given, all the input files except for archives are
+  deleted after successful conversion.  If the -s option is given,
+  debugging information is omitted.
+
+  You can put emxomf options into the environment variable EMXOMFOPT.
+  These options will be read before the options given on the command
+  line.
+
+  Options common to both calling sequences:
+
+þlist
+þitem -D <dataseg>
+
+    Change the name of the data segment.  By default, all initialized
+    variables are put into the DATA32 segment which is a member of the
+    DGROUP group.  By using the -D option, the segment used for
+    initialized variables can be changed.  That segment won't be a
+    member of the DGROUP.  This can be used for creating dynamic link
+    libraries with both instance data and shared data.  Define all
+    variables which should be private to the instances of the DLL in a
+    separate source file, initialize all the variables, use the -D
+    option of emxomf to put these variables into a separate segment
+    and set the attributes of that segment in the module definition
+    file to NONSHARED.  All other variables will go into the default
+    data segment, which is shared by all instances of the DLL.
+    Alternatively, you can make variables private by default and put
+    the shared variables into a separate segment.  You have to list
+    all the segments of class DATA in the module definition file.
+    Example:
+
+þexample
+SEGMENTS
+  PRIV CLASS 'DATA' NONSHARED
+  DATA32 CLASS 'DATA' SHARED
+  BSS32 CLASS 'BSS' SHARED
+þendexample
+
+    In this example, variables are shared by default.  The segment
+    PRIV contains private variables.
+
+þitem -g
+
+    Create groups for sets, as did previous versions of emxomf.  This
+    causes an extra object to be created for each set (such as
+    þtt{__CTOR__LIST__}).  By default, all sets are merged into the
+    text object.
+
+þitem -i <default_lib>
+
+    Add default library request.  LINK386 is informed that the .obj
+    file should be linked with the library <default_lib>.  If
+    <default_lib> doesn't include a file name extension, LINK386
+    uses the default extension .lib.  You can specify multiple
+    libraries by using multiple -i options.
+
+þitem -I <idmdll>
+
+    Change the name of the identifier manipulation DLL.  That DLL is
+    used by LINK386 to demangle C++ symbol names in error messages.  A
+    special record (IDMDLL) is inserted into the .obj file by emxomf
+    to tell LINK386 about the name of the DLL.  emxomf inserts that
+    record only if it recognizes the input file as being compiled by
+    G++.  The default for the identifier manipulation DLL is
+    þtt{gppdemid}.  Use þtt{-I-} to suppress the insertion of the
+    IDMDLL record.
+
+þitem þsy{-l[<symbol>]}
+
+    The module (all the modules of an archive when converting an
+    archive) is supposed to be a library modules.  A library module
+    doesn't define a stack segment and doesn't request libraries.  If
+    <symbol> is given (following directly -l, without space), it is
+    used as name of the entry point, that is, the function that should
+    be called when the DLL is started.  If <symbol> is not specified,
+    no entry point will be defined.  If -l and -m are missing, the
+    module is supposed to be part of a program but not the main
+    module.  Such a module doesn't define a stack segment and doesn't
+    have an entry point.
+
+þitem -m <symbol>
+
+    The module is supposed to be the main module of a program.  A main
+    module defines a default stack segment (0x8000 bytes) and has an
+    entry point.  <symbol> is the name of the entry point, that is,
+    the function that should be called when the program is started.
+    -m is used for the startup code module crt0 and should not be used
+    for user modules.  If -l and -m are missing, the module is
+    supposed to be part of a program but not the main module.  Such a
+    module doesn't define a stack segment and doesn't have an entry
+    point.
+
+þitem -p <page_size>
+
+    Set the page size of .lib files to <page_size> bytes (16, 32, 64,
+    ..., 32768).  If -p is not given, a page size of 16 bytes will be
+    used.  Increase the page size if emxomf complains about too big
+    a library.  If emxomf doesn't complain, you shouldn't increase
+    the page size to save disk space.
+
+þitem -q
+
+    Suppress certain warning messages.  Currently, this option
+    suppresses the warning message for internal PC-relative
+    relocations being ignored.
+
+þitem -s
+
+    If the -s option is given, debugging information is omitted.  By
+    default, debugging information is converted from a.out
+    þbf{DBX}-style (with GNU extensions) to HLL version 3 format (as
+    used by IBM's IPMD debugger of the C/C++ Tools 2.0 package and by
+    SD386).  If emxomf cannot translate debugging information, a
+    warning message is displayed.  Types not recognized by emxomf are
+    treated as `þtt{int}' to be able to continue conversion.
+    Restrictions:
+
+þitemize
+þitem
+
+      The Objective C language is not supported yet.
+
+þitem
+
+      Structures (or unions) without declarator within another
+      structure (or union) are ignored as GCC doesn't emit suitable
+      debugging information.
+
+þitem
+
+      Variable-length automatic arrays are not supported.
+
+þitem
+
+      `þtt{long long}' and `þtt{unsigned long long}' types are
+      translated to the following structure, as HLL version 3
+      debugging information doesn't support 64-bit integers:
+
+þexample
+struct _long_long
+{
+   unsigned long lo;
+   unsigned long hi;
+}
+þendexample
+
+þitem
+
+     Pointer to member (C++) is not yet supported.
+
+þenditemize
+
+þitem -u
+
+    List all symbol table entries (stabs code and symbol name) unknown
+    to emxomf.  This option is used for debugging emxomf.
+
+þendlist
+
+
+þh2 emxomfar
+þlabel emxomfar
+þindex emxomfar
+þkeyword emxomfar
+
+  emxomfar is a librarian for OMF .lib files with a command line
+  interface similar to þbf{ar} to simplify makefiles.
+
+þindent
+  þsy{emxomfar [-p#] <command> <library_file> [<module>]...}
+þendindent
+
+  The default extension for <library_file> is .lib.  When modifying a
+  library file, a backup file with .bak extension is created.
+
+  Here's a description of emxomfar commands:
+
+þdescription
+þitem d
+
+    Delete modules from library.  The module name __.SYMDEF is
+    ignored.
+
+þitem m
+
+    Move members to the end of the archive.  Not implemented in
+    emxomfar.
+
+þitem p
+
+    Copy members to standard output.  Not implemented in emxomfar.
+
+þitem q
+
+    Quick append.  This command is equivalent to the r command in
+    emxomfar.
+
+þitem r
+
+    Replace modules in library.  Modules which are not in the library
+    are added to the library.  The default extension for modules is
+    .obj.
+
+þitem s
+
+    Build the __.SYMDEF symbol table member.  This command is ignored
+    by emxomfar.
+
+þitem t
+
+    List table of contents.  Use the v option to also list public
+    symbols.
+
+þitem x
+
+    Extract modules from library.  The default extension for modules
+    is .obj.
+
+þenddescription
+
+  You can additionally use the following modifiers in the <command>
+  argument:
+
+þdescription
+
+þitem a
+
+    Position after specified member.  Not implemented in emxomfar
+
+þitem b
+
+    Position before specified member.  Not implemented in emxomfar
+
+þitem c
+
+    Don't display warning when creating new library.
+
+þitem i
+
+    Position before specified member.  Not implemented in emomfar
+
+þitem l
+
+    Create temporary file in current directory.  Ignored by emxomfar
+
+þitem o
+
+    Preserve dates.  Ignored by emxomfar
+
+þitem u
+
+    Don't replace members with older files (update).  Ignored by
+    emxomfar
+
+þitem v
+
+    Verbose output.
+
+þenddescription
+
+  The following option must precede <command> if used:
+
+þdescription
+þitem -p#
+
+    Set page size to # bytes (16, 32, 64, ..., 32768).  If -p is not
+    given, a page size of 16 bytes will be used.  Increase the page
+    size if emxomfar complains about too big a library.  If emxomfar
+    doesn't complain, you shouldn't increase the page size to save
+    disk space.
+
+þenddescription
+
+  Example:
+
+þexample
+emxomfar -p32 rc newlib *.obj
+þendexample
+
+
+þh2 emxomfld
+þlabel emxomfld
+þindex emxomfld
+þkeyword emxomfld
+
+  emxomfld is a front end to LINK386, providing an þhpt{ld}-like
+  command line syntax for LINK386.  After parsing the command line,
+  LINK386 is called with equivalent command line arguments.
+
+þindent
+  þsy{emxomfld -o <file> [-l <lib>] [-L <libdir>] [-T <base>] [-sS]} þbreak
+  þsy{         [-Zexe] [-Zdll] [-Zstack <stack_size>] [-Zmap[=<map_file>]]} þbreak
+  þsy{         [-O <option>] <file>...}
+þendindent
+
+  The files given on the emxomfld command line are assumed to be .obj
+  files to be linked unless the extension is .def, .lib or
+  .res.  A file having a .def extension is used as module definition
+  file.  There may be at most one module definition file.  A file
+  having a .lib extension is used as library file.  A file
+  having a .res extension is used as binary resource file; þbf{rc} is
+  called to attach the resources to the output file.
+
+  Example:
+
+þexample
+emxomfld -o test -lc -Lc:/mylibs test1 test2 test.def test.res
+þendexample
+
+  Create file test.exe (or test.dll, depending on the contents of
+  test.def), by linking test1.obj and þtt{obj2.obj} with c.lib.  c.lib
+  is sought in þtt{c:/mylibs}.  Use the module definition file
+  test.def.  Call þbf{rc} to copy the resources from test.res to
+  test.exe (or test.dll).
+
+  The following options are available:
+
+þlist
+þitem þsy{-i}
+
+    Pass the þtt{/INFORMATION} option to LINK386, causing filenames
+    to be displayed while linking.  This is used for debugging
+    emxomfld.
+
+þitem þsy{-l <lib>}
+
+    Link with the library þsy{<lib>}þtt{.lib}.  For instance, -lc
+    causes c.lib to be used.
+
+þitem þsy{-L <libdir>}
+
+    Add the directory <libdir> to the library search path.  Libraries
+    are sought in the directories given by -L options.  emxomfld
+    prepends the directories to the LIB environment variable.
+
+þitem þsy{-o <file>}
+
+    <file> is the output file.  The default extension (.exe or .dll)
+    is provided by LINK386.  If -o is omitted, þtt{$$$} will be used.
+
+þitem þsy{-O <option>}
+
+    Pass the option <option> to LINK386.  For each option to be passed
+    to LINK386, one -O has to be used.  <option> should start with a
+    slash.  Example:
+
+þexample
+-O/runfromvdm
+þendexample
+
+    See also the -Zlinker option of GCC.
+
+þitem þsy{-s}
+
+    Strip all symbols, including debugging information.  If -s and -S
+    are not used, emxomfld passes the þtt{/DEBUG} option to LINK386.
+
+þitem þsy{-S}
+
+    Strip debugging symbols (emxomfld strips all symbols, including
+    debugging information, if -S is used).  If -s and -S are not used,
+    emxomfld passes the þtt{/DEBUG} option to LINK386.
+
+þitem þsy{-T <base>}
+
+    Set the base address of the text segment.  This option is
+    translated to the þtt{/BASE} option of LINK386.  emxomfld
+    automatically passes þtt{/BASE:0x10000} to LINK386 unless -T is
+    used or a DLL is built.  If neither -T nor -Zdll is used, the
+    module definition file is read to learn whether a DLL is being
+    built or not.
+
+þitem þsy{-x}
+
+    Discard all local symbols (this option is ignored by emxomfld).
+
+þitem þsy{-X}
+
+    Discard local symbols starting with þtt{L} (this option is ignored
+    by emxomfld).
+
+þitem þsy{-Zdll}
+
+    Build a DLL.  If the -Zdll option is present, emxomfld does not
+    automatically pass þtt{/BASE:0x10000} to LINK386.  The -Zdll
+    option isn't necesary as a module definition file is required when
+    building a DLL and emxomfld and emxbind read the module definition
+    file to learn whether a DLL is to be built or not.
+
+þitem þsy{-Zexe}
+
+    If the -Zexe option is present, emxomfld deletes the output file
+    (whose name is given on the command line) and adds .exe to the
+    output filename.  After calling LINK386, emxomfld creates an
+    empty output file (without .exe).  This feature is used for
+    minimizing changes to Unixoid makefiles.  See also the -Zexe
+    option of GCC and ld.
+
+þitem þsy{-Zmap[=<map_file>]}
+
+    Let LINK386 write the map file <map_file>.  LINK386 adds the
+    default extension `þtt{map}'.  If þsy{=<map_file>} is not
+    specified, the name of the map file will be derived from the
+    output file name.
+
+þitem þsy{-Zstack <stack_size>}
+
+    Set the stack size of the executable, in Kbyte.  The argument of
+    the -Zstack option is multiplied by 1024 and turned into a
+    þtt{/STACK} LINK386 option.  The number can be given in decimal,
+    octal or hexadecimal, using C notation.
+
+þendlist
+
+
+þh2 emxrev
+þlabel emxrev
+þindex emxrev
+þkeyword emxrev
+
+  emxrev displays the revision number of emx DLLs (emx.dll, emxio.dll,
+  emxlibc.dll, emxlibcm.dll, emxlibcs.dll, and emxwrap.dll).  The
+  revision number is incremented every time a changed version of a DLL
+  is released.  By looking at the revision numbers of the DLLs, you
+  can tell which one is the newest one.
+
+  To display the revision number of the default emx DLLs, type
+
+þindent
+  þsy{emxrev}
+þendindent
+
+  The default DLLs are those used by the operating system when
+  starting a program.
+
+  To display the revision number of a specific file, type
+
+þindent
+  þsy{emxrev -f <file>}
+þendindent
+
+  If a directory is included in <file>, append .dll to the name.  If
+  no directory is included in <file>, don't append .dll to the name.
+
+  To display the revision numbers of the emx DLLs in directory <dir>,
+  type
+
+þindent
+  þsy{emxrev -d <dir>}
+þendindent
+
+  To display the revision numbers of the emx DLLs in all directories
+  of drive <drive> (þtt{c:}, for instance), type
+
+þindent
+  þsy{emxrev -c <drive>}
+þendindent
+
+  To display the revision numbers of the emx DLLs in all directories
+  of all hard disks, type
+
+þindent
+  þsy{emxrev -a}
+þendindent
+
+  To display the revision numbers of the emx DLLs in the directories
+  listed in the LIBPATH statement of a config.sys file, type
+
+þindent
+  þsy{emxrev -p <file>}
+þendindent
+
+  where <file> is the name of the config.sys file.
+
+
+þh2 emxtsf
+þlabel emxtsf
+þindex emxtsf
+þkeyword emxtsf
+
+  emxtsf assists in creating .tsf files for TRCUST.  TRCUST (which can
+  be downloaded as part of the þtt{os2pdp.zip} package from the usual
+  OS/2 archives) generates þtt{.tdf} and þtt{.tff} files from .tsf
+  files; þtt{.tdf} files are used by OS/2's TRACE command,
+  þtt{.tff} files are used by OS/2's TRACEFMT command.
+
+þindent
+  þsy{emxtsf [-d <dll_name>] [-w <level>] <tss_file> <map_file> <def_file> <dll_name>}
+þendindent
+
+  <tss_file> declares what functions are to be traced and how to
+  format their arguments; the format of that file is described below.
+
+  <map_file> is the .map file created by the linker for the DLL.  It's
+  used to find out which symbols are available.  This avoids errors
+  when TRCUST is run.
+
+  <def_file> is the DLL's module definition file (.def file); the
+  ordinal numbers of the EXPORTS statement will be used as minor trace
+  codes.  Functions which are not exported will be assigned minor
+  trace codes starting at 0x7fff, counting down.
+
+  <dll_name> is the name of the DLL.  If the -d option is not used,
+  TRACEFMT will print the function name as is.  If the -d option is
+  used, <dll_name> followed by a colon and a space will be prefixed to
+  the function name.
+
+  The -w option sets the warning level.  Warning level 0 is the
+  default setting.  Warning level 1 prints the names of functions
+  exported by the DLL but not defined in the <tss_file> to standard
+  error.  Warning level 2 additionally prints the names of functions
+  for which no epilogue has been found.
+
+  emxtsf writes the output to standard output; the output should be
+  appended to a manually created .tsf file header.
+
+  In <tss_file>, empty lines and lines starting with a semicolon are
+  ignored.  All remaining lines start with a letter which is followed
+  by a space character and additional data.
+
+  A line starting with `þtt{G}' defines a group; all following
+  function definitions belong to that group until another group is
+  defined.  A line starting with `þtt{T}' defines a list of event
+  types; these event types will be used for all following function
+  definitions until another list of event types is defined.
+
+Example:
+
+þexample
+G IO
+T APP,CPP
+þendexample
+
+  Note that in the header of the .tsf file, each group must be defined
+  in a þtt{GROUP} statement and each event types must be defined in a
+  þtt{TYPELIST} statement.  Both a group and a list of event types
+  must be defined before functions can be defined.
+
+  A line defining a function starts with a letter which defines the
+  return type of the function.  The following return types are
+  supported:
+
+þdescription
+þitem þtt{i}
+32-bit integer
+þitem þtt{p}
+pointer
+þitem þtt{v}
+no return value (void)
+þitem þtt{I}
+ignore this symbol
+þenddescription
+
+  Note that floating-point return values cannot be traced.  `þtt{I}'
+  pretends that a symbol has been used; this is used to avoid the
+  warnings for exported symbols (such as variables) that are not
+  traced.
+
+  The letter is followed by a space and the function name.  The
+  function name is followed by parenthesis in which the arguments are
+  declared.  For each argument, the argument type and the argument
+  name is provided (separated by a space), arguments are separated by
+  commas.  The argument type is a single letter:
+
+þdescription
+þitem þtt{i}
+32-bit integer
+þitem þtt{p}
+pointer
+þitem þtt{s}
+string (consisting entirely of printable characters)
+þenddescription
+
+  The following example defines tracepoints for some standard library
+  functions:
+
+þexample
+v clearerr (p stream)
+p fgets (p buffer, i size, p stream)
+v abort ()
+I errno         ; suppress warning about errno not being traced
+þendexample
+
+  If a function has more arguments than declared in the <tss_file>,
+  remaining arguments of the function won't be traced.
+
+  For each function, emxtsf creates a Pre-Invocation tracepoint.  If
+  the function has been compiled with the þhpt{-mepilogue} option of
+  GCC, a Post-Invocation tracepoint will be created as well.
+
+
+þh2 listomf
+þlabel listomf
+þindex listomf
+þkeyword listomf
+
+  listomf lists an .obj or .lib file in (more or less) human-readable form.
+
+þindent
+  þsy{listomf [-d] <input_file>}
+þendindent
+
+  Give the name of the object file or library file on the command
+  line.  There is no default extension.  If the -d option is given,
+  listomf won't interpret debugging information.
+
+  Warning: listomf is a quick and dirty program which was used for
+  developing þhpt{emxomf}.
+
+
+þh2 updt
+þlabel updt
+þindex updt
+þkeyword updt
+
+þitemize
+þitem
+    Copy file if contents have changed:
+
+þindent
+  þsy{updt [-v] <source_file> <target_file>}
+þendindent
+
+  updt copies the source file to the target file if the target file
+  does not exist or if the source and target files differ in contents.
+  This is used by the makefile for GCC.
+
+þitem
+    Copy file if source file is newer:
+
+þindent
+  þsy{updt [-v] -t <source_file> <target_file>}
+þendindent
+
+  updt copies the source file to the target file if the target file
+  does not exist or if the source file is newer than the target file.
+  This is used for configuring GCC.
+þenditemize
+
+  The -v option turns on information messages.
+
+
+þh1 Hints for porting Unix programs to emx
+
+þitemize
+þitem
+
+  If you want Unix-like wildcard expansion built into the program, use
+
+þexample
+int main (int argc, char *argv[])
+{
+  _wildcard (&argc, &argv);
+  /* ... the program ... */
+}
+þendexample
+
+  This should be done at the very beginning of þhpt{main()}, before
+  þpa{ARGC} and þpa{ARGV} are used.  See þhpt{_wildcard()} and
+  þhpt{_response()}.
+
+þitem
+
+  Change all þhpt{open()}, þhpt{fopen()}, þhpt{fdopen()} and
+  þhpt{freopen()} calls to use O_BINARY or "b", respectively, for
+  binary files.  If a file contains both binary and textual data, read
+  the file in binary mode and do the conversion yourself.
+
+þitem
+
+  Though fseek() and ftell() now work on text files, the offsets are
+  different from what Unix programs expect.  You may have to open the
+  files in binary mode and ignore carriage returns (this has been done
+  in GDB).
+
+þitem
+
+  Replace þhpt{fork()} and þhpt{exec*()} with þhpt{spawn*()}.  Under
+  OS/2, fork() is inefficient.  Under DOS, fork() is not implemented.
+
+þitem
+
+  Replace þhpt{exec*()} with þhpt{spawn*()} and þhpt{exit()} if the
+  parent process waits for the termination of the new process (by
+  calling þhpt{wait()} or by waiting for SIGCLD).  This is required to
+  keep the process ID of the child process.  In a forked process,
+  however, you don't have to do this because emx.dll does it for you.
+
+þitem
+
+  Programs reading a.out files should be changed to call
+  þhpt{_seek_hdr()} or þhpt{_fseek_hdr()} before reading the header to
+  support .exe files.  More changes are usually required.
+
+þitem
+
+  Watch out for Unix file system hacks: Unix allows deleting and
+  renaming an open file (the file will be deleted after being closed).
+
+þitem
+
+  Watch out for Unix file names (Unix is case sensitive, long file
+  names and multiple dots are allowed).  On OS/2's HPFS multiple dots
+  are also allowed; however, trailing dots are not significant (except
+  for the special file names `þtt{.}' and `þtt{..}').
+
+þitem
+
+  The null device is called þtt{/dev/null} under Unix.  The __open()
+  system call translates the filenames þtt{"/dev/null"} and
+  þtt{"/dev/tty"} (lower case, with slashes) to þtt{"nul"} and
+  þtt{"con"}, respectively.  However,
+
+þexample
+system ("whatever >/dev/null");
+þendexample
+
+  won't work as the standard OS/2 and DOS command interpreters don't
+  recognize þtt{/dev/null}.
+
+þitem
+
+  Programs using stdin, stdout or stderr for binary data should call
+  þhpt{_fsetmode()} to switch the stream to binary mode.
+
+þitem
+
+  If you want to use þtt{\} for separating directories, changes may be
+  necessary.  These changes are optional because þtt{/} also works.
+
+þitem
+
+  Implement support for drive names.  This can be done by using
+
+þexample
+#define getcwd _getcwd2
+#define chdir _chdir2
+þendexample
+
+  In addition, some changes will be necessary.  For instance, you have
+  to change code which checks whether a filename is an absolute path
+  name.  þhpt{_fullpath()} and þhpt{_abspath()} can also be useful.
+
+þitem
+
+  Note that þtt{///abc} is a valid Unix filename.  It's equivalent to
+  þtt{/abc}.
+
+þitem
+
+  Note that þtt{chdir ("..")} is a no-op under Unix if the current working
+  directory is the root directory.  Under emx, þtt{chdir ("..")} fails in
+  the root directory.
+
+þitem
+
+  Use termio or termios or read the keyboard with þhpt{_read_kbd()} if
+  you don't want to get input line by line.
+
+þitem
+
+  Under Unix, directories in environment variables (PATH, for
+  instance) are separated by colons; use semicolons instead.
+
+þitem
+
+  Do not use the þtt{PTRACE_TRACEME} request of þhpt{ptrace()}: use
+  P_DEBUG instead when starting the process with þhpt{spawn*()}.
+
+þitem
+
+  By default, signal processing is different when using signal():
+  SIG_ACK should be used instead of the signal handler address to
+  re-enable a signal by calling þhpt{signal()} when the signal handler
+  has been called.  This behavior can be changed with the
+  -Zbsd-signals and -Zsysv-signals options of GCC.  If you use POSIX.1
+  functions for signal handling, SIG_ACK is not required.
+
+þitem
+
+  The shell isn't called þtt{/bin/sh}.  Use þhpt{system()}.  system()
+  and þhpt{popen()} don't expand wildcards (unless COMSPEC points to a
+  shell which expands wildcards).
+
+þitem
+
+  Printing single characters is inefficient.  A solution is to use
+
+þexample
+setvbuf (stdout, NULL, _IOLBF, BUFSIZ)
+þendexample
+
+  and to use þtt{fflush (stdout)} if you need the output immediately
+  (flushing is required only after displaying prompting texts before
+  reading input or displaying progress reports that don't end with a
+  newline character).  GDB output has been made much faster by using
+  line buffering.
+
+þitem
+
+  Note that þtt{VEOF != VMIN} and þtt{VEOL != VTIME}.  Programs which
+  use VEOF and VEOL to access VMIN and VTIME, respectively, should be
+  changed to use VMIN and VTIME.  emx uses separate fields for VEOF,
+  VEOL, VMIN and VTIME.
+
+þitem
+
+  To use termio, you have to reset the IDEFAULT bit of c_lflag.  This
+  does not apply to termios.
+
+þenditemize
+
+
+þh1 Creating OS/2 programs
+
+  This section describes additional features available when devoloping
+  OS/2 programs.
+
+þipfminitoc
+
+þh2 Calling OS/2 API functions
+þlabel Calling OS/2 API functions
+
+  Use
+
+þexample
+#include <os2.h>
+þendexample
+
+  in your C files to call OS/2 API functions.  GCC automatically links
+  your program with os2.a (or os2.lib) by passing the -los2 option to
+  the linker.  If you call the linker manually, you have to tell the
+  linker to link with library os2.  Note that your program will crash
+  if it calls an OS/2 API function when run under DOS.
+
+  You can use either the header file that comes with emx (os2emx.h) or
+  the header files that come with the Developer's Toolkit for OS/2
+  (an IBM product).  By default, os2emx.h is used when doing
+  þtt{#include <os2.h>}.  To use the header files of the Developer's
+  Toolkit for OS/2, edit þtt{/emx/include/os2.h} to #include
+  os2tk.h instead of os2emx.h, and add the toolkit include file
+  directory to the C_INCLUDE_PATH, CPLUS_INCLUDE_PATH and
+  OBJC_INCLUDE_PATH environment variables.  Instead of editing
+  þtt{os2.h}, you can #define þtt{USE_OS2_TOOLKIT_HEADERS} before
+  doing þtt{#include <os2.h>}.
+
+  Note that you should define þtt{INCL_}þsl{WHATEVER} constants when
+  using os2emx.h as you would with the IBM Developer's Toolkit for
+  OS/2 -- though not all constants are tested by the current
+  version of os2emx.h.
+
+  When compiling C++ programs, you may have to define the preprocessor
+  symbol þtt{OS2EMX_PLAIN_CHAR}.
+
+  When passing a pointer to a structure to a 16-bit function, the
+  structure must not cross a 64 KByte boundary.  This (currently)
+  cannot be automatically assured for structures allocated in the
+  stack (auto variables and function arguments).
+
+  To pass the address of an þtt{auto} variable to a 16-bit function,
+  you should define the variable twice and use þtt{_THUNK_PTR_STRUCT_OK}
+  or þtt{_THUNK_PTR_SIZE_OK} to check which one is properly aligned.
+
+  To ensure that all structures passed to 16-bit functions are
+  properly aligned, define all those variables in a module of their
+  own which must be the first module linked.  This doesn't work if the
+  combined size of all those variables exceeds 64 KByte.  Use
+  þhpt{_tmalloc()} to allocate memory for structures passed to 16-bit
+  functions.
+
+  The 32-bit wrappers for 16-bit OS/2 API functions are provided for
+  both static linking (library os2) and dynamic linking (library
+  þtt{wrap}, emxwrap.dll).
+
+
+þh2 Importing from OS/2 DLLs
+þlabel Importing from OS/2 DLLs
+
+  All functions in the list above are defined in os2.a and os2.lib.
+  Moreover, the 32-bit wrappers for the 16-bit OS/2 API functions are
+  available in the dynamic link library emxwrap.dll to reduce the size
+  of the executables.  The import library for emxwrap.dll is
+  þtt{wrap}.  To import functions not defined in os2.a and os2.lib,
+  you have to create an import list file for these functions.
+
+  See the þhpt{emximp} documentation for details.
+
+  Please note that you cannot directly call 16-bit functions not
+  listed above.  See below for details.
+
+
+þh2 Creating Presentation Manager applications using ld and emxbind
+þlabel Creating Presentation Manager applications using ld and emxbind
+
+  To create a Presentation Manager application using ld and emxbind,
+
+þitemize
+þitem
+
+  þtt{#include <os2.h>}
+
+þitem
+
+  link with os2.a (done automatically when using GCC to link)
+
+þitem
+
+  use þtt{rc -r} to compile the resource-definition file into a binary
+  resource file (.res file)
+
+þitem
+
+  use þtt{emxbind -ep} or a module definition file to set the
+  application type
+
+þitem
+
+  use the -r option of emxbind to put the resources from the binary
+  resource file into the .exe file.  If there is a .res file on the GCC
+  or ld command line, it is automatically passed to emxbind
+
+þenditemize
+
+  Do not use rc to put the resources into the .exe file!
+
+  Example:
+
+þexample
+cd \emx\test
+rc -r pm1.rc
+gcc -o pm1 pm1.c
+emxbind -bp -rpm1.res /emx/bin/emxl pm1
+þendexample
+
+  Ditto, using a module definition file:
+
+þexample
+cd \emx\test
+rc -r pm1.rc
+gcc -o pm1.exe pm1.c pm1.def pm1.res
+þendexample
+
+  Example (compiling the `template' toolkit sample program):
+
+þexample
+cd \toolkt20\c\samples\template
+copy ..\prodinfo.bmp
+rc -r main.rc
+gcc -s -o template.exe *.c template.def main.res
+þendexample
+
+
+þh2 Creating Presentation Manager applications using emxomf and LINK386
+þlabel Creating Presentation Manager applications using emxomf and LINK386
+
+  To create a Presentation Manager application using emxomf and LINK386,
+
+þitemize
+þitem
+
+  þtt{#include <os2.h>}
+
+þitem
+
+  link with os2.lib (done automatically when using GCC to link)
+
+þitem
+
+  use a module definition file which uses the WINDOWAPI keyword of the
+  NAME statement
+
+þitem
+
+  use þtt{rc -r} to compile the resource-definition file into a binary
+  resource file (.res file)
+
+þitem
+
+  use rc or emxomfld to add the binary resource file to the .exe
+  file.  Optionally, you can compile the resource-definition file and
+  add it to the .exe file using rc in one step.  Using two steps is
+  recommended in makefiles.
+
+þenditemize
+
+  Example:
+
+þexample
+cd \emx\test
+rc -r pm1.rc
+gcc -o pm1.exe pm1.c pm1.def pm1.res -Zomf
+þendexample
+
+  Example (compiling the `template' toolkit sample program):
+
+þexample
+cd \toolkt20\c\samples\template
+copy ..\prodinfo.bmp
+rc -r main.rc
+gcc -Zomf -o template.exe *.c template.def main.res
+þendexample
+
+  If you want to use the þhpt{-Zsys} option, you should increase the
+  stack size by editing the STACKSIZE statement in the .def file.
+  Note that the command line arguments and the complete environment
+  are copied to the stack!  The stack size should be at least 32768.
+
+
+þh2 Creating Workplace Shell applications
+þlabel Creating Workplace Shell applications
+
+  Dynamic link libraries for Workplace Shell objects should be either
+  DLLs without C runtime environment or stand-alone DLLs (see below).
+
+  For creating Workplace Shell applications, you need the SOM headers
+  and the SOM compiler from the Developer's Toolkit for OS/2 (an IBM
+  product).
+
+  See the `flag' example in þtt{/emx/samples}.
+
+þh2 Creating dynamic link libraries
+þlabel Creating dynamic link libraries
+
+  There are six types of dynamic link libraries:
+
+þenumerate
+þitem
+
+  DLLs which use emxlibcm.dll or emxlibcs.dll or a custom C runtime
+  DLL.  These DLLs don't contain C library functions.  Calls to C
+  library functions are resolved by emxlibcm.dll or emxlibcs.dll or a
+  custom C runtime DLL (and, in all three cases, emx.dll).  The main
+  program and all DLLs must use the same C runtime DLL.
+
+þitem
+
+  Custom C runtime DLLs.  These DLLs contain the C library or parts
+  thereof and export the C library functions to other DLLs and to the
+  main program.  An application (main program and DLLs) should use
+  only one custom C runtime DLL; emxlibcm.dll and emxlibcs.dll should
+  not be used.  Either the system call library sys.lib or emx.dll can
+  be used.  This type of DLL is recommended if you want to ship your
+  application with your own DLLs, but without any emx DLLs.  This type
+  of DLL can also be used when replacing library functions such as
+  malloc() which are referenced by other library functions.
+
+þitem
+
+  C runtime forwarder DLLs.  These DLLs forward all C runtime
+  functions to emxlibcm.dll or emxlibcs.dll, and add some functions of
+  their own.  However, they cannot safely replace functions of
+  emxlibcm.dll or emxlibcs.dll as the latter ones won't call the
+  replacement functions.
+
+þitem
+
+  Stand-alone DLLs.  These DLLs contain the C library or parts
+  thereof, which is used privately by the DLL.  The main program and
+  the other DLLs use a different C runtime environment.  You should
+  use only `simple' C library functions such as memcpy() which don't
+  require global variables.
+
+  Keep in mind that the DLL and the program using the DLL don't share
+  global variables such as þhpt{errno}, þhpt{timezone}, and -- very
+  important -- the variables used for I/O.
+
+þitem
+
+  DLLs without C runtime environment.  These DLLs don't call any C
+  library functions which require a runtime environment.  Only OS/2
+  API functions and simple C library functions such as þtt{strcpy()}
+  can be called.
+
+þitem
+
+  Resource DLLs.  These DLLs contain only resources.  Some bits of
+  code are required for library initialization.
+
+þendenumerate
+
+  Write a þhpt{module definition file} (.def file) that contains a
+  LIBRARY statement and an EXPORTS statement.  The EXPORTS statement
+  has to list all functions to be exported by your DLL.  The .def file
+  should have the same name as the .dll file to be created.
+
+  Compile and link your program using the þhpt{-Zdll} option of GCC.
+  This option causes the dll0 startup to be used instead of crt0 and
+  selects appropriate libraries.  As DLLs are usually multithread
+  libraries, you should also use the þhpt{-Zmt} option.  Specify the
+  name of the .def file on the GCC or ld command line, respectively.
+
+  Using the þhpt{-mprobe} GCC option is recommended for creating DLLs
+  as the DLL might be called from a thread with uncommitted stack.
+
+  Linking with LINK386 (using GCC -Zomf) is recommended for dynamic
+  link libraries.  Use ld and emxbind only if you want to debug the
+  dynamic link library.
+
+þh3 Creating dynamic link libraries that use a C library DLL
+
+  Dynamic link libraries that use emxlibcm.dll or emxlibcs.dll (or a
+  custom C runtime DLL) are allowed to call all library functions,
+  including stream I/O, as long as they are used together with
+  programs and other dynamic link libraries that use the same
+  emxlibcm.dll or emxlibcs.dll (or the same custom C runtime DLL used
+  by the DLL).  That is, all I/O done by C library functions must be
+  done in a single place, emxlibcm.dll, emxlibcs.dll, or the custom C
+  runtime DLL.  The following GCC options are used for building
+  a DLL which uses a C library DLL: þhpt{-Zdll} þhpt{-Zcrtdll}.
+
+  The default _DLL_InitTerm() function calls _CRT_init(),
+  constructors, and destructors, but does not call _CRT_term().
+  _CRT_init() is called to ensure that the C library has been
+  initialized for use by the constructors, even if OS/2 happens to
+  initialize the DLLs in a wrong sequence.  _CRT_term() is not called
+  because other libraries may still use the C library.
+
+  See þtt{/emx/test/testdll3.cc} for an example.
+
+þh3 Creating custom C runtime DLLs
+
+  Creating a custom C runtime DLL means creating a DLL which contains
+  your own code and some or all code of emxlibcm.dll or emxlibcs.dll.
+  Write a module definition file which exports your functions and all
+  C library functions and variables referenced by the main program and
+  other DLLs using the custom C runtime DLL.
+
+  You can use þtt{/emx/lib/cdll.def} as template.  Note that some
+  symbols must always be exported, see þtt{/emx/lib/cdll.def} for
+  details.
+
+  To create a multithread DLL, delete all lines of
+  þtt{/emx/lib/cdll.def} which contain the string þtt[{ST}].  To
+  create a single-thread DLL, delete all lines containing þtt[{MT}].
+  To create a DLL which uses emx.dll, delete all lines containing
+  þtt[{SYS}].  To create a DLL which does not use emx.dll (-Zsys),
+  delete all lines containing þtt[{EMX}].  This can be automatically
+  done, for instance with the þtt{sed} tool; see target
+  þtt{testdll7.def} in þtt{/emx/test/makefile}.
+
+  Don't forget to use the following statement:
+
+þexample
+DATA
+  MULTIPLE NONSHARED
+þendexample
+
+  Use the following GCC option for building a custom C runtime DLL:
+  þhpt{-Zdll}.  The options þhpt{-Zomf} and þhpt{-Zsys} are optional.
+
+  If clients of your DLL call the hardware port I/O functions such as
+  þhpt{_inp8()}, either link the clients with þtt{-lemxio} or use
+  þtt{/emx/src/lib/cdll/emxio.def} in addition to your module
+  definition file for creating the import library (it is essential to
+  import the functions from þtt{emxio.dll}, therefore appending
+  þtt{emxio.def} to your module definition file won't work).
+
+  To use your custom C runtime DLL, use the þhpt{-Zcrtdll} option of
+  GCC: If your import library is named þtt{myclib.lib}, use
+  þtt{-Zcrtdll=myclib} in GCC's command line.
+
+  The default _DLL_InitTerm() function calls _CRT_init(),
+  constructors, destructors, and _CRT_term().
+
+  See þtt{/emx/test/testdll4.c} and þtt{/emx/test/testdll7.c} for
+  examples.
+
+þh3 Creating C runtime forwarder DLLs
+
+  Creating a C runtime forwarder DLL is similar to creating a custom C
+  runtime DLL (see above).  However, instead of statically linking the
+  C runtime library, it is linked dynamically.  That is, the exports
+  of the forwarder DLL are resolved by imports from emxlibcm.dll or
+  emxlibcs.dll.
+
+  Use the following GCC option for building a forwarder DLL:
+  þhpt{-Zdll} þhpt{-Zomf} þhpt{-Zcrtdll}.  As emxbind does not
+  support forwarders, you have to use -Zomf.
+
+þh3 Creating stand-alone dynamic link libraries
+
+  A stand-alone dynamic link library has its own runtime environment
+  which is not shared with the client application or other DLLs.  Use
+  the following GCC options for creating a stand-alone DLL:
+  þhpt{-Zdll} þhpt{-Zso} þhpt{-Zsys} þhpt{-Zomf}.
+
+  The default _DLL_InitTerm() function calls _CRT_init(),
+  constructors, destructors, and _CRT_term().
+
+  See þtt{/emx/test/testdll5.c} for an example.
+
+þh3 Creating dynamic link libraries without C runtime environment
+
+  To create a dynamic link library without C runtime, do not reference
+  any C library function which requires a runtime environment.  As the
+  þtt{new} operator of C++ calls malloc(), you cannot use C++ to
+  create a DLL of this type unless you provide your own memory
+  management.  Do not use þhpt{-Zmt} even if the DLL is used by
+  multithread programs; you have to use Mutex semaphores when using
+  functions such as þtt{strtok()} which are not thread-safe.  Use the
+  following GCC options to build a DLL without C runtime environment:
+  þhpt{-Zdll} þhpt{-Zno-rte} þhpt{-Zomf}.
+
+  The default _DLL_InitTerm() function calls constructors and
+  destructors, but does not call _CRT_init() and _CRT_term() as there
+  is no runtime environment to initialize.
+
+  See þtt{/emx/test/testdll1.c} for an example.
+
+þh3 Creating resource DLLs
+
+  To create a resource DLL, build a DLL from þtt{/emx/lib/res0.obj}
+  and add the resources with rc:
+
+þexample
+link386 \emx\lib\res0,myres.dll,nul,,myres.def
+rc myres.res myres.dll
+þendexample
+
+  The module definition file should start with a LIBRARY statement.
+
+þh3 Creating dynamic link libraries using C++
+
+  You should not use the GNU C++ libraries (þhpt{libg++} and
+  þhpt{libstdc++}) if you create a DLL (unless you are building a
+  stand-alone DLL or a private C runtime DLL) as there is not yet a
+  DLL version of these libraries.
+
+  As creating the module definition file for the DLL by hand is quite
+  boring, you should let your computer do it: see the description of
+  the þhpt{emxexp} tool for details.  The þtt{sign} sample of
+  þtt{emxample.zip} uses emxexp to create the module definition file.
+
+  To call the constructors and destructors for static objects in the
+  DLL, make sure that the þhpt{_DLL_InitTerm()} function of the DLL
+  calls þhpt{__ctordtorInit()} and þhpt{__ctordtorTerm()}.  You should
+  call _CRT_init() before __ctordtorInit() to ensure that the C
+  library has been initialized for use by the constructors, even if
+  OS/2 happens to initialize the DLLs in a wrong sequence.
+
+þh2 Using the DLL version of the C library
+þlabel Using the DLL version of the C library
+
+  To use emxlibcm.dll or emxlibcs.dll, simply type þhpt{-Zcrtdll} on
+  the GCC command line.  This links your program with the import
+  libraries c_import.a or c_import.lib instead of the static C library
+  (þtt{c}, þtt{c_app}, þtt{gcc}, þtt{emx}).  Additionally, code which
+  must be statically linked is taken from c_static.a or c_static.lib.
+  -Zcrtdll can be used with methods (E1) and (E2).  See the
+  þhpt{introduction} for further information.
+
+  Note that emxlibcm.dll and emxlibcs.dll use emx.dll.  Thus, the
+  restrictions of -Zsys do not apply.
+
+  Do not redefine functions in your program which are contained in
+  emxlibcm.dll or emxlibcs.dll.  Other functions in emxlibcm.dll or
+  emxlibcs.dll will continue to use the original versions in that DLL
+  which will cause problems.  If you have to replace library functions
+  and want to use a C library DLL, create a new DLL (which must not be
+  called emxlibc.dll, emxlibcm.dll, or emxlibcs.dll), add your
+  replacement functions and all the functions of emxlibcm.dll or
+  emxlibcs.dll except for the functions you are replacing.
+
+
+þh2 Creating multithread programs
+þlabel Creating multithread programs
+
+  Multithread programs have to use either the multithread static
+  libraries or the dynamic link library emxlibcm.dll.  You have to say
+  þhpt{-Zmt} on the GCC command line.
+
+  Use þhpt{_beginthread()} to start a new thread.  Do not use
+  DosCreateThread unless the new thread doesn't call C library
+  functions.
+
+  The C library functions in þtt{mt/c.a}, þtt{mt/c.lib}, and
+  emxlibcm.dll are not yet completely thread-safe.  The -Zmt, -Zmts,
+  and -Zmtd options define the __MT__ preprocessor macro.  The C
+  library header files check for __MT__ to use alternate definitions
+  suitable for multithread programs when -Zmt, -Zmts, or -Zmtd is
+  used.
+
+  Each thread has its own þhpt{errno} value.  To create a library
+  which can be used for both single-thread and multithread programs,
+  use the þhpt{_errno()} function instead of the errno variable.  If
+  the preprocessor symbol þtt{__ST_MT_ERRNO__} is defined, errno will
+  be redefined to call _errno().  Just use the þtt{-D__ST_MT_ERRNO__}
+  option in the GCC command line.
+
+  If you are very careful, you can write multithread programs that
+  use the single-thread libraries.  Only the main thread is allowed
+  to call library functions that have side effects, including
+  functions that set errno.  All other threads should use OS/2 API
+  functions instead.
+
+  For performance reasons, single-thread programs should be linked
+  with the single-thread libraries (that is, without the -Zmt option).
+
+
+þh2 Calling 16-bit functions
+þlabel Calling 16-bit functions
+
+  Limited support for calling 16-bit functions is available.  You can
+  call 16-bit OS/2 API functions and other 16-bit functions that use
+  the pascal (_pascal) or C (_cdecl) calling convention and are
+  exported by a dynamic link library.  As no changes have been made to
+  GCC to support direct calls to 16-bit functions (this would require
+  big changes to GCC), you have to call 16-bit functions by applying
+  the (awkward) C preprocessor macros and functions described below.
+  There are two sets of macros, one for the pascal calling convention
+  (_THUNK_PASCAL_***) and one for the C calling convention
+  (_THUNK_C_***).  For convenience and compatibility with emx 0.8f,
+  there are also macros _THUNK_*** which are aliases for the
+  _THUNK_PASCAL_*** macros.  For brevity, only the _THUNK_*** macros
+  are explained below.  To call a _cdecl function, use
+  _THUNK_C_FUNCTION etc. instead of _THUNK_FUNCTION etc.
+
+þlist
+þitem þtt{_THUNK_FUNCTION(}þpa{FUNCTION}þtt{)}
+
+        This macro is used for declaring the 16-bit function.  The
+        function is declared as usual, using a prototype, but
+        _THUNK_FUNCTION is applied to the function name.  The 16-bit
+        function must not be called directly.
+
+þitem þtt{_THUNK_PROLOG(}þpa{SIZE}þtt{)}
+
+        For each call to the 16-bit function, this macro must be
+        called first.  þpa{SIZE} is the number of bytes in the
+        argument list of the 16-bit function.  After calling
+        _THUNK_PROLOG, the following macros are used to build the
+        argument list.  The macros are to be applied left-to-right,
+        that is, the first argument is handled first both for the
+        pascal and the C calling convention.
+
+þitem þtt{_THUNK_CHAR(}þpa{ARG}þtt{)}
+
+        Pass an 8-bit argument to the function.
+
+þitem þtt{_THUNK_SHORT(}þpa{ARG}þtt{)}
+
+        Pass a 16-bit argument to the function.
+
+þitem þtt{_THUNK_LONG(}þpa{ARG}þtt{)}
+
+        Pass a 32-bit argument to the function.
+
+þitem þtt{_THUNK_FLAT(}þpa{ARG}þtt{)}
+
+        Pass a 32-bit (flat) pointer to the function.
+
+þitem þtt{_THUNK_FAR16(}þpa{ARG}þtt{)}
+
+        Pass a 16:16-bit far pointer to the function.  After
+        building the argument list, the 16-bit function is called by
+        invoking the following macro.
+
+þitem þtt{_THUNK_CALL(}þpa{FUNCTION}þtt{)}
+
+        Call the 16-bit function þpa{FUNCTION}.  Do not apply
+        _THUNK_FUNCTION to the function name.
+
+þitem þtt{_THUNK_CALLI(}þpa{FUNCTION}þtt{)}
+
+        Call the 16-bit function pointed to by the 16:16-bit far
+        pointer þpa{FUNCTION}.  Use this macro instead of _THUNK_CALL
+        when employing DosLoadModule and DosQueryProcAddr.  The
+        pointer returned by DosQueryProcAddr must be turned into a
+        16:16-bit far pointer by calling _emx_32to16().
+
+þendlist
+
+  There should be no statements other than calls to the _THUNK macros
+  between _THUNK_PROLOG and _THUNK_CALL.  _THUNK_PROLOG starts an
+  expression which is terminated by _THUNK_CALL.  Therefore, the
+  return value of the 16-bit function is returned by _THUNK_CALL and
+  by the entire sequences of statements from _THUNK_PROLOG to
+  _THUNK_CALL.  The return value is the value returned by the 16-bit
+  function in the DX and AX registers.  If the function returns a
+  16-bit value, you have to typecast the return value to þtt{SHORT} or
+  þtt{USHORT} to discard the upper 16 bits.
+
+  See the description of þhpt{_emx_16to32()} and _emx_32to16() for
+  converting 16-bit far pointers to 32-bit flat pointers and vice
+  versa.  This conversion is not done automatically.
+
+  You will get a warning about the variable _tp being unused if the
+  16-bit function doesn't take arguments.  This warning is harmless.
+
+  When passing a pointer to a structure to a 16-bit function, the
+  structure must not cross a 64 KByte boundary.  This (currently)
+  cannot be assured for structures allocated in the stack (þtt{auto}
+  variables and function arguments).  To ensure that all structures
+  passed to 16-bit functions are properly aligned, define all those
+  variables in a module of their own which must be the first module
+  linked.  This doesn't work if the combined size of all those
+  variables exceeds 64 KByte.  Alternatively, you can define the
+  variable twice and use þtt{_THUNK_PTR_STRUCT_OK} or
+  þtt{_THUNK_PTR_SIZE_OK} to check which one is properly aligned.  Use
+  þhpt{_tmalloc()} to allocate memory for structures passed to 16-bit
+  functions.  Example:
+
+þexample
+#include <os2.h>                /* define _THUNK_*** macros */
+
+/* Declare 16-bit function */
+USHORT _THUNK_FUNCTION (Dos16Beep) (USHORT usFrequency, USHORT usDuration);
+
+void beep (int frequency, int duration)
+{
+  _THUNK_PROLOG (2+2);
+  _THUNK_SHORT (frequency);
+  _THUNK_SHORT (duration);
+  _THUNK_CALL (Dos16Beep);
+}
+þendexample
+
+  See þtt{/emx/test/c16test1.c}, þtt{/emx/test/c16test2.c},
+  þtt{/emx/src/lib/sys/scrsize.c}, and þtt{/emx/src/lib/os2/*.c} for
+  more examples.
+
+
+þh1 Customizing
+
+  Default values are provided for the heap size, the stack size and
+  the number of files that can be open simultaneously.  The following
+  sections describe how to increase the limits.
+
+þipfminitoc
+
+þh2 Increasing the heap size
+þlabel Increasing the heap size
+
+  The malloc() implementation of emx 0.9c and later can use multiple
+  heap objects under OS/2; in consequence, the heap size is no longer
+  limited under OS/2.  However, if you use another malloc()
+  implementation which does not support non-contiguous memory
+  allocation or if the application is run under DOS, the maximum size
+  of the heap available for þhpt{malloc()} is fixed.  The default for
+  the combined size of the heap and stack is 8 MByte under DOS.  Use
+  the þhpt{-s# emx option} (see section þref{Using emx options}) to
+  increase the heap and stack size.
+
+  The default heap size is 32 MByte under OS/2.  For the emx
+  implementation of malloc(), this is the size of the initial heap
+  object and the minimum size of additional heap objects.  If ld and
+  emxbind are used for linking, you can change the heap size with the
+  þhpt{-h<heap_size> option of emxbind}.
+
+  If emxomf and LINK386 without -Zsys are used for linking, the heap
+  size cannot be changed.  If -Zsys is used, initialize the variable
+  þtt{_sys_heap_size} to the desired heap size:
+þexample
+unsigned _sys_heap_size = 0x4000000; /* 64 MByte */
+þendexample
+  This can be done in any module explicitely linked to your
+  application.
+
+
+þh2 Increasing the stack size
+þlabel Increasing the stack size
+
+  The default for the combined size of the heap and stack is 8 MByte
+  under DOS.  When using emxbind, the default stack size is 8 MB under
+  OS/2.  When using emxomf and LINK386, the default stack size is 0x8000
+  bytes under OS/2.
+
+  The stack size for DOS can be changed with the þhpt{-s# emx option}.
+  emxbind can put this option into the executable file.
+
+  The stack size for OS/2 can be changed with the þhpt{-k<stack_size>
+  option of emxbind} when using emxbind.  When using LINK386, use the
+  þhpt{STACKSIZE statement} in a þhpt{module definition file}.  The
+  stack size should be at least 32768 bytes.  You can also use the
+  þhpt{-Zstack} option of GCC.
+
+  If you are using certain beta versions of LINK386, bits 16 through 23
+  of the stack size should not equal 0x20000 or 0x40000 bits set.
+  Otherwise, your program will crash under OS/2 2.0 due to a bug in
+  OS/2 2.0.  Use only stack sizes where both the 0x20000 and 0x40000
+  bits are zero or the 0x10000 or 0x80000 bits are one.
+
+þh2 Increasing the number of files
+þlabel Increasing the number of files
+
+  Under DOS and when using emx.dll under OS/2, you can set the number
+  of file handles supported by the emx runtime by setting the EMXOPT
+  environment variable or by using emxbind to put emx options into the
+  .exe file.  See section þref{Using emx options} for the þhpt{-h# emx
+  option}.
+
+  Note that you might have to change the FILES settings in the
+  config.sys file under DOS.  (Under OS/2, the FILES setting of
+  config.sys applies only to DOS programs.)
+
+  When using the system call library (-Zsys, sys.lib) you have to call
+  DosSetMaxFH to increase the number of file handles.
+
+  The number of file handles and streams supported by the C library is
+  not limited.  However, a process inherits only the first 40 file
+  handles (0 through 39) of its parent process.
+
+þh1 Profiling
+
+  Profiling is used to find out where a program spends most of its
+  time, to be able to improve performance of the program by paying
+  special attention to those hot spots.
+
+  See also the GCOV chapter in the GCC manual.  Note that GCOV
+  currently requires support for long file names, that is, it won't
+  work on FAT drives.
+
+þipfminitoc
+
+þh2 Limitations
+
+  Currently, profiling is supported only for programs built with
+  emxbind; that is, you cannot use the -Zomf and -Zsys options of GCC.
+  Moreover, profiling is restricted to the main thread (thread 1), all
+  other threads are ignored.
+
+  Under OS/2, DosProfile, an unsupported and undocumented API is used.
+  That API may disappear in future versions of OS/2 or behave
+  differently in older versions of OS/2: Profiling has been tested
+  only under OS/2 Warp 3.0.
+
+  Under DOS, the periodic interrupt of the real-time clock is used.
+  If emx thinks another programs uses that interrupt, it silently
+  refuses to profile your program (all sampling counters will remain
+  zero).  Profiling also doesn't work if there is no real-time clock
+  or if it is not IBM-compatible.
+
+þh2 Preparing your program for profiling
+
+  You have to recompile your program for profiling, using the -pg or
+  -pn option of GCC.  The -pg option adds specials hooks to functions,
+  uses gcrt0.o instead of crt0.o (to start profiling when the program
+  is run), and uses library þtt{c_p.a} instead of þtt{c.a} (which has
+  been compiled with -pg and therefore contains profiling hooks).  The
+  profiling hooks added by -pg enable gprof to print a call graph
+  which shows which functions called which others, and how much time
+  each function used when its function calls are included.  The -pn
+  option does not add profiling hooks; it uses gcrt0.o instead of
+  crt0.o (to start profiling when the program is run).  Profiling with
+  -pn avoids the overhead caused by the profiling hooks; gprof won't
+  be able to print a call graph and won't know how many times the
+  functions have been called.  Do not use the -s option as gprof needs
+  the symbol table.
+
+  Note that þtt{gcrt0.o} is built from þtt{gmon.c} which is covered by
+  the BSD license (see þtt{\emx\doc\COPYING.BSD}).  þtt{gcrt0.o} is
+  distributed in þtt{bsddev.zip}, therefore you have to install
+  þtt{bsddev.zip} for profiling.
+
+þh2 Creating execution profiles
+
+  To collect profiling data for a program compiled with the -pg or -pn
+  option of GCC, just run it.  On termination of the program, a file
+  named gmon.out will be written in the (then) current working
+  directory.
+
+  A program compiled with the -pg option of GCC will run a bit
+  slower than if compiled without the -pg option.
+
+þh2 Viewing execution profiles
+
+  Change to the directory containing the gmon.out file and run gprof
+  on the executable file:
+
+þexample
+[C:\TEST]myprog args
+[C:\TEST]gprof myprog.exe
+þendexample
+
+  See the gprof manual for details (shipped in þtt{gnudoc.zip}).
+  gprof is distributed in þtt{bsddev.zip}, therefore you have to
+  install þtt{bsddev.zip} for profiling.
+
+  Note that the sampling frequency is 1024Hz under DOS, and 1000Hz
+  under OS/2.  gprof assumes a sampling frequency of 1024Hz under DOS,
+  and 1000Hz under OS/2.  When running gprof under OS/2 on a gmon.out
+  file created under DOS, or vice versa, the absolute timings will be
+  slightly incorrect, though the relative timings will still be valid.
+
+
+þh1 Tracing
+
+  All functions of emxlibcs.dll and emxlibcm.dll can be traced with
+  the OS/2 TRACE command.  If you want to trace the library calls of
+  an application, you have to link it dynamically (þhpt{-Zcrtdll}).
+
+þipfminitoc
+
+þh2 Preparing for tracing
+
+  The following changes should be made to your config.sys file:
+
+þitemize
+þitem
+  Add the þtt{c:\emx\etc} directory to the DPATH environment variable,
+  using the correct drive letter.
+þitem
+  Add the line
+þexample
+TRACEBUF=63
+þendexample
+  to enable tracing.
+þenditemize
+
+  Reboot the machine after changing config.sys.
+
+þh2 Groups and event types
+
+  All the functions of emxlibcs.dll and emxlibcm.dll are divided into
+  groups, to simplify tracing and to reduce the amount of trace data
+  being produced.  Each function belongs to exactly one group.  You
+  can enable and disable tracing for entire groups of tracepoints.
+  The following groups are defined:
+
+þdescription
+þitem þtt{CONV}
+  Converting strings to numbers and vice versa (<stdlib.h> etc.)
+þitem þtt{CTYPE}
+  Functions of <ctype.h>
+þitem þtt{DIR}
+  Reading and managing directories (<unistd.h>, <dirent.h>, etc.)
+þitem þtt{EA}
+  Extended attributes (<io.h>)
+þitem þtt{EMXLOAD}
+  emxload support (<sys/emxload.h>)
+þitem þtt{ENV}
+  environment (<stdlib.h>)
+þitem þtt{FNAME}
+  File names (<stdlib.h> etc.), e.g., þtt{_defext()}
+þitem þtt{GCC}
+  Compiler helper functions and other functions of þtt{libgcc} (þtt{gcc.a})
+þitem þtt{INIT}
+  Initialization and termination
+þitem þtt{LOCALE}
+  Locale support (<locale.h>)
+þitem þtt{LOWIO}
+  Low-level I/O (<io.h>, <unistd.h> etc.)
+þitem þtt{MALLOC}
+  Memory allocation (<stdlib.h>, <malloc.h>, and <umalloc.h>)
+þitem þtt{MATH}
+  Floating-point math (<math.h> and <float.h>)
+þitem þtt{NLS}
+  National language support (<sys/nls.h>)
+þitem þtt{OTHER}
+  All remaining functions
+þitem þtt{PROCESS}
+  Process management and thread management (<unistd.h>, <process.h> etc.)
+þitem þtt{PWD}
+  Password database (<pwd.h>), user IDs, group IDs, etc.
+þitem þtt{RTTI}
+  C++ Run Time Type Identification
+þitem þtt{SEM}
+  Semaphores (<sys/fmutex.h> etc.)
+þitem þtt{SIGNAL}
+  Signal processing (<signal.h>)
+þitem þtt{STDIO}
+  C stream I/O (<stdio.h>)
+þitem þtt{STRING}
+  String and buffer processing (<string.h>, <strings.h>, etc.)
+þitem þtt{SYSCALL}
+  emx system calls
+þitem þtt{TERMIOS}
+  POSIX.1 general terminal interface (<termios.h>)
+þitem þtt{TIME}
+  Time and date (<time.h> etc.)
+þenddescription
+
+  Each tracepoint has two event types: þtt{PRE} or þtt{POST} for the
+  Pre-Invocation tracepoint and Post-Invocation tracepoint,
+  respectively, and þtt{API} or þtt{INT} for API functions and
+  internal functions, respectively.  You can enable or disable tracing
+  by event type.
+
+þh2 Minor trace codes
+
+  Each function has a unique minor trace code.  You can enable tracing
+  of a function by specifying its minor trace code.  For functions
+  which are exported by the DLL, the minor trace code for
+  Pre-Invocation is identical to the ordinal number.  See
+  þtt{\emx\src\lib\cdll\emxlib.def} for the ordinal numbers.
+  Additionally, the following minor trace codes are defined:
+
+þdescription
+þitem 32767
+  þtt{_DLL_InitTerm()}
+þenddescription
+
+  To get the minor trace code for Post-Invocation, add 32768 to the
+  minor trace code for Pre-Invocation.
+
+þh2 Using the TRACE command
+
+  The following command enables tracing for all trace points of
+  emxlibcs.dll:
+
+þexample
+trace on emxlibcs
+þendexample
+
+  Usually, this generates too much data and causes the trace buffer to
+  wrap around.  The following command disables tracing for all trace
+  points of all DLLs:
+
+þexample
+trace on emxlibcs
+þendexample
+
+  The following command enables tracing of all functions of group
+  STDIO and all API functions of LOWIO:
+
+þexample
+trace on emxlibcs (stdio,lowio=api)
+þendexample
+
+  The following command enables tracing for all þtt{exec*()} and
+  þtt{spawn*()} functions:
+
+þexample
+trace on emxlibcs (100-107, 112-119)
+þendexample
+
+  See the OS/2 command reference (þtt{help trace}) for details.
+  Use the TRACEFMT command to view the contents of the trace buffer.
+
+
+þh1 Debugger (DOS)
+þlabel emx kernel debugger
+
+  emxd.exe contains a debugger (that's the difference between emx.exe
+  and emxd.exe).  Use the -S option to enable the debugger.  If you
+  want to debug using a terminal, enter -S1 to use COM1, -S2 to use
+  COM2.  To debug an emx program, type
+
+þindent
+  þsy{emxd -S [<options>] <program> [<arguments>]}
+þendindent
+
+  (which works with all emx programs) or
+
+þtypewriter
+  set emx=c:\emx\bin\emxd.exe þbreak
+  set emxopt=-S þbreak
+  þsy{<program>}
+þendtypewriter
+
+  (which doesn't work if emx.exe is bound to the program).  When
+  starting an emx program by running emx.exe or emxd.exe, the emx
+  options -d, -h#, -m#, -o, -p, -E, -F, -O, -P and -V set by emxbind
+  are ignored.  Pass these options on the command line instead.
+
+  þbf{Command keys:}
+
+þdescription
+þitem .
+
+        display registers and next instruction
+
+þitem :
+
+        show CS:EIP and next instruction (toggle)
+
+þitem BLANK
+
+        1 step
+
+þitem 0
+
+        10 steps
+
+þitem 1-9
+
+        1 through 9 steps
+
+þitem C
+
+        set breakpoint after next instruction and start program.  This
+        command should only be used on þtt{CALL} instructions
+
+þitem F
+
+        display floating point (387) status
+
+þitem N
+
+        step without stopping
+
+þitem F2
+
+        display registers and next instruction
+
+þitem F5
+
+        start program without setting breakpoint
+
+þitem F8
+
+        1 step
+
+þitem F10
+
+        set breakpoint after next instruction and start program
+
+þenddescription
+
+  þbf{Commands:}
+
+þlist
+þitem þsy{A <address>}
+
+        display inforomation about <address> (virtual, physical and
+        external addresses)
+
+þitem þsy{A <range>}
+
+        ditto, loop through <range> in steps of 1000H bytes
+
+þitem þsy{B}
+
+        display breakpoints and watchpoints
+
+þitem þsy{B <address>}
+
+        set breakpoint (default segment: CS).  Up to 3 breakpoints and
+        watchpoints can be set
+
+þitem þsy{D}
+
+        continue last þsy{D} command
+
+þitem þsy{D <address>}
+
+        display hex dump: 16 lines (default segment: DS)
+
+þitem þsy{D <range>}
+
+        display hex dump (default segment: DS)
+
+þitem þsy{G}
+
+        start program
+
+þitem þsy{G <address>}
+
+        set temporary breakpoint at <address> (default segment: CS)
+        and start program
+
+þitem þsy{I}
+
+        display process table: process index, process id, parent
+        process id, and file handle mapping
+
+þitem þsy{K}
+
+        display breakpoints and watchpoints
+
+þitem þsy{K <value>}
+
+        delete breakpoint or watchpoint (by number)
+
+þitem þsy{L <value>}
+
+        display info about selector <value>
+
+þitem þsy{L <value> <value>}
+
+        ditto, loop through range in steps of 8 (not 4!)
+
+þitem þsy{Q}
+
+        quit, return value 0
+
+þitem þsy{Q <value>}
+
+        quit and set the return value to <value>
+
+þitem þsy{R}
+
+        display registers and next instruction
+
+þitem þsy{R <register> <value>}
+
+        set register to <value>
+
+þitem þsy{R <condition>}
+
+        set/reset processor flag
+
+þitem þsy{S <range> <list>}
+
+        search memory
+
+þitem þsy{U}
+
+        continue last þsy{U} command
+
+þitem þsy{U <address>}
+
+        unassemble (default segment: CS)
+
+þitem þsy{V <value>}
+
+        display info about virtual address
+
+þitem þsy{V <value> <value>}
+
+        ditto, loop through range in steps of 1000H bytes
+
+þitem þsy{VP}
+
+        display info about pages that have physical memory assigned
+
+þitem þsy{VP <value>}
+
+        display info by physical address
+
+þitem þsy{VP <value> <value>}
+
+        ditto, loop through range in steps of 1000H bytes
+
+þitem þsy{VX}
+
+        display info about pages that have an external address
+
+þitem þsy{VX <value>}
+
+        display info by external address
+
+þitem þsy{VX <value> <value>}
+
+        ditto, loop through range in steps of 1000H bytes
+
+þitem þsy{W}
+
+        display breakpoints and watchpoints
+
+þitem þsy{W<l><a> <address>}
+
+        set watchpoint at given address (default segment: DS).
+        þsy{<l>} is þtt{B} (byte), þtt{W} (word, <address> must be
+        even) or þtt{D} (dword, the 2 low bits of <address> must be
+        zero).  þsy{<a>} is þtt{R} (trap read and write accesses),
+        þtt{W} (trap write accesses) or þtt{X} (trap modifying write
+        accesses).
+
+þitem þsy{X <value>}
+
+        find symbol at address <value> or below
+
+þendlist
+
+  The following arguments are used by the commands listed above:
+
+þlist
+þitem <address>
+
+þlist
+þitem þsy{[<value>:]<value>}
+
+    selector and offset.  If using the SS register for the selector
+    fails, type the value of SS as hexadecimal number
+
+þitem <symbol>
+
+    use address of variable or function <symbol>.  If <symbol> looks
+    like a hexadecimal number you lose
+
+þendlist
+
+þitem <condition>
+
+  Each processor flag has two states:
+
+þverbatim
+NC, CY, PE, PO, NA, AC, NZ, ZR, PL, NG, DI, EI, UP, DN, NV, OV
+þendverbatim
+
+þitem <register>
+
+   The following registers can be used:
+
+þverbatim
+EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP, EFLAGS,
+AX, BX, CX, DX, SI, DI, BP, SP, IP,
+AL, AH, BL, BH, CL, CH, DL, DH,
+CS, DS, ES, FS, GS, SS
+þendverbatim
+
+þitem <range>
+
+    A <range> includes all addresses between the start address and the
+    end address:
+
+þlist
+þitem þsy{<address> <address>}
+
+   The selectors of both addresses must be identical (the selector of
+   the second address should be omitted, it defaults to the selector
+   of the first address).  The second offset must be greater than or
+   equal to the first offset
+
+þendlist
+
+þitem <list>
+
+  A <list> is made of one or more values or multi-letter strings:
+
+  þsy{<value>|'<text>' ...}
+
+þitem <value>
+
+  A <value> is the basic element of an expression.
+
+þlist
+þitem þsy{0} through þsy{ffffffff}
+
+    Hexadecimal number
+
+þitem <register>
+
+    Current value of the register <register>
+
+þitem þsy{'<C>'}
+
+    Character code (ASCII) of the character þsy{<C>}
+
+þendlist
+þendlist
+
+  If the -S option is used, emx will display swapper statistics when
+  returning to DOS.  It displays
+
+þindent
+  þsy{Swapper statistics: F=<f> R=<r> W=<w> N=<n> S=<s>}
+þendindent
+
+  where þsy{<f>} is the number of page faults, þsy{<r>} is the number
+  of swapper file reads, þsy{<w>} is the number of swapper file
+  writes, þsy{<n>} is the number of times the swap space of present
+  pages has been recycled, and þsy{<s>} is the size of the swapper
+  file.  All numbers are decimal numbers.
+
+
+þh1 Executable file format
+
+þdescription
+þitem a.out
+
+    see þtt{/emx/include/a_out.h}
+
+þitem exe
+
+    OS/2 LX format with additional sections, see diagram below
+
+þenddescription
+
+þexample
+ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
+³                                 ³
+³ DOS .exe header:                ³
+³                                 ³
+³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ
+³  ³                              ³ÄÄÄÄÄÄÄÄ¿
+³  ³ Control information          ³ÄÄÄÄ¿   ³
+³  ³                              ³ÄÄ¿ ³   ³
+³  ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ<ÄÙ ³   ³
+³  ³                              ³    ³   ³
+³  ³ Relocation table             ³    ³   ³
+³  ³                              ³    ³   ³
+ÀÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ    ³   ³
+                                       ³   ³
+ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿<ÄÄÄÙ   ³
+³                                 ³        ³
+³ DOS (emx or emxl) image:        ³        ³
+³                                 ³        ³
+³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ        ³
+³  ³                              ³        ³
+³  ³ emxbind header (options)     ³ÄÄÄÄÄÄ¿ ³
+³  ³                              ³      ³ ³
+³  ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ      ³ ³
+³  ³                              ³      ³ ³
+³  ³ Code & data                  ³      ³ ³
+³  ³                              ³      ³ ³
+ÀÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ      ³ ³
+                                         ³ ³
+ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿<ÄÄÄÄÄÄÄÙ
+³                                 ³      ³
+³ OS/2 linear executable header:  ³      ³
+³                                 ³      ³
+³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ      ³
+³  ³                              ³      ³
+³  ³ Fixed-size header            ³ÄÄÄÄ¿ ³
+³  ³                              ³ÄÄ¿ ³ ³
+³  ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ<ÄÙ ³ ³
+³  ³                              ³    ³ ³
+³  ³ Loader section               ³ÄÄ¿ ³ ³
+³  ³                              ³  ³ ³ ³
+³  ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ<ÄÄÄÙ ³
+³  ³                              ³  ³   ³
+³  ³ Fixup section                ³  ³   ³
+³  ³                              ³  ³   ³
+ÀÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ  ³   ³
+ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿<ÄŽ   ³
+³                                 ³  ³   ³
+³ Resources                       ³  ³   ³
+³                                 ³  ³   ³
+ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ  ³   ³
+ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿<Ä³ÄÄÄÙ
+³                                 ³  ³
+³ a.out executable:               ³  ³
+³                                 ³  ³
+³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ  ³
+³  ³                              ³ÄÄ³ÄÄ¿
+³  ³ a.out header                 ³  ³  ³
+³  ³                              ³  ³  ³
+³  ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ<ÄŽ  ³
+³  ³                              ³  ³  ³
+³  ³ Text segment                 ³  ³  ³
+³  ³                              ³  ³  ³
+³  ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ<ÄÙ<ÄŽ
+³  ³                              ³     ³
+³  ³ Data segment                 ³     ³
+³  ³                              ³     ³
+³  ³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ     ³
+³  ³  ³                           ³     ³
+³  ³  ³ OS/2 emxbind header       ³     ³
+³  ³  ³                           ³     ³
+³  ³  ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ     ³
+³  ³  ³                           ³     ³
+³  ³  ³ Other data                ³     ³
+³  ³  ³                           ³     ³
+³  ÃÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ<ÄÄÄÄÙ
+³  ³                              ³
+³  ³ Symbol table                 ³
+³  ³                              ³
+ÀÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
+þendexample
+
+þh1 Known problems
+
+þitemize
+þitem
+
+  þhpt{sleep()} and þhpt{_sleep2()} hold signals under
+  DOS, that is, if the þhpt{alarm()} timer elapses, the signal handler
+  for SIGALRM isn't called until the completion of those functions
+
+þitem
+
+  when using the þhpt{-C# emx option}, memory allocated by an
+  unsuccessful þhpt{brk()} or þhpt{sbrk()} call isn't freed.  That is,
+  as soon as a þhpt{malloc()} call fails, further calls will also
+  fail.  Actually, this isn't a bug -- it's a lacking feature
+
+þitem
+
+  emx doesn't work under DOS if more than 64 MByte of memory is
+  installed
+
+þitem
+
+  running emx programs by a DOS program started by an emx program
+  seems not to work under certain circumstances [Is this still true?]
+
+þitem
+
+  breakpoints are shared by all instances of a program under OS/2 2.1
+  and earlier -- this is an OS/2 bug which seems to be fixed OS/2 2.11
+  (ServicePak XR06200 for OS/2 2.1)
+
+þitem
+
+  þhpt{fork()} doesn't work correctly in multithread programs.
+
+þenditemize
+
+þtext
+
+--------------------------- END OF EMXDEV.DOC ------------------------------
+þendtext
Index: trunk/src/emx/src/doc/emxgnu.src
===================================================================
--- trunk/src/emx/src/doc/emxgnu.src	(revision 18)
+++ trunk/src/emx/src/doc/emxgnu.src	(revision 18)
@@ -0,0 +1,2002 @@
+þtext
+===============================================================================
+emxgnu.doc        emx 0.9d     GNU DEVELOPMENT TOOLS INFORMATION    21-Dec-1998
+===============================================================================
+                                     Copyright (c) 1990-1998 by Eberhard Mattes
+þendtext
+
+þtitle GNU Development Tools Information
+
+þformat bold emx emxbind emximp emxomf emxomfld emxtsf pmgdb
+þformat bold GCC CPP GDB GAS GASP readline ld ar nm objdump GPPDEMID
+þformat bold genclass makeinfo texindex termcap texinfo
+
+þformat tty .a .cc .cpp .cxx .C .def .dll .exe .o .obj .res .map
+þformat tty install.doc build.doc emxl.exe emx.dll emxlibc.dll emxlibcm.dll
+þformat tty emxlibcs.dll emxomf.exe
+þformat tty gcc.exe cpp.exe cc1.exe cc1plus.exe cc1obj.exe as.exe
+þformat tty c_alias.a c_alias.lib sys.lib os2.a os2.lib
+þformat tty emx2.a emx2.lib libg++
+þformat tty dll0.o dll0.obj crt0.o lib1.a lib2.a
+þformat tty .gdbinit termcap.dat gppdemid.dll
+þformat tty /emx /emx/bin /emx/etc
+þformat tty -mepilogue -mno-epilogue -mprobe -mno-probe -pg -pn -fstack-check
+þformat tty -Zdll -Zexe -Zmt -Zmtd -Zmts -Zomf -Zstack -Zso -Zno-rte -Zcrtdll
+þformat tty -Zsys -Zno-demangle -Zdemangle-proto -Zbsd-signals -Zsysv-signals
+þformat tty -Zsmall-conv
+þformat tty -lgpp -lobjc -ltermcap -lbtermcap -lstdcpp -ltmalloc
+þformat tty -c -s -d -da -freg-struct-return
+þformat tty -fpcc-struct-return -E -R -l -r -b -ZC++-comments -Zc++-comments
+þformat tty -Zlinker -O -Xlinker -Zmap -Zstrip -Zbin-files
+
+þformat tty __MT__ __32BIT__ __EMX__
+
+þformat tty alloca() fopen() open() ptrace() malloc() _heapchk() _tmalloc()
+þformat tty fork()
+þformat tty <stdarg.h> <varargs.h> <fix-args.h>
+þformat tty DosCreateThread DosAllocMem
+
+þformat tty __.SYMDEF
+
+þformat abbrev etc. W.M.
+
+
+þif text
+þh= Table of Contents
+þtoc
+þendif
+
+
+þh1 Introduction to GNU Development Tools Information
+þipf
+:font facename=Helv size=24x14.:hp2.GNU Development Tools Information
+:ehp2.
+:p.
+:font facename=Helv size=16x10.      Copyright (c) 1990-1993 by Eberhard Mattes
+:font facename=default size=0x0.
+:p.
+þendipf
+
+  This text describes how to use the GNU C Compiler and other GNU
+  utilities with emx.
+þif text
+  See emxdev.doc for instructions for the emx utilities.
+þendif
+  For detailed information about GCC, GDB, and GAS, read the GCC, GDB,
+  and GAS manuals, see install.doc.  See build.doc for details on
+  compiling the GNU utilities.
+
+  All programs assume that the entire package is installed on one
+  disk drive in these directories:
+
+þexample
+/emx/bin           Executable files
+/emx/etc           termcap.dat
+/emx/lib           Library files
+/emx/include       Header files (C language)
+/emx/include/cpp   Header files (C++ language)
+/emx/include/objc  Header files (Objective C language)
+þendexample
+
+If the /emx directory is not on the current drive, use the
+C_INCLUDE_PATH and LIBRARY_PATH environment variables, for instance
+
+þexample
+set C_INCLUDE_PATH=c:/emx/include
+set LIBRARY_PATH=c:/emx/lib
+þendexample
+
+  to use drive C.
+
+  Use forward slashes instead of backward slashes in path names!
+
+  Directories:
+
+þexample
+/emx                            Main directory, empty
+/emx/bin                        Executable files and batch files
+/emx/dll                        Dynamic link libraries
+/emx/doc                        Documentation
+/emx/etc                        termcap.dat
+/emx/gnu/binutils.old           old GNU binary utilities (sources)
+/emx/gnu/binutils.26            new GNU binary utilities (sources)
+/emx/gnu/doc                    Documentation
+/emx/gnu/duel                   DUEL (for GDB)
+/emx/gnu/gcc-2.8                GNU C compiler source (GCC)
+/emx/gnu/gdb-4.16               GNU debugger source (GDB)
+/emx/gnu/gppdemid               C++ demangler for LINK386
+/emx/gnu/info                   GNU info source
+/emx/gnu/libtxi                 -libtxi  (for GNU info)
+/emx/gnu/libg++-2.8.1.1a        GNU C++ library (obsolete)
+/emx/gnu/libstdc++-2.8.1.1      GNU standard C++ library
+/emx/gnu/makeinfo               GNU makeinfo source
+/emx/gnu/termcap                GNU termcap
+/emx/gnu/texindex               GNU texindex source
+/emx/include                    header files (C language)
+/emx/include/cpp                Header files (C++ language)
+/emx/include/objc               Header files (Objective C language)
+/emx/lib                        Libraries
+þendexample
+
+
+þh1 GCC -- compiling and linking C and C++ programs
+þlabel GCC
+þi1 GCC
+þkeyword GCC
+
+  GCC 2.8.1 has been ported to emx, including Richard W.M. Jones's
+  bounds checking patches.
+
+þipfminitoc
+
+þh2 Calling GCC
+þlabel Calling GCC
+
+For small projects, one invokation GCC can be used to compile and link
+the program.  Example:
+
+þexample
+gcc dwim.c
+þendexample
+
+  This assumes that emxl.exe can be found in one of the directories
+  listed in the EMXPATH and PATH environment variables, or in the
+  directory /emx/bin, see also þhpt{ld}.  If no output file name is
+  given, the name of the first input file, with .exe extension (or
+  .dll extension if -Zdll is given), is used for the output file
+  unless linking is suppressed (with the -c option, for instance).
+  That is, the above example creates þtt{dwim.exe}.
+
+  Please note that the example given above creates a file named
+  þtt{dwim} which will be deleted after conversion to .exe format.
+
+  If the output file name doesn't end in .exe or .dll, the output file
+  will have a.out format (however, see þhpt{-Zexe}).  Example:
+
+þexample
+gcc -o dwim dwim.c
+þendexample
+
+  This example creates the a.out file `þtt{dwim}'.
+
+
+þh2 Environment variables
+þlabel Environment variables for GCC
+
+  If you want to develop programs on a drive different from the drive
+  where emx is installed, you have to set the C_INCLUDE_PATH and
+  LIBRARY_PATH environment variables, for instance,
+
+þexample
+set C_INCLUDE_PATH=c:/emx/include
+set LIBRARY_PATH=c:/emx/lib
+þendexample
+
+  If you want to compile þhpt{C++} programs, set CPLUS_INCLUDE_PATH as well:
+
+þexample
+set CPLUS_INCLUDE_PATH=c:/emx/include/cpp;c:/emx/include
+þendexample
+
+  If you want to compile þhpt{Objective C} programs, set
+  OBJC_INCLUDE_PATH as well:
+
+þexample
+set OBJC_INCLUDE_PATH=c:/emx/include
+þendexample
+
+  The genclass utility needs the following environment variable:
+
+þexample
+set PROTODIR=c:/emx/include/cpp/gen
+þendexample
+
+  If the TMPDIR, TMP and TEMP environment variables are not set, GCC
+  writes temporary files in the current working directory.  GCC tries
+  TMPDIR, TMP and TEMP in turn and uses the first valid one.  Note
+  that þtt{c:} is not a valid directory name, you have to use þtt{c:/}
+  or þtt{\} instead.  In other cases, a trailing slash or backslash is
+  optional.  For instance, use
+
+þexample
+SET TMPDIR=f:/tmp/
+þendexample
+
+  to put temporary files into the þtt{f:/tmp} directory.
+
+  When compiling projects consisting of many modules (such as
+  libraries) under OS/2, you can speed up compilation if you have
+  enough memory by keeping GCC in memory.  For example, to keep GCC in
+  memory for 5 minutes, use
+
+þexample
+set GCCLOAD=5
+þendexample
+
+  The following programs use GCCLOAD: gcc.exe, cpp.exe, cc1.exe,
+  cc1plus.exe, cc1obj.exe, as.exe and emxomf.exe.
+
+  You can put GCC options into the environment variable GCCOPT.  These
+  options will be read before the options given on the command line.
+  For example, to use þtt{-pipe}, type
+
+þexample
+set GCCOPT=-pipe
+þendexample
+
+þh2 Bounds checking
+
+  The emx port of GCC includes Richard W.M. Jones's bounds checking
+  patches.  See the GCC manual and þtt{\emx\gnu\doc\bounds\README} for
+  details.  The complete report is in
+  þtt{\emx\gnu\doc\bounds\bcrep2.ps} (shipped in þtt{gnudoc.zip}).
+  Use GhostScript if you don't have a PostScript printer.
+  þtt{\emx\gnu\doc\bounds\bcreport.txt} contains important excerpts
+  from an earlier version of the report as plain ASCII text.
+
+  There are a few additional restrictions under OS/2:
+
+þitemize
+þitem
+  Bounds checking is not available for multithread programs
+þitem
+  Bounds checking is available for statically linked programs only
+þitem
+  Bounds checking is not available for DLLs
+þitem
+  If your program uses _tmalloc(), you have use the -ltmalloc
+  option as the bounds checking library þtt{check.a} replaces
+  malloc()
+þenditemize
+
+  The header files <stdarg.h> and <varargs.h> automatically include
+  <fix-args.h> if bounds checking is enabled.  Therefore you don't
+  have to include <fix-args.h> yourself.
+
+
+þh2 #pragma statement
+þlabel #pragma statement
+þlabel #pragma pack()
+þindex #pragma pack()
+þkeyword #pragma
+
+  The emx port of GCC supports the
+
+þtypewriter
+  #pragma pack(þpa{N})
+þendtypewriter
+
+  statement where þpa{N} is 1, 2 or 4.  The default is 4.  Structure
+  fields are aligned to multiples of þpa{N} bytes, according to the
+  value þpa{N} as set by the last þtt{#pragma pack} statement.
+
+þexample
+#pragma pack()
+þendexample
+
+  reverts to the default (4).  Note that other C compilers revert to
+  the value in effect before the previous þtt{#pragma pack}
+  statement.
+
+
+þh2 Additional command line options
+þlabel Additional command line options
+
+  Several command line options have been added to GCC:
+
+þlist
+þitem þhpt{-mepilogue}
+
+    emit only one epilogue per function
+
+þitem -mno-epilogue
+
+    emit multiple epilogues per function if appropriate (default)
+
+þitem þhpt{-mprobe}
+
+    generate stack probes
+
+þitem -mno-probe
+
+    do not generate stack probes (default)
+
+þitem þhpt{-pn}
+
+    Enable profiling but do not generate profile hooks
+
+þitem þhpt{-Zbin-files}
+
+    open files in binary mode by default
+
+þitem þhpt{-Zbsd-signals}
+
+    select the `BSD' signal processing model
+
+þitem þhpt{-Zcrtdll}
+
+    link the C library dynamically
+
+þitem þhpt{-Zdll}
+
+    create a dynamic link library
+
+þitem þhpt{-Zexe}
+
+    touch output file, add .exe extension
+
+þitem þhpt{-Zmap}
+
+    let LINK386 or emxbind create a .map file
+
+þitem þhpt{-Zlinker}
+
+    pass option to LINK386
+
+þitem þhpt{-Zmt}
+
+    multithread code
+
+þitem þhpt{-Zmtd}
+
+    multithread code, link C library dynamically
+
+þitem þhpt{-Zmts}
+
+    multithread code, link C library statically
+
+þitem þhpt{-Zno-rte}
+
+    create DLL without runtime environment
+
+þitem þhpt{-Zomf}
+
+    create .obj files instead of .o files
+
+þitem þhpt{-Zsmall-conv}
+
+    use small, fast, and inaccurate routines for converting decimal
+    numbers to binary and vice versa
+
+þitem þhpt{-Zstack}
+
+    set the stack size
+
+þitem þhpt{-Zso}
+
+    create stand-alone DLL
+
+þitem þhpt{-Zsys}
+
+    create stand-alone OS/2 program (no emx.dll)
+
+þitem þhpt{-Zsysv-signals}
+
+    select the `System V' signal processing model
+
+þendlist
+
+  The following table shows which compiler phases are affected by the
+  options.  If an option affects the preprocessor, the compiler, or
+  the assembler, you should use that option when compiling.  When an
+  option affects the linker, you should use that option when linking.
+  However, you can use options affecting the preprocessor, the
+  compiler, or the assembler also when not compiling; you can use
+  options affecting the linker also when not linking.
+
+þexample
+               ³ Prepro- ³ Com-  ³ Assem- ³
+Option         ³ cessor  ³ piler ³ bler   ³ Linker
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄ
+-mepilogue     ³    X    ³   X   ³        ³
+-mno-epilogue  ³    X    ³   X   ³        ³
+-mprobe        ³         ³   X   ³        ³
+-mno-probe     ³         ³   X   ³        ³
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄ
+-pg            ³    X    ³   X   ³        ³   X
+-pn            ³         ³       ³        ³   X
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄ
+-Zcrtdll       ³         ³       ³        ³   X
+-Zdll          ³         ³       ³        ³   X
+-Zmt           ³    X    ³       ³        ³   X
+-Zmtd          ³    X    ³       ³        ³   X
+-Zmts          ³    X    ³       ³        ³   X
+-Zomf          ³    X    ³       ³   X    ³   X
+-Zno-rte       ³         ³       ³        ³   X
+-Zso           ³         ³       ³        ³   X
+-Zsys          ³         ³       ³        ³   X
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄ
+-Zexe          ³         ³       ³        ³   X
+-Zlinker       ³         ³       ³        ³   X
+-Zmap          ³         ³       ³        ³   X
+-Zstack        ³         ³       ³        ³   X
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄ
+-Zbin-files    ³         ³       ³        ³   X
+-Zbsd-signals  ³         ³       ³        ³   X
+-Zsmall-conv   ³         ³       ³        ³   X
+-Zsysv-signals ³         ³       ³        ³   X
+þendexample
+
+
+þh3 -mepilogue
+þlabel -mepilogue
+þi2 -mepilogue
+þi2 -mno-epilogue
+þkeyword -mepilogue -mno-epilogue
+
+  By default (-mno-epilogue), GCC may emit multiple epilogues (return
+  statements) per function if appropriate. With -mepilogue, GCC emits
+  only one epilogue at the end of each function; any function exit in
+  the middle of a function jumps to the epilogue at the end of the
+  function.  Moreover, -mepilogue causes a symbol to be defined at the
+  start of the epilogue code.  The name of that symbol is constructed
+  by prepending `tt{__POST$}' to the function's label.
+
+  -mno-epilogue generates faster code. For tracing with the OS/2
+  þtt{TRACE} command, however, each function should have only one
+  epilogue, so that a tracepoint can be defined for the epilogue.
+
+  The C library for emx has been compiled with -mepilogue to enable
+  tracing of DLLs.  See also þhpt{emxtsf}.
+
+þh3 -mprobe
+þlabel -mprobe
+þi2 -mprobe
+þi2 -mno-probe
+þkeyword -mprobe -mno-probe
+
+  -mprobe enables generation of þhpt{stack probes} (see below),
+  -mno-probe (which is the default) disables generation of stack
+  probes.  See also GCC's -fstack-check option.
+
+  All libraries for emx are compiled with both stack probes and stack
+  checking enabled.
+
+
+þh3 -pn
+þlabel -pn
+þi2 -pn
+þkeyword -pn
+
+  -pn enables profiling by using þtt{gcrt0.o} instead of þtt{crt0.o}
+  for linking the program.  In contrast to -pg, no profiling hooks are
+  generated.
+
+þh3 -Zbin-files
+þlabel -Zbin-files
+þi2 -Zbin-files
+þkeyword -Zbin-files
+
+  The additional GCC command line option -Zbin-files causes the
+  program to be linked with þtt{binmode.o}, selecting binary mode
+  as default for fopen(), open(), etc.
+
+
+þh3 -Zbsd-signals
+þlabel -Zbsd-signals
+þi2 -Zbsd-signals
+þkeyword -Zbsd-signals
+
+  The additional GCC command line option -Zbsd-signals causes the
+  program to be linked with þtt{sigbsd.o}, selecting the `BSD' signal
+  processing model.  See also þhpt{-Zsysv-signals}.  -Zbsd-signals
+  cannot be used with þhpt{-Zsys}.
+
+
+þh3 -Zcrtdll
+þlabel -Zcrtdll
+þi2 -Zcrtdll
+þkeyword -Zcrtdll
+
+  -Zcrtdll causes the executable file to be linked dynamically to the
+  C runtime library.  If -Zmt is also given, the program will use
+  emxlibcm.dll.  Otherwise, the program will use emxlibcs.dll.
+  Without -Zcrtdll, the executable file is linked statically to the C
+  runtime library.
+
+  -Zcrtdll uses the import library þtt{c_import} and a small static
+  library (þtt{c_static}) which contains code that must be linked
+  statically.  To link with a different import library, use
+  þsy{-Zcrtdll=<lib>} instead of -Zcrtdll.  The library name
+  þsy{<lib>} must not include a directory or a suffix.  The library
+  will be sought in the standard library path, therefore you can use
+  the þtt{-L} option for adding another library directory.  Example:
+þexample
+gcc -Zcrtdll=myclib -L/mylib myprog.c
+þendexample
+þif ipf
+  See also þhpt{-Zmt}, þhpt{-Zmtd}, þhpt{-Zmts}, and þhpt{Startup
+  modules and libraries}.
+þendif
+
+
+þh3 -Zdll
+þlabel -Zdll
+þi2 -Zdll
+þkeyword -Zdll
+
+  The additional GCC command line option -Zdll causes the program to
+  be linked with dll0.o (or dll0.obj if þhpt{-Zomf} is given) instead
+  of crt0.o.  This is required for creating dynamic link libraries.
+þif ipf
+  See also þhpt{Startup modules and libraries}.
+þendif
+
+
+þh3 -Zexe
+þlabel -Zexe
+þi2 -Zexe
+þkeyword -Zexe
+
+  To avoid changing Unix-style makefiles, the additional GCC command line
+  option -Zexe can be used.  If -Zexe is present, the linker (ld or
+  emxomfld) automatically adds the .exe extension to the output file
+  name and creates an empty file of that name (without .exe) to keep
+  the þbf{make} utility happy.  The output file name must not have an
+  extension.  See the descriptions of þhpt{ld} and þhpt{emxomfld} for details.
+
+þh3 -Zlinker
+þlabel -Zlinker
+þi2 -Zlinker
+þkeyword -Zlinker
+
+  Use the additional GCC command line option -Zlinker to pass an
+  option to LINK386.  -Zlinker should be used only when using the
+  -Zomf option.  The argument following -Zlinker will be passed to
+  þhpt{emxomfld} (preceded by an -O option) which in turn will pass it
+  to LINK386.  The LINK386 option must start with a slash.  Example:
+
+þexample
+gcc yzzyx.obj -Zomf -Zlinker /runfromvdm
+þendexample
+
+  Don't confuse the -Zlinker option with the -Xlinker option, which
+  passes an option to þhpt{ld} or emxomfld.
+
+þh3 -Zmap
+þlabel -Zmap
+þi2 -Zmap
+þkeyword -Zmap
+
+  Use the additional GCC command line option -Zmap to let LINK386 or
+  emxbind create a .map file.  The name of the .map file will be
+  derived from the output file name, both LINK386 and emxbind add the
+  default extension .map.  To specify the name of the .map file, use
+  þsy{-Zmap=<map_file>}.
+
+  GCC passes the -Zmap option down to emxomfld (or ld) which passes
+  the file name down to LINK386 (or emxbind).
+
+  To get a detailed .map file including all the public symbols, also
+  use þtt{-Zlinker /map} with -Zomf.  By default, the .map file
+  created by LINK386 lists only the segments.  Example:
+
+þexample
+gcc -o dwimtest.exe dwim.c -Zomf -Zmap -Zlinker /map
+þendexample
+
+  Note that LINK386 creates the .map file in the same directory as the
+  .exe file unless the name of the .map file includes a path.
+
+þh3 -Zmt
+þlabel -Zmt
+þi2 -Zmt
+þkeyword -Zmt
+
+  Use the additional GCC command line option -Zmt to compile
+  multithread code.  The preprocessor macro __MT__ will be
+  defined when -Zmt is used.
+þif ipf
+  See also þhpt{-Zmts} and þhpt{-Zmtd}.
+þendif
+
+
+þh3 -Zmtd
+þlabel -Zmtd
+þi2 -Zmtd
+þkeyword -Zmtd
+
+  Use the additional GCC command line option -Zmtd to link a
+  multithread program that uses emxlibcm.dll, the DLL version of
+  the C library.  The preprocessor macro __MT__ will be defined when
+  -Zmtd is used.  -Zmtd is equivalent to -Zmt -Zcrtdll and is provided
+  for compatibility with existing makefiles.
+þif ipf
+  See also þhpt{-Zcrtdll}, þhpt{-Zmt}, þhpt{-Zmts}, and þhpt{Startup
+  modules and libraries}.
+þendif
+
+
+þh3 -Zmts
+þlabel -Zmts
+þi2 -Zmts
+þkeyword -Zmts
+
+  Use the additional GCC command line option -Zmts to link a
+  multithread program which is statically linked with the C
+  library.  The preprocessor macro __MT__ will be defined if -Zmts is
+  used.  -Zmts is equivalent to -Zmt (without -Zcrtdll) and is provided
+  for compatibility with existing makefiles.
+þif ipf
+  See also þhpt{-Zcrtdll}, þhpt{-Zmt}, þhpt{-Zmtd}, and þhpt{Startup
+  modules and libraries}.
+þendif
+
+
+þh3 -Zno-rte
+þlabel -Zno-rte
+þi2 -Zno-rte
+þkeyword -Zno-rte
+
+  Use -Zno-rte with þhpt{-Zdll} and þhpt{-Zomf} (all of which must be
+  specified) to create a DLL without runtime environment
+  not use the runtime environment of its client application.
+  þhpt{-Zcrtdll}, þhpt{-Zmt}, þhpt{-Zmtd}, þhpt{-Zmts}, þhpt{-Zso}, and
+  þhpt{-Zsys} must not be used with -Zno-rte.
+þif ipf
+  See also þhpt{Startup modules and libraries}.
+þendif
+
+
+þh3 -Zomf
+þlabel -Zomf
+þi2 -Zomf
+þkeyword -Zomf
+
+  The additional GCC command line option -Zomf causes GCC to call
+  þhpt{emxomf} for converting .o files to .obj files and to call
+  þhpt{emxomfld} instead of þhpt{ld}.  As emxomfld calls LINK386, this
+  option works only under OS/2.  You should use a module definition
+  file (.def file) or the þhpt{-Zstack} option if you need a stack
+  bigger than 0x8000 bytes.  Note that LINK386 adds a default
+  extension (.exe or .dll) to the output file name.
+
+þh3 -Zsmall-conv
+þlabel -Zsmall-conv
+þi2 -Zsmall-conv
+þkeyword -Zsmall-conv
+
+  The additional GCC command line option -Zomf causes the program to
+  be linked with þtt{smallcnv.o}, select smaller, faster, and
+  inaccurate routines for converting decimal numbers to binary and
+  vice versa.  By default, accurate conversion routines are used.
+  -Zsmall-conv saves about 14KB for programs which use binary to
+  decimal conversions, about 11KB for programs which use decimal to
+  binary conversions, and about 15KB for programs which use both.
+
+  The -Zsmall-conv option cannot be used with the -Zcrtdll option;
+  the C runtime DLLs always use the accurate conversion routines.
+
+þh3 -Zstack
+þlabel -Zstack
+þi2 -Zstack
+þkeyword -Zstack
+
+  The -Zstack option sets the OS/2 stack size of the executable.
+  -Zstack takes an argument, which is the stack size in KByte.  The
+  stack size can be given in decimal, octal or hexadecimal, using C
+  notation.  The -Zstack option is passed down unmodified to þhpt{ld}
+  or þhpt{emxomfld}.  Example:
+
+þexample
+gcc bigstack.c -Zomf -Zstack 0x2000
+þendexample
+
+  This sets the stack size to 8 MBytes.
+
+þh3 -Zso
+þlabel -Zso
+þi2 -Zso
+þkeyword -Zso
+
+  Use -Zso with þhpt{-Zdll}, þhpt{-Zsys}, and þhpt{-Zomf} (all of
+  which must be specified) to create a stand-alone DLL, that is, a DLL
+  which does not use the runtime environment of its client application
+  but has a runtime environment of its own.
+þif ipf
+  See also þhpt{Startup modules and libraries}.
+þendif
+
+
+þh3 -Zsys
+þlabel -Zsys
+þi2 -Zsys
+þkeyword -Zsys
+
+  Use -Zsys with þhpt{-Zomf} to link with the system call library (emx
+  emulator) sys.lib instead of using the run time library emx.dll for
+  system calls.  The library version of the system calls provide only
+  a subset of the emx system call interface.  þhpt{fork()}, for
+  instance, isn't supported with -Zsys.  DLLs created with -Zsys must
+  be either custom C runtime DLLs or stand-alone DLLs (see þhpt{-Zso}).
+þif ipf
+  See also þhpt{Startup modules and libraries}.
+þendif
+
+
+þh3 -Zsysv-signals
+þlabel -Zsysv-signals
+þi2 -Zsysv-signals
+þkeyword -Zsysv-signals
+
+  The additional GCC command line option -Zsysv-signals causes the
+  program to be linked with þtt{sigsysv.o}, selecting the `System V'
+  signal processing model.  See also þhpt{-Zbsd-signals}.
+  -Zsysv-signals cannot be used with þhpt{-Zsys}.
+
+
+þh2 Special file extensions
+þlabel Special file extensions
+
+  You can give the name of a module definition file on the command
+  line.  The name must end with .def and is passed to þhpt{ld}, which
+  in turn passes it to þhpt{emxbind}.  When using þhpt{-Zomf}, the
+  name is passed to þhpt{emxomfld}, which in turn passes it to
+  LINK386.  If the output file names ends with .dll, a default module
+  definition file is used by emxbind unless a .def file is given on
+  the GCC command line.
+
+  You can give the name of a binary resource file on the command
+  line.  The name must end with .res and is passed to ld, which in
+  turn passes it to emxbind.  When using -Zomf, the name is passed to
+  emxomfld, which runs þbf{rc} to copy the resources to the output
+  file.
+
+þh2 Startup modules and libraries
+þlabel Startup modules and libraries
+
+  The following table shows the startup module and the libraries
+  passed to the linker by GCC, depending on the command line options
+  þhpt{-Zcrtdll}, þhpt{-Zmt}, þhpt{-Zomf}, þhpt{-Zso}, þhpt{-Zsys}, and
+  þhpt{-Zdll}.  Note that -Zmtd is equivalent to -Zmt -Zcrtdll and
+  -Zmts is equivalent to -Zmt without -Zcrtdll:
+
+þexample
+Options                      ³Startup³ Libraries
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+-Zomf not specified          ³ *.o   ³ *.a
+-Zomf specified              ³ *.a   ³ *.lib
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+(none)                       ³ crt0  ³ gcc st/c st/c_app   st/emx emx2
+                         -Zmt³ crt0  ³ gcc mt/c mt/c_app   mt/emx emx2
+              -Zsys          ³ crt0  ³ gcc st/c st/c_app   st/sys
+              -Zsys      -Zmt³ crt0  ³ gcc mt/c mt/c_app   mt/sys
+      -Zcrtdll               ³ crt0  ³ c_static st/c_import       emx2
+      -Zcrtdll           -Zmt³ crt0  ³ c_static mt/c_import       emx2
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+-Zdll                        ³ dll0  ³ gcc st/c st/c_dllrt st/emx emx2
+-Zdll                    -Zmt³ dll0  ³ gcc mt/c mt/c_dllrt mt/emx emx2
+-Zdll         -Zsys          ³ dll0  ³ gcc st/c st/c_dllrt st/sys
+-Zdll         -Zsys      -Zmt³ dll0  ³ gcc mt/c mt/c_dllrt mt/sys
+-Zdll         -Zsys -Zso     ³ dll0  ³ gcc st/c st/c_dllso st/sys
+-Zdll         -Zsys -Zso -Zmt³ dll0  ³ gcc mt/c mt/c_dllso mt/sys
+-Zdll         -Zno-rte       ³ dll0  ³ gcc st/c c_dllnrt
+-Zdll -Zcrtdll               ³ dll0  ³ c_static st/c_import       emx2
+-Zdll -Zcrtdll           -Zmt³ dll0  ³ c_static mt/c_import       emx2
+þendexample
+
+  In addition to the libraries mentioned above, the alias library
+  (c_alias.a or c_alias.lib) and the OS/2 import library (os2.a or
+  os2.lib) are always passed to the linker.  If -Zomf is used,
+  þtt{end.lib} is also passed to the linker.  Note that -Zomf must be
+  used if -Zsys is used.
+
+þh2 Assertions
+þlabel Assertions
+
+  The following assertions are predefined in the emx port of GCC:
+  þtt{#system(unix)}, þtt{#system(emx)}, þtt{#cpu(i386)} and
+  þtt{#machine(i386)}.
+
+
+þh2 C++
+þlabel C++
+
+  Files containing C++ programs should have one of the following file
+  name extensions:
+
+þdescription
+þitem .cc
+
+    Unix style
+
+þitem .cpp
+
+    PC style (GCC has been patched to recognize this)
+
+þitem .cxx
+
+    (?)
+
+þitem .C
+
+    Type an upper-case C!
+
+þenddescription
+
+  Use the -lstdcpp command line option to link C++ programs with the
+  GNU standard C++ library (þhpt{libstdc++}), which includes the
+  former iostream library.
+
+  Use the -lgpp command line option to link C++ programs with the GNU
+  C++ class libraray (þhpt{libg++}).  If you link with libg++,
+  you have to obey the rules stated in þtt{/emx/doc/COPYING.LIB}.
+
+  Example:
+
+þexample
+gcc hello.cc -lstdcpp -s
+þendexample
+
+  The þbf{collect} program is not required with the emx port of GCC.
+
+  Hint: Use the -s option (of GCC, þhpt{emxomf} or þhpt{emxbind}) to
+  remove the symbol table; it's quite big.
+
+
+þh2 Objective C
+þlabel Objective C
+
+  To link a program written in the Objective C language, you have to
+  use library þtt{objc}: use -lobjc on the GCC command line.  Example:
+
+þexample
+gcc objcsamp.m -lobjc -s
+þendexample
+
+  Note that GCC does not include any class libraries for Objective C.
+
+
+þh2 Stack probes
+þlabel Stack probes
+þlabel stack probes
+
+  Stack probes are used to manage automatic stack growth if the stack
+  is not completely committed.  When allocating stack space, the new
+  stack pages are touched before changing the stack pointer to make
+  them accessible.  Generation of stack probes is disabled by default.
+  Use the þhpt{-mprobe} option to enable generation of stack probes.
+
+  The -fstack-check option of GCC generates stack probes for stack
+  checking; when there's not enough stack space, an exception will be
+  generated.  Unlike -mprobe, -fstack-check guarantees "enough" stack
+  space left for running a simple exception handler.
+
+  You need stack probes if
+
+þitemize
+þitem
+
+  you use DosCreateThread to create a thread that doesn't have a
+  completely committed stack, that is, if bit 1 of the
+  þsl{ulThreadFlags} argument is zero, or
+
+þitem
+
+  you create a DLL which might be used by an application which uses
+  DosCreateThread to create a thread that doesn't have a completely
+  committed stack, or
+
+þitem
+
+  you want to trap the stack overflow exception issued when hitting
+  the guard page at the bottom of the stack.  (You should use
+  -fstack-check instead of -mprobe.)
+
+þenditemize
+
+  Stack probes are not generated for all allocations of stack space: A
+  stack probe is not generated if the size of the allocated memory
+  block is constant and less than 4096 bytes.  This optimization
+  causes a problem if two such allocations of stack space occur
+  without access to the stack between the allocations.  There are two
+  occasions for this: Two calls in a row to þhpt{alloca()} with
+  constant argument which is less than 4096 and where nothing is
+  stored to the first pointer returned by alloca() before getting the
+  second pointer:
+
+þexample
+p = alloca (0xf00);
+q = alloca (0xf00);
+þendexample
+
+  The second case is a function with less than 4096 bytes of local
+  data which calls alloca() with constant argument which is less than
+  4096 before accessing a local variable or calling a function:
+
+þexample
+void test (void)
+{
+  char local[0xf00], *p;
+
+  p = alloca (0xf00);
+  /*...*/
+}
+þendexample
+
+  As both cases are unlikely to occur in practice, I chose to not
+  generate a stack probe for less than 4096 bytes.  If you experience
+  problems (that is, stack exceptions), insert the statement
+
+þexample
+{char *p=alloca (0); *p = 0;}
+þendexample
+
+  in critical places, as between the two alloca() calls in the first
+  example and before the alloca() call in the second example.
+
+  All emx libraries are compiled with both stack probes and stack
+  checking enabled.
+
+
+þh2 Other changes
+þlabel Other changes
+
+  The preprocessor CPP defines the symbols __32BIT__ and __EMX__.  If
+  the þhpt{-Zmt}, þhpt{-Zmts}, or þhpt{-Zmtd} option is given on the
+  GCC command line, the symbol __MT__ is defined.
+
+  The file name extensions of the debugging output files (-d option)
+  have been changed as follows:
+
+þexample
+combine  -> cmb
+cse      -> cs1
+cse2     -> cs2
+flow     -> flo
+greg     -> gre
+jump     -> jp1
+jump2    -> jp2
+loop     -> loo
+lreg     -> lre
+sched    -> sd1
+sched2   -> sd2
+stack    -> stk
+þendexample
+
+  The extension is added to the base name of the input file, not to
+  the complete name of the input file.  For instance, when compiling
+  þtt{world.c}, the file þtt{world.cs1} will be created instead of
+  þtt{world.c.cse}.  If using the -da GCC option, you should use the
+  þtt{-h30} emx option.
+
+
+þh2 Calling conventions
+þlabel Calling conventions
+
+  The calling convention used by GCC is almost compatible with the
+  `þtt{system}' calling convention of IBM C Set/2.  Structures are
+  returned differently: IBM C Set/2 uses a hidden parameter which is
+  removed from the stack by the caller, GCC returns the structure in
+  registers EAX and EDX if its size is 8 bytes or less
+  (-freg-struct-return is the default).  GCC uses a hidden parameter
+  if the size of the structure is more than 8 bytes, but the callee
+  removes the hidden parameter from the stack.  Currently, the GCC
+  option -fpcc-struct-return doesn't solve that problem.  Instead,
+  rewrite the function and the function call as follows:
+
+þexample
+/* Original code */
+struct s1 func1 (int a1)
+{
+  struct s1 t1;
+  ...
+  return (t1);
+}
+...
+
+struct s1 v1;
+v1 = f1 (0);
+þendexample
+
+
+þexample
+/* Modified code */
+
+struct s1 *f1 (struct s1 *ret, int a1)
+{
+  struct s1 t1;
+  ...
+  *ret = t1;
+  return (ret);
+}
+
+...
+
+struct s1 v1;
+f1 (&v1, 0);
+þendexample
+
+þi1
+
+þh1 libg++ -- the GNU C++ library (gpp.a and gpp.lib)
+þlabel libg++
+þlabel gpp
+þindex libg++
+þindex gpp
+
+  libg++ 2.8.1.1a, the obsolete GNU C++ library, has been ported to
+  emx.
+
+  If you link with libg++, (-lgpp), you have to obey the rules
+  stated in þtt{/emx/doc/COPYING.LIB}.
+
+  Due to name collisions, the following include files have been renamed:
+
+þexample
+Complex.h   -> Complx.h
+Regex.h     -> Regx.h
+String.h    -> Strng.h
+þendexample
+
+
+þh1 libstdc++ -- the GNU standard C++ library
+þlabel libstdc++
+þindex libstdc++
+
+  libstdc++ 2.8.1.1, the GNU standard C++ library, is provided for emx.
+  Use the -lstdcpp option to link with that library.
+  See þtt{/emx/doc/COPYING.SCP} for copyright information.
+
+  The þtt{istream::seekg}, þtt{istream::tellg}, þtt{ostream::seekp},
+  and þtt{ostream::tellg} methods do not work for text files.
+
+
+þh1 GDB -- debugging programs
+þlabel GDB
+þindex GDB
+þkeyword GDB
+
+  GDB uses GNU þhpt{readline}, see below.  GDB works only with a.out
+  files (under DOS) and with bound files (both under OS/2 and DOS),
+  not with arbitrary DOS or OS/2 progams.  The DUEL debugging language
+  has been added to GDB, see below.  Anthony Green's þhpt{GDBRX}
+  extension has been added to GDB, see below.
+
+  See the GDB manual for details.
+
+  A preliminary version of a Presentation Manager front end for GDB is
+  shipped with emx.  See the online help and the online tutorial of
+  pmgdb for details.
+
+þh2 Example
+
+  The following example shows how to debug a fictitious program
+  þtt{myprog.exe}.  See install.doc for an example with one of the emx
+  sample programs.
+
+þexample
+C> gcc -g myprog.c                                   (compile)
+C> gdb myprog.exe                                    (start debugger)
+(gdb) set args -o myprog.out myprog.in               (set arguments)
+(gdb) b main                                         (set breakpoint)
+(gdb) run                                            (start program)
+(gdb) dl argv[0..argc-1]                             (display arguments)
+(gdb) s                                              (step)
+þendexample
+
+  Command line arguments for the program to be debugged can be passed
+  on the GDB command line if the þtt{--args} option is used:
+
+þexample
+C> gcc -g myprog.c                                   (compile)
+C> gdb --args myprog.exe -o myprog.out myprog.in     (start debugger)
+(gdb) b main                                         (set breakpoint)
+(gdb) run                                            (start program)
+(gdb) dl argv[0..argc-1]                             (display arguments)
+(gdb) s                                              (step)
+þendexample
+
+  If the executable file cannot be found and does not include a
+  filename extension, GDB appends `þtt{.exe}' to the filename and
+  tries again.
+
+  Continuing the example, if there's no file named `þtt{myprog}', you
+  can omit the `þtt{.exe}' extension of the executable file name:
+
+þexample
+C> gdb --args myprog -o myprog.out myprog.in
+þendexample
+
+  That is, you can just prepend `þtt{gdb --args}' to the command line.
+
+þh2 Restrictions
+
+  Please do not use backslashes in path names.  For your convenience,
+  backslashes in path names specified as command line arguments of GDB
+  are automatically turned into slashes.  For commands entered
+  interactively, you have to use slashes yourself.
+
+  The following GDB commands do not work or do not work completely or
+  have been changed:
+
+þitemize
+þitem
+
+ `þtt{signal}' does not work under OS/2 unless the same signal is used
+  by which the debuggee has been stopped
+
+þitem
+
+  `þtt{attach}' and `þtt{detach}' cannot work in general; however,
+  these commands can be used in a limited way for descendant processes
+  as explained below
+
+þitem
+
+  `þtt{tty}' and `þtt{term-status}' are not implemented
+
+þitem
+
+  `þtt{directory}' has been changed to use semicolons instead of
+  colons for separating directories.
+
+þitem
+
+  `þtt{watch}' is almost unusable because GDB disables the watchpoints
+  as soon as a function without debugging symbols is called, such as
+  an OS/2 API function.  That could be fixed by making GDB believe
+  that the functions in os2.a have debugging symbols.
+
+þenditemize
+
+þh2 Special features
+
+  Various special features have been added to the emx port of GDB.
+
+þipfminitoc
+
+þh3 Setting command line arguments for the program being debugged
+
+  The þtt{--args} option of GDB causes all arguments following the
+  name of the executable file on the command line of GDB to be used as
+  arguments for the program for the program being to debugged.
+  Example:
+
+þexample
+gdb --args -nx myprog.exe -o myprog.out myprog.in
+þendexample
+
+  This invocation of GDB is equivalent to running
+
+þexample
+gdb -nx myprog.exe
+þendexample
+
+  and typing the GDB command
+
+þexample
+set args -o myprog.out myprog.in
+þendexample
+
+  However, the `þtt{set args}' command supports redirection operators,
+  whereas þtt{--args} passes them as command line arguments to the
+  program being debugged.  The `þtt{show args}' command does not print
+  the equivalent `þtt{set args}' arguments for achieving the effect of
+  þtt{--args}; for instance, quoting is not correct.
+
+þh3 Running the debuggee in the same window
+
+  If you want to run the debuggee in the same OS/2 session (window) as
+  GDB (for instance if you're running GDB in a full-screen session),
+  use the -E emx option.
+
+þh3 Switching sessions
+
+  By default, GDB selects the child session when executing a þtt{CALL}
+  instruction of the inferior process.  Use the `þtt{set switch off}'
+  command to disable that feature.  Use `þtt{set switch on}' to turn
+  on switching to the child session.  Use `þtt{show switch}' to
+  display the current setting.  Under DOS, `þtt{set switch}' is
+  ignored.
+
+  To debug a Presentation Manager application, run GDB full-screen and
+  use `þtt{set switch on}'.  Do not manually switch to the
+  Presentation Manager session while the program is stopped!
+  Otherwise the Presentation Manager will hang and you will have to reboot.
+  Alternatively, you can use pmgdb to debug Presentation Manager
+  applications.
+
+  As import method þhpt{(I1)} uses a þtt{JMP} instruction instead of a
+  þtt{CALL} instruction to call OS/2 API functions, the `þtt{stepi}'
+  command must not be used to step into the code generated by emximp
+  for a method (I1) import.  Use `þtt{nexti}' on the call to that
+  code, instead.
+
+þh3 Closing the window after termination of the debuggee
+
+  Use the `þtt{set close}' command to control whether to close the
+  child session window after termination of the debuggee.  `þtt{set
+  close off}' is the default -- the window will stay open.  After a
+  debuggee has been started, `þtt{set close}' doesn't take effect for
+  that debuggee.
+
+þh3 Debugging threads
+
+  You can freeze a thread with the `þtt{thread disable}' command
+  (`þtt{freeze}' is an alias).  Without argument, this command freezes
+  the current thread.  Otherwise, the argument must be a thread
+  number.  A frozen thread won't execute until you thaw it.
+
+  You can thaw a thread with the `þtt{thread enable}' command
+  (`þtt{thaw}' is an alias).  Without argument, this command thaws the
+  current thread.  Otherwise, the argument must be a thread number.
+
+  You can freeze or thaw multiple threads with one command by using
+  `þtt{thread apply}':
+
+þexample
+thread apply all thaw
+thread apply 2-4 6 freeze
+þendexample
+
+  Restarting the process being debugged while the current thread is
+  frozen will result in this message:
+
+þexample
+ptrace: No such process.
+þendexample
+
+  Use the `þtt{thread}' command to switch to an enabled thread when
+  this happens:
+
+þexample
+thread 5
+þendexample
+
+  Note that debugging multithread processes has some rough edges.  See
+  the GDB manual for more information on debugging multithread
+  processes.
+
+þh3 Debugging DLLs
+
+  GDB automatically loads the symbols of DLLs created with ld and
+  emxbind.  Currently, there are a few rough edges such as problems
+  with restarting the program being debugged if symbols have been
+  loaded from DLLs.
+
+  Use the `þtt{set show-dlls on}' command to let GDB show the path names
+  of DLLs as they are loaded and freed.
+
+  Use the `þtt{dll-break}' command to set a stop-on-load breakpoint on
+  a DLL.  The `þtt{dll-break}' command takes one argument, the name of
+  the DLL.  The name must not include a path; the extension
+  `þtt{.dll}' will be added if no extension is provided.  Letter case
+  does not matter.  When the named DLL is loaded, GDB will stop the
+  program being debugged.  Then, you can set breakpoints in the DLL
+  and continue.  The `þtt{dll-clear}' command removes a stop-on-load
+  breakpoint by number; the `þtt{info dll-break}' command lists all
+  stop-on-load breakpoints, showing the number of the stop-on-load
+  breakpoint and the name of the DLL.
+
+þh3 Debugging descendant processes
+
+  Under OS/2, you can optionally debug processes (descendant
+  processes) started by the debuggee.  For each descendant process to
+  be debugged, one extra instance of GDB will be required.  Due to
+  OS/2 limitations, session switching does not work for descendants;
+  therefore descendants which are Presentation Manager applications
+  cannot be debugged.
+
+  GDB maintains a list of programs to be debugged when started by the
+  debuggee.  The `þtt{descendant add}' command adds a program to that
+  list.  The first argument of that command is the name of the
+  executable file, which can be specified in the following three ways:
+
+þenumerate
+þitem
+  A path name (including a directory) will be turned into an absolute
+  path name by GDB; all descendants matching the absolute path name
+  will be debugged.  The path name should include the correct file
+  name extension as no default extension will be applied.
+þitem
+  A file name (without directory); all descendants whose file name
+ (without directory) match the specified file name will be debugged.
+  The file name should include the correct file name extension as no
+  default extension will be applied.
+þitem
+  The word `þtt{fork}' means that this entry applies to child
+  processes created with fork().
+þitem
+  A `þtt{*}' means that this entry applies to all descendants, without
+  regard to their file names.
+þendenumerate
+
+  The second argument specifies the action to be taken when a
+  descendant with a matching executable file name is started.  The
+  following actions are available:
+
+þdescription
+þitem þtt{window}
+  Start a new instance of GDB, running in a new windowed session.
+
+þitem þtt{fs}
+  Start a new instance of GDB, running in a new full-screen session.
+
+þitem þtt{cont}
+  Do not start a new instance of GDB and continue the debuggee.  The
+  descendant will block until GDB is attached to the descendant.  Note
+  that the debuggee may also block if it waits for the start or
+  completion of the child process.
+þenddescription
+
+  If the first argument is `þtt{fork}' and the third argument is
+  `þtt{init}', you'll be able to debug the initialization code of the
+  forked process; this is used for debugging the implementation of
+  fork().  If there is no third argument or if the third argument is
+  not `þtt{init}', debugging of the child process will start in the
+  fork() call; one `þtt{step}' command will step to the location (in
+  the child process) from which fork() has been called (in the parent
+  process).
+
+  Any remaining arguments should be GDB options and will be passed to
+  the new instance of GDB.  This is in particular useful to set up GDB
+  with commands from a file specified with `þtt{--command}' or to
+  prevent GDB from reading the `þtt{!gdbinit}' file with `þtt{-nx}'.
+
+  Examples for `þtt{descendant add}':
+
+þexample
+desc add * window
+desc add fork window init -q
+desc add special.exe window --command special.gdb
+þendexample
+
+  At least one descendant must be defined with `þtt{descendant add}'
+  þem{before} the start of the debuggee; otherwise debugging of
+  descendants will be disabled.  If debugging of descendants is
+  enabled (by defining at least one descendant), GDB will show a
+  message each time a new descendant is started:
+
+þexample
+[New process: 4713 C:/EMX/TEST/ARGS.EXE]
+þendexample
+
+  The message includes the process ID (4713 in the example) and the
+  path name of the executable file.  If the path name does not match
+  any entry in the table of descendants, the descendant will be run
+  with debugging disabled.  The descendant will be terminated or will
+  block if the instance of GDB debugging its parent process ends.
+
+  If the path name matches an entry in the table of descendants, the
+  associated action will be performed.  First, the table is searched
+  for a matching absolute path name.  If there is no matching entry,
+  all entries having file names (without directory) will be searched.
+  If there is still no matching entry, the `þtt{*}' entry will be used
+  if present.  That is, the most stricly matching entry will be used,
+  falling back to more general entries if there is no matching entry.
+
+  For the actions `þtt{window}' and `þtt{fs}' a new instance of GDB
+  will be started for the descendant.  Now, you can set a breakpoint
+  (usually on `þtt{main}') and continue execution of the descendant
+  with the `þtt{continue}' command.  If the descendant has been
+  created with fork(), use the `þtt{step}' command.  The instance of
+  GDB debugging the parent process of the descendant must not be
+  terminated until debugging of all the descendants of that parent
+  process is complete.
+
+  The following example shows how to debug `þtt{args.exe}' when run
+  from `þtt{exec.exe}'.  Both are test programs in þtt{\emx\test}.
+  First, start GDB on the parent process:
+
+þexample
+[c:\emx\test]gdb -q exec.exe
+(gdb) desc add * window -q
+Debugging of descendant * enabled (number 1).
+(gdb) set close
+(gdb) run
+Starting program: c:/emx/test/exec.exe
+[New thread 1]
+þendexample
+
+  Now type `þtt{run args a b c}' in the `þtt{exec.exe}' window.  This
+  will cause `þtt{exec.exe}' to start `þtt{args.exe}'.  GDB will display
+
+þexample
+[New process: 41 C:/EMX/TEST/ARGS.EXE]
+þendexample
+
+  and a new window will show up, running GDB:
+
+þexample
+0x138 in ?? ()
+(gdb)
+þendexample
+
+  Now, you can debug `þtt{args.exe}':
+
+þexample
+(gdb) b main
+Breakpoint 1 at 0x1007f: file args.c, line 11.
+(gdb) cont
+Continuing.
+[New thread 1]
+[Switching to thread 1]
+
+Breakpoint 1, main (argc=4, argv=0x282ffd4, envp=0x282fdc8) at args.c:11
+11        _envargs (&argc, &argv, "ARGS");
+(gdb) p argv[1]
+$1 = 0x282fff0 "a"
+(gdb) cont
+Continuing.
+[Thread terminated: 1]
+
+Program exited normally.
+(gdb) q
+þendexample
+
+  If the action `þtt{cont}' is specified for a descendant, you have to
+  start GDB manually to debug the descendant.  Use the `þtt{attach}'
+  command with the process ID of the descendant as argument:
+
+þexample
+[C:\EMX\TEST]gdb -q args.exe
+(gdb) attach 41
+Attaching to program `c:/emx/test/args.exe', process 41
+0x138 in ?? ()
+(gdb)
+þendexample
+
+  You can take the process ID from the output of the instance of GDB
+  debugging the parent process.  The `þtt{detach}' command detaches
+  GDB from the descendant, letting the descendant run without
+  debugging (as long as the instance of GDB debugging the parent
+  process lives).
+
+  Note that GDB's table of descendants applies to the first level of
+  descendants only; to debug a child process of a descendant process,
+  you have to issue another `þtt{descendant add}' command in the
+  second instance of GDB.  Child processes of descendants not defined
+  in the table of descendants cannot be debugged.
+
+  The `þtt{info descendants}' command lists the table of descendands;
+  for each descendant, a number, the path name or file name, the
+  action, and the GDB options are shown.
+
+  The `þtt{descendant clear}' command removes an entry of the table of
+  descendants.  You have to specify the number of the entry, as shown
+  by `þtt{info descendants}'.
+
+  To modify an entry of the table of descendants, just issue another
+  `þtt{descendant add}' command for the same file name or path name.
+
+
+þh3 Examining the heap
+
+  If the debuggee has been linked with the emx or GNU implementation
+  of malloc(), you can examine the heap with the `þtt{info heap}'
+  command.  That command will list all used and free blocks of the
+  heap.  You'll get more detailed information if you type `þtt{info
+  heap /v}'.  Moreover, you can type an argument which specifies the
+  address of the heap to examine.  If the address points to a
+  substructure of the heap, such as a block or a segment, that
+  substructure will be displayed.
+
+  For programs linked with -Zcrtdll, GDB does not know the address of
+  the heap.  Therefore, you have to use the `þtt{info heap}' command
+  with the address of the heap (this works with the emx implementation
+  of malloc() only):
+þenumerate
+þitem
+  Before starting the program, type
+þexample
+set show-dlls
+þendexample
+  to let GDB print information about DLLs.
+þitem
+  Start the program with the `þtt{run}' command.  GDB will show
+  the names and addresses of the DLLs.  You need the address of
+  the þtt{.data} object of emxlibcs.dll or emxlibcm.dll:
+þexample
+[Load DLL: C:\EMX\DLL\EMXLIBCM.DLL]
+[.text: 0x0e400000 - 0x0e419c10]
+[.data: 0x0e420000 - 0x0e425f90]
+[.bss:  0x0e425f90 - 0x0e428190]
+þendexample
+  In this example, the address of the þtt{.data} object is 0xe420000.
+þitem
+  Search the file þtt{\emx\etc\emxlibcs.map} (or
+  þtt{\emx\etc\emxlibcm.map}, depending on which DLL is used) for
+  the symbol þtt{_um_regular_heap}:
+þexample
+ 0002:00007CB4       _um_regular_heap
+þendexample
+  In this example, the offset we're looking for is 0x7cb4.
+þitem
+  Compute the address of the þtt{_um_regular_heap} variable by
+  adding the address of the þtt{.data} object and the offset
+  of the variable.  In the example, the address is 0xe427cb4.
+þitem
+  Display the value of the variable:
+þexample
+x/w 0xe427cb4
+þendexample
+  GDB responds with
+þexample
+0xe427cb4 <end+239105292>:      0x02970000
+þendexample
+  In this example, the address of the heap is 0x2970000.
+þitem
+  Use the `þtt{info heap}' command with the address of the heap:
+þexample
+info heap 0x2970000
+þendexample
+  All numbers in this recipe are samples.
+þendenumerate
+
+  If the debuggee has the _heapchk() function linked in, you can call
+  it from GDB to check the heap:
+
+þexample
+call _heapchk()
+þendexample
+
+  That function returns 0 if the heap is OK, 1 if the heap is empty
+  (uninitialized).  Other return values indicate heap corruption.  To
+  check the heap each time the program stops, use
+
+þexample
+display _heapchk()
+þendexample
+
+  _heapchk() works with the emx implementation of malloc() only.
+  Other malloc packages may support a similar function.
+
+þh3 Initialization file
+
+  The .gdbinit file has been renamed þtt{!gdbinit}.  To save typing,
+  you might want to create a file named þtt{!gdbinit} in the directory
+  where you're debugging.  Here's an example of a þtt{!gdbinit} file:
+
+þexample
+file myprog.exe
+set arg -o test.out test.inp
+b main
+set close on
+run
+set switch off
+þendexample
+
+þh3 DUEL
+
+  Michael Golan's DUEL debugging language has been added to GDB.
+  You'll find detailed instructions in þtt{\emx\doc\duel.man}.  Note
+  that GDB has not been modified to require `þtt{##}' for comments,
+  therefore you have to use alternate names for two DUEL operators:
+  Use `þtt{%/}' instead of `þtt{#/}', and `þtt{%%}' instead of
+  `þtt{#}'.
+
+
+þh3 GDBRX -- use REXX in GDB
+þlabel GDBRX
+
+  The `þtt{rexx}' command of GDB invokes the OS/2 REXX interpreter.
+  The argument of the `þtt{rexx}' command is interpreted as a REXX
+  program.  `þtt{rx}' is an alias for the `þtt{rexx}' command.
+  Important: use single quotes instead of double quotes in REXX
+  commands as GDB treats double quotes specially.  Example:
+
+þexample
+(gdb) rx say 'Hello World!'
+Hello World!
+þendexample
+
+  Once the REXX interpreter has been invoked, the default subcommand
+  handler is GDBRX.  This means that any commands REXX doesn't
+  understand get passed back to GDB for processing.  Any output from
+  GDB gets passed back to REXX through the standard result variable
+  þtt{RC}.  Example:
+
+þexample
+(gdb) rx do i = 2 to 4; 'p 'i; say rc; end
+$1 = 2
+$2 = 3
+$3 = 4
+þendexample
+
+  This is where the real power of the REXX command lies.  It makes it
+  really easy to hack together quick and dirty debugging functions.
+  For instance, þtt{\emx\bin\logargs.cmd} is a REXX program that logs
+  all parameters used in calls to a given function.  You invoke it
+  with
+
+þexample
+(gdb) rx call logargs
+þendexample
+
+  þtt{logargs.cmd} assumes that you have loaded the program, and have
+  breaked somewhere in it (since it starts off with a
+  `þtt{continue}').
+
+  When you run it you get something like this:
+
+þexample
+cd \emx\test
+gdb version.exe
+(gdb) b main
+(gdb) set sw off
+(gdb) set cl on
+(gdb) run
+(gdb) rx call logargs
+logargs 1.1
+Enter function name:
+bit
+Running...
+þendexample
+
+  And you end up with a very useful þtt{logargs.txt} file:
+
+þexample
+*** logargs 1.1 --- 20:02:33 02 Jul 1993 ***
+s=0x100b7 "VCPI     ", n=1
+s=0x100c1 "XMS      ", n=2
+s=0x100cb "VDISK 3.3", n=4
+s=0x100d5 "DESQview ", n=8
+s=0x100df "287      ", n=16
+s=0x100e9 "387      ", n=32
+s=0x100f3 "OS/2 2.x ", n=512
+s=0x100fd "-t       ", n=1024
+s=0x10107 "-ac      ", n=2048
+þendexample
+
+  where each line represents the parameters passed to þtt{bit()}.
+
+  When analyzing þtt{RC}, note that newlines are represented by two
+  characters, CR and LF.
+
+
+þh2 Hints
+
+  To debug an .exe file which doesn't have a symbol table use
+  the symbol table from the a.out file and type
+
+þexample
+gdb -e myprog.exe -s myprog
+þendexample
+
+  You can do post-mortem debugging by using the þtt{core} file written
+  by emx when a program aborts.
+
+  You can use the following redirection specifications with `þtt{set
+  args}':
+
+þlist
+þitem þtt{<}þpa{FILENAME}
+
+    Redirect the file named þpa{FILENAME} to standard input
+
+þitem þtt{>}þpa{FILENAME}
+
+    Redirect standard output to the file named þpa{FILENAME},
+    overwriting
+
+þitem þtt{>>}þpa{FILENAME}
+
+    Redirect standard output to the file named þpa{FILENAME},
+    appending
+
+þendlist
+
+  You can prepend a handle number (0 to 9) to such a redirection
+  specification; for instance
+
+þtypewriter
+  2>þpa{FILENAME}
+þendtypewriter
+
+  redirects standard error to þpa{FILENAME}.  Use quotation marks to
+  include `þtt{<}', `þtt{>}', spaces, or TABs in arguments.  Use
+  backslashes to escape quotation marks.
+
+  Example:
+
+þexample
+set args "first arg" "second arg" <input >output 2>error
+þendexample
+
+
+þh1 GAS -- assembling
+þlabel GAS
+þindex GAS
+þindex assembler
+þkeyword GAS
+
+  GAS is the GNU assembler.  The executable file name of GAS is
+  as.exe. The GNU assembler preprocessor, GASP, is also
+  available. Usually, GAS is called by þhpt{GCC}. See the GAS and GASP
+  manuals for details.
+
+  This port of GAS supports two additional command line options:
+
+þdescription
+
+þitem -Zomf
+
+    Call emxomf to convert the output file to OMF.  This option is
+    used for creating .obj files.
+
+þitem -Zstrip
+
+    Pass the -s option to emxomf.  This option is used with -Zomf 
+    to omit debugging information.
+
+þenddescription
+
+
+þh1 ld -- linking
+þlabel ld
+þindex ld
+þindex linker
+þkeyword ld
+
+  ld is the GNU linker.
+
+  If the output file has an .exe or .dll extension, þhpt{emxbind} will
+  automatically be called to bind emxl.exe and the temporary a.out
+  file into an .exe or .dll file.  See þtt{/emx/gnu/binutils.old/ld.c} and
+  the description of þhpt{emxomfld} for command line options.  ld is
+  usually called only by GCC, not from the command line.
+
+  The -s option (strip symbols) is passed on to emxbind.  If ld
+  doesn't call emxbind, ld will strip the symbol table.
+  Unfortunately, ld doesn't correctly strip the symbol table.
+
+  This port of ld supports several additional command line options:
+
+þdescription
+
+þitem -R
+
+  The -R option is used for creating relocatable executable files.  -R
+  is automatically set if the output file has a .dll extension.  -R is
+  also automatically set if an import definition of type þhpt{(I2)} is
+  referenced.  This is used to import functions from dynamic link
+  libraries.  If you link with import definitions of type (I1), you
+  have to manually supply the -R option.
+
+þitem -Zexe
+
+  If the -Zexe option is present, ld deletes the output file (whose
+  name is given on the command line) and, after linking, calls emxbind
+  to create an .exe file (.exe is appended to the name of the output
+  file) After calling emxbind, ld creates an empty output file
+  (without .exe).  This feature is used for minimizing changes to
+  Unix-style makefiles.  See also the þhpt{-Zexe} option of þhpt{GCC}
+  and þhpt{emxomfld}.  The output file name must not have an extension
+  if -Zexe is used.
+
+þitem -Zmap
+
+  Let emxbind create a .map file.  The name of the .map file will be
+  derived from the output file name, the default extension is .map.
+  To specify the name of the .map file, use þsy{-Zmap=<map_file>}.
+
+þitem -Zstack
+
+  The -Zstack option is passed down to emxbind to set the stack size
+  for OS/2 programs.
+
+þitem -Zno-demangle
+
+  Don't demangle C++ symbols in error messages.
+
+þitem -Zdemangle-proto
+
+  Include parameters and qualifiers in demangled C++ symbols in error
+  messages.
+
+þenddescription
+
+  If a file name with .def extension is given on the ld command line,
+  it will be passed as module definition file (-d option) to emxbind.
+  If there is no .def file on the command line and the output file is
+  a .dll file, the -d option without argument is passed to emxbind;
+  emxbind will use the name of the output file (with .def extension)
+  for the module definition file.
+
+  If a file name with .res extension is given on the ld command line,
+  it will be passed as resource file (-r option) to emxbind.
+
+  Note that the sequence of .o and .a files and -l options is
+  essential.  crt0.o or dll0.o must come first.  Libraries are
+  considered only once, that is, if a library references symbols
+  defined in another library, the former one must be used before the
+  latter one.  If library lib1.a uses library lib2.a, which in turn
+  uses library lib1.a, you have to use þtt{-llib1 -llib2 -llib1}.
+
+
+þh1 ranlib
+þindex ranlib
+þkeyword ranlib
+
+  þbf{ranlib} is not available.  Use the þtt{s} command of þbf{ar}
+  instead.
+
+
+þh1 strip -- removing the symbol table
+þlabel strip
+þindex strip
+þkeyword strip
+
+  þbf{strip} is used to delete symbols from an a.out file.  It cannot
+  be applied to bound .exe files.  See þtt{/emx/gnu/binutils.old/strip.c}
+  for command line options.  See also the þhpt{emxbind} (-s command
+  and the -s option of the -b command).
+
+
+þh1 info -- browsing info files
+þlabel info
+þindex info
+þkeyword info
+
+  Before using þbf{info}, you have to install termcap.  This is done by
+  setting the TERM environment variable and one of the following
+  environment variables: INIT, EMXETC, TERMCAP.  Here's an example:
+
+þexample
+set term=mono
+set termcap=c:/emx/etc/termcap.dat
+þendexample
+
+  Then, you have to set the INFOPATH environment variable.  It's a
+  list of directories, separated by semicolons.  The þtt{/emx/info}
+  directory should be included.  Example:
+
+þexample
+set infopath=.;c:/emx/info
+þendexample
+
+  If the INFOPATH environment variable is not set, the following list
+  of directories will be used:
+
+þexample
+.;/emx/info;/emacs/info
+þendexample
+
+  After setting all the environment variables, you can run info by
+  typing
+
+þexample
+info
+þendexample
+
+  Type þtt{?} to get a list of keys.
+
+
+þh1 makeinfo -- creating info files
+þlabel makeinfo
+þindex makeinfo
+þkeyword makeinfo
+
+  makeinfo creates info files from texinfo files.  Type makeinfo to
+  get a list of options.  There's also texinfo documentation available
+  for makeinfo.
+
+  When splitting files, makeinfo uses the extensions þtt{i01},
+  þtt{i02}, ..., þtt{i99}.
+
+
+þh1 texindex -- creating the index for a printed manual
+þlabel texindex
+þindex texindex
+þkeyword texindex
+
+  texindex sorts the index for typesetting a texinfo file with
+  þbf{TeX}.  To compile a texinfo file under OS/2, simply move to the
+  directory where the source file resides and enter
+
+þtypewriter
+  texi2dvi þpa{FILENAME}
+þendtypewriter
+
+  where þpa{FILENAME} is the name of the source file.  Example:
+
+þexample
+cd \emx\gnu\texinfo
+texi2dvi texi.tex
+þendexample
+
+  þbf{texi2dvi} is a REXX procedure which calls þbf{TeX} and texindex.
+  See the first two statements of þtt{/emx/bin/texi2dvi.cmd} for
+  customization.
+
+
+þh1 termcap -- terminal capabilities
+þlabel termcap
+þindex termcap
+þkeyword termcap
+
+  For using termcap, you have to put termcap.dat in the current
+  working directory, into directory /emx/etc on the current drive, or
+  into a directory listed in the INIT or EMXETC environment
+  variables.  You can also set the TERMCAP environment variable to
+  contain the absolute path name of termcap.dat.  If the TERM
+  environment variable isn't set, ansi will be used (þtt{ansi.sys}
+  required).  Otherwise, the terminal given in the TERM environment
+  variable will be used.  I recommend using þtt{mono}.  See
+  termcap.dat for details.
+
+  To link a program with the GNU termcap library, specify -ltermcap on
+  the GCC command line.  Read the license in þtt{/emx/doc/COPYING}!
+
+  Alternatively, the BSD termcap library is available.  See
+  þtt{emxbsd.doc} and þtt{emxbsd.inf} for details.
+
+þh1 readline
+þlabel readline
+þindex readline
+þkeyword readline
+
+  The standard þbf{Emacs}/þbf{readline} key bindings are used with the
+  following exceptions and additions:
+
+þexample
+BS, C-H         rubout
+HOME            beg_of_line
+END             end_of_line
+UP              get_previous_history
+DOWN            get_next_history
+LEFT            backward
+RIGHT           forward
+PAGEUP          beginning_of_history
+PAGEDOWN        end_of_history
+DELETE          delete
+C-LEFT          backward_word
+C-RIGHT         forward_word
+C-HOME          backward_kill_line
+C-END           kill_line
+þendexample
+
+  The readline library source comes with the GDB source files.
+
+
+þh1 GPPDEMID -- an identifier manipulation DLL for G++
+þlabel GPPDEMID
+þi1 GPPDEMID
+þkeyword GPPDEMID
+
+  GPPDEMID (þtt{/emx/dll/gppdemid.dll}) is a dynamic link library
+  which demangles symbols mangled by the G++ compiler.  This DLL is
+  used by LINK386 to demangle symbols to make error messages more
+  readable when linking C++ programs.  LINK386 is told about the name
+  of the DLL by a special record inserted into the .obj files by
+  þhpt{emxomf}.
+
+  GPPDEMID is subject to the GNU Library General Public License, see
+  þtt{/emx/doc/COPYING.LIB} for details.  The source code for GPPDEMID
+  can be found in the þtt{gnusrc.zip} archive.
+
+
+þh1 Known problems
+þlabel Known problems
+
+þitemize
+
+þitem
+
+  gcc.exe cannot pass more than 24 (temporary) files derived by
+  the GCC command from source files to the linker
+
+þitem
+
+  If GDB fails under OS/2 with an error message like
+
+þexample
+DosDebug error: 00000135
+þendexample
+
+  stop any screen savers you are running.  If that does not help, use
+  the -E emx option:
+
+þexample
+set emxopt=-E
+þendexample
+
+  and run GDB from a full-screen command prompt.
+
+þenditemize
+
+þtext
+
+--------------------------- END OF EMXGNU.DOC ------------------------------
+þendtext
Index: trunk/src/emx/src/doc/emxlib.src
===================================================================
--- trunk/src/emx/src/doc/emxlib.src	(revision 18)
+++ trunk/src/emx/src/doc/emxlib.src	(revision 18)
@@ -0,0 +1,22707 @@
+þc emxlib.src
+
+þtext
+===============================================================================
+emxlib.doc        emx 0.9d     C LIBRARY REFERENCE                  21-Dec-1998
+===============================================================================
+                                     Copyright (c) 1990-1998 by Eberhard Mattes
+þendtext
+
+þtitle emx 0.9d C Library Reference
+
+þformat bold emx emxbind emxload ld
+
+þformat tty .a .o .com .exe cmd.exe command.com
+þformat tty emx.dll emxlibc.dll emxlibcm.dll emxlibcs.dll
+þformat tty emxwrap.dll emxio.dll makefile emx.exe
+þformat tty sys.lib emx.a emx.lib emx2.a emx2.lib os2.a os2.lib
+þformat tty binmode.o binmode.obj
+þformat tty <a_out.h> <alloca.h> <ar.h> <assert.h> <conio.h> <ctype.h>
+þformat tty <curses.h> <dirent.h> <dos.h> <errno.h> <fcntl.h> <float.h>
+þformat tty <fnmatch.h> <ftw.h> <getopt.h> <glob.h> <graph.h> <grp.h>
+þformat tty <ieee.h> <io.h> <limits.h> <malloc.h> <math.h> <memory.h>
+þformat tty <os2.h> <os2emx.h> <os2thunk.h> <os2tk.h> <process.h> <pwd.h>
+þformat tty <setjmp.h> <sgtty.h> <share.h> <signal.h> <stdarg.h> <stddef.h>
+þformat tty <stdio.h> <stdlib.h> <string.h> <strings.h> <termcap.h>
+þformat tty <termio.h> <termios.h> <time.h> <umalloc.h> <unistd.h> <varargs.h>
+þformat tty <locale.h> <ulimit.h> <utime.h>
+þformat tty <emx/bigint.h> <emx/float.h> <emx/io.h> <emx/locale.h> <emx/nls.h>
+þformat tty <emx/pwd.h> <emx/startup.h> <emx/syscalls.h> <emx/thread.h>
+þformat tty <emx/time.h> <emx/umalloc.h>
+þformat tty <sys/builtin.h> <sys/dir.h> <sys/dirent.h>
+þformat tty <sys/dirtree.h> <sys/ea.h> <sys/ead.h> <sys/emxload.h>
+þformat tty <sys/fcntl.h> <sys/file.h> <sys/fmutex.h> <sys/hw.h> <sys/ioctl.h>
+þformat tty <sys/ipc.h> <sys/kbdscan.h> <sys/moddef.h> <sys/msg.h> <sys/nls.h>
+þformat tty <sys/param.h> <sys/process.h> <sys/ptrace.h> <sys/reg.h>
+þformat tty <sys/rmutex.h>
+þformat tty <sys/resource.h> <sys/select.h> <sys/signal.h> <sys/smutex.h>
+þformat tty <sys/socket.h> <sys/so_ioctl.h> <sys/stat.h> <sys/statfs.h>
+þformat tty <sys/termio.h> <sys/time.h> <sys/timeb.h> <sys/times.h>
+þformat tty <sys/types.h> <sys/uflags.h> <sys/uio.h> <sys/user.h> <sys/utime.h>
+þformat tty <sys/utsname.h> <sys/video.h> <sys/wait.h> <sys/winmgr.h>
+
+þformat tty HPFS.IFS xf86sup.sys
+
+þformat tty c_alias c_app c_dllnrt, c_dllrt c_dllso c_import c_static emx2
+þformat tty emxio moddef
+
+þformat tty -Zmt -Zmtd -Zmts -Zomf -Zsys -Zbsd-signals -Zsysv-signals
+þformat tty -Zno-rte -Zso -Zcrtdll -Zbin-files -Zsmall-conv -pg
+þformat tty -l -lg -lgcc -lc -g -lwrap -lemxio -ltmalloc -mprobe
+þformat tty -lgraph -lvideo -lmoddef -lsocket -fpcc-struct-return
+þformat tty -c -p -t -ac -acm -ai -am -aw
+
+þformat tty #define void volatile wchar_t jmp_buf sigjmp_buf sigset_t glob_t
+
+þformat tty _DT_TREE _DT_NOCPDIR _EMXLOAD_INDEFINITE
+þformat tty MB_CUR_MAX MB_MAX_LEN
+þformat tty O_RDONLY O_WRONLY O_RDWR O_NDELAY O_APPEND O_CREAT O_TRUNC O_EXCL
+þformat tty O_BINARY O_TEXT O_NOINHERIT O_SYNC O_SIZE O_NONBLOCK
+þformat tty SH_DENYNO SH_DENYRD SH_DENYWR SH_DENYRW
+þformat tty F_OK R_OK W_OK X_OK
+þformat tty P_WAIT P_NOWAIT P_OVERLAY P_DEBUG P_DETACH _MEMDIF_EQ
+þformat tty P_SESSION P_PM P_DEFAULT P_FULLSCREEN P_WINDOWED P_MINIMIZE
+þformat tty P_MAXIMIZE P_BACKGROUND P_FOREGROUND P_NOCLOSE P_NOSESSION
+þformat tty P_QUOTE P_TILDE P_UNRELATED P_DEBUGDESC
+þformat tty NULL USE_OS2_TOOLKIT_HEADERS MAXNAMLEN _MAX_DRIVE _MAX_FNAME
+þformat tty  _MAX_EXT _MAX_DIR _MAX_PATH L_cuserid _PASSWORD_LEN MAXPATHLEN
+þformat tty RAND_MAX BUFSIZ L_tmpnam P_tmpdir TMP_MAX
+þformat tty HUGE_VAL HUGE_VALF HUGE_VALL CHAR_MAX
+þformat tty LONG_MIN LONG_MAX ULONG_MAX
+þformat tty LONG_LONG_MIN LONG_LONG_MAX ULONG_LONG_MAX
+þformat tty EOF CLK_TCK HZ CLOCKS_PER_SEC
+þformat tty FP_ZERO FP_SUBNORMAL FP_NORMAL FP_INFINITE FP_NAN DECIMAL_DIG
+þformat tty GETOPT_ANY GETOPT_KEEP GETOPT_UNIX
+þformat tty WNOHANG WUNTRACED
+þformat tty ARG_MAX CHILD_MAX NGROUPS_MAX OPEN_MAX STREAM_MAX
+þformat tty TZNAME_MAX LINK_MAX MAX_CANON MAX_INPUT NAME_MAX PATH_MAX
+þformat tty PIPE_BUF
+þformat tty _POSIX_JOB_CONTROL _POSIX_SAVED_IDS _POSIX_VERSION
+þformat tty _POSIX_CHOWN_RESTRICTED _POSIX_NO_TRUNC _POSIX_VDISABLE
+þformat tty _SC_ARG_MAX _SC_CHILD_MAX _SC_CLK_TCK _SC_NGROUPS_MAX
+þformat tty _SC_OPEN_MAX _SC_STREAM_MAX _SC_TZNAME_MAX _SC_JOB_CONTROL
+þformat tty _SC_SAVED_IDS _SC_VERSION
+þformat tty _PC_LINK_MAX _PC_MAX_CANON _PC_MAX_INPUT _PC_NAME_MAX
+þformat tty _PC_PATH_MAX _PC_PIPE_BUF _PC_CHOWN_RESTRICTED _PC_NO_TRUNC
+þformat tty _PC_VDISABLE
+þformat tty FNM_NOMATCH _FNM_MATCH _FNM_ERR
+þformat tty FNM_NOESCAPE FNM_PATHNAME FNM_PERIOD _FNM_POSIX
+þformat tty _FNM_OS2 _FNM_DOS _FNM_IGNORECASE _FNM_PATHPREFIX
+þformat tty GLOB_APPEND GLOB_DOOFFS GLOB_ERR GLOB_MARK GLOB_NOESCAPE
+þformat tty GLOB_NOCHECK GLOB_NOSORT GLOB_PERIOD
+þformat tty GLOB_ABEND GLOB_NOMATCH GLOB_NOSPACE
+þformat tty S_IREAD S_IWRITE S_IEXEC S_IFCHR S_ISCHR FD_SET FD_SETSIZE
+þformat tty IDEFAULT IDELETE IGNCR ISTRIP INLCR ICANON ISIG IUCLC ICRNL
+þformat tty ECHO ECHOK
+þformat tty VINTR VQUIT VERASE VEOF VKILL VEOL VMIN VTIME VSUSP VSTOP VSTART
+þformat tty TCIOFF TCION TCOOFF TCOON TCIFLUSH TCIOFLUSH TCOFLUSH
+þformat tty TCSANOW TCSADRAIN TCSAFLUSH
+þformat tty SIG_DFL SIG_IGN SIG_ERR SIG_ACK SIGABRT SIGALRM SIGBREAK SIGFPE
+þformat tty SIGILL SIGINT SIGPIPE SIGSEGV SIGCHLD SIGCLD SIGKILL SIGTERM
+þformat tty SIGQUIT SIGTRAP SIGEMT SIGBUS SIGSYS SIGUSR1 SIGUSR2 SIGHUP
+þformat tty SIGPTRACENOTIFY SIGWINCH
+þformat tty SA_NOCLDSTOP SA_SYSV SA_ACK SIG_BLOCK SIG_UNBLOCK SIG_SETMASK
+þformat tty TCGETA TCSETA TCSETAF TCSETAW TCFLSH TCSBRK TCXONC
+þformat tty FIONREAD FGETHTYPE
+þformat tty F_GETFL F_SETFL F_GETFD F_SETFD F_DUPFD FD_CLOEXEC
+þformat tty OS2_MODE DOS_MODE SEEK_SET SEEK_CUR SEEK_END HT_FILE
+þformat tty EPERM ENOENT ESRCH EINTR EIO E2BIG ENOEXEC EBADF ECHILD
+þformat tty EAGAIN ENOMEM EACCES EEXIST EXDEV ENOTDIR EISDIR EINVAL
+þformat tty EMFILE ENOTTY ENOSPC ESPIPE EROFS EPIPE EDOM ERANGE ENOSYS
+þformat tty ENAMETOOLONG EWOULDBLOCK
+þformat tty LC_ALL LC_COLLATE LC_CTYPE LC_MONETARY LC_NUMERIC LC_TIME
+þformat tty G_OUTLINE G_FILL G_MODE_OFF G_MODE_EGA_C G_MODE_EGA_E
+þformat tty G_MODE_VGA_H G_MODE_VGA_L G_SET_KEEP
+þformat tty _HEAPBADBEGIN _HEAPBADNODE _HEAPEMPTY _HEAPOK _HEAPBADEND
+þformat tty _BLOCK_CLEAN _HEAP_REGULAR _HEAP_TILED _HEAP_SHARED _HEAP_MIN_SIZE
+þformat tty _RUNTIME_HEAP _FORCE _FREEENTRY _USEDENTRY
+þformat tty FTW_D FTW_F FTW_NS FTW_DNR _IONBF _IOFBF _IOLBF
+þformat tty PTRACE_TRACEME PTRACE_PEEKTEXT PTRACE_PEEKDATA PTRACE_PEEKUSER
+þformat tty PTRACE_POKETEXT PTRACE_POKEDATA PTRACE_POKEUSER PTRACE_RESUME
+þformat tty PTRACE_EXIT PTRACE_STEP PTRACE_SESSION PTRACE_NOTIFICATION
+þformat tty PTRACE_CONT PTRACE_THAW PTRACE_FREEZE PTRACE_ATTACH PTRACE_DETACH
+þformat tty PTRACE_GETPID PTRACE_GETTID PTRACE_PIDTID
+þformat tty PTN_NONE PTN_THREAD_NEW PTN_THREAD_END PTN_MODULE_LOAD
+þformat tty PTN_MODULE_FREE PTN_PROC_NEW
+þformat tty PTNMOD_DLL PTNMOD_AOUT PTNPROC_FORK PTNPROC_AOUT
+þformat tty MCW_EM MCW_IC MCW_RC MCW_PC EM_INVALID EM_DENORMAL EM_ZERODIVIDE
+þformat tty EM_OVERFLOW EM_UNDERFLOW EM_INEXACT RC_NEAR RC_DOWN
+þformat tty RC_UP RC_CHOP PC_24 PC_53 PC_64
+þformat tty V_MONOCHROME V_COLOR_8 V_COLOR_12 BLINK INTENSITY
+þformat tty V_SCROLL_UP V_SCROLL_DOWN V_SCROLL_CLEAR
+þformat tty UL_GFILLIM UL_SFILLIM UL_GMEMLIM UL_NOFILES UL_OBJREST
+þformat tty _UF_SIG_MODEL _UF_SIG_EMX _UF_SIG_SYSV _UF_SIG_BSD
+þformat tty _UF_SBRK_MODEL _UF_SBRK_CONTIGUOUS _UF_SBRK_MONOTONOUS
+þformat tty _UF_SBRK_ARBITRARY
+þformat tty _UF_PTRACE_MODEL _UF_PTRACE_STANDARD _UF_PTRACE_NOTIFY
+þformat tty _UF_PTRACE_MULTITHREAD
+þformat tty _EAD_MERGE NDEBUG _FMC_SHARED _FMR_IGNINT _FMR_NOWAIT
+þformat tty _MD_BASE _MD_CODE _MD_DATA _MD_DESCRIPTION _MD_EXETYPE _MD_EXPORTS
+þformat tty _MD_HEAPSIZE _MD_IMPORTS _MD_LIBRARY _MD_NAME _MD_OLD _MD_PHYSICAL
+þformat tty _MD_PROTMODE _MD_REALMODE _MD_SEGMENTS _MD_STACKSIZE _MD_STUB
+þformat tty _MD_VIRTUAL
+þformat tty _MD_eof _MD_dot _MD_at _MD_equal _MD_number _MD_word
+þformat tty _MD_quote _MD_ioerror _MD_missingquote _MD_parseerror
+þformat tty _MDE_IO_ERROR _MDE_MISSING_QUOTE _MDE_EMPTY _MDE_NAME_EXPECTED
+þformat tty _MDE_STRING_EXPECTED _MDE_NUMBER_EXPECTED _MDE_DEVICE_EXPECTED
+þformat tty _MDE_EQUAL_EXPECTED _MDE_DOT_EXPECTED _MDE_STRING_TOO_LONG
+þformat tty _MDE_INVALID_ORDINAL _MDE_INVALID_STMT
+þformat tty _MDEP_ORDINAL _MDEP_RESIDENTNAME _MDEP_NONAME _MDEP_NODATA
+þformat tty _MDEP_PWORDS _MDIP_ORDINAL _MDIT_DEFAULT _MDIT_INSTANCE
+þformat tty _MDIT_GLOBAL _MDS_IOPL _MDS_MULTIPLE _MDS_SHARED _MDT_DEFAULT
+þformat tty _MDT_WINDOWAPI _MDT_WINDOWCOMPAT _MDT_NOTWINDOWCOMPAT
+þformat tty _MDX_OS2 _MDX_WINDOWS
+
+þformat tty c_lflag c_oflag c_cflag c_cc c_line st_dev st_rdev st_ino umask
+þformat tty dstflag millitm time_t errno quot rem tms_utime
+þformat tty tm_hour tm_mday tm_min tm_mon tm_sec tm_year tm_wday
+þformat tty tm_yday tm_isdst gl_pathc gl_pathv gl_offs
+þformat tty sa_handler sa_mask sa_flags
+
+þformat tty getch() getche()
+þformat tty __open() DosAllocMem DosAllocSharedMem DosCreateThread DosFreeMem
+þformat tty DosGetMessage DosGetNamedSharedMem DosGetSharedMem
+þformat tty DosGiveSharedMem DosQueryMessageCP DosExit
+þformat tty DosExecPgm DosSleep DosStartSession DosExitList DosOpen DosRead
+þformat tty DosResetBuffer
+þformat tty HMTX
+þformat tty ERROR_INVALID_HANDLE ERROR_INTERRUPT ERROR_TOO_MANY_HANDLES
+þformat tty ERROR_MUTEX_OWNED ERROR_ACCESS_DENIED ERROR_FILE_EXISTS
+
+þformat tty _ea _ead fd_set ino_t wm_handle _dt_tree _far16ptr _dt_node
+þformat tty FEA2LIST FEALIST PFEA2LIST PFEALIST REGS
+þformat tty optarg opterr optind optopt optswchar optmode
+þformat tty _nls_tolower_tab _nls_toupper_tab _nls_ctype_tab
+þformat tty sys_errlist sys_nerr _emx_rev environ g_xsize g_ysize g_colors
+þformat tty _osmajor _osminor _osmode tzname stdin stdout stderr
+þformat tty _fmutex _rmutex _smutex Heap_t _HEAPSTATS
+
+þformat tty BASE CODE DATA DESCRIPTION EXETYPE EXPORTS HEAPSIZE IMPORTS
+þformat tty LIBRARY NAME OLD PROTMODE REALMODE SEGMENTS STACKSIZE STUB
+þformat tty PHYSICAL VIRTUAL DEVICE
+þformat tty WINDOWS RESIDENTNAME NODATA NONAME MAXVAL NEWFILES NONE
+
+þformat abbrev etc.
+
+þif text
+þh= Table of Contents
+þtoc
+þendif
+
+þh1 Introduction to the emx C Library Reference
+þipf
+:font facename=Helv size=24x14.:hp2.emx 0.9d C Library Reference
+:ehp2.
+:p.
+:font facename=Helv size=16x10.      Copyright (c) 1990-1998 by Eberhard Mattes
+:font facename=default size=0x0.
+:p.
+þendipf
+
+þipfminitoc
+
+þh2 Preliminary notes
+
+þitemize
+þitem
+
+  `C90' is short for ISO 9899-1990, the ANSI/ISO standard for the C
+  programming language
+
+þitem
+
+  `C9X' is short for the upcoming version of ISO 9899
+
+þitem
+
+  Not all functions declared in the headers are implemented.
+
+þitem
+
+  By default, text mode is used for files.  See þhpt{fread()} and
+  þhpt{fwrite()} for details.  The default can be globally changed to
+  binary mode by linking with binmode.o or binmode.obj
+  (þhpt{-Zbin-files} option of GCC).
+
+þitem
+
+  See the description of þhpt{g_mode()} for general information about
+  the graphics library.
+
+þitem
+
+  See the description of þhpt{v_init()} for general information about
+  the video library.
+
+þitem
+
+  See the description of þhpt{wm_init()} for general information about
+  the window manager functions.
+
+þenditemize
+
+
+þh2 Libraries
+
+  The following emx libraries are provided:
+
+þlist
+þitem þtt{st/c}
+
+    The single-thread C library.  This library includes the ISO C
+    library functions, Unix extensions and emx extensions.  Only
+    functions are included which are common to all types of
+    applications and DLLs.  See also c_app, c_dllnrt, c_dllrt, and
+    c_dllso.
+
+þitem þtt{mt/c}
+
+    The multithread C library.  See library þtt{st/c}.  This library
+    is used instead of library þtt{st/c} if the þhpt{-Zmt} or
+    þhpt{-Zmts} option is specified.
+
+þitem c_alias
+
+    Aliases for non-ISO-C symbols.  This library maps, for
+    instance, þtt{eof()} to þtt{_eof()}.  The static and dynamic C
+    libraries contain these symbols with one underscore prepended to
+    the names.  In consequence, redefining a non-ISO-C library
+    function should be possible even if the C library uses the
+    function internally.  (c_alias has not been merged into the
+    static, dynamic, and import libraries due to restrictions in
+    LINK386, þbf{ar}, and þhpt{emxomfar}.)
+
+þitem þtt{st/c_app}
+
+    This library is used in addition to þtt{st/c} for building a
+    single-thread statically linked application.
+
+þitem þtt{st/c_app_p}
+
+    Like library þtt{st/c_app}, with profiling hooks.  This library is
+    used instead of library þtt{st/c_app} if the -pg option is
+    specified.
+
+þitem þtt{mt/c_app}
+
+    This library is used in addition to þtt{st/c} for building a
+    multithread statically linked application.
+
+þitem þtt{c_dllrt}
+
+    This library is used in addition to þtt{st/c} for building a
+    DLL without runtime environment.
+
+þitem þtt{st/c_dllrt}
+
+    This library is used in addition to þtt{st/c} for building a
+    single-thread custom C runtime DLL.
+
+þitem þtt{mt/c_dllrt}
+
+    This library is used in addition to þtt{mt/c} for building a
+    multithread custom C runtime DLL.
+
+þitem þtt{st/c_dllso}
+
+    This library is used in addition to þtt{mt/c} for building a
+    single-thread stand-alone DLL.  Such a DLL has its own runtime
+    environment.
+
+þitem þtt{mt/c_dllso}
+
+    This library is used in addition to þtt{mt/c} for building a
+    multithread stand-alone DLL.  Such a DLL has its own runtime
+    environment.
+
+þitem þtt{st/c_import}
+
+    Import library for emxlibcs.dll.  This library is used instead of
+    libraries þtt{c}, c_app, and þtt{gcc} if the þhpt{-Zcrtdll} option
+    without the þhpt{-Zmt} option is specified.
+
+þitem þtt{mt/c_import}
+
+    Import library for emxlibcm.dll.  This library is used instead of
+    libraries þtt{c}, c_app, and þtt{gcc} if the þhpt{-Zcrtdll} and
+    þhpt{-Zmt} options (or þhpt{-Zmtd}) are specified.
+
+þitem þtt{st/c_p}
+
+    The single-thread C library, with profiling hooks.  See library
+    þtt{st/c}.  This library is used instead of library þtt{st/c} if
+    the -pg option is specified.
+
+þitem c_static
+
+    Code which must be statically linked when linking the C library
+    dynamically.  This library is searched if the þhpt{-Zcrtdll}
+    option of GCC is specified.
+
+þitem þtt{st/emx}
+
+    System call interface to emx for single-thread programs.  For
+    instance, this library translates the __open() system call to
+    system call 0x2b of emx.  When using this library, emx.dll is
+    required under OS/2.  This library is always required for DOS
+    programs.
+
+þitem þtt{mt/emx}
+
+    System call interface to emx for multithread programs.  For
+    instance, this library translates the __open() system call to
+    system call 0x2b of emx.  When using this library, emx.dll is
+    required.
+
+þitem emx2
+
+    Import library for emx.dll.  This library is used by libraries
+    emx.a, emx.lib, os2.a, and os2.lib (unless sys.lib is used, see
+    þhpt{-Zsys}).
+
+þitem emxio
+
+    Import library for emxio.dll.  When using hardware port I/O
+    functions such as þhpt{_outp8()} with non-standard libraries, you
+    may have to use this library.  With the standard emx libraries,
+    -lemxio is not required.  -lemxio must not be used if the program
+    should also run under DOS.
+
+þitem þtt{end.lib}
+
+    Library defining the þtt{edata}, þtt{end}, and þtt{etext} symbols.
+    ld automatically defines these symbols, therefore there is no
+    þtt{end.a} library.  GCC uses þtt{-lend} if -Zomf is given on the
+    command line.
+
+þitem þtt{g}
+
+    Dummy debugging library.  GCC uses -lg if -g is given on the
+    command line.
+
+þitem þtt{gcc}
+
+    Compiler helper functions for GCC.  The functions of library
+    þtt{gcc} are duplicated in emxlibcm.dll and emxlibcs.dll.  As
+    library þtt{gcc} requires functions from library þtt{c} and
+    library þtt{c} requires functions from library þtt{gcc}, -lgcc
+    must be given twice on the command line of the Unix-style linker:
+    -lgcc -lc -lgcc.
+
+þitem þtt{gcc_p}
+
+    Compiler helper functions for GCC, with profiling hooks.  See
+    library þtt{gcc}.  This library is used instead of library
+    þtt{gcc} if the -pg option is specified.
+
+þitem þtt{graph}
+
+    Graphics library
+
+þitem þtt{m}
+
+    Dummy math library.  This library is provided for makefile
+    compatibility; it isn't required as the math functions are
+    contained in library þtt{c}.
+
+þitem þtt{st/malloc1}
+
+    Old malloc() library of emx 0.9b and older, single-thread.  This
+    library is provided as fall back in case the new malloc()
+    implementation turns out not to work properly.
+
+þitem þtt{mt/malloc1}
+
+    Old malloc() library of emx 0.9b and older, multithread.  This
+    library is provided as fall back in case the new malloc()
+    implementation turns out not to work properly.
+
+þitem moddef
+
+    Functions for reading module definition files.  See
+    þhpt{_md_open()} for details.  This library can be used for
+    single-thread programs and multithread programs.
+
+þitem þtt{omflib}
+
+    Functions for reading and creating OMF (Object Module Formats)
+    libraries, that is, þtt{.lib} files.
+
+þitem þtt{os2}
+
+    Import library for OS/2 API.  This library is not a pure import
+    library, it also contains static code for DosGetMessage and
+    DosQueryMessageCP and for the 32-bit wrappers.  emx2.a, emx2.lib,
+    or sys.lib is required by the 32-bit wrappers.
+
+þitem þtt{os2_p}
+
+    Profiling hooks and import definitions for OS/2 API.  See library
+    þtt{os2}.  This library is used instead of library þtt{os2} if the
+    -pg option is specified.
+
+þitem þtt{socket}
+
+    Socket library.
+
+þitem þtt{st/sys}
+
+    System call emulation library for single-thread programs.  This
+    library is used instead of emx.a or emx.lib for creating
+    stand-alone OS/2 applications (þhpt{-Zsys}).  It is provided in
+    OMF style only (þtt{st/sys.lib}).
+
+þitem þtt{mt/sys}
+
+    Multithread version of þtt{st/sys} (see above).  This library is
+    provided in OMF style only (þtt{mt/sys.lib}).  It is used instead
+    of þtt{st/sys.lib} if the þhpt{-Zmt} option is specified.
+
+þitem þtt{tmalloc}
+
+    Implement þhpt{_tmalloc()} etc. on top of malloc() etc.  This
+    library is required if you replace the emx implementation of
+    malloc() with an implementation of malloc() (GNU malloc, for
+    instance) that has not _tmalloc() built in.
+
+þitem þtt{video}
+
+    Video library.  This library contains the functions declared in
+    <sys/video.h> and <sys/winmgr.h>.
+
+þitem þtt{wrap}
+
+    Import library for emxwrap.dll.  Use this library (-lwrap) to
+    reduce the size of your executable file when using 16-bit OS/2 API
+    functions.  If you don't use -lwrap, the wrapper functions are
+    taken from library þtt{os2}.
+
+þendlist
+
+þh- The following dynamic link libraries are provided:
+
+þlist
+
+þitem emx.dll
+
+    This is the emx run-time support.  The import library for emx.dll
+    is emx2.
+
+þitem emxio.dll
+
+    Access to hardware ports.  The import library for emxio.dll is
+    emxio.
+
+þitem emxlibc.dll
+
+    Forwarder DLL.  This DLL is provided to maintain compatibility of
+    existing applications using emxlibc.dll.  Entry points are
+    forwarded to emxlibcm.dll.
+
+þitem emxlibcm.dll
+
+    Multithread emx C library.  Contains all functions of the
+    libraries þtt{mt/c}, þtt{mt/c_dllrt}, and þtt{gcc}.  For
+    compatibility with existing programs, emxlibcm.dll contains dummy
+    functions for port I/O, though these didn't work in emxlibc.dll of
+    emx 0.8e.  The import library for emxlibcm.dll is
+    þtt{mt/c_import}.
+
+þitem emxlibcs.dll
+
+    Single-thread emx C library.  Contains all functions of the
+    libraries þtt{st/c}, þtt{st/c_dllrt}, and þtt{gcc}.  The import
+    library for emxlibcs.dll is þtt{st/c_import}.
+
+þitem emxwrap.dll
+
+    32-bit wrappers for 16-bit OS/2 API functions.  This DLL uses
+    emx.dll.  The import library for emxwrap.dll is þtt{wrap}.  The
+    functions contained in emxwrap.dll are also available for static
+    linking in library þtt{os2}.
+
+þendlist
+
+
+þh2 Headers
+
+  This section briefly describes the headers.
+
+þlist
+
+þitem <a_out.h>
+
+    Contains definitions for the a.out file format (.o and executable
+    files).
+
+þitem <alloca.h>
+
+    Makes the þhpt{alloca()} built-in function available.
+
+þitem <ar.h>
+
+    Contains definitions for the archive file format (.a files).
+
+þitem <assert.h>
+
+    Implements assertions for debugging (C90): þhpt{assert()}.
+
+þitem <conio.h>
+
+    Defines getch() and getche() for porting MS-DOS programs.
+
+þitem <ctype.h>
+
+    Character classification macros and functions.  Letter case
+    conversion.  If you include this header, you get the macro
+    (and inline) versions of the routines.  Otherwise, you get the
+    function versions.
+
+    C90 functions and macros: þhpt{isalnum()}, þhpt{isalpha()},
+    þhpt{iscntrl()}, þhpt{isdigit()}, þhpt{isgraph()},
+    þhpt{islower()}, þhpt{isprint()}, þhpt{ispunct()},
+    þhpt{isspace()}, þhpt{isupper()}, þhpt{isxdigit()},
+    þhpt{tolower()}, þhpt{toupper()}.
+
+    Additional functions and macros: þhpt{isascii()},
+    þhpt{_tolower()}, þhpt{_toupper()}.
+
+þitem <curses.h>
+
+    Declarations and definitions of the BSD curses screen library.
+
+þitem <dirent.h>
+
+    Functions for reading directories.
+
+    POSIX.1 functions: þhpt{closedir()}, þhpt{opendir()},
+    þhpt{readdir()}, þhpt{rewinddir()}.
+
+    Additional functions: þhpt{seekdir()}, þhpt{telldir()}.
+
+þitem <dos.h>
+
+    Declares the þhpt{_int86()} function and associated structures.
+
+þitem <errno.h>
+
+    Declares the þhpt{errno} object and defines error code constants
+    (C90).
+
+þitem <fcntl.h>
+
+    Defines file mode constants such as O_RDONLY and other constants.
+    Declares the þhpt{fcntl()} and þhpt{flock()} functions.  Includes
+    <sys/fcntl.h>.
+
+þitem <float.h>
+
+    Floating point constants and functions for controlling the math
+    coprocessor (C90).
+
+    Non-standard functions: þhpt{_clear87()}, þhpt{_control87()},
+    þhpt{_fpreset()}, þhpt{_status87()}.
+
+þitem <fnmatch.h>
+
+    Declares the þhpt{fnmatch()} function and defines constants for
+    fnmatch() (POSIX.2).
+
+þitem <ftw.h>
+
+    File tree walk: þhpt{ftw()}.  Apply a function to all files in a
+    directory tree.
+
+þitem <getopt.h>
+
+    Declares þhpt{getopt()} for parsing command line options
+    (POSIX.2).
+
+þitem <glob.h>
+
+    Declares the þhpt{glob()} and þhpt{globfree()} functions and
+    defines the glob_t type and constants for glob() (POSIX.2).
+
+þitem <graph.h>
+
+    Declares the emx graphics library functions and defines associated
+    constants.
+
+    Functions: þhpt{g_box()}, þhpt{g_clear()}, þhpt{g_clip()},
+    þhpt{g_ellipse()}, þhpt{g_get()}, þhpt{g_hline()}, þhpt{g_line()},
+    þhpt{g_lock()}, þhpt{g_mode()}, þhpt{g_modeset()},
+    þhpt{g_polygon()}, þhpt{g_set()}, þhpt{g_triangle()},
+    þhpt{g_unlock()}, þhpt{g_unlockall()}, þhpt{g_vgapal()},
+    þhpt{g_vline()}, þhpt{g_waitv()}, þhpt{g_wmode()}.
+
+þitem <grp.h>
+
+    Declares the þtt{getgrgid()} and þtt{getgrnam()} functions and
+    defines þtt{struct group} (POSIX.1).
+
+þitem <ieee.h>
+
+    Constants describing the IEEE floating point format used under emx.
+
+þitem <io.h>
+
+    Declares low-level I/O functions.
+
+    Functions: þhpt{access()}, þhpt{chmod()}, þhpt{chsize()},
+    þhpt{close()}, þhpt{creat()}, þhpt{_crlf()}, þhpt{dup()},
+    þhpt{dup2()}, þhpt{eof()}, þhpt{filelength()}, þhpt{fstat()},
+    þhpt{fsync()}, þhpt{ftruncate()}, þhpt{_imphandle()},
+    þhpt{ioctl()}, þhpt{isatty()}, þhpt{_isterm()}, þhpt{lseek()},
+    þhpt{mkstemp()}, þhpt{mktemp()}, þhpt{open()}, þhpt{pipe()},
+    þhpt{read()}, þhpt{remove()}, þhpt{rename()}, þhpt{_seek_hdr()},
+    þhpt{select()}, þhpt{setmode()}, þhpt{sopen()}, þhpt{stat()},
+    þhpt{tell()}, þhpt{truncate()}, þhpt{umask()}, þhpt{unlink()},
+    þhpt{write()}.
+
+þitem <limits.h>
+
+    Data type limit constants (C90).
+
+þitem <locale.h>
+
+    Functions and constants for localization.
+
+    C90 functions: þhpt{localeconv()}, þhpt{setlocale()}.
+
+þitem <malloc.h>
+
+    Declares functions for dynamic memory allocation.  For
+    portability, use <stdlib.h> instead of <malloc.h>.
+
+    C90 functions (note that <malloc.h> is not a C90 header):
+    þhpt{calloc()}, þhpt{free()}, þhpt{malloc()}, þhpt{realloc()}.
+
+    Functions for allocating tiled memory: þhpt{_tcalloc()},
+    þhpt{_tfree()}, þhpt{_tmalloc()}, þhpt{_trealloc()}.
+
+    Additional non-standard functions: þhpt{_expand()},
+    þhpt{_heapchk()}, þhpt{_heapmin()}, þhpt{_heapset()},
+    þhpt{_msize()}.
+
+þitem <math.h>
+
+    Declares floating-point functions.
+
+    C90 functions: þhpt{acos()}, þhpt{asin()}, þhpt{atan()},
+    þhpt{atan2()}, þhpt{ceil()}, þhpt{cos()}, þhpt{cosh()},
+    þhpt{exp()}, þhpt{fabs()}, þhpt{floor()}, þhpt{fmod()},
+    þhpt{frexp()}, þhpt{ldexp()}, þhpt{log()}, þhpt{log10()},
+    þhpt{modf()}, þhpt{pow()}, þhpt{sin()}, þhpt{sinh()},
+    þhpt{sqrt()}, þhpt{tan()}, þhpt{tanh()}.
+
+    Functions proposed for C9X: þhpt{acosl()}, þhpt{asinl()},
+    þhpt{atanl()}, þhpt{atan2l()}, þhpt{ceill()}, þhpt{copysign()},
+    þhpt{copysignf()}, þhpt{copysignl()}, þhpt{cosl()}, þhpt{coshl()},
+    þhpt{expl()}, þhpt{fabsl()}, þhpt{floorl()}, þhpt{fmodl()},
+    þhpt{frexpl()}, þhpt{hypot()}, þhpt{hypotl()}, þhpt{ldexpl()},
+    þhpt{logl()}, þhpt{log10l()}, þhpt{modfl()}, þhpt{nextafter()},
+    þhpt{nextafterf()}, þhpt{nextafterl()}, þhpt{powl()},
+    þhpt{rint()}, þhpt{rintl()}, þhpt{sinl()}, þhpt{sinhl()},
+    þhpt{sqrtl()}, þhpt{tanl()}, þhpt{tanhl()}, þhpt{trunc()},
+    þhpt{truncl()}.
+
+    Macros proposed for C9X: þhpt{fpclassify()}, þhpt{isfinite()},
+    þhpt{isnan()}, þhpt{isnormal()}, þhpt{signbit()}.
+
+    Other functions: þhpt{atof()}, þhpt{_atofl()}, þhpt{cbrt()},
+    þhpt{_cbrtl()}.
+
+þitem <memory.h>
+
+    Declares functions dealing with blocks of memory.  New programs
+    should use <string.h> instead.
+
+    Functions: þhpt{memccpy()}, þhpt{memchr()}, þhpt{memcmp()},
+    þhpt{_memcount()}, þhpt{memcpy()}, þhpt{_memdif()},
+    þhpt{memicmp()}, þhpt{memmove()}, þhpt{_memrchr()},
+    þhpt{memset()}, þhpt{_memswap()}.
+
+þitem <os2.h>
+
+    Include this header to get all or part of the OS/2 constants,
+    macros and functions.  Includes either <os2emx.h> or <os2tk.h>.
+    Either change <os2.h> or #define USE_OS2_TOOLKIT_HEADERS in your
+    source file to use the header files of the Programmer's Toolkit
+    for OS/2 2.x (an IBM product).
+
+þitem <os2emx.h>
+
+    A subset of the OS/2 definitions and declarations.  This header
+    file is included by <os2.h> unless you choose to use the header
+    files of the Programmer's Toolkit for OS/2 2.x (an IBM product).
+
+þitem <os2thunk.h>
+
+    Thunking support, included by <os2.h>.  You don't have to include
+    this header in your programs unless you want to create thunks
+    without including <os2.h>.
+
+þitem <os2tk.h>
+
+    Makes the header files of the Developer's Toolkit for OS/2 2.x
+    usable for emx and GCC.
+
+þitem <process.h>
+
+    Process management.  Includes <sys/process.h>.
+
+    Functions: þhpt{abort()}, þhpt{atexit()}, þhpt{execl()},
+    þhpt{execle()}, þhpt{execlp()}, þhpt{execlpe()}, þhpt{execv()},
+    þhpt{execve()}, þhpt{execvp()}, þhpt{execvpe()}, þhpt{exit()},
+    þhpt{_exit()}, þhpt{fork()}, þhpt{getpid()}, þhpt{getppid()},
+    þhpt{spawnl()}, þhpt{spawnle()}, þhpt{spawnlp()},
+    þhpt{spawnlpe()}, þhpt{spawnv()}, þhpt{spawnve()},
+    þhpt{spawnvp()}, þhpt{spawnvpe()}, þhpt{system()}, þhpt{wait()},
+    hpt{waitpid()}.
+
+þitem <pwd.h>
+
+    Password management.
+
+    POSIX.1 functions: þhpt{getpwnam()}, þhpt{getpwuid()}.
+
+    Additional functions: þhpt{endpwent()}, þhpt{getpass()},
+    þhpt{_getpass1()}, þhpt{_getpass2()}, þhpt{getpwent()},
+    þhpt{setpwent()}.
+
+þitem <setjmp.h>
+
+    Non-local jumps.  Defines jmp_buf and sigjmp_buf.
+
+    C90 functions: þhpt{longjmp()}, þhpt{setjmp()}.
+
+    POSIX.1 functions: þhpt{siglongjmp()}, þhpt{sigsetjmp()}.
+
+þitem <sgtty.h>
+
+    Empty file.  emx doesn't have a BSD-style general terminal interface.
+
+þitem <share.h>
+
+    Constants for file sharing.
+
+þitem <signal.h>
+
+    Signal processing.  Includes <sys/signal.h>.
+
+    C90 functions: þhpt{signal()}, þhpt{raise()}.
+
+    POSIX.1 functions: þhpt{kill()}, þhpt{pause()}, þhpt{sigaction()},
+    þhpt{sigaddset()}, þhpt{sigdelset()}, þhpt{sigemptyset()},
+    þhpt{sigfillset()}, þhpt{sigismember()}, þhpt{sigpending()},
+    þhpt{sigprocmask()}, þhpt{sigsuspend()}.
+
+þitem <stdarg.h>
+
+    Macros to implement functions with variable number of arguments --
+    ISO C version.
+
+    C90 macros: þhpt{va_start()}, þhpt{va_arg()}, þhpt{va_end()}.
+
+þitem <stddef.h>
+
+    Various definitions.
+
+    C90 macros: þhpt{offsetof()}.
+
+    Other macros: þhpt{_threadid}.
+
+þitem <stdio.h>
+
+    Stream I/O library.
+
+    C90 functions: þhpt{clearerr()}, þhpt{fclose()},
+    þhpt{feof()}, þhpt{ferror()}, þhpt{fflush()}, þhpt{fgetc()},
+    þhpt{fgetpos()}, þhpt{fgets()}, þhpt{fopen()}, þhpt{fprintf()},
+    þhpt{fputc()}, þhpt{fputs()}, þhpt{fread()}, þhpt{freopen()},
+    þhpt{fscanf()}, þhpt{fseek()}, þhpt{fsetpos()}, þhpt{ftell()},
+    þhpt{fwrite()}, þhpt{getc()}, þhpt{getchar()}, þhpt{gets()},
+    þhpt{perror()}, þhpt{printf()}, þhpt{putc()}, þhpt{putchar()},
+    þhpt{puts()}, þhpt{remove()}, þhpt{rename()}, þhpt{rewind()},
+    þhpt{scanf()}, þhpt{setbuf()}, þhpt{setvbuf()}, þhpt{sprintf()},
+    þhpt{sscanf()}, þhpt{tmpfile()}, þhpt{tmpnam()}, þhpt{ungetc()},
+    þhpt{vfprintf()}, þhpt{vprintf()}, þhpt{vsprintf()}.
+
+    POSIX.1 functions: þhpt{fdopen()}, þhpt{fileno()}.
+
+    POSIX.2 functions: þhpt{pclose()}, þhpt{popen()}.
+
+    Additional functions: þhpt{cuserid()}, þhpt{_fassign()},
+    þhpt{fcloseall()}, þhpt{fgetchar()}, þhpt{flushall()},
+    þhpt{fputchar()}, þhpt{_fseek_hdr()}, þhpt{_fsetmode()},
+    þhpt{_fsopen()}, þhpt{getw()}, þhpt{_mfclose()}, þhpt{_mfopen()},
+    þhpt{putw()}, þhpt{setbuffer()}, þhpt{snprintf()},
+    þhpt{tempnam()}, þhpt{vfscanf()}, þhpt{vscanf()},
+    þhpt{vsnprintf()}, þhpt{vsscanf()}.
+
+þitem <stdlib.h>
+
+    Various library functions and global variables.  Includes <malloc.h>.
+
+    C90 string conversion functons: þhpt{atof()}, þhpt{atoi()},
+    þhpt{atol()}, þhpt{strtod()}, þhpt{strtol()}, þhpt{strtoul()}.
+
+    C90 functions for generating pseudo-random sequences:
+    þhpt{rand()}, þhpt{srand()}.
+
+    C90 memory management functions: þhpt{calloc()}, þhpt{free()},
+    þhpt{malloc()}, þhpt{realloc()}.
+
+    C90 functions for searching and sorting: þhpt{bsearch()},
+    þhpt{qsort()}.
+
+    C90 integer arithmetic functions: þhpt{abs()}, þhpt{div()},
+    þhpt{labs()}, þhpt{ldiv()}.
+
+    C90 multibyte character functions: þhpt{mblen()},
+    þhpt{mbstowcs()}, þhpt{mbtowc()}, þhpt{wcstombs()},
+    þhpt{wctomb()}.
+
+    Other C90 functions: þhpt{abort()}, þhpt{atexit()}, þhpt{exit()},
+    þhpt{getenv()}, þhpt{system()}.
+
+    String conversion functions proposed for C9X: þhpt{strtof()},
+    þhpt{strtold()}.
+
+    Additional string conversion functions (to and from strings):
+    þhpt{_atofl()}, þhpt{_atoll()}, þhpt{gcvt()}, þhpt{_itoa()},
+    þhpt{_lltoa()}, þhpt{_ltoa()}, þhpt{_strtoll()},
+    þhpt{_strtoull()}, þhpt{_ulltoa()}, þhpt{_ultoa()}.
+
+    Additional functions for generating pseudo-random sequences:
+    þtt{initstate()}, þtt{random()}, þtt{setstate()}, þtt{srandom()}.
+
+    Additional memory management functions: þhpt{brk()},
+    þhpt{_expand()}, þhpt{_heapchk()}, þhpt{_heapmin()},
+    þhpt{_heapset()}, þhpt{_msize()}, þhpt{sbrk()}.
+
+    Additional functions for allocating tiled memory:
+    þhpt{_tcalloc()}, þhpt{_tfree()}, þhpt{_tmalloc()},
+    þhpt{_trealloc()}.
+
+    Additional functions for searching and sorting: þtt{heapsort()}.
+
+    Additional integer arithmetic functions: þhpt{_lldiv()},
+    þhpt{_uldiv()}, þhpt{_ulldiv()}.
+
+    Additional functions for managing directories and disk drives:
+    þhpt{chdir()}, þhpt{_chdir2()}, þhpt{_chdrive()},
+    þhpt{_filesys()}, þhpt{getcwd()}, þhpt{_getcwd1()},
+    þhpt{_getcwd2()}, þhpt{_getvol()}, þhpt{getwd()}, þhpt{mkdir()},
+    þhpt{rmdir()}.
+
+    Additional functions for processing file names: þhpt{_abspath()},
+    þhpt{_defext()}, þhpt{_fncmp()}, þhpt{_fnexplode()},
+    þhpt{_fnexplodefree()}, þhpt{_fngetdrive()}, þhpt{_fnisabs()},
+    þhpt{_fnisrel()}, þhpt{_fnlwr()}, þhpt{_fnlwr2()},
+    þhpt{_fnslashify()}, þhpt{_fullpath()}, þhpt{_getdrive()},
+    þhpt{_getext()}, þhpt{_getext2()}, þhpt{_getname()},
+    þhpt{_makepath()}, þhpt{_path()}, þhpt{_remext()},
+    þhpt{_rfnlwr()}, þhpt{_sfnlwr()}, þhpt{_splitpath()}.
+
+    Additional functions for multithread programs:
+    þhpt{_beginthread()}, þhpt{_endthread()}, þhpt{_gettid()},
+    þhpt{_threadstore()}.
+
+    Additional functions for managing the command line:
+    þhpt{_envargs()}, þhpt{_response()}, þhpt{_wildcard()}.
+
+    Miscellaneous additional functions: þhpt{alarm()}, þhpt{_core()},
+    þhpt{_execname()}, þhpt{_exit()}, þhpt{getpagesize()},
+    þhpt{_getsockhandle()}, þhpt{perror()}, þhpt{putenv()},
+    þhpt{_read_kbd()}, þhpt{_scrsize()}, þhpt{_searchenv()},
+    þhpt{_setsyserrno()}, þhpt{sleep()}, þhpt{_sleep2()},
+    þhpt{_splitargs()}, þhpt{swab()}, þhpt{_swchar()},
+    þhpt{_syserrno()}, þhpt{ulimit()}.
+
+þitem <string.h>
+
+    This header declares functions for processing null-terminated
+    strings and for processing arrays of characters and objects
+    treated as arrays of characters.
+
+    C90 functions for processing null-terminated strings:
+    þhpt{strcat()}, þhpt{strchr()}, þhpt{strcmp()}, þhpt{strcoll()},
+    þhpt{strcpy()}, þhpt{strcspn()}, þhpt{strerror()}, þhpt{strlen()},
+    þhpt{strncat()}, þhpt{strncmp()}, þhpt{strncpy()},
+    þhpt{strpbrk()}, þhpt{strrchr()}, þhpt{strspn()}, þhpt{strstr()},
+    þhpt{strtok()}, þhpt{strxfrm()}.
+
+    C90 functions for processing arrays of characters:
+    þhpt{memchr()}, þhpt{memcmp()}, þhpt{memcpy()}, þhpt{memmove()},
+    þhpt{memset()}.
+
+    Non-standard functions for processing null-terminated strings:
+    þhpt{strdup()}, þhpt{stricmp()}, þhpt{strlwr()}, þhpt{_strncpy()},
+    þhpt{strnicmp()}, þhpt{strnset()}, þhpt{strrev()}, þtt{strsep()},
+    þhpt{strset()}, þhpt{strupr()}.
+
+    Non-standard functions for processing arrays of characters:
+    þhpt{memccpy()}, þhpt{_memcount()}, þhpt{_memdif()},
+    þhpt{memicmp()}, þhpt{_memrchr()}, þhpt{_memswap()}.
+
+þitem <strings.h>
+
+    This header defines the BSD string and memory functions and
+    includes <string.h>.
+
+    BSD functions: þhpt{bcmp()}, þhpt{bcopy()}, þhpt{bzero()},
+    þhpt{ffs()}, þhpt{index()}, þhpt{rindex()}.
+
+þitem <termcap.h>
+
+    Terminal data base (FSF).
+
+þitem <termio.h>
+
+    Defines þtt{struct termio} and constants for the þhpt{general
+    terminal interface} (System V variant).  Includes <sys/termio.h>.
+
+þitem <termios.h>
+
+    Declares functions and defines þtt{struct termios} and constants
+    for the þhpt{general terminal interface} (POSIX.1 variant).
+
+    POSIX.1 functions: þhpt{cfgetispeed()}, þhpt{cfgetospeed()},
+    þhpt{cfsetispeed()}, þhpt{cfsetospeed()}, þhpt{tcdrain()},
+    þhpt{tcflow()}, þhpt{tcflush()}, þhpt{tcgetattr()},
+    þhpt{tcsendbreak()}, þhpt{tcsetattr()}.
+
+þitem <time.h>
+
+    Functions and structures for converting time values between
+    various formats.
+
+    C90 functions: þhpt{asctime()}, þhpt{ctime()}, þhpt{clock()},
+    þhpt{difftime()}, þhpt{gmtime()}, þhpt{localtime()},
+    þhpt{mktime()}, þhpt{strftime()}, þhpt{time()}.
+
+    POSIX.1 functions: þhpt{tzset()}.
+
+    Additional functions: þhpt{strptime()}.
+
+þitem <ulimit.h>
+
+    Declares the þhpt{ulimit()} function and defines constants for
+    ulimit().
+
+þitem <umalloc.h>
+
+    Declares heap-specific functions for dynamic memory allocation.
+    See þhpt{_ucreate2()} for details.
+
+    Functions for allocating memory: þhpt{_ucalloc()},
+    þhpt{_umalloc()}.
+
+    Functions for allocating tiled memory: þhpt{_utcalloc()},
+    þhpt{_utmalloc()}.
+
+    Functions for maintaining heaps: þhpt{_theapmin()},
+    þhpt{_uaddmem()}, þhpt{_uclose()}, þhpt{_ucreate()}
+    þhpt{_ucreate2()}, þhpt{_udefault()}, þhpt{_udestroy()},
+    þhpt{_uheapchk()}, þhpt{_uheapmin()}, þhpt{_uheapset()},
+    þhpt{_uopen()}, þhpt{_utdefault()}.
+
+    Functions for getting information about blocks and heaps:
+    þhpt{_mheap()}, þhpt{_uheap_type()}, þhpt{_uheap_walk()},
+    þhpt{_uheap_walk2()}, þhpt{_ustats()}.
+
+    Functions declared in <malloc.h> which can also be used on blocks
+    allocated by heap-specific functions: þhpt{_expand()},
+    þhpt{free()}, þhpt{_msize()}, þhpt{realloc()}.
+
+þitem <unistd.h>
+
+    Various POSIX.1-related definitions and declarations.
+
+    POSIX.1 functions: þhpt{access()}, þhpt{alarm()}, þhpt{chdir()},
+    þhpt{close()}, þhpt{cuserid()}, þhpt{dup()}, þhpt{dup2()},
+    þhpt{execl()}, þhpt{execle()}, þhpt{execlp()}, þhpt{execv()},
+    þhpt{execve()}, þhpt{execvp()}, þhpt{_exit()}, þhpt{fork()},
+    þhpt{fpathconf()}, þhpt{getcwd()}, þtt{getegid()}, þtt{geteuid()},
+    þtt{getgid()}, þtt{getgroups()}, þtt{getlogin()}, þtt{getpgrp()},
+    þhpt{getpid()}, þhpt{getppid()}, þtt{getuid()}, þhpt{isatty()},
+    þhpt{lseek()}, þhpt{pathconf()}, þhpt{pause()}, þhpt{pipe()},
+    þhpt{read()}, þhpt{rmdir()}, þtt{setgid()}, þtt{setpgid()},
+    þtt{setsid()}, þtt{setuid()}, þhpt{sleep()}, þhpt{sysconf()},
+    þtt{tcgetpgrp()}, þtt{tcsetpgrp()}, þhpt{ttyname()},
+    þhpt{unlink()}, þhpt{write()}.
+
+    POSIX.2 functions: þhpt{getopt()}.
+
+    Additional functions: þhpt{brk()}, þhpt{getpass()},
+    þhpt{_getpass1()}, þhpt{_getpass2()}, þhpt{mkstemp()},
+    þhpt{mktemp()}, þhpt{profil()}, þhpt{sbrk()}.
+
+þitem <utime.h>
+
+    Declares þhpt{utime()} and defines þtt{struct utimbuf}.  Includes
+    <sys/utime.h>.
+
+þitem <varargs.h>
+
+    Functions with variable number of arguments -- traditional Unix
+    version.  New programs should use <stdarg.h> instead of
+    <varargs.h>, therefore the macros of <varargs.h> are not
+    documented here.
+
+þitem <emx/bigint.h>
+
+    Internal header file for the implementation of decimal to binary
+    and binary to decimal conversions of floating point numbers.
+    Application programs should never include this header -- it's used
+    for library modules only.
+
+þitem <emx/float.h>
+
+    Internal header file for the implementation of floating point
+    math.  Application programs should never include this header --
+    it's used for library modules only.
+
+þitem <emx/io.h>
+
+    Internal header file for the implementation of low-level I/O and
+    stream I/O.  Application programs should never include this header
+    -- it's used for library modules only.
+
+þitem <emx/nls.h>
+
+    Internal header file for the implementation of some functions of
+    <sys/nls.h>.  Application programs should never include this header --
+    it's used for library modules only.
+
+þitem <emx/pwd.h>
+
+    Internal header file for the implementation of some functions of
+    <pwd.h>.  Application programs should never include this header --
+    it's used for library modules only.
+
+þitem <emx/startup.h>
+
+    Internal header file for the implementation of startup and cleanup
+    code.  Application programs should never include this header --
+    it's used for library modules only.
+
+þitem <emx/syscalls.h>
+
+    Declare emx syscall functions and defines constants and types for
+    emx syscalls.  Application programs should never include this
+    header -- it's used for library modules only.
+
+þitem <emx/thread.h>
+
+    Internal header file for the implementation of thread-local
+    variables used by library functions.  Application programs should
+    never include this header -- it's used for library modules only.
+
+þitem <emx/time.h>
+
+    Internal header file for the implementation of time-related
+    library functions.  Application programs should never include this
+    header -- it's used for library modules only.
+
+þitem <emx/umalloc.h>
+
+    Internal header file for the implementation of malloc().
+    Application programs should never include this header -- it's used
+    for library modules only.
+
+þitem <sys/builtin.h>
+
+    Defines inline assembly functions for some low-level tasks.
+    Several of these functions are provided for compatibility with
+    functions declared in the þtt{<builtin.h>} header of IBM's Visual
+    Age C++ 3.0 compiler (VAC++).
+
+    Functions for RAM semaphores: þhpt{__cxchg()}, þhpt{__lxchg()},
+    þhpt{__sxchg()}.
+
+    Functions for disabling and enabling interrupts:
+    þhpt{__disable()}, þhpt{__enable()}.
+
+    Functions for bit operations: þhpt{_crotl()}, þhpt{_crotr()},
+    þhpt{__fls()}, þhpt{_lrotl()}, þhpt{_lrotr()}, þhpt{_srotl()},
+    þhpt{_srotr()}.
+
+þitem <sys/dir.h>
+
+    Prerequisite header: <sys/types.h>You should use <dirent.h>
+    instead of <sys/dir.h>.
+
+    Functions: þhpt{closedir()}, þhpt{readdir()}, þhpt{rewinddir()},
+    þhpt{opendir()}, þhpt{seekdir()}, þhpt{telldir()}.
+
+þitem <sys/dirent.h>
+
+    Defines þtt{struct dirent} and associated constants.  This header
+    file is used by <dirent.h>, you don't have to include <sys/dirent.h>
+    yourself.
+
+þitem <sys/dirtree.h>
+
+    Declares the emx directory tree functions and defines associated
+    constants and types.
+
+    Functions: þhpt{_dt_free()}, þhpt{_dt_read()}, þhpt{_dt_sort()},
+    þhpt{_dt_split()}.
+
+þitem <sys/ea.h>
+
+    Defines þtt{struct _ea} and declares the emx functions for
+    low-level extended attributes handling.  See also <sys/ead.h> --
+    don't confuse these two different approaches to extended
+    attributes.
+
+    Functions: þhpt{_ea_free()}, þhpt{_ea_get()}, þhpt{_ea_put()},
+    þhpt{_ea_remove()}.
+
+þitem <sys/ead.h>
+
+    Declares the _ead type and the emx functions for high-level
+    extended attributes handling via `EA descriptors'.  See also also
+    <sys/ea.h> -- don't confuse these two different approaches to
+    extended attributes.
+
+    Functions: þhpt{_ead_add()}, þhpt{_ead_clear()},
+    þhpt{_ead_copy()}, þhpt{_ead_count()}, þhpt{_ead_create()},
+    þhpt{_ead_delete()}, þhpt{_ead_destroy()},
+    þhpt{_ead_fea2list_size()}, þhpt{_ead_fea2list_to_fealist()},
+    þhpt{_ead_fealist_to_fea2list()}, þhpt{_ead_find()},
+    þhpt{_ead_get_fea2list()}, þhpt{_ead_get_flags()},
+    þhpt{_ead_get_name()}, þhpt{_ead_get_value()},
+    þhpt{_ead_name_len()}, þhpt{_ead_read()}, þhpt{_ead_replace()},
+    þhpt{_ead_sort()}, þhpt{_ead_use_fea2list()},
+    þhpt{_ead_value_size()}, þhpt{_ead_write()}.
+
+þitem <sys/emxload.h>
+
+    Declares functions for keeping programs in memory with
+    þtt{emxload.exe}.
+
+    Functions: þhpt{_emxload_env()}, þhpt{_emxload_this()},
+    þhpt{_emxload_prog()}, þhpt{_emxload_unload()},
+    þhpt{_emxload_list_start()}, þhpt{_emxload_list_get()},
+    þhpt{_emxload_connect()}, þhpt{_emxload_disconnect()},
+    þhpt{_emxload_stop()}.
+
+þitem <sys/fcntl.h>
+
+    Defines file mode constants such as O_RDONLY and other constants.
+    Declares the þhpt{fcntl()} and þhpt{flock()} functions.  You
+    should include <fcntl.h> instead.
+
+þitem <sys/file.h>
+
+    This header is provided for compatibility with Unix systems
+    -- it includes <sys/fcntl.h>.
+
+þitem <sys/fmutex.h>
+
+    Prerequisite header: <sys/builtin.h>
+
+    This header contains definitions and declarations for _fmutex
+    semaphores.  _fmutex semaphores are fast RAM semaphores which
+    control access to a resources shared by threads or processes.  See
+    `þhpt{_fmutex semaphores}' for details.
+
+    Functions: þhpt{_fmutex_available()},
+    þhpt{_fmutex_checked_close()}, þhpt{_fmutex_checked_create()},
+    þhpt{_fmutex_checked_open()}, þhpt{_fmutex_checked_release()},
+    þhpt{_fmutex_checked_request()}, þhpt{_fmutex_close()},
+    þhpt{_fmutex_create()}, þhpt{_fmutex_dummy()},
+    þhpt{_fmutex_open()}, þhpt{_fmutex_release()},
+    þhpt{_fmutex_request()}.
+
+þitem <sys/hw.h>
+
+    Declares the emx port access and memory access functions.
+
+    Function: þhpt{_inp8()}, þhpt{_inp16()}, þhpt{_inp32()},
+    þhpt{_inps8()}, þhpt{_inps16()}, þhpt{_inps32()},
+    þhpt{_memaccess()}, þhpt{_outp8()}, þhpt{_outp16()},
+    þhpt{_outp32()}, þhpt{_outps8()}, þhpt{_outps16()},
+    þhpt{_outps32()}, þtt{_outpt()}, þhpt{_outps8dac()},
+    þhpt{_portaccess()}, þhpt{_wait0()}, þhpt{_wait01()},
+    þhpt{_wait1()}, þhpt{_wait10()}.
+
+þitem <sys/ioctl.h>
+
+    Declares the þhpt{ioctl()} function and defines various constants
+    to be used with ioctl().  This header includes <sys/so_ioctl.h> if
+    a TCP/IP-related header such as <sys/socket.h> has been included
+    before <sys/ioctl.h>.
+
+þitem <sys/ipc.h>
+
+    This header contains some definitions for System V IPC
+    facilities.  However, these are not yet implemented in emx.
+
+þitem <sys/kbdscan.h>
+
+    Defines keyboard scan codes.
+
+þitem <sys/moddef.h>
+
+    Declares types and functions for reading module definition files.
+
+    Functions: þhpt{_md_close()}, þhpt{_md_errmsg()},
+    þhpt{_md_get_linenumber()}, þhpt{_md_get_number()},
+    þhpt{_md_get_string()}, þhpt{_md_get_token()},
+    þhpt{_md_next_token()}, þhpt{_md_open()}, þhpt{_md_parse()},
+    þhpt{_md_use_file()}.
+
+þitem <sys/msg.h>
+
+    This header contains some definitions for System V message
+    queues.  However, these are not yet implemented in emx.
+
+þitem <sys/nls.h>
+
+    Declares the emx national-language support functions and macros.
+
+    Functions: þhpt{_nls_init()}, þhpt{_nls_strlwr()},
+    þhpt{_nls_strupr()}.
+
+    Macros: þhpt{_nls_tolower()}, þhpt{_nls_toupper()},
+    þhpt{_nls_is_dbcs_lead()}.
+
+þitem <sys/param.h>
+
+    Defines constants such as MAXNAMLEN which describe system
+    parameters.
+
+þitem <sys/process.h>
+
+    Process handling.  Application programs should include <process.h>
+    instead.  See <process.h> for details.
+
+þitem <sys/ptrace.h>
+
+    Declares the þhpt{ptrace()} function and defines associated
+    constants.
+
+þitem <sys/reg.h>
+
+    Defines register offset constants.  These are usually used with
+    þhpt{ptrace()} and for reading core dump files.
+
+þitem <sys/resource.h>
+
+    This header is empty.
+
+þitem <sys/rmutex.h>
+
+    Prerequisite headers: <sys/builtin.h>, <sys/fmutex.h>
+
+    This header contains definitions and declarations for _rmutex
+    semaphores.  _rmutex semaphores are registered _fmutex semaphores.
+    See `þhpt{_fmutex semaphores}' for details.
+
+    Functions: þhpt{_rmutex_available()},
+    þhpt{_rmutex_checked_close()}, þhpt{_rmutex_checked_create()},
+    þhpt{_rmutex_checked_open()}, þhpt{_rmutex_checked_release()},
+    þhpt{_rmutex_checked_request()}, þhpt{_rmutex_close()},
+    þhpt{_rmutex_create()}, þhpt{_rmutex_dummy()},
+    þhpt{_rmutex_open()}, þhpt{_rmutex_release()},
+    þhpt{_rmutex_request()}.
+
+þitem <sys/select.h>
+
+    Defines the fd_set type and macros (FD_SET etc.) for þhpt{select()}.
+
+þitem <sys/signal.h>
+
+    Functions and constants for signal processing.  Application
+    programs should include <signal.h> instead.
+
+þitem <sys/smutex.h>
+
+    Prerequisite header: <sys/builtin.h>
+
+    This header contains definitions and declarations for _smutex
+    semaphores.  _smutex semaphores are very simple RAM semaphores
+    which control access to a resources shared by threads or
+    processes.  See `þhpt{_smutex semaphores}' for details.
+
+    Functions: þhpt{_smutex_available()}, þhpt{_smutex_release()},
+    þhpt{_smutex_request()}.
+
+þitem <sys/socket.h>
+
+    Definitions and declarations related to sockets.
+
+þitem <sys/so_ioctl.h>
+
+    Socket-specific definitions for ioctl().  This header is
+    automatically included by <sys/ioctl.h> if a TCP/IP-related header
+    such as <sys/socket.h> has been included before <sys/ioctl.h>.
+
+þitem <sys/stat.h>
+
+    Prerequisite header: <sys/types.h>
+
+    Defines þtt{struct stat} for þhpt{stat()} and þhpt{fstat()}.
+    Defines S_IREAD, S_IWRITE and S_IEXEC for þhpt{open()}.  Defines
+    S_IFCHR etc. constants and S_ISCHR etc. macros for checking file
+    types.  Declares the stat() and fstat() functions.
+
+þitem <sys/statfs.h>
+
+    Declares þtt{struct statfs} -- which is not yet supported by emx.
+
+þitem <sys/termio.h>
+
+    Defines þtt{struct termio} and constants for the þhpt{general
+    terminal interface} (System V variant).
+
+þitem <sys/time.h>
+
+    Declares þhpt{utimes()}, þhpt{gettimeofday()} and
+    þhpt{settimeofday()}.
+
+þitem <sys/timeb.h>
+
+    Declares þhpt{ftime()} and defines þtt{struct timeb}.
+
+þitem <sys/times.h>
+
+    Prerequisite header: <time.h>
+
+    Declares þhpt{times()} and defines þtt{struct tms}.
+
+þitem <sys/types.h>
+
+    Defines various types such as ino_t for <sys/stat.h>.  Defines the
+    fd_set type and macros (FD_SET etc.) for þhpt{select()}.
+
+þitem <sys/uio.h>
+
+    Declares þtt{struct iovec} and the þtt{readv()} and þtt{writev()}
+    functions.
+
+þitem <sys/uflags.h>
+
+    Declares the þhpt{_uflags()} function and constants for _uflags().
+
+þitem <sys/user.h>
+
+    Declares þtt{struct user} which is used by þhpt{ptrace()} and in
+    core dump files.  See also <sys/reg.h> and <sys/ptrace.h>.
+
+þitem <sys/utime.h>
+
+    Declares þhpt{utime()} and defines þtt{struct utimbuf}.  You
+    should include <utime.h> instead.
+
+þitem <sys/utsname.h>
+
+    Declares þhpt{uname()} and defines þtt{struct utsname}.
+
+þitem <sys/video.h>
+
+    Declares the emx video library functions and defines associated
+    constants.
+
+    Functions: þhpt{v_attrib()}, þhpt{v_backsp()}, þhpt{v_clear()},
+    þhpt{v_clreol()}, þhpt{v_ctype()}, þhpt{v_delline()},
+    þhpt{v_dimen()}, þhpt{v_fclose()}, þhpt{v_fopen()},
+    þhpt{v_getattr()}, þhpt{v_getctype()}, þhpt{v_getline()},
+    þhpt{v_getxy()}, þhpt{v_gotoxy()}, þhpt{v_hardware()},
+    þhpt{v_hidecursor()}, þhpt{v_init()}, þhpt{v_insline()},
+    þhpt{v_putc()}, þhpt{v_putline()}, þhpt{v_putm()},
+    þhpt{v_putmask()}, þhpt{v_putn()}, þhpt{v_puts()},
+    þhpt{v_scroll()}, þhpt{v_scrollup()}, þhpt{v_printf()},
+    þhpt{v_vprintf()}.
+
+þitem <sys/wait.h>
+
+    Declares þhpt{wait()} and þhpt{waitpid()}.  Defines constants and
+    macros for using these functions.
+
+þitem <sys/winmgr.h>
+
+    Declares the emx window manager library functions and the
+    wm_handle type.  Defines window manager constants.
+
+    Functions for mangaging windows: þhpt{wm_border()},
+    þhpt{wm_bottom()}, þhpt{wm_close()}, þhpt{wm_close_all()},
+    þhpt{wm_create()}, þhpt{wm_delete()}, þhpt{wm_dimen()},
+    þhpt{wm_down()}, þhpt{wm_exit()}, þhpt{wm_find()},
+    þhpt{wm_get_pos()}, þhpt{wm_init()}, þhpt{wm_move()},
+    þhpt{wm_open()}, þhpt{wm_top()}, þhpt{wm_up()}, þhpt{wm_update()}.
+
+    Functions for managing the cursor: þhpt{wm_chide()},
+    þhpt{wm_ctype()}, þhpt{wm_cursor()}, þhpt{wm_cvis()},
+    þhpt{wm_get_cursor()}, þhpt{wm_getx()}, þhpt{wm_getxy()},
+    þhpt{wm_gety()}, þhpt{wm_gotoxy()}.
+
+    Functions for scrolling: þhpt{wm_del_char()}, þhpt{wm_del_line()},
+    þhpt{wm_ins_char()}, þhpt{wm_ins_line()}, þhpt{wm_scroll()},
+
+    Functions for output to a window: þhpt{wm_attrib()},
+    þhpt{wm_attrib_all()}, þhpt{wm_backsp()}, þhpt{wm_clear()},
+    þhpt{wm_clr_eol()}, þhpt{wm_fclose()}, þhpt{wm_fopen()},
+    þhpt{wm_get_attrib()}, þhpt{wm_printf()}, þhpt{wm_puta_at()},
+    þhpt{wm_putc()}, þhpt{wm_putc_at()}, þhpt{wm_putca()},
+    þhpt{wm_putca_at()}, þhpt{wm_puts()}, þhpt{wm_puts_at()},
+    þhpt{wm_putsa()}, þhpt{wm_putsa_at()}, þhpt{wm_vprintf()},
+    þhpt{wm_wrap()}.
+
+þendlist
+
+þh1 Dynamic memory allocation
+
+  Dynamic memory allocation means allocation of objects at runtime
+  where the lifetime of the objects is independent of the nesting of
+  blocks and functions.
+
+þipfminitoc
+
+þh2 Allocating blocks
+
+  The þhpt{malloc()} function is used to dynamically allocate an
+  object.  You pass the size of the object to malloc() and malloc will
+  return a pointer to a block of memory allocated from a heap.  The
+  contents of the block are indeterminate.  If you need a block of
+  memory initialized to zeros, use the þhpt{calloc()} function.
+  calloc() takes two arguments: the number of objects and the size of
+  one object.  The size of the block is the product of the two
+  numbers.  Using calloc() can be more efficient than calling malloc()
+  and zeroing the block with memset() because calloc() can avoid
+  zeroing the block if it knows that it already is zeroed.
+
+þh2 Deallocating (freeing) blocks
+
+  When you no longer need the object, you can deallocate it by passing
+  a pointer to the object to the þhpt{free()} function.  After
+  deallocating a block, you must no longer use the block.  (Strictly,
+  you are even no longer allowed to use the pointer to the block.)
+  The memory block can be reused later by malloc() etc. for other
+  dynamically allocated objects.
+
+þh2 Resizing blocks
+
+  The size of blocks allocated with malloc() etc. can be changed with
+  the þhpt{realloc()} function.  Quite often, the size of a block
+  cannot be changed in place, that is, the block must be moved to
+  another location in the heap.  Therefore, realloc() returns a
+  pointer to the new location of block, which might happen to be equal
+  to the old one.
+
+  The þhpt{_expand()} function attempts to resize a block in place,
+  that is, without moving it.  In most cases, blocks cannot be resized
+  in place.  If resizing the block fails, _expand() does not move the
+  block to another location.
+
+þh2 ISO 9899 standard
+
+  Whenever possible, you should use only calloc(), free(), malloc(),
+  and realloc() for dynamic memory allocation.  All other functions
+  described here are not defined by the ISO standard for the C
+  programming language.
+
+þh2 Tiled memory
+
+  16-bit OS/2 API functions have special requirements for the
+  alignment of objects.  A `tiled' object is an object which meets
+  these requirements.  The þhpt{_tmalloc()} function dynamically
+  allocates a tiled object from the tiled default heap.  The
+  þhpt{_tcalloc()} function allocates a tiled object initialized to
+  zeros.  The þhpt{_trealloc()} function resizes a tiled object -- the
+  object will remain tiled.  The þhpt{_tfree()} function deallocates a
+  tiled object allocated with _tmalloc() or _tcalloc().
+
+þh2 Multiple heaps
+
+  The emx C library maintains a runtime heap, from which malloc()
+  allocates by default and a tiled runtime heap, from which _tmalloc()
+  allocates by default.  (These two runtime heaps happen to be
+  identical in the current implementation, so there's in fact only one
+  runtime heap.)
+
+  However, you can create your own heaps in addition to the runtime
+  heaps.  The interface to multiple heaps is more or less compatible
+  to the one of IBM's Visual Age C++ compiler.  Definitions and
+  declarations for using multiple heaps are in the <umalloc.h> header.
+
+  To create a heap, you have to reserve a memory area for the heap.
+  This memory area can be statically allocated, obtained with
+  þhpt{sbrk()}, obtained with DosAllocMem, or even allocated from
+  another heap.  The þhpt{_ucreate()} function creates a heap in the
+  memory area you provide and returns a pointer to the new heap.
+  Before using the new heap, you have to open the heap by calling
+  þhpt{_uopen()}.
+
+  To allocate from a specific heap, call þhpt{_umalloc()} instead of
+  malloc(), passing a pointer to the heap as first argument.
+  þhpt{_ucalloc()} allocates a zero-initialized block from the hea
+  pointed to by the first argument.
+
+  You can use realloc() to resize a block of any heap -- realloc()
+  automatically determines from which heap the block has been
+  allocated and will keep the block in that heap.  You can use free()
+  to deallocate a block from any heap -- free() automatically
+  determines from which heap the block has been allocated.
+
+  If you no longer need a heap, you can close it with þhpt{_uclose()}
+  and then destroy it with þhpt{_udestroy()}.  You are responsible for
+  deallocating the memory area in which the heap was created; if you
+  allocated the memory area with DosAllocMem, deallocate it with
+  DosFreeMem.
+
+  Note that only memory obtained with brk() and sbrk() is dumped into
+  the core file.  Heaps in memory objects allocated with DosAllocMem
+  are not visible when performing post-mortem debugging.
+
+þh2 Tiled heaps
+
+  The þhpt{_utmalloc()} function allocates a tiled object from a heap
+  which is not tiled.  Objects allocated with þhpt{_utmalloc()} can be
+  resized with realloc() and can be dealllocated with free().
+  þhpt{_utcalloc()} allocates a tiled object initialized to zeros.
+  Note that allocating tiled objects from a regular (untiled) heap may
+  increase fragmentation of the heap.
+
+  You can create a tiled heap by passing the _HEAP_TILED flag to
+  _ucreate().  All objects allocated from a tiled heap are tiled
+  objects.  Again, realloc() and free() can be used instead of
+  _trealloc() and _tfree(), respectively.
+
+þh2 Default heaps
+
+  The main thread and each thread created with þhpt{_beginthread()}
+  has its own two pointers to its two default heaps (regular and
+  tiled), that is, different threads can have different default heaps.
+  Do not confuse the default heaps of a thread with the runtime heaps;
+  the runtime heaps are special heaps maintained by the C library.
+  Initially, each thread has the runtime heap as its default heap and
+  the tiled runtime heap as its tiled default heap.  (Note that the
+  two runtime heaps happen to be identical in the current
+  implementation, that is, the two heap pointers of a thread initially
+  point to the same heap, the runtime heap.)
+
+  For each thread, you can select a default heap with the
+  þhpt{_udefault()} function which takes a pointer to the heap to be
+  used.  After selecting a default heap for a thread, all malloc()
+  calls in that thread will allocate memory from the selected heap.
+  You can switch back to the runtime heap by passing _RUNTIME_HEAP to
+  _udefault(); _RUNTIME_HEAP is a pointer to the runtime heap.
+
+  For each thread, you can select a tiled default heap with the
+  þhpt{_utdefault()} function which takes a pointer to the heap to be
+  used.  After selecting a tiled default heap for a thread, all
+  _tmalloc() calls in that thread will allocate memory from the
+  selected heap.
+
+  If a tiled heap is selected as default heap with _udefault(),
+  malloc() always allocates tiled objects.
+
+þh2 Shared heaps
+
+  Heaps created with _ucreate() can be shared between processes.  To
+  create a shared heap, allocate shared memory with DosAllocSharedMem
+  and pass the _HEAP_SHARED flag to _ucreate().  Each process (except
+  the process which created the shared memory object) which wants to
+  access such a shared heap must first obtain access to the shared
+  memory allocated with DosAllocSharedMem.  This is done with
+  DosGetNamedSharedMem, DosGetSharedMem, or DosGiveSharedMem.  Then,
+  each process, including the process which created the heap, must
+  obtain access to the heap.  This is done with _uopen().  _udefault()
+  can be used to use a shared heap as default heap.
+
+  If a shared heap is no longer needed by a process, that process
+  should close the heap with _uclose() and relinquish access to the
+  shared memory object with DosFreeMem.  After all processes,
+  including the process which created the heap, have closed the heap
+  with _uclose(), the heap can be destroyed with _udestroy().
+
+þh2 Checking heaps
+
+  Heap corruption is a quite common problem of C programs.  To track
+  down such errors, you can periodically call the þhpt{_heapchk()}
+  function to check the default heap and the tiled default heap of the
+  current thread for consistency.  The þhpt{_uheapchk()} function
+  checks a specific heap.
+
+  Sometimes, programs erroneously depend on the contents of
+  dynamically allocated blocks.  To debug these problems, you can call
+  þhpt{_heapset()} to fill all bytes of all free blocks of the default
+  heap and the tiled default heap with a certain value.
+  þhpt{_uheapset()} does the same thing for a specific heap.
+
+  The þhpt{_heap_walk()} function calls a user-supplied function for
+  each block of the default heap and the tiled default heap, passing
+  the address, size, and status (used or free) of one block per call.
+  This can be used to identify memory leaks.  The þhpt{_uheap_walk()}
+  function does the same thing for a specific heap.
+
+þh2 Other heap-related functions
+
+  The þhpt{_heapmin()} function attempts to minimize the size of the
+  default heap by deallocating memory areas which are not used for any
+  blocks.  The þhpt{_theapmin()} function attempts to minimize the
+  tiled default heap.  The þhpt{_uheapmin()} function attempts to
+  minimize a specific heap.
+
+  You can add memory to a heap by calling the þhpt{_uaddmem()}
+  function.  For instance, the memory area passed to _uaddmem() can be
+  allocated with DosAllocMem.
+
+  The þhpt{_msize()} function returns the size of the block pointed to
+  by its argument.  The þhpt{_mheap()} function returns a pointer to
+  the heap containing the block pointed to by its argument.  For both
+  functions, the pointer must point to a used object of a heap.
+
+  The þhpt{_ustats()} function reports the amount of memory used for a
+  heap, the total number of allocated bytes, the size of the biggest
+  free block, etc.
+
+þh2 Why multiple heaps?
+
+  Using multiple heaps has several advantages:
+
+þitemize
+
+  If you need a lot of objects of the same size, you can reduce
+  fragmentation of memory by creating a separate heap for those
+  objects.  Using separate heaps for untiled and tiled objects also
+  reduces fragmentation.
+
+þitem
+
+  By having different heaps for different threads, access to the heaps
+  does not have to be serialized, making the application more
+  efficient, especially on machines with multiple CPUs.  Moreover, the
+  probability of one thread corrupting another thread's objects is
+  reduced if objects are allocated in different heaps for different
+  threads.
+
+þitem
+
+  You can deallocate all objects of a heap at once, by destroying the
+  heap.  Though this is not good programming practice, you can use
+  this scheme if you can't keep track of all the pointers.
+
+þitem
+
+  You can create heaps shared by multiple processes.
+
+þenditemize
+
+þh2 Non-contiguous heaps
+
+  The malloc() implementation of the emx C library supports
+  non-contiguous memory.  A heap can consist of several non-contiguous
+  segments.
+
+  Currently, there are some restrictions when using a non-contiguous
+  heap.  See sbrk() for details.
+
+
+þh2 Replacing malloc()
+
+  You can replace the emx implementation of malloc() with an alternate
+  implementation of malloc() such as GNU malloc.  This is done by
+  linking with that alternate malloc() library.  Additionally, you
+  have to link with the þtt{tmalloc} library which implements
+  _tmalloc() etc. on top of malloc().  Example:
+
+þexample
+gcc -o program.exe src1.c src2.c -lvideo -ltmalloc gmalloc.a
+þendexample
+
+  If the linker complains about malloc() being multiply defined, you
+  probably forgot to link with the þtt{tmalloc} library.  (There is a
+  hack in the emx C library which tries to provoke this behavior to
+  guard against forgetting to link with the þtt{tmalloc} library.)
+
+  You must not replace the emx implementation of malloc() if you are
+  using a C runtime DLL (emxlibcs.dll, for instance) unless you
+  replace malloc() in that library.  The application and all DLLs
+  (with the exception of stand-alone DLLs) must use the same
+  implementation of malloc().
+
+
+þh1 General terminal interface
+þlabel General terminal interface
+þlabel general terminal interface
+
+  Both the System V and POSIX.1 terminal interfaces are supported by
+  emx.
+
+  Currently, only the keyboard device is supported.  The file
+  descriptor used by the terminal interface must refer to the
+  keyboard.  Moreover, the file descriptor must currently be 0 under
+  DOS.
+
+  Both terminal interfaces are not supported with the system call
+  library sys.lib (þhpt{-Zsys}).
+
+  The main implementation-specific difference between the two
+  interfaces is the usage of the IDEFAULT bit of the c_lflag member of
+  þtt{struct termio} and þtt{struct termios} for diabling the general
+  terminal interface.  The POSIX.1 terminal interface does not use the
+  IDEFAULT bit.
+
+þipfminitoc
+
+þh2 System V terminal interface
+
+  The System V terminal interface uses the TCGETA, TCSETA, TCSETAF,
+  TCSETAW, TCFLSH, TCSBRK, and TCXONC requests of þhpt{ioctl()} for
+  controlling terminals.  The TCGETA, TCSETA, TCSETAF, and TCSETAW
+  requests employ the following structure defined in <sys/termio.h>:
+
+þexample
+struct termio
+{
+  unsigned int  c_iflag;      /* input modes */
+  unsigned int  c_oflag;      /* output modes */
+  unsigned int  c_cflag;      /* control modes */
+  unsigned int  c_lflag;      /* local modes */
+  unsigned int  c_line;       /* unused */
+  unsigned char c_cc[NCC];    /* control characters etc. */
+};
+þendexample
+
+  If c_lflag includes IDEFAULT, the default operating system input
+  method is used (including line editing).  Input is always done line
+  by line.  All other fields of the þtt{termio} structure are ignored
+  in this case.
+
+  If c_lflag does not include IDEFAULT, UNIX-like input processing is
+  performed.
+
+  All bits of c_oflag, c_cflag, and c_line are currently ignored.
+
+
+þh2 POSIX.1 terminal interface
+
+  The POSIX.1 terminal interface uses þhpt{cfgetispeed()},
+  þhpt{cfgetospeed()}, þhpt{cfsetispeed()}, þhpt{cfsetospeed()},
+  þhpt{tcdrain()}, þhpt{tcflow()}, þhpt{tcflush()}, þhpt{tcgetattr()},
+  þhpt{tcsendbreak()}, and þhpt{tcsetattr()}.
+
+  The tcgetattr() and tcsetattr() functions employ the following
+  structure defined in <termios.h>:
+
+þexample
+struct termios
+{
+  tcflag_t c_iflag;           /* input modes */
+  tcflag_t c_oflag;           /* output modes */
+  tcflag_t c_cflag;           /* control modes */
+  tcflag_t c_lflag;           /* local modes */
+  cc_t c_cc[NCCS];            /* control characters etc. */
+  int c_reserved[4];          /* currently unused */
+};
+þendexample
+
+  The POSIX.1 terminal interface is enabled by calling tcsetattr().
+  Before the first invocation of tcsetattr(), the default operating
+  system input method is used (including line editing).
+
+  All bits of c_oflag, and c_cflag are currently ignored.
+
+
+þh2 Terminal parameters
+
+  This description applies to both the System V and the POSIX.1
+  terminal interfaces, unless otherwise indicated.
+
+  The following bits of c_iflag are used by emx in the following
+  sequence:
+
+þdescription
+
+þitem IDELETE
+
+  Backspace key generates DEL character (emx extension)
+
+þitem ISTRIP
+
+  Clear bit 7 of all input characters
+
+þitem INLCR
+
+  Translate linefeed into carriage return
+
+þitem IGNCR
+
+  Ignore carriage return
+
+þitem ICRNL
+
+  Translate carriage return into linefeed
+
+þitem IUCLC
+
+  Convert upper case letters (A-Z) into lower case (a-z)
+
+þenddescription
+
+  If IDELETE is set, the two meanings of the backspace key (the one
+  above the Return key) are swapped: Backspace generates DEL and
+  Ctrl-Backspace generates Ctrl-H.  If IDELETE is not set, Backspace
+  generates Ctrl-H and Ctrl-Backspace generates DEL.  The IDELETE bit
+  applies only to the backspace key and does not affect other methods
+  of entering Ctrl-H or DEL.
+
+  The following bits of c_lflag are used by emx:
+
+þdescription
+þitem IDEFAULT
+
+  Disable special processing for the terminal interface (emx
+  extension, this bit is always clear for the POSIX.1 terminal
+  interface).  If this bit is set, the default operating system input
+  method is used (including line editing).  For the System V
+  terminal interface, this bit is initially set
+
+þitem ISIG
+
+  Enable signal processing (see VINTR and VQUIT)
+
+þitem ICANON
+
+  Read input line by line, enable line editing
+
+þitem ECHO
+
+  Echo input
+
+þitem ECHOK
+
+  Echo CR/LF after VKILL
+
+þenddescription
+
+  The c_cc array contains control characters.  If an element of c_cc
+  is set to zero (for the System V terminal interface) or
+  _POSIX_VDISABLE (for the POSIX.1 terminal interface), no character
+  will trigger the action associated with that element.
+
+þdescription
+þitem VINTR
+
+  Generate SIGINT (in thread 1) if ISIG is set in c_iflag
+
+þitem VQUIT
+
+  Generate SIGQUIT (in thread 1) if ISIG is set in c_iflag
+
+þenddescription
+
+  The following characters are used if ICANON is set:
+
+þdescription
+þitem VERASE
+
+  Delete one character to the left (default: Ctrl-H)
+
+þitem VKILL
+
+  Deletes the entire input line (default: Ctrl-U)
+
+þitem VEOF
+
+  Indicates end of file (default: Ctrl-D)
+
+þitem VEOL
+
+  Indicates end of line (default: none)
+
+þitem VSUSP
+
+  Stop process (POSIX.1, ignored by emx)
+
+þitem VSTOP
+
+  Suspend output (POSIX.1, ignored by emx)
+
+þitem VSTART
+
+  Resume output (POSIX.1, ignored by emx)
+
+þenddescription
+
+  The VERASE, VKILL and VEOF characters can be escaped by preceding
+  them with a backslash.  End of file at the beginning of a line is
+  usually interpreted as end of input.
+
+  The following elements are used if ICANON is not set:
+
+þdescription
+þitem VMIN
+
+  Minimum number of characters to be read (default: 6)
+
+þitem VTIME
+
+  Time-Out in 0.1 seconds (default: 1)
+
+þenddescription
+
+  Note that VMIN and VTIME are not equal to VEOF and VEOL,
+  respectively.  Unix uses the VEOF field for both VEOF and VMIN, the
+  VEOL field for both VEOL and VTIME.  emx uses separate fields for
+  the four values.
+
+  There are four cases for VMIN and VTIME (that is, þtt{c_cc[VMIN]}
+  and þtt{c_cc[VTIME]}):
+
+þlist
+
+þitem þtt{VMIN = 0, VTIME = 0}
+
+  Return all the characters stored in the input buffer.  If there are
+  no characters in the buffer, read() returns immediately.  read()
+  doesn't wait for input.
+
+þitem þtt{VMIN = 0, VTIME > 0}
+
+  Return after at least one character has been received or after
+  waiting for VTIME * 0.1 seconds, whichever happens first.  In the
+  latter case, read() will return 0.
+
+þitem þtt{VMIN > 0, VTIME = 0}
+
+  Return after at least VMIN characters have been received.
+
+þitem þtt{VMIN > 0, VTIME > 0}
+
+  Return after at least VMIN characters have been received or if no
+  characters have been received for VMIN * 0.1 seconds after receipt
+  of a character (the time-out applies after at least one character
+  has been received and is reset after each character).
+
+þendlist
+
+  In all cases, read() will return as many characters as are available
+  in the input buffer, up to the number of characters requested in the
+  read() call.
+
+  If O_NONBLOCK (alias O_NDELAY) has been set for the file descriptor
+  with þhpt{fcntl()}, read() will always immediately return.  If there
+  is not enough data available with respect to VMIN, read() will
+  immediately return -1 and set errno to EAGAIN.
+
+  If the general terminal interface is enabled, the text/binary mode
+  of the handle is ignored: the conversions are controlled by c_iflag,
+  including CR-to-LF conversion and the end-of-file character.
+
+  If ICANON is not set, function keys are returned as two characters.
+  The first one is a null (þtt{'\0'}) character, the second one is the
+  scan code.  See <sys/kbdscan.h> for scan codes.
+
+
+þh1 Signal processing
+þlabel signal processing
+
+
+  Signals are conditions that may be reported synchronously or
+  asynchronously during program execution.  Each signal is associated
+  with a signal action, which specifies what action to perform when
+  the signal occurs.
+
+þipfminitoc
+
+þh2 Signal actions
+
+  Each signal is associated with one of the following actions:
+
+þdescription
+þitem SIG_DFL
+
+  Default signal action.  The action depends on the signal, see the
+  table below.
+
+þitem SIG_IGN
+
+  Ignore the signal.
+
+þitem signal-catching function
+
+  Upon receipt of the signal, a signal-catching function (also known
+  as signal handler) is called.  The signal number is passed as the
+  only argument to the signal-catching function.  Before the
+  signal-catching funcion is called, the signal is blocked or the
+  signal action is reset to SIG_DFL, depending on the signal
+  processing model.
+
+þenddescription
+
+  The signal action can be changed with the þhpt{signal()} and
+  þhpt{sigaction()} functions.  The signal action for SIGKILL is
+  SIG_DFL and cannot be changed.  Signal actions are private to each
+  thread of multithread programs.
+
+  If a signal which isn't ignored (that is, SIG_DFL or handler
+  installed) occurs while calling read() with the þhpt{general
+  terminal interface} enabled, -1 will be returned by read() and errno
+  will be set to EINTR.  The buffer will flushed.
+
+  For all signals, the initial signal handler is SIG_DFL (unless
+  SIG_IGN is inherited from the parent process), sa_mask is 0, and
+  sa_flags is SA_ACK.  Initially, all signals are not blocked.
+
+  Only certain library functions can be called by a signal-catching
+  function.  All other library functions are considered to be unsafe.
+  Calling an unsafe function in a signal-catching function which
+  interrupted an unsafe function causes undefined behavior.
+
+þc TODO: List of reentrant functions
+
+þc _exit() access() alarm() cfgetispeed() cfgetospeed() cfsetispeed()
+þc cfsetospeed() chdir() chmod() chown() close() creat() dup2() dup()
+þc execle() execve() fcntl() fork() fstat() getegid() geteuid()
+þc getgid() getgroups() getpgrp() getpid() getppid() getuid() kill()
+þc link() lseek() mkdir() mkfifo() open() pathconf() pause() pipe()
+þc read() rename() rmdir() setgid() setpgid() setsid() setuid() sigaction()
+þc sigaddset() sigdelset() sigemptyset() sigfillset() sigismember()
+þc sigpending() sigprocmask() sigsuspend() sleep() stat() sysconf()
+þc tcdrain() tcflow() tcflush() tcgetattr() tcgetpgrp() tcsendbreak()
+þc tcsetattr() tcsetpgrp() time() times() umask() uname() unlink()
+þc utime() wait() waitpid() write()
+
+þh2 Blocking signals
+
+  Signals can be blocked with the þhpt{sigprocmask()} function.  If a
+  signal is generated while it is blocked, it won't be delivered until
+  unblocked, that is, the generated signal will be pending while the
+  signal is blocked.  As soon as the signal is unblocked, the pending
+  signal will be delivered.  At most one signal of each kind can be
+  pending, that is, if a signal is generated twice while it is
+  blocked, it will be delivered only once as soon as it will be
+  unblocked.  However, SIGCHLD will be stay pending until termination
+  status for all terminated child processes has been fetched with
+  wait() or waitpid().  The action taken on delivery is determined by
+  the signal action in effect when the signal is delivered, not when
+  the signal is generated.  If a signal like SIGILL is caused by an
+  exception while it is blocked, the default action will be taken.
+
+
+þh2 Signal processing models
+
+  The following signal processing models are available:
+
+þdescription
+þitem emx
+  On entry to a signal handler, the signal is blocked.  To unblock
+  (acknowledge) the signal,
+þexample
+signal (signo, SIG_ACK);
+þendexample
+  must be called (by the signal handler, usually), otherwise that
+  signal cannot be delivered again.  For compatibility with existing
+  emx programs, this model is the default.
+
+þitem System V
+  On entry to a signal handler, the action for the signal is set to
+  SIG_DFL.  The signal handler has to be reinstalled with sigaction()
+  or signal().  Note that there is a timing window; for instance, the
+  process will be terminated if two SIGINT signals occur in quick
+  succession.
+
+þitem BSD and POSIX.1
+  On entry to a signal handler, the signal is blocked.  It will be
+  unblocked automatically when the signal handler returns.
+þenddescription
+
+  With the system call library sys.lib (þhpt{-Zsys}), only the
+  `emx' signal processing model is available with signal(); however,
+  sigaction() is fully supported.
+
+  When using þhpt{signal()} to install a signal handler, the signal
+  processing model for that signal is by default `emx'.  To use the
+  `System V' model for signal(), link with þtt{sigsysv.o} by using the
+  -Zsysv-signals option of GCC.  To use the `BSD' model for signal(),
+  link with þtt{sigbsd.o} by using the -Zbsd-signals option of GCC.
+  -Zsysv-signals and -Zbsd-signals cannot be used with -Zsys.
+
+  When using þhpt{sigaction()} to install a signal handler, the signal
+  processing model for that signal is `BSD', which conforms to
+  POSIX.1.  The `emx' model can be selected by setting the SA_ACK bit of
+  the sa_flags member of þtt{struct sigaction}.  The `System V' model
+  can be selected by setting the SA_SYSV bit of the sa_flags member of
+  þtt{struct sigaction}.
+
+þh2 Available signals
+
+  The following signals are defined by emx:
+
+þexample
+Signal   ³  SIG_DFL  ³ Standard ³ Description
+ÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+SIGHUP   ³ terminate ³ POSIX.1  ³ Hangup
+SIGINT   ³ terminate ³ C90      ³ Interrupt (Ctrl-C or Ctrl-Break)
+SIGQUIT  ³   core    ³ POSIX.1  ³ Quit
+SIGILL   ³   core    ³ C90      ³ Illegal instruction
+SIGTRAP  ³   core    ³          ³ Single step (debugging)
+SIGABRT  ³   core    ³ C90      ³ abort ()
+SIGEMT   ³   core    ³          ³ EMT instruction
+SIGFPE   ³   core    ³ C90      ³ Floating point exception
+SIGKILL  ³ terminate ³ POSIX.1  ³ Kill process, cannot be caught or ignored
+SIGBUS   ³   core    ³          ³ Bus error
+SIGSEGV  ³   core    ³ C90      ³ Segmentation violation
+SIGSYS   ³   core    ³          ³ Invalid argument to system call
+SIGPIPE  ³ terminate ³ POSIX.1  ³ Broken pipe
+SIGALRM  ³ terminate ³ POSIX.1  ³ Alarm lock
+SIGTERM  ³ terminate ³ C90      ³ Termination, process killed
+SIGUSR1  ³  ignore   ³ POSIX.1  ³ User-defined signal #1
+SIGUSR2  ³  ignore   ³ POSIX.1  ³ User-defined signal #2
+SIGCHLD  ³  ignore   ³ POSIX.1  ³ Death of a child process
+SIGCLD   ³  ignore   ³ SysV     ³ Synonym for SIGCHLD
+SIGBREAK ³ terminate ³          ³ Break (Ctrl-Break)
+SIGWINCH ³  ignore   ³          ³ Window size changed
+þendexample
+
+    The SIG_DFL column gives the default action for the signals, that
+    is, when the signal action is SIG_DFL:
+
+þdescription
+þitem terminate
+
+    Terminate the process with return code 3.
+
+þitem core
+
+    Dump core and terminate the process.  A file whose name is
+    `þtt{core}' will be written in the current working directory.  A
+    `þtt{core}' file contains a memory dump and the values of the
+    registers at the time the signal was delivered.  It can be used
+    for post-mortem debugging.  If LINK386 was used for linking, no
+    core dump file will be written.
+
+þitem ignore
+
+    The signal is ignored, the process will be continued at the place
+    it was interrupted.
+
+þenddescription
+
+þh2 Catching signals
+
+  You can use þhpt{sigaction()} or þhpt{signal()} to set signal
+  handlers for all signals but SIGKILL.
+
+  If a signal handler returns, further processing depends on how the
+  signal was generated.  If the signal was generated by raise() or
+  kill(), processing will continue where it was interrupted.  If the
+  signal was generated by an exception (this applies to signals
+  SIGILL, SIGSEGV, SIGFPE), core will be dumped and the process will
+  be terminated with return code 3.
+
+  If LINK386 was used for linking, no core dump file will be written.
+
+  In the `emx' signal model, the signal handler should call
+
+þexample
+signal (signal_number, SIG_ACK);
+þendexample
+
+  before returning to unblock the signal.  In the `System V' signal
+  model, the signal handler should reinstall itself as soon as
+  possible.  However, for SIGCHLD and SIGCLD, wait() or waitpid() must
+  be called before reinstalling the signal handler.
+
+  In the `BSD' and `POSIX.1' signal models, the signal handler need
+  not unblock the signal as the signal mask which was active before
+  calling the signal handler is reinstalled after the signal handler
+  returns.
+
+  A signal handler usually looks like this in the `emx' signal model:
+
+þexample
+void handler (int signo)
+{
+  /* Do the work here, the signal is blocked */
+  signal (signo, SIG_ACK);
+}
+þendexample
+
+  A signal handler usually looks like this in the `System V' signal
+  model:
+
+þexample
+void handler (int signo)
+{
+  /* Call wait() or waitpid() here for SIGCHLD aka SIGCLD */
+  signal (signo, handler);
+  /* Do other work here (the signal is not blocked!) */
+}
+þendexample
+
+  A signal handler usually looks like this in the `BSD' and `POSIX.1'
+  signal models:
+
+þexample
+void handler (int signo)
+{
+  /* Do the work here, the signal is blocked */
+}
+þendexample
+
+  Do not use floating point math in a signal handler if the signal
+  handler will return to the interrupted code.  File I/O in the signal
+  handler is also dangerous because a file I/O function could have
+  been interrupted by the signal.
+
+  Only one signal of any type may be pending.  However, SIGCHLD will
+  be stay pending until termination status for all terminated child
+  processes has been fetched with wait() or waitpid().
+
+þh2 Signals generated by the system
+
+  The following signals can be generated by the system:
+
+þdescription
+þitem SIGINT
+  Ctrl-C typed by user (or VINTR, see `þhpt{General terminal interface}')
+þitem SIGQUIT
+  VQUIT character entered (see `þhpt{General terminal interface}')
+þitem SIGILL
+  Illegal instruction
+þitem SIGFPE
+  Floating point exception or division by zero
+þitem SIGSEGV
+  Segmentation violation
+þitem SIGPIPE
+  An attempt is made to write to a pipe or named pipe that is not
+  open for reading by any process
+þitem SIGALRM
+  alarm() timer expired
+þitem SIGTERM
+  Process termination request
+þitem SIGCHLD
+  Termination status for a child process is available
+þitem SIGBREAK
+  Ctrl-Break typed by user
+þenddescription
+
+  Note that SIGWINCH is not generated by the system.
+
+  The signals SIGINT, SIGQUIT, SIGALRM, SIGTERM, SIGCHLD and SIGBREAK
+  are generated in the main thread (thread 1).
+
+  The signals SIGILL, SIGFPE and SIGSEGV are generated in the thread
+  which caused the exception. If generated by an exception, these
+  signals are delivered even if blocked and SIG_IGN is treated like
+  SIG_DFL (however, under OS/2, the core dump will be suppressed by
+  SIG_IGN).
+
+þh3 SIGINT and SIGBREAK
+
+  If you want to trap Ctrl-C and Ctrl-Break, register a signal handler
+  for both SIGINT and SIGBREAK.  Note that typing Ctrl-Break generates
+  SIGINT unless termio is used under OS/2 with the IDEFAULT bit reset.
+  With a future release of emx, Ctrl-Break may generate SIGBREAK in
+  all cases.  Under DOS, SIGINT generated by Ctrl-Break is delivered on
+  return from the next system call or on return to protected mode from
+  the next hardware interrupt, whichever comes first; SIGINT generated
+  by Ctrl-C is delivered on return from the next system call which
+  uses a DOS call which checks for Ctrl-C.  Under OS/2, SIGINT is
+  generated and delivered asynchronously.
+
+þh3 SIGFPE
+
+  By default, all floating point exceptions are masked: The
+  coprocessor will perform a default action (replace the result with
+  a NaN, for instance) and continue without generating SIGFPE.  Use
+  þhpt{_control87()} to enable floating point exceptions.  However,
+  SIGFPE is not reliable.  Under DOS, SIGFPE is not supported for
+  machines not compatible enough with the industry standard.
+
+þh3 SIGTERM
+
+  SIGTERM is implemented only under OS/2.  It is sent to a process if
+  the user or another process requests the termination of the process.
+  Continuing the process by calling longjmp() is not a good idea.
+
+þh3 SIGCHLD
+
+  SIGCHLD will be generated again if there is termination status
+  available for a child process on return from the signal handler for
+  SIGCHLD or when unblocking SIGCHLD or when, for the `System V'
+  signal processing model, installing a signal handler for SIGCHLD.
+  That is, the signal handler must call wait() or waitpid() before
+  returning or unblocking the signal to avoid infinite invocation of
+  the signal handler.
+
+  Note that SIGCHLD and SIGCLD are synonyms; both names refer to the
+  same signal.
+
+  In contrast to System V, emx currently treats SIG_DFL and SIG_IGN
+  identically for SIGCHLD, that is, child processes are turned into
+  zombies when they terminate even if the action for SIGCHLD is
+  SIG_IGN.  Moreover, the behavior of wait() and waitpid() is not
+  affected by the action for SIGCHLD.
+
+  With the system call library sys.lib (þhpt{-Zsys}), SIGCHLD is
+  not generated by the system.
+
+þh3 SIGTRAP
+
+  In addition to the signals which can be generated by the system, the
+  SIGTRAP signal can be returned by þhpt{wait()} when using
+  þhpt{ptrace()}.  SIGTRAP is returned after single-stepping one
+  instruction.
+
+þh2 Sending signals to other processes
+
+  Due to OS/2 restrictions, only SIGINT and SIGBREAK can be sent to
+  arbitrary child processes.  A process can send the other signals
+  only to itself, see þhpt{raise()}, or to other emx programs (which
+  use emx.dll under OS/2) being immediate children of the process.
+
+þh2 Inheriting signal handlers
+
+  Programs which use emx.dll or emx.exe inherit the signal actions of
+  the parent process if the parent process also uses emx.dll or
+  emx.exe: Signals set to SIG_IGN in the parent process will be set to
+  SIG_IGN in the child process, signals set to SIG_DFL in the parent
+  process will be set to SIG_DFL in the child process, signals caught
+  in the child process will be set to SIG_DFL in the child process.
+
+  Programs which don't use emx.dll or emx.exe or have not been started
+  by a program which uses emx.dll or emx.exe will have all signal
+  actions set to SIG_DFL initially.
+
+  Processes created by fork() inherit all signal settings (including
+  sa_mask and sa_flags) of their parent process.
+
+
+þh1 Sockets
+
+  emx includes support for sockets of IBM TCP/IP for OS/2 (including
+  the Internet Access Kit of OS/2 3.0).  The headers files are derived
+  from NetBSD and are packaged in þtt{bsddev.zip}.  Some manual pages
+  are packaged in þtt{bsddoc.zip}.
+
+  To use IBM TCP/IP 4.0, you must compile your applications with
+  þtt{-DTCPIPV4}.  Programs which use þtt{<net/if.h>} are compatible
+  either with TCP/IP 4.0 or older versions, not both.
+
+  Use the -lsocket option to link with the socket library.  Note that
+  -lsocket, like all -l option, should be given þem{after} the source
+  files:
+
+þexample
+gcc mymain.c mysub.c -lsocket
+þendexample
+
+  emx tries to provide seamless support for sockets, like Unix systems
+  do.  This approach is quite different from the one taken by IBM's
+  TCP/IP for OS/2 Toolkit.
+
+  Sockets are not supported with the system call library sys.lib
+  (þhpt{-Zsys}).
+
+  The header <sys/so_ioctl.h>, which includes TCP/IP-specific
+  definitions for ioctl(), is included by <sys/ioctl.h> only if a
+  TCP/IP-related header such as <sys/socket.h> has been
+  included before <sys/ioctl.h>.  If you don't want to reorder the
+  þtt{#include} directives, define the symbol þtt{_EMX_TCPIP} before
+  including <sys/ioctl.h>, or include <sys/so_ioctl.h> directly
+  (however, the last alternative is not recommended).
+
+þipfminitoc
+
+þh2 Porting Unix applications
+
+  When porting Unix applications, please note the following
+  restrictions:
+
+þitemize
+þitem
+  Socket handles are not inherited across þhpt{exec*()} and
+  þhpt{spawn*()}.  (Note that a process created by þhpt{fork()}
+  inherits the socket handles of its parent process.)  Inheriting
+  socket handles is planned for a future release of emx.
+
+þitem
+  The size of messages is restricted to 32767 bytes (this is a
+  limitation of IBM TCP/IP for OS/2).
+
+þitem
+  Initially, sockets are in binary mode.  Use þhpt{setmode()} to
+  switch to text mode.  Text mode applies to read() and write(), only.
+  þtt{recv()} and þtt{send()} always use binary mode.
+
+þitem
+  The functions þtt{recvmsg()}, þtt{sendmsg()}, and
+  þtt{socketpair()} are not implemented.
+
+þenditemize
+
+þh2 Porting OS/2 applications
+
+  When porting OS/2 applications written for IBM's TCP/IP for OS/2
+  Toolkit, please note the following differences:
+
+þitemize
+þitem
+  Socket handles and file handles share a common handle space which is
+  managed by emx.dll.  To obtain the internal socket handle (used by
+  IBM TCP/IP for OS/2) associated with a handle, use the
+  þhpt{_getsockhandle()} function.
+
+þitem
+  þtt{sock_init()} is not required and not implemented.
+
+þitem
+  Use þhpt{close()} instead of þtt{soclose()}.
+
+þitem
+  You can use þhpt{read()} and þhpt{write()} on sockets.
+
+þitem
+  The þhpt{select()} function uses BSD semantics (except for the
+  return value) and works for sockets and some other types of file
+  handles.
+
+þitem
+  Use þhpt{errno} instead of þtt{sock_errno()}, and þhpt{perror()}
+  instead of þtt{psock_errno()}.
+
+þitem
+  þhpt{ioctl()} of emx takes three arguments whereas the ioctl()
+  function of the IBM TCP/IP for OS/2 Toolkit takes four arguments.
+
+þitem
+  The functions þtt{recvmsg()}, þtt{sendmsg()}, and
+  þtt{socketpair()} are not implemented.
+
+þenditemize
+
+
+þh1 Floating-point math
+
+  Applications which need to conform to IEEE 754 to obtain the same
+  results across architectures should call þhpt{_control87()} to
+  change the precision to a mantissa size of 53 bits:
+
+þexample
+_control87 (PC_53, MCW_PC);
+þendexample
+
+  The default precision is 64 bits.
+
+  By default, all floating-point exceptions are masked off.  You can
+  use þtt{_control87()} to enable floating-point exceptions.  SIGFPE
+  will be raised if an unmasked floating-point exception occurs.
+
+  Decimal to binary conversions (scanf(), strtod(), ...) and binary to
+  decimal conversions (gcvt(), printf(), ...) by default conform to
+  IEEE 754.  Conversion from decimal to binary does not round
+  correctly if the decimal number has more than DECIMAL_DIG
+  significant digits.  Currently, conversion always rounds to
+  nearest/even, no matter what rounding mode is selected.
+
+  The IEEE 754 conversion routines are slow and big.  To use the
+  faster and smaller, but inaccurate, conversion routines, use the
+  -Zsmall-conv option of GCC.  This saves about 14KB for programs
+  which use binary to decimal conversions, about 11KB for programs
+  which use decimal to binary conversions, and about 15KB for programs
+  which use both.
+
+þh1 Mutex semaphores
+
+  In addition to OS/2's mutex semaphores (HMTX), the emx runtime
+  library offers three types of mutex semaphores: _fmutex semaphores,
+  _rmutex semaphores, and _smutex semaphores.
+
+  A mutex semaphore has two states: available and owned.  At most one
+  thread can own a mutex semaphore.  If a thread request ownership of
+  a mutex semaphore which is already owned, the thread will be
+  suspended until the semaphores becomes available.  When ownership of
+  a mutex semaphore is relinquished, exactly one of the threads
+  waiting for the semaphore will become the new owner and will resume
+  execution.
+
+  For all three types of emx semaphores, ownership of a semaphore is
+  not tied to a thread, that is, it's not a thread which owns the
+  semaphore.  This is in contrast to OS/2's mutex semaphores.
+  Deadlock will occur if ownership of a semaphore is requested twice
+  for the same semaphore by the same thread without relinquishing
+  ownership of the semaphore between the two request.  This fact is
+  important to keep in mind in presence of signals.  Signal handlers
+  must not request semaphores which can be owned by the interrupted
+  code.  You might want to block signals before requesting ownership
+  of an emx semaphore.
+
+þipfminitoc
+
+þh2 _fmutex semaphores
+þlabel _fmutex semaphores
+
+  _fmutex semaphores are fast RAM semaphores which control access to a
+  resource shared by threads or processes.  _fmutex semaphores must be
+  created with þhpt{_fmutex_create()}. The þhpt{_fmutex_request()}
+  function is used to request ownership of an _fmutex semaphore: If
+  the semaphore is available, it will be set to owned and
+  _fmutex_request() will return immediately.  If the semaphore is
+  owned, _fmutex_request() will block while the semaphore is owned.
+  When the semaphore becomes available, one of the threads blocking in
+  _fmutex_request() will unblock and become the owner of the
+  semaphore.  Ownership of an _fmutex semaphore is relinquished with
+  þhpt{_fmutex_release()}.  If another thread blocks in
+  _fmutex_request(), _fmutex_release() will unblock one of the
+  blocking threads.
+
+  þhpt{_fmutex_open()} obtains access to a shared _fmutex semaphore
+  created by another process.  All threads of the process which called
+  _fmutex_create() have access to the semaphore without calling
+  _fmutex_open().  þhpt{_fmutex_close()} closes an _fmutex semaphore.
+  Destroying _fmutex objects without calling _fmutex_close() will
+  cause a semaphore leak.  þhpt{_fmutex_available()} returns the
+  status of an _fmutex semaphore without blocking and without changing
+  the state of the semaphore.
+
+  Unlike _rmutex semaphores, _fmutex semaphores are not inherited by
+  child processes created with fork().  In most cases, _fmutex
+  semaphores cannot be used by programs which use fork().
+
+þh2 _rmutex semaphores
+þlabel _rmutex semaphores
+
+  _rmutex semaphores are fast RAM semaphores like _fmutex semaphores.
+  However, the runtime library keeps track of _rmutex semaphores (the
+  `þtt{r}' is for `registered'); in consequence, _rmutex semaphores
+  are inherited by child processes created with fork().  However, this
+  applies only to non-shared _rmutex semaphores; shared _rmutex
+  semaphores (created with the _FMC_SHARED flag) behave like _fmutex
+  semaphores.  Copying and assigning _rmutex semaphores is not
+  allowed.  An _rmutex object must not go out of scope or be
+  deallocated while the _rmutex semaphore is open; you must close the
+  semaphore before destroying the object!  _rmutex semaphores must be
+  created with þhpt{_rmutex_create()}.
+
+þh2 _smutex semaphores
+þlabel _smutex semaphores
+
+  _smutex semaphores are very simple RAM semaphores which control
+  access to a resource shared by threads or processes.  These
+  semaphores need not be created and destroyed, _smutex objects just
+  have to be initialized to zero.  _smutex semaphores are implemented
+  with looping and DosSleep.  Therefore, they should be used only if a
+  collision is very unlikely, for instance, during initializing.  In
+  all other cases, _fmutex, _rmutex, or HMTX semaphores should be
+  used.
+
+  An _smutex semaphore is available if object of type _smutex is
+  (explicitely or implicitely initialized to) zero.  The
+  þhpt{_smutex_request()} function is used to request ownership of an
+  _smutex semaphore: If the semaphore is available, it will be set to
+  owned and _smutex_request() will return immediately.  If the
+  semaphore is owned, _smutex_request() will not return while the
+  semaphore is owned.  When the semaphore becomes available, one of
+  the threads blocking in _smutex_request() will unblock sooner or
+  later and will become the owner of the semaphore.  Ownership of an
+  _smutex semaphore is relinquished with þhpt{_smutex_release()}.
+  þhpt{_smutex_available()} returns the status of an _smutex semaphore
+  without blocking and without changing the state of the semaphore.
+  An _smutex semaphore can be used by multiple processes if the
+  _smutex object is in shared memory.
+
+
+þh1 Function reference
+þi1 Functions
+
+  The functions are listed almost alphabetically.
+þif text
+  The origin of most of the functions is shown in [brackets] at the
+  end of the first line.  Functions which are not available or are
+  limited with the system call library (-Zsys, sys.lib) are marked
+  * in [brackets].
+þelse
+  Functions which are not available or are limited with the system
+  call library (þhpt{-Zsys}, sys.lib) are marked * in the `Compatibility'
+  section.
+þendif
+
+
+þfunction abort()
+þcompat C90 POSIX.1
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+void abort (void);
+þendprototype
+
+    abort() causes abnormal termination of the process, unless the
+    signal SIGABRT is caught, and not blocked, and the signal handler
+    does not return.  If SIGABRT is blocked, the signal handler won't
+    be called.
+
+    If abort() causes termination of the process, open streams and
+    file handles will be closed prior to termination of the process.
+    The process is terminated by calling þtt{raise (SIGABRT)} with the
+    signal action associated with SIGABRT being set to SIG_DFL.
+
+þreturnvalue
+
+    abort() does not return.
+
+þimplementation
+
+    The default action for SIGABRT is to display the message
+
+þexample
+Abnormal program termination
+þendexample
+
+    and dump core (for post mortem debugging) and terminate the
+    process with return code 3.
+
+þseealso exit() _exit() raise() sigaction() signal()
+
+
+þfunction abs()
+þcompat C90
+þheaders
+#include <stdlib.h>     /* use this */
+#include <math.h>       /* or this */
+þendheaders
+
+þparam N
+þprototype
+int abs (int N);
+þendprototype
+
+    Return the absolute value of N: If N is negative, -þpa{N} is
+    returned.  Otherwise, N is returned.
+
+þreturnvalue
+
+    abs() returns the absolute value of its argument.
+
+þimplementation
+
+    In-line code is generated for this function.
+
+þseealso fabs() labs()
+
+
+þfunction _abspath()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DST SRC SIZE
+þprototype
+int _abspath (char *DST, const char *SRC, int SIZE);
+þendprototype
+
+    Construct an absolute path name for the file name or directory
+    name pointed to by SRC.  The absolute path name is written to the
+    array pointed to by DST.  It is assumed that there are SIZE bytes
+    available at DST, this includes the terminating null character.
+    If there is an error, -1 is returned.  If _abspath() succeeds, 0
+    is returned.  If SIZE is too small, errno is set to ERANGE and -1
+    is returned.  DST can be identical to SRC.  Backslashes are
+    translated into forward slashes.  The absolute path name is not
+    translated to lower case.  If the string pointed to by SRC ends
+    with a slash or backslash, the string pointed to by DST will end
+    with a slash.
+
+    In contrast to _fullpath(), _abspath() works with non-existing
+    paths: it accesses the appropriate drive only for finding out the
+    current working directory if necessary.
+
+    _abspath() properly handles DBCS characters.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso _fnisabs() _fnisrel() _fullpath() _nls_init()
+
+
+þfunction access()
+þcompat UNIX
+þheaders
+#include <io.h>
+þendheaders
+
+þparam NAME MODE
+þprototype
+int access (const char *NAME, int MODE);
+þendprototype
+
+    Check whether MODE access is allowed for the file or directory
+    whose name is in the string pointed to NAME.  If MODE is F_OK (0),
+    access() checks only for existence of the file or directory.  If
+    MODE is W_OK (2), access() checks for write permission.  If MODE
+    is R_OK (4), access() checks for read permission (always granted
+    under DOS and OS/2 if the file exists).  If MODE is þtt{R_OK|W_OK}
+    (6), access() checks for read and write permission.
+
+þreturnvalue
+
+    access() returns 0 if the file or directory is accessible in mode
+    MODE.  Otherwise, access() set errno and returns -1.
+
+þerrors
+
+þdescription
+
+þitem EACCES
+
+    Access to the file or directory is not permitted
+
+þitem ENAMETOOLONG
+
+    The file or directory name is too long
+
+þitem ENOENT
+
+    The file or directory does not exist
+
+þenddescription
+
+þrestrictions
+
+    access() does not work with devices (errno is set to ENOENT).
+    X_OK is ignored.
+
+þseealso open() stat()
+
+
+þfunction alarm()
+þcompat UNIX *
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam SEC
+þprototype
+unsigned alarm (unsigned SEC);
+þendprototype
+
+    Cause SIGALRM to be generated after SEC seconds have expired.
+    alarm() returns immediately after setting the alarm clock.  There
+    is only one alarm clock; when calling alarm() while the alarm
+    clock is running the time will be reset to the new value.  If SEC
+    is zero, the alarm clock will be stopped.
+
+þreturnvalue
+
+    alarm() returns the number of seconds remaining on the alarm clock
+    before setting the new value.
+
+þimplementation
+
+    In a multithread process, there is a single alarm clock which
+    can be set from all the threads.  SIGALRM is always generated and
+    delivered in the main thread (thread 1).
+
+þrestrictions
+
+    alarm() is not available with the system call library sys.lib
+    (þhpt{-Zsys}).
+
+    Under DOS, SIGALRM is not delivered until return from DOS if the
+    timer expired during a DOS call.
+
+þseealso raise() sigaction() signal() sleep() _sleep2()
+
+
+þfunction alloca()
+þheaders
+#include <alloca.h>
+þendheaders
+
+þparam N
+þprototype
+void *alloca (size_t N);
+þendprototype
+
+    Allocate N bytes from the current stack frame.  The memory space
+    allocated by alloca() will be freed on exit from the current
+    function.  Do not pass the pointer returned by alloca() to free().
+
+þreturnvalue
+
+    alloca() returns a pointer to a block of memory in the stack.
+
+þrestrictions
+
+    This note applies only if you need stack probes (þhpt{-mprobe}
+    option of GCC):
+
+    If alloca() with constant argument occurs in the first statement
+    of a function with less than 4096 bytes of local data or if two
+    calls to alloca() with constant arguments occur twice in a row
+    without accessing the memory pointed to by the return value of the
+    first call, you have to change your code to make GCC generate
+    correct stack probes.  This can be done by storing a dummy value
+    to the return value of alloca().  Example:
+
+þexample
+p = alloca (0xf00);
+{char *fix=alloca (0); *fix = 0;}
+q = alloca (0xf00);
+þendexample
+
+þseealso malloc() _tmalloc()
+
+þsamplecode
+void test (void)
+{
+  char local[0xf00], *p;
+
+  {char *fix=alloca (0); *fix = 0;}
+  p = alloca (0xf00);
+  /*...*/
+}
+þendsamplecode
+
+
+þfunction asctime()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þparam T
+þprototype
+char *asctime (const struct tm *T);
+þendprototype
+
+    Convert the time and date in the structure pointed to by T to a
+    string.  A pointer to the string is returned.  There is only one
+    memory location for the ctime() and asctime() results, a call to
+    ctime() or asctime() overwrites the result of a previous calls to
+    ctime() or asctime().  As localtime() is called by ctime(), the
+    memory location shared by localtime(), gmtime(), and mktime() is
+    overwritten.  The string looks like
+
+þexample
+"Sun Mar  2 07:59:18 1992\n"
+þendexample
+
+    with a terminating null character.  All fields have fixed width.
+
+þreturnvalue
+
+    asctime() returns a pointer to a string containing the textual
+    representation of its argument.
+
+þseealso ctime() gmtime() localtime() mktime()
+
+
+þfunction acos() asin() atan() atan2() acosl() asinl() atanl() atan2l()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X Y
+þprototype
+double acos (double X);
+double asin (double X);
+double atan (double X);
+double atan2 (double Y, double X);
+
+long double acosl (long double X);
+long double asinl (long double X);
+long double atanl (long double X);
+long double atan2l (long double Y, long double X);
+þendprototype
+
+    asin(), acos(), and atan() compute the arc sine, arc cosine and
+    arc tangent of X, respectively.  atan2() computes the arctangent
+    of þpa{Y}/þpa{X}, using the signs of Y and X to determine the
+    quadrant.  If X is outside [-1,1], asin() and acos() return a NaN
+    and set errno to EDOM.
+
+    acosl(), asinl(), atanl() and atan2l() use the þtt{long double}
+    format.
+
+þreturnvalue
+
+    acos(), asin(), atan() and atan2() return the arc sine, arc cosine
+    or arc tangent, respectively, of their argument.  These functions
+    return a NaN on error.
+
+þseealso cos() sin() tan()
+
+
+þfunction assert()
+þcompat C90
+þheaders
+#include <assert.h>
+þendheaders
+
+þparam EXP FILE LINE
+þprototype
+void assert (int EXP);
+þendprototype
+
+    If the preprocessor macro NDEBUG is defined at the time <assert.h>
+    is included, assert() does nothing.  Otherwise, if EXP is zero,
+    the message
+
+þtypewriter
+    Assertion failed: þpa{EXP}, file þpa{FILE}, line þpa{LINE}
+þendtypewriter
+
+    is displayed and the program is aborted by calling abort().  EXP,
+    FILE and LINE are replaced with EXP (as text), the source file
+    name and the source line number, respectively.  If EXP is
+    non-zero, nothing is done.
+
+þseealso abort()
+
+
+þfunction atexit()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam FUNC
+þprototype
+int atexit (void (*FUNC)(void));
+þendprototype
+
+    The function FUNC will be called when the process is terminated.
+    The last function installed by calling atexit() will be called
+    first.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þimplementation
+
+    Up to 32 functions can be installed.
+
+þseealso abort() exit() _exit()
+
+
+þfunction atof() atoi() atol() _atofl() _atoll()
+þcompat C90
+þheaders
+#include <stdlib.h>
+#include <math.h>  /* alternate include file for atof() */
+þendheaders
+
+þparam STRING
+þprototype
+double atof (const char *STRING);
+int atoi (const char *STRING);
+long atol (const char *STRING);
+
+long double _atofl (const char *STRING);
+long long _atoll (const char *STRING);
+þendprototype
+
+    Convert the textual, decimal representation of a number in the
+    string pointed to by STRING to a number.  Leading whitespace is
+    ignored.  If the string cannot be converted, 0 (or 0.0) is
+    returned.  The value of errno is not reliable.
+
+    The decimal point character of the current locale is used by
+    atof() and _atofl().
+
+    _atofl() uses the þtt{long double} format and is not an ISO C
+    function.  _atoll() uses the þtt{long long} format and is not an
+    ISO C function.
+
+þreturnvalue
+
+    These functions return their argument as number.  They return 0
+    (or 0.0) on error.
+
+þseealso _ltoa() scanf() setlocale() strtod() strtol()
+
+
+þfunction bcmp()
+þcompat BSD
+þheaders
+#include <strings.h>
+þendheaders
+
+þparam BUFFER1 BUFFER2 N
+þprototype
+int bcmp (const void *BUFFER1, const void *BUFFER2, size_t N);
+þendprototype
+
+    Compare the first N bytes at BUFFER1 to the first N bytes at
+    BUFFER2.  If the two buffers are identical (or if N is zero), 0 is
+    returned.  Otherwise, a non-zero value is returned.
+
+þreturnvalue
+þdescription
+þitem 0
+    the buffers are identical
+þitem non-0
+    the buffers are different
+þenddescription
+
+þseealso memcmp()
+
+
+þfunction bcopy()
+þcompat BSD
+þheaders
+#include <strings.h>
+þendheaders
+
+þparam SRC DST N
+þprototype
+void bcopy (const void *SRC, void *DST, size_t N);
+þendprototype
+
+    Copy memory.  Copy N bytes from SRC to DST.
+
+þimplementation
+
+    The two regions may overlap.
+
+þseealso memcpy() memmove()
+
+
+þfunction _beginthread()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam START ARG STACK STACK_SIZE ARG_LIST
+þprototype
+int _beginthread (void (*START)(void *ARG), void *STACK, unsigned STACK_SIZE,
+                  void *ARG_LIST);
+þendprototype
+
+    Start a thread.  START is the start address (a function).
+    ARG_LIST will be passed in the ARG parameter of the START
+    function.  STACK is ignored, using NULL is recommended.
+    STACK_SIZE is the size of the stack for the new thread.  When the
+    START function returns, the thread is terminated by an automatic
+    call to _endthread().  A thread can also terminate itself by
+    calling _endthread().  If successful, _beginthread() returns the
+    thread ID.  On error, _beginthread() sets errno and returns -1.
+    The stack allocated for the new thread is completely committed,
+    that is, stack probes are not required.
+
+    _beginthread() is preferred over DosCreateThread because it
+    initializes the C library.
+
+þreturnvalue
+
+    _beginthread() returns the thread ID of the new thread.  It
+    returns -1 on error.
+
+þrestrictions
+
+    _beginthread() is available in the multithread libraries only
+    (-Zmt, -Zmts, or -Zmtd).
+
+þhints
+
+     STACK_SIZE should be at least 32768.  Specifying a big stack size
+     doesn't hurt.
+
+þseealso _endthread() _gettid() _threadid _threadstore()
+
+
+þfunction brk()
+þcompat UNIX
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam ADDR
+þprototype
+void *brk (void *ADDR);
+þendprototype
+
+    Change the end address of the data segment to ADDR.  On success,
+    brk() returns 0, cast as pointer.  Otherwise, -1 cast as pointer
+    is returned and errno set to ENOMEM.  Please don't use brk() --
+    use malloc() instead for memory allocation.
+
+    brk() never allocates non-contiguous memory; in consequence,
+    allocation with brk() is limited by the size of the memory object
+    of the heap.  On the other hand, sbrk() may add memory objects to
+    the heap if non-contiguous allocation has been enabled with
+    _uflags().  Setting back the memory limit into a gap produced
+    non-contiguous allocation by sbrk() is not possible.  However,
+    brk() can be used to deallocate memory objects allocated by
+    sbrk().
+
+þreturnvalue
+þlist
+þitem þtt{(void *)0}
+    success
+þitem þtt{(void *)-1}
+    error
+þendlist
+
+þseealso malloc() sbrk() _uflags() ulimit()
+
+
+þfunction bsearch()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam KEY BASE NUM WIDTH COMPARE ELEMENT
+þprototype
+void *bsearch (const void *KEY, const void *BASE, size_t NUM, size_t WIDTH,
+               int (*COMPARE)(const void *KEY, const void *ELEMENT));
+þendprototype
+
+    Perform a binary search on the sorted array BASE to find KEY.  The
+    array has NUM elements of size WIDTH bytes each.  bsearch() calls
+    COMPARE to compare an array element pointed to by ELEMENT with
+    KEY.  COMPARE should return 0 if KEY and ELEMENT are equal; a
+    negative value, if KEY is smaller than ELEMENT; a positive value
+    if KEY is greater than ELEMENT with respect to the sorting order
+    of BASE.  If there are multiple occurrences of KEY in BASE,
+    bsearch() returns a pointer to any one of the entries.  If the
+    array pointed to by BASE is not sorted, bsearch() does not work.
+
+þreturnvalue
+
+    bsearch() returns a pointer to an occurrence of KEY in
+    the array.  If KEY is not found, bsearch() returns NULL.
+
+þseealso qsort()
+
+
+þfunction bzero()
+þcompat BSD
+þheaders
+#include <strings.h>
+þendheaders
+
+þparam BUFFER N
+þprototype
+void bzero (void *BUFFER, size_t N);
+þendprototype
+
+    Set N bytes at BUFFER to 0.
+
+þseealso calloc() memset()
+
+
+þfunction calloc()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam ELEMENTS SIZE
+þprototype
+void *calloc (size_t ELEMENTS, size_t SIZE);
+þendprototype
+
+    Allocate a block of memory big enough for holding ELEMENTS
+    elements of SIZE bytes each.  calloc() fills the block with zeros.
+    If there is an error, calloc() returns NULL.
+
+þimplementation
+
+    calloc() allocates from the default heap of the current thread.
+    If at least one argument is zero, calloc() returns a non-NULL
+    pointer if there's enough space left in the heap for a block of
+    the minimum size.
+
+þreturnvalue
+
+    calloc() returns a pointer to a newly allocated block of memory.
+    On error, calloc() returns NULL.
+
+þseealso free() malloc() _msize() _tcalloc() _ucalloc() _udefault()
+
+
+þfunction cbrt() _cbrtl()
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double cbrt (double X);
+long double _cbrtl (long double X);
+þendprototype
+
+    Compute the cube root of X.  This is done by calling
+    pow() and adjusting the sign.
+
+    _cbrtl() uses the þtt{long double} format and is an þbf{emx}-specific
+    function.
+
+þreturnvalue
+
+    cbrt() returns the cube root of its argument.
+
+þseealso pow() sqrt()
+
+
+þfunction ceil() ceill()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double ceil (double X);
+long double ceill (long double X);
+þendprototype
+
+    Compute the smallest integer that is greater than or equal to X
+    (round up).
+
+    ceill() uses the þtt{long double} format.
+
+þreturnvalue
+
+    ceil() returns as floating-point number the smallest integer that
+    is greater than or equal to X.
+
+þseealso floor() rint() trunc()
+
+
+þfunction cfgetispeed() cfgetospeed()
+þcompat POSIX.1 *
+þheaders
+#include <termios.h>
+þendheaders
+
+þparam PTERMIOS
+þprototype
+speed_t cfgetispeed (const struct termios *ptermios);
+speed_t cfgetospeed (const struct termios *ptermios);
+þendprototype
+
+    cfgetispeed() returns the input bit rate stored in the structure
+    pointed to by PTERMIOS.
+
+    cfgetospeed() returns the output bit rate stored in the structure
+    pointed to by PTERMIOS.
+
+    See `þhpt{General terminal interface}' for details.
+
+þreturnvalue
+
+    cfgetispeed() and cfgetospeed() return a bit rate.  Bit rates are
+    represented by the symbols þtt{B0} through þtt{B38400}.
+
+þrestrictions
+
+    Asynchronous lines are not yet supported.
+
+þseealso cfsetispeed() cfsetospeed() tcgetattr() tcsetattr()
+
+
+þfunction cfsetispeed() cfsetospeed()
+þcompat POSIX.1 *
+þheaders
+#include <termios.h>
+þendheaders
+
+þparam PTERMIOS SPEED
+þprototype
+int cfsetispeed (struct termios *ptermios, speed_t speed);
+int cfsetospeed (struct termios *ptermios, speed_t speed);
+þendprototype
+
+    cfsetispeed() and cfsetospeed() set the input bit rate and output
+    bit rate, respectively, in the structure pointed to by PTERMIOS
+    from the value of SPEED.  Bit rates are represented by the symbols
+    þtt{B0} through þtt{B38400}.
+
+    See `þhpt{General terminal interface}' for details.
+
+þreturnvalue
+
+    cfsetispeed() and cfsetospeed() return 0 if successful.
+    Otherwise, cfsetispeed() and cfsetospeed() set errno and return
+    -1.
+
+þerrors
+þdescription
+þitem EINVAL
+  The bit rate SPEED is not valid.
+þenddescription
+
+þrestrictions
+
+    Asynchronous lines are not yet supported.
+
+þseealso cfgetispeed() cfgetospeed() tcgetattr() tcsetattr()
+
+
+þfunction chdir()
+þcompat UNIX
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME
+þprototype
+int chdir (const char *NAME);
+þendprototype
+
+    Change to directory whose name is in the string pointed to by
+    NAME.  If the name contains a drive letter, the working directory
+    on that drive is changed, but the selected drive does not change.
+
+    chdir() properly handles DBCS characters.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    Under DOS, the current working directory is not a property of a
+    process, it is a system-wide property.  That may change in a future
+    release of emx.  þtt{chdir ("..")} fails if the current working
+    directory is the root directory.
+
+þseealso _chdir2() getcwd() _nls_init()
+
+
+þfunction _chdir2()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME
+þprototype
+int _chdir2 (const char *NAME);
+þendprototype
+
+    Change to the directory whose name is in the string pointed to by
+    NAME.  If the name contains a drive letter, that drive is selected
+    before changing to the directory.  If the name contains a drive
+    letter, the directory can be omitted:
+
+    _chdir2() properly handles DBCS characters.
+
+þexample
+_chdir2 ("c:")
+þendexample
+
+    is equivalent to
+
+þexample
+_chdrive ('C')
+þendexample
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    Under DOS, the current working directory and the default drive is
+    not a property of a process, it's a system-wide property.  That
+    may change in a future release of emx.  þtt{_chdir ("..")} fails
+    if the current working directory is the root directory.
+
+
+þseealso chdir() getcwd() _nls_init()
+
+
+þfunction _chdrive()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DRIVE
+þprototype
+int _chdrive (char DRIVE);
+þendprototype
+
+    Make the disk drive DRIVE the default drive.  DRIVE must be in
+    þtt{'A'} through þtt{'Z'} or in þtt{'a'} through þtt{'z'}.
+
+þreturnvalue
+
+    _chdrive() always returns 0, even if the drive does not exist.
+
+þseealso _chdir2() _getdrive()
+
+
+þfunction chmod()
+þcompat UNIX
+þheaders
+#include <io.h>
+#include <sys/stat.h>
+þendheaders
+
+þparam NAME PMODE
+þprototype
+int chmod (const char *NAME, int PMODE);
+þendprototype
+
+    Change permission settings of the file whose name is in the string
+    pointed to by NAME to PMODE.  There is only one permission bit
+    under OS/2 and DOS, the read-only attribute.  The read-only bit is
+    set if S_IWRITE is not included in PMODE.  Either specify
+    þtt{S_IREAD|S_IWRITE} or þtt{S_IREAD} for PMODE.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    Only the S_IWRITE bit of PMODE is used.
+
+þseealso creat() open() stat() umask()
+
+
+þfunction chsize()
+þcompat PC
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE SIZE
+þprototype
+int chsize (int HANDLE, long SIZE);
+þendprototype
+
+    Change the length of the file associated with HANDLE to SIZE
+    bytes.  The position of the file pointer is undefined after
+    calling this function.  If SIZE is greater than the current length
+    of the file, bytes of zeros are appended.  HANDLE must be open for
+    writing.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso ftruncate() lseek()
+
+
+þfunction _clear87()
+þcompat PC
+þheaders
+#include <float.h>
+þendheaders
+
+þprototype
+unsigned _clear87 (void);
+þendprototype
+
+    Clear the coprocessor status word.
+
+þreturnvalue
+
+    _clear87() returns the previous value of the status word.
+
+þseealso _control87() _fpreset() _status87()
+
+
+þfunction clearerr()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+void clearerr (FILE *STREAM);
+þendprototype
+
+    Clear the error and end-of-file indicators of STREAM.
+
+þseealso ferror() feof()
+
+
+þfunction clock()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þprototype
+clock_t clock (void);
+þendprototype
+
+    clock() returns the amount of processor time (timer ticks) used by
+    the calling process since the process has been started.  There are
+    CLOCKS_PER_SEC timer ticks per second.
+
+þreturnvalue
+
+    clock() returns the number of timer ticks used by the process.
+
+þrestrictions
+
+    clock() returns the time elapsed, not the CPU time.
+
+þseealso time()
+
+
+þfunction close()
+þcompat UNIX
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int close (int HANDLE);
+þendprototype
+
+    Close the file associated with the handle HANDLE.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso dup() open()
+
+
+þfunction _control87()
+þcompat PC
+þheaders
+#include <float.h>
+þendheaders
+
+þparam NEW_CW MASK
+þprototype
+unsigned _control87 (unsigned NEW_CW, unsigned MASK);
+þendprototype
+
+    Set the coprocessor control word.  Bits of the control word set in
+    MASK are replaced with the matching bits of NEW_CW:
+
+þexample
+cw = ((cw & ~mask) | (new_cw & mask));
+þendexample
+
+    If MASK is 0, the control word is not changed.  MASK should be one
+    of the following symbols:
+þdescription
+þitem MCW_EM
+  Exception masks
+þitem MCW_IC
+  Infinity control (ignored by the 387 and later)
+þitem MCW_RC
+  Rounding control
+þitem MCW_PC
+  Precision control
+þenddescription
+  To pass multiple values in NEW_CW, use the þtt{|} operator to
+  combine the symbols described below.
+
+  If MASK includes MCW_EM, any combination of the following symbols,
+  including none (0), can be used in NEW_CW.  If one of these symbol
+  is included, the corresponding exception is masked off, that is, the
+  coprocessor will take a corrective action and continue.  If an
+  exception is not masked off, SIGFPE will be generated by that
+  exception.
+þdescription
+þitem EM_INVALID
+  Invalid operation (corrective action: return a NaN)
+þitem EM_DENORMAL
+  Denormalized operand (corrective action: use
+  gradual underflow)
+þitem EM_ZERODIVIDE
+  Division by zero (corrective action: return infinity)
+þitem EM_OVERFLOW
+  Overflow (corrective action: return infinity)
+þitem EM_UNDERFLOW
+  Underflow (corrective action: return a denormal or zero)
+þitem EM_INEXACT
+  Precision lost (corrective action: ignore)
+þenddescription
+  By default, all floating-point exceptions are masked off.
+
+  If MASK includes MCW_RC, exactly one of the following symbols should
+  be used in NEW_CW:
+þdescription
+þitem RC_NEAR
+  Round to nearest or even (default)
+þitem RC_DOWN
+  Round down toward -infinity
+þitem RC_UP
+  Round up toward infinity
+þitem RC_CHOP
+  Chop by truncating toward zero
+þenddescription
+
+  If MASK includes MCW_PC, exactly one of the following symbols should
+  be used in NEW_CW:
+þdescription
+þitem PC_24
+  24-bit mantissa
+þitem PC_53
+  53-bit mantissa
+þitem PC_64
+  64-bit mantissa (default)
+þenddescription
+  Only addition, subtraction, multiplication, division, and sqrt() are
+  affected by the precision-control bits.  Note that IEEE 754 requires
+  PC_53, which is not the default setting.
+
+þreturnvalue
+
+    _control87() returns the previous value of the control word.
+
+þseealso _clear87() _fpreset()
+
+þsamplecode
+_control87 (PC_53, MCW_PC);     /* Round to 64-bit double */
+þendsamplecode
+
+
+þfunction copysign() copysignf() copysignl()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X Y
+þprototype
+double copysign (double X, double Y);
+float copysignf (float X, float Y);
+long double copysignl (long double X, long double Y);
+þendprototype
+
+    Return a value with the magnitude of X and the sign bit of Y.
+
+þreturnvalue
+
+    copysign() returns a value with the magnitude of X and the sign
+    bit of Y.
+
+
+þseealso fpclassify() nextafter() signbit()
+
+
+þfunction _core()
+þcompat emx *
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int _core (int HANDLE);
+þendprototype
+
+    Write a core dump to the file associated with HANDLE.  HANDLE must
+    be open for writing.  The core dump file can be used later for
+    debugging or for creating another .exe file which includes the
+    data as saved when _core() was called.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    _core() works only in programs linked with ld.  It does not work
+    in programs linked with LINK386.  _core() is not available with
+    the system call library sys.lib (þhpt{-Zsys}).
+
+þseealso close() open() raise() sigaction() signal()
+
+
+þfunction cos() sin() tan() cosl() sinl() tanl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double cos (double X);
+double sin (double X);
+double tan (double X);
+
+long double cosl (long double X);
+long double sinl (long double X);
+long double tanl (long double X);
+þendprototype
+
+    cos(), sin(), and tan() compute the sine, cosine and tangent of X,
+    respectively.
+
+    cosl(), sinl() and tanl() use the þtt{long double} format.
+
+þreturnvalue
+
+    The cos(), sin() and tan() functions return the cosine, sine and
+    tangent, respectively, of their argument.
+
+þimplementation
+
+    If the absolute value of X is greater than or equal to 2^63,
+    sin(), sinl(), tan(), and tanl() return 0.0, cos() and cosl()
+    return 1.0.
+
+þseealso acos() asin() atan()
+
+
+þfunction cosh() sinh() tanh() coshl() sinhl() tanhl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double cosh (double X);
+double sinh (double X);
+double tanh (double X);
+
+long double coshl (long double X);
+long double sinhl (long double X);
+long double tanhl (long double X);
+þendprototype
+
+    cosh(), sinh(), and tanh() compute the hyperbolic cosine,
+    hyperbolic sine and hyperbolic tangent of X, respectively.  On
+    overflow, +INF or -INF is returned and errno set to ERANGE.
+
+    coshl(), sinhl() and tanhl() use the þtt{long double} format.
+
+þreturnvalue
+
+    The cosh(), sinh() and tanh() functions return the hyperbolic
+    cosine, hyperbolic sine and hyperbolic tangent, respectively, of
+    their argument.  These functions return NaN on error.
+
+þseealso exp()
+
+
+þfunction creat()
+þcompat UNIX
+þheaders
+#include <io.h>
+#include <sys/stat.h>
+þendheaders
+
+þparam NAME PMODE
+þprototype
+int creat (const char *NAME, int PMODE);
+þendprototype
+
+    Create a file whose name is in the string pointed to by NAME with
+    permission settings PMODE.  This is equivalent to
+
+þtypewriter
+  open (þpa{name}, O_WRONLY|O_TRUNC|O_CREAT, þpa{pmode})
+þendtypewriter
+
+þreturnvalue
+
+    creat() returns a file handle of the new file.  On error, creat()
+    sets errno and returns -1.
+
+þseealso open()
+
+
+þfunction _crlf()
+þcompat emx
+þheaders
+#include <io.h>
+þendheaders
+
+þparam BUF SIZE NEW_SIZE
+þprototype
+int _crlf (char *BUF, size_t SIZE, size_t *NEW_SIZE);
+þendprototype
+
+    Translate CR/LF pairs to newline characters.  The conversion is
+    done in-place in the array of SIZE characters pointed to by BUF.
+    The new size is stored to *NEW_SIZE.
+
+þreturnvalue
+
+    _crlf() returns 1 if the buffer ends with a CR.  Otherwise,
+    _crlf() returns 0.
+
+þseealso fread() _fsetmode() read() setmode()
+
+
+þfunction _crotl() _crotr()
+þcompat VAC++
+þheaders
+#include <sys/builtin.h>
+þendheaders
+
+þparam VALUE SHIFT
+þprototype
+unsigned char _crotl (unsigned char VALUE, int SHIFT);
+unsigned char _crotr (unsigned char VALUE, int SHIFT);
+þendprototype
+
+    _crotl() returns VALUE (8 bits) rotated left by SHIFT bits.  If
+    SHIFT is 1, bit 6 is returned as bit 7, bit 5 is returned as bit
+    6, and so on, bit 0 is returned as bit 1, and bit 7 is returned as
+    bit 0.
+
+    _crotr() returns VALUE (8 bits) rotated right by SHIFT bits.  If
+    SHIFT is 1, bit 1 is returned as bit 0, bit 2 is returned as bit
+    1, and so on, bit 7 is returned as bit 6, and bit 0 is returned as
+    bit 7.
+
+    SHIFT should be 0 through 7.
+
+    These functions are implemented as inline functions.
+
+þseealso _lrotl() _lrotr() _srotl() _srotr()
+
+
+þfunction _CRT_init() _CRT_term()
+þcompat OS/2
+
+þprototype
+int _CRT_init (void);
+void _CRT_term (void);
+þendprototype
+
+    These two functions are provided for being called from
+    _DLL_InitTerm(), the DLL initialization and termination function.
+
+    _CRT_init() initializes the C run-time library if it has not yet
+    been initialized.
+
+    _CRT_term() terminates the C run-time library if it has not yet
+    been terminated.
+
+þreturnvalue
+
+    _CRT_init() returns
+
+þdescription
+þitem 0
+    if successful
+þitem -1
+    on error
+þenddescription
+
+þseealso _DLL_InitTerm() __ctordtorInit() __ctordtorTerm()
+
+þsamplefile /emx/test/testdll1.c
+
+
+þfunction ctime()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þparam T
+þprototype
+char *ctime (const time_t *T);
+þendprototype
+
+    Convert the number of seconds elapsed since 00:00:00 1-Jan-1970
+    Coordinated Universal Time (UTC, GMT) in the variable pointed to
+    by T to a string representing that moment for the local timezone.
+    A pointer to the string is returned.  There is only one memory
+    location for the ctime() and asctime() results, a call to ctime()
+    or asctime() overwrites the result of a previous calls to ctime()
+    or asctime().  As localtime() is called by ctime(), the memory
+    location shared by localtime(), gmtime(), and mktime() is
+    overwritten.  The string looks like
+
+þexample
+"Sun Mar  2 07:59:18 1992\n"
+þendexample
+
+    with a terminating null character.  All fields have fixed width.
+
+þreturnvalue
+
+    ctime() returns a pointer to a string containing the textual
+    representation of its argument.
+
+þseealso asctime() gmtime() localtime() mktime()
+
+
+þfunction __ctordtorInit() __ctordtorTerm()
+þcompat OS/2
+
+þprototype
+void __ctordtorInit (void);
+void __ctordtorTerm (void);
+þendprototype
+
+    These two functions are provided for being called from
+    _DLL_InitTerm(), the DLL initialization and termination function.
+
+    __ctordtorInit() invokes the constructors for the static objects
+    of the DLL.  You should call __ctordtorInit() after calling
+    _CRT_init().
+
+    __ctordtorTerm() invokes the destructors for the static objects of
+    the DLL.  You should call __ctordtorTerm() before calling
+    _CRT_term().
+
+þseealso _CRT_init() _CRT_term() _DLL_InitTerm()
+
+
+þfunction cuserid()
+þcompat UNIX
+þheaders
+#include <stdio.h>              /* prototype and L_cuserid constant */
+#include <unistd.h>             /* prototype */
+þendheaders
+
+
+þparam BUFFER
+þprototype
+char *cuserid (char *BUFFER);
+þendprototype
+
+    Return the login name of the owner of current process.  If BUFFER
+    is NULL, a pointer to a statically allocated buffer is returned.
+    Otherwise, the login name is copied to the array pointed to by
+    BUFFER.  The array must be big enough to hold L_cuserid
+    characters.  If there is an error, NULL is returned.
+
+þimplementation
+
+    The emx implementation of cuserid() takes the login name from the
+    USER environment variable.  If that environment variable is not
+    defined, the login name is þtt{"root"}.
+
+þreturnvalue
+
+    cuserid() returns BUFFER if BUFFER is not a null pointer.
+    cuserid() returns a pointer to a statically allocated buffer if
+    BUFFER is NULL.  cuserid() returns NULL on error.
+
+þseealso getpwent()
+
+
+þfunction __cxchg() __lxchg() __sxchg() 
+þcompat VAC++
+þheaders
+#include <sys/builtin.h>
+þendheaders
+
+þparam P V
+þprototype
+signed char __cxchg (volatile signed char *p, signed char v);
+int         __lxchg (volatile int *p,         int v);
+short       __sxchg (volatile short *p,       short v);
+þendprototype
+
+    These functions atomically store V in the object pointed to by P
+    and return the previous value of that object.  As this operation
+    is done atomically, these functions can be used for implementing
+    semaphores.  In fact, __cxchg() is used for implementing _fmutex
+    and _smutex semaphores.
+
+    These functions are implemented as inline functions.
+
+þreturnvalue
+
+    These functions return the previous value of the object pointed to
+    by P.
+
+þseealso _fmutex_request() _smutex_request()
+
+
+þfunction _defext()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DST EXT
+þprototype
+void _defext (char *DST, const char *EXT);
+þendprototype
+
+    Add the default extension EXT to the file name pointed to by DST.
+    If the file name part of the string pointed to by DST contains an
+    extension (including the empty extension), nothing will be done.
+    Otherwise, a dot and the string pointed to by EXT will be
+    appended.
+
+    _defext() properly handles DBCS characters.
+
+þseealso _getext() _nls_init() _remext() _splitpath()
+
+
+þfunction difftime()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þparam T1 T0
+þprototype
+double difftime (time_t T1, time_t T0);
+þendprototype
+
+    Compute the difference (in seconds) between two time values.
+
+þreturnvalue
+
+    difftime() returns the difference (in seconds) þpa{T1}-þpa{T0}
+    between T0 and T1.
+
+
+þfunction __disable() __enable()
+þcompat VAC++
+þheaders
+#include <sys/builtin.h>
+þendheaders
+
+þprototype
+void __disable (void);
+void __enable (void);
+þendprototype
+
+    __disable() disables interrupts, __enable() enables interrupts.
+    Note that these functions cause an access violation unless dirty
+    tricks are used (see xf86sup.sys).
+
+    These functions are implemented as inline functions.
+
+
+þfunction div() ldiv()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NUM DEN
+þprototype
+div_t div (int NUM, int DEN);
+ldiv_t ldiv (long NUM, long DEN);
+þendprototype
+
+    Perform an integer division, dividing NUM by DEN.  The quotient
+    and the remainder are returned in the quot and rem fields,
+    respectively.
+
+    The following table shows the signs of quot and rem depending on
+    the signs of NUM and DEN:
+
+þexample
+NUM DEN ³ quot rem
+ÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄ
+ +   +  ³  +    +
+ +   -  ³  -    +
+ -   +  ³  -    -
+ -   -  ³  +    -
+þendexample
+
+    þbf{Note:} Do not use the -fpcc-struct-return option of GCC.
+
+þreturnvalue
+
+    div() and ldiv() return a structure which contains the quotient
+    and the remainder in the quot and rem fields, respectively.
+
+þseealso _lldiv() _uldiv() _ulldiv()
+
+
+þfunction _DLL_InitTerm()
+þcompat OS/2
+
+þparam MOD_HANDLE FLAG
+þprototype
+unsigned long _DLL_InitTerm (unsigned long MOD_HANDLE, unsigned long FLAG);
+þendprototype
+
+    _DLL_InitTerm() is the library initialization and termination
+    function for dynamic link libraries.  It is called by the
+    operating system to initialize the library (if FLAG is zero) or to
+    terminate the library (if FLAG is one).  MOD_HANDLE is the module
+    handle of the dynamic link library.
+
+    For all types of DLLs, the default _DLL_InitTerm() function calls
+    __ctordtorInit() and __ctordtorTerm().  _CRT_init() is called for
+    all types of DLLs except for DLLs without runtime environment
+    (-Zno-rte).  _CRT_term() is called for stand-alone DLLs (-Zso) and
+    for custom C runtime DLLs.
+
+    If you write your own _DLL_InitTerm() to perform additional
+    actions, don't forget to call _CRT_init() -- if required -- to
+    initialize the runtime environment and to call __ctordtorInit()
+    (after calling _CRT_init()) to invoke the static constructors of
+    the DLL.  On termination (FLAG is one), you should call
+    _CRT_term() in DLLs which include a C runtime environment .  To
+    invoke the static destructors of the DLL, call __ctordtorTerm()
+    before calling _CRT_term().
+
+    If the DLL shares the heap with the program (for instance, if both
+    use emxlibcs.dll) and if _DLL_InitTerm() uses the heap (by calling
+    sbrk(), malloc(), etc.), fork() will always fail for that program.
+
+þreturnvalue
+
+    _DLL_InitTerm() should return 1 to indicate success.  On failure,
+    _DLL_InitTerm() should return 0.
+
+þseealso _CRT_init() _CRT_term() __ctordtorInit() __ctordtorTerm() fork()
+
+þsamplecode
+/* This is the default _DLL_InitTerm() function for
+   stand-alone dynamic link libraries. */
+
+int _CRT_init (void);
+void _CRT_term (void);
+void __ctordtorInit (void);
+void __ctordtorTerm (void);
+
+unsigned long _DLL_InitTerm (unsigned long mod_handle,
+                             unsigned long flag)
+{
+  switch (flag)
+    {
+    case 0:
+      if (_CRT_init () != 0)
+        return 0;
+      __ctordtorInit ();
+     return 1;
+    case 1:
+      __ctordtorTerm ();
+      _CRT_term ();
+      return 1;
+    default:
+      return 0;
+    }
+  return 1;
+}
+þendsamplecode
+
+
+þfunction _dt_free()
+þcompat emx
+þheaders
+#include <sys/dirtree.h>
+þendheaders
+
+þparam DT
+þprototype
+void _dt_free (struct _dt_tree *DT);
+þendprototype
+
+    Deallocate the memory allocated by _dt_read() for the directory
+    tree DT.
+
+þseealso _dt_read()
+
+
+þfunction _dt_read()
+þcompat emx
+þheaders
+#include <sys/dirtree.h>
+þendheaders
+
+þparam DIR MASK FLAGS
+þprototype
+struct _dt_tree *_dt_read (const char *DIR, const char *MASK, unsigned FLAGS);
+þendprototype
+
+    Create a directory tree in memory.  The tree consists of a linked
+    list of _dt_node structures.  Subtrees are attached to the
+    þtt{sub} field of _dt_node structures for directories.  Files
+    matching the wildcard in the string pointed to by MASK in the
+    directory whose name is in the string pointed to by DIR are put
+    into the tree.  If FLAGS includes _DT_TREE, all subdirectories of
+    DIR are also scanned for files and directories matching the
+    wildcard.  If _DT_TREE is not included, the subdirectories of the
+    directory are not scanned.  If FLAGS includes _DT_NOCPDIR, the `.'
+    and `..'  entries are omitted.
+
+    _fnlwr() is used to convert file names to lower case on
+    upper-case-only file systems.  _dt_read() properly handles DBCS
+    characters.
+
+þreturnvalue
+
+    If successful, _dt_read() returns a pointer to a _dt_tree
+    structure.  The þtt{tree} field of that structure is the root of
+    the tree.  On error, _dt_read() sets the errno variable and
+    returns NULL.
+
+þseealso _dt_free() _dt_sort() _dt_split() _fnlwr() _fnexplode() _nls_init()
+
+þsamplefile /emx/test/dttest.c
+
+
+þfunction _dt_sort()
+þcompat emx
+þheaders
+#include <sys/dirtree.h>
+þendheaders
+
+þparam DT SPEC
+þprototype
+void _dt_sort (struct _dt_tree *DT, const char *SPEC);
+þendprototype
+
+    Sort the directory tree DT according to the string pointed to by
+    SPEC.  DT is a directory tree created by _dt_read().  SPEC points
+    to a string of characters which is read from left to right.  Each
+    character tells _dt_sort() how to compare two tree nodes.  If the
+    nodes compare equal, the next character is examined.  This is
+    repeated until the two nodes are different according to the
+    sorting criterion indicated by a character of the string pointed
+    to by SPEC or the end of the SPEC string is reached.  If the end
+    of the string pointed to by SPEC is reached, the two nodes are
+    considered equal and the two nodes are put in an arbitrary order.
+    The following characters are defined in the string pointed to by
+    SPEC:
+
+þdescription
+þitem e
+
+    File name extensions are compared, ascending ASCII order
+
+þitem E
+
+    File name extensions are compared, descending ASCII order
+
+þitem f
+
+    Directories are placed before files
+
+þitem F
+
+    Files are placed before directories
+
+þitem n
+
+    File names are compared, ascending ASCII order
+
+þitem N
+
+    File names are compared, descending ASCII order
+
+þitem s
+
+    File size is compared, ascending
+
+þitem S
+
+    File size is compared, descending
+
+þitem t
+
+    Time stamps (last modification) are compared, ascending
+
+þitem T
+
+    Time stamps (last modification) are compared, descending
+
+þenddescription
+
+    All other characters are ignored.  _fncmp() is used for comparing
+    file names.  If _fncmp() returns 0, strcmp() is used in addition.
+    Then, strcmp() can return a non-zero value only if the current
+    code page does not match the code page used for creating the
+    directory entries.
+
+þseealso _dt_read() _fncmp()
+
+
+þfunction _dt_split()
+þcompat emx
+þheaders
+#include <sys/dirtree.h>
+þendheaders
+
+þparam SRC DIR MASK
+þprototype
+int _dt_split (const char *SRC, char *DIR, char *MASK);
+þendprototype
+
+    Split the path name pointed to by SRC into a directory part and a
+    name part for _dt_read().  The directory part is stored to the
+    array pointed to by DIR, the name part is stored to the array
+    pointed to by MASK.  If the string pointed to by SRC is the name
+    of a directory, the array pointed to by MASK is set to þtt{"*.*"}.
+
+    _dt_split() properly handles DBCS characters.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error (errno set)
+þenddescription
+    
+þseealso _dt_read() _nls_init()
+
+
+þfunction dup() dup2()
+þcompat UNIX
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE HANDLE1 HANDLE2
+þprototype
+int dup (int HANDLE);
+int dup2 (int HANDLE1, int HANDLE2);
+þendprototype
+
+    Create a duplicate of the file handle HANDLE or HANDLE1,
+    respectively, that is, another handle that refers to the same file
+    or device or pipe as the handle given.  Both handles share the
+    same file pointer.  dup() chooses the lowest numbered available
+    handle.  dup2() uses HANDLE2 for the new file handle.  If HANDLE2
+    is open when dup2() is called, it will be closed by dup2() unless
+    HANDLE1 is invalid or identical to HANDLE2.
+
+    If HANDLE1 is a valid open file handle and is equal to HANDLE2,
+    dup2() returns HANDLE2 without closing it.
+
+þreturnvalue
+
+    dup() and dup2() return the new file handle (which is HANDLE2 if
+    dup2() succeeds).  They return -1 on error.
+
+þerrors
+þdescription
+þitem EBADF
+    The HANDLE or HANDLE1 argument is not a valid open file descriptor
+    or HANDLE2 is out of range.
+þitem EMFILE
+    No file descriptor is available.
+þenddescription
+
+þrestrictions
+
+    Duplicated file handles should share the file status flags
+    O_APPEND and O_NONBLOCK; however, dup() and dup2() just copy the
+    file status flags, changing the file status flags after
+    duplicating a file handle does not affect the other file handle.
+
+    dup2() currently doesn't work correctly under DOS.
+
+þseealso close() fcntl() open()
+
+
+þfunction _ea_free()
+þcompat emx
+þheaders
+#include <sys/ea.h>
+þendheaders
+
+þparam PTR
+þprototype
+void _ea_free (struct _ea *PTR);
+þendprototype
+
+    Free the memory allocated for the value of an extended attribute
+    stored in the structure pointed to by PTR.  If the þtt{value}
+    field of the structure is non-þtt{NULL}, free() is called for that
+    pointer.  Then, the þtt{value} field is set to NULL.
+
+þseealso _ea_get()
+
+
+þfunction _ea_get()
+þcompat emx
+þheaders
+#include <sys/ea.h>
+þendheaders
+
+þparam DST PATH HANDLE NAME
+þprototype
+int _ea_get (struct _ea *DST, const char *PATH, int HANDLE,
+             const char *NAME);
+þendprototype
+
+    Retrieve the extended attribute whose name is in the string
+    pointed to by NAME of a file or directory.  If PATH is
+    non-þtt{NULL}, an extended attribute of the file or directory
+    whose name is in the string pointed to by PATH is retrieved.
+    Otherwise, an extended attribute of the file referred to by HANDLE
+    is retrieved.  The letter case of NAME is ignored.  The flags, the
+    value and the size of the value of the extended attribute is
+    copied to the structure pointed to by DST.  If the extended
+    attribute does not exist, the þtt{size} member of the structure
+    pointed to by DST is set to 0 and the þtt{value} member of the
+    structure pointed to by DST is set to NULL.  _ea_get() allocates
+    memory for the value of the extended attribute by calling
+    malloc().  The structure declaration is:
+
+þexample
+struct _ea
+{
+  int flags;
+  int size;
+  void *value;
+};
+þendexample
+
+    The þtt{flags} member contains the flags byte of the extended
+    attribute (only bits 0 through 7 of þtt{flags} are used).
+    Currently, OS/2 defines only bit 7: it's set for critical EAs.
+    þtt{size} is the length of the value in bytes.  The þtt{value}
+    member points to the (binary) value of the extended attribute.
+
+    Use _ead_read() to retrieve all the extended attributes of a file
+    or directory.
+
+þreturnvalue
+þdescription
+þitem 0
+    success or EA not found
+þitem -1
+    error
+þenddescription
+
+þseealso _ea_free() _ea_put() _ead_read()
+
+
+þfunction _ea_put()
+þcompat emx
+þheaders
+#include <sys/ea.h>
+þendheaders
+
+þparam SRC PATH HANDLE NAME
+þprototype
+int _ea_put (struct _ea *SRC, const char *PATH, int HANDLE,
+             const char *NAME);
+þendprototype
+
+    Add an extended attribute to a file or directory.  If PATH is
+    non-þtt{NULL}, the extended attribute is added to the file or
+    directory whose name is in the string pointed to by PATH.
+    Otherwise, the extended attribute is added to the file referred to
+    by HANDLE which must be open for writing.  The string pointed to
+    by NAME contains the name of the extended attribute.  The letter
+    case of the name is ignored.  SRC points to an _ea structure which
+    holds the flags, size and value of the extended attribute to be
+    added.  If the þtt{size} member is 0, the extended attribute is
+    removed.  Bits 0 though 7 of þtt{flags} contain the flags byte for
+    the extended attribute.  Currently, OS/2 defines only bit: the
+    critical EA bit.  The þtt{flags} member should be zero unless you
+    exactly know what you are doing.
+
+    Use _ead_write() to replace or update multiple extended attributes
+    at once.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error (errno is set)
+þenddescription
+
+þseealso _ea_get() _ea_remove() _ead_write()
+
+
+þfunction _ea_remove()
+þcompat emx
+þheaders
+#include <sys/ea.h>
+þendheaders
+
+þparam PATH HANDLE NAME
+þprototype
+int _ea_remove (const char *PATH, int HANDLE, const char *NAME);
+þendprototype
+
+    Remove the extended attribute whose name is in the string pointed
+    to by NAME from a file or directory.  If PATH is non-þtt{NULL},
+    the extended attribute is removed from the file or directory whose
+    name is in the string pointed to by PATH.  Otherwise, the extended
+    attribute is removed from the file referred to by HANDLE.  The
+    letter case of the string pointed to by NAME is ignored.  Removing
+    a non-existing extended attribute of an existing file or directory
+    is not an error.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error (errno is set)
+þenddescription
+
+þseealso _ea_put() _ead_write()
+
+
+þfunction _ead_add()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD NAME FLAGS VALUE SIZE
+þprototype
+int _ead_add (_ead EAD, const char *NAME, int FLAGS, const void *VALUE,
+              int SIZE);
+þendprototype
+
+    Add the extended attribute whose name is in the string pointed to
+    by NAME to the extended attributes descriptor EAD.  NAME should
+    point to a null-terminated string.  The value of the extended
+    attribute is set to SIZE bytes of the array pointed to by VALUE.
+    The flags byte of the extended attribute is set to FLAGS.  Only
+    bits 0 through 7 of FLAGS are used.  Currently, OS/2 defines only
+    bit 7 of the flags byte: it's the critical EA bit.  FLAGS should
+    be zero unless you exactly know what you are doing.  If an
+    extended attribute with the name in the string pointed to by NAME
+    already exists in EAD, it is updated with FLAGS, SIZE and the
+    array pointed to by VALUE.  The extended attributes on disk are
+    not affected.  After calling _ead_add(), the pointers returned by
+    previous invocations of _ead_get_fea2list(), _ead_get_name() and
+    _ead_get_value() will be invalid.  As _ead_add() does a
+    case-sensitive search, you should pass an upper-case names in the
+    string pointed to by NAME.  If there are two extended attributes
+    in an extended attributes descriptor whose names differ only in
+    letter case, only one of both will be written to the disk by
+    _ead_write().
+
+þreturnvalue
+
+    _ead_add() returns the index of the new (or updated) extended
+    attribute.  On error, _ead_add() sets errno and returns a negative
+    value.
+
+þseealso _ead_delete() _ead_replace() _ead_write() _nls_strupr()
+
+
+þfunction _ead_clear()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD
+þprototype
+void _ead_clear (_ead EAD);
+þendprototype
+
+    Discard the extended attributes of the extended attributes
+    descriptor EAD.  After calling _ead_clear(), _ead_count() will
+    return 0 for EAD.  The extended attributes on disk are not
+    modified.  After calling _ead_clear(), do not use pointers
+    returned by _ead_get_name(), _ead_get_value() and
+    _ead_get_fea2list() for that descriptor.
+
+
+þseealso _ead_create() _ead_destroy() _ead_read()
+
+
+þfunction _ead_copy()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam DST_EAD SRC_EAD SRC_INDEX
+þprototype
+int _ead_copy (_ead DST_EAD, _ead SRC_EAD, int SRC_INDEX);
+þendprototype
+
+    Copy the extended attribute SRC_INDEX from the extended attributes
+    descriptor SRC_EAD to the extended attributes descriptor DST_EAD.
+    If SRC_INDEX is 0, all extended attributes of SRC_EAD are copied
+    to DST_EAD.  Otherwise, SRC_INDEX must be a number between 1 and
+    the number of extended attributes of SRC_EAD.  _ead_copy() uses
+    _ead_add() to copy the extended attributes.  The extended
+    attributes on disk are not affected.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error (errno is set)
+þenddescription
+
+þseealso _ead_add()
+
+
+þfunction _ead_count()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD
+þprototype
+int _ead_count (_ead EAD);
+þendprototype
+
+    Get the number of extended attributes available from the
+    extended attributes descriptor EAD.
+
+þreturnvalue
+
+    _ead_count() returns the number of extended attributes available
+    from the extended attributes descriptor EAD.
+
+þseealso _ead_create() _ead_get_name() _ead_get_value()
+
+
+þfunction _ead_create()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þprototype
+_ead _ead_create (void)
+þendprototype
+
+    Create an extended attributes descriptor.  Such a descriptor is
+    used for handling the extended attributes of files and
+    directories.  Use _ead_destroy() if you no longer need the
+    descriptor.  To copy all the extended attributes of a file or a
+    directory to an extended attributes descriptor, use _ead_read().
+    Initially, no extended attributes are held by an extended
+    attributes descriptor.
+
+þreturnvalue
+
+    _ead_create() returns a descriptor which can be used by the other
+    functions for handling extended attributes.  On error,
+    _ead_create() sets errno and returns NULL.
+
+þseealso _ead_destroy() _ead_get_name() _ead_get_value() _ead_read()
+
+þsamplefile /emx/samples/eatool.c
+
+
+þfunction _ead_delete()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD INDEX
+þprototype
+int _ead_delete (_ead EAD, int INDEX);
+þendprototype
+
+    Delete the extended attribute INDEX from the extended attributes
+    descriptor EAD.  INDEX must be a number between 1 and the number
+    of extended attributes of EAD.  After calling _ead_delete(), the
+    pointers returned by previous invocations of _ead_get_fea2list(),
+    _ead_get_name() and _ead_get_value() will be invalid.  Moreover,
+    _ead_delete() invalidates index numbers.
+
+þreturnvalue
+
+    _ead_delete() returns 0 if successful.  On error, _ead_delete()
+    sets errno and returns a negative number.
+
+þseealso _ead_add() _ead_find()
+
+
+þfunction _ead_destroy()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD
+þprototype
+void _ead_destroy (_ead EAD);
+þendprototype
+
+    Invalidate the extended attributes descriptor EAD which has been
+    created by _ead_create().  All memory associated with EAD is
+    released.  EAD must not be NULL.  After calling _ead_destroy(),
+    EAD is invalid and can no longer be used.  After calling
+    _ead_destroy(), do not use pointers returned by _ead_get_name(),
+    _ead_get_value() and _ead_get_fea2list() for that descriptor.
+
+þseealso _ead_clear() _ead_create()
+
+
+þfunction _ead_fea2list_size()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD
+þprototype
+int _ead_fea2list_size (_ead EAD);
+þendprototype
+
+    Get the size of the FEA2LIST of the extended attributes
+    descriptor EAD.  If EAD doesn't hold any extended attributes, the
+    size is 0.
+
+þreturnvalue
+
+    _ead_fea2list_size() returns the size of the FEA2LIST of the
+    extended attributes descriptor EAD.  _ead_fea2list_size() returns
+    0 if EAD doesn't hold any extended attributes.
+
+þseealso _ead_get_fea2list()
+
+
+þfunction _ead_fea2list_to_fealist()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam SRC
+þprototype
+void *_ead_fea2list_to_fealist (const void *SRC);
+þendprototype
+
+    Convert the FEA2LIST SRC (OS/2 2.x format) to a FEALIST (OS/2 1.2
+    format).  SRC must not be NULL.  This function allocates memory
+    with malloc() to hold the converted list.  A pointer to the
+    converted list is returned.  If you no longer need the buffer
+    allocated by this function, you should deallocate it with free().
+    SRC is of type PFEA2LIST, the return value is of type PFEALIST.
+    To avoid having to include <os2.h> when including <sys/ead.h>, void
+    pointers are used instead.
+
+þreturnvalue
+
+    _ead_fea2list_to_fealist() returns a pointer to a FEALIST,
+    allocated with malloc().  On error, _ead_fea2list_to_fealist()
+    sets errno and returns NULL.
+
+þseealso _ead_fealist_to_fea2list() _ead_get_fea2list()
+
+
+þfunction _ead_fealist_to_fea2list()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam SRC
+þprototype
+void *_ead_fealist_to_fea2list (const void *SRC);
+þendprototype
+
+    Convert the FEALIST SRC (OS/2 1.2 format) to a FEA2LIST (OS/2 2.x
+    format).  SRC must not be NULL.  This function allocates memory
+    with malloc() to hold the converted list.  A pointer to the
+    converted list is returned.  If you no longer need the buffer
+    allocated by this function, you should deallocate it with free().
+    SRC is of type PFEALIST, the return value is of type PFEA2LIST.
+    To avoid having to include <os2.h> when including <sys/ead.h>, void
+    pointers are used instead.
+
+þreturnvalue
+
+    _ead_fealist_to_fea2list() returns a pointer to a FEA2LIST,
+    allocated with malloc().  On error, _ead_fealist_to_fea2list()
+    sets errno and returns NULL.
+
+þseealso _ead_fea2list_to_fealist()
+
+
+þfunction _ead_find()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD NAME
+þprototype
+int _ead_find (_ead EAD, const char *NAME);
+þendprototype
+
+    Retrieve the index of the extended attribute whose name is in the
+    string pointed to by NAME of the extended attributes descriptor
+    EAD.  NAME should point to a null-terminated string.  If there is
+    no such extended attribute, errno is set to ENOENT and -1 is
+    returned.  Otherwise, a number between 1 and the number of
+    extended attributes of EAD is returned.  Note that OS/2 converts
+    names of extended attributes to upper case when writing them to
+    the disk.  As _ead_find() does a case-sensitive compare,
+    lower-case names are not found.
+
+þreturnvalue
+
+    _ead_find() returns the index of the extended attribute.  If the
+    extended attribute is not found, _ead_find() returns -1.
+
+þseealso _ead_count() _ead_get_name() _ead_get_value() _nls_strupr()
+
+
+þfunction _ead_get_fea2list()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD
+þprototype
+const void *_ead_get_fea2list (_ead EAD);
+þendprototype
+
+    Retrieve a pointer to the FEA2LIST of the extended attributes
+    descriptor EAD.  You should cast the return value to PFEA2LIST.
+    The return type of _ead_get_fea2list() is not PFEA2LIST to be able
+    to include <sys/ead.h> without having to include <os2.h>.  The pointer
+    points to memory allocated by the extended attributes functions --
+    do not use the pointer after calling _ead_add(), _ead_clear(),
+    _ead_copy(), _ead_delete(), _ead_destroy() or _ead_replace() and
+    do not write to the buffer.
+
+þreturnvalue
+
+    _ead_get_fea2list() returns a pointer to the FEA2LIST of the
+    extended attributes descriptor EAD.
+
+þseealso _ead_fea2list_size() _ead_fea2list_to_fealist()
+
+
+þfunction _ead_get_flags()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD INDEX
+þprototype
+int _ead_get_flags (_ead EAD, int INDEX);
+þendprototype
+
+    Get the þtt{flags} byte of the extended attribute INDEX of the
+    extended attributes descriptor EAD.  INDEX must be a number
+    between 1 and the number of extended attributes of EAD.  On error,
+    errno is set and -1 is returned.
+
+þreturnvalue
+
+    _ead_get_flags() returns the þtt{flags} by of an extended
+    attribute.  On error, _ead_get_flags() returns -1.
+
+þseealso _ead_count() _ead_get_value()
+
+
+þfunction _ead_get_name()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD INDEX
+þprototype
+const char *_ead_get_name (_ead EAD, int INDEX);
+þendprototype
+
+    Return a pointer to the name of the extended attribute INDEX of
+    the extended attributes descriptor EAD.  INDEX must be a number
+    between 1 and the number of extended attributes of EAD.  The
+    pointer points to memory allocated by the extended attributes
+    functions -- do not use the pointer after calling _ead_add(),
+    _ead_clear(), _ead_copy(), _ead_delete(), _ead_destroy() or
+    _ead_replace() and do not write to the buffer.  On error, errno is
+    set and NULL is returned.
+
+þreturnvalue
+
+    _ead_get_name() returns a pointer to the name of an extended
+    attribute.  On error, _ead_get_name() returns NULL.
+
+þseealso _ead_count() _ead_name_len()
+
+
+þfunction _ead_get_value()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD INDEX
+þprototype
+const void *_ead_get_value (_ead EAD, int INDEX);
+þendprototype
+
+    Return a pointer to the value of the extended attribute INDEX of
+    the extended attributes descriptor EAD.  INDEX must be a number
+    between 1 and the number of extended attributes of EAD.  The
+    pointer points to memory allocated by the extended attributes
+    functions -- do not use the pointer after calling _ead_add(),
+    _ead_clear(), _ead_copy(), _ead_delete(), _ead_destroy() or
+    _ead_replace() and do not write to the buffer.  On error, errno is
+    set and NULL is returned.
+
+þreturnvalue
+
+    _ead_get_value() returns a pointer to the value of an extended
+    attribute.  On error, _ead_get_value() returns NULL.
+
+þseealso _ead_count() _ead_find() _ead_get_flags() _ead_value_size()
+
+
+þfunction _ead_name_len()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD INDEX
+þprototype
+int _ead_name_len (_ead EAD, int INDEX);
+þendprototype
+
+    Get the length of the name of the extended attribute INDEX of the
+    extended attributes descriptor EAD.  If INDEX is 0, the total
+    length of all the names is returned, not including the terminating
+    null characters.  Otherwise, INDEX must be a number between 1 and
+    the number of extended attributes of EAD; the length of the name
+    of the þpa{INDEX}th extended attribute is returned.  The
+    terminating null character is not included in the length.  On
+    error, errno is set and -1 is returned.
+
+þreturnvalue
+
+    _ead_name_len() returns the length of the name of an extended
+    attribute.  On error, _ead_name_len() returns -1.
+
+þseealso _ead_count() _ead_get_name()
+
+
+þfunction _ead_read()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD PATH HANDLE FLAGS
+þprototype
+int _ead_read (_ead EAD, const char *PATH, int HANDLE, int FLAGS);
+þendprototype
+
+    Copy the extended attributes of a file or directory to the
+    extended attributes descriptor EAD.  The extended attributes held
+    previously by EAD are discarded.  If PATH is not NULL, the
+    extended attributes of file or directory whose name is in the
+    string pointed to by PATH are copied to EAD.  If PATH is NULL, the
+    extended attributes of the file referred to by the file handle
+    HANDLE are copied to EAD.  FLAGS is not yet used and must be 0.
+    _ead_read() calls _ead_clear(), reads all the extended attributes
+    and stores them in memory.  Use _ead_destroy() to deallocate that
+    memory and invalidate EAD.  When using a non-þtt{NULL} PATH,
+    _ead_read() does not lock the file while while reading the
+    extended attributes.  You might want to open a handle in
+    deny-write mode and pass it in HANDLE to avoid problems due to
+    other threads or processes modifying the extended attributes while
+    _ead_read() is reading.  This doesn't work with and isn't required
+    for directories.  _ead_read() can also be used under DOS though no
+    extended attributes will be copied.  Therefore, your program
+    doesn't have to decide whether to use these functions or not.
+
+    Use _ea_get() to retrieve extended attributes one by one.
+
+þreturnvalue
+
+  If successful, _ead_read() returns 0.  On error, _ead_read() sets
+  errno and returns a negative number.
+
+þseealso _ea_get() _ead_create() _ead_destroy() _ead_get_name() _ead_get_value() _ead_write()
+
+þfunction _ead_replace()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD INDEX FLAGS VALUE SIZE
+þprototype
+int _ead_replace (_ead EAD, int INDEX, int FLAGS, const void *VALUE,
+                  int SIZE);
+þendprototype
+
+    Update the extended attribute INDEX of the extended attributes
+    descriptor EAD with FLAGS and SIZE bytes of VALUE.  INDEX must be
+    a number between 1 and the number of extended attributes of EAD.
+    The extended attributes on disk are not affected.  After calling
+    _ead_replace(), the pointers returned by previous invocations of
+    _ead_get_fea2list(), _ead_get_name() and _ead_get_value() will be
+    invalid.
+
+þreturnvalue
+
+    On success, _ead_replace() returns 0.  On error, _ead_replace()
+    sets errno and returns a negative value.
+
+þseealso _ead_add() _ead_write()
+
+
+þfunction _ead_sort()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD
+þprototype
+void _ead_sort (_ead EAD);
+þendprototype
+
+    Sort by name the extended attributes of the extended attributes
+    descriptor EAD.  Sorting is done in memory -- the extended
+    attributes on disk are not affected.  After calling _ead_sort(),
+    index 1 refers to the extended attribute with the lexically
+    smallest name.  strcmp() is used for comparing names.  _ead_sort()
+    sorts the index, not the extended attributes proper.  Therefore,
+    all functions that modify the extended attributes of EAD undo the
+    effect of _ead_sort().
+
+þseealso _ead_create() _ead_get_name() _ead_read()
+
+
+þfunction _ead_use_fea2list()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD SRC
+þprototype
+int _ead_use_fea2list (_ead EAD, const void *SRC);
+þendprototype
+
+    Copy all the extended attributes from the FEA2LIST SRC (OS/2 2.x
+    format) to the extended attributes descriptor EAD.  All extended
+    attributes previously held by EAD are discarded.  The extended
+    attributes on the disk are not affected.
+
+þreturnvalue
+
+    If successful, _ead_use_fea2list() returns 0.  Otherwise,
+    _ead_use_fea2list() sets errno and returns a negative value.
+
+þseealso _ead_write()
+
+
+þfunction _ead_value_size()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD INDEX
+þprototype
+int _ead_value_size (_ead EAD, int INDEX);
+þendprototype
+
+    Get the size of the extended attribute INDEX of the extended
+    attributes descriptor EAD.  If INDEX is 0, the total size of all
+    the values of EAD is returned.  Otherwise, INDEX must be a number
+    between 1 and the number of extended attributes of EAD; the size
+    of the þtt{INDEX}th extended attribute is returned.  On error,
+    errno is set and -1 is returned.
+
+þreturnvalue
+
+    _ead_value_size() returns the length of the value of an extended
+    attribute.  On error, _ead_value_size() returns -1.
+
+þseealso _ead_count() _ead_get_value()
+
+
+þfunction _ead_write()
+þcompat emx
+þheaders
+#include <sys/ead.h>
+þendheaders
+
+þparam EAD PATH HANDLE FLAGS
+þprototype
+int _ead_write (_ead EAD, const char *PATH, int HANDLE, int FLAGS);
+þendprototype
+
+    Write all the extended attributes of the extended attributes
+    descriptor EAD to the file or directory whose name is in the
+    string pointed to by PATH or to the file associated with HANDLE.
+    The extended attributes previously attached to that file or
+    directory are discarded and replaced by the extended attributes of
+    EAD if FLAGS is 0.  This is done by deleting the extended
+    attributes of the file or directory which are not in EAD.  If
+    FLAGS is _EAD_MERGE, the extended attributes of the file or
+    directory which are also present in EAD are replaced by those of
+    EAD.  Extended attributes of EAD which are not attached to the
+    file or directory are added to the extended attributes of the file
+    or directory.  If PATH is non-þtt{NULL}, the extended attributes
+    are written to the file or directory whose name is in the string
+    pointed to by PATH.  If PATH is NULL, the extended attributes are
+    written to the file referred to by the file handle HANDLE.  The
+    extended attributes of EAD are not modified.
+
+    Use _ea_put() to add or update extended attributes one by one.
+
+þreturnvalue
+
+  _ead_write() returns 0 if successful.  On error, _ead_write() sets
+  errno and returns a negative value.  Under DOS, _ead_write() does
+  nothing and always returns 0.
+
+þseealso _ea_put() _ead_clear() _ead_read() _ead_use_fea2list()
+
+
+þfunction _emx_16to32() _emx_32to16()
+þcompat emx
+þheaders
+#include <os2.h>
+þendheaders
+
+þparam PTR
+þprototype
+void *_emx_16to32 (_far16ptr PTR);
+_far16ptr _emx_32to16 (void *PTR);
+þendprototype
+
+    _emx_16to32() converts a 16-bit far pointer (16:16 format) to a
+    32-bit flat pointer.
+
+    _emx_32to16() converts a 32-bit flat pointer to a 16-bit far
+    pointer (16:16 format).
+
+    The type _far16ptr is used for 16-bit far pointers.
+
+þreturnvalue
+
+    _emx_16to32() returns a 32-bit flat pointer.
+    _emx_32to16() returns a 16-bit far pointer.
+
+    
+þfunction _emxload_connect() _emxload_disconnect()
+þcompat emx
+þheaders
+#include <sys/emxload.h>
+þendheaders
+
+þprototype
+int _emxload_connect (void)
+int _emxload_disconnect (void)
+þendprototype
+
+    Call _emxload_connect() to explicitly connect to the emxload
+    server process.  The connection will be kept open until
+    _emxload_disconnect() or _emxload_stop() is called to terminate
+    the connection.  A counter is maintained which is incremented for
+    each successful call to _emxload_connect() and decremented by each
+    successful call to _emxload_disconnect().  The connection is
+    closed when the counter reaches zero.
+
+    If _emxload_connect() has not been called, _emxload_env(),
+    _emxload_prog(), _emxload_this(), _emxload_stop() and
+    _emxload_unload() open and close a temporary connection to the
+    emxload server process.
+
+    The emxload server process is started by _emxload_connect() if the
+    emxload server process is not already running.
+
+þreturnvalue
+þdescription
+þitem 0
+    connection sucessfully established or closed
+þitem -1
+    the emxload server process could not be started
+þenddescription
+
+þrestrictions
+
+    Under DOS, _emxload_connect() and _emxload_disconnect() do nothing
+    and return -1.
+
+þseealso _emxload_disconnect() _emxload_prog() _emxload_stop()
+
+
+þfunction _emxload_env()
+þcompat emx
+þheaders
+#include <sys/emxload.h>
+þendheaders
+
+þparam NAME
+þprototype
+int _emxload_env (const char *NAME)
+þendprototype
+
+    Keep (another copy of) the current program in memory if the
+    environment variable whose name is in the string pointed to by
+    NAME is set and contains a number.  That number specifies the
+    number of minutes the process should be kept in memory.
+
+    The emxload server process is started by _emxload_env() if the
+    environment variable is valid and the emxload server process is
+    not already running.
+
+þreturnvalue
+þdescription
+þitem 0
+    request successfully sent to the emxload server process
+þitem -1
+    error: the environment variable is not set, or does not contain a
+    valid number or the emxload server process could not be started
+þenddescription
+
+þrestrictions
+
+    Under DOS, _emxload_env() does nothing and returns -1.
+
+þseealso _emxload_prog() _emxload_this() _emxload_unload()
+
+
+þfunction _emxload_list_start() _emxload_list_get()
+þcompat emx
+þheaders
+#include <sys/emxload.h>
+þendheaders
+
+þparam BUF BUF_SIZE PSECONDS
+þprototype
+int _emxload_list_start (void);
+int _emxload_list_get (char *BUF, size_t BUF_SIZE, int *PSECONDS);
+þendprototype
+
+    Get a list of all preloaded programs.  To start the list, call
+    _emxload_list_start().  If _emxload_list_start() returns 0, call
+    _emxload_list_get() to receive the names and timeouts of the
+    preloaded programs until _emxload_list_get() returns a non-zero value.
+
+    _emxload_list_get() stores the complete path name of the program
+    to the array pointed to by BUF.  BUF_SIZE is the size of the
+    array, including the trailing null character.  The number of
+    seconds remaining until automatic unloading is stored to the
+    integer pointed to by PSECONDS.  If automatic unloading is
+    disabled for that program, _EMXLOAD_INDEFINITE is stored.
+
+    If you stop calling _emxload_list_get() before information about
+    all the programs has been transferred, you should call
+    _emxload_disconnect() to close the connection.  Calling
+    _emxload_disconnect() is not required if _emxload_list_start()
+    returns a non-zero value or after _emxload_list_get() returns a
+    non-zero value.
+
+    Do not call _emxload_list_get() without prior calling
+    _emxload_list_start().  Do not call _emxload_list_get() if the
+    previous call to _emxload_list_start() or _emxload_list_get()
+    returned a non-zero value.
+
+þreturnvalue
+þdescription
+þitem 0
+    request processed successfully
+þitem -1
+    an error occured
+þitem 1
+    end of the list of programs (_emxload_list_get() only)
+þenddescription
+
+þrestrictions
+
+    Under DOS, _emxload_list_start() and _emxload_list_get() do
+    nothing and return -1.
+
+þseealso _emxload_prog() _emxload_disconnect()
+
+
+þfunction _emxload_prog()
+þcompat emx
+þheaders
+#include <sys/emxload.h>
+þendheaders
+
+þparam NAME SECONDS
+þprototype
+int _emxload_prog (const char *NAME, int SECONDS)
+þendprototype
+
+    Keep a program in memory for SECONDS seconds.  NAME points to a
+    string containing the file name of the program.  If SECONDS is
+    _EMXLOAD_INDEFINITE, the program will not be unloaded
+    automatically.  The default extension of the name is .exe, the
+    PATH environment variable is used for finding the executable file.
+
+    The emxload server process is started by _emxload_prog() if
+    SECONDS and the string pointed to by NAME are valid and the
+    emxload server process is not already running.
+
+þreturnvalue
+þdescription
+þitem 0
+    request successfully sent to the emxload server process
+þitem -1
+    error: the program has not been found or the emxload server process
+    could not be started
+þenddescription
+
+þrestrictions
+
+    Under DOS, _emxload_prog() does nothing and returns -1.
+
+þseealso _emxload_connect() _emxload_env() _emxload_list_start() _emxload_this() _emxload_unload()
+
+
+þfunction _emxload_stop()
+þcompat emx
+þheaders
+#include <sys/emxload.h>
+þendheaders
+
+þparam WAIT_FLAG
+þprototype
+int _emxload_stop (int WAIT_FLAG)
+þendprototype
+
+    Stop the emxload server process.  All preloaded programs will be
+    unloaded.  If WAIT_FLAG is zero, _emxload_stop() returns
+    immediately after sending the request to the server.  If WAIT_FLAG
+    is non-zero, _emxload_stop() waits until the server process no
+    longer exists.
+
+þreturnvalue
+þdescription
+þitem 0
+    emxload server process stopped
+þitem -1
+    the emxload server process was not running or could not be stopped
+þenddescription
+
+þrestrictions
+
+    Under DOS, _emxload_stop() does nothing and returns -1.
+
+þseealso _emxload_connect()
+
+
+þfunction _emxload_this()
+þcompat emx
+þheaders
+#include <sys/emxload.h>
+þendheaders
+
+þparam SECONDS
+þprototype
+int _emxload_this (int SECONDS)
+þendprototype
+
+    Keep (another copy of) the current program in memory for SECONDS
+    seconds.  If SECONDS is _EMXLOAD_INDEFINITE, the program will not
+    be unloaded automatically.
+
+    The emxload server process is started by _emxload_this() if
+    SECONDS is valid and the emxload server process is not already
+    running.
+
+þreturnvalue
+þdescription
+þitem 0
+    request successfully sent to the emxload server process
+þitem -1
+    error: SECONDS is invalid or the emxload server process could
+    not be started
+þenddescription
+
+þrestrictions
+
+    Under DOS, _emxload_this() does nothing and returns -1.
+
+þseealso _emxload_env() _emxload_prog() _emxload_unload()
+
+
+þfunction _emxload_unload()
+þcompat emx
+þheaders
+#include <sys/emxload.h>
+þendheaders
+
+þparam NAME WAIT_FLAG
+þprototype
+int _emxload_unload (const char *NAME, int WAIT_FLAG)
+þendprototype
+
+    Unload a preloaded program.  NAME points to a string containing
+    the file name of the program.  The default extension for the file
+    name is .exe, the PATH environment variable is used for finding
+    the executable file.  If WAIT_FLAG is zero, _emxload_unload()
+    returns immediately after sending the request to the server.  If
+    WAIT_FLAG is non-zero, _emxload_unload() waits until the server
+    process has unloaded the program.
+
+þreturnvalue
+þdescription
+þitem 0
+    request successfully sent to the emxload server process
+þitem -1
+    error: the program has not been found
+þenddescription
+
+þrestrictions
+
+    Under DOS, _emxload_unload() does nothing and returns -1.
+
+þseealso _emxload_prog() _emxload_stop()
+
+
+þfunction _endthread()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+void _endthread (void);
+þendprototype
+
+    A thread that has been created by _beginthread() can call
+    _endthread() to end its execution.  A thread also ends when the
+    function started with _beginthread() returns.  In that case,
+    _endthread() will be called automatically.  Terminating the main
+    thread (thread 1) of a process terminates the process (return
+    value will be 0).  Do not use DosExit to end a thread started by
+    _beginthread().
+
+    _endthread() is available only in the multithread libraries (-Zmt,
+    -Zmts, or -Zmtd).
+
+þseealso _beginthread()
+
+
+þfunction _envargs()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam ARGCP ARGVP NAME
+þprototype
+void _envargs (int *ARGCP, char ***ARGVP, const char *NAME);
+þendprototype
+
+    Take arguments from the environment variable whose name is in the
+    string pointed to by NAME and insert them before the arguments
+    given on the command line.  If you want to get arguments from the
+    environment variable MYPROGOPT, insert
+
+þexample
+_envargs (&argc, &argv, "MYPROGOPT");
+þendexample
+
+    at the beginning of main().  The contents of the environment
+    variable is parsed the same way as the command line, including
+    quoting.  If you call _response() or _wildcard() after _envargs(),
+    the arguments taken from the environment variable are treated like
+    command line arguments, that is, _wildcard() will expand wildcards
+    in the value of the environment variable unless they are quoted.
+
+    If the environment variable is not defined or if there is not
+    enough memory, _envargs() does not modify *ARGCP and *ARGVP.
+
+þseealso getenv() main() _response() _wildcard()
+
+
+þfunction eof()
+þcompat PC
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int eof (int HANDLE);
+þendprototype
+
+    Check whether the current position of HANDLE is at the end of the
+    file or not.
+
+þreturnvalue
+þdescription
+þitem 1
+    at end of file
+þitem 0
+    not at end of file
+þitem -1
+    error
+þenddescription
+
+
+þfunction _errno()
+þcompat emx
+þheaders
+#include <errno.h>
+þendheaders
+
+þprototype
+int *_errno (void);
+þendprototype
+
+    Return the address of the errno value.  In single-thread
+    programs, errno is a variable, in multithread programs, errno
+    is an lvalue that depends on the thread number.  In consequence,
+    you cannot create a library that uses errno and can be used for
+    both single-thread and multithread programs.  To solve this
+    problem, the _errno() function has been provided: it returns a
+    pointer to the errno value in both single-thread and
+    multithread programs.  Use the option
+
+þexample
+-D__ST_MT_ERRNO__
+þendexample
+
+    on the GCC command line to define errno to call _errno().
+    However, using _errno() doesn't remove any other reasons why your
+    library might not be thread-safe.
+
+þseealso errno
+
+
+þfunction exec*() execl() execle() execlp() execlpe() execv() execve() execvp() execvpe()
+þcompat UNIX
+þheaders
+#include <process.h>
+þendheaders
+
+þparam NAME ARG0 ARGV ENVP
+þprototype
+int execl (const char *NAME, const char *ARG0, ...);
+int execle (const char *NAME, const char *ARG0, ...);
+int execlp (const char *NAME, const char *ARG0, ...);
+int execlpe (const char *NAME, const char *ARG0, ...);
+int execv (const char *NAME, char * const ARGV[]);
+int execve (const char *NAME, char * const ARGV[], char * const ENVP[]);
+int execvp (const char *NAME, char * const ARGV[]);
+int execvpe(const char *NAME, char * const ARGV[], char * const ENVP[]);
+þendprototype
+
+    Replace calling process with a new process.  The calling process
+    terminates after starting the new process.  NAME points to a
+    string containing the name of the executable file to run.
+
+    Use execl(), execle(), execlp() or execlpe() for passing a fixed
+    number of arguments.  ARG0 points to a string containing the 0th
+    argument which is the program name, by convention.  Following
+    ARG0, pointers to the argument strings are passed.  After the last
+    argument pointer, a null pointer cast to `þtt{char *}' must be
+    following.  At least ARG0 must be specified.
+
+    Use execv(), execve(), execvp() or execvpe() for passing a
+    variable number of arguments.  ARGV points to an array of pointers
+    to strings.  The first entry is the program name, by convention.
+    The last argument must be followed by a null pointer.
+
+    execl(), execlp(), execv() and execvp() pass the environment of
+    the current process to the new process.  To pass a different
+    environment to the new process, pass a pointer to an array of
+    pointers to strings after the null argument pointer of execle()
+    and execlpe() or pass the pointer in the ENVP argument of execve()
+    and execvpe().  The last pointer to an environment string in the
+    array must be followed by a null pointer.
+
+    If both the old process and the new process use emx.exe or
+    emx.dll, the new process will inherit the signal actions of the
+    old process: Signals set to SIG_IGN in the old process will be set
+    to SIG_IGN in the new process, signals set to SIG_DFL in the old
+    process will be set to SIG_DFL in the new process, signals caught
+    in the old process will be set to SIG_DFL in the new process.
+
+    When the new process ends, the parent process will be notified by
+    SIGCHLD and wait() will return the original process ID.
+
+þreturnvalue
+
+    These functions return -1 if an error occurs.  On success, they do
+    not return.
+
+þrestrictions
+
+    Native DOS programs cannot be run.  The new process gets a new
+    process ID.  Unless the new process is an emx program (using
+    emx.dll or emx.exe), the actions for all signals are reset to
+    SIG_DFL in the new process
+
+þseealso fork() sigaction() signal() spawn*() wait() waitpid()
+
+
+þfunction _execname()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam BUF BUFSIZE
+þprototype
+int _execname (char *BUF, size_t BUFSIZE);
+þendprototype
+
+    Copy the full path name of the executable file for the current
+    process to the array pointed to by BUF.  It is assumed that there
+    are BUFSIZE bytes available at BUF, including the terminating null
+    character.
+
+þreturnvalue
+
+    _execname() returns 0 on success, -1 on error (buffer too small,
+    for instance).
+
+þrestrictions
+
+    _execname() is not yet implemented under DOS.
+
+þseealso main()
+
+
+þfunction exit()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam RET
+þprototype
+void exit (int RET);
+þendprototype
+
+    Flush streams, remove temporary files, call functions set by
+    atexit() and terminate the current process.  The return code RET
+    is passed to the parent process.  If RET is negative or greater
+    than 255, 255 will be used instead to avoid returning 0 (success)
+    for non-zero RET due to truncation to 8 bits.
+
+þseealso abort() atexit() _exit()
+
+
+þfunction _exit()
+þcompat UNIX
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam RET
+þprototype
+void _exit (int RET);
+þendprototype
+
+    Terminate the process without flushing streams, removing temporary
+    files or calling functions set by atexit().  The return code RET
+    is passed to the parent process.  If RET is negative or greater
+    than 255, 255 will be used instead to avoid returning 0 (success)
+    for non-zero RET due to truncation to 8 bits.
+
+þseealso abort() atexit() exit()
+
+
+þfunction exp() expl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double exp (double X);
+long double expl (long double X);
+þendprototype
+
+    exp() computes the exponential function of X.  On overflow, +INF
+    is returned and errno set to ERANGE.
+
+    expl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    exp() returns e^þpa{X}.  On overflow, exp() returns +INF.
+
+
+þseealso log() pow()
+
+
+þfunction _expand()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam MEM NEW_SIZE
+þprototype
+void *_expand (void *MEM, size_t NEW_SIZE);
+þendprototype
+
+    Try to expand the memory block pointed to by MEM to the new size
+    NEW_SIZE.  If the block cannot be expanded, NULL is returned.
+    Otherwise, MEM is returned.  Please do not use this function --
+    use realloc() instead.
+
+þreturnvalue
+
+    _expand() returns MEM if the block could be resized.  Otherwise,
+    _expand() returns NULL.
+
+þseealso realloc()
+
+
+þfunction fabs() fabsl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double fabs (double X);
+long double fabsl (long double X);
+þendprototype
+
+    Return the absolute value of X: If X is negative, -þpa{X} is returned.
+    Otherwise, X is returned.
+
+    fabsl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    fabs() returns the absolute value of its argument.
+
+þseealso abs() labs()
+
+
+þfunction _fassign()
+þcompat emx
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam TARGET SOURCE
+þprototype
+FILE *_fassign (FILE *TARGET, FILE *SOURCE);
+þendprototype
+
+    Replace the stream pointed to by TARGET with the stream pointed to
+    by SOURCE.  After a successful call of _fassign(), the stream
+    pointed to by SOURCE is no longer available and the stream pointed
+    to by TARGET is associated with the file with which the stream
+    pointed to by SOURCE was associated.  _fassign() closes the file
+    previously associated with the stream pointed to by TARGET.
+
+    If TARGET and SOURCE are equal and both point to a stream,
+    _fassign() does nothing.
+
+þreturnvalue
+
+    _fsasign() returns TARGET if successful.  _fassign() returns NULL
+    on error.
+
+þseealso freopen() _mfopen() v_fopen() wm_fopen()
+
+þsamplecode
+#include <stdio.h>
+#include <sys/winmgr.h>
+
+wm_handle wh_stderr;
+
+void init (void)
+{
+  FILE *f;
+
+  /*...*/
+  f = wm_fopen (wh_stderr);
+  _fassign (stderr, f);
+}
+þendsamplecode
+
+
+þfunction fclose()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int fclose (FILE *STREAM);
+þendprototype
+
+    Flush and close the stream STREAM.  STREAM must be open prior to
+    calling fclose().  If the stream buffer was automatically
+    allocated, it will be deallocated.  If the stream was created with
+    tmpfile(), the temporary file will be deleted.
+
+þreturnvalue
+þdescription
+þitem 0
+  success
+þitem EOF
+  error
+þenddescription
+
+þseealso fcloseall() fflush() fopen() tmpfile()
+
+
+þfunction fcloseall()
+þcompat PC
+þheaders
+#include <stdio.h>
+þendheaders
+
+þprototype
+int fcloseall (void);
+þendprototype
+
+    Close all open streams.
+
+þreturnvalue
+
+    fcloseall() returns the number of streams closed.  On error,
+    fcloseall() returns EOF.
+
+þseealso fclose() flushall() fopen()
+
+
+þfunction fcntl()
+þcompat BSD *
+þheaders
+#include <fcntl.h>
+þendheaders
+
+þparam HANDLE REQUEST ARG
+þprototype
+int fcntl (int HANDLE, int REQUEST);
+int fcntl (int HANDLE, int REQUEST, int ARG);
+þendprototype
+
+    File control.  The following REQUEST codes are implemented
+    (partially):
+
+þdescription
+þitem F_DUPFD
+
+    Create a duplicate of the file handle HANDLE, that is, another
+    handle that refers to the same file or device or pipe as HANDLE.
+    Both handles share the same file pointer.  The lowest numbered
+    available file handle greater than or equal to ARG will be used
+    and returned.
+
+þitem F_GETFL
+
+    Return the file flags of the file associated with HANDLE.
+    Currently, only two file flags are supported by fcntl(): O_APPEND
+    and O_NONBLOCK (alias O_NDELAY).
+
+þitem F_SETFL
+
+    Set the file flags of the file associated with HANDLE.  Currently,
+    only two file flags are supported by fcntl(): O_APPEND and
+    O_NONBLOCK (alias O_NDELAY).  O_NONBLOCK has an effect only if
+    HANDLE is 0 and HANDLE refers to the keyboard and the IDEFAULT and
+    ICANON bits are not set.  O_NONBLOCK also works for pipes created
+    by emx programs, for named pipes, and for sockets.  See
+    `þhpt{General terminal interface}' and þhpt{read()}.
+
+þitem F_GETFD
+
+    Return file descriptor flags.  If the return value includes
+    FD_CLOEXEC (close-on-exec flag), HANDLE will not be inherited by
+    child processes created with þhpt{exec*()} and þhpt{spawn*()}.
+
+þitem F_SETFD
+
+    Set file-descriptor flags.  If the flags include FD_CLOEXEC,
+    (close-on-exec flag), HANDLE will not be inherited by child
+    processes created with þhpt{exec*()} and þhpt{spawn*()}.
+
+þenddescription
+
+þreturnvalue
+
+    On error, fcntl() sets errno and returns -1.  Otherwise, fcntl()
+    returns 0 unless a different return value is defined above.
+
+þerrors
+þdescription
+þitem EBADF
+    The HANDLE argument is not a valid open file descriptor.
+þitem EINVAL
+    REQUEST is invalid.
+
+    REQUEST is F_DUPFD and ARG is out of range.
+
+    REQUEST is F_SETFL and ARG is not a combination of supported
+    flags.
+
+þitem EMFILE
+    REQUEST is F_DUPFD and no file descriptor greater than or equal to
+    ARG is available.
+þenddescription
+
+þrestrictions
+
+    O_NONBLOCK is not supported by the system call library sys.lib
+    (þhpt{-Zsys}).
+
+    Duplicated file handles should share the file status flags
+    O_APPEND and O_NONBLOCK; however, F_DUPFD, dup(), and dup2() just
+    copy the file status flags, changing the file status flags after
+    duplicating a file handle does not affect the other file handle.
+
+    F_GETFL should return the access mode but doesn't.
+
+    Under DOS, FD_CLOEXEC is currently ignored for child processes
+    which are DOS programs (vs. emx programs).
+
+þseealso dup() ioctl() open() read()
+
+
+þfunction fdopen()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam HANDLE MODE
+þprototype
+FILE *fdopen (int HANDLE, const char *MODE);
+þendprototype
+
+    Create a stream for the file handle HANDLE.  The flags in the mode
+    string pointed to by MODE should match the mode used for opening
+    the file handle HANDLE.  If þtt{b} or þtt{t} is used in the mode
+    string, the handle will be changed using setmode() to O_BINARY or
+    O_TEXT mode, respectively.  If neither þtt{b} nor þtt{t} is used,
+    the translation mode is not changed.  You should not rely on this
+    behavior: always specify the desired translation mode.
+
+þreturnvalue
+
+    fdopen() returns a new stream.  On error, fdopen() returns NULL.
+
+þseealso fopen() open()
+
+
+þfunction ferror() feof()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int ferror (FILE *STREAM);
+int feof (FILE *STREAM);
+þendprototype
+
+    ferror() checks STREAM for an error condition.  feof() checks
+    STREAM for an end-of-file condition.
+
+þreturnvalue
+
+    ferror() returns a non-zero value if the error indicator of STREAM
+    is set.  Otherwise, ferror() returns zero.  feof() returns a
+    non-zero value if the end-of-file indicator of STREAM is set.
+    Otherwise, feof() returns zero.
+
+þhints
+
+    The end-of-file indicator is not set if the file position
+    indicator reaches the end of the file; rather, it is set when
+    attempting to read past end-of-file.
+
+þseealso clearerr() fgetc() rewind()
+
+
+þfunction fflush()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int fflush (FILE *STREAM);
+þendprototype
+
+    If STREAM is an output stream or an update stream in write mode,
+    write unwritten data of STREAM's buffer to its file.  If STREAM is
+    NULL, fflush() is applied to all open output streams and update
+    streams in write mode.
+
+    If STREAM is an update stream in write mode, the next operation on
+    STREAM may be input or output.
+
+þreturnvalue
+
+    fflush() returns EOF if a write error occurs, otherwise zero.
+
+þimplementation
+
+    If STREAM is an input stream, fflush() discards the buffer
+    contents and undoes any effects of ungetc().  If the stream is
+    connected to a disk file, the buffer will be refilled (no data
+    lost) on the next input operation.  If the stream is connected to
+    a character device, a pipe, or a socket, the buffer contents will
+    be lost.  (Note that this does not clear the type-ahead buffer of
+    the keyboard device!  Only the data which has been read into the
+    buffer will be discarded.)
+
+þhints
+
+    Use fflush() for switching an update stream from write mode to
+    read mode: output may not be directly followed by input --
+    fflush(), fseek(), fsetpos(), or rewind() must be called between
+    output and input.
+
+    Use fflush() to force output (for instance, a prompt) of a
+    buffered stream to a device: you should do
+þexample
+fflush (stdout);
+þendexample
+    before getting input from stdin, in case stdout is connected to a
+    pipe (a stream connected to a pipe is buffered by default).
+
+þseealso fclose() fopen() fseek() ungetc()
+
+
+þfunction ffs()
+þcompat BSD
+þheaders
+#include <strings.h>
+þendheaders
+
+þparam I
+þprototype
+int ffs (int I);
+þendprototype
+
+    Find the first (least significant, right-most) bit in I which is
+    set and return the index of that bit.  The least significant bit
+    is numbered 1, the most significant bit is numbered 32.
+
+þreturnvalue
+
+    ffs() returns the smallest number þpa{N} for which bit þpa{N} is
+    set in I (the least significant bit is numbered 1).  If there are
+    no bits set in I (that is, I is zero), ffs() returns zero.
+
+þseealso __fls()
+
+
+þfunction fgetc()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int fgetc (FILE *STREAM);
+þendprototype
+
+    Read the next character (as þtt{unsigned char} converted to an
+    þtt{int}) from the input stream STREAM and advance the file
+    position indicator of the stream (if defined).  All input from
+    streams takes place as if characters were read by successive calls
+    to fgetc().
+
+    fgetc() is a function, in contrast to getc().
+
+þreturnvalue
+
+    fgetc() returns the next character from the stream.  If the stream
+    is at end-of-file (before fgetc() is called), fgetc() sets the
+    end-of-file indicator of the stream and returns EOF.  If a read
+    error occurs, fgetc() sets the error indicator of the stream and
+    returns EOF.
+
+þhints
+
+    Use feof() and ferror() to distinguish an end-of-file condition
+    from a read error.
+
+    If you assign the return value of fgetc() to a þtt{char} variable,
+    you cannot compare it to EOF.  Use an þtt{int} variable instead.
+
+þseealso feof() ferror() fgetchar() getc() getchar()
+
+
+þfunction fgetchar()
+þcompat PC
+þheaders
+#include <stdio.h>
+þendheaders
+
+þprototype
+int fgetchar (void);
+þendprototype
+
+    fgetchar() is equivalent to þtt{fgetc (stdin)}.
+
+þreturnvalue
+
+    fgetchar() returns the next character from stdin.  If stdin is at
+    end-of-file (before fgetchar() is called), fgetchar() sets the
+    end-of-file indicator of stdin and returns EOF.  If a read error
+    occurs, fgetchar() sets the error indicator of stdin and returns
+    EOF.
+
+þhints
+
+    Use getchar() or þtt{fgetc(stdin)} instead of fgetchar() as
+    fgetchar() is not portable.
+
+þseealso fgetc() getchar()
+
+
+þfunction fgetpos()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM POS
+þprototype
+int fgetpos (FILE *STREAM, fpos_t *POS);
+þendprototype
+
+    Store the current position of the file pointer of the file STREAM
+    in the variable pointed to by POS.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem non-0
+    error
+þenddescription
+
+þrestrictions
+
+    fgetpos() does not work for text-mode streams unless either CR/LF
+    pairs or LF only is used for all lines of the file.  If there are
+    lines terminated with CR/LF and lines terminated with LF,
+    fgetpos() does not work correctly.
+
+þseealso fsetpos() ftell()
+
+
+þfunction fgets()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUFFER N STREAM
+þprototype
+char *fgets (char *BUFFER, int N, FILE *STREAM);
+þendprototype
+
+    Read a string from STREAM to the array pointed to by BUFFER.  Stop
+    after reading þpa{N}-1 characters or after a newline character has
+    been read.  A null character is appended.
+
+þreturnvalue
+
+    fgets() returns BUFFER.  If end of file occurs before any
+    character has been read, the array pointed to by BUFFER will
+    remain unchanged and fgets() will return NULL.  If a read error
+    occurs, fgets() will return NULL.
+
+þseealso gets() scanf()
+
+
+þfunction filelength()
+þcompat PC
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+long filelength (int HANDLE);
+þendprototype
+
+    Get the length of the file HANDLE, in bytes.
+
+þreturnvalue
+
+    filelength() returns the length of the file HANDLE.  If there is
+    an error, filelength() returns -1.
+
+þseealso chsize() ftruncate() lseek()
+
+
+þfunction fileno()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int fileno (FILE *STREAM);
+þendprototype
+
+    Get the file handle associated with STREAM.
+
+þreturnvalue
+
+    fileno() returns the file handle associated with STREAM.
+
+þseealso fdopen()
+
+
+þfunction _filesys()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DRIVE NAME SIZE
+þprototype
+int _filesys (const char *DRIVE, char *NAME, size_t SIZE);
+þendprototype
+
+    Copy the file system type of the disk drive whose name is in the
+    string pointed to by DRIVE to the array pointed to by NAME.  The
+    size of the array is SIZE bytes.  DRIVE must point to a drive
+    letter followed by a colon.  Examples for file system types are:
+    FAT, LAN, HPFS, CDFS, NFS.
+
+þreturnvalue
+
+þdescription
+þitem 0
+    Success.  The file system type has been copied to NAME.
+þitem -1
+    Error.  errno contains the error number.
+þenddescription
+
+þseealso _fnlwr()
+
+þsamplecode
+char drive[3] = "C:";
+char fsys[16];
+
+if (_filesys (drive, fsys, sizeof (fsys)) != 0)
+  perror ("_filesys");
+else
+  printf ("File system: %s\n", fsys);
+þendsamplecode
+
+    Typical output of the example:
+
+þexample
+File system: FAT
+þendexample
+
+
+þfunction flock()
+þcompat UNIX
+þheaders
+#include <fcntl.h>
+þendheaders
+
+þparam HANDLE OPERATION
+þprototype
+int flock (int HANDLE, int OPERATION)
+þendprototype
+
+    Perform file locking.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    flock() is not yet implemented (dummy function).
+
+
+þfunction floor() floorl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double floor (double X);
+long double floorl (long double X);
+þendprototype
+
+    Compute the largest integer that is less than or equal to X (round
+    down).
+
+    floorl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    Return as floating-point number the largest integer that is less
+    than or equal to X.
+
+þseealso ceil() rint() trunc()
+
+
+þfunction __fls()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+þendheaders
+
+þparam I
+þprototype
+int __fls (int I);
+þendprototype
+
+    Find the last (most significant, left-most) bit in I which is
+    set and return the index of that bit.  The most significant bit
+    is numbered 32, the least significant bit is numbered 1.
+
+    This function is implemented as inline function.
+
+þreturnvalue
+
+    __fls() returns the greatest number þpa{N} for which bit þpa{N} is
+    set in I (the least significant bit is numbered 1).  If there are
+    no bits set in I (that is, I is zero), __fls() returns zero.
+
+þseealso ffs()
+
+
+þfunction flushall()
+þcompat PC
+þheaders
+#include <stdio.h>
+þendheaders
+
+þprototype
+int flushall (void);
+þendprototype
+
+    Flush the buffers of all open streams.  Write the buffers of
+    streams open for writing to their files, clear the buffers of
+    streams open for reading.
+
+    Locked streams are ignored; therefore, flushall() can be called in
+    signal handlers.
+
+þreturnvalue
+
+    flushall() returns the number of open streams.
+
+þhints
+
+    If you don't need the return value (that is, the number of open
+    streams) and deadlock on locked streams cannot occur, you should
+    use
+þexample
+fflush (NULL)
+þendexample
+    instead of flushall().
+
+þseealso fflush()
+
+
+þfunction fmod() fmodl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X Y
+þprototype
+double fmod (double X, double Y);
+long double fmodl (long double X, long double Y);
+þendprototype
+
+    Compute remainder of þpa{X}/þpa{Y}.  The return value z is
+    calculated such that X = i * Y + z, where i is an integer, z has
+    the same sign as X and |z| < |þpa{Y}|.  If Y is 0.0, fmod()
+    returns 0.0.
+
+    fmodl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    See above.
+
+
+þfunction _fmutex_available()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+int _fmutex_available (_fmutex *SEM);
+þendprototype
+
+    Check if the _fmutex semaphore pointed to by SEM is available or
+    owned, without changing the state of the semaphore and without
+    blocking.  Return zero if the semaphore is owned, return a
+    non-zero value if the semaphore is available.  Note that
+    _fmutex_available() just returns a snapshot of the state of the
+    semaphore; in presence of other threads or, in case of a shared
+    semaphore, other processes, the state may change at any time, even
+    before _fmutex_available() returns. This function can be used to
+    avoid deadlock.
+
+þreturnvalue
+
+    _fmutex_available() returns a non-zero value if the semaphore is
+    available.  _fmutex_available() returns 0 if the semaphore is
+    owned.  The return value is undefined if the object pointed to by
+    SEM has not been initialized by _fmutex_create().
+
+þseealso _fmutex_close() _fmutex_create() _fmutex_open() _fmutex_release() _fmutex_request() _rmutex_available() _smutex_available()
+
+
+þfunction _fmutex_close() _fmutex_checked_close()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+unsigned _fmutex_close (_fmutex *SEM);
+void _fmutex_checked_close (_fmutex *SEM);
+þendprototype
+
+    Close an _fmutex semaphore.  SEM should point to an _fmutex object
+    initialized by _fmutex_create().  If there have been þpa{N} calls
+    to þhpt{_fmutex_open()} for this semaphore, þpa{N}+1 calls to
+    _fmutex_close() are required to destroy the semaphore, one call
+    for þhpt{_fmutex_create()} and one call per _fmutex_open().  The
+    semaphore can no longer be used after it has been destroyed.
+
+    _fmutex_checked_close() does not return an error code; it calls
+    abort() on failure.
+
+þreturnvalue
+
+    _fmutex_close() returns 0 if successful.  Otherwise,
+    _fmutex_close() returns an OS/2 error code defined in <os2.h> such
+    as ERROR_INVALID_HANDLE.  Under DOS, _fmutex_close() always
+    returns 0.
+
+þseealso abort() atexit() _fmutex_available() _fmutex_create() _fmutex_open() _fmutex_release() _fmutex_request() _rmutex_close()
+
+
+þfunction _fmutex_create() _fmutex_checked_create()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+þendheaders
+
+þparam SEM FLAGS
+þprototype
+unsigned _fmutex_create (_fmutex *SEM, unsigned FLAGS);
+void _fmutex_checked_create (_fmutex *SEM, unsigned FLAGS);
+þendprototype
+
+    Create an _fmutex semaphore.  SEM points to the _fmutex object to
+    be initialized.  The semaphore is local to the process if FLAGS is
+    0.  The semaphore can be shared by multiple processes if FLAGS is
+    _FMC_SHARED.  A shared _fmutex semaphore must be located in shared
+    memory (that is, SEM must point to an object in shared memory).
+
+    _fmutex_checked_create() does not return an error code; it calls
+    abort() on failure.
+
+þreturnvalue
+
+    _fmutex_create() returns 0 if successful.  Otherwise,
+    _fmutex_create() returns an OS/2 error code defined in <os2.h>
+    such as ERROR_TOO_MANY_HANDLES.  Under DOS, _fmutex_create()
+    always returns 0.
+
+þseealso abort() _fmutex_available() _fmutex_close() _fmutex_dummy() _fmutex_open() _fmutex_release() _fmutex_request() _rmutex_create()
+
+
+þfunction _fmutex_dummy()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+void _fmutex_dummy (_fmutex *SEM);
+þendprototype
+
+    Create a dummy _fmutex semaphore.  SEM points to the _fmutex
+    object to be initialized.  Behavior is undefined if ownership of a
+    dummy _fmutex semaphore is requested when the semaphore is owned.
+    _fmutex_close() must not be called on a dummy _fmutex semaphore.
+
+þseealso _fmutex_create() _rmutex_dummy()
+
+
+þfunction _fmutex_open() _fmutex_checked_open()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+unsigned _fmutex_open (_fmutex *SEM);
+void _fmutex_checked_open (_fmutex *SEM);
+þendprototype
+
+    Open an _fmutex semaphore.  SEM should point to an _fmutex object
+    initialized by þhpt{_fmutex_create()}.  _fmutex_open() is used to
+    obtain access to a shared _fmutex semaphore created by another
+    process.  All threads of the process which called _fmutex_create()
+    have access to the semaphore without calling _fmutex_open().  Call
+    þhpt{_fmutex_close()} when you no longer need access to the
+    semaphore.
+
+    _fmutex_checked_open() does not return an error code; it calls
+    abort() on failure.
+
+þreturnvalue
+
+    _fmutex_open() returns 0 if successful.  Otherwise, _fmutex_open()
+    returns an OS/2 error code defined in <os2.h> such as
+    ERROR_INVALID_HANDLE.  Under DOS, _fmutex_open() always returns 0.
+
+þseealso abort() atexit() _fmutex_available() _fmutex_close() _fmutex_create() _fmutex_release() _fmutex_request() _rmutex_open()
+
+
+þfunction _fmutex_release() _fmutex_checked_release()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+unsigned _fmutex_release (_fmutex *SEM);
+void _fmutex_checked_release (_fmutex *SEM);
+þendprototype
+
+    Relinquish ownership of the _fmutex semaphore pointed to by SEM.
+    If another thread blocks in þhpt{_fmutex_request()} for this
+    semaphore, _fmutex_release() will unblock one of the blocking
+    threads.  The semaphore should be owned when _fmutex_release() is
+    called.  Though not strictly necessary, ownership of the semaphore
+    should have been requested by the same thread.
+
+    _fmutex_checked_release() does not return an error code; it calls
+    abort() on failure.  Note that _fmutex_checked_release() is slower
+    than _fmutex_release() because it is not inlined.
+
+þreturnvalue
+
+    _fmutex_release() returns 0 if successful.  Otherwise,
+    _fmutex_release() returns an OS/2 error code defined in <os2.h>
+    such as ERROR_TOO_MANY_HANDLES.
+
+þseealso abort() __cxchg() _fmutex_available() _fmutex_close() _fmutex_create() _fmutex_open() _fmutex_request() _rmutex_release()
+
+
+þfunction _fmutex_request() _fmutex_checked_request()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+þendheaders
+
+þparam SEM FLAGS
+þprototype
+unsigned _fmutex_request (_fmutex *SEM, unsigned FLAGS);
+void _fmutex_checked_request (_fmutex *SEM, unsigned FLAGS);
+þendprototype
+
+    Request ownership of the _fmutex semaphore pointed to by SEM.  If
+    FLAGS is 0, _fmutex_request() returns ERROR_INTERRUPT if
+    interrupted by a signal while blocking.  FLAGS is zero or a set of
+    flags combined with the þtt{|} operator.  If FLAGS includes
+    _FMR_IGNINT, _fmutex_request() does not return if a signal occurs
+    while blocking.  If FLAGS includes _FMR_NOWAIT and the semaphore
+    is owned, _fmutex_request() returns immediately ERROR_MUTEX_OWNED.
+
+    _fmutex_checked_request() does not return an error code; it calls
+    abort() on failure.  Note that _fmutex_checked_request() is slower
+    than _fmutex_request() because it is not inlined.
+
+    If the semaphore is available, it will be set to owned and
+    _fmutex_request() will return immediately.  If the semaphore is
+    owned, _fmutex_request() will block while the semaphore is owned.
+    When þhpt{_fmutex_release()} is called for the semaphore, one of
+    the threads blocking in _fmutex_request() for this semaphore will
+    wake up and gain ownership of the semaphore.
+
+    Note that ownership of an _fmutex semaphore is not tied to a
+    thread, that is, it's not a thread which owns the semaphore.  This
+    is in contrast to OS/2's mutex semaphores (HMTX).  Deadlock will
+    occur if _fmutex_request() is called twice for the same semaphore
+    by the same thread without an intervening call to
+    _fmutex_release().  This fact is important to keep in mind in
+    presence of signals.  Signal handlers must not request semaphores
+    which can be owned by the interrupted code.  You might want to
+    block signals before requesting ownership of an _fmutex semaphore.
+
+þreturnvalue
+
+    _fmutex_request() returns 0 if successful.  Otherwise,
+    _fmutex_request() returns an OS/2 error code defined in <os2.h>
+    such as ERROR_INTERRUPT.
+
+þrestrictions
+
+    Under DOS, _fmutex_request() and _fmutex_checked_request() crash
+    if the semaphore is already owned.
+
+þseealso abort() __cxchg() _fmutex_available() _fmutex_close() _fmutex_create() _fmutex_open() _fmutex_release() _rmutex_request()
+
+
+þfunction _fncmp()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+int _fncmp (const unsigned char *STRING1, const unsigned char *STRING2);
+þendprototype
+
+    _fncmp() compares the two file name strings pointed to by STRING1
+    and STRING2 and returns zero if the two strings are identical
+    after conversion to upper case.  Otherwise, a non-zero value is
+    returned which is negative if the string pointed to by STRING1 is
+    less than the string pointed to by STRING2 and positive if the
+    string pointed to by STRING1 is greater than the string pointed to
+    by STRING2 after conversion to upper case.  Conversion to upper
+    case includes accented characters etc., depending on the current
+    country code and code page, DBCS characters are compared as is.
+
+þreturnvalue
+þdescription
+þitem <0
+   1st string < 2nd string
+þitem =0
+   1st string = 2nd string
+þitem >0
+   1st string > 2nd string
+þenddescription
+
+þseealso _nls_init() _nls_strupr() strcmp()
+
+
+þfunction _fnexplode() _fnexplodefree()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam MASK LIST
+þprototype
+char **_fnexplode (const char *MASK);
+void _fnexplodefree (char **LIST);
+þendprototype
+
+    Wildcard expansion of MASK.  _fnexplode() returns a vector
+    containing pointers to the file name strings.  The list includes
+    directories.  Hidden and system files are omitted.  The end of the
+    list is marked by a NULL pointer.  On error, NULL is returned.
+    MASK not being a wildcard or no files matching MASK is treated as
+    error.  Memory is allocated with malloc().
+
+    _fnlwr() is used to convert file names to lower case on
+    upper-case-only file systems.
+
+    Use _fnexplodefree() to free the memory allocated for a file name
+    list.
+
+þreturnvalue
+
+    _fnexplode() returns a vector containing pointers to file name
+    strings.
+
+þseealso _dt_read() _fnlwr() glob() opendir() _wildcard()
+
+þsamplefile /emx/samples/eatool.c
+
+
+þfunction _fngetdrive()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam SRC
+þprototype
+char _fngetdrive (const char *SRC);
+þendprototype
+
+    Extract the drive name of the path name SRC.
+
+þreturnvalue
+
+    _fngetdrive () return as upper-case letter the drive name in the
+    path name pointed to by SRC.  If the string does not contain a
+    drive name, _fngetdrive() returns 0.
+
+þseealso _fnisabs() _fnisrel() _getdrive()
+
+þsamplecode
+/* this fails if the -r emx option is used */
+
+char *fname, drive;
+
+drive = _fngetdrive (fname);
+if (drive == 0)
+  drive = _getdrive ();
+þendsamplecode
+
+
+þfunction _fnisabs() _fnisrel()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME
+þprototype
+int _fnisabs (const char *NAME);
+int _fnisrel (const char *NAME);
+þendprototype
+
+    _fnisabs() returns a non-zero value if the string pointed to by
+    NAME is an absolute file name.  Otherwise, it returns 0.  Absolute
+    file names start with \ or /, optionally preceded by a drive name.
+    If _fnisabs() returns a non-zero value, the location of the file
+    whose name is in the string pointed to by NAME does not depend on
+    the current working directory (though it may depend on the current
+    drive).
+
+    _fnisrel() returns a non-zero value if the string pointed to by
+    NAME is a relative file name.  Otherwise is returns 0.  Relative
+    file names do not start with \ or / or a drive name.  If
+    _fnisrel() returns a non-zero value, you can prepend a directory
+    to the string pointed to by NAME.
+
+    Note that both _fnisabs() and _fnisrel() return 0 for path names
+    which start with a drive name not followed by \ or /.
+
+þexample
+name                  ³ _fnisabs (name) ³ _fnisrel (name)
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+"\\"                  ³ non-zero        ³ zero
+"/etc/passwd"         ³ non-zero        ³ zero
+"c:\\foo\\bar"        ³ non-zero        ³ zero
+"c:/"                 ³ non-zero        ³ zero
+"foo"                 ³ zero            ³ non-zero
+"foo/bar"             ³ zero            ³ non-zero
+"c:foo"               ³ zero            ³ zero
+"d:"                  ³ zero            ³ zero
+""                    ³ zero            ³ zero
+þendexample
+
+þreturnvalue
+
+    _fnisabs() returns a non-zero value if the string pointed to by
+    NAME is an absolute file name.  Otherwise, _fnisabs() returns 0.
+
+    _fnisrel() returns a non-zero value if the string pointed to by
+    NAME is a relative file name.  Otherwise _fnisrel() returns 0.
+
+þseealso _abspath() _fngetdrive()
+
+
+þfunction _fnlwr() _fnlwr2() _rfnlwr() _sfnlwr()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME BASE
+þprototype
+void _fnlwr (char *NAME);
+void _fnlwr2 (char *NAME, const char *BASE);
+void _rfnlwr (void);
+void _sfnlwr (const char *NAME);
+þendprototype
+
+    _fnlwr() converts the file name pointed to by NAME to lower case
+    unless the file system is case preserving.  Accented characters
+    etc. are converted as well, DBCS characters are not changed.  If
+    the file name does not contain a drive letter, it is assumed to
+    refer to the drive set by _sfnlwr().  To save time, _fnlwr()
+    caches information about file systems.  If the file system of a
+    drive changes or if the current drive changes, you should call
+    _rfnlwr() to reset the cache.  _sfnlwr() takes the drive name from
+    the string pointed to by NAME for future _fnlwr() calls.  If
+    _sfnlwr() hasn't been called since the last call to _rfnlwr() or
+    if the file name does not contain a drive letter, _fnlwr() uses
+    the current drive.
+
+    _fnlwr2() is a variant of _fnlwr() which should be used when
+    converting only a suffix of a path name to lower case.  NAME
+    points to the suffix, BASE points to the beginning of the path
+    name.  The string pointed to by BASE is used for getting the drive
+    letter.
+
+þhints
+
+    _fnlwr2() should be used instead of _sfnlwr() and _fnlwr()
+    whenever possible.
+
+þseealso _filesys() _nls_init() _nls_strlwr()
+
+
+þfunction fnmatch()
+þcompat POSIX.2
+þheaders
+#include <fnmatch.h>
+þendheaders
+
+þparam PATTERN NAME FLAGS
+þprototype
+int fnmatch (const char *PATTERN, const char *NAME, int FLAGS);
+þendprototype
+
+    The fnmatch() function checks the string pointed to by NAME to see
+    if it matches the file name pattern pointed to by the PATTERN
+    argument.  The interpretation of the strings pointed to by PATTERN
+    and NAME are is modified by FLAGS, which is the bitwise OR of zero
+    or more of the following flags:
+
+þdescription
+þitem FNM_NOESCAPE
+
+    If FNM_NOESCAPE is þem{not} set, a backslash character (`þtt{\}')
+    in the string pointed to by PATTERN followed by any other character
+    matches that second character in the string pointed to by NAME.
+    In particular, `þtt{\\}' matches a backslash in the string pointed
+    to by NAME.
+
+    If FNM_NOESCAPE is set, a backslash character in the string
+    pointed to by PATTERN is treated as an ordinary character.
+
+þitem FNM_PATHNAME
+
+    If FNM_PATHNAME is set, a slash character (`þtt{/}') in the string
+    pointed to by NAME must be explicitely matched by a slash in the
+    string pointed to by PATTERN; it is not matched by `þtt{?}',
+    `þtt{*}', or `þtt{[]}' in the string pointed to by PATTERN.
+
+    If FNM_PATHNAME is not set, a slash character in the string
+    pointed to by NAME is treated as an ordinary character.
+
+    If _FNM_OS2 or _FNM_DOS is set, the backslash character is treated
+    like a slash, with repect to FNM_PATHNAME.
+
+þitem FNM_PERIOD
+
+    If FNM_PERIOD is set, then a `leading' period character (`þtt{.}')
+    in the string pointed to by NAME matches a period (but not
+    `þtt{?}', `þtt{*}', and `þtt{[]}') in the string pointed to by
+    PATTERN.  The meaning of `leading' depends on FNM_PATHNAME: If
+    FNM_PATHNAME is set, a period is `leading' if it is the first
+    character in the string pointed to by NAME or if it immediately
+    follows a slash.  If FNM_PATHNAME is not set, a period is
+    `leading' if it is the first character of the string pointed to by
+    NAME.
+
+    If FNM_PERIOD is not set, a period in the string pointed to by
+    NAME is treated as an ordinary character.
+
+þitem _FNM_IGNORECASE
+
+    If _FNM_IGNORECASE is set, letter case is ignored, that is, lower
+    case letters match the corresponding upper case letters.  If
+    _FNM_IGNORECASE is not set, lower case letters and upper case
+    letters are distinct.
+
+    _FNM_IGNORECASE is an emx extension.
+
+þitem _FNM_PATHPREFIX
+
+    If _FNM_PATHPREFIX is set, the string pointed to by PATTERN may match
+    a complete path prefix of the string pointed to by NAME, that is,
+    the string pointed to by NAME can have additional path components
+    at the end.
+
+    _FNM_PATHPREFIX is an emx extension.
+
+þitem _FNM_POSIX
+
+    If _FNM_POSIX is set, or none of _FNM_OS2 and _FNM_DOS are set,
+    fnmatch() has POSIX.2 semantics.
+
+    _FNM_POSIX is an emx extension.
+
+þitem _FNM_OS2
+
+    If _FNM_OS2 is set, fnmatch() has OS/2 semantics: Path components
+    in the string pointed to by NAME have an implicit period at the
+    end if they don't contain a period.  A period at the end of a
+    component in the string pointed to by PATTERN may match zero
+    characters at the end of a component of the string pointed to by
+    NAME.  `þtt{?}' may match zero characters at the end of a
+    component of the string pointed to by NAME or before a period.
+    þtt{"/*/"} does not match UNC names.  `þtt{[}' in the string
+    pointed to by PATTERN is treated as an ordinary character.  `þtt{\}'
+    is a path separator.  _FNM_NOESCAPE implied.
+
+    _FNM_OS2 is an emx extension.  At most one of _FNM_POSIX,
+    _FNM_OS2, and _FNM_DOS can be set.
+
+þitem _FNM_DOS
+
+    If _FNM_OS2 is set, fnmatch() has DOS semantics: Path components
+    in the string pointed to by NAME have an implicit period at the
+    end if they don't contain a period.  A period at the end of a
+    component in the string pointed to by PATTERN may match zero
+    characters at the end of a component of the string pointed to by
+    NAME.  `þtt{?}' may match zero characters at the end of a
+    component of the string pointed to by NAME or before a period.
+    `þtt{*}' does not match a period.  þtt{"/*/"} does not match UNC
+    names.  `þtt{[}' in the string pointed to by PATTERN is treated as an
+    ordinary character.  `þtt{\}' is a path separator.  _FNM_NOESCAPE
+    is implied.
+
+    _FNM_DOS is an emx extension.  At most one of _FNM_POSIX,
+    _FNM_OS2, and _FNM_DOS can be set.
+
+þenddescription
+
+    The characters `þtt{?}', `þtt{*}', and `þtt{[]}' are interpreted
+    as wildcard characters in the pattern.  `þtt{?}' matches one
+    character, `þtt{*}' matches zero or more characters.  For
+    _FNM_POSIX, `þtt{[]}' matches the set of characters listed between
+    the brackets, ranges (such as `þtt{[0-9]}') are allowed.  If the
+    first character after `þtt{[}' is `þtt{!}', all characters
+    þem{not} in the set match the set.  DBCS characters are not
+    allowed in sets.
+
+þreturnvalue
+
+    fnmatch() returns 0 if the string pointed to by NAME matches the
+    string pointed to by PATTERN.  fnmatch() returns FNM_NOMATCH if the
+    string pointed to by NAME does not match the string pointed to by
+    PATTERN.  fnmatch() returns another non-zero value on error.
+
+þimplementation
+
+    If the first character after `þtt{[}' is `þtt{^}', all characters
+    þem{not} in the set match the set.
+
+þbugs
+
+    Ranges in `þtt{[]}' which include letters don't work correctly if
+    _FNM_IGNORECASE is set.
+
+þseealso glob() _nls_tolower()
+
+
+þfunction _fnslashify()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME
+þprototype
+char *_fnslashify (char *NAME);
+þendprototype
+
+    _fnslashify() replaces backslashes by slashes in the string pointed to
+    by NAME.
+
+    _fnslashify() properly handles DBCS characters.
+
+þreturnvalue
+
+   _fnslashify() returns NAME.
+
+þseealso _nls_init()
+
+
+þfunction fopen()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam FNAME MODE
+þprototype
+FILE *fopen (const char *FNAME, const char *MODE);
+þendprototype
+
+    Open a stream.  FNAME points to a string giving the name of the
+    file, MODE points to a string which specifies the file mode:
+
+þlist
+þitem þtt{r}
+
+    Open the file for reading.  The file must exist.
+
+þitem þtt{w}
+
+    Open the file for writing.  If the file exists, it will be
+    truncated to 0 bytes, destroying its contents.  If the file does
+    not exist, it will be created.
+
+þitem þtt{a}
+
+    Open the file for appending.  Writing will always take place at
+    the end of the file.  If the file does not exist, it will be
+    created.
+
+þitem þtt{r+}
+
+    Open the file for both reading and writing.  The file must exist.
+
+þitem þtt{w+}
+
+    Open the file for both reading and writing.  If the file exists,
+    it will be truncated to 0 bytes, destroying its contents.  If the
+    file does not exist, it will be created.
+
+þitem þtt{a+}
+
+    Open the file for both reading and appending.  Writing will always
+    take place at the end of the file.  If the file does not exist, it
+    will be created.
+
+þendlist
+
+    There are two additional MODE flags which can be appended to one
+    of the above modes: þtt{t} for text mode, þtt{b} for binary mode.
+    Text mode, which is the default, skips CR characters on input and
+    converts newline characters to CR/LF pairs on output.  If the last
+    character of a file is Ctrl-Z, it is discarded on input.  Binary
+    mode disables these transformations.
+
+    The file is opened in the sharing mode SH_DENYNO, see
+    þhpt{sopen()}.  If you want to use a different sharing mode, use
+    þhpt{_fsopen()}.
+
+þreturnvalue
+
+    fopen() returns a new stream.  On error, fopen() returns NULL.
+
+þseealso fclose() fdopen() freopen() _fsopen() sopen()
+
+
+þfunction fork()
+þcompat POSIX.1 *
+þheaders
+#include <unistd.h>
+þendheaders
+
+þprototype
+int fork (void);
+þendprototype
+
+    Duplicate the current process.  A child process is created which is a
+    copy of the calling process.  Both the parent process and the
+    child process resume at the point where fork() was called.  The
+    child process inherits the following attributes of the parent
+    process:
+
+þitemize
+
+þitem
+
+    environment
+
+þitem
+
+    dynamically loaded DLLs created with emx 0.9c or later
+
+þitem
+
+    memory (data segment, heap, stack, and data segments of DLLs
+    created with emx 0.9c or later)
+
+þitem
+
+    signal actions
+
+þitem
+
+    file handles
+
+þitem
+
+    current working directories
+
+þitem
+
+    umask
+
+þitem
+    flags set with _uflags()
+
+þitem
+
+    break points.  This is an OS/2 bug.  To debug a program containing
+    fork(), set a breakpoint in the branch of execution that's
+    executed only in the parent process
+
+þenditemize
+
+    The new process differs from the parent process in the following
+    ways:
+
+þitemize
+
+þitem
+
+    the child process has a unique process ID
+
+þitem
+
+    the child process has a different parent process ID (the process
+    ID of the parent process)
+
+þitem
+
+    the child process has copies of the file descriptors of the parent
+    process.  The file pointers are shared
+
+þitem
+
+    Terminal settings are reset in the child process (that is, the
+    IDEFAULT bit is set)
+
+þitem
+
+    all resources allocated using OS/2 calls (except for DLLs created
+    with emx 0.9c or later) are not inherited by the child process:
+    semaphores, queues, threads, memory, file handles, etcþ.
+
+þitem
+
+    the alarm clock is turned off
+
+þitem
+
+    the CPU time (returned by þhpt{clock()}) is set to 0
+
+þitem
+
+    non-shared _rmutex semaphores
+
+þenditemize
+
+    When the new process terminates, SIGCHLD is sent to the process
+    which forked that process.
+
+þreturnvalue
+
+    On success, fork() returns the process ID of the new process to
+    the calling process, 0 to the new process.  On error, fork()
+    returns -1.
+
+þrestrictions
+
+    fork() is not implemented for DOS.  fork() works only in programs
+    linked by ld.  It does not work in programs linked by LINK386.
+    fork() is not available with the system call library sys.lib
+    (þhpt{-Zsys}).
+
+    The data segments of dynamic link libraries created with emx 0.9c
+    or later are copied, therefore fork() can be used with the
+    þhpt{-Zcrtdll} option of GCC and with DLLs created with emx 0.9c
+    and later.  However, data segments of DLLs not created with emx or
+    created with emx 0.9b or older are not duplicated, therefore
+    fork() does not work correctly when using such DLLs.
+
+    fork() is very inefficient for OS/2.  To start a child process,
+    use spawn*() instead of fork() and exec*().
+
+    If the parent process uses the þhpt{general terminal interface}
+    for the keyboard, the child process cannot read from the keyboard
+    using þhpt{_read_kbd()}, the general terminal interface, or the
+    þtt{Kbd} OS/2 API functions.
+
+    If the process has a non-contiguous heap (that is, multiple heap
+    objects), fork() will fail.  Increase the initial heap size to
+    work around this problem.  If any DLL used by the program shares
+    the heap with the program and uses the heap in _DLL_InitTerm() by
+    calling sbrk(), malloc(), etc., fork() will fail.  In both cases,
+    fork() will return -1 and set errno to ENOMEM.
+
+þseealso alarm() exec*() _rmutex_create() sbrk() sigaction() signal() spawn*() _uflags() wait() waitpid()
+
+
+þfunction fpclassify()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+int fpclassify (float X);
+int fpclassify (double X);
+int fpclassify (long double X);
+þendprototype
+
+    Classify X as zero (FP_ZERO), subnormal (FP_SUBNORMAL), normal
+    (FP_NORMAL), infinite (FP_INFINITE), or NaN (FP_NAN).  The
+    argument X must be of a floating-point type.  Classification is
+    based on the type of the argument.
+
+þreturnvalue
+
+    fpclassify() returns the value of one of the following macros:
+    FP_ZERO, FP_SUBNORMAL, FP_NORMAL, FP_INFINITE, FP_NAN.
+
+þseealso copysign() isfinite() isnan() isnormal() signbit()
+
+
+þfunction _fpreset()
+þcompat PC
+þheaders
+#include <float.h>
+þendheaders
+
+þprototype
+void _fpreset (void);
+þendprototype
+
+    Reset the floating point coprocessor.
+
+þseealso _clear87() _control87()
+
+
+þfunction fprintf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM FORMAT
+þprototype
+int fprintf (FILE *STREAM, const char *FORMAT, ...);
+þendprototype
+
+    Formatted output to the stream STREAM.  See printf() for details.
+
+þreturnvalue
+
+    On success, fprintf() returns the number of characters written to
+    STREAM.  On error, fprintf() returns EOF.
+
+þseealso fscanf() printf()
+
+
+þfunction fputc()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam C STREAM
+þprototype
+int fputc (int C, FILE *STREAM);
+þendprototype
+
+    Write the character C (converted to an þtt{unsigned char}) to the
+    output stream STREAM and advance the file position indicator of
+    the stream (if defined).  All output to streams takes place as if
+    characters were written by successive calls to fputc().
+
+    fputc() is a function, in contrast to putc().
+
+þreturnvalue
+
+    fputc() returns the character written.  On error, fputc() sets the
+    error indicator of the stream and returns EOF.
+
+þseealso ferror() fprintf() fputchar() fputs() putc() putchar()
+
+
+þfunction fputchar()
+þcompat PC
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam C
+þprototype
+int fputchar (int C);
+þendprototype
+
+    þtt{fputchar (c)} is equivalent to þtt{fputc (c, stdout)}.
+
+þreturnvalue
+
+    fputchar() returns the character written.  On error, fputchar()
+    sets the error indicator of stdout and returns EOF.
+
+þhints
+
+    Use putchar() or þtt{fputc (c, stdout)} instead of fputchar() as
+    fputchar() is not portable.
+
+þseealso fputc() putchar()
+
+
+þfunction fputs()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STRING STREAM
+þprototype
+int fputs (const char *STRING, FILE *STREAM);
+þendprototype
+
+    Write the string pointed to by STRING to STREAM.  In contrast to
+    puts(), a newline character is not appended automatically.
+
+þreturnvalue
+
+    fputs() returns a non-negative value if successful.  On error,
+    fputs() returns EOF.
+
+þseealso fgets() fputc() printf() puts() setvbuf()
+
+
+þfunction fread()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUFFER SIZE COUNT STREAM
+þprototype
+size_t fread (void *BUFFER, size_t SIZE, size_t COUNT, FILE *STREAM);
+þendprototype
+
+    Read up to COUNT elements whose size is SIZE from STREAM to the
+    array pointed to by BUFFER.  The file pointer is incremented by
+    the number of bytes read.  If STREAM has been opened in text mode,
+    CR/LF pairs are translated to newline characters and a Ctrl-Z
+    character is discarded if it is the last character of the file.
+    If fread() fails, the position of the file pointer will be
+    undefined.
+
+þreturnvalue
+
+    fread() returns the number of elements successfully read, which
+    may be less than COUNT if an error occurs or if the end of the
+    file is reached.  Use ferror() and feof() to distinguish between
+    these two conditions.
+
+    Text mode translation does not affect the return value -- SIZE and
+    COUNT are applied after translation.
+
+þseealso fgetc() fgets() _fsetmode() fwrite()
+
+
+þfunction free()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam MEM
+þprototype
+void free (void *MEM);
+þendprototype
+
+    Deallocate the block of memory pointed to by MEM.  MEM must point
+    to a block which is still in use (that is, has not been freed) and
+    must have been returned by calloc(), malloc(), realloc(),
+    _tcalloc(), _tmalloc(), _trealloc(), _ucalloc(), _umalloc(),
+    _utcalloc(), or _utmalloc().  Do not use the memory pointed to by
+    MEM after calling free().  If MEM is NULL, free() does nothing.
+
+þseealso calloc() _heapmin() malloc() realloc() _tfree() _umalloc()
+
+
+þfunction freopen()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam FNAME MODE STREAM
+þprototype
+FILE *freopen (const char *FNAME, const char *MODE, FILE *STREAM);
+þendprototype
+
+    Open the file whose name is in the string pointed to by FNAME in
+    the mode given by the string pointed to by MODE (see
+    þhpt{fopen()}) and associate STREAM with that file.  If STREAM is
+    associated with a file when freopen() is called, freopen() will
+    close the file, ignoring any errors, before opening the file whose
+    name is in the string pointed to by FNAME.
+
+þreturnvalue
+
+    If successful, freopen() returns STREAM.  On error, freopen()
+    returns NULL.
+
+þhints
+
+    The major application of freopen() is to redirect stdin, stdout,
+    or stderr.
+
+þseealso _fassign() fclose() fopen() stderr
+
+
+þfunction frexp() frexpl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X EXP_PTR
+þprototype
+double frexp (double X, int *EXP_PTR);
+long double frexpl (long double X, int *EXP_PTR);
+þendprototype
+
+    Extract mantissa and exponent of X.  The mantissa is returned, the
+    exponent, an integer, is stored to *EXP_PTR.  The following holds
+    for the mantissa m: 0.5 <= |m| < 1.0.  If X is zero, both the
+    mantissa and the exponent are 0.
+
+    frexpl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    frexp() returns the mantissa of X.
+
+þseealso ldexp() log()
+
+
+þfunction fscanf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM FORMAT
+þprototype
+int fscanf (FILE *STREAM, const char *FORMAT, ...);
+þendprototype
+
+    The stream STREAM is read and input is parsed according to the
+    format string FORMAT.  For each field in the string pointed to by
+    FORMAT there must be a pointer to the location receiving the
+    value.  The pointers are passed after the FORMAT argument.
+
+þreturnvalue
+
+    If successful, fscanf() returns the number of fields converted.
+    On error, fscanf() returns EOF.
+
+þseealso fprintf() scanf()
+
+
+þfunction fseek()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM OFFSET ORIGIN
+þprototype
+int fseek (FILE *STREAM, long OFFSET, int ORIGIN);
+þendprototype
+
+    fseek() moves the file pointer of STREAM.  The new position OFFSET
+    is relative to ORIGIN: If ORIGIN is SEEK_SET, OFFSET is relative
+    to the beginning of the file, if ORIGIN is SEEK_CUR, OFFSET is
+    relative to the current position, if ORIGIN is SEEK_END, OFFSET is
+    relative to the end of the file.  The file pointer cannot be moved
+    before the beginning of the file.
+
+    For text-mode streams, OFFSET must be either zero (with ORIGIN
+    equal to SEEK_SET, SEEK_CUR, or SEEK_END) or a value returned by a
+    call to ftell() on the same stream (with ORIGIN equal to
+    SEEK_SET).
+
+    If successful, fseek() resets the end-of-file indicator of the
+    stream and undoes ungetc().  If STREAM is open for reading and
+    writing (update), the next operation after fseek() can be either
+    input or output.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem non-0
+    error
+þenddescription
+
+þimplementation
+
+    For binary-mode streams, the file position can be set beyond end
+    of file; the data between end of file and the new position is
+    undefined.
+
+    For text-mode streams ending with a Ctrl-Z, SEEK_END is not
+    allowed.
+
+þrestrictions
+
+    fseek() does not work for text-mode streams unless either CR/LF
+    pairs or LF only is used for all lines of the file.  If there are
+    lines terminated with CR/LF and lines terminated with LF, fseek()
+    does not work correctly.
+
+þseealso chsize() fgetpos() fsetpos() ftell() lseek() rewind()
+
+
+þfunction _fseek_hdr()
+þcompat emx
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int _fseek_hdr (FILE *STREAM);
+þendprototype
+
+    Move the file pointer of STREAM to the a.out header of an
+    executable file (a.out or bound .exe).  _fseek_hdr() assumes that
+    the file pointer points to the beginning of the header (ie, the
+    beginning of the file).  If no header is found, the file pointer
+    will be repositioned to the original position.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error (errno is set)
+þenddescription
+
+þseealso _seek_hdr()
+
+
+þfunction _fsetmode()
+þcompat emx
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM MODE
+þprototype
+int _fsetmode (FILE *STREAM, const char *MODE);
+þendprototype
+
+    Change the text/binary mode of a stream.  MODE must point either
+    to þtt{"b"} or to þtt{"t"}.  _fsetmode() is usually used to switch
+    stdin or stdout to binary mode.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    Do not call _fsetmode() on a stream with non-empty buffer.  If
+    there is data in the buffer (either data to be read or data to be
+    written), call fflush() before _fsetmode().  Otherwise, future
+    behavior of the stream will be undefined.
+
+þseealso fopen()
+
+
+þfunction fsetpos()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM POS
+þprototype
+int fsetpos (FILE *STREAM, const fpos_t *POS);
+þendprototype
+
+    Restore the position of the file pointer of the file STREAM to the
+    position saved by fgetpos() in the variable pointed to by POS.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem non-0
+    error
+þenddescription
+
+þrestrictions
+
+    fsetpos() does not work for text-mode streams unless either CR/LF
+    pairs or LF only is used for all lines of the file.  If there are
+    lines terminated with CR/LF and lines terminated with LF,
+    fsetpos() does not work correctly.
+
+þseealso fgetpos() fseek()
+
+
+þfunction _fsopen()
+þcompat PC
+þheaders
+#include <stdio.h>
+#include <share.h>
+þendheaders
+
+þparam FNAME MODE SHFLAG
+þprototype
+FILE *_fsopen (const char *FNAME, const char *MODE, int SHFLAG);
+þendprototype
+
+    Open a stream.  FNAME points to a string giving the name of the
+    file, MODE points to a string which specifies the file mode, see
+    þhpt{fopen()} for details.
+
+    The sharing mode of the file is given by SHFLAG.  The following
+    sharing modes are available:
+
+þdescription
+
+þitem SH_DENYRW
+
+    Deny read and write access
+
+þitem SH_DENYRD
+
+    Deny read access (permit write access)
+
+þitem SH_DENYWR
+
+    Deny write access (permit read access)
+
+þitem SH_DENYNO
+
+    Deny nothing (permit read and write access)
+
+þenddescription
+
+þreturnvalue
+
+    _fsopen() returns a new stream.  On error, _fsopen() returns NULL.
+
+þseealso fopen() sopen()
+
+
+þfunction fstat()
+þcompat UNIX
+þheaders
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+þendheaders
+
+þparam HANDLE BUFFER
+þprototype
+int fstat (int HANDLE, struct stat *BUFFER);
+þendprototype
+
+    Retrieve information about the open file HANDLE.  fstat() will put
+    the data into the structure pointed to by BUFFER.
+
+    See þhpt{stat()} for a description of þtt{struct stat}.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error (errno is set)
+þenddescription
+
+þrestrictions
+
+    st_dev and st_rdev are set to zero.  Each call to fstat() returns
+    a different value for st_ino.
+
+þseealso ioctl() stat() ttyname()
+
+
+þfunction fsync()
+þcompat BSD
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int fsync (int HANDLE);
+þendprototype
+
+    Flush the buffers associated with HANDLE and update the directory.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    fsync() is currently not implemented for DOS: errno is set to
+    ENOSYS.
+
+    Due to a bug in HPFS.IFS, calling fsync() can be quite dangerous.
+    If HPFS.IFS has the bug, and fsync() (i.e., DosResetBuffer) is
+    called after writing to a file, and Ctrl+Alt+Del is pressed while
+    the file is still open, HPFS.IFS will corrupt the allocation
+    bitmap of the partition containing that file.  This may damange
+    existing and future files and directories.  The bug is present in
+    all HPFS.IFS versions of (at least) OS/2 2.0 through OS/2 Warp
+    3.0, red box of 1994.  That HPFS.IFS bug seems to be fixed in
+    FixPak XR_W005 and later.  Performing a system shutdown instead of
+    pressing Ctrl+Alt+Del causes the same problem if the process that
+    wrote to the file and called fsync() or DosResetBuffer cannot be
+    killed.  As you cannot assume that the user of your application
+    has a working HPFS.IFS, better don't call fsync() and
+    DosResetBuffer.
+
+
+þfunction ftell()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+long ftell (FILE *STREAM);
+þendprototype
+
+    ftell() retrieves the current position of the file pointer of
+    STREAM.  
+
+þreturnvalue
+
+    ftell() returns the current position of the file pointer of
+    STREAM, in characters.  On error, ftell() returns -1.
+
+þrestrictions
+
+    ftell() does not work for text-mode streams unless either CR/LF
+    pairs or LF only is used for all lines of the file.  If there are
+    lines terminated with CR/LF and lines terminated with LF,
+    ftell() does not work correctly.
+
+þseealso fgetpos() fseek()
+
+
+þfunction ftime()
+þcompat SysV
+þheaders
+#include <sys/timeb.h>
+þendheaders
+
+þparam PTR
+þprototype
+void ftime (struct timeb *PTR);
+þendprototype
+
+    Get the current time and store it to the structure pointed to by PTR.
+    That structure has the following fields:
+
+þlist
+
+þitem dstflag
+
+    Non-zero if daylight saving time is active for the local timezone.
+
+þitem millitm
+
+    Milliseconds of current time.
+
+þitem þtt{time}
+
+    Current time in seconds since 00:00:00 1-Jan-1970 Coordinated
+    Universal Time (UTC, GMT).
+
+þitem þtt{timezone}
+
+    Difference between UTC and local time in minutes.  Positive values
+    are to the west of the Prime Meridian.
+
+þendlist
+
+    See þhpt{tzset()} for a description of the TZ environment
+    variable.
+
+þseealso gettimeofday() settimeofday() time() tzset()
+
+
+þfunction ftruncate()
+þcompat BSD
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE LENGTH
+þprototype
+int ftruncate (int HANDLE, long LENGTH);
+þendprototype
+
+    Truncate the file associated with HANDLE to at most LENGTH bytes.
+    The position of the file pointer is undefined after calling this
+    function.  If LENGTH is greater than the current length of the
+    file, the length is not changed.  HANDLE must be open for writing.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso chsize() truncate()
+
+
+þfunction ftw()
+þcompat UNIX
+þheaders
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ftw.h>
+þendheaders
+
+þparam PATH FN NAME STAT_PTR FLAG DEPTH
+þprototype
+int ftw (const char *PATH,
+         int (*FN)(const char *NAME, const struct stat *STAT_PTR, int FLAG),
+         int DEPTH);
+þendprototype
+
+    Call FN for all entries of the directory tree whose root directory
+    is in the string pointed to by PATH.  Directories are visited
+    before the entries they contain.  FN is not called for the
+    directories `.' and `..'.  A pointer to a string holding the name
+    of the entry is passed in NAME.  Forward slashes are used to
+    separate directories (backslashes in PATH are not converted to
+    forward slashes).  _fnlwr() is called to convert the file names to
+    lower case on upper-case-only file systems.  A structure filled in
+    by stat() is pointed to by STAT_PTR.  FLAG is one of the
+    following:
+
+þdescription
+
+þitem FTW_D
+
+    NAME is a directory
+
+þitem FTW_F
+
+    NAME is a file
+
+þitem FTW_NS
+
+    stat() failed, the contents of structure pointed to by STAT_PTR
+    are undefined
+
+þitem FTW_DNR
+
+    the directory whose name is in the string pointed to by NAME is
+    unreadable (does not happen under DOS and OS/2)
+
+þenddescription
+
+    If FN returns 0, ftw() continues.  Otherwise, ftw() terminates and
+    returns the value returned by FN.
+
+    The DEPTH argument is ignored by this implementation of ftw().  In
+    other implementations, DEPTH is used to restrict the number of
+    file handles used by ftw(): one file handle is required for each
+    level.  If DEPTH is less than the number of levels, ftw() will be
+    slow.
+
+    ftw() properly handles DBCS characters.
+
+þreturnvalue
+
+    If FN returns a non-zero value, ftw() returns that value.
+    Otherwise, ftw() returns 0.  On error, ftw() returns -1.
+
+
+þseealso _fnlwr() _nls_init() opendir()
+
+þsamplefile /emx/test/ftwtest.c
+
+
+þfunction _fullpath()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DST SRC SIZE
+þprototype
+int _fullpath (char *DST, const char *SRC, int SIZE);
+þendprototype
+
+    Construct an absolute path name for the file name or directory
+    name pointed to by SRC.  The absolute path name is written to the
+    array pointed to by DST.  It is assumed that there are SIZE bytes
+    available at DST, this includes the terminating null character.
+    DST can be identical to SRC.  Backslashes are translated into
+    forward slashes.  The absolute path name is not translated to
+    lower case.
+
+    _fullpath() accesses the appropriate drive.  It fails if a
+    directory does not exist unless the non-existing directory is the
+    last member of the resulting path name.
+
+    _fullpath() properly handles DBCS characters.
+
+þreturnvalue
+
+  If successful, _fullpath() returns 0.  If there is an error,
+  _fullpath() returns -1.  If SIZE is too small, _fullpath() sets
+  errno to ERANGE and returns -1.
+
+þseealso _abspath() _nls_init()
+
+
+þfunction fwrite()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUFFER SIZE COUNT STREAM
+þprototype
+size_t fwrite (const void *BUFFER, size_t SIZE, size_t COUNT, FILE *STREAM);
+þendprototype
+
+    Write COUNT elements whose size is SIZE from the array pointed to
+    by BUFFER to STREAM.  The file pointer is incremented by the
+    number of bytes written.  If fwrite() fails, the value of the file
+    pointer is undefined.  If STREAM has been opened in text mode,
+    newline characters are translated to CR/LF pairs.
+
+þreturnvalue
+
+    fwrite() returns the number of elements successfully written,
+    which will be less than COUNT if an error occurs.  Text mode
+    translation does not affect the return value -- SIZE and COUNT are
+    applied before the translation.
+
+þseealso fputc() fputs() fread() _fsetmode() printf() setvbuf()
+
+
+þfunction g_box()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam X0 Y0 X1 Y1 COLOR FILL_FLAG
+þprototype
+void g_box (int X0, int Y0, int X1, int Y1, int COLOR, int FILL_FLAG);
+þendprototype
+
+    Draw a box which has the four vertices (X0,Y0), (X0,Y1), (X1, Y0)
+    and (X1, Y1).  If FILL_FLAG is G_OUTLINE, the outline is drawn,
+    that is, four lines between the vertices.  If FILL_FLAG is G_FILL,
+    the interior of the box is filled.  The color COLOR is used for
+    drawing.
+
+þseealso g_clip()
+
+
+þfunction g_clear()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam COLOR
+þprototype
+void g_clear (int COLOR);
+þendprototype
+
+    Clear the screen (graphics mode, only).  All pixels are set to the
+    color COLOR.  The clipping rectangle is ignored.
+
+
+þfunction g_clip()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam X0 Y0 X1 Y1
+þprototype
+void g_clip (int X0, int Y0, int X1, int Y1);
+þendprototype
+
+    Define the clipping rectangle.  Only pixels with X coordinate
+    between X0 and X1 (inclusive) and with Y coordinate between Y0 and
+    Y1 (inclusive) are drawn.  No drawing is performed outside that
+    clipping rectangle.  After switching to graphics mode with
+    g_mode(), the clipping rectangle is set to the entire screen.
+    This is equivalent to calling
+
+þexample
+g_clip (0, 0, g_xsize-1, g_ysize-1);
+þendexample
+
+þseealso g_mode() g_xsize g_ysize
+
+
+þfunction g_ellipse()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam CX CY RX RY COLOR FILL_FLAG
+þprototype
+void g_ellipse (int CX, int CY, int RX, int RY, int COLOR, int FILL_FLAG);
+þendprototype
+
+    Draw an ellipse or a circle.  One axis is horizontal, the other
+    one vertical.  The center of the ellipse is at (CX,CY).  The
+    horizontal radius is RX, the vertical radius is RY.  It's
+    impossible to draw an ellipse with even length of an axis.  If
+    FILL_FLAG is G_OUTLINE, the outline of the ellipse is drawn.  If
+    FILL_FLAG is G_FILL, the interior of the ellipse is filled.  The
+    color COLOR is used for drawing.
+
+þseealso g_clip()
+
+
+þfunction g_get()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam X Y
+þprototype
+int g_get (int X, int Y);
+þendprototype
+
+    Return the color of the pixel at (X,Y).  If (X,Y) is outside the
+    clipping rectangle, -1 is returned.
+
+þseealso g_clip() g_set()
+
+
+þfunction g_hline()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam Y X0 X1 COLOR
+þprototype
+void g_hline (int Y, int X0, int X1, int COLOR);
+þendprototype
+
+    Draw a horizontal line between (X0,Y) and (X1,Y).  The color COLOR
+    is used for drawing.
+
+þseealso g_box() g_clip() g_line() g_vline()
+
+
+þfunction g_line()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam X0 Y0 X1 Y1 COLOR
+þprototype
+void g_line (int X0, int Y0, int X1, int Y1, int COLOR);
+þendprototype
+
+    Draw a line of arbitrary slope between (X0,Y0) and (X1,Y1).  The
+    color COLOR is used for drawing.  To draw horizontal or vertical
+    lines, you should use g_hline() and g_vline(), respectively, which
+    are specialized functions optimized for speed.
+
+þseealso g_clip() g_hline() g_polygon() g_triangle() g_vline()
+
+
+þfunction g_lock()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þprototype
+void g_lock (void);
+þendprototype
+
+    Lock the screen.  Under OS/2, the screen must be locked while
+    access graphics memory.  All the graphics drawing functions lock
+    the screen, draw, and unlock the screen unless it's already
+    locked.  To avoid the overhead of locking and unlocking for each
+    function call, you can lock and unlock the screen yourself when
+    performing many successive drawing operations.  Note that you
+    should not lock the screen for more than a few seconds.  g_lock()
+    increments a counter, which is initialized to zero by g_mode().
+    The screen is locked while the counter is non-zero.  g_unlock()
+    decrements the counter and unlocks the screen if the counter
+    reaches zero.
+
+þseealso g_unlock()
+
+
+þfunction g_mode()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam MODE
+þprototype
+int g_mode (int MODE);
+þendprototype
+
+    Select graphics mode.  If MODE is G_MODE_OFF, graphics mode is
+    turned off and 0 is returned.  Other values of MODE select the
+    following graphics modes:
+
+þdescription
+þitem G_MODE_EGA_C
+    640x200 EGA mode with 16 colors
+þitem G_MODE_EGA_E
+    640x350 EGA mode with 16 colors
+þitem G_MODE_VGA_H
+    640x480 VGA mode with 16 colors
+þitem G_MODE_VGA_L
+    320x200 VGA mode with 256 colors
+þenddescription
+
+    The global variables g_xsize, g_ysize and g_colors are set.  The
+    clipping rectangle is set to the entire screen.
+
+    General information about the graphics library: Programs using the
+    graphics library work both under DOS and in OS/2 full-screen
+    sessions.  The coordinates of the screen are (0,0) (upper left)
+    through (þtt{g_xsize}-1,þtt{g_ysize}-1) (lower right).  You have
+    to link with -lgraph.  Under DOS, emx option -acm is required, see
+    `þhpt{Using emx options}'.
+
+þreturnvalue
+
+  If switching to graphics mode succeeds, gmode() returns 1.
+  Otherwise, gmode() returns 0.
+
+þseealso g_clip() g_modeset() g_colors g_xsize g_ysize
+
+þsamplefile /emx/samples/graph.c
+
+
+þfunction g_modeset()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam MODE FLAG
+þprototype
+int g_modeset (int MODE, int FLAG);
+þendprototype
+
+    Modify a graphics mode number.  The mode number to be modified is
+    passed in MODE, the value passed in FLAG specifies how to modify
+    the mode number: G_SET_KEEP causes the mode number to be not
+    modified.
+
+    The global variables g_xsize, g_ysize and g_colors are set.
+
+þreturnvalue
+
+    g_modeset() returns the new mode number.  On failure, g_modeset()
+    returns G_MODE_OFF.
+
+þrestrictions
+
+    As only G_SET_KEEP is implemented, g_modeset() is useless.  It's
+    included for compatibility with existing programs.
+
+þseealso g_mode() g_colors g_xsize g_ysize
+
+
+þfunction g_polygon()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam X Y N COLOR FILL_FLAG
+þprototype
+void g_polygon (const int *X, const int *Y, int N, int COLOR,
+                int FILL_FLAG);
+þendprototype
+
+    Draw a polygon.  The N vertices are stored in the X and Y arrays:
+    (þpa{X}[i],þpa{Y}[i]) for i = 0, ..., þpa{N}-1.  If FILL_FLAG is
+    G_OUTLINE, the outline of the polygon is drawn, that is, a line
+    from vertex 0 to vertex 1, from vertex 1 to vertex 2, ..., vertex
+    þpa{N}-2 to vertex þpa{N}-1, vertex þpa{N}-1 to vertex 0.  If
+    FILL_FLAG is G_FILL, the interior of the polygon is filled.  A
+    point is defined to be in the interior of the polygon, if an
+    infinite line to any side of that pixel intersects the polygon an
+    odd number of times.  The color COLOR is used for drawing.
+
+þseealso g_clip() g_line() g_triangle()
+
+
+þfunction g_set()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam X Y COLOR
+þprototype
+void g_set (int X, int Y, int COLOR);
+þendprototype
+
+    Set the pixel (X,Y) to the color COLOR.
+
+þseealso g_clip() g_get()
+
+
+þfunction g_triangle()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam X0 Y0 X1 Y1 X2 Y2 COLOR FILL_FLAG
+þprototype
+void g_triangle (int X0, int Y0, int X1, int Y1, int X2, int Y2, int COLOR,
+                 int FILL_FLAG);
+þendprototype
+
+    Draw a triangle.  The vertices are (X0,Y0), (X1,Y1) and (X2,Y2).
+    If FILL_FLAG is G_OUTLINE, the outline of the triangle is drawn,
+    that is, a line from (X0,Y0) to (X1,Y1), a line from (X1,Y1) to
+    (X2,Y2) and a line from (X2,Y2) to (X0,Y0).  If FILL_FLAG is
+    G_FILL, the interior of the triangle is filled.  The color COLOR
+    is used for drawing.
+
+þseealso g_clip() g_line() g_polygon()
+
+
+þfunction g_unlock() g_unlockall()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þprototype
+void g_unlock (void);
+void g_unlockall (void);
+þendprototype
+
+    Unlock the screen.  g_unlock() undoes one invocation of g_lock()
+    by decrementing the counter incremented by g_lock().  If the
+    counter reaches zero, the screen is unlocked.  If the counter
+    already was zero, the counter is not changed.  g_unlockall()
+    undoes all invocations of g_lock() by resetting the counter to
+    zero and unlocking the screen if the counter was non-zero.
+
+þseealso g_lock()
+
+
+þfunction g_vgapal()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam PAL FIRST N WAIT_FLAG
+þprototype
+void g_vgapal (const char *PAL, int FIRST, int N, int WAIT_FLAG);
+þendprototype
+
+    Set the VGA palette.  This function sets N (1 through 256) DAC
+    registers starting with register FIRST (0 through 255).  For each
+    register, 3 bytes are taken from the array pointed to by PAL: red,
+    green, blue.  Each byte should have a value between 0 and 63,
+    inclusive.  If WAIT_FLAG is non-zero, g_vgapal() waits for the
+    vertical retrace to avoid snow on the screen, see þhpt{g_waitv()}.
+    Under DOS, emx option -ai is required, see `þhpt{Using emx
+    options}'.  Under OS/2, emxio.dll is required.
+
+þseealso g_waitv() _outps8dac()
+
+
+þfunction g_vline()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam X Y0 Y1 COLOR
+þprototype
+void g_vline (int X, int Y0, int Y1, int COLOR);
+þendprototype
+
+    Draw a vertical line between (X,Y0) and (X,Y1).  The color COLOR
+    is used for drawing.
+
+þseealso g_box() g_clip() g_hline() g_line()
+
+
+þfunction g_waitv()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þprototype
+void g_waitv (void);
+þendprototype
+
+    Wait for vertical retrace.  Under DOS, emx option -ai is required,
+    see `þhpt{Using emx options}'.  Under OS/2, emxio.dll is required.
+    Note that this function eats a lot of CPU time.
+
+þseealso g_vgapal() _wait01()
+
+
+þfunction g_wmode()
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þparam WMODE
+þprototype
+void g_wmode (int WMODE);
+þendprototype
+
+    Select a `writing mode'.  This is not yet implemented.
+
+
+þfunction gcvt()
+þcompat UNIX
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam VALUE DIGITS BUFFER
+þprototype
+char *gcvt (double VALUE, int DIGITS, char *BUFFER);
+þendprototype
+
+    Convert the floating point number VALUE to a null-terminated
+    string of ASCII digits in the array pointed to by BUFFER, using
+    exponential-decimal format or floating-decimal and return a
+    pointer to BUFFER.  gcvt() produces DIGITS significant digits.
+    Trailing zeros and a trailing decimal point are removed.  The
+    array pointed to by BUFFER must be big enough for holding the
+    string.
+
+    The decimal point character of the current locale is used.
+
+    Exponential format is used if the absolute value of VALUE is less
+    than 0.1 or if the exponent is greater than or equal to DIGITS.
+
+    The empty string is stored to the array pointed to by BUFFER if
+    DIGITS is less than one.
+
+þreturnvalue
+
+    gcvt() returns BUFFER.
+
+þrestrictions
+
+    NaN and other special values are not yet handled correctly.
+
+þseealso setlocale() sprintf()
+
+
+þfunction getc()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int getc (FILE *STREAM);
+þendprototype
+
+    Read the next character (as þtt{unsigned char} converted to an
+    þtt{int}) from the input stream STREAM and advance the file
+    position indicator of the stream (if defined).  getc() is
+    equivalent to fgetc().
+
+    getc() may be implemented as macro, in contrast to fgetc().  In
+    consequence, getc() may evaluate its argument more than once.
+
+þreturnvalue
+
+    getc() returns the next character from the stream.  If the stream
+    is at end-of-file (before getc() is called), getc() sets the
+    end-of-file indicator of the stream and returns EOF.  If a read
+    error occurs, getc() sets the error indicator of the stream and
+    returns EOF.
+
+þimplementation
+
+    getc() is implemented as in-line function for single-thread
+    programs.
+
+þhints
+
+    Use getc() instead of fgetc() if you want to read a lot of
+    characters.
+
+    The argument of getc() should not be an expression with side
+    effects.
+
+þseealso fgetc() getchar()
+
+
+þfunction getchar()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þprototype
+int getchar (void);
+þendprototype
+
+    getchar() is equivalent to þtt{getc (stdin)}.
+
+þreturnvalue
+
+    getchar() returns the next character from stdin.  If stdin is at
+    end-of-file (before getchar() is called), getchar() sets the
+    end-of-file indicator of stdin and returns EOF.  If a read error
+    occurs, getchar() sets the error indicator of stdin and returns
+    EOF.
+
+þimplementation
+
+    getchar() is implemented as in-line function for single-thread
+    programs.
+
+þhints
+
+    Use getchar() instead of þtt{fgetc(stdin)} if you want to read a
+    lot of characters.
+
+þseealso fgetc() getc()
+
+
+þfunction getcwd()
+þcompat POSIX.1
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam BUFFER SIZE
+þprototype
+char *getcwd (char *BUFFER, size_t SIZE);
+þendprototype
+
+    getcwd() retrieves the name of the current working directory
+    (excluding the drive name) and stores it to the array pointed to
+    by BUFFER.  It is assumed that there are SIZE bytes available at
+    BUFFER.  This includes the terminating 0.  If BUFFER is NULL, an
+    array of suitable size, but at least SIZE bytes, is allocated with
+    malloc().  getcwd() translates backslashes into forward slashes.
+    It does not translate upper-case directory names to lower case.
+
+    _getcwd() properly handles DBCS characters.
+
+þreturnvalue
+
+    If successful, getcwd() returns BUFFER, or a buffer allocated with
+    malloc() if BUFFER is NULL.  On error, getcwd() sets errno and
+    returns NULL.
+
+þerrors
+þdescription
+þitem EINVAL
+  SIZE is zero
+þitem ENOMEM
+  BUFFER is NULL and malloc() failed
+þitem ERANGE
+  BUFFER is not NULL and SIZE is positive and the length of the
+  pathname plus 1 is greater than SIZE
+þenddescription
+
+þseealso chdir() _getcwd1() _getcwd2() getwd() _nls_init()
+
+
+þfunction _getcwd1()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam BUFFER DRIVE
+þprototype
+int _getcwd1 (char *BUFFER, char DRIVE);
+þendprototype
+
+    _getcwd1() retrieves the name of the current working directory
+    (starting with a slash, excluding the drive name) of drive DRIVE
+    and stores it to the array pointed to by BUFFER.  If DRIVE is 0,
+    the currently selected drive is used.  Otherwise, DRIVE must be in
+    þtt{'A'} through þtt{'Z'}.  It is assumed that there are enough
+    bytes available at BUFFER.  _getcwd1() translates backslashes into
+    forward slashes.  It does not translate upper-case directory names
+    to lower case.
+
+    _getcwd1() properly handles DBCS characters.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso chdir() getcwd() _getcwd2() _nls_init()
+
+
+þfunction _getcwd2()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam BUFFER SIZE
+þprototype
+char *_getcwd2 (char *BUFFER, int SIZE);
+þendprototype
+
+    _getcwd2() retrieves the name of the current working directory
+    (including the drive name) and stores it to the array pointed to
+    by BUFFER.  It is assumed that there are SIZE bytes available at
+    BUFFER.  This includes the terminating 0.  If BUFFER is NULL, an
+    array of suitable size, but at least SIZE bytes, is allocated with
+    malloc().  _getcwd2() translates backslashes into forward slashes.
+    It does not translate upper-case directory names to lower case.
+
+    _getcwd2() properly handles DBCS characters.
+
+þreturnvalue
+
+    If successful, _getcwd2() returns BUFFER, or a buffer allocated
+    with malloc() if BUFFER is NULL.  On error, _getcwd2() sets errno
+    and returns NULL.
+
+þerrors
+þdescription
+þitem EINVAL
+  SIZE is zero
+þitem ENOMEM
+  BUFFER is NULL and malloc() failed
+þitem ERANGE
+  BUFFER is not NULL and SIZE is positive and the length of the
+  pathname plus 3 is greater than SIZE
+þenddescription
+
+þseealso chdir() getcwd() _getcwd1() _nls_init()
+
+
+þfunction _getdrive()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+char _getdrive (void);
+þendprototype
+
+    Get the currently selected drive.
+
+þreturnvalue
+
+    _getdrive() returns as upper-case letter the currently selected
+    drive.
+
+þseealso _chdir2() _chdrive() _getcwd2()
+
+
+þfunction getenv()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME
+þprototype
+char *getenv (const char *NAME);
+þendprototype
+
+    Find NAME in the environment.
+
+þreturnvalue
+
+    If the variable is found, getenv() returns a pointer to the
+    value.  Otherwise, getenv() returns NULL.
+
+þseealso environ putenv()
+
+
+þfunction _getext() _getext2()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam PATH
+þprototype
+char *_getext (const char *PATH);
+char *_getext2 (const char *PATH);
+þendprototype
+
+    _getext() and _getext2() return a pointer to the extension of the
+    file name pointed to by PATH.  The pointer points to the dot
+    character that starts the extension.  If there is no extension,
+    _getext() returns NULL and _getext2() returns the empty string
+    þtt{""}.  If the last member of the string pointed to by PATH
+    starts with a dot (þtt{"/usr/mattes/.profile"}, for instance),
+    _getext() returns NULL and _getext2() returns the empty string
+    þtt{""}.
+
+    _getext() and _getext2() properly handle DBCS characters.
+
+þreturnvalue
+
+    See above.
+
+þseealso _defext() _getname() _nls_init() _remext() _splitpath()
+
+
+þfunction _getname()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam PATH
+þprototype
+char *_getname (const char *PATH);
+þendprototype
+
+    Return a pointer to the name part (last component, including the
+    extension) of the file name pointed to by PATH.  The pointer
+    returned by _getname() points to the character after the last path
+    separator (slash, backslash and colon).  If there is no path
+    separator, PATH is returned.
+
+    _getname() properly handles DBCS characters.
+
+þreturnvalue
+
+    See above.
+
+þseealso _getext() _nls_init() _remext() _splitpath()
+
+þsamplecode
+int main (int argc, char *argv[])
+{
+  argv[0] = _getname (argv[0]);   /* Remove pathname */
+  ...
+}
+þendsamplecode
+
+
+þfunction getopt()
+þcompat POSIX.2
+þheaders
+#include <unistd.h>     /* without extensions */
+#include <getopt.h>     /* with extensions */
+þendheaders
+
+þparam ARGC ARGV OPT_STR
+þprototype
+int getopt (int ARGC, char **ARGV, const char *OPT_STR);
+þendprototype
+
+    Parse command line options.  ARGC is the number of argument
+    strings, ARGV points to an array of pointers to argument strings,
+    OPT_STR points to a string describing the available options.
+    Typically, the ARGC and ARGV arguments of main() are passed to
+    getopt().  Each option is of one of the following types:
+
+þitemize
+þitem
+
+    option without argument: the option letter is listed in the string
+    pointed to by OPT_STR;
+
+þitem
+
+    option with mandatory argument: the option letter in the string
+    pointed to by OPT_STR is followed by a colon
+
+þitem
+
+    option with optional argument: the option letter in the string
+    pointed to by OPT_STR is followed by two colons.
+
+þenditemize
+
+    For instance,
+
+þexample
+c = getopt (argc, argv, "abc:d::v");
+þendexample
+
+    defines five options: -a, -b, -c and -v don't take arguments, -c
+    takes a mandatory argument, -d takes an optional argument.
+
+    Before the first call to getopt(), the global variable optind must
+    be set to 0 (that's the initial value, see also bugs below).
+    Calling getopt() parses the next command line option.  If there
+    are no more command line options, getopt() returns -1.  After
+    calling getopt(), optind is the index of the next command line
+    argument.  After calling getopt(), the global variable optarg
+    points to the argument of the option.  If there is no argument,
+    optarg is NULL.
+
+    There are three modes of operation, which are controlled by the
+    global variable optmode declared in <getopt.h>:
+
+þdescription
+þitem GETOPT_UNIX
+
+    Options are at the start of the command line.  When the first
+    non-option is reached, parsing options stops and getopt() returns
+    -1.  GETOPT_UNIX is the default.
+
+þitem GETOPT_ANY
+
+    Options may appear anywhere on the command line.  ARGV is
+    reordered to move the non-options to the end.  When there are no
+    more options, getopt() returns -1.  The remaining arguments are
+    all the arguments of the command line which are not options.
+
+þitem GETOPT_KEEP
+
+    Options may appear anywhere on the command line.  If the current
+    argument is not an option, getopt() returns 0.  optarg will point
+    to the argument.  The next call to getopt() examines the next
+    command line argument.
+
+þenddescription
+
+    The behavior on error (invalid option or missing argument) depends
+    on the global variable opterr (which is non-zero unless set by the
+    application) and the first character of the string pointed to by
+    OPT_STR: If the global variable opterr is non-zero and the first
+    character of the string pointed to by OPT_STR is not a colon,
+    getopt() writes an appropriate error message to stderr and returns
+    þtt{'?'} or þtt{':'}.  If opterr is zero and the first character
+    of the string pointed to by OPT_STR is not a colon, getopt() does
+    not display an error message and returns þtt{'?'}.  If the first
+    character of the string pointed to by OPT_STR is a colon, getopt()
+    does not display an error message and returns þtt{'?'} or
+    þtt{':'}.  In all cases, the global variable optopt is set to the
+    character code of the option which caused the error.  The error
+    message includes the program name which is taken from
+    þpa{ARGV}þtt{[0]}.
+
+    The global variable optswchar declared in <getopt.h> is a string of
+    characters which start options.  The default value is þtt{"-"},
+    that is, options are started by hyphens.  You might want to assign
+    þtt{"-/"} or þtt{"/"} to optswchar.
+
+    If a command line argument consists of two equal switch characters
+    (see optswchar), the remaining command line arguments are not
+    treated as options.
+
+    Options may be clustered, that is, if an option does not take an
+    argument, getopt() treats the following character of the same
+    command line argument as option.  If an option takes a mandatory
+    argument, the argument either follows immediately the option or is
+    taken from the next command line argument.  If an option takes an
+    optional argument, the argument must immediately follow the
+    option.
+
+    When writing portable programs, you should not use optmode,
+    optswchar and options taking optional arguments.  Only letters
+    should be used as options.
+
+    optmode must not be changed after the first call to getopt().
+    optswchar, however, may be changed at any time.
+
+þreturnvalue
+
+    getopt() returns the next option character.  If there are no more
+    command line options, -1 is returned (note that the value of the
+    EOF macro defined in <stdio.h> is -1).  If an invalid option is
+    encountered, þtt{'?'}  is returned.  If an argument is missing for
+    an option which requires an argument, þtt{':'} (if the first
+    character of the string pointed to by OPT_STR is a colon) or
+    þtt{'?'} (if the first character of the string pointed to by
+    OPT_STR is not a colon) is returned.  If optmode is GETOPT_KEEP
+    and the current command line argument is not an option, 0 is
+    returned.
+
+þimplementation
+
+    The variables optswchar and optmode are extensions.  Both are
+    declared in <getopt.h> but not in <unistd.h>.  Optional arguments
+    (two colons) are an extension.
+
+    To reinitialize getopt(), that is, to restart parsing options, set
+    optind to zero.
+
+þbugs
+
+    For POSIX.2, the ARGV argument should be a þtt{const} pointer;
+    however, GETOPT_ANY reorders the array pointed to by ARGV.
+
+þseealso main() _swchar()
+
+
+þfunction getpagesize()
+þcompat BSD
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+int getpagesize (void);
+þendprototype
+
+    Return the page size, which is 4096 for the 386.
+
+þreturnvalue
+
+    getpagesize() returns the page size.
+
+
+þfunction getpass()
+þcompat UNIX
+þheaders
+#include <pwd.h>
+#include <unistd.h>
+þendheaders
+
+þparam PROMPT
+þprototype
+char *getpass (const char *PROMPT);
+þendprototype
+
+    Print the string pointed to by PROMPT on stderr and read a
+    password from the keyboard device without echoing.  Up to
+    _PASSWORD_LEN (which is 128, defined in <pwd.h>) characters can be
+    entered.
+
+þreturnvalue
+
+    getpass() returns a pointer to a statically allocated buffer.  The
+    string will be null-terminated.
+
+þseealso _getpass1() _getpass2()
+
+þfunction _getpass1() _getpass2()
+þcompat emx
+þheaders
+#include <pwd.h>
+#include <unistd.h>
+þendheaders
+
+þparam PROMPT KBD
+þprototype
+char *_getpass1 (const char *PROMPT);
+char *_getpass2 (const char *PROMPT, int KBD);
+þendprototype
+
+    Print the string pointed to by PROMPT on stderr and read a
+    password from the keyboard device or from standard input without
+    echoing.  Up to _PASSWORD_LEN (which is 128, defined in <pwd.h>)
+    characters can be entered.
+
+    _getpass1() reads from the keyboard device if standard input is
+    associated with the console.  Otherwise, _getpass1() reads from
+    standard input.
+
+    _getpass2() reads from the keyboard device if KBD is non-zero.
+    _getpass2() reads from standard input if KBD is zero.
+
+þreturnvalue
+
+    _getpass1() and _getpass2() return a pointer to a statically
+    allocated buffer.  The buffer is shared by getpass(), _getpass1(),
+    and _getpass2().  The string will be null-terminated.
+
+þhints
+
+    Use _getpass2() passing zero for KBD if the application should
+    work correctly with pseudo ttys (ptys).
+
+þseealso getpass()
+
+
+þfunction getpid()
+þcompat UNIX
+þheaders
+#include <process.h>
+þendheaders
+
+þprototype
+int getpid (void);
+þendprototype
+
+    Get the process identification number of the calling process.
+
+þreturnvalue
+
+    getpid() returns the process identification number of the calling
+    process.
+
+þseealso getppid() _gettid()
+
+
+þfunction getppid()
+þcompat UNIX
+þheaders
+#include <process.h>
+þendheaders
+
+þprototype
+int getppid (void);
+þendprototype
+
+    Get the process identification number of the parent process of
+    the calling process.
+
+þreturnvalue
+
+    getppid() returnes the process identification number of the parent
+    process of the calling process.
+
+þseealso getpid()
+
+
+þfunction getpwent() getpwuid() getpwnam() setpwent() endpwent()
+þcompat UNIX
+þheaders
+#include <pwd.h>
+þendheaders
+
+þparam UID NAME
+þprototype
+struct passwd *getpwent (void);
+struct passwd *getpwuid (int UID);
+struct passwd *getpwnam (char *NAME);
+void setpwent (void);
+void endpwent (void);
+þendprototype
+
+    Dummy functions.
+
+þseealso cuserid()
+
+
+þfunction gets()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUFFER
+þprototype
+char *gets (char *BUFFER);
+þendprototype
+
+    Read a string from stdin to the array pointed to by BUFFER.  Stop
+    after a newline (LF) character has been read.  The newline
+    character is replaced with a null character.  Use fgets() instead
+    as gets() doesn't know how big the array pointed to by BUFFER is.
+
+þreturnvalue
+
+    gets() returns BUFFER.  If an error occurs or the end of the file
+    is reached, gets() returns NULL.
+
+þseealso fgets() scanf()
+
+
+þfunction _getsockhandle()
+þcompat emx *
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int _getsockhandle (int HANDLE);
+þendprototype
+
+    Return the internal socket handle associated with socket handle
+    HANDLE.  As emx.dll maps socket handles internally, you cannot
+    pass handles directly to IBM TCP/IP for OS/2 functions.  Use
+    _getsockhandle() to retrieve the internal socket handle (for IBM
+    TCP/IP for OS/2) of a socket handle.  Internal socket handles can
+    be used with IBM TCP/IP for OS/2 functions, only.  Note that you
+    cannot use socket handles and internal socket handles with OS/2
+    API functions such as DosRead.
+
+    You have to link with the þtt{socket} library (use the -lsocket
+    option).
+
+þreturnvalue
+
+    _getsockhandle() returns an internal socket handle.  On error,
+    _getsockhandle() sets errno and returns -1.
+
+þrestrictions
+
+    _getsockhandle() is implemented for OS/2 only.
+
+    _getsockhandle() is not available with the system call library
+    sys.lib (þhpt{-Zsys}).
+
+þhints
+
+    _getsockhandle() can be used with _impsockhandle() to pass socket
+    handles down to child processes.  See þhpt{_impsockhandle()} for
+    details.
+
+þseealso _impsockhandle()
+
+
+þfunction _gettid()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+int _gettid (void);
+þendprototype
+
+    Get the thread identification number of the calling thread.
+
+þreturnvalue
+
+    _gettid() returns the thread identification number of the calling
+    thread.  Under DOS, _gettid() always returns 1.
+
+þseealso _beginthread() getpid() _threadid _threadstore()
+
+
+þfunction _getvol()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DRIVE
+þprototype
+char *_getvol (char DRIVE);
+þendprototype
+
+    Retrieve the volume label of the drive DRIVE.  DRIVE must be zero
+    (for retrieving the volume label of the currently selected drive)
+    or in þtt{'A'} through þtt{'Z'} or in þtt{'a'} through þtt{'z'}.
+
+þreturnvalue
+
+    If successful, _getvol() returns a pointer to a statically
+    allocated string of up to 11 characters containing the volume
+    label.  That string will be overwritten by the next call to
+    _getvol().  On error, _getvol() returns NULL.
+
+
+þfunction getw()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int getw (FILE *STREAM);
+þendprototype
+
+    Read a word (þtt{int}) from STREAM.  Avoid using this function.
+
+þreturnvalue
+
+    getw() returns the word read.  On error, getw() returns -1.  As -1
+    is also a possible word value, you have to use ferror() to
+    recognize an error condition.
+
+þseealso putw() fwrite()
+
+
+þfunction getwd()
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam BUFFER
+þprototype
+char *getwd (char *BUFFER);
+þendprototype
+
+    getwd() retrieves the name of the current working directory
+    (excluding the drive name) and stores it to the array pointed to
+    by BUFFER.  It is assumed that there are MAXPATHLEN bytes
+    available at BUFFER.  This includes the terminating 0.  MAXPATHLEN
+    is defined in <sys/param.h>.  getwd() translates backslashes into
+    forward slashes.  It does not translate upper-case directory names
+    to lower case.
+
+    getwd() properly handles DBCS characters.
+
+þreturnvalue
+
+    If successful, getwd() returns BUFFER.  On error, getwd() copies
+    an error message to BUFFER and returns NULL.
+
+þseealso getcwd() _nls_init()
+
+
+þfunction gettimeofday()
+þcompat BSD
+þheaders
+#include <sys/time.h>
+þendheaders
+
+þparam TP TZP
+þprototype
+int gettimeofday (struct timeval *TP, struct timezone *TZP);
+þendprototype
+
+    Obtain the current time and timezone.  If TP is not NULL, the
+    current Coordinated Universal Time (UTC, GMT), expressed in
+    seconds and microseconds since 00:00 1-Jan-1970, is stored to *TP.
+    If TZP is not NULL, information about the timezone is stored to
+    *TZP.
+
+    The þtt{timeval} structure is defined as follows:
+
+þexample
+struct timeval
+{
+  long tv_sec;
+  long tv_usec;
+};
+þendexample
+
+    þtt{tv_sec} and þtt{tv_usec} are the number of seconds and
+    microseconds, respectively, elapsed since 00:00:00 1-Jan-1970
+    Coordinated Universal Time (UTC, GMT).
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso ftime() settimeofday() time()
+
+
+þfunction glob() globfree()
+þcompat POSIX.2
+þheaders
+#include <glob.h>
+þendheaders
+
+þparam PATTERN FLAGS ERRFUNC EPATH EERRNO PGLOB
+þprototype
+int glob (const char *PATTERN, int FLAGS,
+          int (*ERRFUNC)(const char *EPATH, int EERRNO), glob_t *PGLOB);
+void globfree (glob_t *PGLOB);
+þendprototype
+
+    The glob() function generates pathnames matching PATTERN.  The
+    value of FLAGS is the bitwise OR of zero or more of the following
+    flags:
+
+þdescription
+þitem GLOB_APPEND
+
+    Append new pathnames to the ones generated by a previous call of
+    glob().  When calling glob() with GLOB_APPEND, glob() must have
+    been called without GLOB_APPEND for the structure pointed to by
+    PGLOB and the members of that structure must have the same values
+    as after the previous call to glob().  Moreover, the GLOB_DOOFFS
+    bit of FLAGS must have the same value as for the previous call of
+    glob().
+
+þitem GLOB_DOOFFS
+
+    Add null pointers at the beginning of PGLOBþtt{->gl_pathv}.  The
+    number of null pointers is specified by PGLOBþtt{->gl_offs}.  If
+    GLOB_APPEND is set, the number of null pointers is not changed.
+
+þitem GLOB_ERR
+
+    Return when a non-readable directory is encountered.  If GLOB_ERR
+    is not set, glob() ignores non-readable directories.
+
+þitem GLOB_MARK
+
+    Append a slash to pathnames that are directories.
+
+þitem GLOB_NOESCAPE
+
+    Do not treat backslash as an escape character.  If GLOB_NOESCAPE
+    is not set, backslash can be used to remove the special meaning
+    from special characters such as` þtt{*}' and `þtt{[}'.
+
+þitem GLOB_NOCHECK
+
+    If PATTERN does not match any pathname, add PATTERN to
+    PGLOBþtt{->gl_pathv}.  If PATTERN does not match any pathname and
+    GLOB_NOCHECK is not set, glob() returns an error.
+
+þitem GLOB_NOSORT
+
+    Do not sort the pathnames.  If GLOB_NOSORT is not set, the
+    pathnames added by this call of glob() are sorted according to
+    strcoll().
+
+þitem GLOB_PERIOD
+
+    Also include pathnames that have a component starting with a
+    period.  If GLOB_PERIOD is not set, those pathnames are excluded.
+
+þenddescription
+
+    If a non-readable directory is encountered and ERRFUNC is not a
+    null pointer, ERRFUNC will be called with EPATH pointing to the
+    pathname of the non-readable directory and EERRNO set to the errno
+    value.  If ERRFUNC returns a non-zero value, glob() will stop the
+    scan and return GLOB_ABEND.  If ERRFUNC returns zero, the behavior
+    depends on GLOB_ERR.
+
+    PGLOB points to a structure of type glob_t which is defined as
+    follows:
+
+þexample
+typedef struct
+{
+  size_t gl_pathc;
+  char **gl_pathv;
+  size_t gl_offs;
+  /* Members used internally are not shown here */
+} glob_t;
+þendexample
+
+    The gl_pathc member contains the number of pathnames matched by
+    PATTERN.  If gl_pathc is zero, the value of gl_pathv is undefined.
+    gl_pathv contains a pointer to an array of pointers to pathnames:
+    If GLOB_DOOFFS is set, the array starts with gl_offs null
+    pointers.  If GLOB_DOOFFS is not set, gl_offs is ignored (treated
+    as zero).  Following these null pointers (if any), glob() stores
+    gl_pathc pointers to pathnames.  A null pointer follows the last
+    pathname.
+
+    The characters `þtt{?}', `þtt{*}', and `þtt{[]}' are interpreted
+    as wildcard characters in the pattern.  `þtt{?}' matches one
+    character, `þtt{*}' matches zero or more characters.  `þtt{[]}'
+    matches the set of characters listed between the brackets, ranges
+    (such as `þtt{[0-9]}') are allowed.  If the first character after
+    `þtt{[}' is `þtt{!}', all characters þem{not} in the set match the
+    set.
+
+    globfree() deallocates any memory allocated by glob() for the
+    structure pointed to by PGLOB.  glob() must have been called for
+    the structure pointed to by PGLOB and the members of that
+    structure must have the same values as after the last call to
+    glob().
+
+þreturnvalue
+
+    glob() returns one of the following values:
+
+þdescription
+þitem 0
+    Success
+þitem GLOB_ABEND
+    The operation of glob() was stopped for a non-readable directory
+    because GLOB_ERR was set or ERRFUNC returned a non-zero value
+þitem GLOB_NOMATCH
+    No pathname matching PATTERN found
+þitem GLOB_NOSPACE
+    Out of memory
+þenddescription
+
+  Even if glob() returns a non-zero value, gl_pathc and gl_pathv of
+  the structure pointed to by PGLOB are set.
+
+þimplementation
+
+    If the first character after `þtt{[}' is `þtt{^}', all characters
+    þem{not} in the set match the set.
+
+þseealso _fnexplode() fnmatch() strcoll() _wildcard()
+
+
+þfunction gmtime()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þparam T
+þprototype
+struct tm *gmtime (const time_t *T);
+þendprototype
+
+    Convert the number of seconds elapsed since 00:00:00 1-Jan-1970
+    Coordinated Universal Time (UTC, GMT) in the variable pointed to
+    by T to a time and date structure (UTC) and return a pointer to
+    the structure.  gmtime(), mktime() and localtime() use the same
+    memory location, therefore the values are overwritten if one of
+    these functions is called.
+
+þreturnvalue
+
+    gmtime() returns a pointer to a structure.
+
+þseealso asctime() ctime() localtime() mktime() time()
+
+
+þfunction _heapchk()
+þcompat PC
+þheaders
+#include <malloc.h>
+þendheaders
+
+þprototype
+int _heapchk (void);
+þendprototype
+
+    _heapchk() checks the default heap and the tiled default heap and
+    all their blocks for consistency.  Note that _heapchk() may crash
+    if the heap is corrupted.  _heapchk() can help debugging programs
+    which experience heap problems.
+
+þreturnvalue
+
+    _heapchk() returns one of the following values:
+þdescription
+þitem _HEAPBADBEGIN
+    The heap is corrupted.
+þitem _HEAPBADEND
+    The heap is corrupted.
+þitem _HEAPBADNODE
+    A block of the heap is damaged or the heap is corrupted.
+þitem _HEAPEMPTY
+    The heap has not been initialized.
+þitem _HEAPOK
+    The heap seems to be consistent.
+þenddescription
+
+þseealso _udefault() _heapset() _uheapchk() _utdefault()
+
+
+þfunction _heapmin()
+þcompat VAC++
+þheaders
+#include <malloc.h>
+þendheaders
+
+þprototype
+int _heapmin (void);
+þendprototype
+
+    The _heapmin() function returns unused memory of the default
+    regular heap to the operating system.  The heap is never made
+    smaller than its initial size.  Calling _heapmin() is equivalent
+    to calling _uheapmin() for the default heap.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso brk() _heapchk() sbrk() _theapmin() _udefault() _uheapmin()
+
+
+þfunction _heapset()
+þcompat PC
+þheaders
+#include <malloc.h>
+þendheaders
+
+þparam FILL
+þprototype
+int _heapset (unsigned FILL);
+þendprototype
+
+    _heapset() fills all bytes of all unused blocks of the default
+    heap and the tiled default heap with FILL.  Note that _heapset()
+    may crash if the heap is corrupted.  _heapset() can help debugging
+    programs which erroneously depend on the contents of dynamically
+    allocated blocks.  þhpt{_heapchk()} checks the heap more
+    thoroughly than _heapset().
+
+þreturnvalue
+
+    _heapset() returns one of the following values:
+þdescription
+þitem _HEAPBADBEGIN
+    The heap is corrupted.
+þitem _HEAPBADEND
+    The heap is corrupted.
+þitem _HEAPBADNODE
+    A block of the heap is damaged or the heap is corrupted.
+þitem _HEAPEMPTY
+    The heap has not been initialized.
+þitem _HEAPOK
+    The heap seems to be consistent.
+þenddescription
+
+þseealso _udefault() _heapchk() _uheapset() _utdefault()
+
+
+þfunction _heap_walk() _uheap_walk()
+þcompat VAC++
+þheaders
+#include <malloc.h>     /* for _heap_walk() */
+#include <umalloc.h>    /* for _uheap_walk() */
+þendheaders
+
+þparam H CALLBACK
+þparam BLOCK SIZE FLAG STATUS FNAME LINENO
+þprototype
+int _heap_walk (int (*CALLBACK)(const void *, size_t, int, int,
+                                const char *, size_t));
+int _uheap_walk (Heap_t H, int (*CALLBACK)(const void *, size_t, int, int,
+                                           const char *, size_t));
+þendprototype
+
+    _heap_walk() applies the function pointed to by CALLBACK to all
+    free and used blocks of the default heap and the tiled default
+    heap.
+
+    _uheap_walk() applies the function pointed to by CALLBACK to all
+    free and used blocks of the heap H.
+
+    Note that the heap is locked, so using the heap in the callback
+    function will cause a deadlock.
+
+þindent
+    þtt{int my_walker (const void *}BLOCKþtt{, size_t }SIZEþtt{, int }FLAGþtt{,} þbreak
+    þtt{               int }STATUSþtt{, const char *}FNAMEþtt{, size_t }LINENOþtt{);}
+þendindent
+
+    BLOCK points to a block of SIZE bytes.  FLAG is either _USEDENTRY
+    (for a used block) or _FREEENTRY (for a free block).  STATUS is
+    one of the following values, describing the status of the block:
+
+þdescription
+þitem _HEAPBADBEGIN
+    The heap is corrupted.
+þitem _HEAPBADEND
+    The heap is corrupted.
+þitem _HEAPBADNODE
+    The block is damaged.
+þitem _HEAPEMPTY
+    The heap has not been initialized.
+þitem _HEAPOK
+    The heap seems to be consistent (_HEAPOK is 0).
+þenddescription
+
+    FNAME points to the file name of the source file in which the
+    block has been allocated.  LINENO is the line number in which the
+    block has been allocated.  FNAME is NULL if that information is
+    not available, that is, if the object has not been allocated with
+    a debugging heap function.
+
+
+þreturnvalue
+
+    _heap_walk() and _uheap_walk() return the last status (see above
+    for a list of values) unless the callback function returned a
+    non-zero value.  If the callback function returned a non-zero
+    value, _heap_walk() and _uheap_walk() return that value.
+
+þrestrictions
+
+    FNAME is current always NULL as there are no debugging heap
+    functions.
+
+þhints
+
+    Use an extra heap if you want to allocate memory in the callback
+    function.
+
+þseealso _heapchk() _udefault() _uheapchk() _uheap_walk2()
+
+þsamplecode
+#include <stdio.h>
+#include <malloc.h>
+#include <umalloc.h>
+
+static int walk_dump (const void *obj, size_t size, int flag,
+                      int status, const char *fname, size_t lineno)
+{
+  if (status == _HEAPOK)
+    printf ("0x%.8lx 0x%.8lx %s\n",
+            (unsigned long)obj, (unsigned long)size,
+            flag == _FREEENTRY ? "free" : "used");
+  return status;
+}
+
+int main (void)
+{
+  void *p;
+
+  /* Avoid deadlock due to buffer allocation in printf()! */
+  setvbuf (stdout, NULL, _IOLBF, BUFSIZ);
+
+  p = malloc (1000);
+  malloc (2000);
+  free (p);
+  _heap_walk (walk_dump);
+  return 0;
+}
+þendsamplecode
+
+
+þfunction hypot() hypotl()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X Y
+þprototype
+double hypot (double X, double Y);
+long double hypotl (long double X, long double Y);
+þendprototype
+
+    Compute and return
+
+þtypewriter
+  sqrt (þpa{X}*þpa{X} + þpa{Y}*þpa{Y})
+þendtypewriter
+
+    On overflow, +INF is returned and errno is set to ERANGE.
+
+    hypotl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    See above.
+
+þseealso sqrt()
+
+
+þfunction _imphandle()
+þcompat emx
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int _imphandle (int HANDLE);
+þendprototype
+
+    Register an OS/2 file handle (created by DosOpen, for instance)
+    with the emx run-time system.  Without importing an OS/2 file
+    handle with _imphandle() into the emx run-time system, that handle
+    cannot be used with any C library function.  If necessary,
+    _imphandle() relocates the file handle (this happens when sockets
+    are used).  After calling _imphandle(), you can use the returned
+    file handle both with library functions and OS/2 API functions,
+    and HANDLE can no longer be used (unless identical to the handle
+    returned).  _imphandle() must not be called for file handles not
+    created by an OS/2 API function.  _imphandle() must not be called
+    for socket handles.  Handles inherited from the parent process are
+    already registered with the emx run-time system.
+
+þreturnvalue
+
+    _imphandle() returns a file handle.  On error, _imphandle() sets
+    errno and returns -1.
+
+þseealso dup() _impsockhandle() open()
+
+
+þfunction _impsockhandle()
+þcompat emx
+þheaders
+#include <sys/socket.h>
+þendheaders
+
+þparam HANDLE RESERVED
+þprototype
+int _impsockhandle (int HANDLE, int RESERVED);
+þendprototype
+
+    Register a socket handle of IBM TCP/IP with the emx run-time
+    system.  HANDLE is the socket handle.  It must not be an emx
+    socket handle.  To obtain the IBM TCP/IP socket handle of an emx
+    socket handle, use þhpt{_getsockhandle()}.  RESERVED must be zero.
+
+    You have to link with the þtt{socket} library (use the -lsocket
+    option).
+
+þreturnvalue
+
+    _impsockhandle() returns a file handle.  On error,
+    _impsockhandle() sets errno and returns -1.
+
+þrestrictions
+
+    _getsockhandle() is implemented for OS/2 only.
+
+    _impsockhandle() is not available with the system call library
+    sys.lib (þhpt{-Zsys}).
+
+þhints
+
+    _getsockhandle() and _impsockhandle() can be used to pass down
+    socket handles to child processes.  Call _getsockhandle() in the
+    parent process, pass the value returned by _getsockhandle() to the
+    child process (on the command line, for instance), and call
+    _impsockhandle() on that value in the child process.  Do not close
+    the socket in the parent process until the child process has
+    called _impsockhandle() for that socket (use a semaphore if the
+    child process is run asynchronously)!  Note that socket handles
+    are automatically inherited across fork(), therefore
+    _impsockhandle() must not be used with fork().
+
+þseealso _getsockhandle() _imphandle()
+
+
+þfunction index()
+þcompat BSD
+þheaders
+#include <strings.h>
+þendheaders
+
+þparam STRING C
+þprototype
+char *index (const char *STRING, int C);
+þendprototype
+
+    Return a pointer to the first occurrence of the character C in the
+    null-terminated string pointed to by STRING.  If there is no
+    character C in that string, NULL is returned.  If C is the null
+    character (0), a pointer to the terminating null character of that
+    string is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso rindex() strchr()
+
+
+þfunction _inp8() _inp16() _inp32()
+þcompat emx *
+þheaders
+#include <sys/hw.h>
+þendheaders
+
+þparam PORT
+þprototype
+unsigned _inp8 (unsigned PORT);
+unsigned _inp16 (unsigned PORT);
+unsigned _inp32 (unsigned PORT);
+þendprototype
+
+    These functions read a single byte or word from a hardware port.
+    _inp8() reads a byte from PORT, _inp16() reads a 16-bit word from
+    PORT, _inp32() reads a 32-bit word from PORT.
+
+    You have to call _portaccess() first to enable access to a range
+    of ports.  To make your program work under DOS, you have to use
+    emx option -ai, see `þhpt{Using emx options}'.  Under OS/2, your
+    program requires emxio.dll in a directory listed in LIBPATH.
+
+þreturnvalue
+
+    _inp8(), _inp16() and _inp32() return the value read from PORT.
+
+þseealso _portaccess() _inps8() _outp8() _wait0()
+
+
+þfunction _inps8() _inps16() _inps32()
+þcompat emx *
+þheaders
+#include <sys/hw.h>
+þendheaders
+
+þparam PORT DST COUNT
+þprototype
+void _inps8 (unsigned PORT, unsigned char *DST, unsigned COUNT);
+void _inps16 (unsigned PORT, unsigned short *DST, unsigned COUNT);
+void _inps32 (unsigned PORT, unsigned long *DST, unsigned COUNT);
+þendprototype
+
+    These functions read multiple bytes or words from a hardware port.
+    _inps8() reads COUNT bytes from PORT to the array pointed to by
+    DST.  _inps16() reads COUNT 16-bit words from PORT to the array
+    pointed to by DST.  _inps32() reads COUNT 32-bit words from PORT
+    to the array pointed to by DST.
+
+    The COUNT argument of _inps8() must not exceed 65535.
+
+    The array pointed to by DST of _inps16() must be aligned on a
+    16-bit boundary, that is, the address must be even.  COUNT must
+    not exceed 32768.
+
+    The array pointed to by DST of _inps32() must be aligned on a
+    32-bit boundary, that is, the address must be a multiple of four.
+    COUNT must not exceed 65536.
+
+    You have to call _portaccess() first to enable access to a range
+    of ports.  To make your program work under DOS, you have to use
+    emx option -ai, see `þhpt{Using emx options}'.  Under OS/2, your
+    program requires emxio.dll in a directory listed in LIBPATH.
+
+þseealso _portaccess() _inp8() _outps8()
+
+
+þfunction _int86()
+þcompat PC
+þheaders
+#include <dos.h>
+þendheaders
+
+þparam INT_NUM INP_REGS OUT_REGS
+þprototype
+int _int86 (int INT_NUM, const union REGS *INP_REGS, union REGS *OUT_REGS);
+þendprototype
+
+    Issue a software interrupt under DOS.  This function loads the
+    processor registers EAX, EBX, ECX, EDX, ESI and EDI from INP_REGS,
+    calls software interrupt INT_NUM and stores the processor
+    registers EAX, EBX, ECX, EDX, ESI, EDI and the flags register to
+    OUT_REGS.
+
+    emx option -ac must be used to enable _int86().  If -ac is not
+    used, a protection violation exception occurs when _int86() is
+    called.  See `þhpt{Using emx options}'.
+
+þreturnvalue
+
+    _int86() returns the value of the EAX register.
+
+þrestrictions
+
+    _int86() is not supported under OS/2 (there are no software
+    interrupts under OS/2).  Calling _int86() under OS/2 results in a
+    protection violation.
+
+    The emx DOS extender currently supports only interrupts 0x10,
+    0x11, 0x14, 0x16, 0x17, 0x21 and 0x33.  Please note the following
+    difference to DOS C compilers: the REGS union does not contain an
+    þtt{x.cflag} field.  The complete flags register is stored to the
+    þtt{e.eflags} field instead.  The carry flag is available in bit 0
+    of the þtt{e.eflags} and þtt{x.flags} fields.
+
+    The following functions of interrupt 0x10 (video) are supported
+    (the AH register contains the function number):
+
+þindent
+
+        0x00-0x0f, 0x10 (only subfunctions which don't involve
+        pointers), 0x13, 0x1a, 0x40-0x4e (Hercules GRAFIX), 0x4f
+        (VESA, subfunction AL=0x06 not supported), 0x6f, 0xf0, 0xf1,
+        0xf6
+
+þendindent
+
+    The following functions of interrupt 0x21 (DOS call) are supported
+    (the AH register contains the function number):
+
+þindent
+
+        0x01-0x0c, 0x0e, 0x19, 0x2a-0x2e, 0x30, 0x33, 0x36-0x37,
+        0x39-0x47, 0x4b-0x4f, 0x54, 0x56, 0x57, 0x5a, 0x5b
+
+þendindent
+
+    The following functions of interrupt 0x33 (mouse) are supported
+    (the AX register contains the function number):
+
+þindent
+
+        0x00-0x0b, 0x0d-0x13, 0x15, 0x1a-0x28, 0x2a, 0x2f-0x32, 0x35
+
+þendindent
+
+    No pointer conversion is done for interrupts 0x11, 0x14, 0x16 and
+    0x17.  That is, you cannot use functions which involve pointers to
+    buffers in memory.
+
+þsamplefile /emx/test/int10.c
+
+
+þfunction ioctl()
+þcompat SysV *
+þheaders
+#include <sys/ioctl.h>
+#include <sys/termio.h>   /* for System V terminal interface */
+#include <sys/kbdscan.h>  /* optional, for extended scan codes */
+þendheaders
+
+þparam HANDLE REQUEST INT_ARG PTR_ARG TIO
+þprototype
+int ioctl (int HANDLE, int REQUEST, int INT_ARG);
+int ioctl (int HANDLE, int REQUEST, void *PTR_ARG);
+int ioctl (int HANDLE, int REQUEST, struct termio *TIO);
+þendprototype
+
+    Device control for HANDLE.  REQUEST codes are:
+
+þdescription
+þitem TCGETA
+
+    Get the parameters associated with the terminal HANDLE and store
+    them in the object pointed to by TIO.  See also `þhpt{General
+    terminal interface}'.
+
+þitem TCSETA
+
+    Immediately set the parameters associated with the terminal HANDLE
+    from the object pointed to by TIO.  See also `þhpt{General
+    terminal interface}'.
+
+þitem TCSETAF
+
+    Set the parameters associated with the terminal HANDLE from the
+    object pointed to by TIO after waiting for the output to drain and
+    after fglusing the input queue.  See also `þhpt{General terminal
+    interface}'.
+
+þitem TCSETAW
+
+    Set the parameters associated with the terminal HANDLE from the
+    object pointed to by TIO after waiting for the output to drain.
+    See also `þhpt{General terminal interface}'.
+
+þitem TCFLSH
+
+    Flush the terminal queues.  If INT_ARG is 0, the input queue is
+    flushed; if INT_ARG is 1, the output queue is flushed; if INT_ARG
+    is 2, both the input and output queues are flushed.  Works only if
+    HANDLE refers to the keyboard.  Only flushing the keyboard queue
+    is implemented.
+
+þitem TCSBRK
+
+    Wait for output to drain and then send a break. The length of the
+    break depends on INT_ARG.  Currently ignored.  It is not yet
+    specified how the length of the break depends on INT_ARG.
+
+þitem TCXONC
+
+    flow control, depending on INT_ARG.  Currently ignored
+
+þitem FIONREAD
+
+    Get number of available characters.  The number of available
+    characters is stored to the int pointed to by PTR_ARG.  FIONREAD
+    is implemented for the following types of handles:
+
+þitemize
+þitem
+
+    Terminal handles (keyboard) for which the general terminal
+    interface is enabled.  Note that if ICANON is set, the number of
+    characters in the keyboard buffer is returned which is not the
+    number of characters available for read(), as at least one of the
+    buffered characters (carriage return) is used for command line
+    editing
+
+þitem
+
+    Pseudo TTYs and console device implemented by xf86sup.sys
+
+þitem
+
+    Named pipes
+
+þitem
+
+    Pipes created with pipe() by programs using emx.dll
+
+þitem
+
+    Sockets
+
+þitem
+
+    All file handles under DOS (0 or 1 character available).
+
+þenditemize
+
+þitem FGETHTYPE
+
+    Get the handle type and store it to the int pointed to by
+    PTR_ARG.  See <sys/ioctl.h> for handle types (HT_FILE, for
+    instance).
+
+þenddescription
+
+    There are additional REQUESTS codes for socket handles.
+
+þreturnvalue
+
+    On error, ioctl() sets errno and returns -1.  Otherwise, ioctl()
+    returns 0 unless a different return value is defined above.
+
+þrestrictions
+
+    With the system call library sys.lib (þhpt{-Zsys}), only the
+    FGETHTYPE request is available.
+
+    The TCSBRK and TCXONC requests are currently ignored.
+
+    Under DOS, for requests TCGETA, TCSETA, TCSETAF, TCSETAW, and
+    TCFLSH, the value of the HANDLE argument must be 0.
+
+    TCFLSH is implemented for the keyboard, only.
+
+þseealso fcntl() open() read()
+
+
+þfunction isascii()
+þcompat UNIX
+þheaders
+#include <ctype.h>
+þendheaders
+
+þparam C
+þprototype
+int isascii (int C);
+þendprototype
+
+    Return a non-zero value iff C is a valid ASCII character (0
+    through 127).  isascii() can be applied to all integer values.
+    isascii() is implemented both as macro and as function.
+
+þreturnvalue
+
+    See above.
+
+þseealso isalnum()
+
+
+þfunction isalnum() isalpha() iscntrl() isdigit() isgraph() islower() isprint() ispunct() isspace() isupper() isxdigit()
+þcompat C90
+þheaders
+#include <ctype.h>
+þendheaders
+
+þparam C
+þprototype
+int isalnum (int C);
+int isalpha (int C);
+int iscntrl (int C);
+int isdigit (int C);
+int isgraph (int C);
+int islower (int C);
+int isprint (int C);
+int ispunct (int C);
+int isspace (int C);
+int isupper (int C);
+int isxdigit (int C);
+þendprototype
+
+    These functions (or macros) are used for determining the type of a
+    character, depending on the current locale.  C must be an integer
+    which is representable as þtt{unsigned char} (that is, 0 through
+    255), or equal to EOF; otherwise the behavior is undefined.  These
+    functions are implemented both as macros and as functions.
+
+    isalnum() tests for alphanumeric characters, that is, any
+    character for which isalpha() or isdigit() is true.
+
+    isalpha() tests for alphabetic characters, that is, any character
+    for which islower() or isupper() is true.  For locales other than
+    þtt{"C"}, isalpha() may also return true for characters for which
+    none of iscntrl(), isdigit(), ispunct() or isspace() is true.
+
+    iscntrl() tests for control characters.  Control characters are
+    not printing characters.
+
+    isdigit() tests for decimal digits (þtt{'0'} through þtt{'9'}).
+
+    isgraph() tests for printing characters except space (þtt{' '}),
+    that is, any character (except space) for which isprint() is true.
+
+    islower() tests for lower-case characters, that is, þtt{'a'}
+    trough þtt{'z'}.  For locales other than þtt{"C"}, islower() may
+    also return true for characters for which none of iscntrl(),
+    isdigit(), ispunct() or isspace() is true.
+
+    isprint() tests for printing characters including space (þtt{' '}).
+    Printing characters are characters which occupy one printing
+    position on a display device.
+
+    ispunct() tests for punctutation characters, that is, printing
+    characters for which isalnum() is false and which are not space
+    (þtt{' '}).
+
+    isspace() tests for white-space characters.  In locales other than
+    þtt{"C"}, isspace() may return true for characters for which
+    isalnum() is false.
+
+    isupper() tests for upper-case characters, that is, þtt{'A'}
+    trough þtt{'Z'}.  For locales other than þtt{"C"}, isupper() may
+    also return true for characters for which none of iscntrl(),
+    isdigit(), ispunct() or isspace() is true.
+
+    isxdigit() tests for hexadecimal digits (þtt{'0'} through
+    þtt{'9'}, þtt{'a'} through þtt{'f'}, and þtt{'A'} through
+    þtt{'F'}).
+
+þreturnvalue
+
+    These functions return a non-zero value if the condition is true,
+    or 0 if it is not true.
+
+þrestrictions
+
+    Currently, locale is ignored.
+
+þseealso isascii() setlocale() tolower() toupper() _tolower() _toupper()
+
+
+þfunction isatty()
+þcompat UNIX
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int isatty (int HANDLE);
+þendprototype
+
+    Returns a non-zero value if HANDLE refers to a character device.
+    Returns 0 if HANDLE does not refer to a character file (file or
+    pipe).  If there is an error, errno is set and -1 is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso _isterm() ioctl()
+
+
+þfunction isfinite()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+int isfinite (float X);
+int isfinite (double X);
+int isfinite (long double X);
+þendprototype
+
+    Determine whether X is finite (zero, subnormal, normal) or not
+    (infinite, NaN).  The argument X must be of a floating-point type.
+    Determination is based on the type of the argument.
+
+þreturnvalue
+
+    isfinite() returns a non-zero value if X is has a finite value;
+    isfinite() returns 0 otherwise.
+
+þseealso fpclassify() isnan() isnormal() signbit()
+
+
+þfunction isnan()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+int isnan (float X);
+int isnan (double X);
+int isnan (long double X);
+þendprototype
+
+    Determine whether X is a NaN.  The argument X must be of a
+    floating-point type.  Determination is based on the type of the
+    argument.
+
+þreturnvalue
+
+    isnan() returns a non-zero value if X has a NaN value; isnan()
+    returns 0 otherwise.  
+
+þseealso fpclassify() isfinite() isnormal() signbit()
+
+
+þfunction isnormal()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+int isnormal (float X);
+int isnormal (double X);
+int isnormal (long double X);
+þendprototype
+
+    Determine whether X is normal or not (zero, subnormal, infinite,
+    NaN).  The argument X must be of a floating-point type.
+    Determination is based on the type of the argument.
+
+þreturnvalue
+
+    isnormal() returns a non-zero value if X has a normal value;
+    isnormal() returns 0 otherwise.
+
+þseealso fpclassify() isfinite() isnan() signbit()
+
+
+þfunction _isterm()
+þcompat emx
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int _isterm (int HANDLE);
+þendprototype
+
+    Returns a non-zero value if HANDLE refers to the standard input
+    (keyboard) or standard output (screen) device.  Otherwise, returns
+    0.  If there is an error, errno is set and 0 is returned.
+
+    Consider using þtt{ioctl (FGETHTYPE)} instead.
+
+þreturnvalue
+
+    See above.
+
+þseealso isatty() ioctl()
+
+
+þfunction _itoa() _ltoa() _ultoa()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam VALUE STRING RADIX
+þprototype
+char *_itoa (int VALUE, char *STRING, int RADIX);
+char *_ltoa (long VALUE, char *STRING, int RADIX);
+char *_ultoa (unsigned long VALUE, char *STRING, int RADIX);
+þendprototype
+
+    Convert the number VALUE to a string using the number base RADIX
+    (between 2 and 36).  The string is stored to the array pointed to
+    by STRING.
+
+þreturnvalue
+
+    _itoa(), _ltoa() and _ultoa() return STRING.
+
+þseealso atoi() _lltoa() sprintf() strtol()
+
+
+þfunction kill()
+þcompat UNIX *
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam PID SIG
+þprototype
+int kill (int PID, int SIG);
+þendprototype
+
+    Send the signal SIG to process PID.  If PID is smaller than -1,
+    the signal is sent to process -þpa{PID} and its children.
+
+    If PID is the process ID of the process which is calling kill(),
+    the signal is sent to the main thread (thread 1) of that process
+    (unless the syscam call library is used).  Use raise() to generate
+    a signal in the current thread.
+
+    If SIG is 0, kill() checks only whether PID is valid or not.
+
+    See section þref{signal processing} for details on
+    þhpt{signal processing}.
+
+þreturnvalue
+
+    If successful, kill() returns 0.  Otherwise kill() sets errno and
+    returns -1.
+
+þerrors
+þdescription
+þitem EINVAL
+    SIG is not a valid signal number
+þitem ESRCH
+    PID is not the process ID of a process or process PID is not a
+    child process
+þenddescription
+
+þrestrictions
+
+    Only SIGKILL can be sent to arbitrary processes.
+    Only SIGINT and SIGBREAK can be sent to arbitrary child processes.
+    A process can send the other signals only to itself, see
+    þhpt{raise()}, or to other emx programs.
+
+    Checking PID by passing 0 for SIG works for child processes only.
+
+    Special treatment of þpa{PID}=0, þpa{PID}=1 and þpa{PID}=-1 is not
+    implemented.  Negative values of PID are implemented for OS/2 only
+    and work only for direct children of the caller.
+
+    When using the system call library sys.lib (þhpt{-Zsys}), a
+    process can send arbitrary signals to itself, only SIGINT and
+    SIGBREAK can be sent to only child processes, negative values of
+    PID are not allowed.  Moreover, kill() cannot be used to send a
+    signal to thread 1; the signal will be generated in the current
+    thread.
+
+þseealso pause() raise() sigaction() signal()
+
+
+þfunction labs()
+þcompat C90
+þheaders
+#include <stdlib.h>     /* use this */
+#include <math.h>       /* or this */
+þendheaders
+
+þparam N
+þprototype
+long labs (long N);
+þendprototype
+
+    Compute the absolute value of N.  In-line code is generated for
+    this function.
+
+þreturnvalue
+
+    If N is negative, labs() returns -þpa{N}.  Otherwise, labs()
+    returns N.
+
+þseealso abs() fabs()
+
+
+þfunction ldexp() ldexpl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X EXP
+þprototype
+double ldexp (double X, int EXP);
+long double ldexpl (long double X, int EXP);
+þendprototype
+
+    Compute and return X * 2 ^ EXP.  On overflow, NaN is returned and
+    errno is set to ERANGE.
+
+    ldexpl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    See above.
+
+þseealso frexp() pow()
+
+
+þfunction _lldiv() _uldiv() _ulldiv()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NUM DEN
+þprototype
+_lldiv_t _lldiv (long long NUM, long long DEN);
+_uldiv_t _uldiv (unsigned long NUM, unsigned long DEN);
+_ulldiv_t _ulldiv (unsigned long long NUM, unsigned long long DEN);
+þendprototype
+
+    Perform an integer division, dividing NUM by DEN.  The quotient
+    and the remainder are returned in the quot and rem fields,
+    respectively.
+
+    The following table shows the signs of quot and rem depending on
+    the signs of NUM and DEN for _lldiv():
+
+þexample
+NUM DEN ³ quot rem
+ÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄ
+ +   +  ³  +    +
+ +   -  ³  -    +
+ -   +  ³  -    -
+ -   -  ³  +    -
+þendexample
+
+    þbf{Note:} Do not use the -fpcc-struct-return option of GCC.
+
+þreturnvalue
+
+    _lldiv(), _uldiv() and _ulldiv() return a structure which contains
+    the quotient and the remainder in the quot and rem fields,
+    respectively.
+
+þseealso div() ldiv()
+
+
+þfunction _lltoa() _ulltoa()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam VALUE STRING RADIX
+þprototype
+char *_lltoa (long long VALUE, char *STRING, int RADIX);
+char *_ulltoa (unsigned long long VALUE, char *STRING, int RADIX);
+þendprototype
+
+    Convert the number VALUE to a string using the number base RADIX
+    (between 2 and 36).  The string is stored to the array pointed to
+    by STRING.
+
+þreturnvalue
+
+    _lltoa() and _ulltoa() return STRING.
+
+þseealso atoi() _itoa() _strtoll() _strtoull()
+
+
+þfunction localeconv()
+þcompat C90
+þheaders
+#include <locale.h>
+þendheaders
+
+þprototype
+struct lconv *localeconv (void);
+þendprototype
+
+    Return the address of a structure containing values for the
+    formatting of umeric and monetary quantities according to the
+    current locale.
+
+    The structure is defined as follows:
+
+þexample
+struct lconv
+{
+  char *decimal_point;
+  char *thousands_sep;
+  char *grouping;
+  char *int_curr_symbol;
+  char *currency_symbol;
+  char *mon_decimal_point;
+  char *mon_thousands_sep;
+  char *mon_grouping;
+  char *positive_sign;
+  char *negative_sign;
+  char int_frac_digits;
+  char frac_digits;
+  char p_cs_precedes;
+  char p_sep_by_space;
+  char n_cs_precedes;
+  char n_sep_by_space;
+  char p_sign_posn;
+  char n_sign_posn;
+};
+þendexample
+
+    If a string member points to þtt{""}, the value is not available
+    in the current locale or is of zero length.  Note that
+    þtt{decimal_point} never points to þtt{""}.  The þtt{char} members
+    are non-negative numbers.  CHAR_MAX indicates that the value is
+    not available in the current locale.
+
+    The members have the following meaning:
+
+þlist
+þitem þtt{decimal_point}
+
+    The decimal point character used for formatting numbers (which are
+    not monetary quantities).
+
+þitem þtt{thousands_sep}
+
+    The character used for separating groups of digits before the
+    decimal point in numbers (which are not monetary quantities).
+
+þitem þtt{grouping}
+
+    An array containing the sizes of the groups of digits (right to
+    left), terminated by zero (the previous size is to be used
+    repeatedly for the remainder of the digits) or CHAR_MAX (no
+    further grouping is to be performed).  This is used for numbers
+    which are not monetary quantities.
+
+þitem þtt{int_curr_symbol}
+
+    The first three characters contain the international currency
+    symbol, the fourth character (which is the last one) is the
+    character used for separating the international currency symbol
+    from the monetary quantity.
+
+þitem þtt{currency_symbol}
+
+    The local currency symbol.
+
+þitem þtt{mon_decimal_point}
+
+    The decimal point character used for formatting monetary
+    quantities.
+
+þitem þtt{mon_thousands_sep}
+
+    The character used for separating groups of digits before the
+    decimal point in monetary quantities.
+
+þitem þtt{mon_grouping}
+
+    An array containing the sizes of the groups of digits (right to
+    left), terminated by zero (the previous size is to be used
+    repeatedly for the remainder of the digits) or CHAR_MAX (no
+    further grouping is to be performed).  This is used for monetary
+    quantities.
+
+þitem þtt{positive_sign}
+
+    The string used for indicating that a monetary quantity is not
+    negative (zero or positive).
+
+þitem þtt{negative_sign}
+
+    The string used for indicating that a monetary quantity is negative.
+
+þitem þtt{int_frac_digits}
+
+    The number of digits after the decimal point in monetary
+    quantities (international format).
+
+þitem þtt{frac_digits}
+
+    The number of digits after the decimal point in monetary
+    quantities (local format).
+
+þitem þtt{p_cs_precedes}
+
+    1 or 0 if þtt{currency_symbol} respectively precedes or succeeds
+    the monetary quantity if it is not negative (zero or positive).
+
+þitem þtt{p_sep_by_space}
+
+    1 or 0 if a space respectively does or does not separate
+    þtt{currency_symbol} from a non-negative (zero or positive)
+    monetary quantity.
+
+þitem þtt{n_cs_precedes}
+
+    1 or 0 if þtt{currency_symbol} respectively precedes or succeeds
+    the monetary quantity if it is negative.
+
+þitem þtt{n_sep_by_space}
+
+    1 or 0 if a space respectively does or does not separate
+    þtt{currency_symbol} from a negative monetary quantity.
+
+þitem þtt{p_sign_posn}
+
+    A number indicating the position of þtt{positive_sign} for a
+    non-negative (zero or positive) monetary quantity:
+
+þdescription
+þitem 0
+    Parentheses surround the monetary quantity and þtt{currency_symbol}.
+þitem 1
+    The sign string precedes the quantity and þtt{currency_symbol}.
+þitem 2
+    The sign string succeeds the quantity and þtt{currency_symbol}.
+þitem 3
+    The sign string immediately precedes þtt{currency_symbol}.
+þitem 4
+    The sign string immediately succeeds þtt{currency_symbol}.
+þenddescription
+
+þitem þtt{n_sign_posn}
+
+    A number indicating the position of þtt{positive_sign} for a
+    negative monetary quantity.  See þtt{p_sign_posn} for a
+    description of the values.
+
+þendlist
+
+þreturnvalue
+
+    localeconv() returns a pointer to a statically allocated
+    structure.  The contents of that structure can be changed by the
+    next call to localeconv() or setlocale().  You must not write to
+    the structure.
+
+þrestrictions
+
+    The contents of the structure are adjusted to use CHAR_MAX for the
+    þtt{char} type of the module calling localeconv().  When mixing
+    modules with different þtt{char} types, this will break.  When
+    calling localeconv() in a library, CHAR_MAX of the library will be
+    used instead of CHAR_MAX of the program using the library.
+
+    When calling the function version of localeconv(), for instance by
+    suppressing macro expansion, it is assumed that þtt{char} is
+    signed.
+
+þseealso setlocale()
+
+
+þfunction localtime()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þparam T
+þprototype
+struct tm *localtime (const time_t *T);
+þendprototype
+
+    Convert the number of seconds elapsed since 00:00:00 1-Jan-1970
+    Coordinated Universal Time (UTC, GMT) in the variable pointed to
+    by T to a time and date structure for the local timezone and
+    return a pointer to the structure.  gmtime(), mktime() and
+    localtime() use the same memory location, therefore the values are
+    overwritten if one of these functions is called.
+
+þreturnvalue
+
+    localtime() returns a pointer to a statically allocated
+    structure.
+
+þseealso asctime() ctime() gmtime() mktime() time()
+
+
+þfunction log() log10() logl() log10l()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double log (double X);
+double log10 (double X);
+
+long double logl (long double X);
+long double log10l (long double X);
+þendprototype
+
+    log() returns the natural logarithm of X.  log10() returns the
+    base-10 logarithm of X.
+
+    If X is zero, -INF is returned and errno set to EDOM.
+    If X is negative, a NaN is returned and errno set to EDOM.
+
+    logl() and log10l() use the þtt{long double} format.
+
+þreturnvalue
+
+    See above.
+
+þseealso exp() pow()
+
+
+þfunction longjmp()
+þcompat C90
+þheaders
+#include <setjmp.h>
+þendheaders
+
+þparam THERE N
+þprototype
+void longjmp (jmp_buf THERE, int N);
+þendprototype
+
+    Restore the context saved in THERE by setjmp().  longjmp() does a
+    non-local þtt{goto}, causing execution to continue at the setjmp()
+    call which most recently saved a stack context in THERE.  setjmp()
+    will return N.  If N is 0, setjmp() will return 1.  When calling
+    longjmp() in a signal handler or in a function called by a signal
+    handler (that is, while a signal handler is active), the signal
+    handler will be unwound, that is, it is assumed that the signal
+    handler doesn't return.  longjmp() must be called in the same
+    thread as the most recent call to setjmp() for THERE.  Moreover,
+    the function which most recently called setjmp() to save a stack
+    context in THERE must still be active.  Don't expect local
+    variables to be preserved unless declared volatile.
+
+    As jmp_buf is an array type, the þtt{&} operator need not be
+    applied.
+
+þseealso setjmp() sigaction() siglongjmp() sigsetjmp() signal()
+
+
+þfunction _lrotl() _lrotr()
+þcompat VAC++
+þheaders
+#include <sys/builtin.h>
+þendheaders
+
+þparam VALUE SHIFT
+þprototype
+unsigned long _lrotl (unsigned long VALUE, int SHIFT);
+unsigned long _lrotr (unsigned long VALUE, int SHIFT);
+þendprototype
+
+    _lrotl() returns VALUE (32 bits) rotated left by SHIFT bits.  If
+    SHIFT is 1, bit 30 is returned as bit 31, bit 29 is returned as
+    bit 30, and so on, bit 0 is returned as bit 1, and bit 31 is
+    returned as bit 0.
+
+    _lrotr() returns VALUE (32 bits) rotated right by SHIFT bits.  If
+    SHIFT is 1, bit 1 is returned as bit 0, bit 2 is returned as bit
+    1, and so on, bit 31 is returned as bit 30, and bit 0 is returned
+    as bit 31.
+
+    SHIFT should be 0 through 31.
+
+    These functions are implemented as inline functions.
+
+þseealso _crotl() _crotr() _srotl() _srotr()
+
+
+þfunction lseek()
+þcompat UNIX
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE OFFSET ORIGIN
+þprototype
+long lseek (int HANDLE, long OFFSET, int ORIGIN);
+þendprototype
+
+    lseek() moves the file pointer of HANDLE.  The new position OFFSET
+    is relative to ORIGIN: If ORIGIN is SEEK_SET, OFFSET is relative
+    to the beginning of the file, if ORIGIN is SEEK_CUR, OFFSET is
+    relative to the current position, if ORIGIN is SEEK_END, OFFSET is
+    relative to the end of the file.  The file pointer cannot be moved
+    before the beginning of the file.  lseek() does not change the
+    size of the file.
+
+þreturnvalue
+
+    lseek() returns the new position relative to the beginning of the
+    file.  If there is an error, lseek() returns -1.
+
+þrestrictions
+
+    If the file pointer is set beyond the end of file, the data
+    between the end of file and the new position is undefined (it
+    should be read as zeros, but isn't).
+
+    For text-mode files, OFFSET must be either zero (with ORIGIN equal
+    to SEEK_SET, SEEK_CUR, or SEEK_END) or a value returned by a call
+    to tell() on the same file (with ORIGIN equal to SEEK_SET).  For
+    text-mode files ending with a Ctrl-Z, SEEK_END is not allowed.
+
+þseealso chsize() filelength() tell()
+
+
+þfunction main()
+þcompat C90
+
+þparam ARGC ARGV ENVP
+þprototype
+int main (void);
+int main (int ARGC, char *ARGV[]);
+int main (int ARGC, char *ARGV[], char *ENVP[]);
+þendprototype
+
+    This is the function called by the startup code to run your
+    program.  It is not a library function.  ARGC is the number of
+    command line arguments, including the program name.  ARGV points
+    to an array of pointers to the command line arguments.  ENVP
+    points to an array of pointers to the environment strings.  The
+    last entry of each array is a NULL pointer.  main() should always
+    return a value.  If main() returns, þhpt{exit()} is called using
+    the return value of main() as argument.  If main() ends without
+    þtt{return} statement and without calling exit(), the return code
+    of the program is undefined.  This should be avoided.  After
+    changing the environment with þhpt{putenv()}, you should use the
+    þhpt{environ} global variable instead of the ENVP argument of
+    main().
+
+þreturnvalue
+
+    The return value of main() will be the return code of the process.
+
+þseealso _envargs() environ _execname() exit() putenv() _response() _wildcard()
+
+
+þfunction _makepath()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DST DRIVE DIR FNAME EXT
+þprototype
+void _makepath (char *DST, const char *DRIVE, const char *DIR,
+                const char *FNAME, const char *EXT);
+þendprototype
+
+    Build a path name from components and store it to the array
+    pointed to by DST.  The array at DST should be of size _MAX_PATH.
+    If DRIVE is not NULL and does not point to the empty string, the
+    first character of the string (a drive name) pointed to by DRIVE
+    followed by a colon is stored to the array pointed to by DST.  If
+    DIR is not NULL and does not point to the empty string, the string
+    (a directory name) pointed to by DIR is copied to DST.  If it does
+    not end with \ or /, _makepath() appends a / character (or a \
+    character if the string pointed to by DIR contains at least one
+    backslash).  If FNAME is not NULL, the string pointed to by FNAME
+    (a filename) is copied to DST.  If EXT is not NULL and does not
+    point to the empty string, the string pointed to by EXT (an
+    extension) is copied to DST.  If the string pointed to by EXT does
+    not start with a þtt{.}  character, _makepath() inserts a þtt{.}
+    in front of the string pointed to by EXT.  If the length of the
+    resulting string (including the terminating null character)
+    exceeds _MAX_PATH, the string is truncated to _MAX_PATH characters
+    (including the terminating null character).
+
+    _makepath() properly handles DBCS characters.
+
+þseealso _nls_init() _splitpath()
+
+þsamplecode
+char drive[_MAX_DRIVE], dir[_MAX_DIR];
+char tmp[_MAX_PATH];
+_splitpath (path, drive, dir, NULL, NULL);
+_makepath (tmp, drive, dir, "tmpfile", "$$$");
+þendsamplecode
+
+
+þfunction malloc()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam SIZE
+þprototype
+void *malloc (size_t SIZE);
+þendprototype
+
+    Allocate a block of memory big enough for holding SIZE bytes.  If
+    there is an error, malloc() returns NULL.  If SIZE is 0, zero
+    bytes of memory are allocated, the return value will be unequal
+    NULL.
+
+þreturnvalue
+
+    malloc() returns a pointer to a newly allocated block of memory.
+    On error, malloc() returns NULL.
+
+þimplementation
+
+    malloc() allocates from the default heap of the current thread.
+    þtt{malloc(0)} returns a non-NULL pointer if there's enough space
+    left in the heap for a block of the minimum size.
+
+þrestrictions
+
+    It's possible to replace the emx C library's malloc()
+    implementation; for instance, you can use GNU malloc.  However, do
+    not replace malloc() etc. when dynamically linking to the C
+    runtime library as the functions in the DLL won't call your
+    replacements.
+
+þseealso calloc() free() _msize() realloc() _tmalloc() _udefault() _umalloc()
+
+
+þfunction matherr()
+þcompat SysV
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+int matherr (struct exception *X);
+þendprototype
+
+    Exception handler for floating point math.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem non-0
+    error
+þenddescription
+
+þrestrictions
+
+    matherr() is not implemented.
+
+þseealso sigaction() signal()
+
+
+þfunction mblen()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam S N
+þprototype
+int mblen (const char *S, size_t N);
+þendprototype
+
+    Compute the number of bytes comprising the multibyte character
+    pointed to by S.  If S is NULL, the shift state is reset to the
+    initial state.  At most N bytes at S are examined; a multibyte
+    character consisting of more than N bytes is deemed invalid.
+
+    Except for the different shift states, this is equivalent to
+
+þtypewriter
+  mbtowc (NULL, þpa{S}, þpa{N})
+þendtypewriter
+
+    The shift state of mbtowc() is not affected.
+
+    In programs linked with the multithread libraries, each thread has
+    its own shift state for mblen().
+
+þreturnvalue
+
+    If S is NULL, mblen() returns a non-zero value (if state-dependent
+    encoding is used) or a zero value (if state-dependent encoding is
+    not used).  If S is not NULL, mblen() returns 0 (if S points to
+    the null character), the number of bytes comprising the multibyte
+    character pointed to by S (if there is a valid multibyte
+    character), or -1 (if there is not a valid multibyte character).
+
+þseealso mbtowc() setlocale()
+
+
+þfunction mbstowcs()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam PWCS S N
+þprototype
+size_t mbstowcs (wchar_t *PWCS, const char *S, size_t N);
+þendprototype
+
+    Convert the null-terminated sequence of multibyte character
+    pointed to by S to a sequence of wchar_t codes pointed to by PWCS.
+    The multibyte character sequence starts in the initial shift
+    state.  At most N codes are stored to PWCS.  PWCS will be
+    terminated with a code of value zero if N is big enough.
+
+    The shift state of mbtowc() and mblen() is not affected.
+
+þreturnvalue
+
+    mbstowcs() returns the number of codes stored to PWCS (excluding
+    the terminating zero code) or þtt{(size_t)-1} if an invalid
+    multibyte character is encountered.
+
+þseealso mblen() mbtowc() setlocale() wcstombs()
+
+
+þfunction mbtowc()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam PWC S N
+þprototype
+int mbtowc (wchar_t *PWC, const char *S, size_t N);
+þendprototype
+
+    Convert the multibyte character pointed to by S to a wchar_t code
+    and store it to PWC.  If S is NULL, the shift state is reset to
+    the initial state.  At most N bytes at S are examined; a multibyte
+    character consisting of more than N bytes is deemed invalid.
+
+    The shift state of mblen() is not affected.
+
+    In programs linked with the multithread libraries, each thread has
+    its own shift state for mbtowc().
+
+þreturnvalue
+
+    If S is NULL, mbtowc() returns a non-zero value (if state-dependent
+    encoding is used) or a zero value (if state-dependent encoding is
+    not used).  If S is not NULL, mbtowc() returns 0 (if S points to
+    the null character), the number of bytes comprising the multibyte
+    character pointed to by S (if there is a valid multibyte
+    character), or -1 (if there is not a valid multibyte character).
+
+þseealso mblen() mbstowcs() setlocale() wctomb()
+
+
+þfunction _md_close()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/moddef.h>
+þendheaders
+
+þparam MD
+þprototype
+int _md_close (struct _md *MD);
+þendprototype
+
+  Destroy the descriptor MD.  MD must have been returned by _md_open()
+  or _md_use_file().  If MD has been returned by _md_open(), the file
+  will be closed.  If MD has been returned by _md_use_file(), the file
+  won't be closed.  _md_close() frees the memory associated with MD.
+  Do not use MD after calling _md_close().
+
+  You have to link with the moddef library (use the -lmoddef option).
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso _md_open() _md_use_file()
+
+
+þfunction _md_errmsg()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/moddef.h>
+þendheaders
+
+þparam CODE
+þprototype
+const char *_md_errmsg (_md_error CODE);
+þendprototype
+
+  Return a pointer to the default error message for the error code
+  CODE.  This function can be used in the callback function of
+  _md_parse().
+
+  You have to link with the moddef library (use the -lmoddef option).
+
+þseealso _md_parse()
+
+
+þfunction _md_get_linenumber() _md_get_number() _md_get_string() _md_get_token()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/moddef.h>
+þendheaders
+
+þparam MD
+þprototype
+_md_token _md_get_token (struct _md *MD);
+long _md_get_number (const struct _md *MD);
+const char *_md_get_string (const struct _md *MD);
+long _md_get_linenumber (const struct _md *MD);
+þendprototype
+
+  Retrieve information about the current token of MD (the token most
+  recently read by þtt{_md_next_token (md)}).
+
+  _md_get_token() returns the token identifier (see
+  þhpt{_md_next_token()} for details).  If _md_get_token() has not
+  been called for MD, _MD_eof is returned.
+
+  If the current token is a number, _md_get_number() returns the value
+  of the number.  Otherwise, _md_get_number() returns 0.
+
+  _md_get_string() returns the string value of the current token.  The
+  string value consists of all the characters that are part of the
+  token.
+
+  _md_get_linenumber() returns the number of the line from
+  which the token has been read.  The first line is numbered 1.
+
+  You have to link with the moddef library (use the -lmoddef option).
+
+þseealso _md_next_token()
+
+
+þfunction _md_next_token()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/moddef.h>
+þendheaders
+
+þparam MD
+þprototype
+_md_token _md_next_token (struct _md *MD);
+þendprototype
+
+  Read the next token from the module definition file MD and return
+  the token identifier.  See <sys/moddef.h> for token identifiers.  Most
+  token identifiers identify a keyword.  For instance, _MD_NAME
+  is returned for the NAME keyword.  The following special token
+  identfiers are defined:
+
+þlist
+þitem _MD_dot
+
+  The character `þtt{.}'.
+
+þitem _MD_at
+
+  The character `þtt{@}'.
+
+þitem _MD_equal
+
+  The character `þtt{=}'.
+
+þitem _MD_number
+
+  A number.  Use _md_get_number() to retrieve the value.
+
+þitem _MD_word
+
+  A word which isn't a keyword.  Use _md_get_string() to retrieve the
+  value.
+
+þitem _MD_quote
+
+  A quoted string. _md_get_string() to retrieve the value.
+
+þitem _MD_eof
+
+  The end of the file has been reached.
+
+þitem _MD_ioerror
+
+  An I/O error occured while reading from the file (fatal error).
+
+þitem _MD_missingquote
+
+  A quote character is missing (fatal error).  Quote characters must
+  come in pairs.
+
+þendlist
+
+  After calling _md_next_token(), you can retrieve the token
+  identifier, numeric value, string value and line number of the
+  current token by calling _md_get_token(), _md_get_number(),
+  _md_get_string() and _md_get_linenumber(), respectively.
+
+  You have to link with the moddef library (use the -lmoddef option).
+
+þseealso _md_get_linenumber() _md_get_number() _md_get_string() _md_get_token() _md_open() _md_parse() _md_use_file()
+
+
+þfunction _md_open()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/moddef.h>
+þendheaders
+
+þparam FNAME
+þprototype
+struct _md *_md_open (const char *FNAME);
+þendprototype
+
+  Create a descriptor for reading module definition statements from
+  the file whose name is in the string pointed to by FNAME.  The file
+  is opened in SH_DENYWR mode.  On error (file cannot be opened or out
+  of memory), _md_open() sets errno and returns NULL.  Otherwise, a
+  descriptor is returned which can be passed to _md_next_token() or
+  _md_parse() to parse the file.  Call _md_close() to close the file
+  and to destroy the descriptor.
+
+  You have to link with the moddef library (use the -lmoddef option).
+
+þseealso _md_next_token() _md_parse() _md_use_file()
+
+
+þfunction _md_parse()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/moddef.h>
+þendheaders
+
+þparam MD CALLBACK ARG STMT TOKEN
+þprototype
+int _md_parse (struct _md *MD,
+               int (*CALLBACK)(struct _md *MD, const _md_stmt *STMT,
+                               _md_token TOKEN, void *ARG),
+               void *ARG);
+þendprototype
+
+  Parse the module definition file MD, calling CALLBACK for each
+  statement.  The token identifier of the statement is passed in TOKEN
+  to CALLBACK.  Information about the statement is passed in STMT.
+  Moreover, CALLBACK receives þtt{_md_parse()}'s MD and ARG arguments.
+  ARG can be used to pass additional user data to CALLBACK.
+
+  CALLBACK is also called if an error is encountered.  In that case,
+  TOKEN has the special value _MD_parseerror.
+
+  _md_parse() starts parsing at the current token, that is,
+  _md_next_token() has to be called before invoking _md_parse().
+  _md_parse() stops parsing when reaching the end of the file or when
+  CALLBACK returns a non-zero value.  In the latter case, _md_parse()
+  returns the value returned by CALLBACK.  In all other cases,
+  _md_parse() returns 0.
+
+  The following values of TOKEN can be passed to CALLBACK:
+
+þlist
+
+þitem _MD_BASE
+
+  BASE statement.  The base address is available in STMTþtt{->base.addr}.
+
+þitem _MD_CODE
+
+  CODE statement.  The segment attributes are available in
+  STMTþtt{->segment.attr}, using a combination of constants like
+  _MDS_IOPL.
+
+þitem _MD_DATA
+
+  DATA statement.  The segment attributes are available in
+  STMTþtt{->segment.attr}, using a combination of constants like
+  _MDS_MULTIPLE.
+
+þitem _MD_DESCRIPTION
+
+  DESCRIPTION statement.  The description string is available in
+  STMTþtt{->descr.string}.
+
+þitem _MD_EXETYPE
+
+  EXETYPE statement.  The executable type is available in
+  STMTþtt{->exetype.type} using a constant like _MDX_OS2.  For
+  _MDX_WINDOWS, the minor and major version numbers are available in
+  STMTþtt{->exetype.minor_version} and STMTþtt{->exetype.major_version},
+  respectively.  If the version numbers are not specified or if the
+  executable type is not WINDOWS, these fields are 0.
+
+þitem _MD_EXPORTS
+
+  One export entry of an EXPORTS statement.  Information about the
+  export entry is available in STMTþtt{->export}:
+
+þlist
+þitem þtt{flags}
+
+  If an ordinal number is present, _MDEP_ORDINAL is set.  If the
+  NONAME keyword is present, _MDEP_NONAME is set.  If the RESIDENTNAME
+  keyword is present, _MDEP_RESIDENTNAME is set.  If the NODATA
+  keyword is present, _MDEP_NODATA is set.  If the number of parameter
+  words is present, _MDEP_PWORDS is set.
+
+þitem þtt{internalname}
+
+  The internal name of the entry point.  If no internal name is
+  specified, the string is empty.
+
+þitem þtt{entryname}
+
+  The external name of the entry point.
+
+þitem þtt{ordinal}
+
+  The ordinal number, if þtt{flags} contains _MDEP_ORDINAL.
+  Otherwise, this field is 0.
+
+þitem þtt{pwords}
+
+  The number of parameter words, if þtt{flags} contains _MDEP_PWORDS.
+  Otherwise, this field is 0.
+
+þendlist
+
+þitem _MD_HEAPSIZE
+
+  HEAPSIZE statement.  If a heap size is specified, the heap size is
+  available in STMTþtt{->heapsize.size} and STMTþtt{->heapsize.maxval}
+  is 0.  If MAXVAL is specified, STMTþtt{->heapsize.maxval} is
+  non-zero and STMTþtt{->heapsize.size} is 0.
+
+þitem _MD_IMPORTS
+
+  One import entry of an IMPORTS statement.  Information about the
+  import entry is available in STMTþtt{->import}:
+
+þlist
+
+þitem þtt{flags}
+
+  If an ordinal number is present, _MDIP_ORDINAL is set.
+
+þitem þtt{internalname}
+
+  The internal name of the entry point.  If no internal name is
+  specified, the string is empty.
+
+þitem þtt{entryname}
+
+  The external name of the entry point.  If no external name is
+  specified (that is, if _MDIP_ORDINAL is set), the string is empty.
+
+þitem þtt{modulename}
+
+  The name of the dynamic link library.
+
+þitem þtt{ordinal}
+
+  The ordinal number, if þtt{flags} contains _MDIP_ORDINAL.
+  Otherwise, this field is 0.
+
+þendlist
+
+þitem _MD_LIBRARY
+
+  LIBRARY statement.  The name is available in
+  STMTþtt{->library.name}.  The library initialization and termination
+  modes are available in STMTþtt{->library.init} and
+  STMTþtt{->library.term}, respectively.  These fields are set to
+  _MDIT_DEFAULT if no modes are specified.  Otherwise, _MDIT_INSTANCE
+  or _MDIT_GLOBAL is used.
+
+þitem _MD_NAME
+
+  NAME statement.  The name is available in STMTþtt{->name.name}.  The
+  application type is available in STMTþtt{->name.pmtype}.  That field
+  is set to _MDT_DEFAULT (if no type is specified), _MDT_WINDOWAPI,
+  _MDT_WINDOWCOMPAT or _MDT_NOTWINDOWCOMPAT.  If NEWFILES is
+  specified, the STMTþtt{->name.newfiles} field is non-zero.
+
+þitem _MD_OLD
+
+  OLD statement.  The file name is available in
+  STMTþtt{->old.name}.
+  
+þitem _MD_PHYSICAL
+
+  PHYSICAL DEVICE statement.  The name is available in
+  STMTþtt{->device.name}.
+
+þitem _MD_PROTMODE
+
+  PROTMODE statement.  No additional information is available.
+
+þitem _MD_REALMODE
+
+  REALMODE statement.  No additional information is available.
+
+þitem _MD_SEGMENTS
+
+  One segment definition of a SEGMENTS statement.  The segment
+  attributes are available in STMTþtt{->segment.attr}, using a
+  combination of constants like _MDS_SHARED.  The segment name is
+  available in STMTþtt{->segment.segname}.  The class name is
+  available in STMTþtt{->segment.classname}.  If no class name is
+  specified, that string is empty.
+
+þitem _MD_STACKSIZE
+
+  STACKSIZE statement.  The stack size is available in
+  STMTþtt{->stacksize.size}.
+
+þitem _MD_STUB
+
+  STUB statement.  The file name is available in STMTþtt{->stub.name}.
+  If the NONE keyword is used, STMTþtt{->stub.none} is none-zero and
+  the string is empty.
+
+þitem _MD_VIRTUAL
+
+  VIRTUAL DEVICE statement.  The name is available in
+  STMTþtt{->device.name}.
+
+þitem _MD_parseerror
+
+  _md_parse() has detected an error.  The token identifier of the
+  current statement is available in STMTþtt{->error.stmt}.  An error
+  code is available in STMTþtt{->error.code}.  The following error
+  codes are defined:
+
+þlist
+þitem _MDE_IO_ERROR
+
+  _md_next_token() returned _MD_ioerror because an I/O error
+  occured while reading from the file.
+
+þitem _MDE_MISSING_QUOTE
+
+  _md_next_token() returned _MD_missingquote because a quote
+  character is missing.  Quote characters must come in pairs.
+
+þitem _MDE_EMPTY
+
+  The module definition file is empty, there are no statements.  This
+  error also occurs if _md_next_token() wasn't called before
+  calling _md_parse().
+
+þitem _MDE_NAME_EXPECTED
+
+  A name (segment name, class name, entry name) was expected, but a
+  different token was read.
+
+þitem _MDE_STRING_EXPECTED
+
+  A quoted string was expected, but a different token was read.
+
+þitem _MDE_NUMBER_EXPECTED
+
+  A number was expected, but a different token was read.
+
+þitem _MDE_DEVICE_EXPECTED
+
+  The VIRTUAL or PHYSICAL keyword isn't followed by the DEVICE
+  keyword.
+
+þitem _MDE_EQUAL_EXPECTED
+
+  An `þtt{=}' character was expected, but a different token was read.
+
+þitem _MDE_DOT_EXPECTED
+
+  A `þtt{.}' character was expected, but a different token was read.
+
+þitem _MDE_STRING_TOO_LONG
+
+  A string is too long.
+
+þitem _MDE_INVALID_ORDINAL
+
+  An ordinal number is invalid.  Valid ordinal numbers are in 1
+  through 65535.
+
+þitem _MDE_INVALID_STMT
+
+  An invalid keyword (which doesn't start a statement) was read.
+
+þendlist
+
+  You can use þhpt{_md_errmsg()} to get a default error message for
+  the error code.
+
+  If CALLBACK returns 0, _md_parse() skips tokens until finding a
+  keyword which starts a statement or until hitting end of file.  If
+  CALLBACK returns a non-zero number, that number will be immediately
+  returned by _md_parse().
+
+þendlist
+
+  You have to link with the moddef library (use the -lmoddef option).
+
+þseealso _md_errmsg() _md_next_token() _md_open() _md_use_file()
+
+þsamplefile /emx/test/mdecho.c
+
+
+þfunction _md_use_file()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/moddef.h>
+þendheaders
+
+þparam F
+þprototype
+struct _md *_md_use_file (FILE *F);
+þendprototype
+
+  Create a descriptor for reading module definition statements from
+  the file F.  On error (out of memory), _md_use_file() sets errno and
+  returns NULL.  Otherwise, a descriptor is returned which can be
+  passed to _md_next_token() or _md_parse() to parse the file.  Don't
+  close F before calling _md_close().  Call _md_close() to destroy the
+  descriptor.
+
+  You have to link with the moddef library (use the -lmoddef option).
+
+þseealso _md_close() _md_next_token() _md_open()
+
+
+þfunction _memaccess()
+þcompat emx
+þheaders
+#include <sys/hw.h>
+þendheaders
+
+þparam FIRST LAST FLAG
+þprototype
+void *_memaccess (unsigned FIRST, unsigned LAST, int FLAG);
+þendprototype
+
+    Gain access to physical memory under DOS.  To access memory which
+    is outside the memory space of the current process, you have to
+    call _memaccess().  emx option -am must be used to enable
+    _memaccess(), see `þhpt{Using emx options}'.
+
+    FIRST is the address of the first byte of the physical memory
+    area, LAST is the address of the last byte of the physical memory
+    area to be accessed.  Both addresses are physical addresses.
+    FIRST and þpa{LAST}+1 must be page aligned: FIRST and þpa{LAST}+1
+    must be integral multiples of 4096.  That is, with using
+    hexadecimal notation, FIRST must end with 000, LAST must end with
+    fff.  If FLAG is 0, read access is granted.  If FLAG is 1, read
+    and write access is granted.  Write access can be granted if the
+    address range of the physical memory area is entirely in the range
+    0xa0000 to 0xbffff.  If bytes outside this range are included in
+    FIRST to LAST, emx option -aw must be used to enable write access,
+    see `þhpt{Using emx options}'.
+
+þreturnvalue
+
+    _memaccess() returns a pointer to virtual memory mapped to the
+    physical memory area.  On failure, _memaccess() sets errno and
+    returns NULL.
+
+þerrors
+
+þdescription
+þitem EACCES
+
+    FIRST not page aligned; þpa{LAST}+1 not page aligned; LAST not
+    greater than FIRST; write access not allowed
+
+þitem EINVAL
+
+    FLAG is not 0 or 1
+
+þitem ENOMEM
+
+    not enough virtual memory for storing the paging tables; linear
+    address space of process not big enough for the request
+
+þenddescription
+
+þrestrictions
+
+    _memaccess() is not available under OS/2.  Obtaining access to
+    memory by linear address is not yet supported.
+
+þseealso _portaccess()
+
+þsamplefile /emx/test/hw_mem.c
+
+
+þfunction memccpy()
+þcompat PC
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S1 S2 C N
+þprototype
+void *memccpy (void *S1, const void *S2, int C, size_t N);
+þendprototype
+
+    Copy at most the first N bytes from S2 to S1, stopping after
+    copying a byte equal to the lower 8 bits C.  If memccpy() stops
+    because a byte equal to C has been found, a pointer to the byte
+    after the last destination byte (which is equal to C) is returned.
+    If N bytes have been copied without finding a byte equal to C,
+    NULL is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso memchr() memcpy() memmove() strcpy() strncpy()
+
+
+þfunction memchr()
+þcompat C90
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S C N
+þprototype
+void *memchr (const void *S, int C, size_t N);
+þendprototype
+
+    Search the first N bytes at S for a byte equal to the lower 8 bits
+    of C.  If a byte equal to C is found, a pointer to the first
+    occurrence of C is returned.  If there is no such byte, NULL is
+    returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso _memrchr() strchr()
+
+
+þfunction memcmp()
+þcompat C90
+
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S1 S2 N
+þprototype
+int memcmp (const void *S1, const void *S2, size_t N);
+þendprototype
+
+    Compare the first N bytes at S1 to the first N bytes at S2.  If
+    the two buffers are identical (or if N is zero), 0 is returned.
+    Otherwise, a value is returned which indicates the relationship of
+    the first differing byte: a negative value means buffer S1 is
+    lexically less than buffer S2, a positive value means buffer S1 is
+    lexically greater than buffer S2.
+
+þreturnvalue
+þdescription
+þitem <0
+   S1 < S2
+þitem =0
+   S1 = S2
+þitem >0
+   S1 > S2
+þenddescription
+
+þseealso bcmp() _memdif() memicmp()
+
+
+þfunction _memcount()
+þcompat emx
+
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam MEM C N
+þprototype
+size_t _memcount (const void *MEM, int C, size_t N);
+þendprototype
+
+    Count and return the number of occurrences of character C in the
+    memory area of size N bytes pointed to by MEM.
+
+þreturnvalue
+
+    See above.
+
+
+þfunction memcpy()
+þcompat C90
+
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S1 S2 N
+þprototype
+void *memcpy (void *S1, const void *S2, size_t N);
+þendprototype
+
+    Copy memory.  Copy N bytes from S2 to S1.  The two regions must
+    not overlap.  GCC generates in-line code for special applications
+    of memcpy().  Use memmove() instead of memcpy() to copy
+    overlapping regions of memory.
+
+þreturnvalue
+
+    memcpy() returns S1.
+
+þseealso bcopy() memmove()
+
+
+þfunction _memdif()
+þcompat emx
+
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam MEM1 MEM2 N
+þprototype
+size_t _memdif (const void *MEM1, const void *MEM2, size_t N);
+þendprototype
+
+    Compare the first N bytes pointed to by MEM1 to the first N bytes
+    pointed to by MEM2.  If the two buffers are identical (or if N is
+    zero), _MEMDIF_EQ is returned.  Otherwise, the byte offset of the
+    first difference is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso memcmp()
+
+
+þfunction memicmp()
+þcompat PC
+
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S1 S2 N
+þprototype
+int memicmp (const void *S1, const void *S2, size_t N);
+þendprototype
+
+    Compare the first N bytes at S1 to the first N bytes at S2,
+    ignoring letter case.  If the two buffers are identical (or if N
+    is zero), 0 is returned.  Otherwise, a value is returned which
+    indicates the relationship of the first differing byte: a negative
+    value means buffer S1 is lexically less than buffer S2 (after
+    conversion to lower case), a positive value means buffer S1 is
+    lexically greater than buffer S2 (after conversion to lower case).
+
+þreturnvalue
+þdescription
+þitem <0
+   S1 < S2
+þitem =0
+   S1 = S2
+þitem >0
+   S1 > S2
+þenddescription
+
+þseealso memcmp() tolower()
+
+
+þfunction memmove()
+þcompat C90
+
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S1 S2 N
+þprototype
+void *memmove (void *S1, const void *S2, size_t N);
+þendprototype
+
+    Copy memory.  Copy N bytes from S2 to S1.  The two regions may
+    overlap.
+
+þreturnvalue
+
+    memmove() returns S1.
+
+þseealso bcopy() memcpy()
+
+
+þfunction _memrchr()
+þcompat emx
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S C N
+þprototype
+void *_memrchr (const void *S, int C, size_t N);
+þendprototype
+
+    Search the first N bytes at S for a byte equal to the lower 8 bits
+    of C.  If a byte equal to C is found, a pointer to the last
+    occurrence of C is returned.  If there is no such byte, NULL is
+    returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso memchr() strrchr()
+
+
+þfunction memset()
+þcompat C90
+
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S C N
+þprototype
+void *memset (void *S, int C, size_t N);
+þendprototype
+
+    Fill memory.  Set N bytes at S to C.
+
+þreturnvalue
+
+    memset() returns S.
+
+þseealso bzero()
+
+
+þfunction _memswap()
+þcompat emx
+
+þheaders
+#include <string.h>     /* use this */
+#include <memory.h>     /* or this */
+þendheaders
+
+þparam S1 S2 N
+þprototype
+void _memswap (void *S1, void *S2, size_t N);
+þendprototype
+
+    Swap two areas of memory of N bytes each, pointed to by S1 and S2.
+    The two areas must not overlap.
+
+
+þfunction _mfclose()
+þcompat emx
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+char *_mfclose (FILE *STREAM);
+þendprototype
+
+    Close a memory file.  A pointer to the buffer is returned.  On
+    error, NULL is returned.  Use ftell() before calling _mfclose() to
+    get the number of characters in the buffer.  If the þpa{BUF}
+    argument of _mfopen() was NULL, use free() to deallocate the
+    buffer.
+
+þreturnvalue
+
+    See above.
+
+þseealso _mfopen()
+
+
+þfunction _mfopen()
+þcompat emx
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUF MODE SIZE INC
+þprototype
+FILE *_mfopen (char *BUF, const char *MODE, size_t SIZE, int INC);
+þendprototype
+
+    Open a memory file.  All output to a memory file goes to a buffer
+    in memory.  The stream returned by _mfopen() can be used with
+    fprintf(), fputc(), ftell() and fwrite().  If BUF is
+    non-þtt{NULL}, output goes to the array of SIZE bytes pointed to
+    by BUF.  INC must be zero.  If BUF is NULL, output goes to a
+    buffer allocated with malloc() and resized with realloc().  The
+    initial size of the buffer is SIZE bytes (which can be zero).  INC
+    must be non-zero.  If INC is positive, the buffer size is
+    increased by INC bytes whenever it is full.  If INC is -2, the
+    buffer size is doubled whenever the buffer is full.  If SIZE
+    is 0 and INC is -2, the initial buffer size is 512 bytes, the
+    buffer will be allocated on the first output to the stream.
+    Currently, MODE must point to þtt{"wb"}.  On error, _mfopen()
+    returns NULL.  Do not use fclose() on a stream created by
+    _mfopen(), use _mfclose() instead.  Do not read from a stream
+    created by _mfopen().
+
+þreturnvalue
+
+    _mfopen() returns a new stream.  On error, _mfopen() returns NULL.
+
+þrestrictions
+
+    _fsetmode() doesn't work, newline characters written to the
+    stream are not expanded to CR/LF.
+
+þseealso _fassign() fopen() _mfclose() sprintf()
+
+þsamplefile /emx/test/mftest.c
+
+
+þfunction _mheap()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam MEM
+þprototype
+Heap_t _mheap (const void *MEM);
+þendprototype
+
+    Return a pointer to the heap in which the memory block MEM has
+    been allocated.  MEM must be the pointer obtained by calling
+    calloc(), malloc(), realloc(), _tcalloc(), _tmalloc(),
+    _trealloc(), _ucalloc(), _umalloc(), _utcalloc(), or _utmalloc().
+    _mheap() returns NULL if MEM is NULL.  The return value of
+    _mheap() is undefined if MEM points to a memory block which has
+    been freed.  _mheap() may crash if MEM does not point to a memory
+    block allocated by one of the functions listed above.
+
+þreturnvalue
+
+    _mheap() returns a pointer to the heap in which the memory block
+    MEM has been allocated. _mheap() returns NULL if MEM is NULL.
+
+þseealso malloc() _msize() _ucreate() _ucreate2() _udefault() _umalloc()
+
+
+þfunction mkdir()
+þcompat BSD
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME MODE
+þprototype
+int mkdir (const char *NAME, long MODE);
+þendprototype
+
+    Create a directory whose name is in the string pointed to by NAME.
+    Only one directory can be created in one step, therefore all but
+    the last component of the string pointed to by NAME must exist.
+    MODE (containing the permission bits) is ignored.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso chdir() rmdir()
+
+
+þfunction mkstemp()
+þcompat BSD
+þheaders
+#include <unistd.h>
+þendheaders
+
+þparam STRING
+þprototype
+int mkstemp (char *STRING);
+þendprototype
+
+    Create a unique file name by modifying the string pointed to by
+    STRING and open a file descriptor for that file using O_RDWR mode.
+    Trailing þtt{X} characters of the string pointed to by STRING are
+    replaced by a letter followed by digits (the process ID).  There
+    should be 6 trailing þtt{X} characters.  Only 26 different file
+    names per process can be created.
+
+þreturnvalue
+
+    On success, mkstemp() returns a file descriptor.  On failure,
+    mkstemp() sets errno and returns -1.
+
+þhints
+
+    Note that the string pointed to by STRING will be modified; do not
+    use a string constant!
+
+    mkstemp() opens the file in text mode; use setmode() to switch the
+    file descriptor to binary mode.
+
+    mkstemp() avoids the race condition of mktemp(), however it is
+    less portable than mktemp().
+
+þseealso mktemp() setmode() tmpfile()
+
+
+þfunction mktemp()
+þcompat UNIX
+þheaders
+#include <unistd.h>
+þendheaders
+
+þparam STRING
+þprototype
+char *mktemp (char *STRING);
+þendprototype
+
+    Create a unique file name by modifying the string pointed to by
+    STRING.  Trailing þtt{X} characters of the string pointed to by
+    STRING are replaced by a letter followed by digits (the process
+    ID).  There should be 6 trailing þtt{X} characters.  Only 26
+    different file names per process can be created.
+
+þreturnvalue
+
+    On success, mktemp() returns STRING.  On failure, mktemp() returns
+    NULL.
+
+þhints
+
+    Note that the string pointed to by STRING will be modified; do not
+    use a string constant!
+
+    Note that mktemp() is subject to a race condition: other threads
+    of the same process may use the same temporary file name before
+    you have a chance to create the temporary file.
+
+þseealso mkstemp() tempnam() tmpfile() tmpnam()
+
+þsamplecode
+char tmp[20];
+
+strcpy (tmp, "exXXXXXX");
+if (mktemp (tmp) != NULL)
+  {
+    /* ... */
+  }
+þendsamplecode
+
+
+þfunction mktime()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þparam T
+þprototype
+time_t mktime (struct tm *T);
+þendprototype
+
+    Compute the number of seconds elapsed between 00:00:00 1-Jan-1970
+    Coordinated Universal Time (UTC, GMT) and the time in the
+    structure pointed to by T, interpreted as local time.  The tm_wday
+    and tm_yday members of the structure are ignored.  The members of
+    the structure are allowed to be out of range; mktime() modifies
+    the structure to force the values to the usual ranges.  The
+    tm_mday member is not set until the tm_mon and tm_year members
+    have been adjusted.  The time in the structure is assumed to
+    initially represent standard time if tm_isdst is zero.  The time
+    in the structure is assumed to initially represent daylight saving
+    time if tm_isdst is positive.  If tm_isdst is negative, mktime()
+    determines whether daylight saving time is in effect for the
+    specified time.  mktime() sets the tm_wday, tm_yday, and tm_isdst
+    members of the structure as appropriate.
+
+    See þhpt{tzset()} for a description of the TZ environment
+    variable.
+
+þreturnvalue
+
+    mktime() returns the number of seconds elapsed between 00:00:00
+    1-Jan-1970 UTC and the time in the structure pointed to by T.  If
+    the time cannot be represented, mktime() returns -1 cast as
+    time_t.
+
+þimplementation
+
+    If tm_isdst is negative and the specified time is in the time gap
+    between standard time and daylight saving time, mktime() assumes
+    that daylight saving time is not in effect for the specified time.
+
+þseealso gmtime() localtime() tzset()
+
+
+þfunction modf() modfl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X INT_PTR
+þprototype
+double modf (double X, double *INT_PTR);
+long double modfl (long double X, long double *INT_PTR);
+þendprototype
+
+    Split X into fractional part (which is returned) and integer part
+    (which is stored to þtt{*}þpa{INT_PTR}).  Both the fractional and
+    the integer part have the same sign as X.
+
+    modfl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    modf() returns the fractional part of X.
+
+þseealso ceil() floor() frexp() rint() trunc()
+
+
+þfunction _msize()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam MEM
+þprototype
+size_t _msize (const void *MEM);
+þendprototype
+
+    Return the size of the memory block MEM which has been allocated
+    by one of the C library's memory allocation functions.  MEM must
+    be the pointer obtained by calling calloc(), malloc(), realloc(),
+    _tcalloc(), _tmalloc(), _trealloc(), _ucalloc(), _umalloc(),
+    _utcalloc(), or _utmalloc().  _msize() returns zero if MEM is
+    NULL.  The return value of _msize() is undefined if MEM points to
+    a memory block which has been freed.
+
+þreturnvalue
+
+    _msize() returns the number of bytes allocated to MEM or zero if
+    MEM is NULL.
+
+þseealso _expand() malloc() _mheap() _umalloc()
+
+
+þfunction nextafter() nextafterf() nextafterl()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X Y
+þprototype
+double nextafter (double X, double Y);
+float nextafterf (float X, float Y);
+long double nextafterl (long double X, long double Y);
+þendprototype
+
+    Return the next representable value after X, in the type of the
+    function, in the direction of Y.
+
+þreturnvalue
+
+    Return Y if Xþtt{==}Y is true.  If both X and Y are NaNs, return
+    one of them.  If X or Y is a NaN, return that NaN.  If Y is
+    greater than X, return the smallest value in the type of the
+    function that is greater than X.  If Y is smaller than X, return
+    the greatest value in the type of the function that is smaller
+    than X.
+
+þseealso copysign() fpclassify()
+
+
+þfunction _nls_init()
+þcompat emx
+þheaders
+#include <sys/nls.h>
+þendheaders
+
+þprototype
+void _nls_init (void);
+þendprototype
+
+    Initialize the global variables _nls_tolower_tab,
+    _nls_toupper_tab, and _nls_ctype_tab, which are used by
+    _nls_tolower(), _nls_toupper(), _nls_strlwr(), _nls_strupr(), and
+    _nls_is_dbcs_lead().  The tables are initialized appropriately for
+    the current country code and code page.  _nls_init() is
+    automatically called by the startup code, therefore you don't have
+    to call _nls_init() unless you change the country code or the code
+    page: _nls_init() should be called after changing the country code
+    or code page.
+
+þseealso _defext() _fncmp() _getext() _getname() _nls_is_dbcs_lead() _nls_strlwr() _nls_tolower() _remext() _splitpath()
+
+
+þfunction _nls_is_dbcs_lead()
+þcompat emx
+þheaders
+#include <sys/nls.h>
+þendheaders
+
+þparam C
+þprototype
+int _nls_is_dbcs_lead (int C);
+þendprototype
+
+    This macro evaluates to a non-zero value if C is the lead byte of
+    a DBCS character.  C must be an integer which is representable as
+    þtt{unsigned char} (that is, 0 through 255).  Note that C must not
+    be EOF.
+
+þreturnvalue
+
+    _nls_is_dbcs_lead() returns zero if its argument is not a DBCS
+    lead byte.  _nls_is_dbcs_lead() returns a non-zero value if its
+    argument is a DBCS lead byte.
+
+þseealso _nls_init() _nls_strlwr() _nls_strupr()
+
+
+þfunction _nls_strlwr() _nls_strupr()
+þcompat emx
+þheaders
+#include <sys/nls.h>
+þendheaders
+
+þparam STRING
+þprototype
+unsigned char *_nls_strlwr (unsigned char *STRING);
+unsigned char *_nls_strupr (unsigned char *STRING);
+þendprototype
+
+    These functions convert all the characters of the string pointed
+    to by STRING to lower case or upper case, respectively.  Accented
+    characters etc.  are converted as well, DBCS characters are not
+    changed.
+
+þreturnvalue
+
+    _nls_strlwr() and _nls_strupr() return STRING.
+
+þseealso _nls_init() _nls_is_dbcs_lead() _nls_tolower() _nls_toupper()
+
+
+þfunction _nls_tolower() _nls_toupper()
+þcompat emx
+þheaders
+#include <sys/nls.h>
+þendheaders
+
+þparam C
+þprototype
+unsigned char _nls_tolower (unsigned char C);
+unsigned char _nls_toupper (unsigned char C);
+þendprototype
+
+    These macros convert the character C to lower case or upper
+    case, respectively.  Accented characters etc. are converted as
+    well.  The result is undefined if C is a DBCS lead byte.
+
+þreturnvalue
+
+    _nls_tolower() returns its argument converted to lower case.
+    _nls_toupper() returns its argument converted to upper case.
+
+þseealso _nls_init() _nls_strlwr() _nls_strupr()
+
+
+þfunction offsetof()
+þcompat C90
+þheaders
+#include <stddef.h>
+þendheaders
+
+þparam TYPE MEMBER
+þprototype
+size_t offsetof (TYPE, MEMBER);
+þendprototype
+
+    The offsetof() macro expands to an integral constant expression of
+    type þtt{size_t}.  The value of that expression is the offset in
+    bytes from the beginning of the structure designated by TYPE to
+    the structure member designated by MEMBER.
+
+    The structure member must not be a bit-field.  Given the declaration
+þtypewriter
+static TYPE s;
+þendtypewriter
+    the expression
+þtypewriter
+&(s.þpa{MEMBER})
+þendtypewriter
+    must evaluate to an address constant.
+
+þreturnvalue
+
+    See above.
+
+þsamplecode
+#include <stddef.h>
+
+struct sample
+{
+  int a;
+  struct
+    {
+      int b[2];
+    } inner;
+};
+
+size_t offset_a  = offsetof (struct sample, a);
+size_t offset_b0 = offsetof (struct sample, inner.b[0]);
+size_t offset_b1 = offsetof (struct sample, inner.b[1]);
+þendsamplecode
+
+
+þfunction open()
+þcompat UNIX
+þheaders
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+þendheaders
+
+þparam NAME OFLAG PMODE ISIZE
+þprototype
+int open (const char *NAME, int OFLAG);
+int open (const char *NAME, int OFLAG, int PMODE);
+
+int open (const char *NAME, int OFLAG, unsigned long ISIZE);
+int open (const char *NAME, int OFLAG, int PMODE, unsigned long ISIZE);
+þendprototype
+
+    Open a file or device.  NAME points to the name of the file or
+    device.  OFLAG contains one or more of the following values,
+    combined by the þtt{|} operator:
+
+þdescription
+
+þitem O_RDONLY
+
+    Open for reading.  Writing is not allowed
+
+þitem O_WRONLY
+
+    Open for writing.  Reading is not allowed
+
+þitem O_RDWR
+
+    Open for reading and writing
+
+þitem O_APPEND
+
+    Move the file pointer to the end of file before any write
+    operation takes place.  This is used for appending to a file
+
+þitem O_CREAT
+
+    Create the file if it does not exist.  If this flag is set, the
+    PMODE argument is required
+
+þitem O_TRUNC
+
+    Truncate the size of the file to 0
+
+þitem O_EXCL
+
+    Fail if the O_CREAT flag is used and the file already exists
+
+þitem O_NONBLOCK and O_NDELAY
+
+    Currently ignored
+
+þitem O_BINARY
+
+    Binary mode, no translation.  See below
+
+þitem O_TEXT
+
+    Text mode, translate CR/LF to the newline character.  See below
+
+þitem O_NOINHERIT
+
+    Child processes won't inherit the file handle
+
+þitem O_SYNC
+
+    Write operations are synchronous, that is, write() waits until
+    file data has been physically written
+
+þitem O_SIZE
+
+    Set the initial size of the file to ISIZE if the file is a new
+    file (O_CREAT) or an existing file truncated (O_TRUNC).  If this
+    flag is set, the ISIZE argument is required.  O_SIZE is ignored
+    under DOS
+
+þenddescription
+
+    If a new file is created, PMODE (modified by the umask value), is
+    used to set the file permissions.  S_IREAD grants read access,
+    S_IWRITE grants write access.  S_IREAD is ignored (DOS and OS/2
+    limitation).  To grant both read and write access, use
+    þtt{S_IREAD|S_IWRITE}.
+
+    There are two additional OFLAG flags: O_TEXT for text mode,
+    O_BINARY for binary mode.  Text mode, which is the default,
+    translates each CR/LF pair to a newline character on input and
+    translates newline characters to CR/LF pairs on output.  If the last
+    character of a file is Ctrl-Z, it is discarded on input.  Binary
+    mode disables these transformations.
+
+    If the file or device cannot be opened, open() sets errno and
+    returns -1.  If open() succeeds, the file handle is returned.  The
+    file handle is always greater than -1.
+
+    The mode þtt{O_TRUNC|O_RDONLY} is not implemented.  A Ctrl-Z at
+    the end of the file is removed only when opening a file for
+    appending in text mode.  Ctrl-Z at the end of the file is
+    obsolete, anyway.
+
+    The file is opened in the sharing mode SH_DENYNO, see
+    þhpt{sopen()}.
+
+þreturnvalue
+
+    open() returns a file handle for the file.  On error, open() sets
+    errno and returns -1.
+
+þimplementation
+
+    O_SIZE is an emx extension.  It's the caller's responsibility to
+    truncate the file if its size should be less than ISIZE bytes.
+    O_SIZE is ignored under DOS.
+
+þrestrictions
+
+    Under DOS, the O_NOINHERIT flag is currently ignored for child
+    processes which are DOS programs (vs. emx programs).  Under DOS,
+    the O_SYNC and O_SIZE flags are ignored.
+
+þseealso close() fcntl() fdopen() ftruncate() sopen()
+
+
+þfunction opendir() closedir() readdir() seekdir() telldir() rewinddir()
+þcompat POSIX.1
+þheaders
+#include <sys/types.h>
+#include <dirent.h>             /* this is recommended */
+#include <sys/dir.h>            /* this also works (for now) */
+þendheaders
+
+þparam NAME DIRP OFF
+þprototype
+DIR *opendir (const char *NAME);
+int closedir (DIR *DIRP);
+struct dirent *readdir (DIR *DIRP);
+void seekdir (DIR *DIRP, long OFF);
+long telldir (DIR *DIRP);
+void rewinddir (DIR *DIRP);
+þendprototype
+
+    Scan directories.  opendir() opens the directory whose name is in
+    the string pointed to by NAME for scanning.  If there is an error,
+    NULL is returned.  Otherwise a value is returned which is used
+    with the other functions to continue the scanning.
+
+    closedir() ends the directory scan of DIRP.  After closing DIRP,
+    you must not use DIRP.  You should close all handles created by
+    opendir().
+
+    readdir() retrieves the next directory entry for DIRP.  If there
+    are no more directory entries, NULL is returned.
+
+    seekdir() moves to the specified directory entry of DIRP.  If OFF
+    is 0, the first directory entry will be read next.  If OFF is 1,
+    the second directory entry will be read next.  And so on.
+    seekdir() is not a POSIX.1 function.
+
+    telldir() returns the current position in DIRP.  0 is returned for
+    the first directory entry.  telldir() is not a POSIX.1 function.
+
+    rewinddir() is equivalent to þtt{seekdir (0)}.
+
+    These functions use _fnlwr() to convert the file names to lower
+    case on upper-case-only file systems.
+
+þreturnvalue
+
+    opendir() returns a descriptor to be used with the other
+    functions.  On error, opendir() returns NULL.
+
+    closedir() returns 0 if successful, -1 on error.
+
+    readdir() returns a pointer to a directory entry.  If there are no
+    more directory entries, readdir() returns NULL.
+
+    telldir() returns the current position in DIRP.
+
+þseealso _fnlwr() _wildcard()
+
+
+þfunction _outp8() _outp16() _outp32()
+þcompat emx *
+þheaders
+#include <sys/hw.h>
+þendheaders
+
+þparam PORT VALUE
+þprototype
+void _outp8 (unsigned PORT, unsigned VALUE);
+void _outp16 (unsigned PORT, unsigned VALUE);
+void _outp32 (unsigned PORT, unsigned VALUE);
+þendprototype
+
+    These functions write a single byte or word to a hardware port.
+    _outp8() writes the byte VALUE to PORT, _outp16() writes the
+    16-bit word VALUE to PORT, _outp32() writes the 32-bit word VALUE
+    to PORT.
+
+    You have to call _portaccess() first to enable access to a range
+    of ports.  To make your program work under DOS, you have to use
+    emx option -ai, see `þhpt{Using emx options}'.  Under OS/2, your
+    program requires emxio.dll in a directory listed in LIBPATH.
+
+þseealso _portaccess() _inp8() _outps8()
+
+
+þfunction _outps8() _outps16() _outps32() _outps8dac()
+þcompat emx *
+þheaders
+#include <sys/hw.h>
+þendheaders
+
+þparam PORT SRC COUNT
+þprototype
+void _outps8 (unsigned PORT, const unsigned char *SRC, unsigned COUNT);
+void _outps16 (unsigned PORT, const unsigned short *SRC, unsigned COUNT);
+void _outps32 (unsigned PORT, const unsigned short *SRC, unsigned COUNT);
+void _outps8dac (unsigned PORT, const unsigned char *SRC, unsigned COUNT);
+þendprototype
+
+    These functions write multiple bytes or words to a hardware port.
+    _outps8() writes COUNT bytes from the array pointed to by SRC to
+    PORT.  _outps16() writes COUNT 16-bit words from the array pointed
+    to by SRC to PORT.  _outps32() writes COUNT 32-bit words from the
+    array pointed to by SRC to PORT.
+
+    The COUNT argument of _outps8() must not exceed 65535.
+
+    The array pointed to by SRC of _outps16() must be aligned on a
+    16-bit boundary, that is, the address must be even.  COUNT must
+    not exceed 32768.
+
+    The array pointed to by SRC of _outps32() must be aligned on a
+    32-bit boundary, that is, the address must be a multiple of four.
+    COUNT must not exceed 65536.
+
+    _outps8dac() is a slowed-down version of _outps8() suitable for
+    writing to the VGA palette registers.
+
+    You have to call _portaccess() first to enable access to a range
+    of ports.  To make your program work under DOS, you have to use
+    emx option -ai, see `þhpt{Using emx options}'.  Under OS/2, your
+    program requires emxio.dll in a directory listed in LIBPATH.
+
+þseealso _portaccess() _inps8() _outp8()
+
+
+þfunction _path()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DST NAME
+þprototype
+int _path (char *DST, const char *NAME);
+þendprototype
+
+    Find an executable file.  If the string pointed to by NAME
+    contains a colon, a slash or a backslash, only that name will be
+    tried.  If the string pointed to by NAME does not contain colons,
+    slashes or backslashes, the file will be sought in the directories
+    listed in the EMXPATH and PATH environment variables.  If the file
+    is not found, the empty string will be stored to the array pointed
+    to by DST, errno will be ENOENT and -1 will be returned.  If the
+    file is found, the path name will be copied to the array pointed
+    to by DST and 0 will be returned.  No default extension is used.
+
+þreturnvalue
+
+    See above.
+
+þseealso getenv() _searchenv()
+
+
+þfunction pathconf() fpathconf()
+þcompat POSIX.1
+þheaders
+#include <unistd.h>
+þendheaders
+
+þparam PATH HANDLE NAME
+þprototype
+long pathconf (const char *PATH, int NAME);
+long fpathconf (int HANDLE, int NAME);
+þendprototype
+
+    Return the current value of the configurable limit or option NAME
+    associated with the file or directory associated with HANDLE or
+    whose name is in the string pointed to by PATH.  NAME is one of
+    the following constants:
+
+þdescription
+þitem _PC_LINK_MAX
+
+    corresponds to LINK_MAX (maximum value of a file's link count)
+
+þitem _PC_MAX_CANON
+
+    corresponds to MAX_CANON (maximum number of bytes in a terminal
+    canonical input line)
+
+þitem _PC_MAX_INPUT
+
+    corresponds to MAX_INPUT (maximum number of bytes for which space
+    will be available in a terminal input queue)
+
+þitem _PC_NAME_MAX
+
+    corresponds to NAME_MAX (maximum number of bytes in a file name)
+
+þitem _PC_PATH_MAX
+
+    corresponds to PATH_MAX (maximum number of bytes in a path name)
+
+þitem _PC_PIPE_BUF
+
+    corresponds to PIPE_BUF (maximum number of bytes that can be
+    written atomically to a pipe)
+
+þitem _PC_CHOWN_RESTRICTED
+
+    corresponds to _POSIX_CHOWN_RESTRICTED (see POSIX.1 for details)
+
+þitem _PC_NO_TRUNC
+
+    corresponds to _POSIX_NO_TRUNC (path name components longer than
+    NAME_MAX generate an error)
+
+þitem _PC_VDISABLE
+
+    corresponds to _POSIX_VDISABLE (terminal special characters can be
+    disabled using this character value, if it is defined)
+
+þenddescription
+
+    See POSIX.1 for more details.
+
+þreturnvalue
+
+    If NAME is invalid, pathconf() and fpathconf() set errno to EINVAL
+    and return -1.  If the value associated with NAME has no limit for
+    the path or handle, pathconf() and fpathconf() return -1 without
+    changing errno.  If the implementation needs to use PATH or HANDLE
+    to determine the value of NAME and the implementation does not
+    support the association of NAME with the file specified by PATH or
+    HANDLE, respectively, or if HANDLE is an invalid file descriptor,
+    pathconf() and fpathconf() set errno and return -1.  Otherwise,
+    pathconf() and fpathconf() return the current value of the
+    variable.
+
+þrestrictions
+
+    pathconf() and fpathconf() currently return just the POSIX.1
+    minimum values.
+
+þseealso sysconf()
+
+
+þfunction pause()
+þcompat UNIX
+þheaders
+#include <signal.h>
+þendheaders
+
+þprototype
+int pause (void);
+þendprototype
+
+    Wait until a signal is received.  The process is suspended until
+    delivery of a signal for which a signal handler is installed.
+    pause() returns after the signal handler returns.
+
+    The process will be terminated (and pause() won't return) if
+    an uncaught signal is delivered which terminates the process.
+
+þreturnvalue
+
+    pause() returns -1 and sets errno to EINTR (if it returns at
+    all).
+
+þrestrictions
+
+    pause() is not implemented under DOS.
+
+þseealso alarm() kill() raise() sigaction() signal() sigsuspend()
+
+
+þfunction pclose()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int pclose (FILE *STREAM);
+þendprototype
+
+    Close a pipe created by popen().  pclose() waits until the child
+    process started by popen() ends and then closes STREAM.  The
+    termination status of the child process is returned.  See
+    þhpt{wait()} for details about the return value.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    pclose() is not implemented under DOS.
+
+þseealso popen() wait()
+
+
+þfunction perror()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STRING
+þprototype
+void perror (const char *STRING);
+þendprototype
+
+    Print an appropriate error message for the current errno value to
+    stderr.  If STRING is NULL or points to the empty string þtt{""},
+    just the error message is printed.  Otherwise, the string pointed
+    to by STRING and a colon precede the error message.
+
+þseealso errno strerror() sys_errlist sys_nerr
+
+
+þfunction pipe()
+þcompat UNIX
+þheaders
+#include <io.h>
+þendheaders
+
+þparam TWO_HANDLES
+þprototype
+int pipe (int *TWO_HANDLES);
+þendprototype
+
+    Create an unnamed pipe.  The handle used for reading from the pipe
+    is stored to þpa{TWO_HANDLES}þtt{[0]}, the handle used for writing
+    to the pipe is stored to þpa{TWO_HANDLES}þtt{[1]}.  Both handles
+    are in text mode; use þtt{setmode()} if you want to switch to
+    binary mode.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    pipe() is implemented for OS/2 only.
+
+þseealso close() dup() popen() setmode()
+
+
+þfunction popen()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam COMMAND MODE
+þprototype
+FILE *popen (const char *COMMAND, const char *MODE);
+þendprototype
+
+    Start a child process and connect one end of a pipe to it.
+    popen() runs the command whose name is in the string pointed to by
+    COMMAND by starting a command processor.  See þhpt{system()} for
+    details on locating and running the command processor.  MODE must
+    point to a string starting with þtt{r} or þtt{w}.  If the string
+    starts with þtt{r}, standard output of the command will be
+    redirected, you can get the output by reading from the stream
+    returned by popen().  If the mode string starts with þtt{w},
+    standard input of the command will be redirected, you can send
+    data to the command by writing to the stream returned by popen().
+    Append þtt{b} for binary mode or þtt{t} for text mode to the mode
+    string.  The default is text mode, see also þhpt{fopen()}.  If an
+    error occurs, popen() returns NULL.  Otherwise, popen() returns a
+    stream which is connected to the local end of the pipe.  Use
+    pclose() to close the stream.
+
+þreturnvalue
+
+    popen() returns a new stream.  On error, popen() returns NULL.
+
+þrestrictions
+
+    popen() is not implemented under DOS.
+
+þseealso pclose() pipe() system()
+
+
+þfunction _portaccess()
+þcompat emx
+þheaders
+#include <sys/hw.h>
+þendheaders
+
+þparam FIRST LAST
+þprototype
+int _portaccess (unsigned FIRST, unsigned LAST);
+þendprototype
+
+    Gain access to hardware ports.  To access hardware ports, you have
+    to call _portaccess().  FIRST is the address of the first port,
+    LAST is the address of the last port.  emx option -ai must be used
+    to enable _portaccess() under DOS, see `þhpt{Using emx options}'.
+
+    _portaccess() always succeeds under OS/2.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso _memaccess() _inp8() _outp8() _wait0()
+
+þsamplefile /emx/test/hw_io.c
+
+
+þfunction pow() powl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X Y
+þprototype
+double pow (double X, double Y);
+long double powl (long double X, long double Y);
+þendprototype
+
+    Raise X to the power of Y and return the result.  If pow() is
+    undefined for a given pair of X and Y, pow() returns an
+    implementation-defined value and sets errno to EDOM.  On overflow,
+    pow() returns HUGE_VAL and sets errno to ERANGE.
+
+    pow() returns 1.0 for all values of X if Y is zero.
+
+    powl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    pow() returns þpa{X}^þpa{Y}.
+
+þseealso cbrt() exp() ldexp() log() sqrt()
+
+
+þfunction printf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam FORMAT <flags> <width> <precision> <size> <type>
+þprototype
+int printf (const char *FORMAT, ...);
+þendprototype
+
+    printf() performs formatted output to the stdout stream.  On
+    success, the number of characters written to stdout is returned.
+    Otherwise, EOF is returned.
+
+    Characters in the string pointed to by FORMAT are copied
+    unmodified to the destination unless a format specification is
+    hit.  A format specification has the following format:
+
+þindent
+  þsy{%[<flags>][<width>][.<precision>][<size>]<type>}
+þendindent
+
+    where items in brackets are optional.  For each format
+    specification an argument of the specified type is taken from the
+    argument list, is formatted according to the format specification
+    and written to the destination.  To include one percent sign in
+    the output, put two percent signs (þtt{%%}) into the FORMAT string.
+
+    A <flag> character can be specified to modify the formatting. The
+    following <flags> characters are available:
+
+þlist
+þitem þtt{-}
+
+    Left-justify the converted value in the field.  Without this flag,
+    the value is right-justified.  The value will be padded with
+    blanks on the right (note that þtt{-} overrides þtt{0}).  If
+    þtt{-} is not given, the value is padded on the left with blanks
+    or zeros, according to the þtt{0} flag and the <type>.
+
+þitem þtt{+}
+
+    Always insert sign (þtt{+} or þtt{-}) for the conversion of a
+    signed number (that is, <type> being þtt{d}, þtt{e}, þtt{E},
+    þtt{f}, þtt{g}, þtt{G} or þtt{i}).  þtt{+} is ignored for all
+    other conversions.  þtt{+} overrides space.  If þtt{+} is not
+    specified, the sign is printed only for negative numbers and for
+    -0.0.
+
+þitem space
+
+    Insert a space if the conversion of a signed number (that is,
+    <type> being þtt{d}, þtt{e}, þtt{E}, þtt{f}, þtt{g}, þtt{G} or
+    þtt{i}) doesn't start with a sign (þtt{+} or þtt{-}).  For all
+    other conversions, space is ignored.  If both þtt{+} and space are
+    given, space is ignored.
+
+þitem þtt{0}
+
+    Pad numbers with þtt{'0'} characters instead of blanks.  This flag
+    is ignored for non-numeric conversions, if þtt{-} is used, or if
+    <precision> is given.
+
+þitem þtt{#}
+
+    Use alternate conversion.  For the þtt{o} conversion, the
+    precision will be increased to force the first digit of the result
+    to be a zero.  For the þtt{x} and þtt{X} conversions, the number
+    will be prefixed with þtt{0x} unless it is zero.  For the þtt{e},
+    þtt{E}, þtt{f}, þtt{g} and þtt{G} conversions, a decimal point
+    will always be printed, even if no digits follow it.  For the
+    þtt{g} and þtt{G} conversions, trailing zeros are not removed.
+
+þendlist
+
+    If the length of the converted value is less than <width>, it is
+    padded with blanks or þtt{'0'} characters.  Unless the þtt{-} flag
+    is used, the field is padded on the left.  Padding is done with
+    zeros for numeric conversions if the þtt{0} flag is given, the
+    þtt{-} flag is not given and <precision> is not given.  Otherwise,
+    blanks are used for padding.  If the length of the converted value
+    is greater than <width>, the field is not truncated.  <width> is
+    either a decimal number or a þtt{*} character.  In the latter
+    case, the width is taken from the argument list.
+
+    <precision> specifies the number of decimal digits after the
+    decimal point of a floating point number when using the þtt{e},
+    þtt{E} or þtt{f} conversions.  For the þtt{g} and þtt{G}
+    conversions, <precision> specifies the maximum number of
+    significant digits.  The number will be rounded according to
+    <precision> for the floating point conversions.  For the þtt{d},
+    þtt{i}, þtt{o}, þtt{u}, þtt{x} and þtt{X} conversions, <precision>
+    specifies the minimum number of digits to print.  If the number
+    has less digits, it will be padded with zeros on the left.  If the
+    precision is 0 and the integer is 0, no output will be produced
+    for this field (except for the þtt{o} conversion if the þtt{#}
+    flag is given).  For the þtt{s} conversion, <precision> specifies
+    the maximum string length.  For all other conversions, <precision>
+    is ignored.  <precision> is either a decimal number or a þtt{*}
+    character.  In the latter case, the precision is taken from the
+    argument list.  If a decimal point without <precision> is given,
+    the precision will be 0.
+
+    <size> is either þtt{h} for a þtt{short} type (þtt{h} is available
+    for the þtt{d}, þtt{i}, þtt{o}, þtt{u}, þtt{x}, and þtt{X}
+    conversions and for þtt{n}) or þtt{l} for a þtt{long} type (þtt{l}
+    is available for the þtt{d}, þtt{i}, þtt{o}, þtt{u}, þtt{x}, and
+    þtt{X} conversions and for þtt{n}) or þtt{L} for the þtt{long
+    double} type (þtt{L} is available for the þtt{e}, þtt{E}, þtt{f},
+    þtt{g}, and þtt{G} conversions).  If <size> is not specified, the
+    default size is used.
+
+    <type> (the conversion type) is one of the following characters:
+
+þlist
+þitem þtt{c}
+
+    Character.  The argument (þtt{char}, þtt{signed char},
+    þtt{unsigned char} or þtt{int}) is converted to an þtt{unsigned
+    char} and that character code will be printed.  <size> is ignored.
+
+þitem þtt{d}
+
+    Signed decimal number.  The argument is converted to a signed
+    integer and printed in decimal notation.  Use þtt{%hd} to print a
+    þtt{short int}, þtt{%ld} to print a þtt{long int} and þtt{%Ld} to
+    print a þtt{long long int}.
+
+þitem þtt{e}
+
+    Floating-point number (þtt{double}), using þtt{e} as exponent
+    sign: þtt{-#.###e+##}.  There's exactly one digit before the
+    decimal point.  The number of digits after the decimal point is
+    specified by <precision>.  If <precision> is missing, 6 digits are
+    printed after the decimal point.  If <precision> is zero, no
+    decimal point is printed unless the þtt{#} flag is given.  The
+    exponent has at least 2 digits.  If the number is zero, the
+    exponent is þtt{00}.  The decimal point character of the current
+    locale is used.  A NaN is printed as `þtt{nan}', infinity as
+    `þtt{inf}'.
+
+þitem þtt{E}
+
+    Floating-point number (þtt{double}); same as þtt{e}, except for
+    þtt{E} being used instead of þtt{e} to introduce the exponent, and
+    `þtt{NAN}' and `þtt{INF}' being printed instead of `þtt{nan}' and
+    `þtt{inf}', respectively.
+
+þitem þtt{f}
+
+    Floating-point number (þtt{double}) printed in fixed-point format.
+    The number of digits after the decimal point is specified by
+    <precision>.  If <precision> is missing, 6 digits are printed.  If
+    <precision> is specified as zero, no decimal point is printed
+    unless the þtt{#} flag is given.  There's always at least one
+    digit before the decimal point.  The decimal point character of
+    the current locale is used.  A NaN is printed as `þtt{nan}',
+    infinity as `þtt{inf}'.
+
+þitem þtt{F}
+
+    Floating-point number (þtt{double}); same as þtt{f}, except for
+    `þtt{NAN}' and `þtt{INF}' being printed instead of `þtt{nan}' and
+    `þtt{inf}', respectively.
+
+þitem þtt{g}
+
+    Floating-point number (þtt{double}).  The number is printed in
+    exponential or fixed-point format, depending on the magnitude.  If
+    the number is an integer, it is printed as integer, without
+    decimal point (unless the þtt{#} flag is used).  If the exponent
+    (of þtt{e} format output) is less than -4 or greater than
+    <precision> (the default is 6), type þtt{e} is used.  Otherwise,
+    type þtt{f} is used.  In both cases, trailing zeros (and the
+    decimal point, if it isn't followed by any digits) will be removed
+    unless the þtt{#} flag is used.  <precision> specifies the number
+    of significant digits to print.  If <precision> is missing, 6
+    significant digits are printed.  If <precision> is zero, a
+    precision of 1 will be used instead.  The decimal point character
+    of the current locale is used.  A NaN is printed as `þtt{nan}',
+    infinity as `þtt{inf}'.
+
+þitem þtt{G}
+
+    Floating-point number (þtt{double}); same as þtt{g}, except for
+    þtt{E} being used instead of þtt{e} to introduce the exponent, and
+    `þtt{NAN}' and `þtt{INF}' being printed instead of `þtt{nan}' and
+    `þtt{inf}', respectively.
+
+þitem þtt{i}
+
+    Signed decimal number.  Same as þtt{d}.
+
+þitem þtt{n}
+
+    Store the number of characters formatted up to this point in the
+    FORMAT string (þtt{int *}).  This `conversion' does not create any
+    output.  Use þtt{%hn} when passing a pointer to a þtt{short int},
+    þtt{%ln} when passing a pointer to a þtt{long int} and þtt{%Ln}
+    when passing a pointer to a þtt{long long int}.
+
+þitem þtt{o}
+
+    Unsigned octal number.  The argument is converted to an unsigned
+    integer and printed in octal notation.  Use þtt{%ho} to print an
+    þtt{unsigned short int}, þtt{%lo} to print an þtt{unsigned long
+    int} and þtt{%Lo} to print an þtt{unsigned long long int}.  If the
+    þtt{#} flag is given, the precision will be increased to force the
+    first digit of the result to be a zero.  If the number is zero and
+    the precision is zero (after taking the þtt{#} flag into account),
+    the result will be empty.
+
+þitem þtt{p}
+
+    Pointer (þtt{void *}).  The output format of a pointer is
+    implementation-dependent.  In this implementation, þtt{p} is
+    equivalent to þtt{x}.
+
+þitem þtt{s}
+
+    String (þtt{char *}).  Print characters of the string until a null
+    character is reached or <precision> (if specified) is exhausted.
+    If <precision> is not specified, the string must have a
+    terminating null character.  If <precision> is specified, the
+    string length is limited by <precision>.
+
+þitem þtt{u}
+
+    Unsigned decimal number.  The argument is converted to an unsigned
+    integer and printed in decimal notation.  Use þtt{%hu} to print an
+    þtt{unsigned short int}, þtt{%lu} to print an þtt{unsigned long
+    int} and þtt{%Lu} to print an þtt{unsigned long long int}.
+
+þitem þtt{x}
+
+    Unsigned hexadecimal number.  The argument is converted to an
+    unsigned integer and printed in hexadecimal notation, using
+    lower-case letters.  Use þtt{%hx} to print an þtt{unsigned short
+    int}, þtt{%lx} to print an þtt{unsigned long int} and þtt{%Lx} to
+    print an þtt{unsigned long long int}.  If the þtt{#} flag is given
+    and the number is non-zero, þtt{0x} is prepended.
+
+þitem þtt{X}
+
+    Hexadecimal number (þtt{unsigned int}); same as þtt{x}, except for
+    upper-case letters being used instead of lower-case letters.
+
+þendlist
+
+    The behavior for other <type> characters is undefined, except for
+    þtt{%} immediately following þtt{%}.
+
+þreturnvalue
+
+    printf() returns the number of characters written to stdout.  On
+    error, printf() returns EOF.
+
+þimplementation
+
+    The þtt{#} flag is ignored for the þtt{c}, þtt{d}, þtt{i},
+    þtt{n}, þtt{p}, þtt{s} and þtt{u} conversions.
+
+    <size> can be þtt{L} for the þtt{long long} type (þtt{L} is
+    available for the þtt{d}, þtt{i}, þtt{o}, þtt{u}, þtt{x}, and
+    þtt{X} conversions and for þtt{n}).  þtt{ll} is an alternate
+    spelling for þtt{L}.
+
+þrestrictions
+
+    The output could be more accurate for floating point values.
+
+þhints
+
+    Note that þtt{%lf} is not a valid conversion specifier, use
+    þtt{%f} instead.  Contrast with scanf().
+
+þseealso fopen() fwrite() _itoa() scanf() setlocale() strftime()
+
+þsamplecode
+int year, month, day;
+...
+printf ("%d/%.2d/%.2d\n", year, month, day);
+þendsamplecode
+
+
+þfunction profil()
+þcompat UNIX *
+þheaders
+#include <unistd.h>
+þendheaders
+
+þparam BUFF BUFSIZ OFFSET SCALE
+þprototype
+int profil (void *BUFF, unsigned BUFSIZ, unsigned OFFSET, unsigned SCALE);
+þendprototype
+
+    Sampling profiler.  This function is very experimental, therefore
+    no documentation is provided.  profil() might disappear in the future.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þimplementation
+
+  The sampling frequency is 1024Hz under DOS, 1000Hz under OS/2.
+  Counters are 32-bit words (under Unix, counters usually are 16-bit
+  words).
+
+þrestrictions
+
+  When an attempt to update a counter causes an exception, the program
+  will be terminated (under OS/2) or the system will be stopped (under
+  DOS).
+
+  Under OS/2, SCALE must be þtt{0x4000}, þtt{0x8000}, or þtt{0x10000}.
+
+  Under OS/2, profil() uses an unsupported and undocumented OS/2 API
+  which has several bugs and may be dropped in future versions.  It
+  has been tested on OS/2 3.0 only.
+
+  profil() is not available with the system call library sys.lib
+  (þhpt{-Zsys}).
+
+
+þfunction ptrace()
+þcompat SysV *
+þheaders
+#include <sys/ptrace.h>
+þendheaders
+
+þparam REQUEST PID ADDR DATA
+þprototype
+int ptrace (int REQUEST, int PID, int ADDR, int DATA);
+þendprototype
+
+    Debug a child process.  The child process is identified by PID.
+    The following REQUEST codes are defined:
+
+þdescription
+
+þitem PTRACE_TRACEME
+
+    Not implemented -- use þtt{spawn (P_DEBUG)} instead
+
+
+þitem PTRACE_PEEKTEXT
+
+    Read a 32-bit word from the text space of the child process.
+    ADDR is the address of the word.  The word at ADDR is returned.
+
+þitem PTRACE_PEEKDATA
+
+    See PTRACE_PEEKTEXT.  On machines with separate data and text
+    space, this request will read from the data space.
+
+þitem PTRACE_PEEKUSER
+
+    Read a 32-bit word from the process table of the child process.
+    This can be used to read the registers of the child process.  See
+    <sys/user.h> for details.
+
+þitem PTRACE_POKETEXT
+
+    Write the 32-bit word DATA to address ADDR of the text space of
+    the child process.
+
+þitem PTRACE_POKEDATA
+
+    See PTRACE_POKETEXT.  On machines with separate data and text
+    space, this request will write to the data space.
+
+þitem PTRACE_POKEUSER
+
+    Write a 32-bit word to the process table of the child process.
+    This can be used to alter the registers of the child process.  See
+    <sys/user.h> for details.  Not all registers can be modified.
+
+þitem PTRACE_RESUME
+
+    Resume the child process.  All pending signals will be canceled.
+    If DATA is non-zero, the child process will continue as if it had
+    received that signal.  The child process will run until another
+    signal occurs.
+
+þitem PTRACE_EXIT
+
+    Kill the child process.
+
+þitem PTRACE_STEP
+
+    Execute the next instruction of the child process.  All pending
+    signals will be canceled.  If DATA is non-zero, the child process
+    will continue as if it had received that signal.  If
+    _UF_PTRACE_MULTITHREAD is selected and PID includes a thread ID, one
+    instruction of that thread only will be executed.  Otherwise, one
+    instruction of any of the ready threads will be executed.
+
+þitem PTRACE_SESSION
+
+    If DATA is 0, select the session of the calling process.  If DATA
+    is 1, select the child session.  If DATA is 2, the child session
+    is automatically selected by the next PTRACE_STEP (on þtt{CALL}
+    instructions only) or PTRACE_RESUME command.  This request is emx
+    specific and is ignored under DOS.
+
+þitem PTRACE_NOTIFICATION
+
+    Return the last notification and store data associated with that
+    notification to the buffer pointed to by ADDR.  DATA is the size
+    of the buffer.  If ADDR is NULL or if the size is too small, data
+    won't be stored.  See below for notification codes and data
+    structures.  This request is emx specific and is ignored under
+    DOS.
+
+þitem PTRACE_CONT
+
+    Continue after a notification has been reported.  The previous
+    PTRACE_RESUME or PTRACE_STEP request will be continued.  This
+    request is emx specific and is ignored under DOS.
+
+þitem PTRACE_THAW
+
+    Thaw (enable) the thread identified by PID (which contains both a
+    process ID and a thread ID).  This request is emx specific and is
+    ignored under DOS.
+
+þitem PTRACE_FREEZE
+
+    Freeze (disable) the thread identified by PID (which contains both
+    a process ID and a thread ID).  Note that an attempt to apply
+    PTRACE_STEP to a frozen thread will result in an error.  This
+    request is emx specific and is ignored under DOS.
+
+þitem PTRACE_ATTACH
+
+    Attach a debugger to the process identified by PID.  That process
+    must be a direct or indirect child process of a process started
+    with the P_DEBUGDESC flag set (see þhpt{spawn*()}) and the
+    debugger process debugging the direct parent process of the
+    process identified by PID must still exist (and must continue to
+    exist while the process identified by PID is being debugged).  For
+    each process of this kind, at most one process (debugger) can
+    attach to that process.
+
+þitem PTRACE_DETACH
+
+    Detach a debugger from the process identified by PID.  That
+    process must have been attached to with PTRACE_ATTACH by the same
+    process.  ADDR must be either 0 or 1.  If ADDR is 0, the process
+    identified by PID will remain stopped (allowing another process to
+    attach).  If ADDR is 1, the process identified by PID will resume
+    execution.  The debugger process debugging the direct parent
+    process of the process identified by PID must continue to exist
+    during the entire lifetime of the process identified by PID,
+    otherwise that process will be terminated prematurely or may
+    block.
+
+þenddescription
+
+    If _UF_PTRACE_NOTIFY or _UF_PTRACE_MULTITHREAD has been set with
+    _uflags(), ptrace() will report creation and termination of
+    threads and loading and freeing of modules (DLLs).  If a
+    notification is pending, wait() and waitpid() report the child
+    process as having been stopped by SIGPTRACENOTIFY.  In that case,
+    use the PTRACE_NOTIFICATION request of ptrace() to get more
+    information.  If successful, the PTRACE_NOTIFICATION request of
+    ptrace() will report one of the following values:
+
+þdescription
+
+þitem PTN_THREAD_NEW
+
+    Creation of a new thread.  To obtain the thread ID, pass a pointer
+    to an object of type þtt{struct ptn_thread} in ADDR.  That
+    structure is defined as follows:
+
+þexample
+struct ptn_thread
+{
+  unsigned tid;
+  unsigned long reserved[31];
+};
+þendexample
+
+    The þtt{tid} member will be set to the thread ID.  Creation of the
+    initial thread (thread 1) is also reported.
+
+þitem PTN_THREAD_END
+
+    Termination of a thread.  To obtain the thread ID, pass a pointer
+    to an object of type þtt{struct ptn_thread} in ADDR.  The þtt{tid}
+    member of that structure will be set to the thread ID.
+    Termination of the initial thread (thread 1) is also reported.
+
+þitem PTN_MODULE_LOAD
+
+    Loading of a module.  To obtain the module handle and the full
+    path name of the module, pass a pointer to an object of type
+    þtt{struct ptn_module} in ADDR.  That structure is defined as
+    follows:
+
+þexample
+struct ptn_module
+{
+  unsigned long hmte;
+  unsigned long text_start;
+  unsigned long text_size;
+  unsigned long data_start;
+  unsigned long data_size;
+  unsigned long bss_start;
+  unsigned long bss_size;
+  unsigned long flags;
+  unsigned long reserved[24];
+  char name[260];
+};
+þendexample
+
+    The þtt{hmte} member will be set to the module handle.  The
+    þtt{text_start} member will be set to the start address of the
+    text segment, the þtt{text_size} member will be set to the size of
+    the text segment.  The þtt{data_start} member will be set to the
+    start address of the initialized data segment, the þtt{data_size}
+    member will be set to the size of the initialized data segment.
+    The þtt{bss_start} member will be set to the start address of the
+    uninitialized data segment, the þtt{bss_size} member will be set
+    to the size of the uninitialized data segment.  The þtt{flags}
+    member will have zero or more of the following flags set:
+    PTNMOD_DLL means that the module is a DLL (otherwise, it's the
+    executable file of the program being debugged), PTNMOD_AOUT means
+    that the module has been created with ld and emxbind (otherwise,
+    it has been created with LINK386).  The þtt{name} member will be
+    set to the full path name of the module.
+
+þitem PTN_MODULE_FREE
+
+    Free a module (DLL).  To obtain the module handle and the full
+    path name of the DLL, pass a pointer to an object of type
+    þtt{struct ptn_module} in ADDR.  The þtt{hmte} member of that
+    structure will be set to the module handle, the þtt{name} member
+    will be set to the full path name of the DLL.
+
+þitem PTN_PROC_NEW
+
+    Descendant process started.  This notification occurs only for
+    processes started with the P_DEBUGDESC flag of þhpt{spawn*()} and
+    for child processes of such processes.  The notification is
+    reported to the debugger process debugging the parent process of
+    the new process.  To obtain the process ID and the full path name
+    of the executable file of the descendant process, pass a pointer
+    to an object of type þtt{struct ptn_proc} in ADDR.  That structure
+    is defined as follows:
+
+þexample
+struct ptn_proc
+{
+  unsigned pid;
+  unsigned long flags;
+  unsigned long fork_addr;
+  unsigned long reserved[29];
+  char name[260];
+};
+þendexample
+
+    The þtt{pid} member of that structure will be set to the process
+    ID of the descendant.  The þtt{flags} member will have zero or
+    more of the following flags set: PTNPROC_FORK means that the
+    descendant has been created with fork(), PTNPROC_AOUT means that
+    the executable file has been created with ld and emxbind
+    (otherwise, it has been created with LINK386).  If PTNPROC_FORK is
+    set, þtt{fork_addr} will contain the return address of the
+    þtt{__fork()} system call, that is, the address at which the
+    parent and child processes will continue.  If that address cannot
+    be determined (should not happen), þtt{fork_addr} will be zero.
+    The þtt{name} member will be set to the full path name of the
+    executable file.
+
+    The descendant process will block until a debugger process
+    attaches to the descendant process with PTRACE_ATTACH.  To let the
+    descendant process continue without being debugged, apply
+    PTRACE_ATTACH and then PTRACE_DETACH to the descendant process.
+    If the descendant process has been created with fork(), the parent
+    process also blocks until the startup code of the descendant
+    process has been executed.
+
+þenddescription
+
+    If _UF_PTRACE_MULTITHREAD has been selected with _uflags(),
+    ptrace() supports debugging of multithread procdesses.  In that
+    case, the PID argument of ptrace() contains both a process ID and
+    a thread ID.  The PTRACE_PEEKUSER, PTRACE_POKEUSER, and
+    PTRACE_STEP requests apply to the specified thread only.
+    Moreover, wait() and waitpid() will return both a process ID and a
+    thread ID.  The following macros are used to deal with combined
+    process IDs and thread IDs:
+
+þdescription
+
+þitem PTRACE_GETPID
+
+    Extract the process ID from the value passed as argument.
+
+þitem PTRACE_GETTID
+
+    Extract the thread ID from the value passed as argument.
+
+þitem PTRACE_PIDTID
+
+    Build the PID argument for ptrace(): the first argument is the
+    process ID, the second argument is the thread ID.
+
+þenddescription
+
+þreturnvalue
+
+    See above.  As -1 is a legal return value for the þtt{PTRACE_PEEK}
+    requests, you should set errno to 0 before calling ptrace() and
+    check errno after the call.
+
+þrestrictions
+
+    Under DOS, a process can debug only one child process.  ptrace()
+    is not available with the system call library sys.lib
+    (þhpt{-Zsys}).  Under OS/2, the only signal number which can be
+    passed in DATA for PTRACE_RESUME and PTRACE_STEP is the one of the
+    signal by which the child process has been stopped.
+    Notifications, multithread processes, and debugging of descendants
+    are not supported under DOS.  PTRACE_ATTACH works only under
+    certain circumstances defined above.
+
+þseealso spawn*() _uflags() wait() waitpid()
+
+
+þfunction putc()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam C STREAM
+þprototype
+int putc (int C, FILE *STREAM);
+þendprototype
+
+    Write the character C (converted to an þtt{unsigned char}) to the
+    output stream STREAM and advance the file position indicator of
+    the stream (if defined).
+
+    putc() may be implemented as macro, in contrast to fputc().  In
+    consequence, putc() may evaluate its arguments more than once.
+
+þreturnvalue
+
+    putc() returns the character written.  On error, putc() sets the
+    error indicator of the stream and returns EOF.
+
+þimplementation
+
+    putc() is implemented as in-line function for single-thread
+    programs.
+
+þhints
+
+    Use putc() instead of fputc() if you want to write a lot of
+    characters.
+
+    The arguments of putc() should not be expressions with side
+    effects.
+
+þseealso fputc() putchar()
+
+
+þfunction putchar()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam C
+þprototype
+int putchar (int C);
+þendprototype
+
+    þtt{putchar (c)} is equivalent to þtt{putc (c, stdout)}.
+
+þreturnvalue
+
+    putchar() returns the character written.  On error, putchar() sets
+    the error indicator of stdout and returns EOF.
+
+þimplementation
+
+    putchar() is implemented as in-line function for single-thread
+    programs.
+
+þhints
+
+    Use putchar() instead of fputc() if you want to write a lot of
+    characters to stdout.
+
+    The argument of putchar() should not be an expression with side
+    effects.
+
+þseealso fputc() putc()
+
+
+þfunction putenv()
+þcompat BSD
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam STRING NAME VALUE
+þparam STRING
+þprototype
+int putenv (const char *STRING);
+þendprototype
+
+    Put a value into the environment of the calling process.  STRING
+    is a pointer to a string of the form
+
+þtypewriter
+  "þpa{NAME}=þpa{VALUE}"
+þendtypewriter
+
+    where NAME is the name of the environment variable and VALUE is
+    the value of the environment variable.  If the environment
+    variable NAME already exists, the current value is replaced by the
+    new value, VALUE.  If NAME is not already in the environment,
+    STRING is put into the environment.  Do not free or reuse the
+    string pointed to by STRING after calling putenv().  Using an auto
+    variable is also a bad idea.  After calling putenv(), do not use
+    the þpa{ENVP} argument of main().  Use environ instead.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso getenv()
+
+
+þfunction puts()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STRING
+þprototype
+int puts (const char *STRING);
+þendprototype
+
+    Write the string pointed to by STRING followed by a newline (LF)
+    character (which is translated to CR/LF if stdout is in text mode)
+    to the stdout stream.
+
+þreturnvalue
+
+    On failure, puts() returns EOF.  Otherwise, puts() returns a
+    non-negative value.
+
+þseealso fputs() fgets()
+
+
+þfunction putw()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam X STREAM
+þprototype
+int putw (int X, FILE *STREAM);
+þendprototype
+
+    Write the word (þtt{int}) X to STREAM and return it.  Avoid using
+    this function.
+
+þreturnvalue
+
+    putw() returns X.  On error, getw() returns -1.  As -1 is also a
+    possible word value, you have to use ferror() to recognize an
+    error condition.
+
+þseealso getw() fwrite()
+
+
+þfunction qsort()
+þcompat C90
+
+þheaders
+#include <stdlib.h> /* use this */
+#include <search.h> /* or this */
+þendheaders
+
+þparam BASE NUM WIDTH COMPARE X1 X2
+þprototype
+void qsort (void *BASE, size_t NUM, size_t WIDTH,
+            int (*COMPARE)(const void *X1, const void *X2));
+þendprototype
+
+   Sort an array.  BASE is a pointer to the beginning of the array.
+   The array contains NUM elements of WIDTH bytes each.  COMPARE is
+   called to compare the two elements pointed to by X1 and X2.
+   COMPARE should return a negative value, if element X1 is less than
+   element X2, zero, if element X1 equals element X2, and a positive
+   value if element X1 is greater than element X2.
+
+   þbf{Note:} qsort() is not stable: the order of equal elements is
+   undefined.  To make qsort() stable, add a field to the sort key
+   which holds the index of the element.
+
+
+þfunction raise()
+þcompat C90
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam SIG
+þprototype
+int raise (int SIG);
+þendprototype
+
+    Generate the signal SIG.  If the signal SIG is blocked, the signal
+    will be made pending, to be delivered when it is unblocked.
+
+    Each thread has its own set of signal handlers.  raise() generates
+    the signal in the thread in which it is called.  Use kill() to
+    send the signal to the main thread (thread 1).
+
+    See section þref{signal processing} for details on
+    þhpt{signal processing}.
+
+þreturnvalue
+
+    If successful, raise() returns 0.  Otherwise -1 is returned and
+    errno is set.
+
+þerrors
+þdescription
+þitem EINVAL
+    SIG is not a valid signal number
+þenddescription
+
+þseealso abort() kill() sigaction() signal()
+
+
+þfunction rand() srand()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam SEED
+þprototype
+int rand (void);
+void srand (unsigned int SEED);
+þendprototype
+
+    rand() returns a pseudo-random number in the range 0 through
+    RAND_MAX (32767).  RAND_MAX is defined in <stdlib.h>.  srand()
+    initializes the sequence of random numbers.  The initial SEED
+    value (if srand() is not called) is 1.
+
+    The quality of the random numbers generated by rand() is poor,
+    though it is not as poor as in other implementations of rand().
+    If you need good random numbers, you should use random(), which is
+    in the BSD library.
+
+    In programs linked with the multithread libraries (-Zmt, -Zmts, or
+    -Zmtd), rand() will generate identical sequences of random numbers
+    in all the threads and srand() will affect only the thread in
+    which it is called.  The behavior of rand() is undefined in
+    multithread programs linked with single-thread libraries.
+
+    You must not call rand() or srand() in a thread created by
+    DosCreateThread.
+
+þreturnvalue
+
+    See above.
+
+þif text
+þc þseealso _beginthread() emxbsd.doc
+þelse
+þc þseealso _beginthread() random()
+þendif
+
+
+þfunction read()
+þcompat UNIX
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE BUF NBYTE
+þprototype
+int read (int HANDLE, void *BUF, size_t NBYTE);
+þendprototype
+
+    Read up to NBYTE characters from file HANDLE to the buffer BUF.
+    The number of characters read is returned.  If there is an error,
+    -1 is returned.  The return value may be less than NBYTE.  For
+    instance, this happens if the end of the file is reached.  See
+    also `þhpt{General terminal interface}'.  If HANDLE is 0 and
+    HANDLE refers to the keyboard and O_NONBLOCK (alias O_NDELAY) has
+    been set with fcntl() for HANDLE and the IDEFAULT and ICANON bits
+    have been reset with ioctl() for HANDLE, -1 is returned and errno
+    is set to EAGAIN if the call to read() would block.  Even if there
+    is some data available, but not enough with respect to VMIN, -1 is
+    returned.
+
+    If HANDLE has been opened in text mode, CR/LF pairs are translated
+    to newline characters and a Ctrl-Z character is discarded if it is
+    the last character of the file.
+
+þreturnvalue
+
+    See above.
+
+þseealso open() setmode() write()
+
+
+þfunction _read_kbd()
+þcompat emx *
+þheaders
+#include <stdlib.h>
+#include <sys/kbdscan.h>  /* optional, for extended scan codes */
+þendheaders
+
+þparam ECHO WAIT SIG
+þprototype
+int _read_kbd (int ECHO, int WAIT, int SIG);
+þendprototype
+
+    Get a character from the keyboard.  Extended codes are preceded by
+    a null character (call _read_kbd() again!), the scan codes are
+    defined in <sys/kbdscan.h>.  If ECHO is non-zero, input will be
+    echoed, if WAIT is non-zero, _read_kbd() will wait until a
+    character is available, if WAIT is zero and no character is
+    available, _read_kbd() will return -1, if SIG is zero, Ctrl-C will
+    be ignored.  Examples (taken from <conio.h>):
+
+þexample
+#define getch()  _read_kbd (0, 1, 0)
+#define getche() _read_kbd (1, 1, 0)
+þendexample
+
+    Please use the þhpt{general terminal interface} instead.
+
+    It's important to call _read_kbd() again if _read_kbd() returns 0.
+    To see what happens if you don't, type Ctrl-S F10 under DOS.
+
+þreturnvalue
+
+    See above.
+
+þc þseealso ioctl() read() <conio.h>
+þseealso ioctl() read()
+
+
+þfunction realloc()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam MEM SIZE
+þprototype
+void *realloc (void *MEM, size_t SIZE);
+þendprototype
+
+    Reallocate the block of memory pointed to by MEM, making it big
+    enough to hold SIZE bytes.  If MEM is NULL, a new block of memory
+    is allocated by calling malloc().  Otherwise, MEM must be a
+    pointer returned by calloc(), malloc(), realloc(), _ucalloc(),
+    _umalloc(), or _utcalloc().  In this case, the size
+    of the block pointer to by MEM is changed to SIZE.  If the block
+    pointed to by MEM cannot be expanded in-place, it is moved.  If
+    MEM is non-þtt{NULL} and SIZE is zero, the block is freed and NULL
+    is returned.  A pointer to the new, resized block of memory is
+    returned.  If there is not enough memory available, NULL is
+    returned.
+
+þreturnvalue
+
+    realloc() returns MEM (if the block could be resized without
+    moving), a pointer to a newly allocated block of memory, or NULL
+    (if there wasn't enough memory, or if MEM is non-þtt{NULL} and
+    SIZE is zero).
+
+þimplementation
+
+    Some implementations of realloc() can be applied to blocks freed
+    by free() as long as calloc(), malloc(), and realloc() have not
+    been called since freeing the block.  This implementation of
+    realloc() cannot be applied to freed blocks.
+
+    If MEM is not NULL and the block cannot be moved, realloc() will
+    allocate the new block in MEM's heap.  If MEM is NULL, realloc()
+    will allocate memory from the default heap of the current thread.
+
+þseealso malloc() _mheap() _trealloc() _udefault()
+
+
+þfunction _remext()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam PATH
+þprototype
+void _remext (char *PATH);
+þendprototype
+
+    Remove the extension from the file name pointed to by PATH.  If
+    the last member of the string starts with a dot
+    (þtt{"/usr/mattes/.profile"}, for instance) the string isn't
+    modified.
+
+    _remext() properly handles DBCS characters.
+
+þseealso _defext() _getext() _nls_init() _splitpath()
+
+
+þfunction remove()
+þcompat C90
+
+þheaders
+#include <stdio.h>      /* use this */
+#include <io.h>         /* or this */
+þendheaders
+
+þparam NAME
+þprototype
+int remove (const char *NAME);
+þendprototype
+
+    Delete a file.  NAME is a pointer to a string containing the name
+    of the file to be deleted.  Under OS/2 and DOS, remove() and
+    unlink() are equivalent.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þimplementation
+
+    If the read-only attribute of the file is set, remove() sets errno
+    to EPERM and returns -1.
+
+    If the file is open in any process, remove() sets errno to EACCES
+    and returns -1.
+
+þseealso unlink()
+
+
+þfunction rename()
+þcompat C90
+
+þheaders
+#include <stdio.h>      /* use this */
+#include <io.h>         /* or this */
+þendheaders
+
+þparam OLD_NAME NEW_NAME
+þprototype
+int rename (const char *OLD_NAME, const char *NEW_NAME);
+þendprototype
+
+    Rename the file or directory whose name is in the string pointed
+    to by OLD_NAME to the name pointed to by NEW_NAME.  Moving a file
+    to a different directory on the same drive is possible.  If a file
+    or directory with the name pointed to by NEW_NAME already exists,
+    rename() fails.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þimplementation
+
+    If the file is open in any process, rename() sets errno to EACCES
+    and returns -1.
+
+þrestrictions
+
+    rename() may set errno to EACCES instead of EEXIST if a file or
+    directory with the name pointed to by NEW_NAME already exists.
+    (Why does OS/2 return ERROR_ACCESS_DENIED instead of
+    ERROR_FILE_EXISTS?)
+
+þfunction _response()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam ARGCP ARGVP
+þprototype
+void _response (int *ARGCP, char ***ARGVP);
+þendprototype
+
+    Expand response files.  If you want response files
+    (þtt{@filename}, the file þtt{filename} contains a list of
+    arguments, one per line) to be expanded, call
+
+þexample
+_response (&argc, &argv);
+þendexample
+
+    at the beginning of main().  Response file arguments enclosed in
+    double quotes won't be expanded.  If a response file cannot be
+    opened, the argument is kept unchanged.
+
+þseealso _envargs() main() _wildcard()
+
+
+þfunction rewind()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM
+þprototype
+void rewind (FILE *STREAM);
+þendprototype
+
+    Move the file pointer of STREAM to the beginning of the file and
+    clear the error and end-of-file indicators.
+
+þseealso fseek()
+
+
+þfunction rindex()
+þcompat BSD
+þheaders
+#include <strings.h>
+þendheaders
+
+þparam STRING C
+þprototype
+char *rindex (const char *STRING, int C);
+þendprototype
+
+    Return a pointer to the last occurrence of the character C in the
+    null-terminated string pointed to by STRING.  If there is no
+    character C in the string pointed to by STRING, NULL is returned.
+    If C is 0, a pointer to the terminating null character of the
+    string pointed to by STRING is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso index() strrchr()
+
+
+þfunction rint() rintl()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double rint (double X);
+long double rintl (long double X);
+þendprototype
+
+    Return as floating-point number the integer that is nearest to X.
+    þtt{rint (}þpa{X}þtt{)} is even if there's a tie, that is if
+
+    rintl() uses the þtt{long double} format.
+
+þtypewriter
+  fabs (rint (þpa{X}) - þpa{X}) == 0.5
+þendtypewriter
+
+þreturnvalue
+
+    See above.
+
+þseealso ceil() floor() trunc()
+
+
+þfunction rmdir()
+þcompat BSD
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME
+þprototype
+int rmdir (const char *NAME);
+þendprototype
+
+    Remove the directory whose name is in the string pointed to by
+    NAME.  Only one directory is removed in one step.  If the
+    directory (or a subdirectory thereof) is the current working
+    directory of a process, it cannot be removed.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso mkdir()
+
+
+þfunction _rmtmp()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þprototype
+int _rmtmp (void);
+þendprototype
+
+    Close and delete the files created by tmpfile() in the current
+    working directory.  It must be used only in the directory in which
+    tmpfile() created the temporary files.
+
+þreturnvalue
+
+    _rmtmp() returns the number of closed (and deleted) files.
+
+þseealso tmpfile()
+
+
+þfunction _rmutex_available()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/rmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+int _rmutex_available (_rmutex *SEM);
+þendprototype
+
+    Check if the _rmutex semaphore pointed to by SEM is available or
+    owned, without changing the state of the semaphore and without
+    blocking.  Return zero if the semaphore is owned, return a
+    non-zero value if the semaphore is available.  Note that
+    _rmutex_available() just returns a snapshot of the state of the
+    semaphore; in presence of other threads or, in case of a shared
+    semaphore, other processes, the state may change at any time, even
+    before _rmutex_available() returns. This function can be used to
+    avoid deadlock.
+
+þreturnvalue
+
+    _rmutex_available() returns a non-zero value if the semaphore is
+    available.  _rmutex_available() returns 0 if the semaphore is
+    owned.  The return value is undefined if the object pointed to by
+    SEM has not been initialized by _rmutex_create().
+
+þseealso _fmutex_available() _rmutex_close() _rmutex_create() _rmutex_open() _rmutex_release() _rmutex_request()
+
+
+þfunction _rmutex_close() _rmutex_checked_close()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/rmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+unsigned _rmutex_close (_rmutex *SEM);
+void _rmutex_checked_close (_rmutex *SEM);
+þendprototype
+
+    Close an _rmutex semaphore.  SEM should point to an _rmutex object
+    initialized by _rmutex_create().  If there have been þpa{N} calls
+    to þhpt{_rmutex_open()} for this semaphore, þpa{N}+1 calls to
+    _rmutex_close() are required to destroy the semaphore, one call
+    for þhpt{_rmutex_create()} and one call per _rmutex_open().  The
+    semaphore can no longer be used after it has been destroyed.
+
+    _rmutex_checked_close() does not return an error code; it calls
+    abort() on failure.
+
+þreturnvalue
+
+    _rmutex_close() returns 0 if successful.  Otherwise,
+    _rmutex_close() returns an OS/2 error code defined in <os2.h> such
+    as ERROR_INVALID_HANDLE.  Under DOS, _rmutex_close() always
+    returns 0.
+
+þseealso abort() atexit() _fmutex_close() _rmutex_available() _rmutex_create() _rmutex_open() _rmutex_release() _rmutex_request()
+
+
+þfunction _rmutex_create() _rmutex_checked_create()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/rmutex.h>
+þendheaders
+
+þparam SEM FLAGS
+þprototype
+unsigned _rmutex_create (_rmutex *SEM, unsigned FLAGS);
+void _rmutex_checked_create (_rmutex *SEM, unsigned FLAGS);
+þendprototype
+
+    Create an _rmutex semaphore.  SEM points to the _rmutex object to
+    be initialized.  The semaphore is local to the process if FLAGS is
+    0.  The semaphore can be shared by multiple processes if FLAGS is
+    _FMC_SHARED.  A shared _rmutex semaphore must be located in shared
+    memory (that is, SEM must point to an object in shared memory).
+
+    _rmutex_checked_create() does not return an error code; it calls
+    abort() on failure.
+
+þreturnvalue
+
+    _rmutex_create() returns 0 if successful.  Otherwise,
+    _rmutex_create() returns an OS/2 error code defined in <os2.h>
+    such as ERROR_TOO_MANY_HANDLES.  Under DOS, _rmutex_create()
+    always returns 0.
+
+þseealso abort() _fmutex_create() _rmutex_available() _rmutex_close() _rmutex_dummy() _rmutex_open() _rmutex_release() _rmutex_request()
+
+
+þfunction _rmutex_dummy()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/rmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+void _rmutex_dummy (_rmutex *SEM);
+þendprototype
+
+    Create a dummy _rmutex semaphore.  SEM points to the _rmutex
+    object to be initialized.  Behavior is undefined if ownership of a
+    dummy _rmutex semaphore is requested when the semaphore is owned.
+    _rmutex_close() must not be called on a dummy _rmutex semaphore.
+
+þseealso _fmutex_dummy() _rmutex_create()
+
+
+þfunction _rmutex_open() _rmutex_checked_open()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/rmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+unsigned _rmutex_open (_rmutex *SEM);
+void _rmutex_checked_open (_rmutex *SEM);
+þendprototype
+
+    Open an _rmutex semaphore.  SEM should point to an _rmutex object
+    initialized by þhpt{_rmutex_create()}.  _rmutex_open() is used to
+    obtain access to a shared _rmutex semaphore created by another
+    process.  All threads of the process which called _rmutex_create()
+    have access to the semaphore without calling _rmutex_open().  Call
+    þhpt{_rmutex_close()} when you no longer need access to the
+    semaphore.
+
+    _rmutex_checked_open() does not return an error code; it calls
+    abort() on failure.
+
+þreturnvalue
+
+    _rmutex_open() returns 0 if successful.  Otherwise, _rmutex_open()
+    returns an OS/2 error code defined in <os2.h> such as
+    ERROR_INVALID_HANDLE.  Under DOS, _rmutex_open() always returns 0.
+
+þseealso abort() atexit() _fmutex_open() _rmutex_available() _rmutex_close() _rmutex_create() _rmutex_release() _rmutex_request()
+
+
+þfunction _rmutex_release() _rmutex_checked_release()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/rmutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+unsigned _rmutex_release (_rmutex *SEM);
+void _rmutex_checked_release (_rmutex *SEM);
+þendprototype
+
+    Relinquish ownership of the _rmutex semaphore pointed to by SEM.
+    If another thread blocks in þhpt{_rmutex_request()} for this
+    semaphore, _rmutex_release() will unblock one of the blocking
+    threads.  The semaphore should be owned when _rmutex_release() is
+    called.  Though not strictly necessary, ownership of the semaphore
+    should have been requested by the same thread.
+
+    _rmutex_checked_release() does not return an error code; it calls
+    abort() on failure.  Note that _rmutex_checked_release() is slower
+    than _rmutex_release() because it is not inlined.
+
+þreturnvalue
+
+    _rmutex_release() returns 0 if successful.  Otherwise,
+    _rmutex_release() returns an OS/2 error code defined in <os2.h>
+    such as ERROR_TOO_MANY_HANDLES.
+
+þseealso abort() __cxchg() _fmutex_release() _rmutex_available() _rmutex_close() _rmutex_create() _rmutex_open() _rmutex_request()
+
+
+þfunction _rmutex_request() _rmutex_checked_request()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/rmutex.h>
+þendheaders
+
+þparam SEM FLAGS
+þprototype
+unsigned _rmutex_request (_rmutex *SEM, unsigned FLAGS);
+void _rmutex_checked_request (_rmutex *SEM, unsigned FLAGS);
+þendprototype
+
+    Request ownership of the _rmutex semaphore pointed to by SEM.  If
+    FLAGS is 0, _rmutex_request() returns ERROR_INTERRUPT if
+    interrupted by a signal while blocking.  FLAGS is zero or a set of
+    flags combined with the þtt{|} operator.  If FLAGS includes
+    _FMR_IGNINT, _rmutex_request() does not return if a signal occurs
+    while blocking.  If FLAGS includes _FMR_NOWAIT and the semaphore
+    is owned, _rmutex_request() returns immediately ERROR_MUTEX_OWNED.
+
+    _rmutex_checked_request() does not return an error code; it calls
+    abort() on failure.  Note that _rmutex_checked_request() is slower
+    than _rmutex_request() because it is not inlined.
+
+    If the semaphore is available, it will be set to owned and
+    _rmutex_request() will return immediately.  If the semaphore is
+    owned, _rmutex_request() will block while the semaphore is owned.
+    When þhpt{_rmutex_release()} is called for the semaphore, one of
+    the threads blocking in _rmutex_request() for this semaphore will
+    wake up and gain ownership of the semaphore.
+
+    Note that ownership of an _rmutex semaphore is not tied to a
+    thread, that is, it's not a thread which owns the semaphore.  This
+    is in contrast to OS/2's mutex semaphores (HMTX).  Deadlock will
+    occur if _rmutex_request() is called twice for the same semaphore
+    by the same thread without an intervening call to
+    _rmutex_release().  This fact is important to keep in mind in
+    presence of signals.  Signal handlers must not request semaphores
+    which can be owned by the interrupted code.  You might want to
+    block signals before requesting ownership of an _rmutex semaphore.
+
+þreturnvalue
+
+    _rmutex_request() returns 0 if successful.  Otherwise,
+    _rmutex_request() returns an OS/2 error code defined in <os2.h>
+    such as ERROR_INTERRUPT.
+
+þrestrictions
+
+    Under DOS, _rmutex_request() and _rmutex_checked_request() crash
+    if the semaphore is already owned.
+
+þseealso abort() __cxchg() _fmutex_request() _rmutex_available() _rmutex_close() _rmutex_create() _rmutex_open() _rmutex_release()
+
+
+þfunction sbrk()
+þcompat UNIX
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam INCR
+þprototype
+void *sbrk (int INCR);
+þendprototype
+
+    Change memory allocation by INCR bytes.  If INCR is positive, the
+    memory limit is increased.  If INCR is negative, the memory limit
+    is decreased.  On success, sbrk() returns the previous memory
+    limit.  Otherwise, -1 cast as pointer is returned and errno set to
+    ENOMEM.  Please don't use sbrk() -- use malloc() instead for
+    memory allocation.
+
+    If non-contiguous memory allocation with monotonous addresses
+    (_UF_SBRK_MONOTONOUS) has been enabled with _uflags(), sbrk() may
+    allocate non-contiguous memory.  In that case, sbrk() with
+    non-negative argument returns the base address of the newly added
+    memory area.  Any memory in the gap between the previous memory
+    limit and the base address returned by sbrk() is not accessible.
+    Setting back the memory limit into a gap is not possible.  If
+    non-contiguous memory allocation with arbitrary addresses
+    (_UF_SBRK_ARBITRARY) has been enabled with _uflags(), sbrk() may
+    allocate non-contiguous memory; the memory object may even be at a
+    lower address than the previous one.  In both cases, at most one
+    memory object can be deallocated with sbrk() at a time, that is,
+    you cannot reset the break address with sbrk() to an address
+    outside the most recently allocated memory object.  However, you
+    can deallocate the most recently allcoated memory object by
+    resetting the break address to the start of the that memory
+    object; after doing so, sbrk(0) will return the break address of
+    the memory object which became the top one.
+
+    Currently, there are some restrictions when using a non-contiguous
+    memory: emxbind cannot create a preloaded executable with more
+    than one heap object.  fork() fails if there is more than one heap
+    object.
+
+þreturnvalue
+
+    See above.
+
+þseealso brk() fork() malloc() _uflags() ulimit()
+
+þsamplecode
+/* Allocate memory with sbrk().  This function fails if sbrk()
+   does not return contiguous memory.  Return a pointer to the
+   new memory area.  Return NULL on error.  This function assumes
+   that no other thread calls sbrk(). */
+
+void *more_memory (size_t n)
+{
+  oid *prev, *base;
+
+  if ((int)n < 0)               /* Check for overflow */
+    return NULL;
+  prev = sbrk (0);              /* Get current memory limit */
+  if (prev == (void *)-1)
+    return NULL;                /* Error */
+  base = sbrk ((int)n);         /* Allocate memory */
+  if (base == (void *)-1)
+    return NULL;                /* Error */
+  if (prev != base)             /* Non-contiguous? */
+    {
+      sbrk (-(int)n);           /* Free non-contiguous memory */
+      return NULL;              /* Failure */
+    }
+  return base;                  /* Success */
+}
+þendsamplecode
+
+
+þfunction scanf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam FORMAT <width> <size> <type>
+þprototype
+int scanf (const char *FORMAT, ...);
+þendprototype
+
+    The stdin stream is read and input is parsed according to the
+    format string pointed to by FORMAT.  For each field in the format
+    string there must be a pointer to the location receiving the
+    value.  The pointers are passed after the FORMAT argument.
+
+    Whitespace (any number of spaces) in the format string matches
+    whitespace (any number of spaces, including zero) in the input.
+    All other characters except for þtt{%} are compared to the input.
+    Parsing ends when a mismatch is encountered.  þtt{%%} in the
+    format string matches þtt{%} in the input.  A þtt{%} which is not
+    followed by another þtt{%} or the end of the string starts a field
+    specification.  The field in the input is interpreted according to
+    the field specification.  For most field types, whitespace is
+    ignored at the start of a field.  Field specifications have the
+    format
+
+þindent
+  þsy{%[*][<width>][<size>]<type>}
+þendindent
+
+    where items in brackets are optional.  If the þtt{*} is present, the
+    value is not assigned.  No pointer will be fetched from the
+    argument list and the value is ignored.
+
+    <width> is a positive integral decimal number specifying the maximum
+    field width.  At most this many characters are read for this
+    field.
+
+    <size> is either þtt{h} for a þtt{short} type (þtt{h} is available
+    for the þtt{d}, þtt{i}, þtt{o}, þtt{u}, and þtt{x} conversions and
+    for þtt{n}), þtt{l} for a þtt{long} type (þtt{l} is available for
+    the þtt{d}, þtt{i}, þtt{o}, þtt{u}, and þtt{x} conversions and for
+    þtt{n}) or the þtt{double} type (þtt{l} is also available for the
+    þtt{e}, þtt{f}, and þtt{g} conversions) or þtt{L} for the þtt{long
+    double} type (þtt{L} is available for the þtt{e}, þtt{f}, and
+    þtt{g} conversions).  If <size> is omitted, the default size is
+    used.
+
+    <type> is one of the following characters:
+
+þlist
+þitem þtt{c}
+
+    Character (þtt{char}).  Whitespace is not skipped.  If a field
+    width is specified, that many characters are read and assigned,
+    without a terminating null character (þtt{char[]}).  If no field
+    width is specified, one character will be read and assigned.
+
+þitem þtt{d}
+
+    Signed decimal integer (þtt{int}).  þtt{%hd} is used for þtt{short
+    int}, þtt{%ld} is used for þtt{long int} and þtt{%Ld} is used for
+    þtt{long long int}.
+
+þitem þtt{e f g E F G}
+
+    Floating-point number (þtt{float}).  þtt{%le} etc. is used for
+    þtt{double}, þtt{%Le} etc. is used for þtt{long double}.  scanf()
+    accepts the same format of float-point numbers as þhpt{strtod()}.
+    The decimal point character of the current locale is used.
+
+þitem þtt{i}
+
+    Decimal, octal or hexadecimal signed integer (þtt{int}).  þtt{%hi}
+    is used for þtt{short int}, þtt{%li} is used for þtt{long int} and
+    þtt{%Li} is used for þtt{long long}.  The base is 16 if the number
+    begins with þtt{0x} or þtt{0X}.  The base is 8 if the number
+    begins with þtt{0} (not followed by an þtt{x} or þtt{X}).
+    Otherwise, the base is 10.
+
+þitem þtt{n}
+
+    Number of characters read so far (þtt{int}).  No input is taken.
+    The number of characters read so far is assigned to the integer
+    (unless assignment is suppressed with the þtt{*} flag).  Use
+    þtt{%hn} to assign to a þtt{short int}, þtt{%ln} to assign to a
+    þtt{long int} or þtt{%Ln} to assign to a þtt{long long int}.
+
+þitem þtt{o}
+
+    Octal unsigned integer (þtt{unsigned}).  þtt{%ho} is used for
+    þtt{unsigned short}, þtt{%lo} is used for þtt{unsigned long int}
+    and þtt{%Lo} is used for þtt{unsigned long long int}.
+    The input may contain a sign character.
+
+þitem þtt{p}
+
+    Pointer (þtt{void *}).  The input format of a pointer is
+    implementation-dependent.  In this implementation, þtt{p} is equivalent
+    to þtt{x}.
+
+þitem þtt{s}
+
+    Read and assign characters until the field width is exhausted or
+    hitting whitespace (þtt{char[]}).  The destination array must be
+    big enough to hold all the characters.  Note that initial
+    whitespace is skipped.  Perhaps you want to use þtt{%[...]}
+    instead of þtt{%s}.
+
+þitem þtt{u}
+
+    Unsigned decimal integer (þtt{unsigned int}).  þtt{%hu} is used
+    for þtt{unsigned short int}, þtt{%lu} is used for þtt{unsigned
+    long int} and þtt{%Lu} is used for þtt{unsigned long long int}.
+    The input may contain a sign character.
+
+þitem þtt{x}
+
+    hexadecimal integer (þtt{unsigned int}).  þtt{%hx} is used for
+    þtt{unsigned short int}, þtt{%lx} is used for þtt{unsigned long
+    int} and þtt{%Lx} is used for þtt{unsigned long long int}. The
+    input may contain a sign character.
+
+þitem þtt{[}
+
+    Null-terminated string (þtt{char[]}).  White space is not skipped.
+    þtt{[} is followed by a set of characters which is delimited by
+    þtt{]}.  The field ends at the first character not in the
+    character set þtt{[...]}.  If þtt{[^...]} is used, the field ends
+    at the first character in that set.  The field also ends when the
+    field width is exhausted.  The set contains all characters listed
+    in the brackets.  To include a þtt{]} in the set, make it the
+    first character of the set.  You can specify a range of characters
+    by listing the first and the last character, separated by a
+    þtt{-}.  To include a þtt{-} in the set, make it the last
+    character of the set.  The destination array must be big enough to
+    hold all the characters.
+
+þendlist
+
+    scanf() puts back into the stream at most one conflicting
+    character.  In consequence, some character sequences acceptable to
+    strtod(), strtof(), strtol(), strtold(), and strtoul() are not
+    acceptable to scanf().
+
+þreturnvalue
+
+    If successful, scanf() returns the number of fields converted.  On
+    error, scanf() returns EOF.
+
+þimplementation
+
+    <size> can be þtt{L} for þtt{long long} types (þtt{L} is available
+    for the þtt{d}, þtt{i}, þtt{o}, þtt{u}, and þtt{x} conversions and
+    for þtt{n})).
+
+þhints
+
+    To read user input, you should use fgets() and sscanf() instead of
+    scanf() because scanf() doesn't stop reading at the end of the
+    line.
+
+    Use þtt{%lf} for variables of type þtt{double}.  Contrast with
+    printf().
+
+þseealso fgets() fread() fscanf() printf() setlocale() sscanf() strptime() strtod() strtol() vscanf()
+
+þsamplecode
+int year, month, day;
+...
+if (scanf ("%d/%d/%d", &year, &month, &day) == 3)
+  {
+    ...
+  }
+þendsamplecode
+
+
+þfunction _scrsize()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam DST
+þprototype
+void _scrsize (int *DST);
+þendprototype
+
+    Retrieve the screen (window) size.  The number of text columns
+    (width) is stored to þpa{DST}þtt{[0]}, the number of text rows
+    (height) is stored to þpa{DST}þtt{[1]}.
+
+þseealso v_dimen()
+
+
+þfunction _searchenv()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam NAME VAR PATH
+þprototype
+void _searchenv (const char *NAME, const char *VAR, char *PATH);
+þendprototype
+
+    Search a file in the directories listed in an environment
+    variable.  First, the file name pointed to by NAME is tried as is.
+    If that file does not exist, the directories listed in the
+    environment variable whose name is in the string pointed to by VAR
+    are searched.  If the file is found, the constructed path name
+    (either the string pointed to by NAME or a directory plus the
+    string pointed to by NAME) will be copied to the array pointed to
+    by PATH.  If the file is not found, the empty string will be
+    stored to the array pointed to by PATH.
+
+    _searchenv() properly handles DBCS characters.
+
+þseealso getenv() _nls_init() _path()
+
+
+þfunction _seek_hdr()
+þcompat emx
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int _seek_hdr (int HANDLE);
+þendprototype
+
+    Move the file pointer of HANDLE to the a.out header of an
+    executable file (a.out or bound .exe).  _seek_hdr() assumes that
+    the file pointer points to the beginning of the header (ie, the
+    beginning of the file).  If no header is found, the file pointer
+    will be repositioned to the original position.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error (errno is set)
+þenddescription
+
+þseealso _fseek_hdr()
+
+
+þfunction select()
+þcompat UNIX *
+þheaders
+#include <sys/select.h>
+þendheaders
+
+þparam NFDS READFDS WRITEFDS EXCEPTFDS TIMEOUT
+þprototype
+int select (int NFDS, fd_set *READFDS, fd_set *WRITEFDS, fd_set *EXCEPTFDS,
+            struct timeval *TIMEOUT);
+þendprototype
+
+    Wait for a file handle to become ready for reading, writing, or
+    until an exceptional situation exists for a file handle, or until
+    a time-out expires.  `Ready for reading' means that a call to
+    read() in blocking mode (O_NONBLOCK not being set) will return
+    immediately, that is, will transfer data and return a positive
+    number, will transfer no data and return zero, or will report an
+    error (except EAGAIN alias EWOULDBLOCK) by returning -1.  `Ready
+    for writing' means that a call to write() in blocking mode will
+    return immediately, that is, will transfer data and return a
+    positive number, will transfer no data and return zero, or will
+    report an error (except EAGAIN alias EWOULDBLOCK) by returning -1.
+    `Exceptional situations' means pending errors for sockets.  No
+    other exceptional situations are currently defined.
+
+    select() returns as soon as any handle in the set pointed to by
+    READFDS is ready for reading, or a handle in the set pointed to by
+    WRITEFDS is ready for writing, or an exceptional situation exists
+    for a handle in the set pointed to by EXCEPTFDS.  READFDS,
+    WRITEFDS, and EXCEPTFDS can each be NULL.  If TIMEOUT is NULL,
+    select() waits indefinitely.  Otherwise, waiting terminates after
+    the time-out pointed to by TIMEOUT expired.  NFDS is the number of
+    handles to be checked.
+
+    select() updates the objects pointed to by READFDS, WRITEFDS, and
+    EXCEPTFDS to include only the handles which are ready for reading,
+    writing, or for which an exceptional situation exists,
+    respectively, and returns the number of those handles.
+
+    Some implementations of select() update the object pointed to by
+    TIMEOUT to reflect the amount of time remaining.  The emx
+    implementation of select() currently doesn't do this and probably
+    won't do this.
+
+    The following macros are available for handling the bitstrings
+    used by select():
+
+þlist
+
+þitem þtt{FD_ZERO(}þpa{S}þtt{)}
+
+    clear all bits of þpa{S}
+
+þitem þtt{FD_SET(}þpa{N}þtt{,}þpa{S)}
+
+    set bit þpa{N} in þpa{S}
+
+þitem þtt{FD_CLR(}þpa{N}þtt{,}þpa{S}þtt{)}
+
+    clear bit þpa{N} in þpa{S}
+
+þitem þtt{FD_ISSET(}þpa{N}þtt{,}þpa{S)}
+
+    return a non-zero value iff bit þpa{N} is set in þpa{S}
+
+þendlist
+
+    The FD_SETSIZE macro specifies the number of file handles in an
+    fd_set object.  The default value is 256.  To increase the number
+    of file descriptors in fd_set, define FD_SETSIZE before including
+    <sys/types.h> and <sys/select.h>.  The FD_ZERO macro and
+    assignment of fd_set objects use the size of the object; in
+    consequence, you must be careful when passing pointers to fd_set
+    objects between modules which have been compiled with different
+    values for FD_SETSIZE (libraries!).
+
+    select() is implemented for the following types of handles:
+
+þitemize
+
+þitem
+
+    Standard input handles (keyboard) with IDEFAULT not set (DOS:
+    handle 0 only).  Note that if ICANON is set, read() has to wait
+    until the line is completed.  If IDEFAULT is set (that's the
+    initial setting), standard input handles are reported as being
+    ready
+
+þitem
+
+    Pseudo TTYs of xf86sup.sys
+
+þitem
+
+    Named pipes.  Named pipes are always reported to be ready for
+    writing
+
+þitem
+
+    Pipes created with pipe() by programs using emx.dll; such pipes
+    are always reported to be ready for writing
+
+þitem
+
+    Sockets under OS/2
+
+þitem
+    ASYNC devices (such as þtt{COM1}) under OS/2
+
+þitem
+
+    All file handles under DOS; regular files are reported to be ready
+    for reading if the file pointer is not at the end of the file --
+    this behavior may change in the future: regular files should be
+    reported to be always ready for reading
+
+þenditemize
+
+    All handle types not supported by select() are reported to be
+    ready for reading and ready for writing and having no exceptional
+    situation pending.
+
+    The þtt{timeval} structure is defined as follows:
+
+þexample
+struct timeval
+{
+  long tv_sec;
+  long tv_usec;
+};
+þendexample
+
+    þtt{tv_sec} and þtt{tv_usec} are the number of seconds and
+    microseconds, respectively.
+
+þreturnvalue
+þdescription
+þitem >0
+    number of ready handles
+þitem 0
+    time out
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    select() is not available with the system call library sys.lib
+    (þhpt{-Zsys}).
+
+þseealso ioctl() pipe()
+
+
+þfunction setbuf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM BUFFER
+þprototype
+int setbuf (FILE *STREAM, char *BUFFER);
+þendprototype
+
+    Associate the buffer of size BUFSIZ pointed to by BUFFER with
+    STREAM.  This must be done before the file has been read or
+    written.  If BUFFER is NULL, the file is unbuffered.  You should
+    use setvbuf() instead.
+
+þreturnvalue
+
+þdescription
+þitem 0
+    success
+þitem EOF
+    error
+þenddescription
+
+    BSD setbuf() seems to have an þtt{int} return value, therefore emx
+    setbuf() has an þtt{int} return value.  This should not break
+    programs which expect þtt{void setbuf()}.
+
+þseealso setbuffer() setvbuf()
+
+
+þfunction setbuffer()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM BUFFER SIZE
+þprototype
+int setbuffer (FILE *STREAM, char *BUFFER, size_t SIZE);
+þendprototype
+
+    Associate the buffer of size SIZE pointed to by BUFFER with
+    STREAM.  This must be done before the file has been read or
+    written.  If BUFFER is NULL, the file is unbuffered.  You should
+    use setvbuf() instead.
+
+þreturnvalue
+
+þdescription
+þitem 0
+    success
+þitem EOF
+    error
+þenddescription
+
+    BSD setbuffer() seems to have an þtt{int} return value, therefore
+    emx setbuffer() has an þtt{int} return value.  This should not
+    break programs which expect þtt{void setbuffer()}.
+
+þseealso setvbuf()
+
+
+þfunction setjmp()
+þcompat C90
+þheaders
+#include <setjmp.h>
+þendheaders
+
+þparam HERE
+þprototype
+int setjmp (jmp_buf HERE);
+þendprototype
+
+    Save the current stack context in HERE and return 0.  Later, you
+    can continue at this point by calling longjmp().  When execution
+    continues at setjmp() after calling longjmp(), the second argument
+    of longjmp() is returned, which is always non-zero (if zero is
+    used as second argument of longjmp(), it will be turned into 1).
+
+    setjmp() may be implemented as macro.  setjmp() can be used only
+    in the following contexts:
+
+þitemize
+þitem
+  the entire controlling expression of a þtt{do}, þtt{if},
+  þtt{switch}, or þtt{while} statement
+þitem
+  the operand to the þtt{!} operator if the resulting expression is
+  the entire controlling expression of one of the statements listed
+  above
+þitem
+  the operand of a relational or equality operator if the resulting
+  expression is the entire controlling expression of one of the
+  statements listed above and the other operand is an integral
+  constant expression
+þitem
+  the entire expression of an expression statement.
+þenditemize
+
+þreturnvalue
+
+    setjmp() returns 0 when directly called.  When returning from a
+    call to longjmp(), setjmp() returns a non-zero value (supplied by
+    the call to longjmp()).
+
+þimplementation
+
+    The restrictions on the contexts in which setjmp() can be used do
+    not apply.
+
+þhints
+
+    As jmp_buf is an array type, the þtt{&} operator need not be
+    applied.
+
+þseealso longjmp() siglongjmp() sigsetjmp()
+
+
+þfunction setlocale()
+þcompat C90
+þheaders
+#include <locale.h>
+þendheaders
+
+þparam CATEGORY LOCALE
+þprototype
+char *setlocale (int CATEGORY, const char *LOCALE);
+þendprototype
+
+    Select a locale.  Either the entire locale or a portion of the
+    locale is set, depending on CATEGORY:
+
+þlist
+þitem LC_ALL
+
+    Set the entire locale, including categories LC_COLLATE, LC_CTYPE,
+    LC_MONETARY, LC_NUMERIC and LC_TIME.
+
+þitem LC_COLLATE
+
+    Control the behavior of strcoll() and strxfrm().
+
+þitem LC_CTYPE
+
+    Control the behavior of isalnum(), isalpha(), iscntrl(),
+    isgraph(), islower(), isprint(), ispunct(), isspace(), isupper(),
+    tolower(), toupper(), mblen(), mbstowcs(), mbtowc(), wcstombs()
+    and wctomb().  This also affects the interpretation of multibyte
+    character format strings by printf(), scanf() and strftime().
+    Note that isdigit() and isxdigit() are not affected.
+
+þitem LC_MONETARY
+
+    Set the information related to formatting of monetary quantities.
+    This affects the contents of the structure returned by
+    localeconv().
+
+þitem LC_NUMERIC
+
+    Select the decimal point character for atof(), _atofl(), gcvt(),
+    printf(), scanf(), strtod(), strtof(), and strtold().  Set the
+    information related to formatting of numeric quantities.  This
+    affects the contents of the structure returned by localeconv().
+
+þitem LC_TIME
+
+    Control the behavior of strftime().
+
+þendlist
+
+    If LOCALE points to the empty string þtt{""}, the value of the
+    environment variable LANG is taken instead.  If LANG is not set,
+    þtt{"C"} is used for LOCALE.  þtt{"C"} is the initial locale at
+    program startup.  It provides the usual C conversions.
+
+    Other possible values of LOCALE are þtt{LC_C_FRANCE},
+    þtt{LC_C_GERMANY}, þtt{LC_C_ITALY}, þtt{LC_C_SPAIN}, þtt{LC_C_UK},
+    þtt{LC_C_USA}, þtt{"de_de"}, þtt{"en_us"}, and þtt{"en_gb"}.
+
+    If LOCALE is a null pointer, a pointer to the string associated
+    with CATEGORY for the currently selected locale is returned.  That
+    string can be used as LOCALE with CATEGORY for restoring that
+    locale.  If CATEGORY is LC_ALL and different locale strings are
+    associated with the categories, a pointer to a string is returned
+    which selects those locales when used with LC_ALL.
+
+    All threads of a process share the same locale.
+
+þreturnvalue
+
+    setlocale() returns NULL on error.  Otherwise, it returns a
+    pointer to the string associated with CATEGORY for the new locale
+    (or the current one if LOCALE is NULL).  The string must not be
+    modified by the program; it may be overwritten by a subsequent
+    call to setlocale().
+
+þrestrictions
+
+    Currently, information associated with LC_COLLATE and LC_CTYPE is
+    ignored.  Moreover, strftime() always assumes that code page 850
+    is in effect.
+
+þseealso isupper() localeconv() mbtowc() strcoll() strftime() strxfrm()
+
+
+þfunction setmode()
+þcompat PC
+þheaders
+#include <io.h>
+#include <fcntl.h>
+þendheaders
+
+þparam HANDLE MODE
+þprototype
+int setmode (int HANDLE, int MODE);
+þendprototype
+
+    Change the text/binary mode of a file handle.  MODE must be either
+    O_BINARY or O_TEXT.
+
+    þbf{Note:} Use _fsetmode() to change the mode of a stream.
+
+þreturnvalue
+
+  If there's an error, setmode() returns -1 and sets errno to EBADF or
+  EINVAL otherwise setmode() returns the previous mode, that is,
+  O_BINARY or O_TEXT.
+
+þseealso _fsetmode() open()
+
+
+þfunction _setsyserrno()
+þcompat emx *
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam CODE
+þprototype
+int _setsyserrno (int CODE);
+þendprototype
+
+    Make the next _syserrno() call return CODE.  This function returns
+    the OS/2 or DOS error code for the last system call of the current
+    thread, like _syserrno().
+
+þreturnvalue
+
+    See above.  If _setsyserrno() is not implemented, -1 will returned
+    without setting errno.
+
+þrestrictions
+
+    _setsyserrno() is not implemented under DOS.  _setsyserrno() is
+    not supported with the system call library sys.lib (þhpt{-Zsys}).
+
+þseealso errno _syserrno()
+
+þfunction settimeofday()
+þcompat BSD
+þheaders
+#include <sys/time.h>
+þendheaders
+
+þparam TP TZP
+þprototype
+int settimeofday (const struct timeval *TP, const struct timezone *TZP);
+þendprototype
+
+    Set the system time and timezone.  If TP is not NULL, the system
+    time is set to the time (Coordinated Universal Time) specified by
+    the structure pointed to by TP.  If TZP is not NULL, the timezone
+    is set according to the structure pointed to by TZP.
+
+    The þtt{timeval} structure is defined as follows:
+
+þexample
+struct timeval
+{
+  long tv_sec;
+  long tv_usec;
+};
+þendexample
+
+    þtt{tv_sec} and þtt{tv_usec} are the number of seconds and
+    microseconds, respectively, elapsed since 00:00:00 1-Jan-1970 UTC.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þrestrictions
+
+    Setting the timezone is not implemented, TZP must be a null
+    pointer.  The real time clock is not set under DOS versions
+    earlier than 3.3.
+
+þseealso gettimeofday() ftime() time()
+
+
+þfunction setvbuf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STREAM BUFFER MODE SIZE
+þprototype
+int setvbuf (FILE *STREAM, char *BUFFER, int MODE, size_t SIZE);
+þendprototype
+
+    Set the buffering mode of STREAM to MODE.  The array of SIZE bytes
+    pointed to by BUFFER may be used instead of a buffer allocated by
+    setvbuf() if BUFFER is not NULL.  Available modes are:
+
+þdescription
+
+þitem _IONBF
+
+    the file is unbuffered, BUFFER and SIZE are always ignored
+
+þitem _IOFBF
+
+    the file is full buffered
+
+þitem _IOLBF
+
+    the file is line buffered
+
+þenddescription
+
+    The file must not have been read or written since it was opened.
+
+þreturnvalue
+
+    On success, setvbuf() returns 0.  On failure, setvbuf() returns a
+    non-zero value.
+
+þimplementation
+
+    This implementation of setvbuf() uses BUFFER unless MODE is _IONBF
+    or SIZE is invalid.  If SIZE is invalid, a buffer of BUFSIZ bytes
+    is used.
+
+    For reading a file, _IOFBF and _IOLBF are equivalent.  Each time a
+    newline character is written to a line-buffered file, the buffer
+    is flushed.  The buffer is also flushed if it becomes full while
+    writing.  The buffer is filled by reading from the disk file (or
+    device) if the buffer becomes empty while reading.
+
+þseealso fflush() fputs() fwrite()
+
+
+þfunction sigaction()
+þcompat POSIX.1 *
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam SIG IACT OACT
+þprototype
+int sigaction (int SIG, const struct sigaction *IACT,
+               struct sigaction *OACT);
+þendprototype
+
+    Examine and/or specify the action associated with the signal SIG.
+    If IACT is not NULL, it points to a structure specifying the
+    action to be associated with the signal SIG.  If IACT is NULL, the
+    action for signal SIG won't be changed.  If OACT is not NULL, the
+    previous action for signal SIG will be stored to the object
+    pointed to by OACT.
+
+    The þtt{sigaction} structure is defined as follows:
+
+þexample
+struct sigaction
+{
+  void (*sa_handler)(int sig);
+  sigset_t sa_mask;
+  int sa_flags;
+};
+þendexample
+
+    sa_handler can be SIG_DFL (to get the default action), SIG_IGN (to
+    ignore the signal), or the address of a signal-catching function
+    (signal handler).
+
+    sa_mask is a set of signals to be blocked prior to calling the
+    signal-catching function.  sa_mask is ignored for the `emx' and
+    `System V' signal models.
+
+    Every object of type sigset_t should be initialized at least once
+    with either sigemptyset() or sigfillset() before any use.  When
+    using an uninitialized object of type sigset_t, the results are
+    undefined.
+
+    sa_flags is a set of flag bits used to modify the behavior of the
+    signal SIG.  The following flag bits are available:
+
+þdescription
+þitem SA_NOCLDSTOP
+
+    Do not generate SIGCHLD when a child process stops.
+
+þitem SA_SYSV
+
+    Use the `System V' signal model for the signal SIG: before calling
+    a signal-catching function, reset the signal action to SIG_DFL,
+    don't block the signal, and ignore sa_mask.
+
+þitem SA_ACK
+
+    Use the `emx' signal model for the signal SIG: ignore sa_mask, use
+    SIG_ACK for unblocking the signal.
+
+þenddescription
+
+    In a multithread program, sigaction() examines and sets the
+    signal action for the thread in which it is called.  Signal action
+    settings are private to each thread.
+
+    If the previous signal action for signal SIG has been set by
+    signal(), the value of the object pointed to by OACT is
+    unspecified; however, if that object is subsequently used for
+    setting the signal action with sigaction(), handling of the signal
+    is as if the original call to signal() were repeated.
+
+    See section þref{signal processing} for details on
+    þhpt{signal processing}.
+
+þreturnvalue
+
+    If successful, sigaction() returns 0.  Otherwise sigaction()
+    sets errno and returns -1.
+
+þerrors
+
+þdescription
+þitem EINVAL
+
+    SIG is not a valid signal number or an attempt was made to catch a
+    signal that cannot be caught or to ignore a signal that cannot be
+    ignored.
+
+þenddescription
+
+þimplementation
+
+    The SA_ACK and SA_SYSV flag bits of sa_flags are emx extensions.
+
+þrestrictions
+
+    The SA_NOCLDSTOP flag bit of sa_flags is ignored as stopped
+    processes are not supported (except for ptrace()).
+
+þseealso raise() kill() sigemptyset() signal() sigpending() sigprocmask()
+
+þsamplecode
+void sig_cleanup (int signo)
+{
+  cleanup ();
+  printf ("Process terminated by signal %d\n", signo);
+  exit (99);
+}
+
+void sig_init (void)
+{
+  struct sigaction sa;
+
+  sa.sa_handler = sig_cleanup;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGINT, &sa, NULL);
+}
+þendsamplecode
+
+
+þfunction sigaddset() sigdelset()
+þcompat POSIX.1 *
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam SET SIG
+þprototype
+int sigaddset (sigset_t *SET, int SIG);
+int sigdelset (sigset_t *SET, int SIG);
+þendprototype
+
+    sigaddset() adds the signal SIG to the set of signals pointed to
+    by SET.
+
+    sigdelset() deletes the signal SIG from the set of signals pointed
+    to by SET.
+
+    Every object of type sigset_t should be initialized at least once
+    with either sigemptyset() or sigfillset() before any use.  When
+    using an uninitialized object of type sigset_t, the results are
+    undefined.
+
+þreturnvalue
+
+    If successful, sigaddset() and sigdelset() return 0.  Otherwise,
+    these functions set errno and return -1.
+
+þerrors
+
+þdescription
+þitem EINVAL
+
+    SIG is not a valid signal number.
+
+þenddescription
+
+þseealso sigemptyset() sigfillset() sigismember()
+
+
+þfunction sigemptyset() sigfillset()
+þcompat POSIX.1 *
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam SET
+þprototype
+int sigemptyset (sigset_t *SET);
+int sigfillset (sigset_t *SET);
+þendprototype
+
+    sigemptyset() initializes the object pointed to by SET to an empty
+    set of signals.
+
+    sigfillset() initializes the object pointed to by SET to a signal
+    set which includes all signals.
+
+    Every object of type sigset_t should be initialized at least once
+    with either sigemptyset() or sigfillset() before any use.  When
+    using an uninitialized object of type sigset_t, the results are
+    undefined.
+
+þreturnvalue
+
+    If successful, sigemptyset() and sigfillset() return 0.  Otherwise,
+    these functions set errno and return -1.
+
+þseealso sigaction() sigaddset() sigdelset() sigprocmask() sigismember()
+
+
+þfunction sigismember()
+þcompat POSIX.1 *
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam SET SIG
+þprototype
+int sigismember (const sigset_t *SET, int SIG);
+þendprototype
+
+    sigismember() tests whether the signal SIG is a member of the set
+    of signals pointed to by SET.
+
+    Every object of type sigset_t should be initialized at least once
+    with either sigemptyset() or sigfillset() before any use.  When
+    using an uninitialized object of type sigset_t, the results are
+    undefined.
+
+þreturnvalue
+
+    sigismember() returns 1 if the signal SIG is a member of the set
+    of signals pointed to by SET, or 0 if the signal SIG is not a
+    member of the set of signals pointed to by SET.  On error,
+    sigismember() sets errno and returns -1.
+
+þerrors
+
+þdescription
+þitem EINVAL
+
+    SIG is not a valid signal number.
+
+þenddescription
+
+þseealso sigaddset() sigdelset() sigemptyset() sigfillset()
+
+
+þfunction siglongjmp()
+þcompat POSIX.1
+þheaders
+#include <setjmp.h>
+þendheaders
+
+þparam THERE N SAVEMASK
+þprototype
+void siglongjmp (sigjmp_buf THERE, int N);
+þendprototype
+
+    Restore the context saved in THERE by sigsetjmp() and -- if the
+    SAVEMASK argument of sigsetjmp() was non-zero -- restore the
+    signal mask saved by sigsetjmp() .  siglongjmp() does a non-local
+    þtt{goto}, causing execution to continue at the sigsetjmp() call
+    which most recently saved a stack context in THERE.  sigsetjmp()
+    will return N.  If N is 0, sigsetjmp() will return 1.  When
+    calling siglongjmp() in a signal handler or in a function called
+    by a signal handler (that is, while a signal handler is active),
+    the signal handler will be unwound, that is, it is assumed that
+    the signal handler doesn't return.  siglongjmp() must be called in
+    the same thread as the most recent call to sigsetjmp() for THERE.
+    Moreover, the function which most recently called sigsetjmp() to
+    save a stack context in THERE must still be active.  Don't expect
+    local variables to be preserved unless declared volatile.
+
+    As sigjmp_buf is an array type, the þtt{&} operator need not be
+    applied.
+
+þseealso longjmp() setjmp() sigaction() sigprocmask() sigsetjmp() signal()
+
+
+þfunction signal()
+þcompat C90
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam SIG HANDLER
+þprototype
+void (*signal (int SIG, void (*HANDLER)()))(int SIG);
+þendprototype
+
+    Set the signal action associated with signal SIG.  HANDLER can be
+    SIG_DFL (to get the default action), SIG_IGN (to ignore the
+    signal), or the address of a signal-catching function (signal
+    handler).
+
+    On delivery of the signal, the signal number is passed as the only
+    argument to the signal-catching function.  Before the
+    signal-catching funcion is called, the signal is blocked or the
+    signal action is reset to SIG_DFL, depending on the signal
+    processing model.
+
+    The action associated with SIGKILL cannot be changed.
+
+    In a multithread program, signal() sets a signal handler for
+    the thread in which it is called.  The set of signal handlers is
+    private to each thread.
+
+    On delivery, the signal is blocked before calling the signal
+    handler, if the `emx' signal model is used and the signal is
+    caught (that is, a signal handler is installed).  To unblock the
+    signal SIG, call
+
+þexample
+signal (sig, SIG_ACK)
+þendexample
+
+    See section þref{signal processing} for details on
+    þhpt{signal processing}.
+
+þreturnvalue
+
+    If successful, signal() returns the previous signal action
+    (SIG_IGN or SIG_DFL or the address of a signal handler) associated
+    with signal SIG.  On failure, signal() returns SIG_ERR.  If
+    HANDLER is SIG_ACK, signal() returns the current signal action
+    associated with the signal SIG.
+
+þseealso abort() kill() raise() sigaction() sigprocmask()
+
+
+þfunction signbit()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+int signbit (float X);
+int signbit (double X);
+int signbit (long double X);
+þendprototype
+
+    Determine the sign of X.  The argument X must be of a
+    floating-point type.
+
+þreturnvalue
+
+    signbit() returns a non-zero value if the sign of X is negative;
+    signbit() returns 0 otherwise.
+
+þseealso copysign() fpclassify() isfinite() isnan() isnormal()
+
+
+þfunction sigpending()
+þcompat POSIX.1 *
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam SET
+þprototype
+int sigpending (sigset_t *SET);
+þendprototype
+
+    Store in the object pointed to by SET the set of signals that
+    are blocked and pending.
+
+    Every object of type sigset_t should be initialized at least once
+    with either sigemptyset() or sigfillset() before any use.  When
+    using an uninitialized object of type sigset_t, the results are
+    undefined.
+
+þreturnvalue
+
+    If successful, sigpending() returns 0.  Otherwise sigpending()
+    returns -1 and sets errno.
+
+þseealso kill() raise() sigaction() sigprocmask() sigismember()
+
+þsamplecode
+int poll_sigint (void)
+{
+  sigset_t s;
+
+  sigemptyset (&s);
+  return (sigprocmask (&s) == 0
+          && sigismember (&s, SIGINT) == 1);
+}
+þendsamplecode
+
+
+þfunction sigprocmask()
+þcompat POSIX.1 *
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam HOW ISET OSET
+þprototype
+int sigprocmask (int HOW, const sigset_t *ISET, sigset_t *OSET);
+þendprototype
+
+    Examine and/or change the signal mask (set of blocked signals) of
+    the calling process.  If ISET is not NULL, it points to a set of
+    signals used to change the signal mask.  The following values are
+    available for HOW to indicate how to modify the signal mask:
+
+þdescription
+þitem SIG_BLOCK
+
+    Add the signals of the set pointed to by ISET to the set of
+    blocked signals.  The resulting signal mask will be the union of
+    the current signal mask and the signal set pointed to by ISET.
+
+þitem SIG_UNBLOCK
+
+    Remove the signals of the set pointed to by ISET from the set of
+    blocked signals.  The resulting signal mask will be the
+    intersection of the current signal mask and the complement of the
+    signal set pointed to by ISET.
+
+þitem SIG_SETMASK
+
+    Replace the current signal mask with the signal set pointed to by
+    ISET.
+
+þenddescription
+
+    SIGKILL cannot be blocked; any attempt to block SIGKILL is ignored
+    by sigprocmask() without indication of an error.
+
+    If ISET is NULL, the signal mask won't be changed.
+
+    If OSET is not NULL, the previous signal mask will be stored in
+    the object pointed to by OSET.
+
+    If any unblocked signal is pending, at least one unblocked pending
+    signal will be delivered before sigprocmask() returns.
+
+    Every object of type sigset_t should be initialized at least once
+    with either sigemptyset() or sigfillset() before any use.  When
+    using an uninitialized object of type sigset_t, the results are
+    undefined.
+
+þreturnvalue
+
+    If successful, sigprocmask() returns 0.  Otherwise sigprocmask()
+    returns -1 and sets errno.
+
+þerrors
+þdescription
+þitem EINVAL
+    HOW is not SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK
+þenddescription
+
+þseealso kill() raise() sigaction() sigemptyset() sigismember() siglongjmp() sigpending() sigsetjmp()
+
+þsamplecode
+void block_sigint (void)
+{
+  sigset_t s;
+
+  sigemptyset (&s);
+  sigaddset (&s, SIGINT);
+  sigprocmask (SIG_BLOCK, &s, NULL);
+}
+þendsamplecode
+
+
+þfunction sigsetjmp()
+þcompat POSIX.1
+þheaders
+#include <setjmp.h>
+þendheaders
+
+þparam HERE SAVEMASK
+þprototype
+int sigsetjmp (sigjmp_buf HERE, int SAVEMASK);
+þendprototype
+
+    Save the current stack context in HERE and return 0.  If SAVEMASK
+    is non-zero, also save the current signal mask (set of blocked
+    signals) to HERE.  Later, you can continue at this point by
+    calling siglongjmp().  When execution continues at sigsetjmp()
+    after calling siglongjmp(), the second argument of siglongjmp() is
+    returned, which is always non-zero (if zero is used as second
+    argument of siglongjmp(), it will be turned into 1).
+
+    sigsetjmp() must not be used in compliated expressions.
+
+    As sigjmp_buf is an array type, the þtt{&} operator need not be
+    applied.
+
+þreturnvalue
+
+    sigsetjmp() returns 0 when directly called.  When returning from a
+    call to siglongjmp(), sigsetjmp() returns a non-zero value
+    (supplied by the call to siglongjmp()).
+
+þseealso longjmp() setjmp() siglongjmp() sigprocmask()
+
+
+þfunction sigsuspend()
+þcompat POSIX.1 *
+þheaders
+#include <signal.h>
+þendheaders
+
+þparam MASK
+þprototype
+int sigsuspend (const sigset_t *MASK);
+þendprototype
+
+    Replace the signal mask with the set of signals pointed to by MASK
+    and then suspend the process until delivery of a signal for which
+    a signal handler is installed.  sigsuspend() returns after the
+    signal handler returns.  Before returning, sigsuspends() restores
+    the signal mask to the set that existed prior to the sigsuspend()
+    call.
+
+    The process will be terminated (and sigsuspend() won't return) if
+    an uncaught signal is delivered which terminates the process.
+
+    SIGKILL cannot be blocked; any attempt to block SIGKILL is ignored
+    by sigsuspend() without indication of an error.
+
+    Every object of type sigset_t should be initialized at least once
+    with either sigemptyset() or sigfillset() before any use.  When
+    using an uninitialized object of type sigset_t, the results are
+    undefined.
+
+þreturnvalue
+
+    sigsuspend() sets errno to EINTR and returns -1.
+
+þrestrictions
+
+    sigsuspend() is not implemented under DOS.
+
+þseealso alarm() kill() pause() sigaction() sigemptyset() sigprocmask()
+
+
+þfunction sleep()
+þcompat POSIX.1
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam SEC
+þprototype
+unsigned sleep (unsigned SEC);
+þendprototype
+
+    Suspend the calling process for SEC seconds or until an unblocked
+    signal is caught.  SEC should not exceed 4294967.
+
+þreturnvalue
+
+    If interrupted by a caught signal, sleep() returns the number of
+    remaining seconds.  Otherwise, sleep() returns 0.
+
+þimplementation
+
+    alarm() and SIGALRM don't interfer with the operation of sleep().
+
+þrestrictions
+
+    sleep() is also interrupted by ignored signals and, under OS/2, by
+    blocked signals.
+
+þseealso alarm() sigaction() signal() sigprocmask() _sleep2()
+
+
+þfunction _sleep2()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam MILLISEC
+þprototype
+unsigned _sleep2 (unsigned MILLISEC);
+þendprototype
+
+    Suspend the calling process for MILLISEC milliseconds.  As the
+    system clock is used for timing, the actual duration of the time
+    interval depends on the granularity of the system clock.  The time
+    interval is rounded up to the next clock tick.  Also note that
+    calling _sleep2() involves an overhead.
+
+    Delivery of a signal which is caught interrupts _sleep2().
+
+þreturnvalue
+
+    _sleep2() returns 0.
+
+þrestrictions
+
+    Under OS/2, sleep() is also interrupted by ignored signals and by
+    blocked signals.  Under DOS, sleep() is not interrupted by
+    signals.
+
+þseealso alarm() sigaction() signal() sigprocmask() sleep()
+
+
+þfunction _smutex_available()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/smutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+int _smutex_available (volatile _smutex *SEM);
+þendprototype
+
+    Check if the _smutex semaphore pointed to by SEM is available or
+    owned, without changing the state of the semaphore and without
+    blocking.  Return zero if the semaphore is owned, return a
+    non-zero value if the semaphore is available.  Note that
+    _smutex_available() just returns a snapshot of the state of the
+    semaphore; in presence of other threads or other processes having
+    access to the semaphore, the state may change at any time, even
+    before _smutex_available() returns. This function can be used to
+    avoid deadlock.
+
+þreturnvalue
+
+    _smutex_available() returns a non-zero value if the semaphore is
+    available.  _smutex_available() returns 0 if the semaphore is
+    owned.
+
+þseealso _smutex_release() _smutex_request()
+
+
+þfunction _smutex_release()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/smutex.h>
+þendheaders
+
+þparam SEM
+þprototype
+void _smutex_release (volatile _smutex *SEM);
+þendprototype
+
+    Relinquish ownership of the _smutex semaphore pointed to by SEM.
+    Unblocking any process blocking in þhpt{_smutex_request()} for
+    this semaphore won't occur before the current time slice ends.
+
+þseealso __cxchg() _smutex_available() _smutex_request()
+
+
+þfunction _smutex_request()
+þcompat emx
+þheaders
+#include <sys/builtin.h>
+#include <sys/smutex.h>
+þendheaders
+
+þparam SEM FLAGS
+þprototype
+void _smutex_request (volatile _smutex *SEM);
+þendprototype
+
+    Request ownership of the _smutex semaphore pointed to by SEM.  If
+    the semaphore is available, it will be set to owned and
+    _smutex_request() will return immediately.
+
+    If the semaphore is owned, _smutex_request() will suspend the
+    current thread, periodically checking whether the semaphore is
+    available or still owned.  If the semaphore is available, it will
+    be set atomically to owned and _smutex_request() will return.
+    Otherwise, _smutex_request() will continue polling.
+    _smutex_request() does not return if a signal occurs while
+    blocking.
+
+    Note that ownership of an _smutex semaphore is not tied to a
+    thread, that is, it's not a thread which owns the semaphore.  This
+    is in contrast to OS/2's mutex semaphores (HMTX).  Deadlock will
+    occur if _smutex_request() is called twice for the same semaphore
+    by the same thread without an intervening call to
+    _smutex_release().  This fact is important to keep in mind in
+    presence of signals.  Signal handlers must not request semaphores
+    which can be owned by the interrupted code.  You might want to
+    block signals before requesting ownership of an _smutex semaphore.
+
+þrestrictions
+
+    Under DOS, _smutex_request() crashes if the semaphore is already
+    owned.
+
+þseealso __cxchg() _fmutex_create() _rmutex_create() _smutex_available() _smutex_release()
+
+
+þfunction snprintf()
+þcompat BSD
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUFFER N FORMAT
+þprototype
+int snprintf (char *BUFFER, size_t N, const char *FORMAT, ...);
+þendprototype
+
+    Formatted output to the string pointed to by BUFFER.  If N is
+    zero, BUFFER may be NULL and nothing is written.  Otherwise, up to
+    þpa{N}-1 characters and a terminating null character will be
+    written to BUFFER.  If formatting yields more than þpa{N}-1
+    characters, output will be truncated.  The terminating null
+    character will be put into BUFFER even if output is truncated.
+
+þreturnvalue
+
+    On success, snprintf() returns the number of characters (excluding
+    the terminating null character) that would have been written to
+    BUFFER if N had been sufficiently large.  That is, output is
+    truncated iff the returned value is greater than or equal to N.
+    On error, snprintf() returns EOF.
+
+þseealso sprintf() vsnprintf()
+
+
+þfunction sopen()
+þcompat PC
+þheaders
+#include <io.h>
+#include <share.h>
+þendheaders
+
+þparam NAME OFLAG SHFLAG PMODE ISIZE
+þprototype
+int sopen (const char *NAME, int OFLAG, int SHFLAG);
+int sopen (const char *NAME, int OFLAG, int SHFLAG, int PMODE);
+
+int sopen (const char *NAME, int OFLAG, int SHFLAG,
+           unsigned long ISIZE);
+int sopen (const char *NAME, int OFLAG, int SHFLAG, int PMODE,
+           unsigned long ISIZE);
+þendprototype
+
+    Open a file or device with an explicit sharing mode.  NAME points
+    to the name of the file or device.  OFLAG contains one or more of
+    the following values, combined by the þtt{|} operator:
+
+þdescription
+
+þitem O_RDONLY
+
+    Open for reading.  Writing is not allowed
+
+þitem O_WRONLY
+
+    Open for writing.  Reading is not allowed
+
+þitem O_RDWR
+
+    Open for reading and writing
+
+þitem O_APPEND
+
+    Move the file pointer to the end of file before any write
+    operation takes place.  This is used for appending to a file
+
+þitem O_CREAT
+
+    Create the file if it does not exist.  If this flag is set, the
+    PMODE argument is required
+
+þitem O_TRUNC
+
+    Truncate the size of the file to 0
+
+þitem O_EXCL
+
+    Fail if the O_CREAT is used and the file already exists
+
+þitem O_NONBLOCK alias O_NDELAY
+
+    Currently ignored
+
+þitem O_BINARY
+
+    Binary mode, no translation.  See below
+
+þitem O_TEXT
+
+    Text mode, translate CR/LF to newline.  See below
+
+þitem O_NOINHERIT
+
+    Child processes won't inherit the file handle
+
+þitem O_SYNC
+
+    Write operations are synchronous, that is, write() waits until
+    file data has been physically written
+
+þitem O_SIZE
+
+    Set the initial size of the file to ISIZE if the file is a new
+    file (O_CREAT) or an existing file truncated (O_TRUNC).  If this
+    flag is set, the ISIZE argument is required.  O_SIZE is ignored
+    under DOS
+
+þenddescription
+
+    If a new file is created, PMODE (modified by the umask value), is
+    used to set the file permissions.  S_IREAD grants read access,
+    S_IWRITE grants write access.  S_IREAD is ignored (DOS and OS/2
+    limitation).
+
+    There are two additional OFLAG flags: O_TEXT for text mode,
+    O_BINARY for binary mode.  Text mode, which is the default,
+    translates each CR/LF pair to a newline character on input and
+    translates newline characters to CR/LF pairs on output.  If the last
+    character of a file is Ctrl-Z, it is discarded on input.  Binary
+    mode disables these transformations.
+
+    If the file or device cannot be opened, open() sets errno and
+    returns -1.  If open() succeeds, the file handle is returned.  The
+    file handle is always greater than -1.
+
+    The mode þtt{O_TRUNC|O_RDONLY} is not implemented.  A Ctrl-Z at
+    the end of the file is removed only when opening a file for
+    appending in text mode.  Ctrl-Z at the end of the file is
+    obsolete, anyway.
+
+    The sharing mode of the file is given by SHFLAG.  The following
+    sharing modes are available:
+
+þdescription
+
+þitem SH_DENYRW
+
+    Deny read and write access
+
+þitem SH_DENYRD
+
+    Deny read access (permit write access)
+
+þitem SH_DENYWR
+
+    Deny write access (permit read access)
+
+þitem SH_DENYNO
+
+    Deny nothing (permit read and write access)
+
+þenddescription
+
+þreturnvalue
+
+    sopen() returns a file handle for the file.  On error, sopen()
+    sets errno and returns -1.
+
+þimplementation
+
+    O_SIZE is an emx extension.  It's the caller's responsibility to
+    truncate the file if its size should be less than ISIZE bytes.
+    O_SIZE is ignored under DOS.
+
+þrestrictions
+
+    Under DOS, the O_NOINHERIT flag is currently ignored for child
+    processes which are DOS programs (vs. emx programs).  Under DOS,
+    the O_SYNC and O_SIZE flags are ignored.
+
+þseealso close() fcntl() fdopen() ftruncate() open()
+
+
+þfunction spawn*() spawnl() spawnle() spawnlp() spawnlpe() spawnv() spawnve() spawnvp() spawnvpe()
+þcompat PC *
+þheaders
+#include <process.h>
+þendheaders
+
+þparam MODE NAME ARG0 ARGV ENVP
+þprototype
+int spawnl (int MODE, const char *NAME, const char *ARG0, ...);
+int spawnle (int MODE, const char *NAME, const char *ARG0, ...);
+int spawnlp (int MODE, const char *NAME, const char *ARG0, ...);
+int spawnlpe (int MODE, const char *NAME, const char *ARG0, ...);
+int spawnv (int MODE, const char *NAME, char * const ARGV[]);
+int spawnve (int MODE, const char *NAME,char * const ARGV[],
+             char * const ENVP[]);
+int spawnvp (int MODE, const char *NAME, char * const ARGV[]);
+int spawnvpe (int MODE, const char *NAME, char * const ARGV[],
+              char * const ENVP[]);
+þendprototype
+
+    Run a program.  NAME points to the name of the executable file to
+    run.
+
+    Use spawnl(), spawnle(), spawnlp() or spawnlpe() for passing a
+    fixed number of arguments.  ARG0 points to a string containing the
+    0th argument which is the program name, by convention.  Following
+    ARG0, pointers to the arguments are passed.  After the last
+    argument pointer, a null pointer cast to `þtt{char *}' must be
+    following.  At least ARG0 must be specified.
+
+    Use spawnv(), spawnve(), spawnvp() or spawnvpe() for passing a
+    variable number of arguments.  ARGV points to an array of pointers
+    to strings.  The first entry is the program name, by convention.
+    The last argument pointer must be followed by a null pointer.
+
+    spawnl(), spawnlp(), spawnv() and spawnvp() pass the environment
+    of the current process to the child process.  To pass a different
+    environment to the child process pass a pointer to an array of
+    strings after the null argument pointer of spawnle() and
+    spawnlpe() or pass the pointer in the ENVP argument of spawnve()
+    and spawnvpe().  The last string pointer in the array must be
+    followed by a null pointer.
+
+    If both the child process and the parent process use emx.exe or
+    emx.dll, the child process will inherit the signal actions of the
+    parent process: Signals set to SIG_IGN in the parent process will
+    be set to SIG_IGN in the child process, signals set to SIG_DFL in
+    the parent process will be set to SIG_DFL in the child process,
+    signals caught in the parent process will be set to SIG_DFL in the
+    child process.
+
+    The MODE argument specifies how to run the child process.  You
+    have to include exactly one of the following values:
+
+þdescription
+
+þitem P_WAIT
+
+    run the process synchronously, that is, control returns to the
+    parent process after the child process finishes
+
+þitem P_NOWAIT
+
+    run the process asynchronously, that is in parallel with the
+    parent process.  Use wait() to wait for completion of the child
+    process and to get its termination status.  Under DOS, the process
+    is run synchronously
+
+þitem P_OVERLAY
+
+    replace the parent process, that is, run the child process and
+    terminate the parent process
+
+þitem P_DEBUG
+
+    run the process in debugging mode, that is, under control of the
+    parent process.  Use ptrace() to control the child process
+
+þitem P_DETACH
+
+    run the process detached, that is, without input and output.
+    P_DETACH is not available under DOS
+
+þitem P_SESSION
+
+    run the process in a separate session.  P_SESSION is not available
+    under DOS.
+
+þitem P_PM
+
+    the process is a Presentation Manager program.  P_PM is not
+    available under DOS.
+
+þenddescription
+
+    Additional flags are available for P_SESSION, which can be added
+    by using the þtt{|} operator:
+
+þdescription
+
+þitem P_QUOTE
+
+    Quote all the arguments, that is, suppress expansion of command
+    line arguments by þhpt{_wildcard()} and þhpt{_response()} in the
+    child process.  Without P_QUOTE, arguments are not quoted
+
+þitem P_TILDE
+
+    Use the `MKS Korn shell' method for passing command line arguments
+    (OS/2, only; this was the default in emx 0.8h and earlier).  That
+    method passes the arguments in the third and following strings of
+    DosExecPgm.  The tilde character is used as flag at the start of
+    the third string
+
+þenddescription
+
+    Use one of the following flags for selecting the session type:
+
+þdescription
+
+þitem P_DEFAULT
+
+    let the operating system choose the session type
+
+þitem P_FULLSCREEN
+
+    start a full-screen session
+
+þitem P_WINDOWED
+
+    start a windowed session
+
+þenddescription
+
+    These flags (which can be used with P_SESSION and P_PM) control
+    the initial appearance of the window:
+
+þdescription
+
+þitem P_MINIMIZE
+
+    minimize the window
+
+þitem P_MAXIMIZE
+
+    maximize the window
+
+þenddescription
+
+    Additionally, you can use the following flags with P_SESSION and
+    P_PM:
+
+þdescription
+
+þitem P_BACKGROUND
+
+    start the session in the background
+
+þitem P_FOREGROUND
+
+    start the session in the foreground.  This works only if the
+    calling session is in the foreground.  P_FOREGROUND is the default
+
+þitem P_NOCLOSE
+
+    don't close the window automatically when the process ends
+    (ignored for P_PM)
+
+þitem P_UNRELATED
+
+    create an independent session.  SIGCHLD won't be raised when the
+    session terminates.  wait() and waitpid() cannot be used on that
+    session.  spawn*() returns zero (instead of a process ID) on
+    success.
+
+þenddescription
+
+    Additional flags are available for P_DEBUG, which can be added
+    by using the þtt{|} operator:
+
+þdescription
+
+þitem P_NOSESSION
+
+    don't run debuggee in a separate session.  The same effect can be
+    achieved with the -E emx option.
+
+þitem P_DEBUGDESC
+
+    enable debugging of descendant processes of the debuggee; see
+    þhpt{ptrace()} for details.  P_DEBUGDESC cannot be used if
+    _UF_PTRACE_STANDARD is in effect, see þhpt{_uflags()} for details.
+
+þenddescription
+
+    When the new process terminates, SIGCHLD is sent to the process
+    which started that process.  You should use wait() or waitpid() to
+    get the return code of the process.  If you don't retrieve the
+    return code for asynchronous child processes, the return codes
+    fill up memory.  All this does not apply to P_WAIT, P_OVERLAY and
+    P_DETACH.
+
+þreturnvalue
+
+    These functions return the return value of the child process
+    (P_WAIT), or the process ID of the child process (P_NOWAIT,
+    P_DEBUG, P_SESSION and P_PM), or zero (P_UNRELATED) if successful.
+    On error they return -1.
+
+þrestrictions
+
+    The command line length is restricted to 126 characters when
+    running DOS programs.  DOS programs can only be run in P_WAIT or
+    P_NOWAIT mode.  P_NOWAIT runs processes synchronously under DOS.
+    The termination status of only one process will be kept for wait()
+    under DOS.  The default extension is .exe; if you want to run a
+    .com file, explicitly add .com.  Currently, DOS seems to crash if
+    you try to spawn a .com file without using emx option -p, see
+    `þhpt{Using emx options}'.  (The machine crashes on the second
+    attempt.)  With the system call library sys.lib (þhpt{-Zsys}),
+    only modes P_WAIT, P_NOWAIT and P_OVERLAY are currently available.
+
+þseealso exit() ptrace() system() wait()
+
+
+þfunction _splitargs()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam STRING COUNT
+þprototype
+char **_splitargs (char *STRING, int *COUNT);
+þendprototype
+
+    Parse the string pointed to by STRING like a command line and
+    build a vector of pointers to the arguments.  The vector is
+    terminated by a NULL pointer.  The number of arguments is stored
+    to the variable pointed to by COUNT unless COUNT is NULL.  The
+    string pointed to by STRING is modified by _splitargs(), the
+    pointers in the resulting vector point into the string pointed to
+    by STRING.  _splitargs() allocates the vector using malloc().  If
+    you no longer need the vector, use free() to deallocate it.  On
+    error, _splitargs() sets errno and returns NULL.
+
+    Arguments in the string pointed to by STRING are separated by
+    whitespace (one or more blanks, tabs and linefeeds).  Whitespace
+    at the start of the string is skipped.  To include blanks, tabs or
+    linefeeds in an argument, the argument must be quoted using double
+    quotation marks.  To remove the special meaning of a double quote,
+    precede it with a backslash.  To remove the special meaning of a
+    backslash in front of a double quote, precede the backslash with a
+    backslash.  The backslash character doesn't have a special meaning
+    unless it precedes a double quote or any number of backslashes
+    followed by a double quote.
+
+    In other words: If there are n backslashes (\) immediately
+    preceding a double quote character ("), floor(n/2) backslashes are
+    put into the argument.  If n is odd, the double quote character is
+    put into the argument.  If n is even (including zero), the double
+    quote character is used for quoting, that is, spaces are not
+    treated as argument delimiters until the next `quoting' double
+    quote character (ie, a double quote character immediately preceded
+    by an even number (including zero) of backslashes) is found.
+    Backslashes not preceding a quote character are always read as
+    backslashes.
+
+þreturnvalue
+
+    See above.
+
+
+þfunction _splitpath()
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam SRC DRIVE DIR FNAME EXT
+þprototype
+void _splitpath (const char *SRC, char *DRIVE, char *DIR, char *FNAME,
+                 char *EXT);
+þendprototype
+
+    Split the path name pointed to by SRC into its components.  The
+    drive name (including the colon) is stored to the array pointed to
+    by DRIVE.  The directory (including the final slash or backslash)
+    is copied to the array pointed to by DIR, the file name without
+    extension is copied to the array pointed to by FNAME, the
+    extension (including the dot) is copied to the array pointed to by
+    EXT.  The arrays should be of size _MAX_DRIVE, _MAX_DIR,
+    _MAX_FNAME and _MAX_EXT, respectively.  These constants include
+    the terminating null characters.  If one of the pointers (except
+    for SRC) is NULL, that component is not stored.
+
+    _splitpath() properly handles DBCS characters.
+
+þseealso _fngetdrive() _getext() _getname() _makepath() _nls_init()
+
+þsamplecode
+char drive[_MAX_DRIVE], dir[_MAX_DIR];
+char fname[_MAX_FNAME], ext[_MAX_EXT];
+char *path = "c:/files/more/test.file.c";
+
+_splitpath (path, drive, dir, fname, ext);
+þendsamplecode
+
+    Results of the example:
+
+þexample
+drive = "c:"
+dir   = "/files/more/"
+fname = "test.file"
+ext   = ".c"
+þendexample
+
+
+þfunction sprintf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUFFER FORMAT
+þprototype
+int sprintf (char *BUFFER, const char *FORMAT, ...);
+þendprototype
+
+    Formatted output to the string pointed to by BUFFER.  The string
+    must be big enough to hold the output.  See þhpt{printf()} for details.
+
+þreturnvalue
+
+    On success, sprintf() returns the number of characters copied to
+    BUFFER (excluding the terminating null character).  On error,
+    sprintf() returns EOF.
+
+þseealso gcvt() _itoa() _mfopen() printf() sscanf() snprintf()
+
+
+þfunction sqrt() sqrtl()
+þcompat C90 C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double sqrt (double X);
+long double sqrtl (long double X);
+þendprototype
+
+    Compute the square root of X.
+
+    sqrtl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    sqrt() returns the square root of X.  If X is negative, a NaN is
+    returned and errno set to EDOM.
+
+þseealso cbrt() pow()
+
+
+þfunction _srotl() _srotr()
+þcompat VAC++
+þheaders
+#include <sys/builtin.h>
+þendheaders
+
+þparam VALUE SHIFT
+þprototype
+unsigned short _srotl (unsigned short VALUE, int SHIFT);
+unsigned short _srotr (unsigned short VALUE, int SHIFT);
+þendprototype
+
+    _srotl() returns VALUE (16 bits) rotated left by SHIFT bits.  If
+    SHIFT is 1, bit 14 is returned as bit 15, bit 13 is returned as bit
+    14, and so on, bit 0 is returned as bit 1, and bit 15 is
+    returned as bit 0.
+
+    _srotr() returns VALUE (16 bits) rotated right by SHIFT bits.  If
+    SHIFT is 1, bit 1 is returned as bit 0, bit 2 is returned as bit
+    1, and so on, bit 7 is returned as bit 6, and bit 0 is returned as
+    bit 7.
+
+    SHIFT should be 0 through 15.
+
+    These functions are implemented as inline functions.
+
+þseealso _crotl() _crotr() _lrotl() _lrotr()
+
+
+þfunction sscanf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUFFER FORMAT
+þprototype
+int sscanf (const char *BUFFER, const char *FORMAT, ...);
+þendprototype
+
+    Parse the string pointed to by BUFFER according to the format
+    string pointed to by FORMAT.  For each field in the format string
+    there must be a pointer to the location receiving the value.  The
+    pointers are passed after the FORMAT argument.
+
+þreturnvalue
+
+    If successful, sscanf() returns the number of fields converted.
+    On error, sscanf() returns EOF.
+
+þseealso scanf() sprintf() strptime()
+
+þsamplecode
+char inp[512];
+int year, month, day;
+...
+if (fgets (inp, sizeof (inp), stdin) != NULL
+    && sscanf (inp, "%d/%d/%d", &year, &month, &day) == 3)
+  {
+    ...
+  }
+þendsamplecode
+
+
+þfunction stat()
+þcompat UNIX
+þheaders
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+þendheaders
+
+þparam NAME BUFFER
+þprototype
+int stat (const char *NAME, struct stat *BUFFER);
+þendprototype
+
+    Retrieve information about a file or directory.  NAME is a pointer
+    to the name of the file or directory.  stat() will put the data
+    into the structure pointed to by BUFFER:
+
+þexample
+struct stat
+{
+  dev_t   st_dev;       /* Device number */
+  ino_t   st_ino;       /* Inode number */
+  mode_t  st_mode;      /* Protection mode, S_IREAD etc. */
+  nlink_t st_nlink;     /* Number of links -- always 1 */
+  uid_t   st_uid;       /* User ID of owner -- always 0 (root) */
+  gid_t   st_gid;       /* Group ID of owner -- always 0 (root) */
+  dev_t   st_rdev;      /* Always 0 */
+  off_t   st_size;      /* Size of file */
+  time_t  st_atime;     /* Time of last access */
+  time_t  st_mtime;     /* Time of last modification */
+  time_t  st_ctime;     /* Time of creation */
+  long    st_attr;      /* File attributes (OS/2 and DOS style) */
+  long    st_reserved;  /* Currently not used */
+};
+þendexample
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error (errno is set)
+þenddescription
+
+þrestrictions
+
+    st_dev and st_rdev are set to zero.  Each call to stat() returns a
+    different value for st_ino.
+
+þseealso fstat()
+
+
+þfunction _status87()
+þcompat PC
+þheaders
+#include <float.h>
+þendheaders
+
+þprototype
+unsigned _status87 (void);
+þendprototype
+
+    Return the coprocessor status word.
+
+þreturnvalue
+
+    See above.
+
+þseealso _clear87() _control87()
+
+
+þfunction strcat()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+char *strcat (char *STRING1, const char *STRING2);
+þendprototype
+
+    Append the null-terminated string pointed to by STRING2 to the
+    null-terminated array pointed to by STRING1.  The objects must
+    not overlap.
+
+þreturnvalue
+
+    strcat() returns STRING1.
+
+þseealso strcpy()
+
+
+þfunction strchr()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING C
+þprototype
+char *strchr (const char *STRING, int C);
+þendprototype
+
+    Return a pointer to the first occurrence of the character C in the
+    null-terminated string pointed to by STRING.  If there is no
+    character C in that string, NULL is returned.  If C is the null
+    character (0), a pointer to the terminating null character of that
+    string is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso index() memchr() strrchr() strstr()
+
+
+þfunction strcmp()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+int strcmp (const char *STRING1, const char *STRING2);
+þendprototype
+
+    Compare the null-terminated strings pointed to by STRING1 and
+    STRING2.  If the string pointed to by STRING1 is less than the
+    string pointed to by STRING2, a negative value is returned.  If
+    the string pointed to by STRING1 is equal to the string pointed to
+    by STRING2, zero is returned.  If the string pointed to by STRING1
+    is greater than the string pointed to by STRING2, a positive value
+    is returned.
+
+þreturnvalue
+þdescription
+þitem <0
+   1st string < 2nd string
+þitem =0
+   1st string = 2nd string
+þitem >0
+   1st string > 2nd string
+þenddescription
+
+þseealso memcmp() stricmp() strncmp()
+
+
+þfunction strcoll()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+int strcoll (const char *STRING1, const char *STRING2);
+þendprototype
+
+    Compare the null-terminated strings pointed to by STRING1 and
+    STRING2 according to the LC_COLLATE category of the current
+    locale.  If the string pointed to by STRING1 is less than the
+    string pointed to by STRING2, a negative value is returned.  If
+    the string pointed to by STRING1 is equal to the string pointed to
+    by STRING2, zero is returned.  If the string pointed to by STRING1
+    is greater than the string pointed to by STRING2, a positive value
+    is returned.
+
+þreturnvalue
+þdescription
+þitem <0
+   1st string < 2nd string
+þitem =0
+   1st string = 2nd string
+þitem >0
+   1st string > 2nd string
+þenddescription
+
+þrestrictions
+
+    Currently, locale is ignored: strcoll() is equivalent to strcmp().
+
+þseealso setlocale() strcmp()
+
+
+þfunction strcpy()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+char *strcpy (char *STRING1, const char *STRING2);
+þendprototype
+
+    Copy the null-terminated string pointed to by STRING2 to the array
+    pointed to by STRING1.  The objects must not overlap.
+
+þreturnvalue
+
+    strcpy() returns STRING1.
+
+þseealso memccpy() memcpy() strcat() strncpy()
+
+
+þfunction strcspn()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+size_t strcspn (const char *STRING1, const char *STRING2);
+þendprototype
+
+    Return the length of the initial substring of the string pointed
+    to by STRING1 which consists of characters not in the string
+    pointed to by STRING2.  That is, the index of the first character
+    in the string pointed to by STRING1 which also occurs in the
+    string pointed to by STRING2 is returned.  If all characters of
+    the string pointed to by STRING1 are not in the string pointed to
+    by STRING2, the length of the string pointed to by STRING1 is
+    returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso strpbrk() strspn()
+
+
+þfunction strdup()
+þcompat UNIX
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING
+þprototype
+char *strdup (const char *STRING);
+þendprototype
+
+    Creates a duplicate of the string pointed to by STRING by using
+    malloc() to allocate storage and copying the string pointed to by
+    STRING.
+
+þreturnvalue
+
+    strdup() returns a pointer to the new string.  If there is not
+    enough memory, strdup() returns NULL.
+
+þseealso malloc() strcpy()
+
+
+þfunction strerror()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam ERRNUM
+þprototype
+char *strerror (int ERRNUM);
+þendprototype
+
+    Return a pointer to a an error message according to the error
+    number ERRNUM.  You must not write to the string returned by
+    strerror().  The string may get changed by the next call to
+    strerror().
+
+þreturnvalue
+
+    See above.
+
+þseealso errno perror() sys_errlist
+
+
+þfunction strftime()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þparam STRING SIZE FORMAT T
+þprototype
+size_t strftime (char *STRING, size_t SIZE, const char *FORMAT,
+                 const struct tm *T);
+þendprototype
+
+    Format time.  The output string is written to the array of SIZE
+    characters pointed to by STRING, including the terminating null
+    character.  Like sprintf(), strftime() copies the string pointed
+    to by FORMAT to the array pointed to by STRING, replacing format
+    specifications with formatted data from T.  Ordinary characters
+    are copied unmodified.  The following format specifications are
+    available:
+
+þdescription
+þitem %%
+
+    percent sign
+
+þitem %a
+
+    locale's abbreviated weekday name
+
+þitem %A
+
+    locale's full weekday name
+
+þitem %b
+
+    locale's abbreviated month name
+
+þitem %B
+
+    locale's full month name
+
+þitem %c
+
+    locale's date and time
+
+þitem %d
+
+    day of month (01-31)
+
+þitem %D
+
+    date, this is equivalent to %m/%d/%y
+
+þitem %e
+
+    day of month ( 1-31), blank padded
+
+þitem %h
+
+    locale's abbreviated month name
+
+þitem %H
+
+    hour (00-23)
+
+þitem %I
+
+    hour (01-12)
+
+þitem %j
+
+    day of year (001-366)
+
+þitem %m
+
+    month (01-12)
+
+þitem %M
+
+    minute (00-59)
+
+þitem %n
+
+    newline character
+
+þitem %p
+
+    locale's equivalent to AM or PM, as appropriate
+
+þitem %r
+
+    time in AM/PM notation, this is equivalent to %I:%M:%S %p
+
+þitem %S
+
+    second (00-59)
+
+þitem %t
+
+    TAB character
+
+þitem %T
+
+    time, this is equivalent to %H:%M:%S
+
+þitem %U
+
+    week number of the year, the first day of the week is Sunday
+    (00-53)
+
+þitem %w
+
+    weekday, the first day of the week is Sunday (0-6)
+
+þitem %W
+
+    week number of the year, the first day of the week is Monday
+    (00-53)
+
+þitem %x
+
+    locale's date representation
+
+þitem %X
+
+    locale's time representation
+
+þitem %y
+
+    year without century (00-99)
+
+þitem %Y
+
+    year with century (1970-2106)
+
+þitem %Z
+
+    timezone name or no characters if no time zone is determinable
+
+þenddescription
+
+    If % is followed by a character not listed above, the results are
+    undefined.
+
+þreturnvalue
+
+    On success, strftime() returns the number of characters copied to
+    the array pointed to by STRING, excluding the terminating null
+    character.  On failure (SIZE exceeded), strftime() returns 0.
+
+þseealso asctime() setlocale() sprintf() strptime() tzset()
+
+
+þfunction stricmp()
+þcompat PC
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+int stricmp (const char *STRING1, const char *STRING2);
+þendprototype
+
+    Compare the strings pointed to by STRING1 and STRING2, ignoring
+    letter case.  If the strings are equal, 0 is returned.  Otherwise,
+    a positive value is returned if the string pointed to by STRING1
+    is greater than the string pointed to by STRING2 (after conversion
+    to lower case).  A negative value is returned if the string
+    pointed to by STRING1 is less than the string pointed to by
+    STRING2 (after conversion to lower case).  The strings are not
+    modified.
+
+þreturnvalue
+þdescription
+þitem <0
+   1st string < 2nd string
+þitem =0
+   1st string = 2nd string
+þitem >0
+   1st string > 2nd string
+þenddescription
+
+þseealso strcmp() tolower()
+
+
+þfunction strlen()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING
+þprototype
+size_t strlen (const char *STRING);
+þendprototype
+
+    Compute the length (number of characters) of the string pointed to
+    by STRING.  The length does not include the terminating null
+    character.
+
+þreturnvalue
+
+    strlen() returns the length of the string pointed to by STRING,
+    that is, the number of characters preceding the terminating null
+    character.
+
+þseealso strchr()
+
+
+þfunction strlwr()
+þcompat PC
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING
+þprototype
+char *strlwr (char *STRING);
+þendprototype
+
+    Convert the string pointed to by STRING to lower case.  The
+    characters þtt{'A'} through þtt{'Z'} are mapped to the characters
+    þtt{'a'} through þtt{'z'}.  All other characters are not changed.
+
+þreturnvalue
+
+    strlwr() returns STRING.
+
+þseealso _fnlwr() strupr()
+
+
+þfunction strncat()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2 COUNT
+þprototype
+char *strncat (char *STRING1, const char *STRING2, size_t COUNT);
+þendprototype
+
+    Append the null-terminated string pointed to by STRING2 to the
+    null-terminated string pointed to by STRING1.  At most COUNT
+    characters of the string pointed to by STRING2 are appended to the
+    string pointed to by STRING1.  strncat() terminates the new string
+    pointed to by STRING1 with a null character.
+
+þreturnvalue
+
+    strncat() returns STRING1.
+
+þseealso strcat() strncpy()
+
+
+þfunction strncmp()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2 COUNT
+þprototype
+int strncmp (const char *STRING1, const char *STRING2, size_t COUNT);
+þendprototype
+
+    Compare the null-terminated strings pointed to by STRING1 and
+    STRING2.  At most the first COUNT characters are compared.  If the
+    string pointed to by STRING1 is less than the string pointed to by
+    STRING2, a negative value is returned.  If the string pointed to
+    by STRING1 is equal to the string pointed to by STRING2, zero is
+    returned.  If the string pointed to by STRING1 is greater than the
+    string pointed to by STRING2, a positive value is returned.
+
+þreturnvalue
+þdescription
+þitem <0
+   1st string < 2nd string
+þitem =0
+   1st string = 2nd string
+þitem >0
+   1st string > 2nd string
+þenddescription
+
+þseealso memcmp() strcmp() strnicmp()
+
+
+þfunction strncpy()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2 COUNT
+þprototype
+char *strncpy (char *STRING1, const char *STRING2, size_t COUNT);
+þendprototype
+
+    Copy the null-terminated string pointed to by STRING2 to the array
+    pointed to by STRING1.  The objects must not overlap.  At most the
+    first COUNT characters of the string pointed to by STRING2 are
+    copied.  If the string pointed to by STRING2 is shorter than COUNT
+    characters, the string pointed to by STRING1 will be padded with
+    null characters to COUNT characters.  If the length of the string
+    pointed to by STRING2 is equal to or greater than COUNT, a
+    terminating null character will not be appended.
+
+þreturnvalue
+
+    strncpy() returns STRING1.
+
+þseealso strcpy() strncat()
+
+
+þfunction _strncpy()
+þcompat emx
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2 SIZE
+þprototype
+char *_strncpy (char *STRING1, const char *STRING2, size_t SIZE);
+þendprototype
+
+    Copy the null-terminated string pointed to by STRING2 to the array
+    pointed to by STRING1.  The objects must not overlap.  At most
+    SIZE characters, including the terminating null character, are
+    copied to the array pointed to by STRING1.  A terminating null
+    character is always appended, even if the string pointed to by
+    STRING2 is too long.
+
+þreturnvalue
+
+    _strncpy() returns STRING1.
+
+þseealso strcpy() strncpy()
+
+
+þfunction strnicmp()
+þcompat PC
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2 COUNT
+þprototype
+int strnicmp (const char *STRING1, const char *STRING2, size_t COUNT);
+þendprototype
+
+    Compare the null-terminated strings pointed to by STRING1 and
+    STRING2 ignoring letter case.  At most the first COUNT characters
+    are compared.  If the string pointed to by STRING1 is equal to the
+    string pointed to by STRING2, zero is returned.  If the string
+    pointed to by STRING1 is less than the string pointed to by
+    STRING2 (after conversion to lower case), a negative value is
+    returned.  If the string pointed to by STRING1 is greater than the
+    string pointed to by STRING2 (after conversion to lower case), a
+    positive value is returned.  The strings are not modified.
+
+þreturnvalue
+þdescription
+þitem <0
+   1st string < 2nd string
+þitem =0
+   1st string = 2nd string
+þitem >0
+   1st string > 2nd string
+þenddescription
+
+þseealso memicmp() strcmp() strncmp() tolower()
+
+
+þfunction strnset()
+þcompat PC
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING C COUNT
+þprototype
+char *strnset (char *STRING, int C, size_t COUNT);
+þendprototype
+
+    Set, at most, the first COUNT characters of the string pointed to
+    by STRING to the character C.  If the length of the string pointed
+    to by STRING is less than COUNT, strnset() stops at the
+    terminating null character.
+
+þreturnvalue
+
+    strnset() returns STRING.
+
+þseealso memset() strset()
+
+
+þfunction strpbrk()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+char *strpbrk (const char *STRING1, const char *STRING2);
+þendprototype
+
+    Return a pointer to the first occurrence in the string pointed to
+    by STRING1 of a character of the string pointed to by STRING2.
+    The terminating null character is not included in the search.  If
+    no character of the string pointed to by STRING2 can be found in
+    the string pointed to by STRING1, NULL is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso strchr() strcspn()
+
+
+þfunction strptime()
+þcompat UNIX
+þheaders
+#include <time.h>
+þendheaders
+
+þparam BUFFER FORMAT T
+þprototype
+char *strptime (const char *BUFFER, const char *FORMAT, struct tm *T);
+þendprototype
+
+    Parse a time specification in the input string pointed to by
+    BUFFER according to the format string pointed to by FORMAT,
+    updating the structure pointed to by T.
+
+    Whitespace (any number of spaces) in the format string matches
+    whitespace (any number of spaces, including zero) in the input
+    string.  All other characters except for þtt{%} are compared to
+    the input.  Parsing ends (with an error being indicated) when a
+    mismatch is encountered.  þtt{%%} in the format string matches
+    þtt{%} in the input string.  A þtt{%} which is not followed by
+    another þtt{%} or the end of the string starts a field
+    specification.  The field in the input is interpreted according to
+    the field specification.  For all field types, whitespace is
+    ignored at the start of a field.  Field specifications matching
+    numbers skip leading zeros.  Case is ignored when comparing
+    strings.  The field width is not restricted, that is, as many
+    characters as possible are matched.  The following field
+    specifications are available:
+
+þdescription
+þitem %%
+
+    percent sign (see above)
+
+þitem %a
+
+    locale's abbreviated weekday name, tm_wday
+
+þitem %A
+
+    locale's full weekday name, update tm_wday
+
+þitem %b
+
+    locale's abbreviated month name, update tm_mon.  %h is a synonym
+    for %b
+
+þitem %B
+
+    locale's full month name, update tm_mon
+
+þitem %c
+
+    locale's date and time, update tm_year, tm_mon, tm_mday, tm_hour,
+    tm_min, and tm_sec
+
+þitem %C
+
+    date and time, equivalent to %x %X, update tm_year, tm_mon,
+    tm_mday, tm_hour, tm_min, and tm_sec
+
+þitem %d
+
+    day of month (1-31), update tm_mday
+
+þitem %D
+
+    date, this is equivalent to %m/%d/%y, update tm_year, tm_mon, and
+    tm_mday
+
+þitem %e
+
+    day of month (1-31), update tm_mday
+
+þitem %H
+
+    hour (0-23), update tm_hour (%k is a synonym for %H)
+
+þitem %I
+
+    hour (1-12), update tm_hour (%l is a synonym for %I)
+
+þitem %j
+
+    day of year (1-366), update tm_yday
+
+þitem %m
+
+    month (1-12), update tm_mon
+
+þitem %M
+
+    minute (0-59), update tm_min
+
+þitem %n
+
+    newline character
+
+þitem %p
+
+    locale's equivalent to AM or PM, as appropriate (for use with %I),
+    update tm_hour
+
+þitem %r
+
+    time in AM/PM notation, this is equivalent to %I:%M:%S %p, update
+    tm_hour, tm_min, and tm_sec
+
+þitem %R
+
+    hour and minutes, equivalent to %H:%M, update tm_hour and tm_min
+
+þitem %S
+
+    second (0-59), update tm_sec
+
+þitem %t
+
+    TAB character
+
+þitem %T
+
+    time, equivalent to %H:%M:%S, update tm_hour, tm_min, tm_sec
+
+þitem %U
+
+    week number of the year, the first day of the week is Sunday
+    (0-53), currently ignored
+
+þitem %w
+
+    weekday, the first day of the week is Sunday (0-6), update tm_wday
+
+þitem %W
+
+    week number of the year, the first day of the week is Monday
+    (0-53), currently ignored
+
+þitem %x
+
+    locale's date representation, update tm_year, tm_mon, and tm_mday
+
+þitem %X
+
+    locale's time representation, update tm_hour, tm_min, and tm_sec
+
+þitem %y
+
+    year without century (0-99, mapping 0-68 to 2000-2068 and 69-99 to
+    1969-1999), update tm_year
+
+þitem %Y
+
+    year with century (1970-2106), update tm_year
+
+þenddescription
+
+    If % is followed by a character not listed above, the results are
+    undefined.
+
+þrestrictions
+
+    Case is currently not ignored for non-ASCII characters.  %p must
+    currently come after %I in the format string.
+
+    As behavior of other implementations of strptime() is quite
+    varying, this implementation of strptime() does not behave like
+    most other implementations of strptime().  strptime() is not
+    portable.
+
+þreturnvalue
+
+    If successful, strptime() returns a pointer to the character
+    following the last character parsed.  On error, strptime() returns
+    NULL.
+
+þseealso setlocale() sscanf() strftime()
+
+
+þfunction strrchr()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING C
+þprototype
+char *strrchr (const char *STRING, int C);
+þendprototype
+
+    Return a pointer to the last occurrence of the character C in the
+    null-terminated string pointed to by STRING.  If there is no
+    character C in that string, NULL is returned.  If C is the null
+    character (0), a pointer to the terminating null character of that
+    string is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso _memrchr() rindex() strchr()
+
+
+þfunction strrev()
+þcompat PC
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING
+þprototype
+char *strrev (char *STRING);
+þendprototype
+
+    Reverse the order of the characters in the string pointed to by
+    STRING.  The terminating null character remains in place.
+
+þreturnvalue
+
+    strrev() returns STRING.
+
+
+þfunction strset()
+þcompat PC
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING C
+þprototype
+char *strset (char *STRING, int C);
+þendprototype
+
+    Replace all the characters of the string pointed to by STRING with
+    the character C.  The terminating null character is not changed.
+
+þreturnvalue
+
+    strset() returns STRING.
+
+þseealso memset() strnset()
+
+
+þfunction strspn()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+size_t strspn (const char *STRING1, const char *STRING2);
+þendprototype
+
+    Return the length of the initial substring of the string pointed
+    to by STRING1 which consists entirely of characters in the string
+    pointed to by STRING2.  That is, the index of the first character
+    in the string pointed to by STRING1 which does not occur in the
+    string pointed to by STRING2 is returned.  If all characters in
+    the string pointed to by STRING1 also occur in the string pointed
+    to by STRING2, the length of the string pointed to by STRING1 is
+    returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso strcspn() strpbrk()
+
+
+þfunction strstr()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+char *strstr (const char *STRING1, const char *STRING2);
+þendprototype
+
+    Return a pointer to the first occurrence of the string pointed to
+    by STRING2 in the string pointed to by STRING1.  If the length of
+    the string pointed to by STRING2 is zero, STRING1 is returned.  If
+    the string pointed to by STRING2 is not a substring of the string
+    pointed to by STRING1, NULL is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso strchr()
+
+
+þfunction strtod() strtof() strtold()
+þcompat C90 C9X
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam STRING END_PTR
+þprototype
+double strtod (const char *STRING, char **END_PTR);
+float strtof (const char *STRING, char **END_PTR);
+long double strtold (const char *STRING, char **END_PTR);
+þendprototype
+
+    strtod() converts a character string to a þtt{double}.  Leading
+    white space is skipped.  strtod() stops at the first character
+    that cannot be converted.  The string pointed to by STRING is
+    expected to have one of the following forms:
+
+þindent
+  þsy{[<whitespace>] [+|-] [<digits>] [.<digits>] [[d|D|e|E] [+|-] <digits>]} þbreak
+  þsy{[<whitespace>] [+|-] INF} þbreak
+  þsy{[<whitespace>] [+|-] INFINITY} þbreak
+  þsy{[<whitespace>] [+|-] NAN} þbreak
+  þsy{[<whitespace>] [+|-] NAN(...)}
+þendindent
+
+    The decimal point character of the current locale is used.  Letter
+    case is ignored for INF, INFINITY, and NAN.  Digits, letters, and
+    the underscore character can occur in the parentheses following
+    `NAN'.
+
+    If END_PTR is not NULL and the conversion has been performed, a
+    pointer to the first character which cannot be converted is stored
+    to the object pointed to by END_PTR.  If END_PTR is not NULL and
+    no conversion has been performed, STRING is stored to the object
+    pointed to by END_PTR.
+
+    If no conversion could be performed, strtod() doesn't change errno
+    and returns 0.0 (you can examine the pointer stored to the object
+    pointed to by END_PTR to recognize this case).  On overflow,
+    strtod() sets errno to ERANGE and returns HUGE_VAL or
+    -þtt{HUGE_VAL}, depending on the sign of the number.  On
+    underflow, strtod() sets errno to ERANGE and returns 0.0.
+
+    The strtold() function proposed for C9X uses the þtt{long double}
+    format.  On overflow, strtold() returns HUGE_VALL or
+    -þtt{HUGE_VALL}, depending on the sign of the number.
+
+    The strtof() function proposed for C9X uses the þtt{float}
+    format.  On overflow, strtof() returns HUGE_VALF or
+    -þtt{HUGE_VALF}, depending on the sign of the number.
+
+þreturnvalue
+
+    strtod(), strtof(), and strtold() return the converted value.  If
+    no number is recognized, strtod(), strtof(), and strtold() return
+    0.0.  On overflow, strtod() returns HUGE_VAL or -þtt{HUGE_VAL}.
+    On overflow, strtof() returns HUGE_VALF or -þtt{HUGE_VALF}.  On
+    overflow, strtold() returns HUGE_VALL or -þtt{HUGE_VALL}.  On
+    underflow, strtod(), strtof(), and strtold() return 0.0.
+
+þseealso atof() setlocale() sscanf() strtol()
+
+
+þfunction strtok()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2
+þprototype
+char *strtok (char *STRING1, const char *STRING2);
+þendprototype
+
+    Return a pointer to the next token in the string pointed to by
+    STRING1.  The characters of the string pointed to by STRING2 are
+    the set of delimiting characters.  Tokens in the string pointed to
+    by STRING1 are separated by one or more characters from the string
+    pointed to by STRING2.
+
+    The first call to strtok() for STRING1 skips leading delimiters
+    and returns a pointer to the first token.  To get the next token
+    of the string pointed to by STRING1, call strtok() with a NULL
+    argument for STRING1.  The set of delimiters pointed to by STRING2
+    as well as the pointer STRING2 may be different on subsequent calls.
+
+    strtok() modifies the string pointed to by STRING1 by inserting
+    null characters for terminating tokens.  Thus, the pointer
+    returned by strtok() points to a null-terminated token.
+
+    If there are no more tokens, NULL is returned.
+
+þreturnvalue
+
+    See above.
+
+þseealso strpbrk()
+
+
+þfunction strtol()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam STRING END_PTR RADIX
+þprototype
+long strtol (const char *STRING, char **END_PTR, int RADIX);
+þendprototype
+
+    Convert a character string to a signed long integer.  The string
+    pointed to by STRING should have the following format:
+
+þindent
+  þsy{[<whitespace>] [+|-] [|0|0x|0X] <digits>}
+þendindent
+
+    Leading white space (as defined by isspace()) is skipped.  RADIX
+    is the number base used for conversion.  It must either be between
+    2 and 36 or be zero.
+
+    If RADIX is 0, the number base is derived from the format of the
+    number: If the number starts with þtt{0x}, base 16 is used.  If
+    the number starts with þtt{0} (not followed by þtt{x}), base 8 is
+    used.  If the number does not start with þtt{0}, base 10 is used.
+
+    strtol() stops at the first character that cannot be converted.
+    If END_PTR is not NULL and the conversion has been performed, a
+    pointer to the first character which cannot be converted is stored
+    to the object pointed to by END_PTR.  If END_PTR is not NULL and
+    no conversion has been performed, STRING is stored to the object
+    pointed to by END_PTR.
+
+    strtol() doesn't change errno and returns 0 if no conversion could
+    be performed (you can examine the pointer stored to the object
+    pointed to by END_PTR to recognize this case).  On overflow,
+    strtol() sets errno to ERANGE and returns LONG_MIN or LONG_MAX
+    (depending on the sign character).  If RADIX is out of range,
+    strtol() sets errno to EDOM and returns 0.
+
+þreturnvalue
+
+    strtol() returns the converted value.  If no number is recognized
+    or if RADIX is invalid, strtol() returns 0.  On overflow, strtol()
+    returns LONG_MIN or LONG_MAX.
+
+þseealso atol() isspace() _ltoa() _strtoll() strtoul() sscanf()
+
+þsamplecode
+int read_long (char **ptr, long *dst)
+{
+  char *p;
+  long n;
+
+  errno = 0;
+  n = strtol (*ptr, &p, 0);
+  if (errno != 0 || p == *ptr)
+    return 0;                   /* Failure */
+  *dst = n; *ptr = p;
+  return 1;                     /* Success */
+}
+þendsamplecode
+
+
+þfunction _strtoll()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam STRING END_PTR RADIX
+þprototype
+long long _strtoll (const char *STRING, char **END_PTR, int RADIX);
+þendprototype
+
+    Convert a character string to a signed long long integer.  The
+    string pointed to by STRING should have the following format:
+
+þindent
+  þsy{[<whitespace>] [+|-] [|0|0x|0X] <digits>}
+þendindent
+
+    Leading white space (as defined by isspace()) is skipped.  RADIX
+    is the number base used for conversion.  It must either be between
+    2 and 36 or be zero.
+
+    If RADIX is 0, the number base is derived from the format of the
+    number: If the number starts with þtt{0x}, base 16 is used.  If
+    the number starts with þtt{0} (not followed by þtt{x}), base 8 is
+    used.  If the number does not start with þtt{0}, base 10 is used.
+
+    _strtoll() stops at the first character that cannot be converted.
+    If END_PTR is not NULL and the conversion has been performed, a
+    pointer to the first character which cannot be converted is stored
+    to the object pointed to by END_PTR.  If END_PTR is not NULL and
+    no conversion has been performed, STRING is stored to the object
+    pointed to by END_PTR.
+
+    _strtoll() doesn't change errno and returns 0 if no conversion
+    could be performed (you can examine the pointer stored to the
+    object pointed to by END_PTR to recognize this case).  On
+    overflow, _strtoll() sets errno to ERANGE and returns
+    LONG_LONG_MIN or LONG_LONG_MAX (depending on the sign character).
+    If RADIX is out of range, _strtoll() sets errno to EDOM and
+    returns 0.
+
+þreturnvalue
+
+    _strtoll() returns the converted value.  If no number is
+    recognized or if RADIX is invalid, strtol() returns 0.  On
+    overflow, _strtoll() returns LONG_LONG_MIN or LONG_LONG_MAX.
+
+þseealso _atoll() isspace() _lltoa() strtol() _strtoull() sscanf()
+
+
+þfunction strtoul()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam STRING END_PTR RADIX
+þprototype
+unsigned long strtoul (const char *STRING, char **END_PTR, int RADIX);
+þendprototype
+
+    Convert a character string to an unsigned long integer.  The
+    string pointed to by STRING should have the following format:
+
+þindent
+  þsy{[<whitespace>] [+|-] [|0|0x|0X] <digits>}
+þendindent
+
+    Leading white space (as defined by isspace()) is skipped.  RADIX
+    is the number base used for conversion.  It must either be between
+    2 and 36 or be zero.
+
+    If RADIX is 0, the number base is derived from the format of the
+    number: If the number starts with þtt{0x}, base 16 is used.  If
+    the number starts with þtt{0} (not followed by þtt{x}), base 8 is
+    used.  If the number does not start with þtt{0}, base 10 is used.
+
+    strtoul() stops at the first character that cannot be converted.
+    If END_PTR is not NULL and the conversion has been performed, a
+    pointer to the first character which cannot be converted is stored
+    to the object pointed to by END_PTR.  If END_PTR is not NULL and
+    no conversion has been performed, STRING is stored to the object
+    pointed to by END_PTR.
+
+    strtoul() returns 0 if no conversion could be performed (errno will
+    not be changed).  On overflow, strtoul() sets errno to ERANGE and
+    returns ULONG_MAX.  If RADIX is out of range, strtoul() sets errno
+    to EDOM and returns 0.
+
+
+þreturnvalue
+
+    strtoul() returns the converted value.  If no number is recognized
+    or if RADIX is invalid, strtoul() returns 0.  On overflow, strtoul()
+    returns ULONG_MAX.
+
+þseealso isspace() strtol() _strtoull() sscanf() _ultoa()
+
+
+þfunction _strtoull()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam STRING END_PTR RADIX
+þprototype
+unsigned long long _strtoull (const char *STRING, char **END_PTR, int RADIX);
+þendprototype
+
+    Convert a character string to an unsigned long long integer.  The
+    string pointed to by STRING should have the following format:
+
+þindent
+  þsy{[<whitespace>] [+|-] [|0|0x|0X] <digits>}
+þendindent
+
+    Leading white space (as defined by isspace()) is skipped.  RADIX
+    is the number base used for conversion.  It must either be between
+    2 and 36 or be zero.
+
+    If RADIX is 0, the number base is derived from the format of the
+    number: If the number starts with þtt{0x}, base 16 is used.  If
+    the number starts with þtt{0} (not followed by þtt{x}), base 8 is
+    used.  If the number does not start with þtt{0}, base 10 is used.
+
+    _strtoull() stops at the first character that cannot be converted.
+    If END_PTR is not NULL and the conversion has been performed, a
+    pointer to the first character which cannot be converted is stored
+    to the object pointed to by END_PTR.  If END_PTR is not NULL and
+    no conversion has been performed, STRING is stored to the object
+    pointed to by END_PTR.
+
+    _strtoull() returns 0 if no conversion could be performed (errno
+    will not be changed).  On overflow, _strtoull() sets errno to
+    ERANGE and returns ULONG_LONG_MAX.  If RADIX is out of range,
+    _strtoull() sets errno to EDOM and returns 0.
+
+þreturnvalue
+
+    _strtoull() returns the converted value.  If no number is recognized
+    or if RADIX is invalid, _strtoull() returns 0.  On overflow, _strtoull()
+    returns ULONG_LONG_MAX.
+
+þseealso isspace() _strtoll() strtoul() sscanf() _ulltoa()
+
+
+þfunction strupr()
+þcompat PC
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING
+þprototype
+char *strupr (char *STRING);
+þendprototype
+
+    Convert the string pointed to by STRING to upper case.  The
+    characters þtt{'a'} through þtt{'z'} are mapped to the characters
+    þtt{'A'} through þtt{'Z'}.  All other characters are not changed.
+
+þreturnvalue
+
+    strupr() returns STRING.
+
+þseealso strlwr()
+
+
+þfunction strxfrm()
+þcompat C90
+þheaders
+#include <string.h>
+þendheaders
+
+þparam STRING1 STRING2 N
+þprototype
+size_t strxfrm (char *STRING1, const char *STRING2, size_t N);
+þendprototype
+
+    Transform the string pointed to by STRING2 according to the
+    LC_COLLATE category of the current locale and copy the result to
+    the array pointed to by STRING1.  After applying strxfrm(), you
+    can use strcmp() for comparing the strings; applying strcmp() to
+    strings transformed by strxfrm() is equivalent to calling
+    strcoll() on the original strings.  At most N characters
+    (including the terminating null character) are stored to the array
+    pointed to by STRING1.  STRING1 can be NULL if N is zero.
+
+þreturnvalue
+
+    strxfrm() returns the number of characters in the transformed
+    string (excluding the terminating null character), even if that
+    number exceeds N.  If the return value is equal to or greater than
+    N, the contents of the string pointed to by STRING1 are
+    indeterminate.
+
+þrestrictions
+
+    Currently, locale is ignored: strxfrm() copies the characters
+    without modifications.
+
+þseealso setlocale() strcoll()
+
+þsamplecode
+/* Transform a string, allocating memory with malloc(). */
+char *xfrm (const char *s)
+{
+  size_t len = strxfrm (NULL, s, 0);
+  char *t = malloc (len + 1);
+  if (t != NULL)
+    strxfrm (t, s, len + 1);
+  return t;
+}
+þendsamplecode
+
+
+þfunction swab()
+þcompat UNIX
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam SRC DST N
+þprototype
+void swab (const void *SRC, void *DST, size_t N);
+þendprototype
+
+    Copy N bytes from SRC to DST, swapping each pair of adjacent
+    bytes.  N must be even.
+
+
+þfunction _swchar()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+char _swchar (void);
+þendprototype
+
+    Retrieve the current switch character.  If the switch character
+    has been changed to þtt{'-'}, _swchar() returns þtt{'-'}.
+    Otherwise, _swchar() returns 0.  In this case, you should use the
+    standard switch character þtt{'/'}.
+
+þreturnvalue
+
+    See above.
+
+þseealso getopt()
+
+
+þfunction sysconf()
+þcompat POSIX.1
+þheaders
+#include <unistd.h>
+þendheaders
+
+þparam NAME
+þprototype
+long sysconf (int NAME);
+þendprototype
+
+    Return the current value of the configurable system limit or
+    option NAME.  NAME is one of the following constants:
+
+þdescription
+þitem _SC_ARG_MAX
+
+    corresponds to ARG_MAX (length of arguments and environment for
+    þtt{exec*()}, in bytes)
+
+þitem _SC_CHILD_MAX
+
+    corresponds to CHILD_MAX (number of simultaneous processes per
+    real user ID)
+
+þitem _SC_CLK_TCK
+
+    number of clock ticks per second, for times()
+
+þitem _SC_NGROUPS_MAX
+
+    corresponds to NGROUPS_MAX (maximum number of simultaneous
+    supplementary group IDs per process)
+
+þitem _SC_OPEN_MAX
+
+    corresponds to OPEN_MAX (number of files that one process can have
+    open at one time)
+
+þitem _SC_STREAM_MAX
+
+    corresponds to STREAM_MAX (number of streams that one process can
+    have open at one time)
+
+þitem _SC_TZNAME_MAX
+
+    corresponds to TZNAME_MAX (number of bytes supported for the name
+    of a time zone)
+
+þitem _SC_JOB_CONTROL
+
+    corresponds to _POSIX_JOB_CONTROL (defined if the implementation
+    supports job control -- emx doesn't)
+
+þitem _SC_SAVED_IDS
+
+    corresponds to _POSIX_SAVED_IDS (defined if each process has a
+    saved set-user-ID and a saved set-group-ID -- not true for emx)
+
+þitem _SC_VERSION
+
+    corresponds to _POSIX_VERSION (the integer 199009L)
+
+þenddescription
+
+    See POSIX.1 for more details.
+
+þreturnvalue
+
+    If NAME is invalid, sysconf() sets errno to EINVAL and returns -1.
+    If NAME is associated with functionality that is not supported by
+    the system, sysconf() returns -1 and does not change errno.
+    Otherwise, sysconf() returns the current value of the variable.
+
+þrestrictions
+
+    sysconf() currently returns just the POSIX.1 minimum values.
+
+þseealso fpathconf() pathconf()
+
+
+þfunction _syserrno()
+þcompat emx *
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+int _syserrno (void);
+þendprototype
+
+    Return the OS/2 or DOS error code for the last system call of the
+    current thread.  If there was no error, 0 is returned.  If the
+    last system call hasn't called an OS/2 or DOS function, 0 is
+    returned.
+
+þreturnvalue
+
+    See above.
+
+þrestrictions
+
+    _syserrno() is not implemented under DOS.  _syserrno() is not
+    supported with the system call library sys.lib (þhpt{-Zsys}).
+
+þseealso errno _setsyserrno()
+
+þfunction system()
+þcompat C90
+þheaders
+#include <process.h>
+þendheaders
+
+þparam NAME
+þprototype
+int system (const char *NAME);
+þendprototype
+
+    Execute a command by passing it to the command interpreter.  NAME
+    is a pointer to a string containing the command name.  system()
+    uses the COMSPEC environment variable for locating cmd.exe or
+    command.com, respectively.  The COMSPEC environment variable can
+    be overriden by setting the EMXSHELL environment variable.  The
+    PATH environment variable is not used for locating cmd.exe.  If
+    the argument is þtt{""}, an interactive shell will be started.  If
+    the argument is NULL, system() only checks whether cmd.exe or
+    command.com, respectively, can be found.
+
+    As command.com is used under DOS, the command line is restricted
+    to about 123 characters.  If you don't need a command shell, use
+    spawn*() instead of system().  It's a bad idea to run emx programs
+    using system() -- not tested.  You must use the -p emx option when
+    using system() under DOS, see `þhpt{Using emx options}'.
+
+    The system() function passes the þtt{/c} option to the command
+    processor if COMSPEC (or EMXSHELL) points to cmd.exe,
+    þtt{4os2.exe}, command.com or þtt{4dos.com}.  Otherwise,
+    system() assumes that a Unix-like shell is to be used and passes
+    the þtt{-c} option.
+
+þreturnvalue
+
+    If system() fails, errno is set and -1 is returned.  If the
+    argument is NULL and the command processor can be found, 0 is
+    returned.  In all other cases, the return code of the command
+    processor is returned.  The return code of the program run by the
+    command processor is returned by cmd.exe but not by command.com.
+    command.com always returns 0.
+
+þseealso popen() spawn*()
+
+
+þfunction _tcalloc()
+þcompat OS/2
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam ELEMENTS SIZE
+þprototype
+void *_tcalloc (size_t ELEMENTS, size_t SIZE);
+þendprototype
+
+    Allocate a block of memory big enough for holding ELEMENTS
+    elements of SIZE bytes each.  The block will not cross a 64 KByte
+    boundary unless SIZE is greater than 65536.  If SIZE is greater
+    than 65536, the block will be aligned on a 64 KByte boundary.
+    _tcalloc() fills the block with zeros.  If there is an error,
+    _tcalloc() returns NULL.
+
+þreturnvalue
+
+    _tcalloc() returns a pointer to a newly allocated block of
+    memory.  On error, _tcalloc() returns NULL.
+
+þrestrictions
+
+    If you replace the emx malloc() implementation with a malloc()
+    implementation (GNU malloc, for instance) that has not _tmalloc()
+    etc. built in, you have to link with the þtt{tmalloc} library
+    (-ltmalloc), which implements _tmalloc() etc. on top of malloc()
+    etc.
+
+þseealso calloc() _tfree() _tmalloc() _utcalloc() _utdefault()
+
+
+þfunction tcdrain()
+þcompat POSIX.1 *
+þheaders
+#include <termios.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+int tcdrain (int HANDLE);
+þendprototype
+
+    tcdrain() waits until all output written to the terminal
+    associated with the file descriptor HANDLE has been transmitted.
+
+þreturnvalue
+
+    tcdrain() returns 0 if successful.  Otherwise, tcdrain()
+    sets errno and returns -1.
+
+þerrors
+þdescription
+þitem EBADF
+  HANDLE is not a valid open file descriptor.
+þitem ENOTTY
+  HANDLE is not associated with a terminal.
+þenddescription
+
+þimplementation
+
+    tcdrain() currently does nothing and always succeeds.
+
+þrestrictions
+
+    tcdrain() is not available with the system call library sys.lib
+    (þhpt{-Zsys}).
+
+þseealso tcflow() tcflush() tcsendbreak() tcsetattr()
+
+
+þfunction tcflow()
+þcompat POSIX.1 *
+þheaders
+#include <termios.h>
+þendheaders
+
+þparam HANDLE ACTION
+þprototype
+int tcflow (int HANDLE, int ACTION);
+þendprototype
+
+    tcflow() suspends or resumes transmission or reception of data on
+    the terminal associated with the file descriptor HANDLE, depending
+    on ACTION:
+
+þdescription
+þitem TCIOFF
+  Transmit a VSTOP character to suspend input.
+þitem TCION
+  Transmit a VSTART character to resume suspended input.
+þitem TCOOFF
+  Suspend output.
+þitem TCOON
+  Resume suspended output.
+þenddescription
+
+    See `þhpt{General terminal interface}' for details.
+
+þreturnvalue
+
+    tcflow() returns 0 if successful.  Otherwise, tcflow()
+    sets errno and returns -1.
+
+þerrors
+þdescription
+þitem EBADF
+  HANDLE is not a valid open file descriptor.
+þitem ENOTTY
+  HANDLE is not associated with a terminal.
+þenddescription
+
+þimplementation
+
+    tcflow() currently does nothing and always succeeds.
+
+þrestrictions
+
+    tcflow() is not available with the system call library sys.lib
+    (þhpt{-Zsys}).
+
+þseealso tcdrain() tcflush() tcsendbreak() tcsetattr()
+
+
+þfunction tcflush()
+þcompat POSIX.1 *
+þheaders
+#include <termios.h>
+þendheaders
+
+þparam HANDLE QUEUE
+þprototype
+int tcflush (int HANDLE, int QUEUE);
+þendprototype
+
+    tcflush() flushes the input and/or output queues of the terminal
+    associated with the file descriptor HANDLE, depending on QUEUE:
+
+þdescription
+þitem TCIFLUSH
+  Flush the input queue.
+þitem TCOFLUSH
+  Flush the output queue.
+þitem TCIOFLUSH
+  Flush the both the input and output queues.
+þenddescription
+
+þreturnvalue
+
+    tcflush() returns 0 if successful.  Otherwise, tcflush()
+    sets errno and returns -1.
+
+þerrors
+þdescription
+þitem EBADF
+  HANDLE is not a valid open file descriptor.
+þitem EINVAL
+  QUEUE is not valid.
+þitem ENOTTY
+  HANDLE is not associated with a terminal.
+þenddescription
+
+þimplementation
+
+    tcflush() currently works on the keyboard, only.
+
+þrestrictions
+
+    tcflush() is not available with the system call library sys.lib
+    (þhpt{-Zsys}).
+
+    Under DOS, the value of the HANDLE argument must be 0.
+
+þseealso tcdrain() tcflow() tcsendbreak() tcsetattr()
+
+
+þfunction tcgetattr()
+þcompat POSIX.1 *
+þheaders
+#include <termios.h>
+þendheaders
+
+þparam HANDLE PTERMIOS
+þprototype
+int tcgetattr (int HANDLE, struct termios *PTERMIOS);
+þendprototype
+
+    Store the parameters of the terminal associated with the file
+    descriptor HANDLE to the object pointed to by PTERMIOS.
+
+    See `þhpt{General terminal interface}' for details.
+
+þreturnvalue
+
+    tcgetattr() returns 0 if successful.  Otherwise, tcgetattr() sets
+    errno and returns -1.
+
+þerrors
+þdescription
+þitem EBADF
+  HANDLE is not a valid open file descriptor.
+þitem ENOTTY
+  HANDLE is not associated with a terminal.
+þenddescription
+
+þimplementation
+
+    Currently, errno is set to ENOTTY instead of EBADF if HANDLE is
+    out of range.
+
+þrestrictions
+
+    tcgetattr() is not available with the system call library sys.lib
+    (þhpt{-Zsys}).
+
+    Under DOS, the value of the HANDLE argument must be 0.
+
+þseealso cfgetispeed() cfgetospeed() tcsetattr()
+
+
+þfunction tcsendbreak()
+þcompat POSIX.1 *
+þheaders
+#include <termios.h>
+þendheaders
+
+þparam HANDLE DURATION
+þprototype
+int tcsendbreak (int HANDLE, int DURATION);
+þendprototype
+
+    tcsendbreak() sends a `break' on an asynchronous line.  The
+    duration of the `break' is controlled by DURATION in a
+    not-yet-specified way.  If applied to a handle which is not
+    associated with an asynchronous line, tcsendbreak() does nothing.
+
+þreturnvalue
+
+    tcsendbreak() returns 0 if successful.  Otherwise, tcsendbreak()
+    sets errno and returns -1.
+
+þerrors
+þdescription
+þitem EBADF
+  HANDLE is not a valid open file descriptor.
+þitem ENOTTY
+  HANDLE is not associated with a terminal.
+þenddescription
+
+þimplementation
+
+    tcsendbreak() currently does nothing and always succeeds.
+
+þrestrictions
+
+    tcsendbreak() is not available with the system call library
+    sys.lib (þhpt{-Zsys}).
+
+þseealso tcdrain() tcflow() tcflush() tcsetattr()
+
+
+þfunction tcsetattr()
+þcompat POSIX.1 *
+þheaders
+#include <termios.h>
+þendheaders
+
+þparam HANDLE OPTIONS PTERMIOS
+þprototype
+int tcsetattr (int HANDLE, int OPTIONS, const struct termios *PTERMIOS);
+þendprototype
+
+    Set the parameters of the terminal associated with the file
+    descriptor HANDLE from the object pointed to by PTERMIOS.  OPTIONS
+    must be one of the following symbols:
+
+þdescription
+þitem TCSANOW
+  The change is performed immediately.
+þitem TCSADRAIN
+  The change is performed after all output has been transmitted.
+þitem TCSAFLUSH
+  The change is performed after all output has been transmitted.
+  The input queue is flushed before performing the change.
+þenddescription
+
+    See `þhpt{General terminal interface}' for details.
+
+þreturnvalue
+
+    tcsetattr() returns 0 if successful.  Otherwise, tcsetattr() sets
+    errno and returns -1.
+
+þerrors
+þdescription
+þitem EBADF
+  HANDLE is not a valid open file descriptor.
+þitem EINVAL
+  OPTIONS is not valid or an attempt was made to change an attribute
+  to an unsupported value.
+þitem ENOTTY
+  HANDLE is not associated with a terminal.
+þenddescription
+
+þimplementation
+
+    Currently, errno is set to ENOTTY instead of EBADF if HANDLE is
+    out of range.
+
+þrestrictions
+
+    tcsetattr() is not available with the system call library sys.lib
+    (þhpt{-Zsys}).
+
+    Under DOS, the value of the HANDLE argument must be 0.
+
+þseealso cfsetispeed() cfsetospeed() tcdrain() tcflush() tcgetattr()
+
+
+þfunction tell()
+þcompat PC
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+long tell (int HANDLE);
+þendprototype
+
+    tell() returns the current position of the file pointer of HANDLE.
+    If there is an error, tell() returns -1.
+
+þreturnvalue
+
+    See above.
+
+þseealso lseek()
+
+
+þfunction tempnam()
+þcompat UNIX
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam DIR PREFIX
+þprototype
+char *tempnam (const char *DIR, const char *PREFIX);
+þendprototype
+
+    Generate a file name suitable for a temporary file without
+    overwriting an existing file.  tempnam() returns a pointer to a
+    string allocated by malloc().  If the TMP environment variable is
+    set and the directory specified by TMP exists, that directory is
+    used.  Otherwise, the DIR argument is used.  If DIR is NULL or the
+    directory whose name is in the string pointed to by DIR does not
+    exist, P_tmpdir as defined in <stdio.h> is used.  If even this
+    fails, NULL is returned.  The name of the file will start with the
+    string pointed to by PREFIX.  The string pointed to by PREFIX must
+    not be longer than 5 characters.
+
+þreturnvalue
+
+    See above.
+
+þseealso tmpnam()
+
+
+þfunction _tfree()
+þcompat OS/2
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam MEM
+þprototype
+void _tfree (void *MEM);
+þendprototype
+
+    Deallocate a block of memory allocated by _tmalloc(), _tcalloc()
+    or _trealloc().  MEM points to the block of memory.  MEM must have
+    been returned by _tmalloc(), _tcalloc() or _trealloc().  Do not
+    use MEM after calling _tfree().  If MEM is NULL, _tfree() does
+    nothing.
+
+þrestrictions
+
+    If you replace the emx malloc() implementation with a malloc()
+    implementation (GNU malloc), for instance) that has not _tmalloc()
+    etc. built in, you have to link with the þtt{tmalloc} library
+    (-ltmalloc), which implements _tmalloc() etc. on top of malloc()
+    etc.
+
+þseealso free() _tcalloc() _tmalloc() _trealloc()
+
+
+þfunction _theapmin()
+þcompat VAC++
+þheaders
+#include <malloc.h>
+þendheaders
+
+þprototype
+int _theapmin (void);
+þendprototype
+
+    The _theapmin() function returns unused memory of the tiled
+    default heap to the operating system.  The heap is never made
+    smaller than its initial size.  Calling _theapmin() is equivalent
+    to calling _uheapmin() for the tiled default heap.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso brk() _heapchk() sbrk() _heapmin() _uheapmin() _utdefault()
+
+
+þfunction _threadstore()
+þcompat OS/2
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam PTR
+þprototype
+void **_threadstore (void);
+þendprototype
+
+    The _threadstore() function returns the address of a pointer to
+    thread-specific user-defined data.  Initially, that pointer is
+    NULL.  To create thread-specific data, allocate a memory object
+    (using malloc(), for instance) and assign the address of that
+    memory object to the location returned by _threadstore():
+
+þexample
+p = malloc (sizeof (struct user_data));
+*_threadstore() = p;
+þendexample
+
+    To access a thread-specific variable, use _threadstore() to get
+    the pointer to the memory object:
+
+þexample
+x = (*_threadstore)->myvar;
+þendexample
+
+þreturnvalue
+
+    _threadstore() returns the address of a pointer located in the
+    thread-specific data block of the emx C library.
+
+þrestrictions
+
+    _threadstore() is available only in the multithread libraries
+    (-Zmt, -Zmts, or -Zmtd).
+
+þseealso _beginthread() _gettid() _threadid
+
+
+þfunction time()
+þcompat C90
+þheaders
+#include <time.h>
+þendheaders
+
+þparam PTR
+þprototype
+time_t time (time_t *PTR);
+þendprototype
+
+    Return the number of seconds elapsed since 00:00:00 1-Jan-1970
+    Coordinated Universal Time (UTC, GMT).  The system time is
+    converted according to the local timezone.  If PTR is not NULL,
+    the result is also stored to the variable pointed to by PTR.
+
+þreturnvalue
+
+    See above.
+
+þseealso ftime() gettimeofday() gmtime() localtime() settimeofday()
+
+
+þfunction times()
+þcompat UNIX
+þheaders
+#include <time.h>
+#include <sys/times.h>
+#include <sys/param.h>  /* for HZ */
+þendheaders
+
+þparam BUFFER
+þprototype
+long times (struct tms *BUFFER);
+þendprototype
+
+    Return the current time in CLK_TCK fractions of a second since
+    00:00:00 1-Jan-1970 Coordinated Universal Time (UTC, GMT).  Also
+    sets the tms_utime field of BUFFER to the number of HZ fractions
+    of a second the process has been running.  The other fields are
+    set to 0.
+
+þreturnvalue
+
+    times() returns the current time in CLK_TCK fractions of a second
+    since 00:00 1-Jan-1970 UTC.
+
+þrestrictions
+
+    The return value is unusable due to overflow.
+
+þseealso clock() time()
+
+
+þfunction _tmalloc()
+þcompat OS/2
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam SIZE
+þprototype
+void *_tmalloc (size_t SIZE);
+þendprototype
+
+    Allocate a block of memory big enough for holding SIZE bytes.  The
+    block will not cross a 64 KByte boundary unless SIZE is greater
+    than 65536.  If SIZE is greater than 65536, the block will be
+    aligned on a 64 KByte boundary.  Therefore, blocks allocated with
+    _tmalloc() can be used with 16-bit functions.  If there is an
+    error, _tmalloc() returns NULL.  If SIZE is 0, zero bytes of
+    memory are allocated, the return value will be unequal NULL.  Use
+    _tfree() to deallocate a block of memory allocated by _tmalloc().
+
+    As _tmalloc() causes additional heap fragmentation, you should not
+    use _tmalloc() unless you need an aligned block.
+
+þreturnvalue
+
+    _tmalloc() returns a pointer to a newly allocated block of memory.
+    On error, _tmalloc() returns NULL.
+
+þrestrictions
+
+    If you replace the emx malloc() implementation with a malloc()
+    implementation (GNU malloc, for instance) that has not _tmalloc()
+    etc. built in, you have to link with the þtt{tmalloc} library
+    (-ltmalloc), which implements _tmalloc() etc. on top of malloc()
+    etc.
+
+þseealso malloc() _tcalloc() _tfree() _trealloc() _utdefault() _utmalloc()
+
+
+þfunction tmpfile()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þprototype
+FILE *tmpfile (void);
+þendprototype
+
+    Create and open a temporary file.  The file is opened in
+    þtt{"w+b"} mode.  The file will automatically be deleted when the
+    stream is closed with fclose() or at program termination.
+
+þreturnvalue
+
+    On success, tmpfile() returns a pointer to the stream associated
+    with the temporary file.  If the file cannot be created, tmpfile()
+    returns NULL.
+
+þimplementation
+
+    The name of the file is created as if tmpnam() were called.
+
+    The temporary file will not be deleted if the program terminates
+    abnormally.
+
+þseealso fclose() _rmtmp() tmpnam()
+
+
+þfunction tmpnam()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam STRING
+þprototype
+char *tmpnam (char *STRING);
+þendprototype
+
+    Create a unique file name and store it to the array pointed to by
+    STRING.  tmpnam() generates a different file name each time it is
+    called, up to TMP_MAX times.  If STRING is NULL, a static buffer
+    is used which will be overwritten by subsequent calls.  If STRING
+    is not NULL, it must point to an array of at least L_tmpnam
+    characters.
+
+þreturnvalue
+
+    On success, tmpnam() returns a pointer to the new name.  On
+    failure, tmpnam() returns NULL.
+
+þimplementation
+
+    The file name is the concatenation of P_tmpdir and a sequence of
+    digits.
+
+þhints
+
+    Use tmpfile() if you need a temporary file but don't need the name
+    of that file.  Note that tmpnam() is subject to a race condition:
+    other processes may use the same temporary file name before you
+    have a chance to create the temporary file.
+
+þseealso tempnam() tmpfile() mktemp()
+
+
+þfunction tolower() toupper()
+þcompat C90
+þheaders
+#include <ctype.h>
+þendheaders
+
+þparam C
+þprototype
+int tolower (int C);
+int toupper (int C);
+þendprototype
+
+    tolower() converts the character C to lower case, if it is an
+    upper-case letter.  toupper() converts the character C to upper
+    case, if it is a lower-case letter.
+
+þreturnvalue
+
+    If the argument of tolower() is a character for which isupper() is
+    true and there is a corresponding character for which islower() is
+    true, tolower() returns the corresponding character; otherwise
+    tolower() returns the argument unchanged.
+
+    If the argument of toupper() is a character for which islower() is
+    true and there is a corresponding character for which isupper() is
+    true, toupper() returns the corresponding character; otherwise
+    toupper() returns the argument unchanged.
+
+þrestrictions
+
+    Currently, locale is ignored.
+
+þseealso setlocale() stricmp() strlwr() strupr() _tolower() _toupper()
+
+
+þfunction _tolower() _toupper()
+þcompat UNIX
+þheaders
+#include <ctype.h>
+þendheaders
+
+þparam C
+þprototype
+int _tolower (int C);
+int _toupper (int C);
+þendprototype
+
+    _tolower() converts the upper-case character C to lower case; C
+    must be in the range þtt{'A'} through þtt{'Z'}.  _toupper()
+    converts the lower-case character C to upper case; C must be in
+    the range þtt{'a'} through þtt{'z'}.
+
+þreturnvalue
+
+    See above.
+
+þseealso tolower() toupper()
+
+
+þfunction _trealloc()
+þcompat OS/2
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam MEM SIZE
+þprototype
+void *_trealloc (void *MEM, size_t SIZE);
+þendprototype
+
+    Reallocate the block of memory pointed to by MEM, making it big
+    enough to hold SIZE bytes.  The block will not cross a 64 KByte
+    boundary unless SIZE is greater than 65536.  If SIZE is greater
+    than 65536, the block will be aligned on a 64 KByte boundary.  If
+    MEM is NULL, a new block of memory is allocated.  Otherwise, MEM
+    must be a pointer returned by _tcalloc(), _tmalloc() or
+    _trealloc(); the size of MEM is adjusted.  If MEM is non-þtt{NULL}
+    and SIZE is zero, the block is freed and NULL is returned.  If MEM
+    cannot be expanded in-place, it is moved.  A pointer to the new,
+    resized block of memory is returned.  If there is not enough
+    memory available, NULL is returned.
+
+    MEM can also be a pointer to a block of memory freed by _tfree()
+    as long as calloc(), malloc(), realloc(), _tcalloc(), _tmalloc()
+    and _trealloc() have not been called since freeing the block.
+    Using this feature is not recommended, it may get removed in
+    future implementations of _trealloc().
+
+þreturnvalue
+
+    _trealloc() returns MEM (if the block could be resized without
+    moving), a pointer to a newly allocated block of memory, or NULL
+    (if there wasn't enough memory).
+
+þrestrictions
+
+    If you replace the emx malloc() implementation with a malloc()
+    implementation (GNU malloc, for instance) that has not _tmalloc()
+    etc. built in, you have to link with the þtt{tmalloc} library
+    (-ltmalloc), which implements _tmalloc() etc. on top of malloc()
+    etc.
+
+þseealso realloc() _tmalloc() _utdefault()
+
+
+þfunction trunc() truncl()
+þcompat C9X
+þheaders
+#include <math.h>
+þendheaders
+
+þparam X
+þprototype
+double trunc (double X);
+long double truncl (long double X);
+þendprototype
+
+    Return as floating-point number X chopped to an integer by
+    truncating the fractional digits (rounding toward 0).
+
+    truncl() uses the þtt{long double} format.
+
+þreturnvalue
+
+    See above.
+
+þseealso ceil() floor() modf() rint()
+
+
+þfunction truncate()
+þcompat BSD
+þheaders
+#include <io.h>
+þendheaders
+
+þparam NAME LENGTH
+þprototype
+int truncate (char *NAME, long LENGTH);
+þendprototype
+
+    Truncate a file to at most LENGTH bytes.  NAME is a pointer to a
+    string containing the name of the file.  If LENGTH is greater than
+    the current length of the file, the length is not changed.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso chsize() ftruncate()
+
+
+þfunction ttyname()
+þcompat POSIX.1
+þheaders
+#include <unistd.h>
+þendheaders
+
+þparam HANDLE
+þprototype
+char *ttyname (int HANDLE);
+þendprototype
+
+    Return a pointer to a string containing the pathname of the device
+    associated with file descriptor HANDLE.
+
+    The pointer returned by ttyname() may point to a static buffer
+    which is overwritten by each call of ttyname().
+
+þreturnvalue
+
+    If successful, ttyname() returns a pointer to a null-terminated
+    string.  On error, ttyname() returns NULL.
+
+þrestrictions
+
+    ttyname() is not implemented for DOS.  ttyname() is not available
+    with the system call library sys.lib (þhpt{-Zsys}).
+
+    ttyname() is implemented for the following devices only:
+    þtt{/dev/con}, þtt{/dev/nul}, þtt{/dev/clock$}, and the devices of
+    Holger Veit's þtt{xf86sup.sys} device driver.
+
+þseealso fstat() isatty()
+
+
+þfunction tzset()
+þcompat C90 VAC++
+þheaders
+#include <time.h>
+þendheaders
+
+þprototype
+void tzset (void);
+þendprototype
+
+    Set timezone according to the TZ environment variable.  The
+    following global variables are set by tzset(): þtt{daylight},
+    þtt{timezone}, tzname.  The value of TZ has the following format:
+
+þindent
+    þsy{<TZ1>[<OFF>,[<TZ2>[,<SM>,<SW>,<SD>,<ST>,<EM>,<EW>,<ED>,<ET>,<SHIFT>]]]}
+þendindent
+
+    þsy{<TZ1>} is the three-letter name of the standard timezone.
+
+    þsy{<OFF>} is the offset to Coordinated Universal Time; positive
+    values are to the west of the Prime Meridian, negative values are
+    to the east of the Prime Meridian.  The offset can be specified as
+    hours, hours and minutes, or hours, minutes, and seconds.  Hours,
+    minutes, and seconds are separated by colons.  If þsy{<OFF>} is
+    not specified, an offset of 0 will be used (this may change in the
+    future).
+
+    þsy{<TZ2>} is the three-letter name of the summer timezone
+    (daylight saving time).  If þsy{<TZ2>} is not specified, daylight
+    saving time does not apply.  If þsy{<TZ2>} is specified, daylight
+    saving time does apply; the remainder of the TZ's value specifies
+    when and how to change to and back from daylight saving time.
+    þsy{<SM>} through þsy{<ST>} define, in current local time, when to
+    switch from standard time to daylight saving time, þsy{<EM>}
+    through þsy{<ET>} define, in current local time, when to switch
+    from daylight saving time to standard time.  (On the southern
+    hemisphere, the end date precedes the start date.)  þsy{<SHIFT>} is
+    the amount of change in seconds.
+
+    þsy{<SM>} specifies the month (1 through 12) of the change.
+    þsy{<SW>} specifies the week of the change; if this value is zero,
+    þsy{<SD>} specifies the day of month (1 through 31).  If þsy{<SW>}
+    is positive (1 through 4), the change occurs on weekday þsy{<SD>}
+    (0=Sunday through 6=Saturday) of the þsy{<SW>}th week of the
+    specified month.  The first week of a month starts on the first
+    Sunday of the month.  If þsy{<SW>} is negative (-1 through -4),
+    the change occurs on weekday þsy{<SD>} (0=Sunday through
+    6=Saturday) of the -þsy{<SW>}th week of the specified month,
+    counted from the end of the month (that is, -1 specifies the last
+    week of the month).  The last week of a month starts on the last
+    Sunday of the month.  þsy{<ST>} specifies the time of the change,
+    in seconds.  Note that þsy{<ST>} is specified in local standard
+    time and þsy{<ET>} is specified in local daylight saving time.
+    Example:
+
+þexample
+CET-1CED,3,-1,0,7200,10,-1,0,10800,3600
+þendexample
+
+    In this example, the name of the standard time zone is þtt{CET},
+    the name of the summer time zone is CED.  Daylight saving time
+    starts at 2:00 on the last Sunday of March and ends at 3:00 on the
+    last Sunday of October.  Time changes by one hour in daylight
+    saving time.
+
+    If no characters follow þsy{<TZ2>}, the rule
+    `þtt{,4,1,0,3600,10,-1,0,7200,3600}' will be used: Daylight saving
+    time starts at 1:00 on the first Sunday of April and ends at 2:00
+    on the last Sunday of October.  Time changes by one hour in
+    daylight saving time.
+
+    If the value of TZ is invalid, tzset() does not have any effect.
+
+þimplementation
+
+    If TZ is not set, Coordinated Universal Time will be used.
+
+    The three-character limit for timezone names and the weird and
+    US-based definition of `first week' and `last week' are required
+    for compatibility with applications compiled with VAC++.
+
+þrestrictions
+
+    After changing the value of TZ by modifying environ, you should
+    call tzset().  That is not required when changing TZ with putenv().
+
+þseealso environ putenv()
+
+
+þfunction _uaddmem()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H MEMORY SIZE CLEAN
+þprototype
+Heap_t _uaddmem (Heap_t H, void *MEMORY, size_t SIZE, int CLEAN);
+þendprototype
+
+    _uaddmem() adds memory to the heap H.  MEMORY points to the memory
+    area to be added, SIZE is the size of the memory area in bytes.
+    CLEAN should be _BLOCK_CLEAN if the memory area has been
+    initialized to zeros; CLEAN should be þtt{!_BLOCK_CLEAN} if the
+    memory area contains or may contain non-zero bytes.  If the heap
+    is shared, MEMORY should point to shared memory.
+
+    If the memory area added by _uaddmem() is adjacent to (the end of)
+    one of the segments of the heap, that segment will be expanded.
+    Otherwise, a new segment will be created and a number of bytes of
+    the memory area will be used for storing control information.
+
+þhints
+
+    Add few large memory areas instead of many small memory areas to
+    minimize the total overhead of the control information added to
+    the segments.  Moreover, the size of the segments limits the size
+    of the blocks which can be allocated from the heap.
+
+    Memory allocated with DosAllocMem is initialized to zeros.
+
+þreturnvalue
+
+    _uaddmem() returns H if successful.  _uaddmem() returns NULL on
+    error.
+
+þseealso sbrk() _ucreate() _ucreate2() _udestroy()
+
+
+þfunction _ucalloc()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H ELEMENTS SIZE
+þprototype
+void *_ucalloc (Heap_t H, size_t ELEMENTS, size_t SIZE);
+þendprototype
+
+    Allocate from the heap H a block of memory big enough for holding
+    ELEMENTS elements of SIZE bytes each.  _ucalloc() fills the block
+    with zeros.  If there is an error, _ucalloc() returns NULL.
+
+þimplementation
+
+    If at least one argument is zero, _ucalloc() returns a non-NULL
+    pointer if there's enough space left in the heap for a block of
+    the minimum size.
+
+þreturnvalue
+
+    _ucalloc() returns a pointer to a newly allocated block of memory.
+    On error, _ucalloc() returns NULL.
+
+þseealso calloc() free() _msize() _udefault() _umalloc() _utcalloc()
+
+
+þfunction _ucreate()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam MEMORY SIZE CLEAN TYPE ALLOC_FUN RELEASE_FUN
+þprototype
+Heap_t _ucreate (void *MEMORY, size_t SIZE, int CLEAN, unsigned TYPE,
+                 void *(*ALLOC_FUN)(Heap_t, size_t *, int *),
+                 void (*RELEASE_FUN)(Heap_t, void *, size_t));
+þendprototype
+
+    _ucreate() creates a heap in the memory area pointed to by MEMORY
+    of size SIZE bytes.  SIZE must be at least _HEAP_MIN_SIZE.  CLEAN
+    should be _BLOCK_CLEAN if the memory area has been initialized to
+    zeros; CLEAN should be þtt{!_BLOCK_CLEAN} if the memory area
+    contains or may contain non-zero bytes.  TYPE specifies the type
+    of the heap: _HEAP_REGULAR (regular, not tiled) or _HEAP_TILED.
+    All memory allocated from a tiled heap will be appropriately
+    aligned (tiled) for 16-bit functions.  In addition to
+    _HEAP_REGULAR or _HEAP_TILED, TYPE may include _HEAP_SHARED (using
+    the þtt{|} operator) if MEMORY points to shared memory.  If
+    _HEAP_SHARED is set, the heap can be shared between processes.
+    The remaining two arguments are pointers to callback functions for
+    allocating and releasing additional memory objects (segments) for
+    the heap.  Any or all of these arguments may be NULL to indicate
+    that no callback function is provided.  _ucreate() returns a
+    pointer to the new heap or, on error, NULL.
+
+    Before the new heap can be used, _uopen() must be called.  To
+    destroy the heap, call _uclose() and _udestroy(), then deallocate
+    the memory area pointed to by MEMORY if appropriate.  You can use
+    the new heap as default heap by calling _udefault() or as tiled
+    default heap by calling _utdefault().
+
+    The function pointed to by ALLOC_FUN is called to allocate more
+    memory for the heap.  See þhpt{_ucreate2()} for details.  If
+    ALLOC_FUN is NULL, the size of the heap is fixed; if the initial
+    size is exhausted, allocation will fail.
+
+    The function pointed to by RELEASE_FUN is called to deallocate
+    memory memory allocated by the function pointed to by ALLOC_FUN.
+    See þhpt{_ucreate2()} for details.  If RELEASE_FUN is NULL,
+    _udestroy() and _uheapmin() won't release memory.
+
+    _ucreate2() is equivalent to _ucreate() with NULL passed for
+    þpa{EXPAND_FUN} and þpa{SHRINK_FUN}.
+
+þreturnvalue
+
+    _ucreate() returns a pointer to the new heap if successful.
+    _ucreate() returns NULL on error.
+
+þseealso sbrk() _ucreate2() _udefault() _udestroy() _uheapchk() _umalloc() _uopen() _utdefault()
+
+þsamplecode
+#define INCL_DOSMEMMGR
+#include <os2.h>
+#include <umalloc.h>
+
+Heap_t create_shared_heap (const char *name, size_t size)
+{
+  ULONG rc;
+  void *mem;
+  Heap_t h;
+
+  rc = DosAllocSharedMem (&mem, name, size,
+                          PAG_COMMIT | PAG_READ | PAG_WRITE);
+  if (rc != 0)
+    return NULL;
+  h = _ucreate (mem, size, !_BLOCK_CLEAN, _HEAP_REGULAR | _HEAP_SHARED,
+                NULL, NULL);
+  if (h == NULL)
+    DosFreeMem (mem);
+  return h;
+}
+þendsamplecode
+
+
+þfunction _ucreate2()
+þcompat emx
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam MEMORY SIZE CLEAN TYPE ALLOC_FUN RELEASE_FUN EXPAND_FUN SHRINK_FUN
+þparam H PSIZE PCLEAN BASE OLD_SIZE PNEW_SIZE
+þprototype
+Heap_t _ucreate2 (void *MEMORY, size_t SIZE, int CLEAN, unsigned TYPE,
+                  void *(*ALLOC_FUN)(Heap_t, size_t *, int *),
+                  void (*RELEASE_FUN)(Heap_t, void *, size_t),
+                  int (*EXPAND_FUN)(Heap_t, void *, size_t, size_t *, int *),
+                  void (*SHRINK_FUN)(Heap_t, void *, size_t, size_t *));
+þendprototype
+
+    _ucreate2() creates a heap in the memory area pointed to by MEMORY
+    of size SIZE bytes.  SIZE must be at least _HEAP_MIN_SIZE.  CLEAN
+    should be _BLOCK_CLEAN if the memory area has been initialized to
+    zeros; CLEAN should be þtt{!_BLOCK_CLEAN} if the memory area
+    contains or may contain non-zero bytes.  TYPE specifies the type
+    of the heap: _HEAP_REGULAR (regular, not tiled) or _HEAP_TILED.
+    All memory allocated from a tiled heap will be appropriately
+    aligned (tiled) for 16-bit functions.  In addition to
+    _HEAP_REGULAR or _HEAP_TILED, TYPE may include _HEAP_SHARED (using
+    the þtt{|} operator) if MEMORY points to shared memory.  If
+    _HEAP_SHARED is set, the heap can be shared between processes.
+    The remaining four arguments are pointers to callback functions
+    for allocating, releasing, expanding, or shrinking additional
+    memory objects (segments) for the heap.  Any or all of these
+    arguments may be NULL to indicate that no callback function is
+    provided.  _ucreate2() returns a pointer to the new heap or, on
+    error, NULL.
+
+    Before the new heap can be used, _uopen() must be called.  To
+    destroy the heap, call _uclose() and _udestroy(), then deallocate
+    the memory area pointed to by MEMORY if appropriate.  You can use
+    the new heap as default heap by calling _udefault() or as tiled
+    default heap by calling _utdefault().  You can add more memory to a
+    heap with _uaddmem().
+
+    The function pointed to by ALLOC_FUN is called to allocate more
+    memory for the heap:
+
+þindent
+    þtt{void *my_alloc (Heap_t }Hþtt{, size_t *}PSIZEþtt{, int *}PCLEANþtt{);}
+þendindent
+
+    H points to the heap to be expanded.  Note that the heap is
+    locked, so passing H to a heap-specific library function (except
+    for _uheap_type()) will cause a deadlock.  If the heap is shared,
+    the function shall allocate shared memory. The function can call
+    _uheap_type() to query the type of memory required.  PSIZE points
+    to an object containing the desired size of the memory area to be
+    allocated.  The function may allocate more memory than requested;
+    it's recommended to allocate a multiple of 65536 bytes.  The
+    function may also allocate less memory than requested; however, it
+    must not do so twice in a row.  This can be used to fill gaps
+    caused by non-contiguous memory allocation.  The function shall
+    store to the object pointed to by PSIZE the actual number of bytes
+    allocated.  Moreover, the function shall store _BLOCK_CLEAN or
+    þtt{!}_BLOCK_CLEAN to the object pointed to by PCLEAN depending on
+    whether the memory area has been initialized to zeros or not,
+    respectively.  The function shall return a pointer to the memory
+    area it has allocated or NULL if the allocation request could not
+    be satisfied.  If the function returns a pointer to a memory area
+    adjacent to (the end of) another memory area of the heap, that
+    memory area will be expanded, so that blocks spanning both memory
+    areas can be allocated.
+
+    If ALLOC_FUN is NULL, the size of the heap is fixed; if the
+    initial size is exhausted, allocation will fail.  However, you can
+    add more memory to a heap with þhpt{_uaddmem()}.
+
+    The function pointed to by RELEASE_FUN is called to deallocate
+    memory memory allocated by the function pointed to by ALLOC_FUN:
+
+þindent
+    þtt{void my_release (Heap_t }Hþtt{, void *}MEMORYþtt{, size_t }SIZEþtt{);}
+þendindent
+
+    H points to the heap for which the memory area has been allocated.
+    Note that the heap is locked, so passing H to a heap-specific
+    library function will cause a deadlock.  MEMORY points to the
+    memory area to be deallocated; the memory area has been allocated
+    by the function pointed to by ALLOC_FUN.  SIZE is the size of the
+    memory area, as reported by the function pointed to by ALLOC_FUN.
+
+    If RELEASE_FUN is NULL, _udestroy() and _uheapmin() won't release
+    memory.
+
+    The function pointed to by EXPAND_FUN is called to expand a memory
+    area of the heap:
+
+þindent
+    þtt{int my_expand (Heap_t }Hþtt{, void *}BASEþtt{, size_t }OLD_SIZEþtt{,} þbreak
+    þtt{               size_t *}PNEW_SIZEþtt{, int *}PCLEANþtt{);}
+þendindent
+
+    H points to the heap to be expanded.  Note that the heap is
+    locked, so passing H to a heap-specific library function will
+    cause a deadlock.  BASE points to the memory area to expand; it
+    points either to the initial memory area for the heap (passed as
+    MEMORY to _ucreate() or _ucreate2()) or to a memory area allocated
+    by the function pointed to by ALLOC_FUN.  The memory area
+    currently has a size of OLD_SIZE bytes (as passed as SIZE to
+    _ucreate() or _ucreate2() or as reported by the function pointed
+    to by ALLOC_FUN or EXPAND_FUN).  PNEW_SIZE points to an object
+    containing the size to which the memory area should be expanded.
+    The function may expand the memory area more than requested; it's
+    recommended to expand to a multiple of 65536 bytes.  Expanding the
+    memory area less than requested is also possible, but not
+    recommended.  The function shall store the actual new size of the
+    memory area to the object pointed to by PNEW_SIZE.  Moreover, the
+    function shall store _BLOCK_CLEAN or þtt{!}_BLOCK_CLEAN to the
+    object pointed to by PCLEAN depending on whether the additional
+    memory has been initialized to zeros or not, respectively.  The
+    function shall return a non-zero value if expansion succeeded, or
+    0 if if the expansion request could not be satisfied.
+
+    If EXPAND_FUN is NULL, _expand() and realloc() won't attempt to
+    expand the heap to expand in place the last block of a heap
+    segment.  Instead, the function pointed to by ALLOC_FUN might be
+    called to expand the heap non-contiguously.
+
+    The function pointed to by SHRINK_FUN is called to shrink a memory
+    area of the heap:
+
+þindent
+    þtt{void my_shrink (Heap_t }Hþtt{, void *}MEMORYþtt{, size_t }OLD_SIZEþtt{,} þbreak
+    þtt{                size_t *}PNEW_SIZEþtt{);}
+þendindent
+
+    H points to the heap to be shrunk.  Note that the heap is locked,
+    so passing H to a heap-specific library function will cause a
+    deadlock.  MEMORY points to the memory area to shrunk; it points
+    to a memory area allocated by the function pointed to by
+    ALLOC_FUN.  Note that the initial memory area is never shrunk
+    below its initial size.  The memory area currently has a size of
+    OLD_SIZE bytes (as reported by the function pointed to by
+    ALLOC_FUN or EXPAND_FUN).  PNEW_SIZE points to an object
+    containing the size to which the memory area should be shrunk;
+    that size might be 0.  The function may shrink the memory area
+    less than requested; it's recommended to shrink to a multiple of
+    65536 bytes.  The function shall store the actual new size of the
+    memory area to the object pointed to by PNEW_SIZE.  If the memory
+    area cannot be shrunk, the function shall store OLD_SIZE to the
+    object pointed to by PNEW_SIZE.
+
+    If SHRINK_FUN is NULL, _uheapmin() won't attempt to shrink memory
+    areas; however, it will still try to deallocate memory areas if
+    RELEASE_FUN is not NULL.
+
+þreturnvalue
+
+    _ucreate2() returns a pointer to the new heap if successful.
+    _ucreate2() returns NULL on error.
+
+þimplementation
+
+    If you need compatibility with VAC++, use _ucreate() instead of
+    _ucreate2().  Note that VAC++ does not allow ALLOC_FUN to allocate
+    less memory than requested.
+
+þhints
+
+    Memory allocated with DosAllocMem is initialized to zeros.
+
+þseealso sbrk() _ucreate() _udefault() _udestroy() _uheapchk() _uheap_type() _umalloc() _uopen() _utdefault()
+
+
+þfunction _uclose()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H
+þprototype
+int _uclose (Heap_t H);
+þendprototype
+
+    Close the heap H.  Heaps should be closed before destruction with
+    _udestroy().  Shared heaps should be closed when they are no
+    longer used; they should be closed by all processes before
+    destruction with _udestroy().  After closing a heap, all attempts
+    to access the heap will invoke undefined behavior.  _uclose()
+    fails if H is the runtime heap (_RUNTIME_HEAP) or the tiled
+    runtime heap.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso _ucreate() _ucreate2() _udestroy() _uopen()
+
+
+þfunction _udefault()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H
+þprototype
+Heap_t _udefault (Heap_t H);
+þendprototype
+
+    The _udefault() function selects the heap pointed to by H as the
+    default heap of the current thread unless H is NULL.  All
+    non-tiled memory allocation functions such as malloc() which don't
+    take a pointer to a heap will use the heap pointed to by H if
+    called in the same thread.  If H is NULL, _udefault() won't set
+    the default heap.
+
+    Initially, the runtime heap, _RUNTIME_HEAP, is used as default
+    heap for all threads.  You can make _RUNTIME_HEAP again the
+    default heap of the current thread by calling
+    þtt{_udefault(_RUNTIME_HEAP)}.
+
+þreturnvalue
+
+    _udefault() returns a pointer to the previous default heap of the
+    current thread.  If the default heap has not yet been created,
+    _udefault() will return NULL.
+
+þhints
+
+    You can use _udefault() to assign a unique heap to each thread or
+    to share the default heap between multiple processes.
+
+    To obtain a pointer to the default heap of the current thread
+    without selecting a new heap, call þtt{_udefault(NULL)}.
+
+þseealso _mheap() _ucreate() _ucreate2() _utdefault()
+
+þsamplecode
+Heap_t *my_heap, old_heap;
+
+old_heap = _udefault (my_heap);
+/*...*/
+_udefault (old_heap);   /* Restore previous default heap */
+þendsamplecode
+
+
+þfunction _udestroy()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H FORCE
+þprototype
+int _udestroy (Heap_t H, int FORCE);
+þendprototype
+
+    Destroy the heap H.  If there are any blocks of the heap in use
+    (not freed) and FORCE is þtt{!_FORCE}, _udestroy() fails.  If
+    FORCE is _FORCE, the heap will be destroyed even if there are
+    blocks in use.
+
+    The function passed to the þpa{RELEASE_FUN} argument (if not NULL)
+    of þhpt{_ucreate()} and þhpt{_ucreate2()} is called to deallocate
+    all segments added to the heap, that is, all memory assigned to
+    the heap except for the initial memory area passed to _ucreate()
+    or _ucreate2().
+
+    _udestroy() fails if H is the runtime heap (_RUNTIME_HEAP) or the
+    tiled runtime heap.  þhpt{_uclose()} should be called before
+    _udestroy().  After destroying a heap, all attempts to access the
+    heap will invoke undefined behavior.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso _uaddmem() _uclose() _ucreate() _ucreate2() _udefault() _uheapmin()
+
+
+þfunction _uflags()
+þcompat emx
+þheaders
+#include <sys/uflags.h>
+þendheaders
+
+þparam MASK NEW_BITS
+þprototype
+int _uflags (int MASK, int NEW_BITS);
+þendprototype
+
+    Set bits which control the behavior of the emx runtime library
+    (emx.dll, emx.exe, or sys.lib).  Bits set in MASK are replaced
+    with the matching bits of NEW_BITS:
+
+þexample
+bits = ((bits & ~mask) | (new_bits & mask));
+þendexample
+
+    If MASK is 0, the bits are not changed.  MASK should be one of the
+    following symbols:
+þdescription
+þitem _UF_SIG_MODEL
+    Signal processing model
+þitem _UF_SBRK_MODEL
+    Memory allocation model for sbrk()
+þitem _UF_PTRACE_MODEL
+    Debugging model for ptrace()
+þenddescription
+    If MASK includes _UF_SIG_MODEL, exactly one of the following
+    symbols should be used in NEW_BITS:
+þdescription
+þitem _UF_SIG_EMX
+    Select the emx signal processing model for signal() -- this is the
+    default setting
+þitem _UF_SIG_SYSV
+    Select the System V signal processing model for signal().  The
+    -Zsysv-signals option selects _UF_SIG_SYSV
+þitem _UF_SIG_BSD
+    Select the BSD and POSIX.1 signal processing model for signal().
+    The -Zbsd-signals option selects _UF_SIG_BSD
+þenddescription
+    If MASK includes _UF_SBRK_MODEL, exactly one of the following
+    symbols should be used in NEW_BITS:
+þdescription
+þitem _UF_SBRK_CONTIGUOUS
+    sbrk() always allocates contiguous memory; the size of the heap is
+    limited to the initial heap size.  This is the initial setting;
+    however, the malloc() implementation of emx selects
+    _UF_SBRK_ARBITRARY
+þitem _UF_SBRK_MONOTONOUS
+    sbrk() may allocate non-contiguous memory with increasing
+    addresses; up to 16 memory objects can be used for the heap
+þitem _UF_SBRK_ARBITRARY
+    sbrk() may allocate non-contiguous memory with arbitrary
+    addresses; up to 16 memory objects can be used for the heap.  The
+    malloc() implementation of emx selects _UF_SBRK_ARBITRARY
+þenddescription
+    If MASK includes _UF_PTRACE_MODEL, exactly one of the following
+    symbols should be used in NEW_BITS:
+þdescription
+þitem _UF_PTRACE_STANDARD
+    ptrace() doesn't report creation and termination of threads and
+    loading and freeing of modules (DLLs); moreover, ptrace() doesn't
+    support multiple threads.  This is the initial setting.
+þitem _UF_PTRACE_NOTIFY
+    ptrace() may report creation and termination of threads and
+    loading and freeing of modules (DLLs); ptrace() does not support
+    multiple threads.
+þitem _UF_PTRACE_MULTITHREAD
+    ptrace() may report creation and termination of threads and
+    loading and freeing of modules (DLLs); moreover, ptrace() does
+    support multiple threads; this model also modifies the return
+    values of wait() and waitpid() for processes being under control
+    of ptrace().
+þenddescription
+    To pass multiple values, use the þtt{|} operator to combine the
+    symbols.
+
+    _uflags() should not be called by application programs.
+    _UF_SBRK_MONOTONOUS and _UF_SBRK_ARBITRARY should not be selected
+    unless all callers of sbrk() know how to cope with non-contiguous
+    memory.
+
+    The -Zsysv-signals and -Zbsd-signals options of GCC add startup
+    code which calls _uflags().
+
+þreturnvalue
+
+    _uflags() returns the previous set of bits (ie, the set of bits
+    which was in effect when _uflags() was called).
+
+þrestrictions
+
+    Under DOS, memory is always contiguous, _UF_SBRK_MONOTONOUS and
+    _UF_SBRK_ARBITRARY are ignored.  _UF_SIG_SYSV and _UF_SIG_BSD are
+    not supported with the system call library sys.lib (þhpt{-Zsys}).
+    Under DOS, the _UF_PTRACE_MODEL settings are ignored.
+
+þseealso brk() sbrk() sigaction() signal() ptrace() ulimit() wait()
+
+
+þfunction _uheapchk()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H
+þprototype
+int _uheapchk (Heap_t H);
+þendprototype
+
+    _uheapchk() checks the heap pointed to by H and all its blocks for
+    consistency.  Note that _uheapchk() may crash if the heap is
+    corrupted.  _uheapchk() can help debugging programs which
+    experience heap problems.
+
+    Use _heapchk() to check the default heap and the tiled default
+    heap.
+
+þreturnvalue
+
+    _uheapchk() returns one of the following values:
+þdescription
+þitem _HEAPBADBEGIN
+    The heap is corrupted.
+þitem _HEAPBADEND
+    The heap is corrupted.
+þitem _HEAPBADNODE
+    A block of the heap is damaged or the heap is corrupted.
+þitem _HEAPEMPTY
+    The heap has not been initialized.
+þitem _HEAPOK
+    The heap seems to be consistent.
+þenddescription
+
+þseealso _heapchk() _uheapset() _uheap_walk()
+
+
+þfunction _uheapmin()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H
+þprototype
+int _uheapmin (Heap_t H);
+þendprototype
+
+    The _uheapmin() function returns unused memory of the heap H to
+    the operating system.  The heap is never made smaller than its
+    initial size.  The function passed to the þpa{RELEASE_FUN} argument
+    (if not NULL) of þhpt{_ucreate()} and þhpt{_ucreate2()} is called
+    to deallocate segments of the heap which don't contain any
+    allocated blocks.  The function pased to the þpa{SHRINK_FUN}
+    argument (if not NULL) of _ucreate2() is called to shrink segments
+    which have free space at the end (except for the initial memory
+    area passed to _ucreate2()).
+
+    You can use _heapmin() and _theapmin() to minimize the default
+    regular heap and tiled default heap, respectively.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso brk() _heapmin() _uheapchk() sbrk() _theapmin() _ucreate() _ucreate2() _ustats()
+
+
+þfunction _uheapset()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H FILL
+þprototype
+int _uheapset (Heap_t H, unsigned FILL);
+þendprototype
+
+    _uheapset() fills all bytes of all unused blocks of the heap
+    pointed to by H with FILL.  Note that _uheapset() may crash if the
+    heap is corrupted.  _uheapset() can help debugging programs which
+    erroneously depend on the contents of dynamically allocated
+    blocks.  þhpt{_uheapchk()} checks the heap more thoroughly than
+    _heapset().
+
+    Use _heapset() to fill the default heap and the tiled default
+    heap.
+
+þreturnvalue
+
+    _uheapset() returns one of the following values:
+þdescription
+þitem _HEAPBADBEGIN
+    The heap is corrupted.
+þitem _HEAPBADEND
+    The heap is corrupted.
+þitem _HEAPBADNODE
+    A block of the heap is damaged or the heap is corrupted.
+þitem _HEAPEMPTY
+    The heap has not been initialized.
+þitem _HEAPOK
+    The heap seems to be consistent.
+þenddescription
+
+þseealso _heapset() _uheapchk() _uheap_walk()
+
+
+þfunction _uheap_type()
+þcompat emx
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H
+þprototype
+unsigned _uheap_type (Heap_t H);
+þendprototype
+
+    The _uheap_type() function returns the type of the heap H, as
+    specified by the þpa{TYPE} argument of þhpt{_ucreate()} and
+    þhpt{_ucreate2()}.
+
+þreturnvalue
+
+    The _uheap_type() function returns a combination of the
+    _HEAP_REGULAR, _HEAP_TILED, and _HEAP_SHARED values.
+
+þhints
+
+    This function can be useful in allocation functions which are used
+    for different heaps.
+
+þseealso _uaddmem() _ucreate() _ucreate2()
+
+
+þfunction _uheap_walk2()
+þcompat emx
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H CALLBACK ARG
+þparam BLOCK SIZE FLAG STATUS FNAME LINENO
+þprototype
+int _uheap_walk2 (Heap_t H,
+                  int (*CALLBACK)(Heap_t, const void *, size_t, int, int,
+                                  const char *, size_t, void *),
+                  void *ARG);
+þendprototype
+
+    Apply the function pointed to by CALLBACK to all free and used
+    blocks of the heap H.  Note that the heap is locked, so using the
+    heap in the callback function will cause a deadlock.  ARG will be
+    passed on to the callback function.
+
+þindent
+    þtt{int my_walker (Heap_t }Hþtt{, const void *}BLOCKþtt{, size_t }SIZEþtt{, int }FLAGþtt{,} þbreak
+    þtt{               int }STATUSþtt{, const char *}FNAMEþtt{, size_t }LINENOþtt{,} þbreak
+    þtt{               void *}ARGþtt{);}
+þendindent
+
+    H points to the heap being examined, it's the same value as passed
+    to _uheap_walk2().  BLOCK points to a block of SIZE bytes.  FLAG
+    is either _USEDENTRY (for a used block) or _FREEENTRY (for a free
+    block).  STATUS is one of the following values, describing the
+    status of the block:
+
+þdescription
+þitem _HEAPBADBEGIN
+    The heap is corrupted.
+þitem _HEAPBADEND
+    The heap is corrupted.
+þitem _HEAPBADNODE
+    The block is damaged.
+þitem _HEAPEMPTY
+    The heap has not been initialized.
+þitem _HEAPOK
+    The heap seems to be consistent (_HEAPOK is 0).
+þenddescription
+
+    FNAME points to the file name of the source file in which the
+    block has been allocated.  LINENO is the line number in which the
+    block has been allocated.  FNAME is NULL if that information is
+    not available, that is, if the object has not been allocated with
+    a debugging heap function.  ARG is the same value as passed to
+    _uheap_walk2().
+
+
+þreturnvalue
+
+    _uheap_walk2() returns the last status (see above for a list of
+    values) unless the callback function returned a non-zero value.
+    If the callback function returned a non-zero value, _uheap_walk2()
+    returns that value.
+
+þrestrictions
+
+    FNAME is current always NULL as there are no debugging heap
+    functions.
+
+þimplementation
+
+    If you need compatibility with VAC++, use _uheap_walk() instead of
+    _uheap_walk2().
+
+þhints
+
+    Use an extra heap if you want to allocate memory in the callback
+    function.
+
+þseealso _heap_walk() _uheap_walk()
+
+
+þfunction ulimit()
+þcompat UNIX
+þheaders
+#include <ulimit.h>
+þendheaders
+
+þparam REQUEST
+þprototype
+long ulimit (int REQUEST, ...);
+þendprototype
+
+    Get or set process limits.  The following REQUEST codes are
+    implemented:
+
+þdescription
+þitem UL_GFILLIM
+
+    Return the maximum file size.  Always returns þtt{1 << 21}.
+
+þitem UL_SFILLIM
+
+    Set the maximum file size according to the second argument which
+    is of type þtt{int}.  Ignored.  Returns the second argument.
+
+þitem UL_GMEMLIM
+
+    Return the greatest possible break value.
+
+þitem UL_NOFILES
+
+    Return the number of files that can be open simultaneously per
+    process.  Always returns 40.
+
+þitem UL_OBJREST
+
+    Return the number of bytes remaining in the current heap object.
+    Let þpa{N} be the return value of þtt{ulimit(UL_OBJREST)}.  If
+    allocation of non-contiguous memory is disabled, up to þpa{N}
+    bytes can be allocated with brk() or sbrk().  Attempts to allocate
+    more than þpa{N} bytes will fail.  If allocation of
+    non-contiguous memory has been enabled with _uflags(), requests
+    for up to þpa{N} bytes will yield contiguous memory; calling
+    sbrk() with an argument greater than þpa{N} will create a new heap
+    object, leaving a gap between the previous heap object and the new
+    one.
+
+þenddescription
+
+þreturnvalue
+
+    See above.
+
+þimplementation
+
+    UL_GFILLIM and UL_NOFILES return dummy values.  UL_SFILLIM is
+    ignored.  UL_OBJREST is an emx extension.
+
+þseealso brk() sbrk() _uflags()
+
+
+þfunction _umalloc()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H SIZE
+þprototype
+void *_umalloc (Heap_t H, size_t SIZE);
+þendprototype
+
+    Allocate from the heap H a block of memory big enough for holding
+    SIZE bytes.  If there is an error, _umalloc() returns NULL.  If
+    SIZE is 0, zero bytes of memory are allocated, the return value
+    will be unequal NULL.
+
+þreturnvalue
+
+    _umalloc() returns a pointer to a newly allocated block of memory.
+    On error, _umalloc() returns NULL.
+
+þimplementation
+
+    þtt{_umalloc(0)} returns a non-NULL pointer if there's enough
+    space left in the heap for a block of the minimum size.
+
+þseealso free() malloc() _msize() realloc() _ucalloc() _utmalloc()
+
+
+þfunction umask()
+þcompat UNIX
+þheaders
+#include <io.h>
+þendheaders
+
+þparam PMODE
+þprototype
+int umask (int PMODE);
+þendprototype
+
+    Set the file-permission mask of the current process to PMODE.
+    Only the S_IWRITE bit is used.  Either specify
+    þtt{S_IREAD|S_IWRITE} or þtt{S_IREAD} for PMODE.
+
+þreturnvalue
+
+    umask() returns the previous file-permission mask.
+
+þrestrictions
+
+    The current file-permission mask is inherited by emx programs
+    spawned under DOS.  Under OS/2, the file-permission mask is not
+    yet inherited.  When spawning a non-emx program (such as
+    command.com, see þhpt{system()}) which spawns an emx program, that
+    program won't inherit the file-permission mask.
+
+þseealso fopen() open()
+
+
+þfunction uname()
+þcompat UNIX
+þheaders
+#include <sys/utsname.h>
+þendheaders
+
+þparam NAME
+þprototype
+int uname (struct utsname *NAME);
+þendprototype
+
+    Store information identifying the current system to the structure
+    pointed to by NAME.
+
+þreturnvalue
+
+    uname() always returns 0 (always successful).
+
+þfunction ungetc()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam C STREAM
+þprototype
+int ungetc (int C, FILE *STREAM);
+þendprototype
+
+    Push back the character C onto STREAM and clear the end-of-file
+    indicator.  STREAM must be open for reading.  The next read
+    operation on STREAM starts with C.  If C is EOF, nothing is done.
+    Only one character can be pushed onto a stream.  fflush(),
+    fseek(), fsetpos() and rewind() undo ungetc().  After a successful
+    ungetc(), the value of the file pointer is undefined until the
+    character has been read.
+
+þreturnvalue
+
+    On success, ungetc() returns the character C.  On failure,
+    ungetc() returns EOF.
+
+þseealso fgetc() fflush()
+
+
+þfunction unlink()
+þcompat UNIX
+
+þheaders
+#include <unistd.h>     /* use this */
+#include <io.h>         /* or this */
+þendheaders
+
+þparam NAME
+þprototype
+int unlink (const char *NAME);
+þendprototype
+
+    Delete a file.  NAME is a pointer to a string containing the name
+    of the file to be deleted.  Under OS/2 and DOS, unlink() and
+    remove() are equivalent.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þimplementation
+
+    If the read-only attribute of the file is set, unlink() sets errno
+    to EPERM and returns -1.
+
+    If the file is open in any process, unlink() sets errno to EACCES
+    and returns -1.
+
+þseealso remove()
+
+
+þfunction _uopen()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H
+þprototype
+int _uopen (Heap_t H);
+þendprototype
+
+    Open the heap H.  Before a heap created with _ucreate() or
+    _ucreate2() can be used, it must be opened.  A shared heap must be
+    opened by all processes which want to access the heap.  All
+    attempts to access a heap before it has been opened will invoke
+    undefined behavior.
+
+    _uopen() fails if H is the runtime heap (_RUNTIME_HEAP) or the
+    tiled runtime heap.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso _uclose() _ucreate() _ucreate2()
+
+
+þfunction _ustats()
+þcompat VAC++
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H PSTATS
+þprototype
+int _ustats (Heap_t H, _HEAPSTATS *PSTATS);
+þendprototype
+
+    _ustats() computes statistics on the heap pointed to by H and fills
+    in the structure pointed to by PSTATS.  The structure has the
+    following members:
+
+þdescription
+þitem þtt{_provided}
+    Total number of bytes provided by the heap, including used and
+    free blocks, excluding overhead for control structures
+þitem þtt{_used}
+    Total number of bytes in used blocks
+þitem þtt{_tiled}
+    1 if the heap is tiled (_HEAP_TILED), 0 if the heap is not tiled
+þitem þtt{_shared}
+    1 if the heap is shared (_HEAP_SHARED), 0 if the heap is not shared
+þitem þtt{_max_free}
+    Number of bytes in the biggest free block
+þitem þtt{_segments}
+    Number of segments
+þitem þtt{_crates}
+    Number of blocks allocated internally for allocation of small user
+    blocks
+þenddescription
+
+þreturnvalue
+
+    _ustats() returns 0 if successful.  _ustats() returns a non-zero
+    value on error.
+
+þimplementation
+
+    The þtt{_segments} and þtt{_crates} members are an emx extension.
+
+þhints
+
+    Use þhpt{_udefault()} to obtain a pointer to the default heap if
+    you want to apply _ustats() to the default heap.
+
+þseealso _uaddmem() _udefault() _uheapmin() _uheap_walk()
+
+
+þfunction _utcalloc()
+þcompat emx
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H ELEMENTS SIZE
+þprototype
+void *_utcalloc (Heap_t H, size_t ELEMENTS, size_t SIZE);
+þendprototype
+
+    Allocate from the heap pointed to by H a block of memory big
+    enough for holding ELEMENTS elements of SIZE bytes each.  The
+    block will not cross a 64 KByte boundary unless SIZE is greater
+    than 65536.  If SIZE is greater than 65536, the block will be
+    aligned on a 64 KByte boundary.  _utcalloc() fills the block with
+    zeros.  If there is an error, _utcalloc() returns NULL.
+
+þreturnvalue
+
+    _utcalloc() returns a pointer to a newly allocated block of
+    memory.  On error, _utcalloc() returns NULL.
+
+þseealso calloc() free() realloc() _tcalloc() _utmalloc()
+
+
+þfunction _utdefault()
+þcompat emx
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H
+þprototype
+Heap_t _utdefault (Heap_t H);
+þendprototype
+
+    The _utdefault() function selects the heap pointed to by H as the
+    tiled default heap of the current thread unless H is NULL.  All
+    tiled memory allocation functions such as _tmalloc() which don't
+    take a pointer to a heap will use the heap pointed to by H if
+    called in the same thread.  If H is NULL, _utdefault() won't set
+    the tiled default heap.
+
+    Initially, the tiled runtime heap is used as tiled default heap
+    for all threads.
+
+þreturnvalue
+
+    _utdefault() returns a pointer to the previous tiled default heap
+    of the current thread.  If the tiled default heap has not yet been
+    created, _utdefault() will return NULL.
+
+þhints
+
+    To obtain a pointer to the tiled default heap of the current
+    thread without selecting a new heap, call þtt{_utdefault(NULL)}.
+
+þseealso _mheap() _ucreate() _ucreate2() _udefault()
+
+
+þfunction utime()
+þcompat SysV
+þheaders
+#include <utime.h>
+þendheaders
+
+þparam NAME TIMES
+þprototype
+int utime (const char *NAME, const struct utimbuf *TIMES);
+þendprototype
+
+    Set the time stamp of a file to the access time and modification
+    time in the structure pointed to by TIMES.  NAME points to a
+    string containing the name of the file.  If TIMES is NULL, both
+    the access time and the modification time are set to the current
+    time.
+
+    The þtt{utimbuf} structure is defined as follows:
+
+þexample
+struct utimbuf
+{
+  time_t actime;
+  time_t modtime;
+};
+þendexample
+
+    þtt{actime} is the time of the last access, þtt{modtime} is the
+    time of the last modification.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso stat() utimes()
+
+
+þfunction utimes()
+þcompat BSD
+þheaders
+#include <sys/time.h>
+þendheaders
+
+þparam NAME TVP
+þprototype
+int utimes (const char *NAME, const struct timeval *TVP);
+þendprototype
+
+    Set the time stamp of a file to the access time in
+    þpa{TVP}þtt{[0]} and the modification time in þpa{TVP}þtt{[1]}.
+    NAME points to a string containing the file name.  If TVP is NULL,
+    both the access time and the modification time are set to the
+    current time.
+
+    The þtt{timeval} structure is defined as follows:
+
+þexample
+struct timeval
+{
+  long tv_sec;
+  long tv_usec;
+};
+þendexample
+
+    þtt{tv_sec} and þtt{tv_usec} are the number of seconds and
+    microseconds, respectively, elapsed since 00:00:00 1-Jan-1970 UTC.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+þseealso stat() utime()
+
+
+þfunction _utmalloc()
+þcompat emx
+þheaders
+#include <umalloc.h>
+þendheaders
+
+þparam H SIZE
+þprototype
+void *_utmalloc (Heap_t H, size_t SIZE);
+þendprototype
+
+    Allocate from the heap pointed to by H a block of memory big
+    enough for holding SIZE bytes.  The block will not cross a 64
+    KByte boundary unless SIZE is greater than 65536.  If SIZE is
+    greater than 65536, the block will be aligned on a 64 KByte
+    boundary.  Therefore, blocks allocated with _utmalloc() can be
+    used with 16-bit functions.  If there is an error, _utmalloc()
+    returns NULL.  If SIZE is 0, zero bytes of memory are allocated,
+    the return value will be unequal NULL.  Use free() to deallocate a
+    block of memory allocated by _utmalloc().
+
+    As _utmalloc() causes additional heap fragmentation, you should
+    not use _utmalloc() unless you need an aligned block.
+
+þreturnvalue
+
+    _utmalloc() returns a pointer to a newly allocated block of
+    memory.  On error, _utmalloc() returns NULL.
+
+þseealso free() realloc() _tmalloc() _umalloc() _utcalloc()
+
+
+þfunction v_attrib()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam A
+þprototype
+void v_attrib (int A);
+þendprototype
+
+    Set the attributes (colors etc.) used by video library functions
+    to A.  You can make A by using the binary OR operator and the
+    þtt{F_}þsl{whatever}, þtt{B_}þsl{whatever}, INTENSITY and BLINK
+    constants.
+
+þseealso v_init() v_putc()
+
+
+þfunction v_backsp()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam COUNT
+þprototype
+void v_backsp (int COUNT);
+þendprototype
+
+    Backspace the cursor.  The cursor is moved left by COUNT
+    characters.  If the cursor leaves the screen at the left edge, it
+    is moved to the end of the previous line.  The cursor cannot leave
+    the screen at the top edge.
+
+þseealso v_putc()
+
+
+þfunction v_clear()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þprototype
+void v_clear (void);
+þendprototype
+
+    Clear the screen using the current attributes.
+
+þseealso v_attrib() v_clreol()
+
+
+þfunction v_clreol()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þprototype
+void v_clreol (void);
+þendprototype
+
+    Clear the line from the current cursor position to the end of the
+    current line using the current attributes.
+
+þseealso v_attrib() v_clear()
+
+
+þfunction v_ctype()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam START END
+þprototype
+void v_ctype (int START, int END);
+þendprototype
+
+    Set the cursor type.  START is the first row of the cursor, END is
+    the last row of the cursor.  Both values are zero-based. Use
+    v_hardware() to determine the size of the character box.
+
+    Note that cmd.exe resets the cursor type.
+
+þseealso v_getctype() v_hardware() v_hidecursor()
+
+
+þfunction v_delline()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam COUNT
+þprototype
+void v_delline (int COUNT);
+þendprototype
+
+    Delete COUNT lines at the current cursor position by moving up the
+    lines below the current line.  The current attributes are used for
+    filling lines becoming empty at the bottom of the screen.
+
+þseealso v_attrib() v_insline() v_scroll()
+
+
+þfunction v_dimen()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam WIDTH HEIGHT
+þprototype
+void v_dimen (int *WIDTH, int *HEIGHT);
+þendprototype
+
+    Store the screen width (columns) to WIDTH, the screen height
+    (lines) to HEIGHT.
+
+þseealso _scrsize()
+
+
+þfunction v_fclose()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/video.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int v_fclose (FILE *STREAM);
+þendprototype
+
+    Close a video file created by v_fopen().
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+þseealso v_fopen()
+
+
+þfunction v_fopen()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/video.h>
+þendheaders
+
+þprototype
+FILE *v_fopen (void);
+þendprototype
+
+    Open a video file.  All output to a video file goes to the screen,
+    using video library functions such as v_puts().  The stream
+    returned by v_fopen() can be used with fprintf(), fputc() and
+    fwrite().  On error, v_fopen() returns NULL.  Do not use fclose()
+    on a stream created by v_fopen(), use v_fclose() instead.  Do not
+    read from a stream created by v_fopen().
+
+þreturnvalue
+
+    See above.
+
+þseealso _fassign() fopen() v_fclose() v_printf()
+
+þsamplefile /emx/test/vftest.c
+
+
+þfunction v_getattr()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þprototype
+int v_getattr (void);
+þendprototype
+
+    Return the current attributes.
+
+þreturnvalue
+
+    See above.
+
+þseealso v_attrib()
+
+
+þfunction v_getctype()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam START END
+þprototype
+void v_getctype (int *START, int *END);
+þendprototype
+
+    Store the current cursor start and end rows to START and END.
+
+þseealso v_ctype()
+
+
+þfunction v_getline()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam DST X Y COUNT
+þprototype
+void v_getline (char *DST, int X, int Y, int COUNT);
+þendprototype
+
+    Copy COUNT character/attributes pairs from the screen at position
+    (X,Y) to the array pointed to by DST.  2*þpa{COUNT} bytes are
+    copied.  The cursor is not moved.
+
+þseealso v_putline()
+
+
+þfunction v_getxy()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam X Y
+þprototype
+void v_getxy (int *X, int *Y);
+þendprototype
+
+    Store the current cursor position to X (column) and Y (line).
+
+þseealso v_gotoxy()
+
+
+þfunction v_gotoxy()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam X Y
+þprototype
+void v_gotoxy (int X, int Y);
+þendprototype
+
+    Move the cursor to line Y, column X.  Both values are zero-based.
+    Line 0 is the top line, column 0 is the left-most column.
+
+þseealso v_getxy()
+
+
+þfunction v_hardware()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þprototype
+int v_hardware (void);
+þendprototype
+
+    Get the display adapter type.
+
+þreturnvalue
+
+þdescription
+
+þitem V_MONOCHROME
+
+    Monochrome display adapter
+
+þitem V_COLOR_8
+
+    Color display adapter, the character box height is 8 scan lines
+
+þitem V_COLOR_12
+
+    Color display adapter, the character box height is 12 scan lines
+
+þenddescription
+
+þseealso v_ctype()
+
+
+þfunction v_hidecursor()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þprototype
+void v_hidecursor (void);
+þendprototype
+
+    Turn off the cursor.  Use v_ctype() to turn the cursor on.
+
+þseealso v_ctype()
+
+
+þfunction v_init()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þprototype
+int v_init (void);
+þendprototype
+
+    Initialize video library.  You must call this function before
+    calling any other video library function.  The attributes are set
+    to þtt{F_WHITE|B_BLACK}.
+
+    General information about the video library: The video library
+    implements text-mode output to the screen.  You have to link with
+    -lvideo.  Under DOS, emx option -acm is required, see `þhpt{Using
+    emx options}'.  See þhpt{wm_init()} for a higher-level interface.
+
+þreturnvalue
+
+    v_init() always returns 1.
+
+þseealso v_attrib()
+
+þsamplefile /emx/test/video.c
+
+
+þfunction v_insline()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam COUNT
+þprototype
+void v_insline (int COUNT);
+þendprototype
+
+    Insert COUNT empty lines at the current cursor position by moving
+    down the line at the current cursor position and all lines below
+    that line.  The current attributes are used for filling the empty
+    lines.
+
+þseealso v_attrib() v_delline() v_scroll()
+
+
+þfunction v_printf()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam FMT
+þprototype
+int v_printf (const char *FMT, ...);
+þendprototype
+
+    Formatted output to the screen at the current cursor position.
+    The cursor is moved.  See þhpt{printf()} for details on the format
+    string pointed to by FMT.
+
+þreturnvalue
+
+    v_printf() returns the number of output characters.
+
+þseealso v_attrib() v_fopen() v_putc() v_puts() v_vprintf()
+
+
+þfunction v_putc()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam C
+þprototype
+void v_putc (char C);
+þendprototype
+
+    Display character C on the screen at the current cursor position,
+    using the current attributes.  The cursor is moved.  If the cursor
+    leaves the screen at the right edge, it will be moved to the start
+    of the next line.  If C is þtt{'\n'}, the cursor is moved to the
+    start of the next line.  If the cursor leaves the screen at the
+    bottom edge, the screen is scrolled up.
+
+þseealso v_attrib() v_puts() v_scrollup()
+
+
+þfunction v_putline()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam SRC X Y COUNT
+þprototype
+void v_putline (const char *SRC, int X, int Y, int COUNT);
+þendprototype
+
+    Copy COUNT character/attributes pairs from the array pointed to by
+    SRC to the screen at position (X,Y).  2*þpa{COUNT} bytes are
+    copied.  The cursor is not moved.
+
+þseealso v_getline() v_putmask() v_putn()
+
+
+þfunction v_putm()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam STR LEN
+þprototype
+void v_putm (const char *STR, int LEN);
+þendprototype
+
+    Display LEN characters of the string pointed to by STR at the
+    current cursor position using the current attributes.  The cursor
+    is not moved.
+
+þseealso v_putline() v_putn() v_puts()
+
+
+þfunction v_putmask()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam SRC MASK X Y COUNT
+þprototype
+void v_putmask (const char *SRC, const char *MASK, int X, int Y, int COUNT);
+þendprototype
+
+    Copy COUNT character/attributes pairs from the array pointed to by
+    SRC to the screen.  A character/attributes pair at
+    þpa{SRC}þtt{[2*i]} and þpa{SRC}þtt{[2*i+1]}, is copied only if
+    þpa{MASK}þtt{[i]} is non-zero.  The cursor is not moved.
+
+þseealso v_putline()
+
+
+þfunction v_putn()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam C COUNT
+þprototype
+void v_putn (char C, int COUNT);
+þendprototype
+
+    Display character C at the current cursor position using the
+    current attributes.  COUNT is the number of times to display the
+    character.  The cursor is not moved.
+
+þseealso v_attrib() v_putc()
+
+
+þfunction v_puts()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam STR
+þprototype
+void v_puts (const char *STR);
+þendprototype
+
+    Display the string pointed to by STR at the current cursor
+    position using the current attributes.  The þtt{'\n'} character
+    moves the cursor to the start of the next line.  Scrolling is
+    performed when the cursor leaves the screen at the bottom edge.
+
+þseealso v_attrib() v_printf() v_putc() v_putm()
+
+
+þfunction v_scroll()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam TL_X TL_Y BR_X BR_Y COUNT FLAG
+þprototype
+void v_scroll (int TL_X, int TL_Y, int BR_X, int BR_Y, int COUNT, int FLAG);
+þendprototype
+
+    Scroll a rectangle of the screen by COUNT lines.  The top left
+    character cell is at (TL_X,TL_Y), the bottom right character cell
+    is at (BR_X,BR_Y).  If FLAG is V_SCROLL_UP, the rectangle is
+    scrolled up, if FLAG is V_SCROLL_DOWN, the rectangle is scrolled
+    down.  If FLAG is V_SCROLL_CLEAR, the rectangle is filled with
+    blanks.  Lines becoming empty are filled with blanks using the
+    current attributes.
+
+þseealso v_attrib() v_scrollup()
+
+
+þfunction v_scrollup()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þprototype
+void v_scrollup (void);
+þendprototype
+
+    Scroll screen up by one line.  The bottom line is filled with
+    blanks, using the current attributes.
+
+þseealso v_attrib() v_putc()
+
+
+þfunction v_vprintf()
+þcompat emx
+þheaders
+#include <sys/video.h>
+þendheaders
+
+þparam FMT ARG_PTR
+þprototype
+int v_vprintf (const char *FMT, va_list ARG_PTR);
+þendprototype
+
+    Formatted output to the screen.  Instead of a list of arguments,
+    this function takes a pointer to the list of arguments.  See
+    v_printf() for details.
+
+þreturnvalue
+
+    v_vprintf() returns the number of output characters.
+
+þseealso v_printf() va_arg()
+
+
+þfunction va_arg() va_end() va_start()
+þcompat C90
+þheaders
+#include <stdarg.h>
+þendheaders
+
+þparam ARG_PTR TYPE PREV_ARG
+þprototype
+type va_arg (va_list ARG_PTR, TYPE);
+void va_end (va_list ARG_PTR);
+void va_start (va_list ARG_PTR, TYPE PREV_ARG);
+þendprototype
+
+    Access arguments of a function with variable number of arguments.
+    You have to declare a variable of type va_list, for instance
+    ARG_PTR.  Use
+
+þtypewriter
+  va_start (ARG_PTR, PREV_ARG)
+þendtypewriter
+
+    where PREV_ARG is the argument preceding the variable arguments,
+    to initialize ARG_PTR.  Use
+
+þtypewriter
+  va_arg (ARG_PTR, TYPE)
+þendtypewriter
+
+    to get the next argument, which is of type TYPE.  Use
+
+þtypewriter
+  va_end (ARG_PTR)
+þendtypewriter
+
+    when you no longer need ARG_PTR.
+
+þreturnvalue
+
+    See above.
+
+þrestrictions
+
+    PREV_ARG must not be declared þtt{register}, must not be of
+    function or array type, and the type must be compatible to the
+    type that results from promotion.  For instance, PREV_ARG must not
+    be of type þtt{char} or þtt{float}.
+
+    TYPE must be compatible to the type that results from promotion.
+    For instance, TYPE must not be þtt{unsigned char} or þtt{float}
+    (instead, use þtt{unsigned int} and þtt{double}, respectively).
+
+þseealso vprintf()
+
+þsamplefile /emx/samples/stdarg.c
+
+
+þfunction vprintf() vfprintf() vsprintf()
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam FORMAT ARG_PTR STREAM BUFFER
+þprototype
+int vprintf (const char *FORMAT, va_list ARG_PTR);
+int vfprintf (FILE *STREAM, const char *FORMAT, va_list ARG_PTR);
+int vsprintf (char *BUFFER, const char *FORMAT, va_list ARG_PTR);
+þendprototype
+
+    Formatted output to stdout, to the stream STREAM or to the string
+    pointed to by BUFFER, respectively.  Instead of a list of
+    arguments, these functions take a pointer to the list of
+    arguments.  See þhpt{printf()} for details.
+
+þreturnvalue
+
+    vprintf(), vfprintf() and vsprintf() return the number of
+    output characters.  On error, these functions return EOF.
+
+þseealso printf() va_arg() vsnprintf()
+
+
+þfunction vscanf() vfscanf() vsscanf()
+þcompat emx
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam FORMAT ARG_PTR STREAM BUFFER
+þprototype
+int vscanf (const char *FORMAT, va_list ARG_PTR);
+int vfscanf (FILE *STREAM, const char *FORMAT, va_list ARG_PTR);
+int vsscanf (const char *BUFFER, const char *FORMAT, va_list ARG_PTR);
+þendprototype
+
+    Parse input from stdin, STREAM or the string pointed to by BUFFER,
+    respectively.  Instead of a list of arguments, these functions
+    take a pointer to the list of arguments.  See þhpt{scanf()} for
+    details.
+
+þreturnvalue
+
+    If successful, vscanf(), vfscanf() and vsscanf() return the number
+    of fields converted.  On error, these functions return EOF.
+
+þseealso scanf() va_arg()
+
+
+þfunction vsnprintf()
+þcompat BSD
+þheaders
+#include <stdio.h>
+þendheaders
+
+þparam BUFFER N FORMAT ARG_PTR
+þprototype
+int vsnprintf (char *BUFFER, size_t N, const char *FORMAT, va_list ARG_PTR);
+þendprototype
+
+    Formatted output to the string pointed to by BUFFER.  If N is
+    zero, BUFFER may be NULL and nothing is written.  Otherwise, up to
+    þpa{N}-1 characters and a terminating null character will be
+    written to BUFFER.  If formatting yields more than þpa{N}-1
+    characters, output will be truncated.  The terminating null
+    character will be put into BUFFER even if output is truncated.
+
+    Instead of a list of arguments, this function takes a pointer to
+    the list of arguments.  See þhpt{printf()} for details.
+
+þreturnvalue
+
+    On success, vsnprintf() returns the number of characters
+    (excluding the terminating null character) that would have been
+    written to BUFFER if N had been sufficiently large.  That is,
+    output is truncated iff the returned value is greater than or
+    equal to N.  On error, vsnprintf() returns EOF.
+
+þseealso printf() snprintf() va_arg() vsprintf()
+
+
+þfunction wait()
+þcompat POSIX.1
+
+þheaders
+#include <sys/types.h>
+#include <sys/wait.h>
+þendheaders
+
+þparam STAT_LOC STAT_VAL
+þprototype
+int wait (int *STAT_LOC);
+þendprototype
+
+    Obtain status information about a child process.  wait() suspends
+    the process until status information for a child process is
+    available or until a signal occurs.
+
+    If status information is available, wait() returns immediately.
+    This happens if a child process terminated before wait() is
+    called, or if status information about a debuggee is available,
+    that is, after calling ptrace() with requests PTRACE_RESUME or
+    PTRACE_STEP.
+
+    If there are no child processes, wait() returns immediately,
+    setting errno to ECHILD and returning -1.  If STAT_LOC is not
+    NULL, the return code and the termination status are stored to the
+    location pointed to by STAT_LOC.
+
+    You can use the following macros for determining the type of
+    status (STAT_VAL is the value pointed to by STAT_LOC):
+
+þlist
+þitem þtt{WIFEXITED (}STAT_VALþtt{)}
+
+    This macro returns a non-zero value if the process for which
+    STAT_VAL was returned terminated normally.
+
+þitem þtt{WIFSIGNALED (}STAT_VALþtt{)}
+
+    This macro returns a non-zero value if the process for which
+    STAT_VAL was returned terminated due to a signal which was not
+    caught.
+
+þitem þtt{WIFSTOPPED (}STAT_VALþtt{)}
+
+    This macro returns a non-zero value if the process for which
+    STAT_VAL was returned is stopped.  This occurs only if the child
+    process is being debugged.
+
+þendlist
+
+    Depending on the type of status indicated by the above macros, you
+    can use exactly one of the following macro to obtain additional
+    information:
+
+þlist
+þitem þtt{WEXITSTATUS (}STAT_VALþtt{)}
+
+    If þtt{WIFEXITED(}STAT_VALþtt{)} is non-zero, this macro returns
+    the return code of the child process (passed to exit(), _exit(),
+    or returned from main()).
+
+þitem þtt{WTERMSIG (}STAT_VALþtt{)}
+
+    If þtt{WIFSIGNALED(}STAT_VALþtt{)} is non-zero, this macro returns
+    the number of the signal by which the child process was terminated.
+
+þitem þtt{WSTOPSIG (}STAT_VALþtt{)}
+
+    If þtt{WIFSTOPPED(}STAT_VALþtt{)} is non-zero, this macro returns
+    the number of the signal by which the child process was stopped.
+
+þendlist
+
+
+þreturnvalue
+
+    wait() returns the process ID of the child process.  If
+    _UF_PTRACE_MULTITHREAD has been set with _uflags(), the return value
+    of wait() contains both the thread ID and the process ID; use the
+    PTRACE_GETPID and PTRACE_GETTID macros of <sys/ptrace.h> to
+    extract the process ID and the thread ID.  If an error occurs,
+    wait() sets errno and returns -1.
+
+þrestrictions
+
+    Under DOS, wait() is currently implemented only for processes
+    being debugged and for synchronous processes started with
+    P_NOWAIT; see þhpt{ptrace()} and þhpt{spawn*()}.  Under DOS, the
+    termination status of only one process is kept for wait().  If you
+    run another process before calling wait(), the termination status
+    will be overwritten.
+
+    Under OS/2, wait() works only for processes started with spawn*()
+    or þhpt{exec*()}.  It does not work for processes started with
+    DosExecPgm or DosStartSession.  If the processes found by wait()
+    has been started as a session, only the return code is available,
+    not the signal number.
+
+    wait() is interrupted by signals which are ignored (SIG_IGN) and
+    by signals which are blocked.
+
+þseealso exit() fork() main() ptrace() sigaction() signal() sigprocmask() spawn*() _uflags() waitpid()
+
+þsamplecode
+int tc, pid;
+
+pid = wait (&tc);
+if (pid >= 0)
+  {
+    if (WIFEXITED (tc))
+      printf ("Normal process termination, rc=%d\n", WEXITSTATUS (tc));
+    else if (WIFSIGNALED (tc))
+      printf ("Process terminated by signal %d\n", WTERMSIG (tc));
+    else
+      printf ("Process stopped by signal %d\n", WSTOPSIG (tc));
+  }
+þendsamplecode
+
+
+þfunction _wait0() _wait1() _wait01() _wait10()
+þcompat emx *
+þheaders
+#include <sys/hw.h>
+þendheaders
+
+þparam PORT MASK
+þprototype
+void _wait0 (unsigned PORT, unsigned MASK);
+void _wait1 (unsigned PORT, unsigned MASK);
+void _wait01 (unsigned PORT, unsigned MASK);
+void _wait10 (unsigned PORT, unsigned MASK);
+þendprototype
+
+    The _wait0() and _wait1() functions wait for the bit indicated by
+    MASK of the 8-bit hardware port PORT being 0 or 1, respectively.
+
+    The _wait01() and _wait10() functions wait for a 0->1 or 1->0
+    transition, respectively, of the bit indicated by MASK of the
+    8-bit hardware port PORT.
+
+    If there are multiple bits set in MASK, 0 means all bits
+    cleared, 1 means at least one bit set.
+
+    You have to call _portaccess() first to enable access to a range
+    of ports.  To make your program work under DOS, you have to use
+    emx option -ai, see `þhpt{Using emx options}'.  Under OS/2, your
+    program requires emxio.dll in a directory listed in LIBPATH.
+
+    Note that these functions eat a lot of CPU time.
+
+þseealso _portaccess() _inp8()
+
+
+þfunction waitpid()
+þcompat POSIX.1
+þheaders
+#include <sys/types.h>
+#include <sys/wait.h>
+þendheaders
+
+þparam PID STAT_LOC OPTIONS
+þprototype
+int waitpid (int PID, int *STAT_LOC, int OPTIONS);
+þendprototype
+
+    Wait until status information for the child process PID is
+    available or until a signal occurs.  If PID is -1, waitpid() waits
+    for any child process, as does wait().  If there is no child
+    process with process ID PID (or if PID is -1 and there is no child
+    process), errno is set to ESRCH and -1 is returned.  On success,
+    the process ID is returned.  If STAT_LOC is not NULL, the return
+    code and the termination status are stored to the location pointed
+    to by STAT_LOC, see þhpt{wait()} for details.
+
+    OPTIONS is the bitwise OR of zero or more of the following flags:
+
+þdescription
+
+þitem WNOHANG
+
+    Don't wait if no status information is currently available.  If
+    WNOHANG is set, and there are any child processes matching PID,
+    and no status available for any child process matching PID, 0 is
+    returned.
+
+þitem WUNTRACED
+
+    Not implemented.
+
+þenddescription
+
+þreturnvalue
+þdescription
+þitem -1
+    error or interrupted (errno set to ECHILD, EINVAL, or EINTR)
+þitem >0
+    process ID.  If _UF_PTRACE_MULTITHREAD has been set with _uflags(),
+    the return value of waitpid() contains both the thread ID and the
+    process ID; use the PTRACE_GETPID and PTRACE_GETTID macros of
+    <sys/ptrace.h> to extract the process ID and the thread ID
+þitem 0
+    WNOHANG is set in OPTIONS, and there are child processes matching
+    PID, and no status available for any child process matching PID
+þenddescription
+
+þrestrictions
+
+    waitpid() is not implemented for negative values of PID.
+    WUNTRACED in OPTIONS is ignored.  waitpid() is not implemented
+    under DOS.  waitpid() is interrupted by signals which are ignored
+    (SIG_IGN) and by signals which are blocked.
+
+þseealso fork() ptrace() sigaction() signal() sigprocmask() spawn*() _uflags() wait()
+
+
+þfunction _wildcard()
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam ARGCP ARGVP
+þprototype
+void _wildcard (int *ARGCP, char ***ARGVP);
+þendprototype
+
+    Expand wildcards.  If you want wildcards on the command line to be
+    expanded, call
+
+þexample
+_wildcard (&argc, &argv);
+þendexample
+
+    at the beginning of main().  Wildcard arguments enclosed in double
+    quotes won't be expanded.  If the expansion of a wildcard argument
+    is empty, the wildcard argument is kept unchanged.  Directories
+    are included in the expansion.  Hidden and system files are
+    omitted.
+
+    _fnlwr() is used to convert file names to lower case on
+    upper-case-only file systems.
+
+    _wildcard() properly handles DBCS characters.
+
+þseealso _envargs() _fnexplode() main() _nls_init() _response()
+
+
+þfunction wcstombs()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam S PWCS N
+þprototype
+size_t wcstombs (char *S, const wchar_t *PWCS, size_t N);
+þendprototype
+
+    Convert the zero-terminated sequence of wchar_t codes at PWCS to a
+    multibyte character sequence beginning at S.  The multibyte
+    character sequence starts in the initial shift state.  At most N
+    bytes are stored.  S will be terminated with a null character if N
+    is big enough.
+
+    The shift state of wctomb() is not affected.
+
+þreturnvalue
+
+    wcstombs() returns the number of bytes stored to S (excluding the
+    terminating null character) or þtt{(size_t_t)-1} if a code could
+    not be counverted.
+
+þseealso mbstowcs() setlocale() wctomb()
+
+
+þfunction wctomb()
+þcompat C90
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þparam S WCHAR
+þprototype
+int wctomb (char *S, wchar_t WCHAR);
+þendprototype
+
+    Convert the wchar_t code WCHAR to a multibyte character sequence
+    pointed to by S.  At most MB_CUR_MAX bytes are stored.  If S is
+    NULL, the shift state is reset to the initial state.  If WCHAR is
+    zero, the shift state is the initial state after return from
+    wctomb().
+
+    In programs linked with the multithread libraries, each thread has
+    its own shift state for wctomb().
+
+þreturnvalue
+
+    If S is NULL, wctomb() returns a non-zero value (if
+    state-dependent encoding is used) or a zero value (if
+    state-dependent encoding is not used).  If S is not NULL, wctomb()
+    returns 0 (if WCHAR is zero), the number of bytes comprising the
+    multibyte character stored to S (if conversion is successful), or
+    -1 (if WCHAR could not be converted).
+
+þseealso mbtowc() setlocale() wcstombs()
+
+
+þfunction wm_attrib()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH A
+þprototype
+void wm_attrib (wm_handle WH, int A);
+þendprototype
+
+    Set the default attributes of window WH to A.
+
+þseealso wm_create() wm_get_attrib() wm_putc()
+
+
+þfunction wm_attrib_all()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH A
+þprototype
+void wm_attrib_all (wm_handle WH, int A);
+þendprototype
+
+    Change the attributes of all characters of window WH (except of
+    the border) to A.  The character codes are not changed.
+
+þseealso wm_attrib() wm_clear() wm_create()
+
+
+þfunction wm_backsp()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH COUNT
+þprototype
+void wm_backsp (wm_handle WH, int COUNT);
+þendprototype
+
+    Backspace the cursor of window WH.  The cursor is moved left by
+    COUNT characters.  If the cursor leaves the window at the left
+    edge, it is moved to the end of the previous line.  The cursor
+    cannot leave the window at the top edge.
+
+þseealso wm_putc()
+
+
+þfunction wm_border()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH BFLAG BATTR TITLE TFLAG TATTR
+þprototype
+void wm_border (wm_handle WH, int BFLAG, int BATTR, const char *TITLE,
+                int TFLAG, int TATTR);
+þendprototype
+
+    Change the border of window WH.  The border type is set to BFLAG:
+    0 turns the border off, 1 uses a single line, 2 uses a double
+    line, 3 and 4 use both single and double lines -- which is not
+    recommended as most code pages do not contain the necessary
+    symbols.  All other values are used as characters for drawing the
+    border.  The attributes BATTR are used for drawing the border.
+    The string pointed to by TITLE is displayed centered in the top
+    line of the border.  If TFLAG is non-zero, vertical bars are used
+    to separate the title text from the border.  The attributes TATTR
+    are used for displaying the title text.
+
+þseealso wm_create()
+
+
+þfunction wm_bottom()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_bottom (wm_handle WH);
+þendprototype
+
+    Move window WH to the bottom of the window stack, that is, it will
+    be moved below all other windows.
+
+þseealso wm_top() wm_up()
+
+
+þfunction wm_chide()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam FLAG
+þprototype
+void wm_chide (int FLAG);
+þendprototype
+
+    Set the cursor hide mode.  If FLAG is non-zero, the cursor is
+    hidden if the current cursor position is hidden by another window.
+    If FLAG is zero, the cursor is visible even if the cursor position
+    is hidden by another window.  The initial value is non-zero.
+
+þseealso wm_ctype() wm_cursor()
+
+
+þfunction wm_clear()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_clear (wm_handle WH);
+þendprototype
+
+    Clear window WH by filling WH with blanks using the current
+    attributes.
+
+þseealso wm_attrib() wm_attrib_all()
+
+
+þfunction wm_close()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_close (wm_handle WH);
+þendprototype
+
+    Close the window WH.  After closing the window, it still exists
+    but is not visible.
+
+þseealso wm_open()
+
+
+þfunction wm_close_all()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þprototype
+void wm_close_all (void);
+þendprototype
+
+   Close all the windows.  wm_close_all() restores the original screen
+   contents.
+
+þseealso wm_close() wm_open()
+
+
+þfunction wm_clr_eol()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y
+þprototype
+void wm_clr_eol (wm_handle WH, int X, int Y);
+þendprototype
+
+    Clear from position (X,Y) of window WH to the end of that line of
+    that window by displaying blanks.  The current attributes are
+    used.
+
+þseealso wm_clear()
+
+
+þfunction wm_create()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam X0 Y0 X1 Y1 BORDER BATTR WATTR
+þprototype
+wm_handle wm_create (int X0, int Y0, int X1, int Y1, int BORDER, int BATTR,
+                     int WATTR);
+þendprototype
+
+    Create a window.  The upper left character of the window interior
+    is at (X0,Y0), the bottom right character of the window interior
+    is at (X1,Y1).  A window may be larger than the screen or
+    partially or completely outside the screen.  BORDER specifies the
+    border type: 0 doesn't draw a border, 1 uses a single line, 2 uses
+    a double line, 3 and 4 use both single and double lines -- which
+    is not recommended as most code pages do not contain the necessary
+    symbols.  All other values are used as characters for drawing the
+    border.  The attributes BATTR are used for drawing the border.
+    The attributes for displaying text in the window are set to WATTR.
+    After creating a window, it is invisible.  Use wm_open() to show
+    the window.
+
+þreturnvalue
+
+    wm_create() returns the handle of the window if successful.
+    Otherwise, NULL is returned.
+
+þseealso wm_attrib() wm_border() wm_delete() wm_open()
+
+
+þfunction wm_ctype()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH START END
+þprototype
+void wm_ctype (wm_handle WH, int START, int END);
+þendprototype
+
+    Set the cursor type of window WH.  START is the first row of the
+    cursor, END is the last row of the cursor.  Both values are
+    zero-based.  The cursor type set by wm_ctype() is used for
+    displaying the cursor if it is connected to window WH.  Use
+    v_hardware() to determine the size of the character box.
+
+þseealso v_hardware() wm_chide() wm_cursor()
+
+
+þfunction wm_cursor()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_cursor (wm_handle WH);
+þendprototype
+
+    Connect the screen cursor with the cursor of window WH.  The
+    cursor is displayed at the cursor position of window WH, using the
+    cursor type of window WH.  If WH is NULL, the screen cursor is not
+    connected to any window and is invisible.  Initially, the screen
+    cursor is not connected to any window.
+
+þseealso wm_chide() wm_ctype() wm_cvis()
+
+
+þfunction wm_cvis()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH FLAG
+þprototype
+void wm_cvis (wm_handle WH, int FLAG);
+þendprototype
+
+    Set the cursor status of window WH.  If FLAG is non-zero, the
+    cursor is enabled, if FLAG is zero, the cursor is disabled.
+
+þseealso wm_chide() wm_cursor()
+
+
+þfunction wm_del_char()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y COUNT
+þprototype
+void wm_del_char (wm_handle WH, int X, int Y, int COUNT);
+þendprototype
+
+    Delete COUNT characters at position (X,Y) of window WH.
+    Characters to the right of that position are moved left, the
+    positions becoming vacant at the right edge of the window are
+    filled with blanks using the current attributes.
+
+þseealso wm_attrib() wm_del_line() wm_ins_char()
+
+
+þfunction wm_del_line()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH Y COUNT
+þprototype
+void wm_del_line (wm_handle WH, int Y, int COUNT);
+þendprototype
+
+    Delete COUNT lines at line Y of window WH by moving up the
+    lines below that line.  The current attributes are used for
+    filling lines becoming empty at the bottom of the window.
+
+þseealso wm_attrib() wm_del_char() wm_ins_line() wm_scroll()
+
+
+þfunction wm_delete()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_delete (wm_handle WH);
+þendprototype
+
+    Destroy the window WH.  After calling wm_delete(), the window
+    handle WH must no longer be used.  The window is not closed.
+
+þseealso wm_close() wm_create()
+
+
+þfunction wm_dimen()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH WIDTH HEIGHT
+þprototype
+void wm_dimen (wm_handle WH, int *WIDTH, int *HEIGHT);
+þendprototype
+
+    Store the width of the window WH (columns) to WIDTH, the height
+    (lines) to HEIGHT.
+
+þseealso wm_create()
+
+
+þfunction wm_down()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_down (wm_handle WH);
+þendprototype
+
+    Move window WH down the window stack, that is, it will be covered
+    by an additional window unless WH is already the bottom window.
+
+þseealso wm_bottom() wm_top() wm_up()
+
+
+þfunction wm_exit()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þprototype
+void wm_exit (void);
+þendprototype
+
+    Quit the window manager and release all memory allocated by the
+    window manager.  All window handles become invalid.  The windows
+    are not closed.
+
+þseealso wm_close() wm_delete()
+
+
+þfunction wm_fclose()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/winmgr.h>
+þendheaders
+
+þparam STREAM
+þprototype
+int wm_fclose (FILE *STREAM);
+þendprototype
+
+    Close a window manager file.
+
+þreturnvalue
+þdescription
+þitem 0
+    success
+þitem -1
+    error
+þenddescription
+
+
+þseealso wm_fopen()
+
+
+þfunction wm_find()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam X Y
+þprototype
+wm_handle wm_find (int X, int Y);
+þendprototype
+
+    Find the window which is visible at position (X,Y) of the screen.
+
+þreturnvalue
+
+    wm_find() returns the window handle if such a window exists.
+    Otherwise, wm_find() returns NULL.
+
+
+þfunction wm_fopen()
+þcompat emx
+þheaders
+#include <stdio.h>
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+FILE *wm_fopen (wm_handle WH);
+þendprototype
+
+    Open a window manager file.  All output to a video file goes to
+    the window WH, using window manager library functions such as
+    wm_puts().  The stream returned by wm_fopen() can be used with
+    fprintf(), fputc() and fwrite().  On error, wm_fopen() returns
+    NULL.  Do not use fclose() on a stream created by v_fopen(), use
+    wm_fclose() instead.  Do not read from a stream created by
+    wm_fopen().
+
+þreturnvalue
+
+    See above.
+
+þseealso _fassign() fopen() wm_printf()
+
+
+þfunction wm_get_attrib()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+int wm_get_attrib (wm_handle WH);
+þendprototype
+
+    Return the current attributes of window WH.
+
+þreturnvalue
+
+    See above.
+
+þseealso wm_attrib()
+
+
+þfunction wm_get_cursor()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þprototype
+wm_handle wm_get_cursor (void);
+þendprototype
+
+    Get the window to which the screen cursor is connected.
+
+þreturnvalue
+
+    wm_get_cursor() returns the window handle of the window to which
+    the screen cursor is connected.  If the cursor is not connected to
+    any window, wm_get_cursor() returns NULL.
+
+þseealso wm_cursor()
+
+
+þfunction wm_get_pos()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y
+þprototype
+void wm_get_pos (wm_handle WH, int *X, int *Y);
+þendprototype
+
+    Store the screen coordinates of the upper left character of the
+    interior of window WH to X and Y.
+
+þseealso wm_create() wm_move()
+
+
+þfunction wm_getxy() wm_getx() wm_gety()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y
+þprototype
+void wm_getxy (wm_handle WH, int *X, int *Y);
+int wm_getx (wm_handle WH);
+int wm_gety (wm_handle WH);
+þendprototype
+
+    wm_getxy() stores the cursor coordinates of window WH to X and Y.
+    wm_getx() returns the horizontal position (column) of the cursor
+    of window WH.  wm_gety() returns the vertical position (line) of
+    the cursor of window WH.  The coordinates are zero-based and are
+    relative to the upper left character of the interior of window WH.
+
+þreturnvalue
+
+    See above.
+
+þseealso wm_gotoxy()
+
+
+þfunction wm_gotoxy()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y
+þprototype
+void wm_gotoxy (wm_handle WH, int X, int Y);
+þendprototype
+
+    Move the cursor of window WH to (X,Y).  The coordinates are
+    zero-based and are relative to the upper left character of the
+    interior of window WH.  If the screen cursor is connected to the
+    cursor of window WH, the screen cursor is moved.
+
+þseealso wm_cursor() wm_getxy()
+
+
+þfunction wm_ins_char()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y COUNT
+þprototype
+void wm_ins_char (wm_handle WH, int X, int Y, int COUNT);
+þendprototype
+
+    Insert COUNT blank characters at position (X,Y) of window WH.
+    Characters to the right of that position are moved right.  The
+    current attributes are used for displaying the blank characters.
+
+þseealso wm_attrib() wm_del_char() wm_ins_line()
+
+
+þfunction wm_ins_line()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH Y COUNT
+þprototype
+void wm_ins_line (wm_handle WH, int Y, int COUNT);
+þendprototype
+
+    Insert COUNT empty lines at line Y of window WH by moving down
+    that line and all lines below that line.  The current attributes
+    are used for filling the empty lines.
+
+þseealso wm_attrib() wm_del_line() wm_scroll()
+
+
+þfunction wm_init()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam N
+þprototype
+int wm_init (int N);
+þendprototype
+
+    Initialize the window manager and allocate memory for N windows.
+    You must call this function before calling any other window
+    manager function.
+
+    General information about window manager functions: The window
+    manager functions implement text-mode output to windows on the
+    screen.  You have to link with -lvideo.  Under DOS, emx option
+    -acm is required, see `þhpt{Using emx options}'.
+
+þreturnvalue
+þdescription
+þitem 1
+    success
+þitem 0
+    error
+þenddescription
+
+þseealso wm_exit()
+
+þsamplefile /emx/samples/wm_demo.c, /emx/samples/wm_hello.c
+
+
+þfunction wm_move()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y
+þprototype
+void wm_move (wm_handle WH, int X, int Y);
+þendprototype
+
+    Move the window WH.  The upper left character of the interior of
+    the window will be at screen coordinates (X,Y).
+
+þseealso wm_get_pos()
+
+
+þfunction wm_open()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_open (wm_handle WH);
+þendprototype
+
+    Open the window WH.  The window will be showed on the screen
+    unless it is covered by other windows or outside the screen.
+
+þseealso wm_close()
+
+
+þfunction wm_printf()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH FMT
+þprototype
+int wm_printf (wm_handle WH, const char *FMT, ...);
+þendprototype
+
+    Formatted output to window WH at the current cursor position of
+    that window.  The cursor is moved.  See þhpt{printf()} for details
+    on the format string pointed to by FMT.
+
+þreturnvalue
+
+    wm_printf() returns the number of output characters.
+
+þseealso wm_attrib() wm_fopen() wm_putc() wm_puts() wm_vprintf()
+
+
+þfunction wm_puta_at()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y A COUNT
+þprototype
+void wm_puta_at (wm_handle WH, int X, int Y, int A, int COUNT);
+þendprototype
+
+    Change to A the attributes of COUNT characters at position (X,Y)
+    of window WH.  All COUNT characters must be in one line of the
+    window.
+
+þseealso wm_attrib() wm_putsa_at()
+
+
+þfunction wm_putc()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH C
+þprototype
+void wm_putc (wm_handle WH, char C);
+þendprototype
+
+    Display character C in window WH at the current cursor position of
+    that window, using the current attributes of that window.  The
+    cursor of that window is moved.  If the cursor leaves the window
+    at the right edge, it will be moved to the start of the next
+    line.  If C is þtt{'\n'}, the cursor is moved to the start of the
+    next line.  If the cursor leaves the window at the bottom edge,
+    the window is scrolled up.
+
+þseealso wm_attrib() wm_putc_at() wm_putca() wm_scroll() wm_wrap()
+
+
+þfunction wm_putc_at()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y C
+þprototype
+void wm_putc_at (wm_handle WH, int X, int Y, char C);
+þendprototype
+
+    Display character C at position (X,Y) of window WH using the
+    current attributes of that window.  The cursor is not moved.
+
+þseealso wm_attrib() wm_gotoxy()
+
+
+þfunction wm_putca()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH C A
+þprototype
+void wm_putca (wm_handle WH, char C, int A);
+þendprototype
+
+    Display character C in window WH at the current cursor position of
+    that window, using the attributes A.  The cursor of that window is
+    moved.  If the cursor leaves the window at the right edge, it will
+    be moved to the start of the next line.  If C is þtt{'\n'}, the
+    cursor is moved to the start of the next line.  If the cursor
+    leaves the window at the bottom edge, the window is scrolled up.
+
+þseealso wm_putc() wm_putca_at() wm_scroll() wm_wrap()
+
+
+þfunction wm_putca_at()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y C A
+þprototype
+void wm_putca_at (wm_handle WH, int X, int Y, char C, int A);
+þendprototype
+
+    Display character C at position (X,Y) of window WH using the
+    attributes A.  The cursor is not moved.
+
+
+þfunction wm_puts()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH STR
+þprototype
+void wm_puts (wm_handle WH, const char *STR);
+þendprototype
+
+    Display the string pointed to by STR in window WH at the current
+    cursor position of that window using the current attributes of
+    that window.  The þtt{'\n'} character moves the cursor to the
+    start of the next line.  Scrolling is performed when the cursor
+    leaves the window at the bottom edge.
+
+þseealso wm_attrib() wm_putc() wm_putsa() wm_scroll() wm_wrap()
+
+
+þfunction wm_puts_at()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y STR
+þprototype
+void wm_puts_at (wm_handle WH, int X, int Y, const char *STR);
+þendprototype
+
+    Display the string pointed to by STR in window WH at position
+    (X,Y) using the current attributes of that window.  The þtt{'\n'}
+    character is not interpreted, the cursor is not moved.
+
+þseealso wm_attrib() wm_puts()
+
+
+þfunction wm_putsa()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH STR LEN
+þprototype
+void wm_putsa (wm_handle WH, const char *STR, int LEN);
+þendprototype
+
+    Display LEN characters with attributes in window WH at the current
+    cursor position of that window.  STR points to an array of
+    character and attributes pairs.  There are 2*þpa{LEN} bytes at
+    STR.
+
+þseealso wm_putca() wm_puts() wm_scroll() wm_wrap()
+
+
+þfunction wm_putsa_at()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH X Y STR LEN
+þprototype
+void wm_putsa_at (wm_handle WH, int X, int Y, const char *STR, int LEN);
+þendprototype
+
+    Display LEN characters with attributes in window WH at position
+    (X,Y).  STR points to an array of character and attributes pairs.
+    There are 2*þpa{LEN} bytes at STR.
+
+þseealso wm_putsa()
+
+
+þfunction wm_scroll()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH COUNT
+þprototype
+void wm_scroll (wm_handle WH, int COUNT);
+þendprototype
+
+    Scroll the interior of window WH up by one line.  The bottom line
+    is filled with blanks, using the current attributes.
+
+þseealso wm_attrib() wm_del_line() wm_ins_line() wm_putc()
+
+
+þfunction wm_top()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_top (wm_handle WH);
+þendprototype
+
+    Move window WH to the top of the window stack, that is, it will
+    cover all other windows.
+
+þseealso wm_bottom() wm_down()
+
+
+þfunction wm_up()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH
+þprototype
+void wm_up (wm_handle WH);
+þendprototype
+
+    Move window WH up the window stack, that is, it will cover an
+    additional window unless WH is already the top window.
+
+þseealso wm_bottom() wm_down() wm_top()
+
+
+þfunction wm_update()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH FLAG
+þprototype
+void wm_update (wm_handle WH, int FLAG);
+þendprototype
+
+    Set the update mode of window WH.  If FLAG is non-zero (which is
+    the default), the screen is updated immediately if window WH is
+    changed.  If FLAG is zero, changes to window WH are done in memory
+    only.  This can be done to improve speed.  Each call to
+    wm_update() copies the window to the screen, regardless of the
+    FLAG argument.
+
+
+þfunction wm_vprintf()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH FMT ARG_PTR
+þprototype
+int wm_vprintf (wm_handle WH, const char *FMT, va_list ARG_PTR);
+þendprototype
+
+    Formatted output to window WH.  Instead of a list of arguments,
+    this function takes a pointer to the list of arguments.  See
+    wm_printf() for details.
+
+þreturnvalue
+
+    wm_vprintf() returns the number of output characters.
+
+þseealso wm_printf() va_arg()
+
+
+þfunction wm_wrap()
+þcompat emx
+þheaders
+#include <sys/winmgr.h>
+þendheaders
+
+þparam WH WRAP_FLAG
+þprototype
+void wm_wrap (wm_handle WH, int WRAP_FLAG);
+þendprototype
+
+    Set the end-of-line wrap mode of window WH.  If WRAP_FLAG is
+    non-zero (which is the default), the cursor is moved to the next
+    line if it reaches the end of a line.  If WRAP_FLAG is zero, the
+    cursor stays at the end of the line.  wm_wrap() applies to
+    wm_putc(), wm_puts(), wm_printf(), etcþ.
+
+þseealso wm_putc()
+
+
+þfunction write()
+þcompat POSIX.1
+þheaders
+#include <io.h>
+þendheaders
+
+þparam HANDLE BUF NBYTE
+þprototype
+int write (int HANDLE, const void *BUF, size_t NBYTE);
+þendprototype
+
+    Write NBYTE characters from the buffer BUF to the file HANDLE.
+    Writing 0 characters is allowed -- the request will be ignored.
+    In text mode, newline characters are translated to CR/LF pairs.
+
+þreturnvalue
+
+    write() returns the number of characters written.  If there is an
+    error, write() returns -1.  Text mode translation does not affect
+    the return value.
+
+þerrors
+þdescription
+þitem EAGAIN
+
+    The O_NONBLOCK (alias O_NDELAY) flag is set for HANDLE and the
+    process would be suspended in the write operation.
+
+þitem EBADF
+
+    The HANDLE argument is not a valid file descriptor.
+
+þitem EINTR
+
+    The write operation was interrupted by a caught signal.
+
+þitem EIO
+
+    An I/O error occured.  Use _syserrno() for getting the system
+    error code.
+
+þitem ENOSPC
+
+    There is no free space remaining on the device containing the file.
+
+þitem EPIPE
+
+    An attempt is made to write to a pipe or named pipe that is not
+    open for reading by any process.  A SIGPIPE signal is sent to the
+    process.  This error is returned if the signal does not terminate
+    the process.
+
+þenddescription
+
+þrestrictions
+
+    In binary mode, partial transfers to disk files (due to lack of
+    disk space) do not occur.  In text mode, partial transfers may
+    occur if the actual number of bytes (with newline translated to
+    CR/LF) written exceeds 1024.
+
+    PIPE_BUF is ignored: Write operations are atomic for any value of
+    NBYTE in blocking mode; write operations may be non-atomic for any
+    value of NBYTE in non-blocking mode.
+
+    O_APPEND is subject to race conditions.
+
+þseealso open() setmode() read() sigaction() signal()
+
+
+þh1 Variable reference
+þi1 Variables
+
+  The variables are listed almost alphabetically.
+
+
+þfunction daylight
+þheaders
+#include <time.h>
+þendheaders
+
+þprototype
+int daylight;
+þendprototype
+
+    This variable is zero if standard time is in effect.  It is
+    non-zero if daylight saving time is in effect.
+
+þseealso timezone tzname tzset()
+
+
+þfunction _emx_env
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+const unsigned int _emx_env;
+þendprototype
+
+    This variable contains bits describing the environment your
+    program is running in:
+
+þdescription
+
+þitem 0x0001
+
+    Running under VCPI
+
+þitem 0x0002
+
+    Running under XMS
+
+þitem 0x0004
+
+    VDISK 3.3 detected
+
+þitem 0x0008
+
+    Running under DESQview
+
+þitem 0x0010
+
+    287 coprocessor present
+
+þitem 0x0020
+
+    387 coprocessor present
+
+þitem 0x0200
+
+    Running under OS/2 2.x
+
+þitem 0x0400
+
+    File names are truncated (-t option)
+
+þitem 0x0800
+
+    Data and stack executable (-ac option under DOS)
+
+þitem 0x1000
+
+    Running under RSX
+
+þenddescription
+
+    You should check the 0x0200 bit before calling an OS/2 API
+    function.  You should check the 0x0400 bit when comparing file
+    names.
+
+þseealso _osmode
+
+
+þfunction _emx_rev
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+const unsigned int _emx_rev;
+þendprototype
+
+    This variable contains the emx revision index.  The revision index
+    is a number that is incremented everytime a new emx revision is
+    released.  When the emx version number changes, the revision index
+    is not reset to zero.  If _emx_rev is zero, the revision index is
+    not available because the emx version being in use is too old or
+    the system call library is used.
+
+þseealso _emx_vcmp _emx_vprt
+
+
+þfunction _emx_vcmp
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+const unsigned int _emx_vcmp;
+þendprototype
+
+    This variable contains the emx version number, suitable for
+    comparing.
+
+þseealso _emx_rev _emx_vprt
+
+þsamplecode
+if (_emx_vcmp > 0x302e3861)             /* > 0.8a */
+  {
+    ...
+  }
+þendsamplecode
+
+
+þfunction _emx_vprt
+þcompat emx
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+const char _emx_vprt[5];
+þendprototype
+
+    This variable contains the emx version number, suitable for
+    printing.
+
+þseealso _emx_rev _emx_vcmp
+
+þsamplecode
+printf ("emx version: %s\n", _emx_vprt);
+þendsamplecode
+
+
+þfunction environ
+þcompat POSIX.1
+
+þprototype
+char **environ;
+þendprototype
+
+    A pointer to the current environment of the process.  environ
+    points to an array of pointers to strings.  The array is
+    terminated by a NULL pointer.  After changing the environment with
+    putenv(), you should use this variable instead of the þpa{ENVP}
+    parameter of main().
+
+þimplementation
+
+    environ is declared in <stdlib.h>.
+
+þrestrictions
+
+    After changing the value of TZ, you should call tzset().
+
+þseealso main() putenv() tzset()
+
+
+þfunction errno
+þcompat C90
+þheaders
+#include <errno.h>
+þendheaders
+
+þprototype
+int errno;
+þendprototype
+
+    When a library function call fails, errno is usually set to a
+    positive value indicating the type of error.  On success, errno is
+    usually not changed.  Note that no library function sets errno to
+    zero.
+
+þimplementation
+
+    The following errno values are supported:
+
+þexample
+Name            ³ Value ³ Description
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+EPERM           ³  1    ³ Operation not permitted
+ENOENT          ³  2    ³ No such file or directory
+ESRCH           ³  3    ³ No such process
+EINTR           ³  4    ³ Interrupted system call
+EIO             ³  5    ³ I/O error
+ENXIO           ³  6    ³ No such device or address
+E2BIG           ³  7    ³ Arguments or environment too big
+ENOEXEC         ³  8    ³ Invalid executable file format
+EBADF           ³  9    ³ Bad file number
+ECHILD          ³  10   ³ No children
+EAGAIN          ³  11   ³ Resource temporarily unavailable
+ENOMEM          ³  12   ³ Not enough memory
+EACCES          ³  13   ³ Permission denied
+EFAULT          ³  14   ³ Bad address
+ENOLCK          ³  15   ³ No locks available
+EBUSY           ³  16   ³ Resource busy
+EEXIST          ³  17   ³ File exists
+EXDEV           ³  18   ³ Cross-device link
+ENODEV          ³  19   ³ No such device
+ENOTDIR         ³  20   ³ Not a directory
+EISDIR          ³  21   ³ Is a directory
+EINVAL          ³  22   ³ Invalid argument
+ENFILE          ³  23   ³ Too many open files in system
+EMFILE          ³  24   ³ Too many open files
+ENOTTY          ³  25   ³ Inappropriate ioctl
+EDEADLK         ³  26   ³ Resource deadlock avoided
+EFBIG           ³  27   ³ File too large
+ENOSPC          ³  28   ³ Disk full
+ESPIPE          ³  29   ³ Illegal seek
+EROFS           ³  30   ³ Read-only file system
+EMLINK          ³  31   ³ Too many links
+EPIPE           ³  32   ³ Broken pipe
+EDOM            ³  33   ³ Domain error
+ERANGE          ³  34   ³ Result too large
+ENOTEMPTY       ³  35   ³ Directory not empty
+EINPROGRESS     ³  36   ³ Operation now in progress
+ENOSYS          ³  37   ³ Function not implemented
+ENAMETOOLONG    ³  38   ³ File name too long
+EDESTADDRREQ    ³  39   ³ Destination address required
+EMSGSIZE        ³  40   ³ Message too long
+EPROTOTYPE      ³  41   ³ Protocol wrong type for socket
+ENOPROTOOPT     ³  42   ³ Option not supported by protocol
+EPROTONOSUPPORT ³  43   ³ tocol not supported
+ESOCKTNOSUPPORT ³  44   ³ ket type not supported
+EOPNOTSUPP      ³  45   ³ Operation not supported on socket
+EPFNOSUPPORT    ³  46   ³ Protocol family not supported
+EAFNOSUPPORT    ³  47   ³ Address family not supported by
+                ³       ³ protocol family
+EADDRINUSE      ³  48   ³ Address already in use
+EADDRNOTAVAIL   ³  49   ³ an't assigned requested address
+ENETDOWN        ³  50   ³ Network is down
+ENETUNREACH     ³  51   ³ Network is unreachable
+ENETRESET       ³  52   ³ Network dropped connection on reset
+ECONNABORTED    ³  53   ³ Software caused connection abort
+ECONNRESET      ³  54   ³ Connection reset by peer
+ENOBUFS         ³  55   ³ No buffer space available
+EISCONN         ³  56   ³ Socket is already connected
+ENOTCONN        ³  57   ³ Socket is not connected
+ESHUTDOWN       ³  58   ³ Can't send after socket shutdown
+ETOOMANYREFS    ³  59   ³ Too many references: can't splice
+ETIMEDOUT       ³  60   ³ Connection timed out
+ECONNREFUSED    ³  61   ³ Connection refused
+ELOOP           ³  62   ³ Too many levels of symbolic links
+ENOTSOCK        ³  63   ³ Socket operation on non-socket
+EHOSTDOWN       ³  64   ³ Host is down
+EHOSTUNREACH    ³  65   ³ No route to host
+EALREADY        ³  66   ³ Operation already in progress
+þendexample
+
+    In multithread programs (-Zmt, -Zmts, or -Zmtd), errno is not a
+    global variable; it is an lvalue that depends on the thread
+    number; each thread has its own errno object.
+
+    To create a library which can be linked to both single-thread and
+    multithread programs, use the option
+
+þexample
+-D__ST_MT_ERRNO__
+þendexample
+
+    on the GCC command line to define errno to call _errno().
+
+þseealso _beginthread() _errno() _gettid() perror() strerror() _syserrno() sys_errlist _threadid _threadstore()
+
+
+þfunction g_xsize g_ysize g_colors
+þcompat emx
+þheaders
+#include <graph.h>
+þendheaders
+
+þprototype
+int g_xsize;
+int g_ysize;
+int g_colors;
+þendprototype
+
+    These variables describe the graphics mode selected by g_mode() or
+    g_modeset().  g_xsize is the horizontal resolution (width),
+    g_ysize is the vertical resolution (height), g_colors is the
+    number of distinct colors that can be displayed at a time.
+
+þseealso g_mode() g_modeset()
+
+
+þfunction _osminor _osmajor
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+const unsigned char _osminor;
+const unsigned char _osmajor;
+þendprototype
+
+    These variables contain the minor and major version numbers of the
+    operating system.  For DOS 3.30, _osmajor is 3 and _osminor is
+    30.  For OS/2 2.0, _osmajor is 20, _osminor is 0.  For OS/2 2.1,
+    _osmajor is 20, _osminor is 10.
+
+þseealso _emx_env _osmode
+
+þsamplecode
+printf ("OS version: %d.%d\n", _osmajor, _osminor);
+þendsamplecode
+
+
+þfunction _osmode
+þcompat PC
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+const unsigned char _osmode;
+þendprototype
+
+    This variable contains DOS_MODE if your program is running under
+    DOS or OS2_MODE if your program is running under OS/2.
+
+þseealso _emx_env
+
+
+þfunction stderr stdin stdout
+þcompat C90
+þheaders
+#include <stdio.h>
+þendheaders
+
+þprototype
+FILE *stderr;
+FILE *stdin;
+FILE *stdout;
+þendprototype
+
+    stderr, stdin, and stdout are expressions of type `þtt{FILE *}'
+    pointing to the þtt{FILE} objects associated with the
+    standard error, standard input, and standard output streams,
+    respectively.
+
+þhints
+
+    Note that stderr, stdin, and stdout need not be variables, that
+    is, you cannot use them in initializers and you cannot assign to
+    them.  Use freopen() to associate another stream with stderr,
+    stdin, or stdout.
+
+þseealso freopen()
+
+
+þfunction sys_errlist sys_nerr
+þheaders
+#include <stdlib.h>
+þendheaders
+
+þprototype
+const char * const sys_errlist[];
+const int sys_nerr;
+þendprototype
+
+    sys_errlist is an array of error messages indexed by errno values.
+    sys_nerr is the number of elements in the sys_errlist array.
+
+þseealso errno perror() strerror()
+
+
+þfunction _threadid
+þcompat OS/2
+þheaders
+#include <stddef.h>
+þendheaders
+
+þprototype
+unsigned *_threadid;
+þendprototype
+
+    _threadid is an lvalue which points to the thread identification
+    number of the current thread as contained in the þtt{TIB2}
+    structure.  _threadid must not be used under DOS.
+
+þseealso _beginthread() _gettid() _threadstore()
+
+
+þfunction timezone
+þheaders
+#include <time.h>
+þendheaders
+
+þprototype
+long timezone;
+þendprototype
+
+    Seconds west of the Prime Meridian.  This variable is set by tzset().
+
+þseealso daylight tzname tzset()
+
+
+þfunction tzname
+þheaders
+#include <time.h>
+þendheaders
+
+þprototype
+char *tzname[2];
+þendprototype
+
+    The first pointer points to the name of the local standard
+    timezone.  The second pointer points to the name of the local
+    summer timezone.  This variable is set by tzset().
+
+þseealso daylight timezone tzset()
+
+
+þh1 System calls
+
+  System calls are documented in þtt{/emx/doc/system.doc}.
+
+  All system calls are declared in <emx/syscalls.h>.  Interface
+  routines are in the emx.a and emx.lib libraries.  System call
+  emulation routines are in the sys.lib libraries.  Please do not use
+  system calls from application programs -- always use C library
+  functions.  If you need a system call, put a function into the
+  library which issues the system call.
+
+  Do not use INT 21H: the function numbers and the parameter passing
+  conventions are subject to change.  Similarities to DOS function
+  numbers are just coincidence and will probably disappear.  Moreover,
+  INT 21H, like any software interrupt, cannot be used under OS/2.
+  The goal is to have Unix-like system calls.
+
+þtext
+
+--------------------------- END OF EMXLIB.DOC ------------------------------
+þendtext
Index: trunk/src/emx/src/doc/emxrt.src
===================================================================
--- trunk/src/emx/src/doc/emxrt.src	(revision 18)
+++ trunk/src/emx/src/doc/emxrt.src	(revision 18)
@@ -0,0 +1,1531 @@
+þtext
+===============================================================================
+emxrt.doc    emx 0.9d FIX 04     USER'S GUIDE TO THE EMX RUNTIME    20-Mar-2001
+===============================================================================
+                                     Copyright (c) 1990-2001 by Eberhard Mattes
+þendtext
+
+
+þtitle User's Guide to the emx Runtime
+
+þformat bold emx emxbind emxstack emxupd emxuzdll termcap rsx
+
+þformat tty emx.exe emxl.exe emxbind.exe emx.dll emxio.dll emxwrap.dll
+þformat tty emxload.exe emxstack.exe emxrt.doc rsx.exe emxfpemu emxrt.zip
+þformat tty \emx\dll \emx\bin config.sys emxlibc.dll emxlibcm.dll emxlibcs.dll
+þformat tty cmd.exe emxrev
+þformat tty SET \emx\bin\emx.exe autoexec.bat termcap.dat himem.sys
+þformat tty unzip.exe
+þformat tty vdisk.sys SIGKILL SIGABRT abort() .dll LIBPATH BREAK=ON
+þformat tty DosKillThread select()
+
+þformat syntax -c -d -e -E -f -h# -K -m1 -m2 -m3 -n -o -O -p -q -x
+þformat syntax -r* -s<size> -t -t* -u<size> -v -I -V -X <size>
+þformat syntax <source_file> <target_path> <old_file> <zip_file> <dll_dir>
+
+þformat abbrev etc.
+
+
+þif text
+þh= Table of Contents
+þtoc
+þendif
+
+
+þh1 Introduction to the User's Guide to the emx Runtime
+þipf
+:font facename=Helv size=24x14.:hp2.User's Guide to the emx Runtime
+:ehp2.
+:p.
+:font facename=Helv size=16x10.      Copyright (c) 1990-1996 by Eberhard Mattes
+:font facename=default size=0x0.
+:p.
+þendipf
+
+  This is the documentation for the emx runtime package.  The emx
+  runtime is an environment for 32-bit programs under OS/2 2.x, OS/2
+  3.x (OS/2, in short), MS-DOS, and PC-DOS (DOS, in short) on machines
+  with a 386 CPU (or one of its successors).
+
+þif text
+
+  Under OS/2, you can view the þtt{.inf} version of this document by
+  typing
+
+þexample
+view \emx\book\emxrt
+þendexample
+
+  If you add þtt{\emx\book} to the BOOKSHELF environment variable, you
+  can type
+
+þexample
+view emxrt
+þendexample
+
+  to view that on-line book.
+
+þendif
+
+þipfminitoc
+
+þh2 Hardware requirements
+þlabel Hardware requirements
+
+  emx requires an 80386 CPU (80386DX, 80386SX, i486, or later)
+
+þh2 Files included in the emx runtime package
+þlabel Files included in the emx runtime package
+
+  The emx runtime package includes the following files:
+
+þverbatim
+  \emx\bin\emx.exe              emx runtime for DOS
+  \emx\bin\emxbind.exe          Tool for modifying emx programs (DOS and OS/2)
+  \emx\bin\emxfpemu             Emulator for numeric coprocessor (DOS)
+  \emx\bin\emxl.exe             emx loader (used by emxbind)
+  \emx\bin\emxload.exe          Server for keeping OS/2 programs in memory
+  \emx\bin\emxrev.cmd           Tool for displaying emx revisions (OS/2)
+  \emx\bin\emxstack.exe         Tool for fixing the stack size of old programs
+  \emx\bin\emxupd.exe           Tool for updating a DLL which is in use
+  \emx\bin\emxuzdll.cmd         Unpack DLLs and install them with emxupd.exe
+  \emx\book\emxrt.inf           The text you are looking at (VIEW version)
+  \emx\dll\emx.dll              emx runtime for OS/2
+  \emx\dll\emxio.dll            Hardware port I/O under OS/2
+  \emx\dll\emxlibc.dll          Forwarder DLL to emxlibcm.dll (OS/2)
+  \emx\dll\emxlibcm.dll         Multithread C library (OS/2)
+  \emx\dll\emxlibcs.dll         Single-thread C library (OS/2)
+  \emx\dll\emxwrap.dll          Interface to 16-bit OS/2 functions (OS/2)
+  \emx\doc\COPYING              GNU General Public License
+  \emx\doc\COPYING.EMX          emx copyright information
+  \emx\doc\emxrt.doc            The text you are looking at (text version)
+  \emx\etc\termcap.dat          Terminal data base for termcap-based programs
+  \emx\etc\emclibcm.map         Map file for emxlibcm.dll
+  \emx\etc\emclibcm.tdf         Trace definition file for emxlibm.dll
+  \emx\etc\emclibcs.map         Map file for emxlibcs.dll
+  \emx\etc\emclibcs.tdf         Trace definition file for emxlibs.dll
+  \emx\etc\trc00f8.tff          Trace format file for emxlibcs.dll
+  \emx\etc\trc00f9.tff          Trace format file for emxlibcm.dll
+þendverbatim
+
+  The þtt{.map}, þtt{.tdf}, and þtt{.tff} files are used for
+  debugging.  They are included in emxrt.zip to keep them in sync with
+  the DLLs.
+
+þh1 License
+
+  emx is free software; you can redistribute it and/or modify it under
+  the terms of the GNU General Public License as published by the Free
+  Software Foundation; either version 2, or (at your option) any later
+  version.
+
+  emx is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with emx; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330,
+  Boston, MA 02111-1307, USA.
+
+  See þtt{\emx\doc\COPYING.EMX} and þtt{\emx\doc\COPYING} for details.
+
+  Please note that source code for parts of the contents of
+  þtt{emxrt.zip} is contained in þtt{emxfix04.zip}.
+
+þh1 Installing the emx runtime package under OS/2
+
+þipfminitoc
+
+þh2 Summary for impatient OS/2 users
+þlabel Summary for impatient OS/2 users
+
+
+þenumerate
+
+þitem
+
+  If you are using Siegfried Hanisch's ScreenSaver, either upgrade to
+  version 2.6 or disable ScreenSaver
+
+þitem
+
+  Add \emx\dll to LIBPATH (always use the latest copy of the .dll files!)
+
+þitem
+
+  Add \emx\bin to PATH
+
+þitem
+
+  Reboot
+
+þendenumerate
+
+
+þh2 Detailed instructions for OS/2 users
+þlabel Detailed instructions for OS/2 users
+þlabel LIBPATH
+
+  emx does not work with OS/2 1.x and in DOS mode of OS/2.
+
+  Before changing config.sys, make a backup copy of that file!
+
+  emx 0.9c and later breaks some versions of Siegfried Hanisch's
+  ScreenSaver.  Either upgrade to version 2.6 or disable ScreenSaver
+  before installing emx 0.9c or later.  Otherwise, your system will
+  freeze.
+
+  The emx runtime is implemented as a set of dynamic link libraries
+  under OS/2:
+
+þdescription
+þitem emx.dll
+
+    emx run-time support for OS/2
+
+þitem emxio.dll
+
+    access to hardware ports for emx programs under OS/2
+
+þitem emxlibc.dll
+
+    forwarder DLL to emxlibcm.dll for existing applications that use
+    emxlibc.dll (which has been renamed to emxlibcm.dll)
+
+þitem emxlibcm.dll
+
+    multithread emx C library
+
+þitem emxlibcs.dll
+
+    single-thread emx C library
+
+þitem emxwrap.dll
+
+    32-bit wrappers for 16-bit OS/2 API functions
+
+þenddescription
+
+  OS/2 looks for dynamic link libraries in the directories listed in
+  the LIBPATH statement of your config.sys file.  Note that LIBPATH is
+  not an environment variable!
+
+  At any time, at most one version of a dynamic link library is
+  loaded.  If there are different versions of a dynamic link library
+  in the directories listed in the LIBPATH statement, the first one
+  listed is loaded.  If you already have installed the emx dynamic
+  link libraries, you should be careful to use the latest revision of
+  those dynamic link libraries.  Newer emx dynamic link libraries work
+  with older emx programs (however, you may have to apply
+  þhpt{emxstack}), but newer emx programs don't work with older emx
+  dynamic link libraries.  To find out about already installed emx
+  dynamic link libraries, type
+
+þexample
+cd \emx\bin
+emxrev
+þendexample
+
+  If no emx dynamic link libraries are installed, no output is
+  produced.  If there are emx dynamic link libraries installed, the
+  names and revision numbers are displayed, for instance
+
+þexample
+EMX : revision = 30
+EMXIO : revision = 30
+EMXLIBC : revision = 30
+EMXLIBCM : revision = 30
+EMXLIBCS : revision = 30
+EMXWRAP : revision = 30
+þendexample
+
+  Only directories listed in the LIBPATH statement are searched.  To
+  find out the revision numbers of the dynamic link libraries of this
+  package, type
+
+þexample
+emxrev -d c:\emx\dll
+þendexample
+
+  if you have put the emx runtime package on drive C.  After running
+  emxrev, you should quit the command processor by typing
+
+þexample
+exit
+þendexample
+
+  to release the dynamic link libraries (they have been loaded by
+  cmd.exe as emxrev is a REXX procedure).  Otherwise, you cannot
+  rename, overwrite, or delete those files.  This also happens if one
+  of the emx dynamic link libraries is currently used by a program.
+  If you get error message þtt{SYS0032}, or the message
+
+þexample
+error:  cannot create emx/dll/emx.dll
+þendexample
+
+  from þtt{unzip} when unpacking emxrt.zip, use
+
+þexample
+pstat /L
+þendexample
+
+  to find out about the dynamic link libraries used by the programs
+  currently running.  Terminate all the programs using emx.dll,
+  emxio.dll, emxlibc.dll, emxlibcm.dll, emxlibcs.dll, or emxwrap.dll.
+  The command
+
+þexample
+emxload -qw
+þendexample
+
+  will unload programs kept in memory by emxload.exe.
+
+  If that doesn't help, use emxuzdll to install the emx DLLs: Create a
+  temporary directory and run emxuzdll in that directory, giving the
+  path name of emxrt.zip and the path name of the emx DLL directory on
+  the command line:
+
+þexample
+mkdir \emxtmp
+chdir \emxtmp
+emxuzdll a:\emxrt.zip c:\emx\dll
+chdir ..
+rmdir emxtmp
+þendexample
+
+  This will replace the DLLs in þtt{c:\emx\dll} with the DLLs in
+  emxrt.zip even if the DLLs are in use.  The new versions of the DLLs
+  become active as soon as the last process referencing them is
+  terminated, or on the next reboot.  Therefore, you should reboot
+  after running emxuzdll, otherwise you won't know if and when the new
+  versions become active.  (Actually, you don't need a temporary
+  directory, any directory not containing any DLL files will do.)
+
+  Either copy the latest revisions of the emx dynamic link libraries
+  (that is, those with the highest revision numbers) to a directory
+  directory listed in the LIBPATH statement of config.sys or, better,
+  modify the LIBPATH statement to include the directory where the
+  latest revisions of the emx dynamic link libraries can be found.
+
+  The directories of the LIBPATH statement are separated by
+  semicolons.  To add þtt{c:\emx\dll} to the LIBPATH statement, append
+  a semicolon -- if there is not yet a semicolon -- to the end of the
+  line of config.sys that starts with
+
+þexample
+LIBPATH=
+þendexample
+
+  Then, type the absolute name of the directory.  Example:
+
+þexample
+LIBPATH=.;C:\OS2\DLL;C:\OS2\MDOS;C:\;C:\OS2\APPS\DLL;D:\EMX\DLL
+þendexample
+
+  Optionally, you can append a semicolon at the end.
+
+  Next, modify the line of config.sys starting with
+
+þexample
+SET PATH=
+þendexample
+
+  to include the \emx\bin directory.  For instance, change
+
+þexample
+SET PATH=C:\OS2;C:\OS2\SYSTEM;C:\OS2\MDOS\WINOS2;C:\OS2\INSTALL;
+C:\;C:\OS2\MDOS;C:\OS2\APPS
+þendexample
+
+  to
+
+þexample
+SET PATH=C:\OS2;C:\OS2\SYSTEM;C:\OS2\MDOS\WINOS2;C:\OS2\INSTALL;
+C:\;C:\OS2\MDOS;C:\OS2\APPS;D:\EMX\BIN
+þendexample
+
+  As with LIBPATH, you have to put a semicolon between the path names
+  and a trailing semicolon is optional.  Note that the last two
+  examples are shown in two lines; in config.sys, however, the
+  complete SET statement must be put into one line.
+
+  You might want to add þtt{\emx\book} to the BOOKSHELF environment
+  variable to simplify viewing the on-line documentation.  For
+  instance, change the line
+
+þexample
+SET BOOKSHELF=C:\OS2\BOOK;
+þendexample
+
+  of your config.sys file to
+
+þexample
+SET BOOKSHELF=C:\OS2\BOOK;C:\EMX\BOOK
+þendexample
+
+  as with PATH, you have to put a semicolon between the path names
+  and a trailing semicolon is optional.
+
+  Now, you should reboot to activate the changes to config.sys.  After
+  booting, run
+
+þexample
+emxrev
+þendexample
+
+  to verify that the latest revision of emx is now active.
+
+  If OS/2 says
+
+þexample
+SYS1804: The system cannot find the file EMX.
+þendexample
+
+  when running an emx program, you have not correctly set the LIBPATH
+  statement of config.sys.  See above for details.
+
+  When running an old program (which assumes that emx.dll creates a
+  stack object if the stack size is too small), you will get an error
+  message like
+
+þexample
+emx.dll: Stack size too small.  Run
+  emxstack -f D:\BIN\PROGRAM.EXE
+and try again.
+þendexample
+
+  Run þhpt{emxstack} as indicated by the error message to fix the
+  stack size of the program.  If you can't (because you don't have
+  write permission for the file), type
+
+þexample
+set emxopt=-I
+þendexample
+
+  to make emx.dll ignore the problem.  However, the program will
+  probably crash due to insufficient stack size.  Using the -I option
+  is not recommended!
+
+þh1 Installing the emx runtime package under DOS
+
+þipfminitoc
+
+þh2 Summary for impatient DOS users
+þlabel Summary for impatient DOS users
+
+þenumerate
+þitem
+
+  Add \emx\bin to PATH or set EMX to point to \emx\bin\emx.exe
+
+þitem
+
+  If you are using a memory manager which implements DPMI, enable VCPI
+
+þitem
+
+  Remove BREAK=ON from config.sys
+
+þitem
+
+  Reboot
+
+þendenumerate
+
+
+þh2 Detailed instructions for DOS users
+þlabel Detailed instructions for DOS users
+
+  emx programs for DOS come in two flavours: those which load emx.exe
+  from a separate file and those which have the emx runtime emx.exe
+  integrated in the executable file of the application program.
+
+  Before changing autoexec.bat and config.sys, make a backup copy of
+  these files!
+
+  If you want to use a program which loads emx.exe, you have to put
+  emx.exe into a directory which is listed in your PATH environment
+  variable or you have to change the PATH environment variable (in
+  autoexec.bat) to include the directory in which emx.exe can be
+  found.  For instance, if your autoexec.bat file contains the line
+
+þexample
+path c:\dos;d:\bin
+þendexample
+
+  you have installed the emx runtime on drive D, you should modify
+  that line to read
+
+þexample
+path c:\dos;d:\bin;d:\emx\bin
+þendexample
+
+  You have to put a semicolon between the path names.
+
+  Alternatively, you can set an environment variable which directly
+  points to the emx.exe executable.  If you use this method, your
+  program can locate emx.exe more quickly.  If you have installed the
+  emx runtime on drive D:, you should add the following line to your
+  autoexec.bat file:
+
+þexample
+set emx=d:\emx\bin\emx.exe
+þendexample
+
+  Note that a directory name is not sufficient -- you have to type the
+  complete path name of the emx.exe file.
+
+  Programs of the second flavour, having emx.exe integrated, don't
+  require \emx\bin added to the PATH environment variable or the EMX
+  environment variable being set.  The program itself, however, may
+  need changes to your autoexec.bat file.  See the documentation
+  accompanying the program.  The following steps are required for both
+  flavours of emx programs.
+
+  If you are using a memory manager (such as QEMM or EMM386 or 386max)
+  which implements DPMI (DOS Protected Mode Interface), you have to
+  change the invokation of that memory manager to enable VCPI as emx
+  does not support DPMI.  See the documentation of your memory for
+  details.  If your memory manager supports DPMI only (without VCPI),
+  you have to remove or disable the memory manager.  Alternatively,
+  you can use þhpt{rsx}, as indicated in section þref{rsx}.  emx
+  supports XMS and VCPI.
+
+  Examine your config.sys file: If there is a line
+
+þexample
+BREAK=ON
+þendexample
+
+  in it, you should remove it as it causes trouble with emx and lots
+  of other programs.
+
+  If and only if you are using an `Intel Inboard 386/PC' expansion
+  board in your 8088-based PC, add the following line to autoexec.bat
+  (it's very unlikely that you are using such an expansion board):
+
+þexample
+set emxopt=-m3
+þendexample
+
+  If the swap file (used to swap memory pages to disk when running out
+  of physical memory) should be in a specific directory or on a
+  specific disk drive, set the EMXTMP environment variable in
+  autoexec.bat.  Example:
+
+þexample
+set emxtmp=c:\tmp
+þendexample
+
+  Now, you should reboot to activate the changes to config.sys and
+  autoexec.bat.
+
+
+þh1 Environment variables (OS/2 and DOS)
+
+  The operation of emx and emx programs is controlled by several
+  environment variables.  You might have to set one or more of the
+  following environment variables:
+
+þdescription
+þitem INIT
+
+    used by termcap to find termcap.dat
+
+þitem TERM
+
+    used by termcap to define the terminal type
+
+þitem EMXETC
+
+    used by termcap to find termcap.dat
+
+þitem EMXOPT
+
+    emx options (see below)
+
+þitem EMXSHELL
+
+    overrides the COMSPEC environment variable.  You can use this to
+    run an alternate command processor (shell) from emx programs
+
+þitem EMXPATH
+
+    search path for programs (usually not relevant)
+
+þitem PATH
+
+    search path for program (used if EMXPATH fails)
+
+þitem TERMCAP
+
+    used by termcap to find termcap.dat
+
+þitem TZ
+
+    selects the timezone
+
+þenddescription
+
+þipfminitoc
+
+þh2 Setting the TZ environment variable
+
+    The TZ environment variable controls how to compute Coordinated
+    Universal Time (UTC aka GMT) from local time.  (Note that under
+    Unix, TZ is used for computing local time from UTC as UTC is used
+    for the system clock under Unix; under OS/2 and DOS, local time is
+    used for the system clock.)
+
+    The value of TZ has the following format:
+
+þindent
+    þsy{<TZ1>[<OFF>,[<TZ2>[,<SM>,<SW>,<SD>,<ST>,<EM>,<EW>,<ED>,<ET>,<SHIFT>]]]}
+þendindent
+
+    þsy{<TZ1>} is the three-letter name of the standard timezone.
+
+    þsy{<OFF>} is the offset to Coordinated Universal Time; positive
+    values are to the west of the Prime Meridian, negative values are
+    to the east of the Prime Meridian.  The offset can be specified as
+    hours, hours and minutes, or hours, minutes, and seconds.  Hours,
+    minutes, and seconds are separated by colons.  If þsy{<OFF>} is
+    not specified, an offset of 0 will be used (this may change in the
+    future).
+
+    þsy{<TZ2>} is the three-letter name of the summer timezone
+    (daylight saving time).  If þsy{<TZ2>} is not specified, daylight
+    saving time does not apply.  If þsy{<TZ2>} is specified, daylight
+    saving time does apply; the remainder of the TZ's value specifies
+    when and how to change to and back from daylight saving time.
+    þsy{<SM>} through þsy{<ST>} define, in current local time, when to
+    switch from standard time to daylight saving time, þsy{<EM>}
+    through þsy{<ET>} define, in current local time, when to switch
+    from daylight saving time to standard time.  (On the southern
+    hemisphere, the end date precedes the start date.)  þsy{<SHIFT>} is
+    the amount of change in seconds.
+
+    þsy{<SM>} specifies the month (1 through 12) of the change.
+    þsy{<SW>} specifies the week of the change; if this value is zero,
+    þsy{<SD>} specifies the day of month (1 through 31).  If þsy{<SW>}
+    is positive (1 through 4), the change occurs on weekday þsy{<SD>}
+    (0=Sunday through 6=Saturday) of the þsy{<SW>}th week of the
+    specified month.  The first week of a month starts on the first
+    Sunday of the month.  If þsy{<SW>} is negative (-1 through -4),
+    the change occurs on weekday þsy{<SD>} (0=Sunday through
+    6=Saturday) of the -þsy{<SW>}th week of the specified month,
+    counted from the end of the month (that is, -1 specifies the last
+    week of the month).  The last week of a month starts on the last
+    Sunday of the month.  þsy{<ST>} specifies the time of the change,
+    in seconds.  Note that þsy{<ST>} is specified in local standard
+    time and þsy{<ET>} is specified in local daylight saving time.
+    Example:
+
+þexample
+CET-1CED,3,-1,0,7200,10,-1,0,10800,3600
+þendexample
+
+    In this example, the name of the standard time zone is þtt{CET},
+    the name of the summer time zone is CED.  Daylight saving time
+    starts at 2:00 on the last Sunday of March and ends at 3:00 on the
+    last Sunday of October.  Time changes by one hour in daylight
+    saving time.
+
+    If no characters follow þsy{<TZ2>}, the rule
+    `þtt{,4,1,0,3600,10,-1,0,7200,3600}' will be used: Daylight saving
+    time starts at 1:00 on the first Sunday of April and ends at 2:00
+    on the last Sunday of October.  Time changes by one hour in
+    daylight saving time.
+
+þh2 Environment variables (DOS)
+þlabel Environment variables (DOS)
+
+þdescription
+þitem EMX
+
+    path name of emx.exe, used by programs which are bound with
+    emxl.exe (the emx loader) instead of emx.exe.  Set EMX to speed up
+    loading of emx.exe or to load a specific version of emx.exe
+
+þitem EMXTMP
+
+    directory for the swap file
+
+þitem TMP
+
+    used if EMXTMP is not set
+
+þenddescription
+
+
+þh1 DOS Notes
+
+þipfminitoc
+
+þh2 General notes
+
+þitemize
+þitem
+
+  emx requires DOS 3.0 or later
+
+þitem
+
+  emx does not support DPMI
+
+þitem
+
+  emx does not support DESQview without VCPI (use QEMM-386 with DESQview)
+
+þitem
+
+  If emx doesn't work under DESQview (especially if it displays the
+  message
+
+þexample
+Nonmaskable interrupt (NMI)
+þendexample
+
+  either set the protection level to 0 or use the þtt{WATCHDOG=0}
+  option of QEMM-386.
+
+þitem
+
+  emx supports VCPI
+
+þitem
+
+  emx supports XMS.  Do not use emx with himem.sys 2.06 or earlier.
+
+þitem
+
+  emx checks for XMS version number 2.00 or later and for XMS driver
+  revision 2.06 or later, as older himem.sys drivers don't work
+  correctly.  You can override this check by using the þhpt{-O} emx
+  option (for drivers using a different revision numbering scheme),
+  but emx may not work with your XMS driver, anyway.  Actually, emx
+  has not been tested with himem.sys 2.05; 2.04 fails, 2.06 works.
+
+þitem
+
+  emx supports vdisk.sys 3.3 and later and most other RAM disk drivers
+
+þitem
+
+  emx uses (or tries to use) all available memory, whether
+  conventional, extended, or expanded memory.  If there isn't enough
+  memory, emx will swap to disk.  The swap file will be created in the
+  directory given by the EMXTMP environment variable.  If EMXTMP is
+  not set, TMP will be used.  If both variables are not set, the swap
+  file will be created in the root directory of the current drive.
+
+þitem
+
+  If a program uses floating point instructions and no numeric
+  coprocessor (387) is installed, emx tries to load the FPU (floating
+  point unit) emulator emxfpemu.  That file is first sought in the
+  directory from which emx.exe was loaded (this does not apply if
+  emx.exe is bound to the executable), then in the current working
+  directory and the directories listed in the EMXPATH and PATH
+  environment variables.  If emxfpemu cannot be found, the program
+  will be aborted by signal SIGFPE.
+
+þenditemize
+
+
+þh2 Emergency exit
+
+  If the computer freezes while running emx, try hitting Ctrl-Break
+  five times in one scond.  That will terminate emx (and all emx
+  processes run by that instance of emx) unless it is blocked in a DOS
+  call.  If blocked in a DOS call, emx will terminate after return
+  from that DOS call.
+
+
+þh2 Using rsx instead of emx
+þlabel rsx
+
+  rsx is a DPMI-compliant DOS extender which is more or less
+  compatible to emx.  Moreover, rsx contains a floating point
+  emulator.  rsx is free software and has been written by Rainer
+  Schnittker.  As of this writing, rsx is assumed to be available for
+  anonymous ftp as
+
+þexample
+ftp.uni-bielefeld.de: /pub/systems/msdos/misc/rsx510.zip
+ftp.leo.org:          /pub/comp/os/os2/leo/gnu/emx+gcc/contrib/rsx510.zip
+þendexample
+
+  If the emx loader emxl.exe finds a DPMI server but no VCPI server,
+  it tries to run rsx.exe instead of emx.exe.  The RSX environment
+  variable will be used instead of the EMX environment variable for
+  locating rsx.exe.
+
+  To load rsx.exe instead of emx.exe even if there is a DPMI server
+  and a VCPI server (for instance if you need the floating point
+  emulation of rsx), set the EMX environment variable to point to
+  rsx.exe.  Note that rsx needs a DPMI server.
+
+þh1 emx options
+
+  You can customize emx by setting the EMXOPT environment variable.
+  This environment variable contains a list of options, similar to
+  command line options.  The options must be separated by at least one
+  blank.  Example:
+
+þexample
+set emxopt=-c -h40
+þendexample
+
+þipfminitoc
+
+þh2 emx options (OS/2)
+þlabel emx options (OS/2)
+
+þdescription
+þitem -c
+
+    Disable core dumps caused by signals and exceptions
+
+þitem -h#
+
+    Set OS/2 file handle limit to þsy{#}.  The number þsy{#} must be
+    between 10 and 65536
+
+þitem -n
+
+    Suppress popups for exceptions.  As emx.dll displays an
+    appropriate error message and dumps core, popups are not required
+
+þitem -q
+
+    All command line arguments passed to child processes will be
+    quoted unconditionally, that is, wildcard expansion and response
+    files won't work in child processes of processes for which the -q
+    option is in effect
+
+þitem -r*
+
+    Prepend drive letter þsy{*} to absolute path names.  If a path
+    name starts with þtt{/} but does not start with þtt{//},
+    þtt{/dev/} or þtt{/pipe/}, þsy{*} followed by a colon will be
+    prepended.  If þsy{-rd} has been given, the file name
+    þtt{\mydir\abc} will be translated to þtt{d:\mydir\abc}.  Note:
+    this option can cause unexpected effects
+
+þitem -t*
+
+    Truncate file names to 8.3 format.  Each part of a pathname is
+    truncated to 8.3 format by taking the first 8 characters before
+    the dot and the first 3 characters after the dot.  This is useful
+    to compile programs on a FAT filesystem with minimal changes.
+
+    Without argument, -t enables truncation on all drives and for UNC
+    pathnames.
+
+    The -t option takes an optional argument, listing the names of the
+    drives on which file names should be truncated.  The special drive
+    name `þtt{/}' controls whether to truncate UNC pathnames.  With
+    `þtt{-tc/}', for instance, file names on drive C and UNC pathnames
+    will be truncated.
+
+    If the argument of the -t option is `þtt{-}', truncation is
+    disabled for all drives and for UNC pathnames.  This is the
+    default setting.  If the argument starts with `þtt{-}', truncation
+    is disabled on all drives listed.  With `þtt{-t -t-d}', for instance,
+    UNC pathnames and file names on all drives except
+    drive D will be truncated.
+
+þitem -x
+
+    Don't suppress wildcard expansion and response files if the `MKS
+    Korn shell' method of passing command line arguments is used
+
+þitem -E
+
+    Run debuggee in same session (window) as debugger
+
+þitem -I
+
+    Don't complain about programs having too small a stack size.
+    Without the -I option, emx.dll displays an error message for those
+    programs, telling how to run þhpt{emxstack} to fix the stack size.
+    With the -I option, the program is run despite of the problem.
+    However, the program will probably crash due to insufficient stack
+    size.  Using the -I option is not recommended!
+
+þitem -K
+
+    Don't use DosKillThread.  Due to bugs in OS/2, DosKillThread may
+    cause problems.  emx.dll automatically avoids using DosKillThread
+    for OS/2 2.1 and older.  For OS/2 2.11 and later, you can use the
+    -K option to disable usage of DosKillThread.  Currently,
+    DosKillThread is not used by emx.dll and this option does not have
+    any effect.
+
+þenddescription
+
+
+þh2 emx options (DOS)
+þlabel emx options (DOS)
+
+þdescription
+
+þitem -c
+
+    Disable core dumps caused by signals and exceptions
+
+þitem -d
+
+    Don't use extended memory
+
+þitem -e
+
+    Redirect the standard error handle (2) to standard output (1)
+
+þitem -h#
+
+    Set DOS file handle limit to þsy{#}.  The number þsy{#} must be
+    between 10 and 65536.  This option is ignored for DOS versions
+    earlier than 3.30.  This option does not change the emx limit for
+    the number of files per process -- that limit is always 40
+
+þitem -m1
+
+    Running on Fujitsu FMR70 (not implemented yet)
+
+þitem -m2
+
+    Running on NEC PC-98 (not implemented yet)
+
+þitem -m3
+
+    Running on Intel Inboard 386/PC
+
+þitem -o
+
+    Send the register dump of an exception to stdout.  Without -o, the
+    register dump is sent to the CON device.  You need -o for
+    redirecting the register dump to a file.
+
+    emx now creates a core dump file (named `þtt{core}') instead of a
+    register dump.  Please keep that file in case the author of the
+    program needs it for debugging.
+
+þitem -q
+
+    All command line arguments passed to child processes will be
+    quoted unconditionally, that is, wildcard expansion and response
+    files won't work in child processes of processes for which the -q
+    option is in effect
+
+þitem -r*
+
+    Prepend drive letter þsy{*} to absolute path names.  If a path
+    name starts with þtt{/} but does not start with þtt{//},
+    þtt{/dev/} or þtt{/pipe/}, þsy{*} followed by a colon will be
+    prepended.  If þsy{-rd} has been given, the file name
+    þtt{\mydir\abc} will be translated to þtt{d:\mydir\abc}.  Note:
+    this option can cause unexpected effects
+
+þitem -t*
+
+    Truncate file names to 8.3 format.  Each part of a pathname is
+    truncated to 8.3 format by taking the first 8 characters before
+    the dot and the first 3 characters after the dot.  This is useful
+    to compile programs on a FAT filesystem with minimal changes.
+
+    Without argument, -t enables truncation on all drives and for UNC
+    pathnames.
+
+    The -t option takes an optional argument, listing the names of the
+    drives on which file names should be truncated.  The special drive
+    name `þtt{/}' controls whether to truncate UNC pathnames.  With
+    `þtt{-tc/}', for instance, file names on drive C and UNC pathnames
+    will be truncated.
+
+    If the argument of the -t option is `þtt{-}', truncation is
+    disabled for all drives and for UNC pathnames.  This is the
+    default setting.  If the argument starts with `þtt{-}', truncation
+    is disabled on all drives listed.  With `þtt{-t -t-d}', for instance,
+    UNC pathnames and file names on all drives except
+    drive D will be truncated.
+
+þitem -E
+
+    Don't check for 387 coprocessor.  Assume no coprocessor is present
+
+þitem -O
+þlabel -O
+
+    Override XMS version check.  By default, emx checks for XMS
+    version number 2.00 or later and for XMS driver revision 2.06 or
+    later, as older himem.sys drivers don't work correctly.  You can
+    override this check by giving the -O option (for drivers using a
+    different revision numbering scheme), but emx may not work with
+    your XMS driver, anyway.  Actually, emx has not been tested with
+    himem.sys 2.05; 2.04 fails, 2.06 works
+
+þitem -V
+
+    Display emx version.  On program start, the emx version will be
+    displayed
+
+þitem -X
+
+    Disable usage of XMS memory.  Usage of XMS memory with VCPI is a
+    new feature of emx.  If this happens to cause trouble, use the -X
+    option.
+
+þenddescription
+
+
+þh1 The emxstack tool
+þlabel emxstack
+
+    The emxstack tool is used for displaying and fixing the stack
+    size.  Old programs assume that emx.dll allocates a stack object
+    if the stack size is too small.  As emx.dll no longer does this,
+    the stack size of the programs must be fixed.
+
+þindent
+  þsy{emxstack <command> [<options>] <file>...}
+þendindent
+
+    The following commands are available:
+
+þlist
+
+þitem -c
+
+    Check whether the stack size should be fixed.  For each file, if
+    the stack size is too small, a message will be displayed.  If the
+    stack size is big enough, no message will be displayed.
+
+þitem -d
+
+    Display the stack size.  For each file, the stack size in KByte
+    will be displayed.
+
+þitem -f
+
+    Fix the stack size.  For each file, the stack size is fixed if it
+    is too small.
+
+þitem -s<size>
+
+    Set the stack size.  For each file, the stack size is set to
+    <size> KByte.
+
+þitem -u<size>
+
+    Update the stack size.  For each file, the stack size is set to
+    <size> KByte if it less than <size> KByte.  If the stack size is
+    not less than <size> KByte, the stack size won't be changed.
+
+þendlist
+
+    The following options are available:
+
+þlist
+
+þitem -p
+
+    Act on all files in the PATH.  The command is applied to each file
+    in a directory listed in the PATH environment variable.  No file
+    names must be given on the command line.
+
+þitem -q
+
+    Be quiet.  No messages will be displayed.  However, error messages
+    won't be suppressed.
+
+þitem -v
+
+    Be verbose.  Display additional messages.
+
+þendlist
+
+    Example:
+
+þexample
+emxstack -f *.exe
+þendexample
+
+
+þh1 The emxupd tool
+þlabel emxupd
+
+    The emxupd tool can replace (and delete) DLLs which are currently
+    in use.  (It can do so for EXE files also.)  The old version of
+    the DLL stays in memory and in use for programs which currently
+    use it until all applications which use that DLL terminate.  Then,
+    the new DLL will be used.  Rebooting also switches to the new DLL.
+
+þipfminitoc
+
+þh2 Replacing a DLL
+
+    To replace a DLL, type
+
+þindent
+  þsy{emxupd <source_file> <target_path>}
+þendindent
+
+    This command copies <source_file> to the directory or file
+    <target_path>.  Examples:
+
+þexample
+emxupd c:\tmp\emx.dll c:\emx\dll
+þendexample
+
+    This command copies þtt{c:\tmp\emx.dll} to þtt{c:\emx\dll\emx.dll}.
+
+þexample
+emxupd abc.dll d:\dll\new.dll
+þendexample
+
+    This command copies þtt{abc.dll} to þtt{d:\dll\new.dll}.
+
+þh2 Deleting a DLL
+
+    To delete a DLL, type
+
+þindent
+  þsy{emxupd -d <old_file>}
+þendindent
+
+    where <old_file> is the path name of the DLL to delete.
+
+þh2 Unpacking DLLs from a ZIP file and installing them with emxupd
+
+    To unpack all DLLs from a ZIP file and install them in a directory
+    with emxupd, replacing DLLs even if they are in use, type
+
+þindent
+  þsy{emxuzdll <zip_file> <dll_dir>}
+þendindent
+
+    where <zip_file> is the path name of the ZIP file to unpack the
+    DLLs from and <dll_dir> is the directory where all the DLLs of the
+    ZIP file should be put.  emxuzdll can be used only if there are no
+    DLL files in the current directory.
+
+þh1 Troubleshooting
+
+    This section shows how to solve common problems involving the emx
+    runtime.
+
+þipfminitoc
+
+þh2 Warning message `WARNING: emx 0.9d or later required'
+
+    If this message appears, an out-of-date version of emx.dll is
+    active.  Make sure that the latest version of emx.dll is in a
+    directory pointed to by the LIBPATH statement in your config.sys
+    file.  Use
+
+þexample
+emxrev -p c:\config.sys
+þendexample
+
+    to list all emx dynamic link libraries reachable by the LIBPATH
+    statement of þtt{c:\config.sys} (use the drive letter of your boot
+    drive instead of þtt{c:}).  To simplify things, you should keep
+    only one version of each DLL.  Older programs work with newer emx
+    DLLs, but not vice versa.
+
+þh2 unzip.exe says `cannot create emx/dll/emx.dll'
+
+    This happens when you try to unpack emxrt.zip while a program is
+    active which uses emx.dll.  Terminate all programs which use
+    emx.dll and try again.  If you run emxrev, the command interpreter
+    keeps emx.dll loaded until terminated.  Therefore, you should
+    close all OS/2 windows and full-screen sessions in which you have
+    run emxrev.  All this also applies to emxlibcm.dll etc.
+
+þh2 emx.dll cannot be deleted, renamed or overwritten
+
+    See the previous problem.
+
+þh2 Error message `SYS1804: The system cannot find the file EMX.'
+
+    You have not correctly set the þhpt{LIBPATH} statement of
+    config.sys, therefore emx.dll could not be found.
+
+þh2 Error message `rsx not found, DPMI not supported by emx'
+
+    The current version of emx cannot use DPMI.  Therefore, the loader
+    tried to use rsx instead, but couldn't find rsx.  Remedy: install
+    þhpt{rsx} or end the DPMI server (MS Windows).
+
+þh2 Error message `emx.dll: Stack size too small...'
+
+    You tried to run an old program (which assumes that emx.dll
+    creates a stack object if the stack size is too small).
+
+    Run þhpt{emxstack} as indicated by the error message to fix the
+    stack size of the program.  If you can't (because you don't have
+    write permission for the file), type
+
+þexample
+set emxopt=-I
+þendexample
+
+  to make emx.dll ignore the problem.  However, the program will
+  probably crash due to insufficient stack size.  Using the -I option
+  is not recommended!
+
+þh2 DOS message `Sector not found'
+
+  DOS seems to display that message if a file is opened twice (perhaps
+  one handle for reading, one for writing).  For instance, this
+  happens when GCC runs out of temporary files.  Look for files named
+  like þtt{cca00002}, þtt{ccz00002} etc. (the digits may vary) in your
+  temporary directory and delete them.
+
+þh1 emx messages
+
+þipfminitoc
+
+þh2 emx messages (OS/2)
+
+þlist
+
+þitem þtt{core dumped}
+
+    The program cannot continue due to a fatal error (exception).  An
+    image of the program's memory has been written to a file named
+    `þtt{core}'.  Please keep that file in case the author of the
+    program needs it for debugging.
+
+þitem þtt{emx.dll: Stack size too small...}
+
+    You tried to run an old program (which assumes that emx.dll
+    creates a stack object if the stack size is too small).  You
+    should run þhpt{emxstack} to fix the stack size.
+
+þitem þtt{Invalid option in EMXOPT}
+
+    An option in the EMXOPT environement variable is not understood by
+    emx.
+
+þitem þtt{Invalid syscall function code}
+
+    The program run by emx has called an invalid system function.
+    Most likely, you're using an emx.dll which is out of date.
+
+þitem þtt{WARNING: emx 0.9d or later required}
+
+    The program requires emx.dll 0.9d or later.  However, an older
+    version of emx.dll is active.  Make sure that the latest version
+    of emx.dll is in a directory pointed to by the LIBPATH statement
+    in your config.sys file.  Use
+
+þexample
+emxrev -p c:\config.sys
+þendexample
+
+    to list all emx dynamic link libraries reachable by the LIBPATH
+    statement of þtt{c:\config.sys} (use the drive letter of your boot
+    drive instead of þtt{c:}).  To simplify things, you should keep
+    only one version of each DLL.  Older programs work with newer emx
+    DLLs, but not vice versa.
+
+þendlist
+
+
+þh2 emx messages (DOS)
+
+þlist
+þitem þtt{Abnormal program termination}
+
+    The program received the SIGABRT signal.  The abort() function was
+    called or SIGABRT was raised.
+
+þitem þtt{Bad environment}
+
+    The program name could not be found in the environment segment or
+    the environment segment is longer than 32768 bytes.  This should
+    not happen in practice.
+
+þitem þtt{Cannot create swap file}
+
+    The swap file could not be created.  Remedy: make sure the swap
+    file can be created in the directory given by the EMXTMP (or TMP)
+    environment variable.  If EMXTMP and TMP are not set, emx will
+    create the swap file in the root directory of the current drive.
+
+þitem þtt{Cannot enable A20}
+
+    emx tried to enable address line A20 and failed.  Remedy: contact
+    the author.
+
+þitem þtt{Cannot enable A20 via XMS}
+
+    emx tried to enable address line A20 by calling the XMS driver.
+    Unfortunately, A20 couldn't be enabled.  Remedy: unknown.
+
+þitem þtt{Cannot open program file}
+
+    The program file given on the emx command line could not be found
+    or opened.  Remedy: type the correct file name.  (This should not
+    happen with bound programs.)
+
+þitem þtt{Cannot read program file}
+
+    An error occured while reading the program file.  Remedy: make
+    sure the program file given on the emx command line is valid (this
+    does not apply to bound programs).  Maybe some other program
+    accesses that file.
+
+þitem þtt{core dumped}
+
+    The program cannot continue due to a fatal error (exception).  An
+    image of the program's memory has been written to a file named
+    `þtt{core}'.  Please keep that file in case the author of the
+    program needs it for debugging.
+
+þitem þtt{DPMI not supported}
+
+    The current version of emx cannot use DPMI.  Maybe some future
+    version will do.  Remedy: end the DPMI server (MS Windows) or use
+    þhpt{rsx}.
+
+þitem þtt{emx not found}
+
+    The emx loader (emxl.exe) failed to find emx.exe.  Make sure that
+    emx.exe is in a directory listed in the PATH environment variable.
+    Alternatively, you can set the EMX environment variable to the
+    complete path name of emx.exe.
+
+þitem þtt{Exception ...}
+
+    The program run by emx tried to do something which is considered
+    illegal by the processor or by emx.  Remedy: report to the
+    supplier of the program.
+
+þitem þtt{Illegal moucall function}
+
+    The program run by emx has called an invalid system function.
+    Remedy: report to the supplier of the program.
+
+þitem þtt{Illegal syscall function}
+
+    The program run by emx has called an invalid system function.
+    Remedy: report to the supplier of the program.
+
+þitem þtt{Illegal viocall function}
+
+    The program run by emx has called an invalid system function.
+    Remedy: report to the supplier of the program.
+
+þitem þtt{Invalid arguments for DOS function }þsl{xx}
+
+    The program run by emx has used invalid arguments for a system
+    function.  Remedy: report to the supplier of the program.
+
+þitem þtt{Invalid emx option}
+
+    An option in EMXOPT or set by emxbind is not understood by emx.
+    Remedy: check EMXOPT.  Use þtt{emxbind -i} to display the options
+    set by emxbind.
+
+þitem þtt{Invalid program file}
+
+    The program file given on the emx command line (or bound to emx)
+    is corrupt.  Remedy: reload the program from diskette.  If this
+    doesn't help you should contact the supplier of the program.
+
+þitem þtt{Invalid special function code: }þsl{xx}
+
+    The program run by emx has called an invalid system function.
+    Remedy: report to the supplier of the program.
+
+þitem þtt{Linear address space exhausted}
+
+    The program run by emx uses far too much memory.  Remedy: complain
+    to the author.
+
+þitem þtt{Nonmaskable interrupt (NMI) at }þsl{xxxx}þtt{:}þsl{yyyyyyyy}
+
+    A nonmaskable interrupt occured.  Maybe this is due to a memory
+    error.  Remedy: if you are using DESQview, either set the
+    protection level to 0 or use the þtt{WATCHDOG=0} option of
+    QEMM-386.  Otherwise, run a program for testing memory.
+
+þitem þtt{Out of memory}
+
+    There isn't enough memory for running emx.  Remedy: remove some
+    drivers and/or resident programs.  Or add memory to your machine.
+
+þitem þtt{Out of stacks}
+
+    emx ran out of local stacks.  Remedy: complain to the author.
+
+þitem þtt{Out of memory or swap space}
+
+    emx cannot write to the swap file because the disk is full.
+    Remedy: make sure there is enough space on the drive used for the
+    swap file.  Use the EMXTMP (or TMP) environment variable to tell
+    emx where to create the swap file.  If neither EMXTMP nor TMP is
+    set, emx will create the swap file in the root directory of the
+    current drive.
+
+þitem þtt{Out of swap space}
+
+    emx cannot write to the swap file because the disk is full.
+    Remedy: make sure there is enough space on the drive used for the
+    swap file.  Use the EMXTMP (or TMP) environment variable to tell
+    emx where to create the swap file.  If neither EMXTMP nor TMP is
+    set, emx will create the swap file in the root directory of the
+    current drive.
+
+þitem þtt{Process terminated by SIGINT}
+
+    You have stopped the program by hitting Ctrl-C or Ctrl-Break.
+
+þitem þtt{Process terminated by SIG...}
+
+    The program has been stopped due to a signal or exception.
+    Usually, this indicates a fatal error in the program.
+
+þitem þtt{Program aborted}
+
+    You have aborted the program by answering `Abort' after a critical
+    error had occured.
+
+þitem þtt{rsx not found, DPMI not supported by emx}
+
+    The current version of emx cannot use DPMI.  Therefore, the loader
+    tried to use rsx instead, but couldn't find rsx.  Remedy: install
+    þhpt{rsx} or end the DPMI server (MS Windows).
+
+þitem þtt{Swap file I/O error}
+
+    emx couldn't read or write the swap file.
+
+þitem þtt{This program does not run in DOS mode of OS/2}
+
+    DOS emulation of OS/2 doesn't support emx.  Remedy: boot DOS or
+    run the program in a OS/2 window
+
+þitem þtt{This program requires an 80386 CPU}
+
+    You need an 80386DX, 80386SX, i486 or later CPU for running emx.
+    Remedy: get another computer.
+
+þitem þtt{This program requires DOS 3.0 or later}
+
+    If emx is bound with an application program into one executable,
+    DOS 3.0 or later is required for execution.
+
+þitem þtt{Too many processes}
+
+    emx supports up to 4 processes.  You tried to start 5 or more
+    processes.
+
+þitem þtt{Unexpected interrupt}
+
+    This cannot happen.  Remedy: report to the author.
+
+þitem þtt{Unsupported VDISK.SYS version}
+
+    emx doesn't support the vdisk.sys device driver you are using.
+    Remedy: remove VDISK.SYS or use a different version.  emx should
+    work with vdisk.sys 3.3 or later.
+
+þitem þtt{Unsupported XMS version}
+
+    emx requires himem.sys 2.06 or later (older versions are too
+    buggy).  Remedy: get a newer himem.sys.  If you are not using
+    himem.sys, use the þhpt{-O} option of emx and tell the author
+    whether this works or not.
+
+þitem þtt{Unusable interrupt vector mappings set by VCPI server}
+
+    The configuration of the VCPI server (EMS driver) is illegal.
+    Remedy: read the manual of the EMS driver.
+
+þitem þtt{Use emxbind}
+
+    You tried to run emxl.exe, which doesn't make sense.  emxl.exe is
+    designed to be bound into an executable file by emxbind.
+
+þitem þtt{Virtual mode not supported without VCPI}
+
+    A VCPI server is required to run emx if the CPU is in virtual
+    mode.  You will get this message if you're using an EMS driver (EMS
+    emulator) which doesn't support VCPI or if you have disabled EMS.
+    Remedy: remove the EMS driver, use an EMS driver which supports
+    VCPI or enable EMS if it has been disabled (for instance, remove
+    the þtt{NOEMS} keyword from the command line of the EMS driver).
+
+þitem þtt{Wrong emx version}
+
+    The version of emx.exe does not match the version the program was
+    compiled for.  Remedy: use the copy of emx.exe that comes with the
+    program.  If you are using different programs which need different
+    versions of emx.exe, use the EMX environment variable to set the
+    path name of the correct version of emx.exe before running a
+    program which requires a version different from the default
+    emx.exe.  You can also use þtt{emxbind -u} to put the correct
+    version of emx.exe into the executable files.
+
+þendlist
+
+
+þh1 Obtaining the complete emx package
+
+  emx is available for anonymous ftp on
+
+þexample
+ftp.leo.org:          /pub/comp/os/os2/leo/gnu/emx+gcc/
+ftp-os2.cdrom.com:    /pub/os2/emx09d/
+ftp-os2.nmsu.edu:     /pub/os2/dev/emx/v0.9d/
+þendexample
+
+
+þh1 The author of emx
+
+The author of emx is
+
+þif ipf
+
+þindent
+  Eberhard Mattes þbreak
+  Teckstraáe 81 þbreak
+  D-71696 Mglingen þbreak
+  Germany
+þendindent
+
+þelse
+
+þexample
+Eberhard Mattes
+Teckstrasse 81                                      (TeX: Teckstra\ss e)
+D-71696 Moeglingen                                  (TeX: M\"oglingen)
+Germany
+þendexample
+
+þendif
+
+  Internet E-Mail:
+
+þindent
+  þtt{mattes@azu.informatik.uni-stuttgart.de}  (subject to change) þbreak
+  þtt{mattes@windhager.de}
+þendindent
+
+  No telephone calls please!  It must be stressed that the author does
+  not reply to letters if you don't include return postage
+  (international postal reply coupon if you are outside Germany) and a
+  self-addressed envelope.
+
+þtext
+
+--------------------------- END OF EMXRT.DOC --------------------------------
+þendtext
Index: trunk/src/emx/src/doc/makefile
===================================================================
--- trunk/src/emx/src/doc/makefile	(revision 18)
+++ trunk/src/emx/src/doc/makefile	(revision 18)
@@ -0,0 +1,133 @@
+#
+# /emx/src/doc/makefile
+#
+
+BOOK=\emx\book\ #
+DOC=\emx\doc\ #
+
+default:	all
+
+all:	docs books ndx
+
+docs:	$(DOC)emxrt.doc $(DOC)emxdev.doc $(DOC)emxlib.doc \
+    $(DOC)emxgnu.doc $(DOC)emxbsd.doc
+
+books:	$(BOOK)emxrt.inf $(BOOK)emxdev.inf $(BOOK)emxlib.inf \
+    $(BOOK)emxgnu.inf $(BOOK)emxbsd.inf
+
+ndx:	$(BOOK)emxdev.ndx $(BOOK)emxlib.ndx $(BOOK)emxgnu.ndx \
+    $(BOOK)emxbsd.ndx $(BOOK)emxbook.ndx
+
+emxrt: $(DOC)emxrt.doc $(BOOK)emxrt.inf
+emxdev: $(DOC)emxdev.doc $(BOOK)emxdev.inf $(BOOK)emxdev.ndx
+emxlib: $(DOC)emxlib.doc $(BOOK)emxlib.inf $(BOOK)emxlib.ndx
+emxgnu: $(DOC)emxgnu.doc $(BOOK)emxgnu.inf $(BOOK)emxgnu.ndx
+emxbsd: $(DOC)emxbsd.doc $(BOOK)emxbsd.inf $(BOOK)emxbsd.ndx
+
+
+$(DOC)emxrt.doc:	emxrt.src
+	emxdoc -To $(DOC)emxrt.doc emxrt.src
+
+$(DOC)emxdev.doc:	emxdev.src
+	emxdoc -To $(DOC)emxdev.doc emxdev.src
+
+$(DOC)emxlib.doc:	emxlib.src
+	emxdoc -To $(DOC)emxlib.doc emxlib.src
+
+$(DOC)emxgnu.doc:	emxgnu.src
+	emxdoc -To $(DOC)emxgnu.doc emxgnu.src
+
+$(DOC)emxbsd.doc:	emxbsd.src
+	emxdoc -To $(DOC)emxbsd.doc emxbsd.src
+
+
+$(BOOK)emxdev.ndx: emxdev.src
+	emxdoc -Ko $(BOOK)emxdev.ndx emxdev.src
+
+$(BOOK)emxlib.ndx: emxlib.src
+	emxdoc -Ko $(BOOK)emxlib.ndx emxlib.src
+
+$(BOOK)emxgnu.ndx: emxgnu.src
+	emxdoc -Ko $(BOOK)emxgnu.ndx emxgnu.src
+
+$(BOOK)emxbsd.ndx: emxbsd.src
+	emxdoc -Ko $(BOOK)emxbsd.ndx emxbsd.src
+
+$(BOOK)emxbook.ndx: $(BOOK)emxdev.ndx $(BOOK)emxlib.ndx $(BOOK)emxgnu.ndx \
+    $(BOOK)emxbsd.ndx emxbook.sed
+	sed -n -f emxbook.sed $(BOOK)emxdev.ndx $(BOOK)emxlib.ndx $(BOOK)emxgnu.ndx $(BOOK)emxbsd.ndx >$(BOOK)emxbook.ndx
+
+$(BOOK)emxrt.inf: emxrt.ipf
+	-del $(BOOK)emxrt.inf
+	ipfc emxrt.ipf /inf
+	move emxrt.inf $(BOOK)emxrt.inf
+
+$(BOOK)emxdev.inf: emxdev.ipf
+	-del $(BOOK)emxdev.inf
+	ipfc emxdev.ipf /inf
+	move emxdev.inf $(BOOK)emxdev.inf
+
+$(BOOK)emxgnu.inf: emxgnu.ipf
+	-del $(BOOK)emxgnu.inf
+	ipfc emxgnu.ipf /inf
+	move emxgnu.inf $(BOOK)emxgnu.inf
+
+$(BOOK)emxbsd.inf: emxbsd.ipf
+	-del $(BOOK)emxbsd.inf
+	ipfc emxbsd.ipf /inf
+	move emxbsd.inf $(BOOK)emxbsd.inf
+
+$(BOOK)emxlib.inf: emxlib.ipf
+	-del $(BOOK)emxlib.inf
+	ipfc emxlib.ipf /inf
+	move emxlib.inf $(BOOK)emxlib.inf
+
+emxrt.ipf:	emxrt.src
+	emxdoc -Ic -icp850 -o emxrt.ipf emxrt.src
+
+emxdev.ipf:	emxdev.src emxbook.dir
+	emxdoc -Iac -n1000 -icp850 -o emxdev.ipf -x emxbook.dir emxdev.src
+
+emxgnu.ipf:	emxgnu.src emxbook.dir
+	emxdoc -Iac -n2000 -o emxgnu.ipf -x emxbook.dir emxgnu.src
+
+emxbsd.ipf:	emxbsd.src emxbook.dir
+	emxdoc -Iac -n3000 -o emxbsd.ipf -x emxbook.dir emxbsd.src
+
+emxlib.ipf:	emxlib.src emxbook.dir
+	emxdoc -Iac -n1 -o emxlib.ipf -x emxbook.dir emxlib.src
+
+emxbook.dir:	st-dir
+st-dir:		emxdev.dir emxgnu.dir emxbsd.dir emxlib.dir
+	emxdoc -Mo tmp emxdev.dir emxgnu.dir emxbsd.dir emxlib.dir
+	updt tmp emxbook.dir
+	del tmp
+	touch st-dir
+
+emxdev.dir:	emxdev.src
+	emxdoc -Ig -n1000 -icp850 -o emxdev.dir emxdev.src
+
+emxgnu.dir:	emxgnu.src
+	emxdoc -Ig -n2000 -o emxgnu.dir emxgnu.src
+
+emxbsd.dir:	emxbsd.src
+	emxdoc -Ig -n3000 -o emxbsd.dir emxbsd.src
+
+emxlib.dir:	emxlib.src
+	emxdoc -Ig -n1 -o emxlib.dir emxlib.src
+
+clean:
+	-del *.dir
+	-del *.ipf
+	-del $(BOOK)*.ndx
+	-del $(DOC)emxrt.doc
+	-del $(DOC)emxdev.doc
+	-del $(BOOK)emxrt.inf
+	-del $(BOOK)emxdev.inf
+	-del $(DOC)emxgnu.doc
+	-del $(BOOK)emxgnu.inf
+	-del $(DOC)emxbsd.doc
+	-del $(BOOK)emxbsd.inf
+	-del $(DOC)emxlib.doc
+	-del $(BOOK)emxlib.inf
+	-del st-dir
Index: trunk/src/emx/src/dos/a20.asm
===================================================================
--- trunk/src/emx/src/dos/a20.asm	(revision 18)
+++ trunk/src/emx/src/dos/a20.asm	(revision 18)
@@ -0,0 +1,400 @@
+;
+; A20.ASM -- Control the A20 gate
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE XMS.INC
+                INCLUDE VCPI.INC
+                INCLUDE OPTIONS.INC
+
+                PUBLIC  USE_A20_PATCH, USE_FAST_A20
+                PUBLIC  INIT_A20, CLEANUP_A20, CHECK_A20
+                PUBLIC  A20_ON, A20_OFF
+
+SV_DATA         SEGMENT
+
+;
+; Enable/disable A20: address of functions
+;
+A20_ON_JMP      DW      ?
+A20_OFF_JMP     DW      ?
+
+A20_FLAG        DB      FALSE
+USE_A20_PATCH   DB      FALSE
+USE_FAST_A20    DB      FALSE
+
+SV_DATA         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Find out which machine we're running on
+; and set A20 enable/disable function addresses
+;
+                ASSUME  DS:SV_DATA
+INIT_A20        PROC    NEAR
+                PUSH    ES                      ; Don't clobber ES (ARGS!)
+                LEA     BX, PATCH_A20_ON
+                LEA     DX, PATCH_A20_OFF
+                CMP     USE_A20_PATCH, FALSE
+                JNE     SHORT INIT_A20_SET
+                LEA     BX, FAST_A20_ON
+                LEA     DX, FAST_A20_OFF
+                CMP     USE_FAST_A20, FALSE
+                JNE     SHORT INIT_A20_SET
+                LEA     BX, XMS_A20_ON
+                LEA     DX, XMS_A20_OFF
+                CMP     XMS_FLAG, FALSE
+                JNE     SHORT INIT_A20_SET
+                LEA     BX, FMR70_A20_ON
+                LEA     DX, FMR70_A20_OFF
+                CMP     MACHINE, MACH_FMR70
+                JE      SHORT INIT_A20_SET
+                LEA     BX, PC98_A20_ON
+                LEA     DX, PC98_A20_OFF
+                CMP     MACHINE, MACH_PC98
+                JE      SHORT INIT_A20_SET
+                LEA     BX, INBOARD_A20_ON
+                LEA     DX, INBOARD_A20_OFF
+                CMP     MACHINE, MACH_INBOARD
+                JE      SHORT INIT_A20_SET
+                MOV     AH, 0C0H                ; Return config. parameters
+                STC                             ; Don't trust BIOS
+                INT     15H                     ; `Cassette I/O'
+                JC      SHORT INIT_A20_1        ; Cannot happen, assume AT
+                MOV     AL, ES:[BX+5]           ; Get flags byte
+                TEST    AL, 00000010B           ; Micro Channel?
+                JZ      SHORT INIT_A20_1        ; No -> AT compatible
+;
+; It's a PS/2
+;
+                CALL    PS2_A20_OFF             ; Turn off A20
+                LEA     BX, PS2_A20_ON          ; Why? HIMEM.SYS does
+                LEA     DX, PS2_A20_OFF
+                JMP     SHORT INIT_A20_SET
+
+;
+; It's an AT compatible machine
+;
+INIT_A20_1:     LEA     BX, AT_A20_ON
+                LEA     DX, AT_A20_OFF
+
+INIT_A20_SET:   CMP     VCPI_FLAG, FALSE        ; VCPI ?
+                JE      SHORT INIT_A20_SET_1    ; No  -> skip
+                LEA     BX, NO_A20_ON           ; Don't enable A20
+                LEA     DX, NO_A20_OFF          ; Don't disable A20
+INIT_A20_SET_1: MOV     A20_ON_JMP, BX
+                MOV     A20_OFF_JMP, DX
+                POP     ES
+                RET
+INIT_A20        ENDP
+
+
+DATA_8042       =       60H                     ; Keyboard processor
+STATUS_8042     =       64H                     ; Keyboard processor
+
+;
+; Enable address line A20
+;
+; Note: disables interrupts
+;
+                ASSUME  DS:SV_DATA
+A20_ON          PROC    NEAR
+                PUSH    AX
+                CLI
+                CALL    A20_ON_JMP
+                MOV     A20_FLAG, NOT FALSE
+                POP     AX
+                RET
+A20_ON          ENDP
+
+;
+; Disable address line A20
+;
+; Note: disables interrupts
+;
+                ASSUME  DS:SV_DATA
+A20_OFF         PROC    NEAR
+                PUSH    AX
+                CLI
+                CALL    A20_OFF_JMP
+                MOV     A20_FLAG, FALSE
+                POP     AX
+                RET
+A20_OFF         ENDP
+
+;
+; Don't enable address line A20
+;
+NO_A20_ON       PROC    NEAR
+                RET
+NO_A20_ON       ENDP
+
+;
+; Don't disable address line A20
+;
+NO_A20_OFF      PROC    NEAR
+                RET
+NO_A20_OFF      ENDP
+
+;
+; Enable address line A20 (AT compatible)
+;
+AT_A20_ON       PROC    NEAR
+                MOV     AH, 0DFH
+                CALL    AT_SET_A20
+                RET
+AT_A20_ON       ENDP
+
+;
+; Disable address line A20 (AT compatible)
+;
+AT_A20_OFF      PROC    NEAR
+                MOV     AH, 0DDH
+                CALL    AT_SET_A20
+                RET
+AT_A20_OFF      ENDP
+
+
+;
+; Enable address line A20 (PS/2)
+;
+PS2_A20_ON      PROC    NEAR
+                IN      AL, 92H
+                OR      AL, 02H
+                OUT     92H, AL
+                RET
+PS2_A20_ON      ENDP
+
+
+;
+; Disable address line A20 (PS/2)
+;
+PS2_A20_OFF     PROC    NEAR
+                IN      AL, 92H
+                AND     AL, NOT 02H
+                OUT     92H, AL
+                RET
+PS2_A20_OFF     ENDP
+
+
+;
+; Enable address line A20 (Inboard 386/PC)
+;
+INBOARD_A20_ON  PROC    NEAR
+                MOV     AL, 0DFH
+                OUT     60H, AL
+                RET
+INBOARD_A20_ON  ENDP
+
+
+;
+; Disable address line A20 (Inboard 386/PC)
+;
+INBOARD_A20_OFF PROC    NEAR
+                MOV     AL, 0DDH
+                OUT     60H, AL
+                RET
+INBOARD_A20_OFF ENDP
+
+
+;
+; Enable/disable address line A20 (AT compatible)
+;
+; In:   AL=0DDH Disable
+;       AL=0DFH Enable
+;
+AT_SET_A20      PROC    NEAR
+                PUSH    CX
+                CALL    READY_8042
+                JNZ     SHORT AT_SET_A20_END
+                MOV     AL, 0D1H                ; Write output port
+                OUT     STATUS_8042, AL
+                CALL    READY_8042
+                JNZ     SHORT AT_SET_A20_END
+                MOV     AL, AH                  ; Data
+                OUT     DATA_8042, AL
+                CALL    READY_8042
+                MOV     AL, 0FFH                ; Pulse nothing (just wait)
+                OUT     STATUS_8042, AL
+                CALL    READY_8042
+AT_SET_A20_END: POP     CX
+                RET
+AT_SET_A20      ENDP
+
+
+;
+; Wait until we can send a command to the keyboard controller
+;
+READY_8042      PROC    NEAR
+                XOR     CX, CX
+                TALIGN  4                       ; Avoid surprises
+READY_1:        IN      AL, STATUS_8042
+                TEST    AL, 02H                 ; Input buffer full?
+                LOOPNZ  READY_1                 ; Yes -> wait
+                RET
+READY_8042      ENDP
+
+
+FAST_IO_DELAY   MACRO
+                LOCAL   L1, L2
+                JMP     SHORT L1
+L1:             JMP     SHORT L2
+L2:
+                ENDM
+
+;
+; Enable address line A20 (fast)
+;
+FAST_A20_ON     PROC    NEAR
+                MOV     AL, 0D1H
+                OUT     STATUS_8042, AL
+                FAST_IO_DELAY
+                MOV     AL, 0DFH                ; Enable
+                OUT     DATA_8042, AL
+                RET
+FAST_A20_ON     ENDP
+
+;
+; Disable address line A20 (fast)
+;
+FAST_A20_OFF    PROC    NEAR
+                MOV     AL, 0D1H
+                OUT     STATUS_8042, AL
+                FAST_IO_DELAY
+                MOV     AL, 0DDH                ; Disable
+                OUT     DATA_8042, AL
+                RET
+FAST_A20_OFF    ENDP
+
+
+;
+; Enable address line A20 (Fujitsu FMR70)
+;
+FMR70_A20_ON    proc    near
+                MOV     AL, 00110000B
+                OUT     20H, AL
+                RET
+FMR70_A20_ON    ENDP
+                
+;
+; Disable address line A20 (Fujitsu FMR70)
+;
+FMR70_A20_OFF   PROC    NEAR
+                MOV     AL, 0
+                OUT     20H, AL
+                RET
+FMR70_A20_OFF   ENDP
+
+
+;
+; Enable address line A20 (NEC PC-98)
+;
+PC98_A20_ON     PROC    NEAR
+                MOV     AL, 0
+                OUT     0F2H, AL
+                RET
+PC98_A20_ON     ENDP
+                
+;
+; Disable address line A20 (NEC PC-98)
+;
+PC98_A20_OFF    PROC    NEAR
+                MOV     AL, 0FFH
+                OUT     0F2H, AL
+                RET
+PC98_A20_OFF    ENDP
+
+
+;
+; Enable address line A20 (patched)
+;
+PATCH_A20_ON    PROC    NEAR
+                RET
+                DB      "PATCH_A20_ON "
+                RET
+PATCH_A20_ON    ENDP
+
+
+;
+; Disable address line A20 (patched)
+;
+PATCH_A20_OFF   PROC    NEAR
+                RET
+                DB      "PATCH_A20_OFF"
+                RET
+PATCH_A20_OFF   ENDP
+
+
+;
+;
+;
+                ASSUME  DS:SV_DATA
+CLEANUP_A20     PROC    NEAR
+                CMP     A20_FLAG, FALSE
+                JE      SHORT CA20_RET
+                CALL    A20_OFF
+CA20_RET:       RET
+CLEANUP_A20     ENDP
+
+
+;
+; Check if A20 is enabled
+;
+; Returns AX=0 iff A20 is disabled
+;
+; Note: disables interrupts
+;
+                ASSUME  DS:SV_DATA
+
+CHECK_A20       PROC    NEAR
+                PUSH    DS
+                PUSH    ES
+                MOV     AX, 1                   ; Assume A20 is enabled
+                CMP     VCPI_FLAG, FALSE        ; VCPI active?
+                JNE     SHORT CKA20_RET         ; Yes -> done
+                MOV     AX, 0000H
+                MOV     DS, AX                  ; We compare data at 0000:0000
+                ASSUME  DS:NOTHING
+                MOV     AX, 0FFFFH              ; to data at FFFF:0010
+                MOV     ES, AX
+                CLI                             ; Avoid unexpected things
+                MOV     AX, DS:[00H]            ; (Divide exception)
+                XOR     AX, ES:[10H]            ; Equal contents?
+                JNZ     SHORT CKA20_RET         ; No -> A20 on (or no mem)
+                NOT     WORD PTR DS:[00H]       ; Change word at 0000:0000
+                MOV     AX, DS:[00H]            ; Get new value
+                XOR     AX, ES:[10H]            ; Still equal contents?
+                NOT     WORD PTR DS:[00H]       ; Restore word at 0000:0000
+CKA20_RET:      POP     ES
+                POP     DS
+                RET
+CHECK_A20       ENDP
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/a20.inc
===================================================================
--- trunk/src/emx/src/dos/a20.inc	(revision 18)
+++ trunk/src/emx/src/dos/a20.inc	(revision 18)
@@ -0,0 +1,38 @@
+;
+; A20.INC -- Control the A20 gate
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_DATA         SEGMENT
+
+                EXTRN   USE_A20_PATCH:BYTE
+                EXTRN   USE_FAST_A20:BYTE
+
+SV_DATA         ENDS
+
+INIT_CODE       SEGMENT
+
+                EXTRN   INIT_A20:NEAR, CLEANUP_A20:NEAR, CHECK_A20:NEAR
+                EXTRN   A20_ON:NEAR, A20_OFF:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/copying
===================================================================
--- trunk/src/emx/src/dos/copying	(revision 18)
+++ trunk/src/emx/src/dos/copying	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/dos/core.asm
===================================================================
--- trunk/src/emx/src/dos/core.asm	(revision 18)
+++ trunk/src/emx/src/dos/core.asm	(revision 18)
@@ -0,0 +1,447 @@
+;
+; CORE.ASM -- Dump core
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE OPRINT.INC
+                INCLUDE HEADERS.INC
+                INCLUDE PMINT.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+
+                PUBLIC  CORE_DUMP, CORE_MAIN, CORE_REGS_I, CORE_REGS_P
+
+SV_DATA         SEGMENT
+
+CORE_SIZE       DD      ?
+CORE_HANDLE     DD      ?
+
+;
+; User area header
+;
+U_HDR           USER_AREA <>
+
+FILL_BUF        DB      32 DUP (0)
+
+$CORE           DB      "core", 0
+
+$CORE_DUMPED    DB      "core dumped", CR, LF, 0
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Write "core" image file
+;
+; In:   BX      Pointer to process table entry
+;
+
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+CORE_DUMP       PROC    NEAR
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                LEA     EDX, $CORE
+                MOV     CX, 0
+                MOV     AH, 3CH
+                INT     21H
+                JC      SHORT CORE_DUMP_RET
+                PUSH    BX
+                CALL    CORE_MAIN
+                MOV     EBX, CORE_HANDLE
+                MOV     AH, 3EH
+                INT     21H
+                POP     BX
+                LEA     EDX, $CORE_DUMPED
+                CALL    OTEXT
+CORE_DUMP_RET:  POP     PROCESS_PTR
+                RET
+CORE_DUMP       ENDP
+
+
+;
+; Write a core image file
+;
+; In:   EAX     Handle
+;       BX      Pointer to process table entry
+;
+; Out:  CY      Error
+;       AX      Error code (CY)
+;
+; Note: This procedure assumes that the file has been rewound.
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+CORE_MAIN       PROC    NEAR
+                MOV     CORE_HANDLE, EAX
+                MOV     CORE_SIZE, 0
+                MOV     U_HDR.U_MAGIC, UMAGIC
+                MOV     U_HDR.U_AR0, USER_AREA.U_REGS + KERNEL_U_ADDR
+;
+; Set base and end fields
+;
+                MOV     EAX, [BX].P_DATA_OFF
+                MOV     EDX, [BX].P_BSS_OFF
+                ADD     EDX, [BX].P_BSS_SIZE
+                MOV     U_HDR.U_DATA_BASE, EAX
+                MOV     U_HDR.U_DATA_END, EDX
+                MOV     EAX, [BX].P_INIT_BRK
+                MOV     EDX, [BX].P_BRK
+                MOV     U_HDR.U_HEAP_BASE, EAX
+                MOV     U_HDR.U_HEAP_END, EDX
+                MOV     U_HDR.U_HEAP_BRK, EDX
+                MOV     EAX, [BX].P_STACK_ADDR
+                MOV     EDX, EAX
+                SUB     EAX, [BX].P_STACK_SIZE
+                MOV     U_HDR.U_STACK_BASE, EAX
+                MOV     U_HDR.U_STACK_END, EDX
+                MOV     EAX, U_HDR.U_UESP
+                MOV     U_HDR.U_STACK_LOW, EAX
+                ASSUME  BX:NOTHING
+;
+; Set offsets
+;
+                MOV     U_HDR.U_DATA_OFF, U_OFFSET
+                MOV     EAX, U_HDR.U_DATA_END
+                SUB     EAX, U_HDR.U_DATA_BASE
+                CALL    ROUND_PAGE
+                ADD     EAX, U_HDR.U_DATA_OFF
+                MOV     U_HDR.U_HEAP_OFF, EAX
+                MOV     EAX, U_HDR.U_HEAP_BRK
+                SUB     EAX, U_HDR.U_HEAP_BASE
+                CALL    ROUND_PAGE
+                ADD     EAX, U_HDR.U_HEAP_OFF
+                MOV     U_HDR.U_STACK_OFF, EAX
+;
+; Write header
+;
+                LEA     ESI, U_HDR
+                MOV     ECX, SIZE U_HDR
+                MOV     AX, DS
+                CALL    CORE_WRITE
+                JC      SHORT CORE_MAIN_RET
+;
+; Write data
+;
+                MOV     EAX, U_HDR.U_DATA_OFF
+                CALL    CORE_FILL
+                JNZ     SHORT CORE_MAIN_RET
+                MOV     ESI, U_HDR.U_DATA_BASE
+                MOV     ECX, U_HDR.U_DATA_END
+                SUB     ECX, ESI
+                JBE     SHORT CM_10
+                MOV     AX, U_HDR.U_DS
+                CALL    CORE_WRITE
+                JC      SHORT CORE_MAIN_RET
+CM_10:
+;
+; Write heap
+;
+                MOV     EAX, U_HDR.U_HEAP_OFF
+                CALL    CORE_FILL
+                JNZ     SHORT CORE_MAIN_RET
+                MOV     ESI, U_HDR.U_HEAP_BASE
+                MOV     ECX, U_HDR.U_HEAP_BRK
+                SUB     ECX, ESI
+                JBE     SHORT CM_11
+                MOV     AX, U_HDR.U_DS
+                CALL    CORE_WRITE
+                JC      SHORT CORE_MAIN_RET
+CM_11:
+;
+; Write stack
+;
+                MOV     EAX, U_HDR.U_STACK_OFF
+                CALL    CORE_FILL
+                JNZ     SHORT CORE_MAIN_RET
+                MOV     ESI, U_HDR.U_STACK_LOW
+                MOV     ECX, U_HDR.U_STACK_END
+                SUB     ECX, ESI
+                JBE     SHORT CM_12
+                MOV     AX, U_HDR.U_SS
+                CALL    CORE_WRITE
+                JC      SHORT CORE_MAIN_RET
+CM_12:          XOR     AX, AX
+CORE_MAIN_RET:  RET
+CORE_MAIN       ENDP
+
+
+
+;
+; Write memory area to core file
+;
+; In:   AX:ESI  Pointer to memory area
+;       ECX     Size of memory area
+;
+; Out:  CY      Error
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+CORE_WRITE      PROC    NEAR
+                PUSH    EBX
+                PUSH    EDX
+                ADD     CORE_SIZE, ECX
+                MOV     EDX, ESI
+                MOV     EBX, CORE_HANDLE
+                PUSH    DS
+                ASSUME  DS:NOTHING
+                MOV     DS, AX
+                MOV     AH, 40H
+                INT     21H
+                POP     DS
+                ASSUME  DS:SV_DATA
+                JC      SHORT CORE_WRITE_1
+                CMP     EAX, ECX
+                STC
+                JNE     SHORT CORE_WRITE_1
+                CLC
+CORE_WRITE_1:   POP     EDX
+                POP     EBX
+                RET
+CORE_WRITE      ENDP
+
+
+;
+; Fill core file
+;
+; In:   EAX     Fill file up to this position
+;
+; Out:  EAX     DOS error code
+;       CY      Error
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+CORE_FILL       PROC    NEAR
+                PUSH    ECX
+                SUB     EAX, CORE_SIZE
+                JBE     SHORT CORE_FILL_OK
+                MOV     ECX, EAX
+CORE_FILL_1:    PUSH    ECX
+                CMP     ECX, SIZE FILL_BUF
+                JBE     SHORT CORE_FILL_2
+                MOV     ECX, SIZE FILL_BUF
+CORE_FILL_2:    PUSH    ESI
+                LEA     ESI, FILL_BUF
+                MOV     AX, DS
+                CALL    CORE_WRITE
+                POP     ESI
+                JC      SHORT CORE_FILL_ERR
+                MOV     EAX, ECX
+                POP     ECX
+                SUB     ECX, EAX
+                JNBE    SHORT CORE_FILL_1
+CORE_FILL_OK:   XOR     EAX, EAX
+CORE_FILL_RET:  POP     ECX
+                RET
+
+CORE_FILL_ERR:  POP     ECX
+                JMP     SHORT CORE_FILL_RET
+CORE_FILL       ENDP
+
+
+
+;
+; Copy registers from stack to U_HDR structure for CORE_MAIN
+;
+; Must not change BX
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+CORE_REGS_I     PROC    NEAR
+                PUSH    EAX
+                PUSH    ECX
+                PUSH    ESI
+                PUSH    EDI
+                LEA     EDI, U_HDR
+                MOV_ES_DS
+                MOV     ECX, SIZE U_HDR
+                XOR     AL, AL
+                REP     STOS BYTE PTR ES:[EDI]
+                IRP     X, <EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP>
+                MOV     EAX, I_&X
+                MOV     U_HDR.U_&X, EAX
+                ENDM
+                MOV     EAX, I_EFLAGS
+                MOV     U_HDR.U_EFL, EAX
+                IRP     X, <CS, DS, ES, FS, GS, SS>
+                MOV     AX, I_&X
+                MOV     U_HDR.U_&X, AX
+                ENDM
+                MOV     EAX, U_HDR.U_ESP
+                MOV     U_HDR.U_UESP, EAX
+                ; TODO: 387
+
+;
+; Unwind the stack for syscalls.  Calling sequence for a syscall:
+;
+;       mov     al, syscall_no
+;       mov     ah, 7fh
+;       call    __syscall
+;       ...
+;
+; __syscall:                    ; at 1000CH
+;       call    __dos_syscall
+;       ...
+
+; __dos_syscall:                ; anywhere
+;       int     21h
+;       ret
+;
+                MOV     EDI, U_HDR.U_EIP
+                MOV     ESI, U_HDR.U_ESP
+                MOVZX   EDX, I_CS               ; Get limit of CS
+                LSL     EDX, EDX
+                CMP     EDI, 10000H + 2         ; Avoid bombing for invalid EIP
+                JB      NO_UPDATE
+                MOV     EAX, EDI
+                INC     EAX
+                CMP     EAX, EDX
+                JAE     NO_UPDATE
+                MOV     ES, I_CS                ; Get segment registers
+                MOV     FS, I_SS
+                CMP     WORD PTR ES:[EDI-2], 021CDH     ; Check for INT 21H
+                JNE     SHORT UPDATE
+                CMP     BYTE PTR ES:[EDI], 0C3H         ; Check for RET
+                JNE     SHORT UPDATE
+                CMP     DWORD PTR FS:[ESI], 1000CH + 5  ; Check return address
+                JNE     SHORT UPDATE
+                ADD     ESI, 4                  ; Undo "call __dos_syscall"
+                MOV     EDI, FS:[ESI]           ; Undo "call __syscall"
+                ADD     ESI, 4
+;
+; Now check for specific syscalls:
+;
+;        Name          ³  AL   ³ PUSH
+;        ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ
+;        __core        ³  11H  ³ 1 (EBX)
+;        __raise       ³  0EH  ³ 0
+;        __signal      ³  0CH  ³ 0
+;        __sigprocmask ³  37H  ³ 1 (EBX)
+;
+                CMP     EDI, 10000H + 9         ; Avoid bombing for invalid
+                JB      SHORT NO_UPDATE         ; return address
+                CMP     EDI, EDX
+                JAE     SHORT NO_UPDATE
+                CMP     BYTE PTR ES:[EDI-9], 0B0H    ; Check for "MOV AL,"
+                JNE     SHORT UPDATE
+                MOV     AL, BYTE PTR ES:[EDI-8]
+                CMP     AL, 0CH                 ; __signal
+                JE      SHORT HANDLE_SYSCALL
+                CMP     AL, 0EH                 ; __raise
+                JE      SHORT HANDLE_SYSCALL
+                CMP     AL, 11H                 ; __core
+                JE      SHORT HANDLE_SYSCALL
+                CMP     AL, 37H                 ; __sigprocmask
+                JNE     SHORT UPDATE
+HANDLE_SYSCALL: CMP     WORD PTR ES:[EDI-7], 07FB4H  ; Check for "MOV AH, 7FH"
+                JNE     SHORT UPDATE
+                CMP     BYTE PTR ES:[EDI-5], 0e8H    ; Check for "CALL"
+                JNE     SHORT UPDATE
+;
+; It's one of the above syscalls.  Remove any arguments.
+;
+                MOV     AL, ES:[EDI-8]
+                CMP     AL, 11H                 ; __core
+                JE      SHORT ONE_ARG
+                CMP     AL, 37H                 ; __sigprocmask
+                JNE     SHORT NO_ARGS
+ONE_ARG:        ADD     ESI, 4                  ; Remove one argument word
+NO_ARGS:        MOV     EDI, FS:[ESI]           ; Undo "CALL __raise" etc.
+                ADD     ESI, 4
+;
+; Update EIP and ESP
+;
+UPDATE:         MOV     U_HDR.U_EIP, EDI
+                MOV     U_HDR.U_ESP, ESI
+NO_UPDATE:      POP     EDI
+                POP     ESI
+                POP     ECX
+                POP     EAX
+                RET
+                ASSUME  BP:NOTHING
+CORE_REGS_I     ENDP
+
+;
+; Copy registers from process table entry to U_HDR structure for CORE_MAIN
+;
+; In:   BX      Pointer to process table entry
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+CORE_REGS_P     PROC    NEAR
+                PUSH    EAX
+                PUSH    ECX
+                PUSH    EDI
+                LEA     EDI, U_HDR
+                MOV_ES_DS
+                MOV     ECX, SIZE U_HDR
+                XOR     AL, AL
+                REP     STOS BYTE PTR ES:[EDI]
+                IRP     X, <EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP>
+                MOV     EAX, [BX].P_&X
+                MOV     U_HDR.U_&X, EAX
+                ENDM
+                MOV     EAX, [BX].P_EFLAGS
+                MOV     U_HDR.U_EFL, EAX
+                IRP     X, <CS, DS, ES, FS, GS, SS>
+                MOV     AX, [BX].P_&X
+                MOV     U_HDR.U_&X, AX
+                ENDM
+                MOV     EAX, U_HDR.U_ESP
+                MOV     U_HDR.U_UESP, EAX
+        ;...387
+                POP     EDI
+                POP     ECX
+                POP     EAX
+                RET
+                ASSUME  BX:NOTHING
+CORE_REGS_P     ENDP
+
+;
+; Round up to multiple of page size
+;
+; In:   EAX     Value to be rounded
+;
+; Out:  EAX     Rounded value
+;
+                TALIGN  4
+                ASSUME  DS:NOTHING
+ROUND_PAGE      PROC    NEAR
+                DEC     EAX
+                AND     EAX, NOT 0FFFH
+                ADD     EAX, 1000H
+                RET
+ROUND_PAGE      ENDP
+
+
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/core.inc
===================================================================
--- trunk/src/emx/src/dos/core.inc	(revision 18)
+++ trunk/src/emx/src/dos/core.inc	(revision 18)
@@ -0,0 +1,33 @@
+;
+; CORE.INC -- Dump core
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_CODE         SEGMENT
+
+                EXTRN   CORE_DUMP:NEAR
+                EXTRN   CORE_MAIN:NEAR
+                EXTRN   CORE_REGS_I:NEAR
+                EXTRN   CORE_REGS_P:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/debug.asm
===================================================================
--- trunk/src/emx/src/dos/debug.asm	(revision 18)
+++ trunk/src/emx/src/dos/debug.asm	(revision 18)
@@ -0,0 +1,3101 @@
+;
+; DEBUG.ASM -- Built-in debugger
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE EXCEPT.INC
+                INCLUDE OPRINT.INC
+                INCLUDE DISASM.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE SYMBOLS.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE PAGING.INC
+                INCLUDE PMINT.INC
+                INCLUDE TABLES.INC
+                INCLUDE PMIO.INC
+                INCLUDE SWAPPER.INC
+                INCLUDE FILEIO.INC
+                INCLUDE UTILS.INC
+
+                PUBLIC  STEP_FLAG, DEBUG_AVAIL, DEBUG_SER_FLAG, DEBUG_SER_PORT
+                PUBLIC  DEBUG_EXCEPTION, SET_BREAKPOINT, INS_BREAKPOINTS
+                PUBLIC  DEBUG_RESUME, DEBUG_STEP, DEBUG_QUIT, DEBUG_INIT
+
+BP_INACTIVE     =       0                       ; Entry unused
+BP_BREAKPOINT   =       1                       ; Code breakpoint
+BP_WATCHPOINT_R =       2                       ; R/W watchpoint
+BP_WATCHPOINT_W =       3                       ; W watchpoint
+BP_WATCHPOINT_X =       4                       ; X watchpoint
+
+BREAKPOINT      STRUCT
+BP_TYPE         DB      ?                       ; Breakpoint type (see above)
+BP_LEN          DB      ?                       ; Watchpoint length
+BP_SEL          DW      ?                       ; Selector
+BP_OFF          DD      ?                       ; Offset
+BP_ADDR         DD      ?                       ; Linear address
+BP_VAL          DD      ?                       ; Watchpoint: initial value
+BREAKPOINT      ENDS
+
+SV_DATA         SEGMENT
+
+DEBUG_SER_PORT  DW      02F8H                   ; COM2
+DEBUG_SER_FLAG  DB      FALSE
+
+STEP_FLAG       DB      FALSE
+DEBUG_AVAIL     DB      NOT FALSE
+
+DEBUG_SHOW_PC   DB      NOT FALSE
+DEBUG_STOP      DB      NOT FALSE
+GO_FLAG         DB      FALSE
+DEBUG_COUNT     DB      0
+FATAL           DB      ?
+DA_SYM_FLAG     DB      ?
+DA_EMPTY_FLAG   DB      ?
+NEXT_CS         DW      ?
+NEXT_EIP        DD      ?
+
+B_NEXT          DB      0
+B_COLUMN        DB      0
+
+                TALIGN  2
+BREAKPOINTS     BREAKPOINT 4 DUP (<BP_INACTIVE>)
+
+                TALIGN  2
+GCHAR           DW      B_CHAR
+GTEXT           DW      B_TEXT
+GDWORD          DW      B_DWORD
+GWORD           DW      B_WORD
+GBYTE           DW      B_BYTE
+GCRLF           DW      B_CRLF
+GINCHAR         DW      B_INCHAR
+DA_SYM_ADDR     DD      ?
+RANGE_SEL       DW      ?
+RANGE_OFF       DD      ?
+ADDR_LIN        DD      ?
+ADDR_ARG        DD      ?
+SEARCH_SEL      DW      ?
+SEARCH_OFF      DD      ?
+SEARCH_LEN      DD      ?
+SEARCH_SIZE     DD      ?
+ADDR_SEL        DW      ?
+ADDR_OFF        DD      ?
+ADDR_COUNT      DD      ?
+SEL_SEL         DW      ?
+SEL_COUNT       DW      ?
+U_LAST_SEL      DW      0
+U_LAST_OFF      DD      ?
+D_LAST_SEL      DW      0
+D_LAST_OFF      DD      ?
+WP_LEN          DB      ?
+WP_TYPE         DB      ?
+SKIP_FLAG       DB      FALSE
+WATCH_FAILURES  DB      ?
+XOFF            DB      FALSE
+LOOK_AHEAD      DB      0
+LIST_ALL        DB      FALSE
+
+SEARCH_BUF      DB      64 DUP (?)
+
+FLAG_TAB        DW      0001H
+                DB      "NCCY"
+                DW      0004H
+                DB      "PEPO"
+                DW      0010H
+                DB      "NAAC"
+                DW      0040H
+                DB      "NZZR"
+                DW      0080H
+                DB      "PLNG"
+                DW      0200H
+                DB      "DIEI"
+                DW      0400H
+                DB      "UPDN"
+                DW      0800H
+                DB      "NVOV"
+                DW      0000H
+
+R8              =       0
+R16             =       1
+R32             =       2
+
+REGISTER        MACRO   @NAME, @SIZE, @OFFSET
+                DB      @NAME, @SIZE, @OFFSET
+                ENDM
+
+REG_TAB         LABEL   BYTE
+                REGISTER "EFLAGS", R32, 52
+                REGISTER "EAX",    R32, 36
+                REGISTER "EBX",    R32, 24
+                REGISTER "ECX",    R32, 32
+                REGISTER "EDX",    R32, 28
+                REGISTER "ESI",    R32, 12
+                REGISTER "EDI",    R32,  8
+                REGISTER "EBP",    R32, 16
+                REGISTER "ESP",    R32, 56      ; See GET_REG
+                REGISTER "EIP",    R32, 44
+                REGISTER "AX",     R16, 36
+                REGISTER "BX",     R16, 24
+                REGISTER "CX",     R16, 32
+                REGISTER "DX",     R16, 28
+                REGISTER "SI",     R16, 12
+                REGISTER "DI",     R16,  8
+                REGISTER "BP",     R16, 16
+                REGISTER "SP",     R16, 56      ; See GET_REG
+                REGISTER "IP",     R16, 44
+                REGISTER "AL",     R8,  36
+                REGISTER "BL",     R8,  24
+                REGISTER "CL",     R8,  32
+                REGISTER "DL",     R8,  28
+                REGISTER "AH",     R8,  37
+                REGISTER "BH",     R8,  25
+                REGISTER "CH",     R8,  33
+                REGISTER "DH",     R8,  29
+                REGISTER "CS",     R16, 48
+                REGISTER "DS",     R16,  6
+                REGISTER "ES",     R16,  4
+                REGISTER "FS",     R16,  2
+                REGISTER "GS",     R16,  0
+                REGISTER "SS",     R16, 60      ; See GET_REG
+                REGISTER 0FFH,     0FFH, 0FFH
+
+$EXCEPT         DB      "Exception ", 0
+$CR2            DB      "  CR2=", 0
+$ERRCD          DB      "ERRCD=", 0
+$BREAKPOINT     DB      "Breakpoint ", 0
+$WATCHPOINT     DB      "Watchpoint ", 0
+$INPUT_ERROR    DB      "Input error", CR, LF, 0
+$INVALID_SEL    DB      "Invalid selector", CR, LF, 0
+$BEYOND_LIMIT   DB      "Offset beyond segment limit", CR, LF, 0
+$ALIGNMENT      DB      "Address not correctly aligned", CR, LF, 0
+$ADDR_FAILURE   DB      "GET_LIN failed", CR, LF, 0
+$PAGE_DIR       DB      "Page table not present", CR, LF, 0
+$PHYSICAL       DB      "physical=", 0
+$LINEAR         DB      "linear=", 0
+$EXTERNAL       DB      "external=", 0
+$LINE           DB      " line ", 0
+$RPL            DB      ": RPL=", 0
+$TI_GDT         DB      " GDT ", 0
+$TI_LDT         DB      " LDT ", 0
+$SEL_INVALID    DB      "invalid selector", 0
+$DPL            DB      " DPL=", 0
+$DATA           DB      "data segment", 0
+$CODE           DB      "code segment", 0
+$BASE           DB      " base=", 0
+$LIMIT          DB      " limit=", 0
+$SEL_16         DB      "16-bit ", 0
+$SEL_32         DB      "32-bit ", 0
+$INT            DB      "int gate", 0
+$TRAP           DB      "trap gate", 0
+$TSS            DB      "TSS", 0
+$CALL           DB      "call gate", 0
+$TASK           DB      "task gate", 0
+$LDT            DB      "LDT", 0
+$NULL           DB      "null", 0
+
+$INSBRK         DB      "INS_BREAKPOINTS", CR, LF, 0
+$CONTINUE       DB      "CONTINUE", CR, LF, 0
+$DO_STEP        DB      "DO_STEP", CR, LF, 0
+$DO_CALL        DB      "DO_CALL", CR, LF, 0
+$DEBUG_EXCEPTION DB     "DEBUG_EXCEPTION ", 0
+$RUN            DB      "RUN", CR, LF, 0
+
+$EMPTY          DB      "empty", 0
+$INFINITY       DB      "invalid or infinity", 0
+$ZERO           DB      "zero", 0
+$CW             DB      "CW=", 0
+$SW             DB      " SW=", 0
+$C3210          DB      " C3210=", 0
+
+$SWAP_FAULTS    DB      CR, LF
+                DB      "Swapper statistics: F=", 0
+$SWAP_READS     DB      " R=", 0
+$SWAP_WRITES    DB      " W=", 0
+$SNATCH_COUNT   DB      " N=", 0
+$SWAP_SIZE      DB      " S=", 0
+
+$INFO_TITLE     DB      "idx pid      ppid     file handles", CR, LF, 0
+;                        xx* xxxxxxxx xxxxxxxx xx
+
+INPUT_BUF       LABEL   BYTE
+DISASM_BUF      DB      80 DUP (?)
+SYMBOL_BUF      DB      80 DUP (?)
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                .386P
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Set EFLAGS for resuming current process (without stepping)
+;
+; In:   SS:BP   Interrupt/exception stack frame
+;
+                ASSUME  BP:PTR ISTACKFRAME
+DEBUG_RESUME    PROC    NEAR
+                AND     I_EFLAGS, NOT FLAG_TF
+                OR      I_EFLAGS, FLAG_RF
+                RET
+                ASSUME  BP:NOTHING
+DEBUG_RESUME    ENDP
+
+
+;
+; Set EFLAGS for single stepping current process
+;
+; In:   SS:BP   Interrupt/exception stack frame
+;
+                ASSUME  BP:PTR ISTACKFRAME
+DEBUG_STEP      PROC    NEAR
+                OR      I_EFLAGS, FLAG_TF
+                RET
+                ASSUME  BP:NOTHING
+DEBUG_STEP      ENDP
+
+
+;
+; Exception 1 (debug)
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+                TALIGN  2
+DEBUG_EXCEPTION PROC    NEAR
+                XOR     EAX, EAX
+                MOV     DR7, EAX                ; Disable break points
+                MOV     EBX, DR6                ; Copy DR6 to EBX
+                MOV     DR6, EAX                ; DR6 never cleared by 386
+                MOV     ECX, CR2                ; Copy CR2 to ECX
+                STI
+                CMP     DEBUG_FLAG, FALSE
+                JE      SHORT DEX0
+                LEA     EDX, $DEBUG_EXCEPTION
+                CALL    GTEXT
+                MOV     AX, I_CS
+                CALL    GWORD
+                MOV     AL, ":"
+                CALL    GCHAR
+                MOV     EAX, I_EIP
+                CALL    GDWORD
+                CALL    GCRLF
+DEX0:           MOV     AL, EXCEPT_NO           ; Get exception number
+                CMP     AL, 1                   ; Debugging exception?
+                JE      SHORT REASON1           ; Yes -> check for reason
+;
+; Fatal exception or breakpoint instruction
+;
+                LEA     EDX, $EXCEPT
+                CALL    GTEXT
+                CALL    GBYTE
+                MOV     AL, ":"
+                CALL    GCHAR
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AL, EXCEPT_NO
+                CALL    EXCEPT_NAME
+                CALL    GTEXT
+                CALL    GCRLF
+                MOV     FATAL, NOT FALSE
+                CMP     EXCEPT_NO, 3            ; INT 3
+                JNE     SHORT DEX1
+                MOV     FATAL, FALSE
+DEX1:           CMP     EXCEPT_NO, 8
+                JB      SHORT DEX9
+                CMP     EXCEPT_NO, 14
+                JA      SHORT DEX9
+                LEA     EDX, $ERRCD
+                CALL    GTEXT
+                MOV     EAX, I_ERRCD
+                CALL    GDWORD
+                CMP     EXCEPT_NO, 14           ; Page fault?
+                JNE     SHORT DEX8
+                LEA     EDX, $CR2
+                CALL    GTEXT
+                MOV     EAX, ECX
+                CALL    GDWORD
+DEX8:           CALL    GCRLF
+DEX9:           MOV     AL, 1                   ; New disassembly
+                JMP     SHOW
+
+;
+; Debugging exception
+;
+REASON1:        MOV     FATAL, FALSE            ; Not a fatal exception
+;
+; Check for X type watchpoints
+;
+                LEA     SI, BREAKPOINTS
+                ASSUME  SI:PTR BREAKPOINT
+                MOV     CX, 4
+                MOV     WATCH_FAILURES, 0
+                MOV     EDX, 0001H              ; B0
+CHECK_WP:       CMP     [SI].BP_TYPE, BP_WATCHPOINT_X
+                JNE     SHORT CHECK_WP9         ; Skip other entries
+                CALL    WATCH_GET               ; Read memory
+                CMP     EAX, [SI].BP_VAL        ; Changed?
+                JNE     SHORT CHECK_WP1         ; Yes -> hit
+                INC     WATCH_FAILURES          ; Increment number of non-hits
+                JMP     SHORT CHECK_WP9         ; Next entry
+CHECK_WP1:      OR      EBX, EDX                ; Set Bx bit of DR6
+CHECK_WP9:      SHL     EDX, 1                  ; Next Bx bit
+                ADD     SI, SIZE BREAKPOINT
+                LOOP    CHECK_WP
+                ASSUME  SI:NOTHING
+                TEST    EBX, 0FH                ; Any breakpoints or wpx hits?
+                JNZ     SHORT SHOW_BP           ; Yes -> display breakpoints
+                CMP     WATCH_FAILURES, 0       ; Any X watchpoint?
+                JNE     SHORT WATCH1            ; Yes -> continue?
+                MOV     AL, FALSE               ; Continue disassembly
+                JMP     SHOW                    ; Stop
+
+WATCH1:         CMP     GO_FLAG, FALSE          ; GO command?
+                JE      SHOW                    ; No  -> stop
+                JMP     CONTINUE                ; Continue program
+;
+; Display breakpoints
+;
+SHOW_BP:        LEA     SI, BREAKPOINTS
+                ASSUME  SI:PTR BREAKPOINT
+                MOV     CX, 4
+SHOW_BP1:       SHR     EBX, 1                  ; Test in turn B0, B1, B2, B3
+                JNC     SHORT SHOW_BP9          ; Not set -> skip
+                CMP     [SI].BP_TYPE, BP_INACTIVE ; B1 seems to be inaccurate
+                JE      SHORT SHOW_BP9
+                LEA     EDX, $BREAKPOINT        ; Breakpoint
+                CMP     [SI].BP_TYPE, BP_BREAKPOINT
+                JE      SHORT SHOW_BP2
+                LEA     EDX, $WATCHPOINT        ; Watchpoint
+SHOW_BP2:       CALL    GTEXT                   ; Display breakpoint type
+                MOV     AL, "4"
+                SUB     AL, CL
+                CALL    GCHAR                   ; Display breakpoint number
+                CALL    GCRLF
+SHOW_BP9:       ADD     SI, SIZE BREAKPOINT     ; Next breakpoint
+                LOOP    SHOW_BP1
+                ASSUME  SI:NOTHING
+                MOV     AL, 1                   ; New disassembly
+;
+; Show disassembled instruction
+;
+SHOW:           CMP     DEBUG_SHOW_PC, FALSE    ; Disassemble?
+                JE      SHORT DEBUG_01          ; No  -> skip
+                CALL    TRACE_DISASM            ; Show current instruction
+DEBUG_01:       CMP     FATAL, FALSE            ; Fatal exception?
+                JNE     STOP1                   ; Yes -> stop
+                CMP     DEBUG_STOP, FALSE       ; Non-stop mode?
+                JE      DO_STEP                 ; Yes -> continue
+                CMP     DEBUG_COUNT, 0          ; Multiple steps?
+                JE      SHORT STOP1             ; No  -> stop
+                DEC     DEBUG_COUNT             ; Another step?
+                JNZ     DO_STEP                 ; Yes -> continue
+;
+; Stop program, wait for command
+;
+STOP1:          MOV     DEBUG_COUNT, 0          ; Disable multiple steps
+                MOV     DEBUG_STOP, NOT FALSE   ; Disable non-stop mode
+                MOV     DEBUG_SHOW_PC, NOT FALSE ; Enable disassembly
+                MOV     BREAKPOINTS[0].BP_TYPE, BP_INACTIVE ; Delete bp 0
+                MOV     GO_FLAG, FALSE          ; No GO command active
+;
+; Wait for command
+;
+KEY:            CALL    GINCHAR
+                OR      AL, AL                  ; Extended key code?
+                JZ      FKEY                    ; Yes ->
+;
+; Check for digits
+;
+                MOV     AH, 10
+                CMP     AL, "0"                 ; 10 steps?
+                JE      CMD_MULT                ; Yes ->
+                JB      SHORT KEY1
+                MOV     AH, AL
+                SUB     AH, "0"
+                CMP     AL, "9"                 ; Multiple steps (1-9) ?
+                JBE     CMD_MULT                ; Yes ->
+;
+; Check for other commands
+;
+KEY1:           CALL    UPPER                   ; Convert to upper case
+                CMP     AL, "."                 ; Registers
+                JE      CMD_DOT
+                CMP     AL, ":"                 ; Silent
+                JE      CMD_SILENT
+                CMP     AL, "A"                 ; Address
+                JE      CMD_ADDR
+                CMP     AL, "B"                 ; Breakpoint
+                JE      CMD_BREAK
+                CMP     AL, "C"                 ; Call
+                JE      CMD_CALL
+                CMP     AL, "D"                 ; Display
+                JE      CMD_DISPLAY
+                CMP     AL, "F"                 ; 387 status
+                JE      CMD_387
+                CMP     AL, "G"                 ; Go
+                JE      CMD_GO
+                CMP     AL, "I"                 ; Info
+                JE      CMD_INFO
+                CMP     AL, "K"                 ; Kill
+                JE      CMD_KILL
+                CMP     AL, "L"                 ; Selector
+                JE      CMD_SELECTOR
+                CMP     AL, "N"                 ; Non-stop
+                JE      SHORT CMD_NONSTOP
+                CMP     AL, "Q"                 ; Quit
+                JE      CMD_QUIT
+                CMP     AL, "R"                 ; Register
+                JE      CMD_REG
+                CMP     AL, "S"                 ; Search
+                JE      CMD_SEARCH
+                CMP     AL, "U"                 ; Unassemble
+                JE      CMD_UNASSEMBLE
+                CMP     AL, "V"                 ; Virtual
+                JE      CMD_VIRT
+                CMP     AL, "W"                 ; Watchpoint
+                JE      CMD_WATCH
+                CMP     AL, "X"                 ; Symbol
+                JE      CMD_SYM
+                CMP     AL, " "                 ; Step
+                JE      CMD_STEP
+BAD_KEY:        MOV     AL, 07H
+                CALL    GCHAR
+                JMP     KEY                     ; Wait for another command
+
+FKEY:           CALL    GINCHAR                 ; Get second code
+                CMP     AL, 3CH                 ; F2
+                JE      CMD_DOT
+                CMP     AL, 3FH                 ; F5?
+                JE      CONTINUE                ; Yes -> continue program
+                CMP     AL, 42H                 ; F8
+                JE      DO_STEP
+                CMP     AL, 44H                 ; F10
+                JE      DO_CALL
+                JMP     SHORT BAD_KEY           ; Ring bell
+
+;
+; Non-stop single stepping mode
+;
+CMD_NONSTOP:    MOV     DEBUG_STOP, FALSE       ; Set non-stop mode
+                JMP     DO_STEP                 ; Continue program
+
+;
+; Display registers
+;
+CMD_DOT:        CALL    GCRLF                   ; New line
+                CALL    REG_DUMP                ; Display registers
+                MOV     AL, 1                   ; New disassembly
+                JMP     SHOW                    ; Display current instruction
+
+;
+; Multiple steps
+;
+CMD_MULT:       MOV     DEBUG_COUNT, AH         ; Set number of steps
+                JMP     DO_STEP                 ; Continue program
+
+;
+; Silent command
+;
+CMD_SILENT:     NOT     DEBUG_SHOW_PC           ; Toggle silent flag
+                JMP     KEY                     ; Command loop
+
+;
+; Go command
+;
+CMD_GO:         CALL    INPUT                   ; Input arguments
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JZ      SHORT CONTINUE
+                MOV     DX, I_CS
+                CALL    GET_ADDR
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+;
+; Breakpoint 0 at DX:EAX and continue program
+;
+                CALL    SET_BREAKPOINT          ; Set breakpoint 0 at DX:EAX
+                JNZ     INPUT_ERROR             ; Error -> display message
+;
+; Insert breakpoints and continue program
+;
+CONTINUE:       CMP     DEBUG_FLAG, FALSE
+                JE      SHORT CONT_0
+                LEA     EDX, $CONTINUE
+                CALL    GTEXT
+CONT_0:         MOV     GO_FLAG, NOT FALSE      ; GO command executing
+                CALL    DEBUG_RESUME            ; Resume program, don't step
+                CALL    INS_BREAKPOINTS         ; Insert breakpoints
+                JMP     RUN                     ; Continue program
+
+
+;
+; Watchpoint command
+;
+CMD_WATCH:      CALL    INPUT                   ; Input arguments
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE             ; Any arguments?
+                JZ      CMD_BREAK_SHOW          ; No  -> display breakpoints
+                CALL    FETCH                   ; Fetch character (length)
+                JZ      INPUT_ERROR             ; End of line -> error
+                MOV     AH, 00H
+                CMP     AL, "B"
+                JE      SHORT CMD_WATCH_1
+                MOV     AH, 01H
+                CMP     AL, "W"
+                JE      SHORT CMD_WATCH_1
+                MOV     AH, 03H
+                CMP     AL, "D"
+                JNE     INPUT_ERROR
+CMD_WATCH_1:    MOV     WP_LEN, AH
+                CALL    FETCH                   ; Fetch character (type)
+                JZ      INPUT_ERROR
+                MOV     AH, BP_WATCHPOINT_R
+                CMP     AL, "R"
+                JE      SHORT CMD_WATCH_2
+                MOV     AH, BP_WATCHPOINT_W
+                CMP     AL, "W"
+                JE      SHORT CMD_WATCH_2
+                MOV     AH, BP_WATCHPOINT_X
+                CMP     AL, "X"
+                JNE     INPUT_ERROR
+CMD_WATCH_2:    MOV     WP_TYPE, AH
+                CALL    SKIP
+                MOV     DX, I_DS
+                CALL    GET_ADDR                ; Get address
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                MOV     BH, WP_LEN
+                MOV     BL, WP_TYPE
+                TEST    AL, BH
+                JNZ     ALIGNMENT_ERROR
+                CALL    SET_WATCHPOINT          ; Set watchpoint
+                JNZ     INPUT_ERROR
+                CALL    SHOW_BREAKPOINT
+                JMP     KEY                     ; Command loop
+
+;
+; Breakpoint command
+;
+CMD_BREAK:      CALL    INPUT                   ; Input arguments
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE             ; Any arguments?
+                JZ      CMD_BREAK_SHOW          ; No  -> display breakpoints
+                MOV     DX, I_CS
+                CALL    GET_ADDR                ; Get address
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                MOV     BH, 0
+                MOV     BL, BP_BREAKPOINT
+                CALL    SET_WATCHPOINT          ; Set breakpoint
+                JNZ     INPUT_ERROR
+                CALL    SHOW_BREAKPOINT
+                JMP     KEY                     ; Command loop
+
+CMD_BREAK_SHOW: LEA     SI, BREAKPOINTS
+                MOV     CX, 4
+CBS_1:          CALL    SHOW_BREAKPOINT
+                ADD     SI, SIZE BREAKPOINT
+                LOOP    CBS_1
+                JMP     KEY
+
+;
+; Delete breakpoint
+;
+CMD_KILL:       CALL    INPUT                   ; Input arguments
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE             ; Any arguments?
+                JZ      CMD_BREAK_SHOW          ; No  -> display breakpoints
+                CALL    FETCH                   ; Fetch character (number)
+                JZ      INPUT_ERROR             ; End of line -> error
+                SUB     AL, "0"
+                CMP     AL, 3
+                JA      INPUT_ERROR
+                MOV     AH, SIZE BREAKPOINT
+                MUL     AH
+                LEA     SI, BREAKPOINTS
+                ADD     SI, AX
+                CALL    SKIP
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                MOV     (BREAKPOINT PTR [SI]).BP_TYPE, BP_INACTIVE
+                JMP     KEY
+
+
+;
+; Display breakpoint entry
+;
+; In:   DS:SI   Pointer to breakpoint entry
+;
+                ASSUME  SI:PTR BREAKPOINT
+SHOW_BREAKPOINT PROC    NEAR
+                CMP     [SI].BP_TYPE, BP_INACTIVE
+                JE      SBP_RET
+                LEA     AX, BREAKPOINTS
+                SUB     AX, SI
+                NEG     AX
+                MOV     BX, SIZE BREAKPOINT
+                XOR     DX, DX
+                DIV     BX
+                ADD     AL, "0"
+                CALL    GCHAR
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AL, "B"
+                CMP     [SI].BP_TYPE, BP_BREAKPOINT
+                JE      SHORT SBP_1
+                MOV     AL, "R"
+                CMP     [SI].BP_TYPE, BP_WATCHPOINT_R
+                JE      SHORT SBP_1
+                MOV     AL, "W"
+                CMP     [SI].BP_TYPE, BP_WATCHPOINT_W
+                JE      SHORT SBP_1
+                MOV     AL, "X"
+                CMP     [SI].BP_TYPE, BP_WATCHPOINT_X
+                JE      SHORT SBP_1
+                MOV     AL, "?"
+SBP_1:          CALL    GCHAR
+                CMP     AL, "B"
+                MOV     AL, " "
+                JE      SHORT SBP_2
+                MOV     AL, "B"
+                CMP     [SI].BP_LEN, 00H
+                JE      SHORT SBP_2
+                MOV     AL, "W"
+                CMP     [SI].BP_LEN, 01H
+                JE      SHORT SBP_2
+                MOV     AL, "D"
+                CMP     [SI].BP_LEN, 03H
+                JE      SHORT SBP_2
+                MOV     AL, "?"
+SBP_2:          CALL    GCHAR
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AX, [SI].BP_SEL
+                CALL    GWORD
+                MOV     AL, ":"
+                CALL    GCHAR
+                MOV     EAX, [SI].BP_OFF
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     EAX, [SI].BP_ADDR
+                CALL    GDWORD
+                CALL    GCRLF
+SBP_RET:        RET
+                ASSUME  SI:NOTHING
+SHOW_BREAKPOINT ENDP
+
+
+;
+; Unassemble
+;
+CMD_UNASSEMBLE: CALL    INPUT
+                JC      INPUT_ERROR
+                MOV     DX, U_LAST_SEL
+                OR      DX, DX
+                JZ      SHORT UAS01
+                CALL    END_OF_LINE
+                MOV     EAX, U_LAST_OFF
+                JZ      UAS02
+UAS01:          MOV     DX, I_CS
+                CALL    GET_ADDR
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+UAS02:          VERR    DX
+                JNZ     INVALID_SEL
+                MOV     FS, DX
+                MOV     ESI, EAX
+                MOV     CX, 16
+                MOV     DA_EMPTY_FLAG, FALSE
+UAS1:           CMP     DA_EMPTY_FLAG, FALSE
+                JE      SHORT UAS2
+                MOV     DA_EMPTY_FLAG, FALSE
+                CALL    GCRLF
+                JMP     SHORT UAS3
+UAS2:           PUSH    CX
+                CALL    SHOW_DISASM
+                POP     CX
+UAS3:           LOOP    UAS1
+                MOV     U_LAST_SEL, FS
+                MOV     U_LAST_OFF, ESI
+                JMP     KEY
+
+CMD_DISPLAY:    CALL    INPUT
+                JC      INPUT_ERROR
+                MOV     DX, D_LAST_SEL
+                OR      DX, DX
+                JZ      SHORT DISP00
+                CALL    END_OF_LINE
+                MOV     EAX, D_LAST_OFF
+                MOV     ECX, 16
+                JZ      SHORT DISP02
+DISP00:         MOV     DX, I_DS
+                CALL    GET_ADDR
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JZ      SHORT DISP01
+                CALL    GET_RANGE_MORE
+                JC      ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                ADD     ECX, 15
+                SHR     ECX, 4
+                JMP     SHORT DISP02
+DISP01:         VERR    DX
+                JNZ     INVALID_SEL
+                MOV     ECX, 16
+DISP02:         MOV     FS, DX
+                MOV     ESI, EAX
+DISP10:         CALL    SHOW_DATA
+                ADD     ESI, 16
+                DEC     ECX
+                JNZ     DISP10
+                MOV     D_LAST_SEL, FS
+                MOV     D_LAST_OFF, ESI
+                JMP     KEY
+
+CMD_REG:        CALL    INPUT
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JZ      CMD_DOT
+                PUSH    BX
+                CALL    FETCH
+                JZ      SHORT REG10
+                MOV     AH, AL
+                CALL    FETCH
+                JZ      SHORT REG10
+                CALL    SKIP
+                CALL    END_OF_LINE
+                JNZ     SHORT REG10
+                XCHG    AL, AH
+                LEA     BX, FLAG_TAB
+REG01:          MOV     CX, [BX+0]
+                JCXZ    REG10
+                CMP     AX, [BX+2]
+                JE      SHORT REG02
+                CMP     AX, [BX+4]
+                JE      SHORT REG03
+                ADD     BX, 6
+                JMP     SHORT REG01
+
+REG02:          NOT     CX
+                AND     WORD PTR I_EFLAGS, CX
+                JMP     SHORT REG04
+
+REG03:          OR      WORD PTR I_EFLAGS, CX
+REG04:          POP     BX
+                JMP     KEY
+
+REG10:          POP     BX
+                PUSH    BX
+                CALL    GET_REG
+                JC      SHORT REG20
+                MOV     CL, AL
+                MOV     DI, DX
+                CMP     BYTE PTR [BX], " "
+                JNE     SHORT REG20
+                CALL    SKIP
+                CALL    GET_NUMBER
+                JC      SHORT REG20
+                CALL    SKIP
+                CALL    END_OF_LINE
+                JNZ     SHORT REG20
+;
+; CL  = R8, R16, R32
+; DI  = pointer to register in stack
+; EAX = value
+;
+                CMP     CL, R8
+                JE      SHORT REG10_8
+                CMP     CL, R16
+                JE      SHORT REG10_16
+                CMP     CL, R32
+                JNE     SHORT REG20
+REG10_32:       MOV     SS:[DI], EAX
+                JMP     SHORT REG11
+REG10_16:       TEST    EAX, NOT 0FFFFH
+                JNZ     SHORT REG10_ERROR
+                MOV     SS:[DI], AX
+                JMP     SHORT REG11
+REG10_8:        TEST    EAX, NOT 0FFH
+                JNZ     SHORT REG10_ERROR
+                MOV     SS:[DI], AL
+REG11:          POP     BX
+                JMP     KEY
+
+REG10_ERROR:    POP     BX
+                JMP     SHORT INPUT_ERROR
+
+REG20:          POP     BX
+                JMP     SHORT INPUT_ERROR
+
+ALIGNMENT_ERROR:
+                LEA     EDX, $ALIGNMENT
+                JMP     SHORT ERROR
+
+BEYOND_LIMIT:   LEA     EDX, $BEYOND_LIMIT
+                JMP     SHORT ERROR
+
+INVALID_SEL:    LEA     EDX, $INVALID_SEL
+                JMP     SHORT ERROR
+
+INPUT_ERROR:    LEA     EDX, $INPUT_ERROR
+ERROR:          CALL    GTEXT
+                JMP     KEY
+
+
+              IF FLOATING_POINT
+CMD_387:        MOV     SI, PROCESS_PTR
+                CMP     SI, NO_PROCESS
+                JE      BAD_KEY
+                ASSUME  SI:PTR PROCESS
+                DB      66H
+                FNSAVE  DWORD PTR [SI].P_CW    ; Save FPU context, initialize
+                FWAIT
+                MOV     DX, [SI].P_TW
+                MOV     CX, [SI].P_SW
+                SHR     CX, 11
+                AND     CX, 7
+                ROR     DX, CL
+                ROR     DX, CL
+                LEA     DI, [SI].P_FST
+                MOV     CX, 8
+FPU_1:          PUSH    DX
+                MOV     AL, "S"
+                CALL    GCHAR
+                MOV     AL, "T"
+                CALL    GCHAR
+                MOV     AL, "("
+                CALL    GCHAR
+                MOV     AL, "8"
+                SUB     AL, CL
+                CALL    GCHAR
+                MOV     AL, ")"
+                CALL    GCHAR
+                MOV     AL, "="
+                CALL    GCHAR
+                MOV     AX, DX
+                AND     AX, 3
+                LEA     EDX, $ZERO
+                DEC     AX
+                JZ      SHORT FPU_2
+                LEA     EDX, $INFINITY
+                DEC     AX
+                JZ      SHORT FPU_2
+                LEA     EDX, $EMPTY
+                DEC     AX
+                JZ      SHORT FPU_2
+                PUSH    CX
+                PUSH    DI
+                MOV     CX, 10
+                ADD     DI, CX
+FPU_VALID_1:    DEC     DI
+                MOV     AL, [DI]
+                CALL    GBYTE
+                LOOP    FPU_VALID_1
+                POP     DI
+                POP     CX
+                JMP     SHORT FPU_3
+FPU_2:          CALL    GTEXT
+FPU_3:          CALL    GCRLF
+                POP     DX
+                ROR     DX, 2
+                ADD     DI, 10
+                LOOP    FPU_1
+                LEA     EDX, $CW
+                CALL    GTEXT
+                MOV     AX, [SI].P_CW
+                CALL    GWORD
+                LEA     EDX, $SW
+                CALL    GTEXT
+                MOV     AX, [SI].P_SW
+                CALL    GWORD
+                LEA     EDX, $C3210
+                CALL    GTEXT
+                MOV     DX, 4000H
+                CALL    FPU_C
+                MOV     DX, 0400H
+                CALL    FPU_C
+                MOV     DX, 0200H
+                CALL    FPU_C
+                MOV     DX, 0100H
+                CALL    FPU_C
+                MOV     AX, [SI].P_SW
+                AND     AX, 4500H
+                MOV     DL, ">"
+                JZ      SHORT FPU_4
+                CMP     AX, 0100H
+                MOV     DL, "<"
+                JE      SHORT FPU_4
+                CMP     AX, 4000H
+                JNE     SHORT FPU_5
+                MOV     DL, "="
+FPU_4:          MOV     AL, " "
+                CALL    GCHAR
+                MOV     AL, DL
+                CALL    GCHAR
+FPU_5:          CALL    GCRLF
+                DB      66H
+                FRSTOR  DWORD PTR [SI].P_CW
+                JMP     KEY
+
+FPU_C           PROC    NEAR
+                MOV     AL, "0"
+                TEST    [SI].P_SW, DX
+                JZ      SHORT FPU_C_1
+                INC     AL
+FPU_C_1:        CALL    GCHAR
+                RET
+FPU_C           ENDP
+
+                ASSUME  SI:NOTHING
+
+              ELSE
+
+CMD_387:        JMP     BAD_KEY
+
+              ENDIF
+                
+
+CMD_STEP:       MOV     FS, I_CS
+                MOV     ESI, I_EIP
+                CALL    GET_INST
+                CMP     AL, 0CCH                ; INT 3
+                JNE     SHORT CMD_STEP_1
+                MOV     I_EIP, ESI              ; Skip INT 3
+                CALL    GET_INST
+CMD_STEP_1:     CMP     AL, 0CDH                ; INT n
+                JE      SHORT DO_CALL
+;
+; Single-step program
+;
+DO_STEP:        CMP     DEBUG_FLAG, FALSE
+                JE      SHORT DO_STEP_0
+                LEA     EDX, $DO_STEP
+                CALL    GTEXT
+DO_STEP_0:      CALL    DEBUG_STEP              ; Set single step mode
+                MOV     SKIP_FLAG, NOT FALSE    ; Ignore breakpoint at CS:EIP
+                CALL    INS_BREAKPOINTS         ; Insert breakpoints
+                MOV     SKIP_FLAG, FALSE        ; Restore original value
+                JMP     RUN                     ; Continue program
+
+;
+; Set breakpoint after current instruction, continue program
+;
+CMD_CALL:       MOV     FS, I_CS
+                MOV     ESI, I_EIP
+                CALL    GET_INST
+                CMP     AL, 0CCH                ; INT 3
+                JNE     SHORT CMD_CALL_1
+                MOV     I_EIP, ESI              ; Skip INT 3
+                CALL    GET_INST
+CMD_CALL_1:     CMP     AL, 0C2H                ; RETN immed
+                JE      SHORT DO_STEP
+                CMP     AL, 0C3H                ; RETN
+                JE      SHORT DO_STEP
+                CMP     AL, 0CAH                ; RETF immed
+                JE      SHORT DO_STEP
+                CMP     AL, 0CBH                ; RETF
+                JE      SHORT DO_STEP
+                CMP     AL, 0CFH                ; IRET/IRETD
+                JE      SHORT DO_STEP
+                CMP     AL, 0E9H                ; JMP NEAR
+                JE      SHORT DO_STEP
+                CMP     AL, 0EAH                ; JMP FAR
+                JE      SHORT DO_STEP
+                CMP     AL, 0EBH                ; JMP SHORT
+                JE      SHORT DO_STEP
+                CMP     AL, 0FFH
+                JE      SHORT CMD_CALL_FF       ; JMP reg/mem ?
+DO_CALL:        CMP     DEBUG_FLAG, FALSE
+                JE      SHORT DO_CALL_0
+                LEA     EDX, $DO_CALL
+                CALL    GTEXT
+DO_CALL_0:      MOV     FS, I_CS
+                MOV     ESI, I_EIP
+                MOV     ECX, ESI                ; No relocation
+                LEA     DI, DISASM_BUF
+                CALL    GET_MODE
+                CALL    DISASM
+                MOV     DX, I_CS
+                MOV     EAX, ESI
+                CALL    SET_BREAKPOINT
+                JMP     CONTINUE
+
+CMD_CALL_FF:    MOV     AL, FS:[ESI]            ; Get mod reg r/m byte
+                AND     AL, 7 SHL 3
+                CMP     AL, 4 SHL 3             ; JMP DWORD PTR reg/mem
+                JE      DO_STEP
+                CMP     AL, 5 SHL 3             ; JMP FWORD PTR reg/mem
+                JE      DO_STEP
+                JMP     SHORT DO_CALL
+
+CMD_SEARCH:     CALL    INPUT
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JZ      INPUT_ERROR             ; Future expansion: cont.
+                MOV     DX, I_DS
+                CALL    GET_RANGE
+                JC      ERROR
+                MOV     SEARCH_SEL, DX
+                MOV     SEARCH_OFF, EAX
+                MOV     SEARCH_LEN, ECX
+                MOV     SEARCH_SIZE, 0
+                LEA     DI, SEARCH_BUF
+CMD_SEARCH_01:  CALL    END_OF_LINE
+                JZ      SHORT CMD_SEARCH_09
+                CMP     SEARCH_SIZE, LENGTH SEARCH_BUF
+                JAE     INPUT_ERROR
+                CMP     BYTE PTR [BX], "'"
+                JE      SHORT CMD_SEARCH_02
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                TEST    EAX, NOT 0FFH
+                JNZ     INPUT_ERROR
+                MOV     [DI], AL
+                INC     DI
+                INC     SEARCH_SIZE
+                CALL    SKIP
+                JMP     SHORT CMD_SEARCH_01
+
+CMD_SEARCH_02:  INC     BX
+                MOV     AL, [BX]
+                CMP     AL, "'"
+                JE      SHORT CMD_SEARCH_04
+CMD_SEARCH_03:  CALL    END_OF_LINE
+                JZ      INPUT_ERROR
+                MOV     AL, [BX]
+                INC     BX
+                CMP     AL, "'"
+                JE      SHORT CMD_SEARCH_05
+CMD_SEARCH_04:  CMP     SEARCH_SIZE, LENGTH SEARCH_BUF
+                JAE     INPUT_ERROR
+                MOV     [DI], AL
+                INC     DI
+                INC     SEARCH_SIZE
+                JMP     SHORT CMD_SEARCH_03
+
+CMD_SEARCH_05:  CALL    DELIM
+                JNZ     INPUT_ERROR
+                CALL    SKIP
+                JMP     SHORT CMD_SEARCH_01
+
+CMD_SEARCH_09:  CMP     SEARCH_SIZE, 0
+                JE      INPUT_ERROR
+CMD_SEARCH_10:  MOV     ES, SEARCH_SEL
+CMD_SEARCH_11:  MOV     EDI, SEARCH_OFF
+                MOV     ECX, SEARCH_LEN
+                MOV     AL, SEARCH_BUF[0]
+                REPNE   SCAS BYTE PTR ES:[EDI]
+                JNE     SHORT CMD_SEARCH_99
+                MOV     SEARCH_OFF, EDI
+                MOV     SEARCH_LEN, ECX
+                INC     ECX
+                CMP     ECX, SEARCH_SIZE
+                JB      SHORT CMD_SEARCH_99
+                MOV     ECX, SEARCH_SIZE
+                DEC     ECX
+                JZ      SHORT CMD_SEARCH_12
+                LEA     ESI, SEARCH_BUF+1
+                REPE    CMPS BYTE PTR DS:[ESI], ES:[EDI]
+                JNE     SHORT CMD_SEARCH_11
+CMD_SEARCH_12:  MOV     ESI, SEARCH_OFF
+                DEC     ESI
+                MOV     FS, SEARCH_SEL
+                CALL    SHOW_DATA
+                JMP     SHORT CMD_SEARCH_10
+
+CMD_SEARCH_99:  JMP     KEY
+
+;
+; A command
+;
+CMD_ADDR:       CALL    INPUT
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JZ      INPUT_ERROR
+                MOV     DX, I_DS
+                CALL    GET_ADDR
+                JC      INPUT_ERROR
+                MOV     ADDR_COUNT, 0
+                CALL    END_OF_LINE
+                JZ      SHORT ADDR_1
+                CALL    GET_RANGE_MORE
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                MOV     ADDR_COUNT, ECX
+ADDR_1:         MOV     ADDR_SEL, DX
+                MOV     ADDR_OFF, EAX
+                VERR    DX
+                JNZ     INVALID_SEL
+ADDR_LOOP:      MOVZX   EDX, ADDR_SEL
+                LSL     ECX, EDX
+                CMP     EAX, ECX
+                JA      BEYOND_LIMIT
+                MOV     AX, ADDR_SEL
+                CALL    GWORD
+                MOV     AL, ":"
+                CALL    GCHAR
+                MOV     EAX, ADDR_OFF
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AX, ADDR_SEL
+                MOV     EBX, ADDR_OFF
+                CALL    GET_LIN
+                LEA     EDX, $ADDR_FAILURE
+                JC      SHORT ADDR_MSG
+                MOV     ADDR_LIN, EBX
+                LEA     EDX, $LINEAR
+                CALL    GTEXT
+                CALL    SHOW_LIN
+ADDR_NEXT:      ADD     ADDR_OFF, 1000H
+                SUB     ADDR_COUNT, 1000H
+                JA      ADDR_LOOP
+                JMP     KEY
+
+ADDR_MSG:       CALL    GTEXT
+                JMP     SHORT ADDR_NEXT
+
+;
+; V command
+;
+CMD_VIRT:       CALL    INPUT
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JZ      INPUT_ERROR
+                MOV     AL, [BX]
+                CALL    UPPER
+                LEA     DI, V_PHYS
+                CMP     AL, "P"
+                JE      VIRT_SCAN
+                LEA     DI, V_EXT
+                CMP     AL, "X"
+                JE      VIRT_SCAN
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                MOV     ADDR_LIN, EAX
+                MOV     ADDR_COUNT, 0
+                CALL    SKIP
+                CALL    END_OF_LINE
+                JZ      SHORT VIRT_LOOP
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                SUB     EAX, ADDR_LIN
+                JB      INPUT_ERROR
+                INC     EAX
+                MOV     ADDR_COUNT, EAX
+VIRT_LOOP:      CALL    SHOW_LIN
+                ADD     ADDR_LIN, 1000H
+                SUB     ADDR_COUNT, 1000H
+                JA      VIRT_LOOP
+                JMP     KEY
+
+;
+; VP and VX commands
+;
+VIRT_SCAN:      MOV     LIST_ALL, NOT FALSE
+                MOV     ADDR_COUNT, 0
+                INC     BX
+                CALL    SKIP
+                CALL    END_OF_LINE
+                JZ      SHORT VSCAN_1
+                MOV     LIST_ALL, FALSE
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                MOV     ADDR_ARG, EAX
+                CALL    SKIP
+                CALL    END_OF_LINE
+                JZ      SHORT VSCAN_1
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                SUB     EAX, ADDR_ARG
+                JB      INPUT_ERROR
+                INC     EAX
+                MOV     ADDR_COUNT, EAX
+VSCAN_1:        AND     ADDR_ARG, NOT 0FFFH
+VSCAN_LOOP:     CALL    SCAN_PAGE_TABLES
+                ADD     ADDR_ARG, 1000H
+                SUB     ADDR_COUNT, 1000H
+                JA      VSCAN_LOOP
+                JMP     KEY
+
+V_PHYS          PROC    NEAR
+                TEST    AX, PAGE_PRESENT OR PAGE_ALLOC
+                JZ      SHORT V_PHYS_RET
+                CMP     LIST_ALL, FALSE
+                JNE     SHORT V_PHYS_SHOW
+                AND     EAX, NOT 0FFFH
+                CMP     EAX, ADDR_ARG
+                JNE     SHORT V_PHYS_RET
+V_PHYS_SHOW:    CALL    SHOW_LIN
+V_PHYS_RET:     RET
+V_PHYS          ENDP
+
+V_EXT           PROC    NEAR
+                TEST    DX, SWAP_ALLOC
+                JNZ     SHORT V_EXT_CMP
+                MOV     AX, DX
+                AND     AX, SRC_MASK
+                CMP     AX, SRC_EXEC
+                JNE     SHORT V_EXT_RET
+V_EXT_CMP:      CMP     LIST_ALL, FALSE
+                JNE     SHORT V_EXT_SHOW
+                AND     EDX, NOT 0FFFH
+                CMP     EDX, ADDR_ARG
+                JNE     SHORT V_EXT_RET
+V_EXT_SHOW:     CALL    SHOW_LIN
+V_EXT_RET:      RET
+V_EXT           ENDP
+
+
+
+SEL_TAB         DW      SEL_INVALID             ; 0000 undefined
+                DW      SEL_TSS                 ; 0001 16-bit TSS
+                DW      SEL_LDT                 ; 0010 LDT
+                DW      SEL_TSS                 ; 0011 16-bit TSS (busy)
+                DW      SEL_CALL                ; 0100 16-bit call gate
+                DW      SEL_TASK                ; 0101 task gate
+                DW      SEL_INT                 ; 0110 16-bit interrupt gate
+                DW      SEL_TRAP                ; 0111 16-bit trap gate
+                DW      SEL_INVALID             ; 1000 undefined
+                DW      SEL_TSS                 ; 1001 32-bit TSS
+                DW      SEL_INVALID             ; 1010 undefined
+                DW      SEL_TSS                 ; 1011 32-bit TSS (busy)
+                DW      SEL_CALL                ; 1100 32-bit call gate
+                DW      SEL_INVALID             ; 1101 undefined
+                DW      SEL_INT                 ; 1110 32-bit interrupt gate
+                DW      SEL_TRAP                ; 1111 32-bit trap gate
+
+CMD_SELECTOR:   CALL    INPUT
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JZ      INPUT_ERROR
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                TEST    EAX, NOT 0FFFFH
+                JNZ     INPUT_ERROR
+                MOV     SEL_SEL, AX
+                MOV     SEL_COUNT, 0
+                CALL    SKIP
+                CALL    END_OF_LINE
+                JZ      SHORT SEL_1
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                SUB     AX, SEL_SEL
+                JB      INPUT_ERROR
+                SHR     AX, 3
+                INC     AX
+                MOV     SEL_COUNT, AX
+                CALL    SKIP
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+SEL_1:
+SEL_LOOP:       MOV     AX, SEL_SEL
+                CALL    GWORD
+                LEA     EDX, $RPL
+                CALL    GTEXT
+                MOV     AX, SEL_SEL
+                AND     AL, 03H
+                ADD     AL, "0"
+                CALL    GCHAR
+                MOV     AX, SEL_SEL
+                LEA     EDX, $TI_GDT
+                MOV     DI, G_GDT_MEM_SEL
+                LEA     SI, GDT
+                TEST    AX, 04H
+                JZ      SHORT SEL_2
+                SLDT    DI
+                MOV     SI, DI
+                AND     SI, NOT 07H
+                SUB     SI, G_LDT_SEL
+                IMUL    SI, LDT_ENTRIES
+                LEA     SI, LDTS[SI]
+                LEA     EDX, $TI_LDT
+SEL_2:          CALL    GTEXT
+                AND     DI, NOT 07H
+                MOV     AX, WORD PTR GDT[DI]    ; ... ignore limit 16..19, G
+                MOV     BX, SEL_SEL
+                OR      BX, 07H
+                CMP     BX, AX
+                JA      SEL_INVALID
+                AND     BX, NOT 07H
+                JZ      SEL_NULL
+                ADD     SI, BX
+                MOV     BX, [SI+5]
+                TEST    BX, 10H                 ; D1
+                JNZ     SHORT SEL_SEG
+                MOV     DI, BX
+                AND     DI, 0FH
+                SHL     DI, 1
+                JMP     SEL_TAB[DI]
+
+SEL_LDT:        LEA     EDX, $LDT
+                CALL    GTEXT
+                CALL    SEL_DPL_P
+                JMP     SHORT SEL_SEG_1
+
+;
+; It's a segment
+;
+SEL_SEG:        TEST    BX, 08H                 ; Code segment?
+                JNZ     SHORT SEL_CODE
+                LEA     EDX, $DATA
+                CALL    GTEXT
+                CALL    SEL_DPL_P
+                MOV     AL, "A"
+                TEST    BX, 01H                 ; Accessed
+                CALL    SHOW_BIT
+                MOV     AL, "W"
+                TEST    BX, 02H                 ; Writable?
+                CALL    SHOW_BIT
+                MOV     AL, "E"
+                TEST    BX, 04H                 ; Expand down?
+                CALL    SHOW_BIT
+                MOV     AL, "B"
+                TEST    BX, 4000H               ; Big?
+                CALL    SHOW_BIT
+SEL_SEG_1:      MOV     AL, "G"
+                TEST    BX, 8000H               ; Granularity?
+                CALL    SHOW_BIT
+                LEA     EDX, $BASE
+                CALL    GTEXT
+                MOV     AH, [SI+7]
+                MOV     AL, [SI+4]
+                SHL     EAX, 16
+                MOV     AX, [SI+2]
+                CALL    GDWORD
+                LEA     EDX, $LIMIT
+                CALL    GTEXT
+                MOV     AL, [SI+6]
+                AND     AX, 0FH
+                SHL     EAX, 16
+                MOV     AX, [SI+0]
+                TEST    BX, 8000H               ; Granularity
+                JZ      SHORT SEL_LIMIT_1
+                SHL     EAX, 12
+                OR      EAX, 0FFFH
+SEL_LIMIT_1:    CALL    GDWORD
+                JMP     SEL_DONE
+
+SEL_CODE:       LEA     EDX, $CODE
+                CALL    GTEXT
+                CALL    SEL_DPL_P
+                MOV     AL, "A"
+                TEST    BX, 01H                 ; Accessed
+                CALL    SHOW_BIT
+                MOV     AL, "R"
+                TEST    BX, 02H                 ; Readable?
+                CALL    SHOW_BIT
+                MOV     AL, "C"
+                TEST    BX, 04H                 ; Conforming?
+                CALL    SHOW_BIT
+                MOV     AL, "D"
+                TEST    BX, 4000H               ; Default?
+                CALL    SHOW_BIT
+                JMP     SEL_SEG_1
+
+SEL_TRAP:       LEA     EDX, $TRAP
+                JMP     SHORT SEL_INT_1
+
+SEL_INT:        LEA     EDX, $INT
+SEL_INT_1:      CALL    SEL_16_32
+                CALL    GTEXT
+                CALL    SEL_DPL_P
+                MOV     AX, [SI+2]
+                CALL    GWORD
+                MOV     AL, ":"
+                CALL    GCHAR
+                XOR     EAX, EAX
+                TEST    BX, 08H
+                JZ      SHORT SEL_INT_2
+                MOV     AX, [SI+6]
+                SHL     EAX, 16
+SEL_INT_2:      MOV     AX, [SI+0]
+                CALL    GDWORD
+                JMP     SEL_DONE
+
+SEL_TSS:        CALL    SEL_16_32
+                LEA     EDX, $TSS
+                CALL    GTEXT
+                CALL    SEL_DPL_P
+                MOV     AL, "B"
+                TEST    BX, 02H                 ; Busy
+                CALL    SHOW_BIT
+                JMP     SEL_SEG_1
+
+SEL_CALL:       CALL    SEL_16_32
+                LEA     EDX, $CALL
+                CALL    GTEXT
+                CALL    SEL_DPL_P
+                MOV     AX, [SI+2]
+                CALL    GWORD
+                MOV     AL, ":"
+                CALL    GCHAR
+                XOR     EAX, EAX
+                TEST    BX, 08H
+                JZ      SHORT SEL_CALL_1
+                MOV     AX, [SI+6]
+                SHL     EAX, 16
+SEL_CALL_1:     MOV     AX, [SI+0]
+                CALL    GDWORD
+                MOV     AL, " "
+                MOV     AL, [SI+4]
+                AND     AL, 0FH
+                CALL    GBYTE
+                JMP     SHORT SEL_DONE
+
+SEL_TASK:       LEA     EDX, $TASK
+                CALL    GTEXT
+                CALL    SEL_DPL_P
+                MOV     AX, [SI+2]
+                CALL    GWORD
+                JMP     SHORT SEL_DONE
+
+SEL_NULL:       LEA     EDX, $NULL
+                CALL    GTEXT
+                JMP     SHORT SEL_DONE
+
+SEL_INVALID:    LEA     EDX, $SEL_INVALID
+                CALL    GTEXT
+SEL_DONE:       CALL    GCRLF
+                ADD     SEL_SEL, 8
+                SUB     SEL_COUNT, 1
+                JA      SEL_LOOP
+                JMP     KEY
+
+
+SEL_16_32       PROC    NEAR
+                PUSH    EDX
+                LEA     EDX, $SEL_32
+                TEST    BX, 08H
+                JNZ     SHORT SEL_16_32_1
+                LEA     EDX, $SEL_16
+SEL_16_32_1:    CALL    GTEXT
+                POP     EDX
+                RET
+SEL_16_32       ENDP
+
+SEL_DPL_P       PROC    NEAR
+                PUSH    EDX
+                LEA     EDX, $DPL
+                CALL    GTEXT
+                MOV     AX, BX
+                SHR     AX, 5
+                AND     AL, 03H
+                ADD     AL, "0"
+                CALL    GCHAR
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AL, "P"
+                TEST    BX, 80H
+                CALL    SHOW_BIT
+                MOV     AL, " "
+                CALL    GCHAR
+                POP     EDX
+                RET
+SEL_DPL_P       ENDP
+
+;
+; Quit
+;
+CMD_QUIT:       CALL    INPUT
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                MOV     AL, 0
+                JZ      CMD_QUIT_0
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                TEST    EAX, NOT 0FFH
+                JNZ     INPUT_ERROR
+CMD_QUIT_0:     MOV     AH, 4CH
+                INT     21H
+                JMP     SHORT $
+
+
+;
+; Symbol
+;
+CMD_SYM:        CALL    INPUT
+                JC      INPUT_ERROR
+                CALL    GET_NUMBER
+                JC      INPUT_ERROR
+                MOV     EDX, EAX
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                MOV     DI, PROCESS_PTR
+                CALL    SYM_BEFORE
+                JC      KEY
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                CALL    PRINT_SYM
+                CALL    GCRLF
+                JMP     KEY
+
+;
+; Info
+;
+CMD_INFO:       CALL    INPUT
+                JC      INPUT_ERROR
+                CALL    END_OF_LINE
+                JNZ     INPUT_ERROR
+                LEA     EDX, $INFO_TITLE
+                CALL    GTEXT
+                LEA     BX, PROCESS_TABLE
+                ASSUME  BX:PTR PROCESS
+                MOV     CX, MAX_PROCESSES + 1
+INFO_10:        CMP     [BX].P_STATUS, PS_NONE  ; Empty slot?
+                JE      SHORT INFO_19
+                MOV     AL, [BX].P_PIDX
+                CALL    GBYTE
+                MOV     AL, " "
+                CMP     BX, PROCESS_PTR
+                JNE     SHORT INFO_13
+                MOV     AL, "*"
+INFO_13:        CALL    GCHAR
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     EAX, [BX].P_PID
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     EAX, [BX].P_PPID
+                CALL    GDWORD
+;
+; File handles
+;
+                MOV     SI, 0
+INFO_LOOP_HANDLE: 
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AX, [BX].P_HANDLES[SI]
+                CMP     AX, NO_FILE_HANDLE
+                JE      SHORT INFO_NO_HANDLE
+                AAM
+                XCHG    AL, AH
+                ADD     AL, "0"
+                CALL    GCHAR
+                XCHG    AL, AH
+                ADD     AL, "0"
+                CALL    GCHAR
+                JMP     SHORT INFO_NEXT_HANDLE
+
+INFO_NO_HANDLE: MOV     AL, "-"
+                CALL    GCHAR
+                CALL    GCHAR
+INFO_NEXT_HANDLE: 
+                ADD     SI, 2
+                CMP     SI, 2 * 19
+                JB      SHORT INFO_LOOP_HANDLE
+                CALL    GCRLF
+;
+; Next process table entry
+;
+INFO_19:        ADD     BX, SIZE PROCESS
+                DEC     CX
+                JNZ     INFO_10
+                ASSUME  BX:NOTHING
+                CALL    CHECK_HANDLES
+                JMP     KEY
+
+;
+; Continue program
+;
+RUN:            CMP     DEBUG_FLAG, FALSE
+                JE      SHORT RUN_0
+                LEA     EDX, $RUN
+                CALL    GTEXT
+RUN_0:          JMP     EXCEPT_RET
+                ASSUME  BP:NOTHING
+DEBUG_EXCEPTION ENDP
+
+
+;
+; Get next instruction opcode byte, skip prefix bytes
+;
+; In:   FS:ESI  Pointer to code
+;
+; Out:  AL      Opcode byte
+;       ESI     Points to next opcode byte
+;
+GET_INST        PROC    NEAR
+GINST1:         MOV     AL, FS:[ESI]
+                INC     ESI
+                CMP     AL, 26H                 ; ES prefix
+                JE      SHORT GINST1
+                CMP     AL, 2EH                 ; CS prefix
+                JE      SHORT GINST1
+                CMP     AL, 36H                 ; SS prefix
+                JE      SHORT GINST1
+                CMP     AL, 3EH                 ; DS prefix
+                JE      SHORT GINST1
+                CMP     AL, 64H                 ; FS prefix
+                JE      SHORT GINST1
+                CMP     AL, 65H                 ; GS prefix
+                JE      SHORT GINST1
+                CMP     AL, 66H                 ; Operand size prefix
+                JE      SHORT GINST1
+                CMP     AL, 67H                 ; Adress size prefix
+                JE      SHORT GINST1
+                CMP     AL, 0F0H                ; LOCK prefix
+                JE      SHORT GINST1
+                CMP     AL, 0F2H                ; REP/REPNE prefix
+                JE      SHORT GINST1
+                CMP     AL, 0F3H                ; REPE prefix
+                JE      SHORT GINST1
+                RET
+GET_INST        ENDP
+
+;
+; In:   AL=0    Display empty line if jumped
+;       AL!=0   Don't display empty line
+;
+                ASSUME  BP:PTR ISTACKFRAME
+TRACE_DISASM    PROC    NEAR
+                OR      AL, AL                  ; Stopped?
+                MOV     AX, I_CS                ; Get CS:EIP
+                MOV     ESI, I_EIP
+                JNZ     SHORT TDA2              ; Yes -> no empty line
+                CMP     AX, NEXT_CS             ; Are we at next instruction?
+                JNE     SHORT TDA1              ; No  -> empty line
+                CMP     ESI, NEXT_EIP
+                JE      SHORT TDA2              ; Yes -> no empty line
+TDA1:           CALL    GCRLF                   ; Display empty line
+TDA2:           MOV     FS, AX
+                CALL    SHOW_DISASM             ; One line of disassembly
+                MOV     NEXT_CS, FS             ; Remember address of
+                MOV     NEXT_EIP, ESI           ; next instruction
+                RET
+                ASSUME  BP:NOTHING
+TRACE_DISASM    ENDP
+
+
+SHOW_DISASM     PROC    NEAR
+                XOR     EAX, EAX
+                MOV     AX, FS
+                LSL     EAX, EAX
+                CMP     ESI, EAX
+                JA      SDIS_RET
+                PUSH    ESI
+                MOV     ECX, ESI                ; No relocation
+                LEA     DI, DISASM_BUF
+                CALL    GET_MODE
+                CALL    DISASM
+                MOV     DA_SYM_FLAG, AL
+                MOV     DA_EMPTY_FLAG, AH
+                MOV     DA_SYM_ADDR, EDX
+                MOV     AX, FS
+                CMP     AX, L_CODE_SEL          ; Symbols only for L_CODE_SEL
+                JNE     SHORT SDIS_S9
+                POP     EDX
+                PUSH    EDX
+                MOV     AL, SYM_LINE
+                MOV     DI, PROCESS_PTR
+                CALL    SYM_BY_ADDR
+                JC      SHORT SDIS_S2
+                POP     EAX
+                PUSH    EAX
+                PUSH    DX
+                MOV     EDX, EAX
+                CALL    SYM_MODULE
+                JC      SHORT SDIS_S1
+                CALL    PRINT_SYM
+SDIS_S1:        LEA     EDX, $LINE
+                CALL    GTEXT
+                POP     AX
+                MOVZX   EAX, AX
+                CALL    DECIMAL
+                MOV     AL, ":"
+                CALL    GCHAR
+                CALL    GCRLF
+SDIS_S2:        POP     EDX
+                PUSH    EDX
+                MOV     AL, SYM_TEXT
+                CALL    SYM_BY_ADDR
+                JC      SHORT SDIS_S9
+                CALL    PRINT_SYM
+                MOV     AL, ":"
+                CALL    GCHAR
+                CALL    GCRLF
+SDIS_S9:        POP     EBX
+                MOV     AX, FS
+                CALL    GWORD
+                MOV     AL, ":"
+                CALL    GCHAR
+                MOV     EAX, EBX
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     CX, 8
+                LEA     EDX, DISASM_BUF
+SDIS1:          CMP     EBX, ESI
+                JAE     SHORT SDIS5
+                OR      CX, CX
+                JNZ     SHORT SDIS4
+                CALL    SDIS_DIS
+                MOV     AL, " "
+                MOV     CX, 14
+SDIS2:          CALL    GCHAR
+                LOOP    SDIS2
+                MOV     CX, 8
+SDIS4:          MOV     AL, FS:[EBX]
+                CALL    GBYTE
+                INC     EBX
+                DEC     CX
+                JMP     SHORT SDIS1
+
+SDIS5:          JCXZ    SDIS7
+                MOV     AL, " "
+SDIS6:          CALL    GCHAR
+                CALL    GCHAR
+                LOOP    SDIS6
+SDIS7:          CALL    SDIS_DIS
+SDIS_RET:       RET
+
+SDIS_DIS        PROC    NEAR
+                PUSH    EBX
+                OR      EDX, EDX
+                JZ      SHORT SDIS_DIS9
+                MOV     AL, " "
+                CALL    GCHAR
+                CALL    GTEXT
+                MOV     AX, FS
+                CMP     AX, L_CODE_SEL          ; Symbols only for L_CODE_SEL
+                JNE     SHORT SDIS_DIS9
+                MOV     AL, DA_SYM_FLAG
+                CMP     AL, SYM_NONE
+                JE      SHORT SDIS_DIS9
+                MOV     EDX, DA_SYM_ADDR
+                CMP     EDX, 2
+                JB      SHORT SDIS_DIS9         ; Avoid symbols for 0, 1
+                MOV     DI, PROCESS_PTR
+                CALL    SYM_BY_ADDR
+                JC      SHORT SDIS_DIS9
+                MOV     AL, " "
+                CALL    GCHAR
+                CALL    GCHAR
+                MOV     AL, ";"
+                CALL    GCHAR
+                MOV     AL, " "
+                CALL    GCHAR
+                CALL    PRINT_SYM
+SDIS_DIS9:      CALL    GCRLF
+                XOR     EDX, EDX
+                POP     EBX
+                RET
+SDIS_DIS        ENDP
+
+SHOW_DISASM     ENDP
+
+;
+; Display a symbol
+;
+; In:   ES:EBX  Name of symbol
+;
+PRINT_SYM       PROC    NEAR
+                PUSH    EDX
+                PUSH    DI
+                LEA     DI, SYMBOL_BUF
+PSYM1:          MOV     AL, ES:[EBX]
+                MOV     [DI], AL
+                INC     EBX
+                INC     DI
+                OR      AL, AL
+                JNZ     SHORT PSYM1
+                LEA     EDX, SYMBOL_BUF
+                CALL    GTEXT
+                POP     DI
+                POP     EDX
+                RET
+PRINT_SYM       ENDP
+
+
+;
+; Get 16/32 mode for disassembler
+;
+; In:   FS      Segment register
+;
+; Out:  AL      0:16, 1:32
+;       EAX     Changed
+;
+GET_MODE        PROC    NEAR
+                XOR     EAX, EAX
+                MOV     AX, FS
+                LAR     EAX, EAX                ; Ignore flags
+                TEST    EAX, 1 SHL 22
+                SETNZ   AL
+                RET
+GET_MODE        ENDP
+
+
+;
+; Display the status of a bit: upper case if set, lower case if clear
+;
+; In:  NZ       Bit is set
+;      AL       Upper case character
+;
+SHOW_BIT        PROC    NEAR
+                JNZ     SHORT SHOW_BIT_1
+                ADD     AL, "a" - "A"
+SHOW_BIT_1:     CALL    GCHAR
+                RET
+SHOW_BIT        ENDP
+
+
+
+
+;
+; Bug: pages protected by swapper cause exception 0EH (and dump)
+;
+SHOW_DATA       PROC    NEAR
+                PUSHAD
+                MOV     AX, FS
+                CALL    GWORD
+                MOV     AL, ":"
+                CALL    GCHAR
+                MOV     EAX, ESI
+                CALL    GDWORD
+                MOV     AL," "
+                CALL    GCHAR
+                XOR     EDX, EDX
+                MOV     DX, FS
+                LSL     EDX, EDX
+                MOV     CX, 16
+SDATA11:        CMP     ESI, EDX
+                JA      SHORT SDATA12
+                MOV     AL, FS:[ESI]
+                CALL    GBYTE
+                JMP     SHORT SDATA13
+SDATA12:        MOV     AL, " "
+                CALL    GCHAR
+                CALL    GCHAR
+SDATA13:        MOV     AL, " "
+                CALL    GCHAR
+                INC     ESI
+                LOOP    SDATA11
+                MOV     AL, " "
+                CALL    GCHAR
+                SUB     ESI, 16
+                MOV     CX, 16
+SDATA21:        CMP     ESI, EDX
+                JA      SHORT SDATA29
+                MOV     AL, FS:[ESI]
+                INC     ESI
+                CMP     AL, 20H
+                JB      SHORT SDATA22
+                CMP     AL, 7FH
+                JB      SHORT SDATA23
+SDATA22:        MOV     AL, "."
+SDATA23:        CALL    GCHAR
+                LOOP    SDATA21
+SDATA29:        CALL    GCRLF
+                POPAD
+                NOP                             ; Avoid 386 bug
+                RET
+SHOW_DATA       ENDP
+
+
+                ASSUME  BP:PTR ISTACKFRAME
+REG_DUMP        PROC    NEAR
+                MOV     AL, "D"
+                MOV     DX, I_DS
+                CALL    RD_SEG
+                MOV     AL, "E"
+                MOV     DX, I_ES
+                CALL    RD_SEG
+                MOV     AL, "F"
+                MOV     DX, I_FS
+                CALL    RD_SEG
+                MOV     AL, "G"
+                MOV     DX, I_GS
+                CALL    RD_SEG
+                MOV     DX, SS
+                TEST    I_CS, 3                 ; RPL=0?
+                JZ      SHORT RD_1
+                MOV     DX, I_SS
+RD_1:           MOV     AL, "S"
+                CALL    RD_SEG
+                MOV     AL, " "
+                CALL    GCHAR
+                LEA     BX, FLAG_TAB
+                MOV     EDX, I_EFLAGS
+RD_F1:          MOV     CX, [BX+0]
+                JCXZ    RD_F9
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AX, [BX+2]
+                TEST    DX, CX
+                JZ      SHORT RD_F2
+                MOV     AX, [BX+4]
+RD_F2:          CALL    GCHAR
+                MOV     AL, AH
+                CALL    GCHAR
+                ADD     BX, 6
+                JMP     SHORT RD_F1
+RD_F9:          CALL    GCRLF
+
+                MOV     BL, "X"
+                MOV     AH, "A"
+                MOV     EDX, I_EAX
+                CALL    RD_GEN
+                MOV     AH, "B"
+                MOV     EDX, I_EBX
+                CALL    RD_GEN
+                MOV     AH, "C"
+                MOV     EDX, I_ECX
+                CALL    RD_GEN
+                MOV     AH, "D"
+                MOV     EDX, I_EDX
+                CALL    RD_GEN
+                CALL    GCRLF
+                MOV     BL, "I"
+                MOV     AH, "S"
+                MOV     EDX, I_ESI
+                CALL    RD_GEN
+                MOV     AH, "D"
+                MOV     EDX, I_EDI
+                CALL    RD_GEN
+                MOV     BL, "P"
+                MOV     AH, "B"
+                MOV     EDX, I_EBP
+                CALL    RD_GEN
+                LEA     EDX, I_ESP
+                TEST    I_CS, 3                 ; RPL=0?
+                JZ      SHORT RD_2
+                MOV     EDX, I_ESP
+RD_2:           MOV     AH, "S"
+                CALL    RD_GEN
+                CALL    GCRLF
+                RET
+                ASSUME  BP:NOTHING
+REG_DUMP        ENDP
+
+RD_SEG          PROC    NEAR
+                CALL    GCHAR
+                MOV     AL, "S"
+                CALL    GCHAR
+                MOV     AL, "="
+                CALL    GCHAR
+                MOV     AX, DX
+                CALL    GWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                RET
+RD_SEG          ENDP
+
+RD_GEN          PROC    NEAR
+                MOV     AL, "E"
+                CALL    GCHAR
+                MOV     AL, AH
+                CALL    GCHAR
+                MOV     AL, BL
+                CALL    GCHAR
+                MOV     AL, "="
+                CALL    GCHAR
+                MOV     EAX, EDX
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                RET
+RD_GEN          ENDP
+
+
+;
+; In:  DI       Address of routine to be called
+;
+; Routine pointed to by DI:
+;
+; In:  EAX      Page table entry
+;      EDX      Swap table entry
+;      ADDR_LIN Linear address
+;
+SCAN_PAGE_TABLES PROC   NEAR
+                MOV     ADDR_LIN, 0
+                MOV     AX, G_PAGEDIR_SEL
+                MOV     FS, AX
+                MOV     ESI, 0
+SPT_10:         MOV     EBX, FS:[ESI]
+                TEST    BL, PAGE_PRESENT
+                JZ      SHORT SPT_18
+                MOV     EAX, FS:[ESI+4096]
+                OR      EAX, EAX
+                JZ      SHORT SPT_18
+                PUSH    ESI
+                MOV     ESI, EAX
+                AND     EBX, NOT 0FFFH
+                MOV     AX, G_PHYS_SEL
+                MOV     ES, AX
+                MOV     CX, 1024
+SPT_11:         MOV     EAX, ES:[EBX]
+                MOV     EDX, ES:[ESI]
+                PUSH    ES
+                PUSH    FS
+                PUSH    EBX
+                PUSH    ESI
+                PUSH    CX
+                PUSH    DI
+                CALL    DI
+                POP     DI
+                POP     CX
+                POP     ESI
+                POP     EBX
+                POP     FS
+                POP     ES
+                ADD     EBX, 4
+                ADD     ESI, 4
+                ADD     ADDR_LIN, 4096
+                LOOP    SPT_11
+                POP     ESI
+                JMP     SHORT SPT_19
+
+SPT_18:         ADD     ADDR_LIN, 1024 * 4096
+SPT_19:         ADD     ESI, 4
+                CMP     ESI, 4096
+                JB      SPT_10
+                RET
+SCAN_PAGE_TABLES ENDP
+
+
+;
+; Display info about linear address (ADDR_LIN)
+;
+SHOW_LIN        PROC    NEAR
+                MOV     EAX, ADDR_LIN
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AX, G_PAGEDIR_SEL
+                MOV     ES, AX
+                MOV     EAX, ADDR_LIN
+                SHR     EAX, 22                 ; Compute page directory index
+                MOV     ESI, ES:[4*EAX+0]       ; Get page directory entry
+                MOV     EDI, ES:[4*EAX+4096]    ; Get swap directory entry
+                TEST    ESI, PAGE_PRESENT       ; Page table present?
+                JNZ     SHORT SL_1              ; Yes -> continue
+                LEA     EDX, $PAGE_DIR          ; Display message
+                CALL    GTEXT
+                JMP     SL_RET                  ; Done
+SL_1:           MOV     AX, G_PHYS_SEL
+                MOV     ES, AX
+                AND     ESI, NOT 0FFFH          ; Page table address
+                MOV     EAX, ADDR_LIN           ; Get linear address
+                SHR     EAX, 12
+                AND     EAX, 03FFH              ; Page table index
+                LEA     ESI, [ESI+4*EAX]        ; Address of page table entry
+                OR      EDI, EDI
+                JZ      SHORT SL_2
+                LEA     EDI, [EDI+4*EAX]        ; Address of swap table entry
+SL_2:           LEA     EDX, $PHYSICAL
+                CALL    GTEXT
+                MOV     EBX, ADDR_LIN
+                MOV     EAX, ES:[ESI]
+                AND     EAX, NOT 0FFFH
+                AND     EBX, 0FFFH
+                OR      EAX, EBX
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     EBX, ES:[ESI]
+                MOV     AL, "P"
+                TEST    EBX, PAGE_PRESENT
+                CALL    SHOW_BIT
+                MOV     AL, "A"
+                TEST    EBX, PAGE_ACCESSED
+                CALL    SHOW_BIT
+                MOV     AL, "D"
+                TEST    EBX, PAGE_DIRTY
+                CALL    SHOW_BIT
+                TEST    EBX, PAGE_USER
+                JNZ     SHORT SL_P1
+                MOV     AL, "-"
+                CALL    GCHAR
+                JMP     SHORT SL_P2
+SL_P1:          MOV     AL, "W"
+                TEST    EBX, PAGE_WRITE
+                CALL    SHOW_BIT
+SL_P2:          MOV     AL, "L"
+                TEST    EBX, PAGE_LOCKED
+                CALL    SHOW_BIT
+                MOV     AL, "X"
+                TEST    EBX, PAGE_ALLOC
+                CALL    SHOW_BIT
+                MOV     AL, " "
+                CALL    GCHAR
+                OR      EDI, EDI                ; Swapper info table present?
+                JZ      SHORT SL_3              ; No  -> skip
+                MOV     AL, ES:[EDI]            ; Get process index
+                CALL    GBYTE                   ; Display process index
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     BX, ES:[EDI]
+                AND     BX, SRC_MASK
+                MOV     AL, "N"
+                CMP     BX, SRC_NONE
+                JE      SHORT SL_SRC
+                MOV     AL, "Z"
+                CMP     BX, SRC_ZERO
+                JE      SHORT SL_SRC
+                MOV     AL, "E"
+                CMP     BX, SRC_EXEC
+                JE      SHORT SL_SRC
+                MOV     AL, "S"
+                CMP     BX, SRC_SWAP
+                JE      SHORT SL_SRC
+                MOV     AL, "?"
+SL_SRC:         CALL    GCHAR
+                TEST    WORD PTR ES:[EDI], SWAP_ALLOC
+                MOV     AL, "X"
+                CALL    SHOW_BIT
+                JMP     SHORT SL_4
+
+SL_3:           MOV     AL, " "
+                CALL    GCHAR
+                CALL    GCHAR
+                CALL    GCHAR
+                CALL    GCHAR
+                CALL    GCHAR
+SL_4:           MOV     AL, " "
+                CALL    GCHAR
+                MOV     BX, ES:[EDI]            ; Get swapper info table entry
+                TEST    BX, SWAP_ALLOC          ; Swap space allocated?
+                JNZ     SL_EXT                  ; Yes -> show address
+                AND     BX, SRC_MASK            ; Extract SRC field
+                CMP     BX, SRC_EXEC            ; Load from exec file?
+                JNE     SHORT SL_NS             ; No  -> don't show address
+SL_EXT:         LEA     EDX, $EXTERNAL
+                CALL    GTEXT
+                MOV     EAX, ES:[EDI]
+                AND     EAX, NOT 0FFFH
+                CALL    GDWORD
+                MOV     AL, " "
+                CALL    GCHAR
+SL_NS:          CALL    GCRLF
+SL_RET:         RET
+SHOW_LIN        ENDP
+
+
+
+;
+; Set breakpoint 0 at address DX:EAX
+;
+; In:   DX:EAX  Address of breakpoint
+;
+; Out:  NZ      Error
+;
+SET_BREAKPOINT  PROC    NEAR
+                PUSH    EAX
+                PUSH    EBX
+                VERR    DX
+                JNZ     SHORT SB1
+                MOV     BREAKPOINTS[0].BP_TYPE, BP_BREAKPOINT
+                MOV     BREAKPOINTS[0].BP_SEL, DX
+                MOV     BREAKPOINTS[0].BP_OFF, EAX
+                MOV     EBX, EAX
+                MOV     AX, DX
+                CALL    GET_LIN
+                MOV     BREAKPOINTS[0].BP_ADDR, EBX
+                XOR     EAX, EAX
+SB1:            POP     EBX
+                POP     EAX
+                RET
+SET_BREAKPOINT  ENDP
+
+
+;
+; Set watchpoint (or breakpoint)
+;
+; In:   DX:EAX  Address
+;       BL      Type (BP_BREAKPOINT, BP_WATCHPOINT_?)
+;       BH      Length:
+;                 0 BYTE
+;                 1 WORD
+;                 3 DWORD
+;
+; Out:  SI      Pointer to breakpoint table entry (0 if table full)
+;       NZ      Error
+;
+SET_WATCHPOINT  PROC    NEAR
+                PUSH    EAX
+                PUSH    CX
+                VERR    DX
+                JNZ     SHORT SET_WP9
+                LEA     SI, BREAKPOINTS
+                ASSUME  SI:PTR BREAKPOINT
+                MOV     CX, 3
+SET_WP1:        ADD     SI, SIZE BREAKPOINT
+                CMP     [SI].BP_TYPE, BP_INACTIVE
+                JE      SHORT SET_WP2
+                LOOP    SET_WP1
+                XOR     SI, SI                  ; Table full
+                OR      CL, 1                   ; Set NZ
+                JMP     SHORT SET_WP9
+SET_WP2:        PUSH    EBX
+                MOV     [SI].BP_TYPE, BL
+                MOV     [SI].BP_LEN, BH
+                MOV     [SI].BP_SEL, DX
+                MOV     [SI].BP_OFF, EAX
+                MOV     EBX, EAX
+                MOV     AX, DX
+                CALL    GET_LIN
+                MOV     [SI].BP_ADDR, EBX
+                POP     EBX
+                XOR     EAX, EAX
+SET_WP9:        POP     CX
+                POP     EAX
+                RET
+                ASSUME  SI:NOTHING
+SET_WATCHPOINT  ENDP
+
+
+;
+; Insert breakpoints
+;
+                ASSUME  BP:PTR ISTACKFRAME
+INS_BREAKPOINTS PROC    NEAR
+                PUSH    ESI
+                PUSH    EDI
+                PUSH    EBX
+                CMP     DEBUG_FLAG, FALSE
+                JE      SHORT INSBP_0
+                LEA     EDX, $INSBRK
+                CALL    GTEXT
+INSBP_0:        MOV     EDI, 0                  ; DR7
+                LEA     SI, BREAKPOINTS
+                ASSUME  SI:PTR BREAKPOINT
+                MOV     DX, 4
+                MOV     CL, 0
+INSBP_1:        CMP     [SI].BP_TYPE, BP_BREAKPOINT     ; Code breakpoint?
+                JNE     SHORT INSBP_3           ; No  -> inactive or watchpoint
+                CMP     SKIP_FLAG, FALSE        ; Skipping breakpoint?
+                JE      SHORT INSBP_2           ; No  -> don't check address
+                MOV     EAX, [SI].BP_OFF
+                CMP     EAX, I_EIP              ; Breakpoint at CS:EIP?
+                JNE     SHORT INSBP_2           ; No  -> set breakpoint
+                MOV     AX, [SI].BP_SEL
+                CMP     AX, I_CS
+                JE      SHORT INSBP_9           ; Yes -> ignore breakpoint
+INSBP_2:        MOV     BL, 0
+                MOV     BH, 00H                 ; Instruction execution only
+                JMP     SHORT INSBP_5
+INSBP_3:        MOV     BL,[SI].BP_LEN
+                MOV     BH, 03H                 ; Data reads or writes only
+                CMP     [SI].BP_TYPE, BP_WATCHPOINT_R
+                JE      SHORT INSBP_4
+                MOV     BH, 01H                 ; Data writes only
+                CMP     [SI].BP_TYPE, BP_WATCHPOINT_W
+                JE      SHORT INSBP_4
+                CMP     [SI].BP_TYPE, BP_WATCHPOINT_X
+                JNE     SHORT INSBP_9
+INSBP_4:        CALL    WATCH_GET
+                MOV     [SI].BP_VAL, EAX
+INSBP_5:        CMP     DEBUG_FLAG, FALSE
+                JE      SHORT INSBP_6
+                PUSHAD
+                CALL    SHOW_BREAKPOINT
+                POPAD
+INSBP_6:        SHL     BL, 2
+                OR      BL, BH
+                MOVZX   EAX, BL
+                SHL     EAX, 16
+                SHL     EAX, CL
+                OR      EAX, 01H                ; L0
+                SHL     EAX, CL
+                OR      EDI, EAX
+                OR      EDI, 100H               ; LE
+                MOV     EAX, [SI].BP_ADDR
+                CMP     DX, 4
+                JE      SHORT INSBP_ADDR_0
+                CMP     DX, 3
+                JE      SHORT INSBP_ADDR_1
+                CMP     DX, 2
+                JE      SHORT INSBP_ADDR_2
+INSBP_ADDR_3:   MOV     DR3, EAX
+                JMP     SHORT INSBP_9
+INSBP_ADDR_1:   MOV     DR1, EAX
+                JMP     SHORT INSBP_9
+INSBP_ADDR_2:   MOV     DR2, EAX
+                JMP     SHORT INSBP_9
+INSBP_ADDR_0:   MOV     DR0, EAX
+INSBP_9:        ADD     SI, SIZE BREAKPOINT
+                ADD     CL, 2
+                DEC     DX
+                JNZ     INSBP_1
+                ASSUME  SI:NOTHING
+                MOV     DR7, EDI
+                POP     EBX
+                POP     EDI
+                POP     ESI
+                RET
+                ASSUME  BP:NOTHING
+INS_BREAKPOINTS ENDP
+
+;
+; Read watch area
+;
+; In:   DS:SI   Pointer to breakpoint table entry
+;
+; Out:  EAX     Contents
+;
+                ASSUME  SI:PTR BREAKPOINT
+WATCH_GET       PROC    NEAR
+                PUSH    ES
+                PUSH    EDI
+                MOV     ES, [SI].BP_SEL
+                MOV     EDI, [SI].BP_OFF
+                CMP     [SI].BP_LEN, 0
+                JE      SHORT WATCH_GET_1
+                CMP     [SI].BP_LEN, 1
+                JE      SHORT WATCH_GET_2
+                MOV     EAX, ES:[EDI]
+WATCH_GET_RET:  POP     EDI
+                POP     ES
+                RET
+WATCH_GET_1:    MOVZX   EAX, BYTE PTR ES:[EDI]
+                JMP     SHORT WATCH_GET_RET
+WATCH_GET_2:    MOVZX   EAX, WORD PTR ES:[EDI]
+                JMP     SHORT WATCH_GET_RET
+                ASSUME  SI:NOTHING
+WATCH_GET       ENDP
+
+
+;
+; Input command line
+;
+; In:   AL      First character
+;
+; Out:  BX      Pointer to first non-blank character (DS=SV_DATA)
+;       CY      Error (never)
+;
+INPUT           PROC    NEAR
+                CALL    GCHAR
+                LEA     BX, INPUT_BUF
+                MOV     CL, 0
+INPUT_LOOP:     CALL    GINCHAR
+                CMP     AL, " "
+                JAE     SHORT INPUT_PUT
+                CMP     AL, LF
+                JE      SHORT INPUT_END
+                CMP     AL, CR
+                JE      SHORT INPUT_END
+                CMP     AL, 08H                 ; ^H
+                JE      SHORT INPUT_BACK
+                CMP     AL, 7FH                 ; DEL
+                JE      SHORT INPUT_BACK
+                CMP     AL, 15H                 ; ^U
+                JE      SHORT INPUT_KILL
+                CMP     AL, 18H                 ; ^X
+                JE      SHORT INPUT_KILL
+INPUT_BEEP:     MOV     AL, 07H
+                CALL    GCHAR
+                JMP     SHORT INPUT_LOOP
+                
+
+INPUT_PUT:      CMP     CL, 64
+                JAE     SHORT INPUT_BEEP
+                MOV     [BX], AL
+                INC     BX
+                INC     CL
+                CALL    GCHAR
+                JMP     SHORT INPUT_LOOP
+
+INPUT_BACK:     CMP     CL, 0
+                JE      SHORT INPUT_LOOP
+                CALL    INPUT_DEL
+                JMP     SHORT INPUT_LOOP
+
+INPUT_END:      MOV     BYTE PTR [BX], 0
+                CALL    GCRLF
+                LEA     BX, INPUT_BUF
+                CALL    SKIP
+                CLC
+                RET
+
+INPUT_KILL:     CMP     CL, 0
+                JE      SHORT INPUT_LOOP
+                CALL    INPUT_DEL
+                JMP     SHORT INPUT_KILL
+
+INPUT           ENDP
+
+
+INPUT_DEL       PROC    NEAR
+                DEC     CL
+                DEC     BX
+                MOV     AL, 08H
+                CALL    GCHAR
+                MOV     AL, " "
+                CALL    GCHAR
+                MOV     AL, 08H
+                CALL    GCHAR
+                RET
+INPUT_DEL       ENDP
+
+
+;
+; Fetch next character
+;
+; In:   BX      Pointer to input (DS=SV_DATA)
+;
+; Out:  AL      Character (uppercase)
+;       ZR      End of line
+;       BX      Advanced to next character
+;
+FETCH           PROC    NEAR
+FETCH1:         MOV     AL, [BX]
+                CALL    END_OF_LINE
+                JZ      SHORT FETCH9
+                INC     BX
+                CALL    UPPER
+                OR      AL, AL
+FETCH9:         RET
+FETCH           ENDP
+
+;
+; Skip blanks and TABs
+;
+; In:   BX      Pointer to input (DS=SV_DATA)
+;
+; Out:  BX      Next character
+;
+SKIP            PROC    NEAR
+SKIP1:          CMP     BYTE PTR [BX], " "
+                JE      SHORT SKIP2
+                CMP     BYTE PTR [BX], TAB
+                JNE     SHORT SKIP9
+SKIP2:          INC     BX
+                JMP     SHORT SKIP1
+SKIP9:          RET
+SKIP            ENDP
+
+
+;
+; Check for argument delimiter
+;
+; In:   BX      Pointer to input (DS=SV_DATA)
+;
+; Out:  ZR      Delimiter
+;
+DELIM:          CMP     BYTE PTR [BX], TAB
+                JE      SHORT EOL9
+                CMP     BYTE PTR [BX], " "
+                JE      SHORT EOL9
+;
+; Check for end of line
+;
+; In:   BX      Pointer to input (DS=SV_DATA)
+;
+; Out:  ZR      End of line
+;
+END_OF_LINE:    CMP     BYTE PTR [BX], 00H
+                JE      SHORT EOL9
+                CMP     BYTE PTR [BX], LF
+                JE      SHORT EOL9
+                CMP     BYTE PTR [BX], CR
+EOL9:           RET
+
+
+;
+; Parse an address range
+;
+; In:   BX      Pointer to input (DS=SV_DATA)
+;       DX      Default selector
+;
+; Out:  CY      Error
+;       DX      Selector
+;       EAX     Offset
+;       ECX     Size
+;       EDX     Error message
+;
+GET_RANGE       PROC    NEAR
+                CALL    GET_ADDR
+                JC      SHORT GRNG_INPUT_ERROR
+GET_RANGE_MORE::VERR    DX
+                JNZ     SHORT GRNG_INVALID_SEL
+                MOV     RANGE_SEL, DX
+                MOV     RANGE_OFF, EAX
+                CALL    GET_ADDR                ; Keep DX
+                JC      SHORT GRNG_INPUT_ERROR
+                CMP     DX, RANGE_SEL
+                JNE     SHORT GRNG_INPUT_ERROR
+                AND     EDX, 0FFFFH
+                LSL     ECX, EDX
+                CMP     EAX, ECX
+                JA      SHORT GRNG_BEYOND_LIMIT
+                SUB     EAX, RANGE_OFF
+                JB      SHORT GRNG_INPUT_ERROR
+                INC     EAX
+                MOV     ECX, EAX
+                MOV     EAX, RANGE_OFF
+                CLC
+                RET
+
+GRNG_BEYOND_LIMIT:
+                LEA     EDX, $BEYOND_LIMIT
+                JMP     SHORT GRNG_ERROR
+
+GRNG_INVALID_SEL:
+                LEA     EDX, $INVALID_SEL
+                JMP     SHORT GRNG_ERROR
+
+GRNG_INPUT_ERROR:
+                LEA     EDX, $INPUT_ERROR
+GRNG_ERROR:     STC
+                RET
+GET_RANGE       ENDP
+
+
+;
+; Parse an address
+;
+; In:   BX      Pointer to input (DS=SV_DATA)
+;       DX      Default selector
+;
+; Out:  CY      Error
+;       DX      Selector
+;       EAX     Offset
+;
+GET_ADDR        PROC    NEAR
+                PUSH    BX
+                CALL    GET_NUMBER
+                JC      SHORT GET_ADDR_1
+                CMP     BYTE PTR [BX], ":"
+                JNE     SHORT GET_ADDR_END
+                INC     BX
+                MOV     DX, AX
+                CALL    GET_NUMBER
+                JC      SHORT GET_ADDR_1
+GET_ADDR_END:   CALL    DELIM
+                JZ      SHORT GET_ADDR_OK
+GET_ADDR_1:     POP     BX
+                PUSH    BX
+                PUSH    DI
+                LEA     DI, SYMBOL_BUF
+                MOV     BYTE PTR [DI], "_"
+                INC     DI
+GET_ADDR_S1:    MOV     AL, [BX]
+                CMP     AL, " "
+                JE      SHORT GET_ADDR_S2
+                CMP     AL, TAB
+                JE      SHORT GET_ADDR_S2
+                CALL    END_OF_LINE
+                JZ      SHORT GET_ADDR_S2
+                MOV     [DI], AL
+                INC     DI
+                INC     BX
+                JMP     SHORT GET_ADDR_S1
+GET_ADDR_S2:    MOV     BYTE PTR [DI], 0
+                PUSH    BX
+                MOV     DI, PROCESS_PTR
+                LEA     BX, SYMBOL_BUF
+                CALL    SYM_BY_NAME
+                JNC     GET_ADDR_S3
+                POP     BX
+                POP     DI
+                JMP     SHORT GET_ADDR_ERROR
+GET_ADDR_S3:    POP     BX
+                POP     DI
+                PUSH    EAX
+                CALL    DELIM
+                POP     EAX
+                JNZ     SHORT GET_ADDR_ERROR
+                XCHG    EAX, EDX
+                CMP     DL, SYM_TEXT
+                MOV     DX, L_CODE_SEL
+                JE      SHORT GET_ADDR_OK
+                MOV     DX, L_DATA_SEL
+GET_ADDR_OK:    CALL    SKIP
+                CLC
+                JMP     SHORT GET_ADDR_RET
+GET_ADDR_ERROR: STC
+GET_ADDR_RET:   ADD     ESP, 2                  ; Remove BX
+                RET
+GET_ADDR        ENDP
+
+;
+; Parse a value (number or register or character constant)
+;
+; In:   BX      Pointer to input (DS=SV_DATA)
+;
+; Out:  CY      Error
+;       BX      Points to next character
+;       EAX     Value
+;
+GET_NUMBER      PROC    NEAR
+                PUSH    EDX
+                PUSH    CX
+                CMP     BYTE PTR [BX], "'"
+                JE      SHORT GNUM_CHR
+                CALL    GET_REG
+                JNC     SHORT GNUM_REG
+GNUM0:          XOR     EDX, EDX
+                MOV     CX, 0
+GNUM1:          MOVZX   EAX, BYTE PTR [BX]
+                SUB     AL, "0"
+                JB      SHORT GNUM_END
+                CMP     AL, 10
+                JB      SHORT GNUM2
+                ADD     AL, "0"-"A"+10
+                CMP     AL, 10
+                JB      SHORT GNUM_END
+                CMP     AL, 16
+                JB      SHORT GNUM2
+                ADD     AL, "A"-"a"
+                CMP     AL, 10
+                JB      SHORT GNUM_END
+                CMP     AL, 16
+                JAE     SHORT GNUM_END
+GNUM2:          SHL     EDX, 4
+                ADD     EDX, EAX
+                INC     BX
+                INC     CX
+                JMP     SHORT GNUM1
+GNUM_END:       JCXZ    GNUM_ERROR
+                MOV     EAX, EDX
+GNUM_OK:        CLC
+                JMP     SHORT GNUM_RET
+
+GNUM_REG:       XCHG    BX, DX
+                CMP     AL, R8
+                JE      SHORT GNUM_REG_R8
+                CMP     AL, R16
+                JE      SHORT GNUM_REG_R16
+GNUM_REG_R32:   MOV     EAX, SS:[BX]
+                JMP     SHORT GNUM_REG2
+GNUM_REG_R16:   MOVZX   EAX, WORD PTR SS:[BX]
+                JMP     SHORT GNUM_REG2
+GNUM_REG_R8:    MOVZX   EAX, BYTE PTR SS:[BX]
+GNUM_REG2:      XCHG    BX, DX
+                JMP     SHORT GNUM_OK
+
+GNUM_CHR:       INC     BX
+                CALL    END_OF_LINE
+                JZ      SHORT GNUM_ERROR
+                MOVZX   EAX, BYTE PTR [BX]
+                INC     BX
+                CMP     BYTE PTR [BX], "'"
+                JNZ     SHORT GNUM_ERROR
+                INC     BX
+                JMP     SHORT GNUM_RET
+
+GNUM_ERROR:     STC
+GNUM_RET:       POP     CX
+                POP     EDX
+                RET
+GET_NUMBER      ENDP
+
+;
+; Parse a register name
+;
+; In:   BX      Pointer to input (DS=SV_DATA)
+;
+; Out:  CY      Error
+;       DX      Pointer to register (offset into stack segment; SS:DX)
+;       AX      Register size (R8, R16, R32)
+;
+                ASSUME  BP:PTR ISTACKFRAME
+GET_REG         PROC    NEAR
+                PUSH    SI
+                PUSH    DI
+                MOV     DI, BX
+                LEA     SI, REG_TAB
+                CLD
+GREG1:          LODS    REG_TAB
+                CMP     AL, 0FFH
+                JE      SHORT GREG_LOSE
+                CMP     AL, R32
+                JBE     SHORT GREG10
+                MOV     AH, AL
+                CALL    FETCH
+                CMP     AL, AH
+                JE      SHORT GREG1
+GREG2:          LODS    REG_TAB
+                CMP     AL, R32
+                JA      SHORT GREG2
+GREG3:          INC     SI
+                MOV     BX, DI
+                JMP     SHORT GREG1
+
+GREG10:         MOVZX   DX, BYTE PTR [SI]
+                CMP     DX, 56                  ; ESP, SS
+                JB      SHORT GREG11
+                TEST    I_CS, 3                 ; RPL=0?
+                JZ      SHORT GREG3
+GREG11:         ADD     DX, BP
+                XOR     AH, AH
+                JMP     SHORT GREG_RET
+
+GREG_LOSE:      MOV     BX, DI
+                STC
+GREG_RET:       POP     DI
+                POP     SI
+                RET
+                ASSUME  BP:NOTHING
+GET_REG         ENDP
+
+
+;
+; Display a number in decimal notation
+;
+; In:   EAX     Number
+;
+DECIMAL         PROC    NEAR
+                PUSH    EDX
+                PUSH    ECX
+                CALL    DECIMAL2
+                POP     ECX
+                POP     EDX
+                RET
+
+DECIMAL1:       OR      EAX, EAX
+                JZ      SHORT DECIMAL9
+DECIMAL2:       XOR     EDX, EDX
+                MOV     ECX, 10
+                DIV     ECX
+                PUSH    EDX
+                CALL    DECIMAL1
+                POP     EAX
+                ADD     AL, "0"
+                CALL    GCHAR
+DECIMAL9:       RET                
+DECIMAL         ENDP
+
+
+                ASSUME  DS:SV_DATA
+DEBUG_INIT      PROC    NEAR
+                CMP     DEBUG_SER_FLAG, FALSE
+                JE      SHORT DEBUG_INIT_RET
+                MOV     GDWORD, OFFSET SV_CODE:S_DWORD
+                MOV     GWORD, OFFSET SV_CODE:S_WORD
+                MOV     GBYTE, OFFSET SV_CODE:S_BYTE
+                MOV     GTEXT, OFFSET SV_CODE:S_TEXT
+                MOV     GCRLF, OFFSET SV_CODE:S_CRLF
+                MOV     GCHAR, OFFSET SV_CODE:S_CHAR
+                MOV     GINCHAR, OFFSET SV_CODE:S_INCHAR
+DEBUG_INIT_RET: RET
+DEBUG_INIT      ENDP
+
+
+                ASSUME  DS:SV_DATA
+DEBUG_QUIT      PROC    NEAR
+                CMP     STEP_FLAG, FALSE
+                JE      SHORT DQ_RET
+                LEA     EDX, $SWAP_FAULTS
+                CALL    GTEXT
+                MOV     EAX, SWAP_FAULTS
+                CALL    DECIMAL
+                LEA     EDX, $SWAP_READS
+                CALL    GTEXT
+                MOV     EAX, SWAP_READS
+                CALL    DECIMAL
+                LEA     EDX, $SWAP_WRITES
+                CALL    GTEXT
+                MOV     EAX, SWAP_WRITES
+                CALL    DECIMAL
+                LEA     EDX, $SNATCH_COUNT
+                CALL    GTEXT
+                MOV     EAX, SNATCH_COUNT
+                CALL    DECIMAL
+                LEA     EDX, $SWAP_SIZE
+                CALL    GTEXT
+                MOV     EAX, SWAP_SIZE
+                CALL    DECIMAL
+                CALL    GCRLF
+                CALL    CHECK_HANDLES
+DQ_RET:         RET
+DEBUG_QUIT      ENDP
+
+
+                ASSUME  DS:SV_DATA
+B_DWORD         PROC    NEAR
+                ROR     EAX, 16
+                CALL    B_WORD
+                ROR     EAX, 16
+                CALL    B_WORD
+                RET
+B_DWORD         ENDP
+
+                ASSUME  DS:SV_DATA
+B_WORD          PROC    NEAR
+                XCHG    AL, AH
+                CALL    B_BYTE
+                XCHG    AL, AH
+                CALL    B_BYTE
+                RET
+B_WORD          ENDP
+
+
+                ASSUME  DS:SV_DATA
+B_BYTE          PROC    NEAR
+                PUSH    AX
+                SHR     AL, 4
+                CALL    B_NIBBLE
+                POP     AX
+                PUSH    AX
+                CALL    B_NIBBLE
+                POP     AX
+                RET
+B_BYTE          ENDP
+
+                ASSUME  DS:SV_DATA
+B_NIBBLE        PROC    NEAR
+                AND     AL, 0FH
+                ADD     AL, 30H
+                CMP     AL, 3AH
+                JB      SHORT SNIB1
+                ADD     AL, 7
+SNIB1:          CALL    B_CHAR
+                RET
+B_NIBBLE        ENDP
+
+
+                ASSUME  DS:SV_DATA
+B_TEXT          PROC    NEAR
+                PUSH    AX
+B_TEXT1:        MOV     AL, DS:[EDX]
+                CMP     AL, 0
+                JE      SHORT B_TEXT9
+                CALL    B_CHAR
+                INC     EDX
+                JMP     SHORT B_TEXT1
+B_TEXT9:        POP     AX
+                RET
+B_TEXT          ENDP
+
+                ASSUME  DS:SV_DATA
+B_CHAR          PROC    NEAR
+                PUSH    AX
+                PUSH    BX
+                CMP     AL, TAB
+                JE      SHORT BC_TAB
+                INC     B_COLUMN
+                CMP     AL, CR
+                JNE     SHORT BC_1
+                MOV     B_COLUMN, 0
+BC_1:           MOV     BX, 0007H
+                MOV     AH, 0EH
+                INT     10H
+BC_RET:         POP     BX
+                POP     AX
+                RET
+
+BC_TAB:         MOV     AH, B_COLUMN
+                NOT     AH
+                AND     AH, 7
+                INC     AH
+                MOV     AL, " "
+BC_TAB_1:       CALL    B_CHAR
+                DEC     AH
+                JNZ     SHORT BC_TAB_1
+                JMP     SHORT BC_RET
+B_CHAR          ENDP
+
+                ASSUME  DS:SV_DATA
+B_CRLF          PROC    NEAR
+                PUSH    AX
+                MOV     AL, CR
+                CALL    B_CHAR
+                MOV     AL, LF
+                CALL    B_CHAR
+                POP     AX
+                RET
+B_CRLF          ENDP
+
+                ASSUME  DS:SV_DATA
+B_INCHAR        PROC    NEAR
+                XOR     AL, AL
+                XCHG    AL, B_NEXT
+                TEST    AL, AL
+                JNZ     SHORT B_INCHAR_RET
+B_INCHAR_LOOP:  MOV     AH, 0
+                INT     16H
+                TEST    AL, AL
+                JNZ     SHORT B_INCHAR_RET
+                TEST    AH, AH
+                JZ      SHORT B_INCHAR_LOOP
+                MOV     B_NEXT, AH
+B_INCHAR_RET:   RET
+B_INCHAR        ENDP
+
+                ASSUME  DS:SV_DATA
+S_DWORD         PROC    NEAR
+                ROR     EAX, 16
+                CALL    S_WORD
+                ROR     EAX, 16
+                CALL    S_WORD
+                RET
+S_DWORD         ENDP
+
+                ASSUME  DS:SV_DATA
+S_WORD          PROC    NEAR
+                XCHG    AL, AH
+                CALL    S_BYTE
+                XCHG    AL, AH
+                CALL    S_BYTE
+                RET
+S_WORD          ENDP
+
+
+                ASSUME  DS:SV_DATA
+S_BYTE          PROC    NEAR
+                PUSH    AX
+                SHR     AL, 4
+                CALL    S_NIBBLE
+                POP     AX
+                PUSH    AX
+                CALL    S_NIBBLE
+                POP     AX
+                RET
+S_BYTE          ENDP
+
+                ASSUME  DS:SV_DATA
+S_NIBBLE        PROC    NEAR
+                AND     AL, 0FH
+                ADD     AL, 30H
+                CMP     AL, 3AH
+                JB      SHORT SNIB1
+                ADD     AL, 7
+SNIB1:          CALL    S_CHAR
+                RET
+S_NIBBLE        ENDP
+
+
+                ASSUME  DS:SV_DATA
+S_TEXT          PROC    NEAR
+                PUSH    AX
+S_TEXT1:        MOV     AL, DS:[EDX]
+                CMP     AL, 0
+                JE      SHORT S_TEXT9
+                CALL    S_CHAR
+                INC     EDX
+                JMP     SHORT S_TEXT1
+S_TEXT9:        POP     AX
+                RET
+S_TEXT          ENDP
+
+                ASSUME  DS:SV_DATA
+S_CHAR          PROC    NEAR
+                PUSH    AX
+                PUSH    DX
+                MOV     AH, AL
+S_CHAR0:        MOV     DX, DEBUG_SER_PORT
+                ADD     DX, 4
+                MOV     AL, 3
+                OUT     DX, AL
+                INC     DX
+S_CHAR1:        IN      AL, DX                  ; Read line status
+                TEST    AL, 01H                 ; Input character ready?
+                JZ      SHORT S_CHAR2           ; No  -> check for output
+                SUB     DX, 5                   ; Receiver register
+                IN      AL, DX                  ; Read input character
+                CMP     AL, 13H                 ; ^S (XOFF)?
+                JE      SHORT S_CHAR_XOFF       ; Yes -> stop
+                CMP     AL, 11H                 ; ^Q (XON)?
+                JE      SHORT S_CHAR_XON        ; Yes -> continue
+                CMP     LOOK_AHEAD, 0           ; Input buffer full?
+                JNE     SHORT S_CHAR0           ; Yes -> discard, repeat
+                MOV     LOOK_AHEAD, AL          ; Save input character
+                JMP     SHORT S_CHAR0           ; (if non-zero)
+
+S_CHAR2:        TEST    AL, 20H                 ; Transmitter empty?
+                JZ      SHORT S_CHAR1           ; No  -> repeat
+                CMP     XOFF, FALSE             ; Stopped?
+                JNE     SHORT S_CHAR1           ; Yes -> repeat
+                SUB     DX, 5                   ; Transmitter register
+                MOV     AL, AH                  ; Write character
+                OUT     DX, AL                  ; to transmitter register
+                POP     DX
+                POP     AX
+                RET
+
+S_CHAR_XON:     MOV     XOFF, FALSE
+                JMP     SHORT S_CHAR1
+
+S_CHAR_XOFF:    MOV     XOFF, NOT FALSE
+                JMP     SHORT S_CHAR1
+
+S_CHAR          ENDP
+
+                ASSUME  DS:SV_DATA
+S_CRLF          PROC    NEAR
+                PUSH    AX
+                MOV     AL, CR
+                CALL    S_CHAR
+                MOV     AL, LF
+                CALL    S_CHAR
+                POP     AX
+                RET
+S_CRLF          ENDP
+
+
+                ASSUME  DS:SV_DATA
+S_INCHAR        PROC    NEAR
+                PUSH    DX
+                XOR     AL, AL
+                XCHG    AL, LOOK_AHEAD          ; Examine input buffer
+                OR      AL, AL                  ; Non-empty?
+                JNZ     SHORT S_INCHAR_RET      ; Yes -> use buffered character
+S_INCHAR1:      MOV     DX, DEBUG_SER_PORT
+                ADD     DX, 4
+                MOV     AL, 3
+                OUT     DX, AL
+                INC     DX                      ; Line status register
+S_INCHAR2:      IN      AL, DX                  ; Read line status
+                TEST    AL, 01H                 ; Input character ready?
+                JZ      SHORT S_INCHAR2         ; No  -> repeat
+                SUB     DX, 5                   ; Receiver register
+                IN      AL, DX                  ; Read input character
+                OR      AL, AL                  ; NUL?
+                JZ      SHORT S_INCHAR2         ; Yes -> discard, repeat
+                CMP     AL, 13H                 ; ^S (XOFF)?
+                JE      SHORT S_INCHAR_XOFF     ; Yes -> stop
+                CMP     AL, 11H                 ; ^Q (XON)?
+                JE      SHORT S_INCHAR_XON      ; Yes -> continue
+S_INCHAR_RET:   POP     DX
+                RET
+
+S_INCHAR_XON:   MOV     XOFF, FALSE
+                JMP     SHORT S_INCHAR1
+
+S_INCHAR_XOFF:  MOV     XOFF, NOT FALSE
+                JMP     SHORT S_INCHAR1
+
+
+S_INCHAR        ENDP
+
+
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/debug.inc
===================================================================
--- trunk/src/emx/src/dos/debug.inc	(revision 18)
+++ trunk/src/emx/src/dos/debug.inc	(revision 18)
@@ -0,0 +1,46 @@
+;
+; DEBUG.INC -- Built-in debugger
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+
+SV_DATA         SEGMENT
+
+                EXTRN   STEP_FLAG:BYTE
+                EXTRN   DEBUG_AVAIL:BYTE
+                EXTRN   DEBUG_SER_FLAG:BYTE
+                EXTRN   DEBUG_SER_PORT:WORD
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                EXTRN   DEBUG_EXCEPTION:NEAR
+                EXTRN   SET_BREAKPOINT:NEAR
+                EXTRN   INS_BREAKPOINTS:NEAR
+                EXTRN   DEBUG_RESUME:NEAR
+                EXTRN   DEBUG_STEP:NEAR
+                EXTRN   DEBUG_INIT:NEAR
+                EXTRN   DEBUG_QUIT:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/disasm.asm
===================================================================
--- trunk/src/emx/src/dos/disasm.asm	(revision 18)
+++ trunk/src/emx/src/dos/disasm.asm	(revision 18)
@@ -0,0 +1,2666 @@
+;
+; DISASM.ASM -- Disassembler
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+DISASM_FLAG     =       1               ; Include disassembler?
+                                        ; Not yet implemented
+
+                INCLUDE EMX.INC
+                INCLUDE SYMBOLS.INC
+
+                PUBLIC  DISASM
+
+              IF DISASM_FLAG
+
+SV_DATA         SEGMENT
+
+SIZE_ON         =       01H
+SIZE_OFF        =       00H
+
+F_SIGNED        =       01H
+F_EMPTY         =       02H
+F_NO_PTR        =       04H
+
+V_REPE          =       1
+V_REPNE         =       2
+
+RELOCATION      DD      ?               ; Add this to EIP
+MODE_32         DB      ?               ; Operand/address size (default)
+PFX_ASIZE       DB      ?               ; Address size prefix
+PFX_OSIZE       DB      ?               ; Operand size prefix
+PFX_SEG         DB      ?               ; Segment override
+PFX_REP         DB      ?               ; Repeat prefix
+PFX_LOCK        DB      ?
+FLAGS           DB      ?
+OPCODE          DB      ?
+OPSIZE          DB      ?
+MOD_REG_RM      DB      ?
+SIB             DB      ?
+ACCU            DB      ?
+SYM_FLAG        DB      ?
+SYM_ADDR        DD      ?
+
+$REG16          DB      "AXCXDXBXSPBPSIDI"
+$REG8           DB      "ALCLDLBLAHCHDHBH"
+
+$BYTE           DB      "byte", 0
+$DWORD          DB      "d"
+$WORD           DB      "word", 0
+$PTR            DB      " ptr ",0
+
+                DW      32 DUP (?)
+DISASM_STACK    LABEL   WORD
+DISASM_SP       DW      ?
+                DB      16 DUP (?)
+ACCU_STACK      LABEL   BYTE
+ACCU_SP         DW      ?
+
+NOT_FLAG        DB      ?
+
+RM_BX           =       01H
+RM_BP           =       02H
+RM_SI           =       04H
+RM_DI           =       08H
+
+RM_TAB          DB      RM_BX+RM_SI
+                DB      RM_BX+RM_DI
+                DB      RM_BP+RM_SI
+                DB      RM_BP+RM_DI
+                DB      RM_SI
+                DB      RM_DI
+                DB      RM_BP
+                DB      RM_BX
+
+DISASM_JMP      DW      Q_END, Q_DWORD, Q_JUMP, Q_DISP
+                DW      Q_NOT, Q_OPCODE, Q_SWITCH, Q_MASK_EQ
+                DW      Q_LD_MOD_REG_RM, Q_TEST, Q_BITS, Q_CMP
+                DW      Q_REG, Q_REGA, Q_MEM, Q_FLAGS
+                DW      Q_NIBBLE, Q_ACCUM, Q_MORE, Q_O16
+                DW      Q_A16, Q_BYTE, Q_WORD, Q_TABLE
+                DW      Q_RET, Q_PREFIX, Q_EXT, Q_OP_SIZE
+                DW      Q_JMP_DST, Q_IMMED, Q_MOD_REG_RM, Q_OP
+
+EXT_JMP         DW      Q_PUSH, Q_POP, Q_XCHG, Q_BACK
+
+Z_END           =       00H
+Z_DWORD         =       01H
+Z_JUMP          =       02H
+Z_DISP          =       03H
+Z_NOT           =       04H
+Z_OPCODE        =       05H
+Z_SWITCH        =       06H
+Z_MASK_EQ       =       07H
+Z_LD_MOD_REG_RM =       08H
+Z_TEST          =       09H
+Z_BITS          =       0AH
+Z_CMP           =       0BH
+Z_REG           =       0CH
+Z_REGA          =       0DH
+Z_MEM           =       0EH
+Z_FLAGS         =       0FH
+Z_NIBBLE        =       10H
+Z_ACCUM         =       11H
+Z_MORE          =       12H
+Z_O16           =       13H
+Z_A16           =       14H
+Z_BYTE          =       15H
+Z_WORD          =       16H
+Z_TABLE         =       17H
+Z_RET           =       18H
+Z_PREFIX        =       19H
+Z_EXT           =       1AH                     ; Currently not used
+Z_OP_SIZE       =       1BH
+Z_JMP_DST       =       1CH
+Z_IMMED         =       1DH
+Z_MOD_REG_RM    =       1EH
+Z_OP            =       1FH
+
+ZE_PUSH         =       00H
+ZE_POP          =       01H
+ZE_XCHG         =       02H
+ZE_BACK         =       03H
+
+; ============================================================================
+; Disassembler language
+; ============================================================================
+
+;
+; Utility macros (required for expansion of numeric variables (N)
+;
+VSET            MACRO   V, N, X
+V&N             =       X
+                ENDM
+VINC            MACRO   V, N
+V&N             =       V&N + 1
+                ENDM
+VDB             MACRO   V, N
+                DB      V&N
+                ENDM
+VDW             MACRO   V, N
+                DW      V&N
+                ENDM
+
+;
+; End of program
+;
+X_END           MACRO
+                DB      Z_END
+                ENDM
+
+;
+; Fetch DWORD from input and insert into output
+;
+X_DWORD         MACRO
+                DB      Z_DWORD
+                ENDM
+
+;
+; Jump to another location
+;
+X_JUMP          MACRO   DST
+                DB      Z_JUMP
+                DW      DST
+                ENDM
+
+;
+; Call subroutine (note: no checking for stack overflow)
+;
+X_CALL          MACRO   DST
+                DB      CALL_&DST
+                ENDM
+;
+; Define subroutine
+;
+CALLCNT         =       0
+X_SUB           MACRO   NAME
+CALL_&NAME      =       80H + CALLCNT
+                VSET    CALLV,%CALLCNT, <THIS BYTE>
+CALLCNT         =       CALLCNT + 1
+                ENDM
+;
+; Negate condition of next conditional jump instruction
+;
+X_NOT           MACRO
+                DB      Z_NOT
+                ENDM
+
+;
+; X_OPCODE
+;
+; Reload opcode into accu
+;
+X_OPCODE        MACRO
+                DB      Z_OPCODE
+                ENDM
+
+
+SWCNT           =       0
+
+;
+; Switch statement (accu)
+;
+X_SWITCH        MACRO
+SWCNT           =       SWCNT+1
+                DB      Z_SWITCH
+                VDB     SWLEN, %SWCNT
+                VSET    SWLEN, %SWCNT, 0
+                ENDM
+
+;
+; One case of a switch statement: jump to DST, if accu==VALUE
+;
+X_CASE          MACRO   VALUE, DST
+                VINC    SWLEN, %SWCNT
+                DB      VALUE
+                DW      DST
+                ENDM
+
+;
+; Jump to DST, if (accu & MASK) == VALUE
+;
+X_MASK_EQ       MACRO   MASK, VALUE, DST
+                DB      Z_MASK_EQ, MASK, VALUE
+                DW      DST
+                ENDM
+
+;
+; Load accu from mod,reg,r/m byte
+;
+X_LD_MOD_REG_RM MACRO
+                DB      Z_LD_MOD_REG_RM
+                ENDM
+
+;
+; Load accu from reg field of mod,reg,r/m byte
+;
+X_LOAD_REG      MACRO
+                X_CALL  P_LOAD_REG
+                ENDM
+
+;
+; Jump to DST, if (accu & MASK) != 0
+;
+; (If we run out of instruction codes, this can be done with Z_MASK_EQ.)
+;
+X_TEST          MACRO   MASK, DST
+                DB      Z_TEST, MASK
+                DW      DST
+                ENDM
+
+;
+; Extract a bit field of accu: accu := (accu AND MASK) SHR b,
+; with b = min {i | (MASK AND (1 SHL i)) != 0}
+;
+; Example:
+;       accu = 01101101
+;       MASK = 00111000
+;     result = 00000101 (bits 3..5 of accu moved to bits 0..2)
+;
+X_BITS          MACRO   MASK
+                DB      Z_BITS, MASK
+                ENDM
+
+;
+; Jump to DST, if variable SRC contains VALUE
+;
+X_CMP           MACRO   SRC, VALUE, DST
+                DB      Z_CMP
+                DW      SRC
+                DB      VALUE
+                DW      DST
+                ENDM
+
+;
+; Insert name of register specified by reg field of reg,mod,r/m byte
+;
+X_REG           MACRO
+                DB      Z_REG
+                ENDM
+
+;
+; Insert name of register specified by bits 0..2 of accu
+;
+X_REGA          MACRO
+                DB      Z_REGA
+                ENDM
+
+;
+; Insert operand specified by mod & r/m fields of reg,mod,r/m byte
+;
+X_MEM           MACRO
+                DB      Z_MEM
+                ENDM
+
+;
+; Insert destination address of a short jump instruction
+;
+X_SHORT         MACRO
+                DB      Z_JMP_DST, 0
+                ENDM
+
+;
+; Insert destination address of a near jump instruction
+;
+X_NEAR          MACRO
+                DB      Z_JMP_DST, 1
+                ENDM
+
+;
+; Insert destination address of a far jump instruction
+;
+X_FAR           MACRO
+                DB      Z_JMP_DST, 2
+                ENDM
+
+;
+; Insert name of 8/16/32 bit accumulator (AL/AX/EAX)
+;
+X_ACCUM         MACRO
+                DB      Z_ACCUM
+                ENDM
+
+;
+; Jump to DST, if operand size = 16 bit
+;
+X_O16           MACRO   DST
+                DB      Z_O16
+                DW      DST
+                ENDM
+
+;
+; Jump to DST, if address size = 16 bit
+;
+X_A16           MACRO   DST
+                DB      Z_A16
+                DW      DST
+                ENDM
+
+;
+; Fetch mod,reg,r/m byte
+;
+X_MOD_REG_RM    MACRO
+                DB      Z_MOD_REG_RM
+                ENDM
+
+;
+; Insert opcode / operand delimiter into output
+;
+X_OP            MACRO
+                DB      Z_OP
+                ENDM
+
+;
+; Fetch BYTE from input and insert into output
+;
+X_BYTE          MACRO
+                DB      Z_BYTE
+                ENDM
+
+;
+; Fetch WORD from input and insert into output
+;
+X_WORD          MACRO
+                DB      Z_WORD
+                ENDM
+
+;
+; Insert [xxxx] (WORD/DWORD, depending on address size)
+;
+X_DISP          MACRO
+                DB      Z_DISP
+                ENDM
+
+;
+; Table jump: load accu'th (0..255) word following this instruction
+;             into instruction pointer
+; Attention:  be sure that there's a table entry for all possible values
+;             of accu!
+;
+X_TABLE         MACRO
+                DB      Z_TABLE
+                ENDM
+
+;
+; Return from subroutine
+;
+X_RET           MACRO
+                DB      Z_RET
+                ENDM
+
+;
+; Handle prefix instruction: store VALUE to variable PREFIX,
+; fetch next opcode byte, and restart program
+;
+X_PREFIX        MACRO   PREFIX, VALUE
+                DB      Z_PREFIX
+                DW      PREFIX
+                DB      VALUE
+                ENDM
+
+;
+; Insert operand / operand delimiter into output
+;
+X_COMMA         MACRO
+                X_CALL  P_COMMA
+                ENDM
+
+;
+; Switch operand size to BYTE (note 1)
+;
+X_BYTE_OP       MACRO
+                DB      Z_OP_SIZE, 00H
+                ENDM
+
+;
+; Switch operand size to WORD (note 1)
+;
+X_WORD_OP       MACRO
+                DB      Z_OP_SIZE, 01H
+                ENDM
+
+;
+; Switch operand size to FWORD (note 1)
+;
+X_FAR_OP        MACRO
+                DB      Z_OP_SIZE, 02H
+                ENDM
+
+;
+; Insert immediate operand into output (uses F_SIGNED flag)
+;
+X_IMMED         MACRO
+                DB      Z_IMMED
+                ENDM
+
+;
+; Fetch next opcode byte
+;
+X_MORE          MACRO
+                DB      Z_MORE
+                ENDM
+
+;
+; Set F_SIGNED flag (for immediate operands)
+;
+X_SIGNED        MACRO
+                DB      Z_FLAGS, F_SIGNED
+                ENDM
+
+;
+; Set F_EMPTY flag (after JMP/RET/... instructions)
+;
+X_EMPTY         MACRO
+                DB      Z_FLAGS, F_EMPTY
+                ENDM
+
+;
+; Set F_NO_PTR flag (omit `byte ptr' etc.)
+;
+X_NO_PTR        MACRO
+                DB      Z_FLAGS, F_NO_PTR
+                ENDM
+
+;
+; Insert accu into output (bits 0..3 in hexadecimal representation)
+;
+X_NIBBLE        MACRO
+                DB      Z_NIBBLE
+                ENDM
+
+;
+; Push accu on stack
+;
+X_PUSH          MACRO
+                DB      Z_EXT, ZE_PUSH
+                ENDM
+
+
+;
+; Pop accu from stack
+;
+X_POP           MACRO
+                DB      Z_EXT, ZE_POP
+                ENDM
+
+
+;
+; Exchange accu with top of stack
+;
+X_XCHG          MACRO
+                DB      Z_EXT, ZE_XCHG
+                ENDM
+
+
+;
+; Backup one byte
+;
+X_BACK          MACRO
+                DB      Z_EXT, ZE_BACK
+                ENDM
+
+
+;
+; Note 1: The default operand size is determined by bit 0 (w) of the
+;         current opcode byte.
+;
+
+; ============================================================================
+; This is the 80386 disassembler, written in disassembler language
+; ============================================================================
+;
+; If I had time, I would create a compiler which translates a C like
+; language to this object code. Example:
+;
+;       if (op & 0xf8 == 0x50)
+;           {
+;           "PUSH\t"; word_op; reg_a; end;
+;           }
+;
+; But of course I don't have time. Therefore, this disassembler is
+; somewhat cryptic.
+;
+;
+DISASM_PROGRAM  LABEL   BYTE
+                X_SWITCH
+                X_CASE   0FH, P_0F
+                X_CASE   26H, P_ES
+                X_CASE   27H, P_DAA
+                X_CASE   2EH, P_CS
+                X_CASE   2FH, P_DAS
+                X_CASE   36H, P_SS
+                X_CASE   37H, P_AAA
+                X_CASE   3EH, P_DS
+                X_CASE   3FH, P_AAS
+                X_CASE   60H, P_PUSHA
+                X_CASE   61H, P_POPA
+                X_CASE   62H, P_BOUND
+                X_CASE   63H, P_ARPL
+                X_CASE   64H, P_FS
+                X_CASE   65H, P_GS
+                X_CASE   66H, P_O_PFX
+                X_CASE   67H, P_A_PFX
+                X_CASE   8DH, P_LEA
+                X_CASE   8FH, P_POP_MEM
+                X_CASE   90H, P_NOP
+                X_CASE   98H, P_CBW
+                X_CASE   99H, P_CDQ
+                X_CASE   9AH, P_CALLF
+                X_CASE   9BH, P_WAIT
+                X_CASE   9CH, P_PUSHF
+                X_CASE   9DH, P_POPF
+                X_CASE   9EH, P_SAHF
+                X_CASE   9FH, P_LAHF
+                X_CASE  0C4H, P_LES
+                X_CASE  0C5H, P_LDS
+                X_CASE  0C8H, P_ENTER
+                X_CASE  0C9H, P_LEAVE
+                X_CASE  0CCH, P_INT3
+                X_CASE  0CDH, P_INT
+                X_CASE  0CEH, P_INTO
+                X_CASE  0CFH, P_IRET
+                X_CASE  0D4H, P_AAM
+                X_CASE  0D5H, P_AAD
+                X_CASE  0D7H, P_XLAT
+                X_CASE  0E0H, P_LOOPNE
+                X_CASE  0E1H, P_LOOPE
+                X_CASE  0E2H, P_LOOP
+                X_CASE  0E3H, P_JCXZ
+                X_CASE  0E8H, P_CALLN
+                X_CASE  0E9H, P_JMPN
+                X_CASE  0EAH, P_JMPF
+                X_CASE  0EBH, P_JMPS
+                X_CASE  0F0H, P_LOCK
+                X_CASE  0F2H, P_REPNE
+                X_CASE  0F3H, P_REPE
+                X_CASE  0F4H, P_HLT
+                X_CASE  0F5H, P_CMC
+                X_CASE  0F8H, P_CLC
+                X_CASE  0F9H, P_STC
+                X_CASE  0FAH, P_CLI
+                X_CASE  0FBH, P_STI
+                X_CASE  0FCH, P_CLD
+                X_CASE  0FDH, P_STD
+                X_MASK_EQ 0F0H,  70H, P_JCOND8
+                X_MASK_EQ 0F8H,  50H, P_PUSH
+                X_MASK_EQ 0F8H,  58H, P_POP
+                X_MASK_EQ 0F8H,  40H, P_INC2
+                X_MASK_EQ 0F8H,  48H, P_DEC2
+                X_MASK_EQ 0F8H,  90H, P_XCHG2
+                X_MASK_EQ 0F8H, 0B0H, P_MOV3B
+                X_MASK_EQ 0F8H, 0B8H, P_MOV3W
+                X_MASK_EQ 0F8H, 0D8H, P_ESC
+                X_MASK_EQ 0FCH,  80H, P_ARITH2
+                X_MASK_EQ 0FCH,  88H, P_MOV1
+                X_MASK_EQ 0FCH, 0A0H, P_MOV4
+                X_MASK_EQ 0FDH,  68H, P_PUSH_IMMED
+                X_MASK_EQ 0FDH,  69H, P_IMUL_IMMED
+                X_MASK_EQ 0FDH,  8CH, P_MOV5
+                X_MASK_EQ 0FEH,  6CH, P_INS
+                X_MASK_EQ 0FEH,  6EH, P_OUTS
+                X_MASK_EQ 0FEH,  84H, P_TEST1
+                X_MASK_EQ 0FEH,  86H, P_XCHG1
+                X_MASK_EQ 0FEH, 0A4H, P_MOVS
+                X_MASK_EQ 0FEH, 0A6H, P_CMPS
+                X_MASK_EQ 0FEH, 0A8H, P_TEST3
+                X_MASK_EQ 0FEH, 0AAH, P_STOS
+                X_MASK_EQ 0FEH, 0ACH, P_LODS
+                X_MASK_EQ 0FEH, 0AEH, P_SCAS
+                X_MASK_EQ 0FEH, 0C0H, P_ROTATE3
+                X_MASK_EQ 0FEH, 0C2H, P_RETN
+                X_MASK_EQ 0FEH, 0CAH, P_RETF
+                X_MASK_EQ 0FEH, 0C6H, P_MOV2
+                X_MASK_EQ 0FEH, 0D0H, P_ROTATE1
+                X_MASK_EQ 0FEH, 0D2H, P_ROTATE2
+                X_MASK_EQ 0FEH, 0E4H, P_IN1
+                X_MASK_EQ 0FEH, 0E6H, P_OUT1
+                X_MASK_EQ 0FEH, 0ECH, P_IN2
+                X_MASK_EQ 0FEH, 0EEH, P_OUT2
+                X_MASK_EQ 0FEH, 0F6H, P_F6_F7
+                X_MASK_EQ 0FEH, 0FEH, P_FE_FF
+                X_MASK_EQ 0E7H,  07H, P_POP_SEG
+                X_MASK_EQ 0C4H,  00H, P_ARITH1
+                X_MASK_EQ 0C6H,  04H, P_ARITH3
+                X_MASK_EQ 0C7H,  06H, P_PUSH_SEG
+FAILURE         DB      "???", Z_END
+
+P_0F            LABEL   BYTE
+                X_MORE
+                X_SWITCH
+                X_CASE   00H, P_0F00
+                X_CASE   01H, P_0F01
+                X_CASE   02H, P_LAR
+                X_CASE   03H, P_LSL
+                X_CASE   06H, P_CLTS
+                X_CASE   20H, P_MOV_FROM_CR
+                X_CASE   21H, P_MOV_FROM_DR
+                X_CASE   22H, P_MOV_TO_CR
+                X_CASE   23H, P_MOV_TO_DR
+                X_CASE   24H, P_MOV_FROM_TR
+                X_CASE   26H, P_MOV_TO_TR
+                X_CASE  0A4H, P_SHLD_IMMED
+                X_CASE  0A5H, P_SHLD_CL
+                X_CASE  0ACH, P_SHRD_IMMED
+                X_CASE  0ADH, P_SHRD_CL
+                X_CASE  0AFH, P_IMUL_MEM
+                X_CASE  0B2H, P_LSS
+                X_CASE  0B4H, P_LFS
+                X_CASE  0B5H, P_LGS
+                X_CASE  0BAH, P_BT1
+                X_CASE  0BCH, P_BSF
+                X_CASE  0BDH, P_BSR
+                X_MASK_EQ 0FEH, 0BEH, P_MOVSX
+                X_MASK_EQ 0FEH, 0B6H, P_MOVZX
+                X_MASK_EQ 0F0H,  80H, P_JCOND16
+                X_MASK_EQ 0F0H,  90H, P_SET
+                X_MASK_EQ 0E7H, 0A3H, P_BT2
+                X_MASK_EQ 0C7H,  80H, P_PUSH_SEG
+                X_MASK_EQ 0C7H,  81H, P_POP_SEG
+                X_JUMP  FAILURE
+
+P_0F00          LABEL   BYTE
+                X_MOD_REG_RM
+                X_LOAD_REG
+                X_SWITCH
+                X_CASE  00H, P_SLDT
+                X_CASE  01H, P_STR
+                X_CASE  02H, P_LLDT
+                X_CASE  03H, P_LTR
+                X_CASE  04H, P_VERR
+                X_CASE  05H, P_VERW
+                X_JUMP  FAILURE
+
+P_0F01          LABEL   BYTE
+                X_MOD_REG_RM
+                X_LOAD_REG
+                X_SWITCH
+                X_CASE  00H, P_SGDT
+                X_CASE  01H, P_SIDT
+                X_CASE  02H, P_LGDT
+                X_CASE  03H, P_LIDT
+                X_CASE  04H, P_SMSW
+                X_CASE  06H, P_LMSW
+                X_JUMP  FAILURE
+
+P_FE_FF         LABEL   BYTE
+                X_MOD_REG_RM
+                X_LOAD_REG
+                X_SWITCH
+                X_CASE  00H, P_INC1
+                X_CASE  01H, P_DEC1
+                X_CASE  02H, P_CALL_INDN
+                X_CASE  03H, P_CALL_INDF
+                X_CASE  04H, P_JMP_INDN
+                X_CASE  05H, P_JMP_INDF
+                X_CASE  06H, P_PUSH_MEM
+                X_JUMP  FAILURE
+
+P_F6_F7         LABEL   BYTE
+                X_MOD_REG_RM
+                X_LOAD_REG
+                X_SWITCH
+                X_CASE  00H, P_TEST2
+                X_CASE  02H, P_NOT
+                X_CASE  03H, P_NEG
+                X_CASE  04H, P_MUL
+                X_CASE  05H, P_IMUL
+                X_CASE  06H, P_DIV
+                X_CASE  07H, P_IDIV
+                X_JUMP  FAILURE
+
+P_AAA           DB      "AAA", Z_END
+P_AAS           DB      "AAS", Z_END
+P_DAA           DB      "DAA", Z_END
+P_DAS           DB      "DAS", Z_END
+P_HLT           DB      "HLT", Z_END
+P_NOP           DB      "NOP", Z_END
+P_CMC           DB      "CMC", Z_END
+P_CLC           DB      "CLC", Z_END
+P_CLI           DB      "CLI", Z_END
+P_CLD           DB      "CLD", Z_END
+P_STC           DB      "STC", Z_END
+P_STI           DB      "STI", Z_END
+P_STD           DB      "STD", Z_END
+P_CLTS          DB      "CLTS", Z_END
+P_INTO          DB      "INTO", Z_END
+P_LAHF          DB      "LAHF", Z_END
+P_SAHF          DB      "SAHF", Z_END
+P_LEAVE         DB      "LEAVE", Z_END
+P_WAIT          DB      "WAIT", Z_END
+
+;
+; XLAT
+;
+; Bug:  prefix ignored
+;
+P_XLAT          DB      "XLAT", Z_END
+
+P_A_PFX         LABEL   BYTE
+                X_PREFIX PFX_ASIZE, SIZE_ON
+
+P_O_PFX         LABEL   BYTE
+                X_PREFIX PFX_OSIZE, SIZE_ON
+
+P_CS            LABEL   BYTE
+                X_PREFIX PFX_SEG, "C"
+
+P_DS            LABEL   BYTE
+                X_PREFIX PFX_SEG, "D"
+
+P_ES            LABEL   BYTE
+                X_PREFIX PFX_SEG, "E"
+
+P_FS            LABEL   BYTE
+                X_PREFIX PFX_SEG, "F"
+
+P_GS            LABEL   BYTE
+                X_PREFIX PFX_SEG, "G"
+
+P_SS            LABEL   BYTE
+                X_PREFIX PFX_SEG, "S"
+
+P_LOCK          DB      "LOCK "
+                X_PREFIX PFX_LOCK, 1
+
+P_REPE          LABEL   BYTE
+                X_PREFIX PFX_REP, V_REPE
+
+P_REPNE         LABEL   BYTE
+                X_PREFIX PFX_REP, V_REPNE
+
+P_AAM           DB      "AAM"
+                X_JUMP  P_10
+P_AAD           DB      "AAD"
+P_10            LABEL   BYTE
+                X_MORE
+                X_CMP   OPCODE, 10, P_10_1
+                DB      Z_OP, Z_BYTE
+P_10_1          DB      Z_END
+
+
+P_INT           DB      "INT", Z_OP, Z_BYTE, Z_END
+
+P_INT3          DB      "INT", Z_OP, "3", Z_END
+
+P_ENTER         DB      "ENTER", Z_OP
+                X_WORD
+                X_COMMA
+                X_BYTE
+                X_END
+
+P_LSS           DB      "LS"
+                X_JUMP  P_LSEG
+
+P_LFS           DB      "LF"
+                X_JUMP  P_LSEG
+
+P_LGS           DB      "LG"
+                X_JUMP  P_LSEG
+
+P_LES           DB      "LE"
+                X_JUMP  P_LSEG
+
+P_LDS           DB      "LD"
+P_LSEG          DB      "S"
+                X_FAR_OP
+                X_CALL  OP_REG_MEM              ; (OP) reg, mem (END)
+
+P_PUSH          LABEL   BYTE
+                X_CALL  TPUSH
+                X_JUMP  P_PUSH_POP
+
+P_POP           LABEL   BYTE
+                X_CALL  TPOP
+P_PUSH_POP      LABEL   BYTE
+                X_WORD_OP
+                DB      Z_REGA, Z_END
+
+P_PUSHF         DB      "PUSHF"
+                X_CALL  APPEND_D
+
+P_POPF          DB      "POPF"
+                X_CALL  APPEND_D
+
+P_PUSHA         DB      "PUSHA"
+                X_CALL  APPEND_D
+
+P_POPA          DB      "POPA"
+                X_CALL  APPEND_D
+
+P_IRET          DB      "IRET"
+                X_EMPTY
+                X_CALL  APPEND_D
+
+P_CBW           DB      "C"
+                X_O16   P_CBW_1
+                DB      "WDE", Z_END
+P_CBW_1         DB      "BW", Z_END
+
+P_CDQ           DB      "C"
+                X_O16   P_CDQ_1
+                DB      "DQ", Z_END
+P_CDQ_1         DB      "WD", Z_END
+
+
+P_LTR           DB      "LTR"
+                X_CALL  WMEM
+
+P_STR           DB      "STR"
+                X_CALL  WMEM
+
+P_LLDT          DB      "LLDT"
+                X_CALL  WMEM
+
+P_LGDT          DB      "LGDT"
+                X_CALL  WMEM                    ; bug: should be FWORD PTR
+
+P_LIDT          DB      "LIDT"
+                X_CALL  WMEM                    ; bug: should be FWORD PTR
+
+P_VERR          DB      "VERR"
+                X_CALL  WMEM
+
+P_VERW          DB      "VERW"
+                X_CALL  WMEM
+
+P_SLDT          DB      "SLDT"
+                X_CALL  WMEM
+
+P_SGDT          DB      "SGDT"
+                X_CALL  WMEM                    ; bug: should be FWORD PTR
+
+P_SIDT          DB      "SIDT"
+                X_CALL  WMEM                    ; bug: should be FWORD PTR
+
+P_LAR           DB      "LAR"
+P_LAR_1         LABEL   BYTE
+                X_WORD_OP
+                X_CALL  OP_REG_MEM              ; (OP) reg, mem (END)
+
+P_LSL           DB      "LSL"
+                X_JUMP  P_LAR_1
+
+P_LMSW          DB      "LMSW"
+                X_CALL  WMEM
+
+P_SMSW          DB      "SMSW"
+                X_CALL  WMEM
+
+;
+; Bug in 16 bit mode: reg16 instead of reg32
+;
+P_MOV_TO_CR     LABEL   BYTE
+                X_CALL  TMOV
+                DB      "C"
+                X_JUMP  MOV_TO_SPEC
+
+P_MOV_FROM_CR   LABEL   BYTE
+                X_CALL  TMOV
+                DB      Z_MOD_REG_RM
+                X_WORD_OP
+                X_MEM
+                X_COMMA
+                DB      "C"
+                X_CALL  SPECIAL
+                X_END
+
+P_MOV_TO_DR     LABEL   BYTE
+                X_CALL  TMOV
+                DB      "D"
+                X_JUMP  MOV_TO_SPEC
+
+P_MOV_FROM_DR   LABEL   BYTE
+                X_CALL  TMOV
+                DB      Z_MOD_REG_RM
+                X_WORD_OP
+                X_MEM
+                X_COMMA
+                DB      "D"
+                X_CALL  SPECIAL
+                X_END
+
+P_MOV_TO_TR     LABEL   BYTE
+                X_CALL  TMOV
+                DB      "T"
+MOV_TO_SPEC     LABEL   BYTE
+                X_MOD_REG_RM
+                X_WORD_OP
+                X_CALL  SPECIAL
+                X_COMMA
+                DB      Z_MEM, Z_END
+
+P_MOV_FROM_TR   LABEL   BYTE
+                X_CALL  TMOV
+                DB      Z_MOD_REG_RM
+                X_WORD_OP
+                X_MEM
+                X_COMMA
+                DB      "T"
+                X_CALL  SPECIAL
+                X_END
+
+P_SHLD_IMMED    LABEL   BYTE
+                X_CALL  TSHL
+                X_JUMP  P_SHD_IMMED
+P_SHRD_IMMED    LABEL   BYTE
+                X_CALL  TSHR
+P_SHD_IMMED     DB      "D", Z_OP, Z_MOD_REG_RM
+                X_WORD_OP
+                X_MEM
+                X_COMMA
+                X_REG
+                X_COMMA
+                DB      Z_BYTE, Z_END
+
+P_SHLD_CL       LABEL   BYTE
+                X_CALL  TSHL
+                X_JUMP  P_SHD_CL
+P_SHRD_CL       LABEL   BYTE
+                X_CALL  TSHR
+P_SHD_CL        DB      "D", Z_OP, Z_MOD_REG_RM
+                X_WORD_OP
+                X_MEM
+                X_COMMA
+                X_REG
+                X_COMMA
+                DB      "CL", Z_END
+
+
+;
+; Bug: source operand is 32 bit instead of 16 bit. 8 bit is ok
+;
+P_MOVSX         DB      "MOVS"
+P_MOVSZ         DB      "X", Z_OP
+                X_WORD_OP
+                DB      Z_MOD_REG_RM, Z_REG
+                X_COMMA
+                X_TEST  01H, P_MOVSZ_1
+                X_BYTE_OP
+P_MOVSZ_1       DB      Z_MEM, Z_END
+
+P_MOVZX         DB      "MOVZ"
+                X_JUMP  P_MOVSZ
+
+;
+; bug: address size prefix & segment overide prefix ignored
+;
+P_CMPS          LABEL   BYTE
+                X_CALL  REP_COND
+                DB      "CMPS"
+STRING_BW       LABEL   BYTE
+                X_TEST  01H, STRING_W
+                DB      "B", Z_END
+STRING_W        LABEL   BYTE
+                X_O16   STRING_W1
+                DB      "D", Z_END
+STRING_W1       DB      "W", Z_END
+
+
+                X_SUB   REP_COND
+                X_CMP   PFX_REP, 0, REP_COND_2
+                DB      "REP"
+                X_CMP   PFX_REP, V_REPE, REP_COND_1
+                DB      "N"
+REP_COND_1      DB      "E "
+REP_COND_2      DB      Z_RET
+
+                X_SUB   REP_UNCOND
+                X_CMP   PFX_REP, 0, REP_UNCOND_1
+                DB      "REP "
+REP_UNCOND_1    DB      Z_RET
+
+
+
+;
+; bug: address size prefix & segment overide prefix ignored
+;
+P_LODS          LABEL   BYTE
+                X_CALL  REP_UNCOND
+                DB      "LODS"
+                X_JUMP  STRING_BW
+
+
+;
+; bug: address size prefix & segment overide prefix ignored
+;
+P_MOVS          LABEL   BYTE
+                X_CALL  REP_UNCOND
+                DB      "MOVS"
+                X_JUMP  STRING_BW
+
+;
+; bug: address size prefix & segment overide prefix ignored
+;
+P_SCAS          LABEL   BYTE
+                X_CALL  REP_COND
+                DB      "SCAS"
+                X_JUMP  STRING_BW
+
+;
+; bug: address size prefix & segment overide prefix ignored
+;
+P_STOS          LABEL   BYTE
+                X_CALL  REP_UNCOND
+                DB      "STOS"
+                X_JUMP  STRING_BW
+
+;
+; bug: address size prefix & segment overide prefix ignored
+;
+P_INS           LABEL   BYTE
+                X_CALL  REP_UNCOND
+                DB      "INS"
+                X_JUMP  STRING_BW
+
+;
+; bug: address size prefix & segment overide prefix ignored
+;
+P_OUTS          LABEL   BYTE
+                X_CALL  REP_UNCOND
+                DB      "OUTS"
+                X_JUMP  STRING_BW
+
+
+P_ARPL          DB      "ARPL"
+                DB      Z_OP, Z_MOD_REG_RM, Z_MEM
+                X_COMMA
+                DB      Z_REG, Z_END
+
+P_BOUND         DB      "BOUND"
+                X_CALL  OP_REG_MEM              ; (OP) reg, mem (END)
+
+                X_SUB   TPUSH
+                DB      "PUSH", Z_OP, Z_RET
+
+                X_SUB   TPOP
+                DB      "POP", Z_OP, Z_RET
+
+P_PUSH_SEG      LABEL   BYTE
+                X_CALL  TPUSH
+                X_BITS  38H
+                X_CALL  SREG
+                X_END
+
+P_PUSH_MEM      LABEL   BYTE
+                X_CALL  TPUSH
+                DB      Z_MEM, Z_END
+
+P_PUSH_IMMED    LABEL   BYTE
+                X_CALL  TPUSH
+                X_WORD_OP
+                X_NOT
+                X_TEST  02H, P_PUSH_IMMED_1
+                X_SIGNED
+P_PUSH_IMMED_1  DB      Z_IMMED, Z_END
+
+P_POP_SEG       LABEL   BYTE
+                X_CALL  TPOP
+                X_BITS  38H
+                X_CALL  SREG
+                X_END
+
+P_POP_MEM       LABEL   BYTE
+                X_CALL  TPOP
+                DB      Z_MOD_REG_RM, Z_MEM, Z_END
+
+                
+P_JMPS          LABEL   BYTE
+                X_CALL  TJMP
+                X_SHORT
+                X_END
+
+P_JMPN          LABEL   BYTE
+                X_CALL  TJMP
+                X_NEAR
+                X_END
+
+P_JMPF          LABEL   BYTE
+                X_CALL  TJMP
+                X_FAR
+                X_END
+
+P_CALLN         LABEL   BYTE
+                X_CALL  TCALL
+                X_NEAR
+                X_END
+
+P_CALLF         LABEL   BYTE
+                X_CALL  TCALL
+                X_FAR
+                X_END
+
+P_JCXZ          DB      "J"
+                X_O16   P_JCXZ1
+                DB      "E"
+P_JCXZ1         DB      "CXZ", Z_OP
+                X_SHORT
+                X_END
+
+P_LOOP          LABEL   BYTE
+                X_CALL  TLOOP
+                X_OP
+                X_SHORT
+                X_END
+
+P_LOOPE         LABEL   BYTE
+                X_CALL  TLOOP
+                DB      "E", Z_OP
+                X_SHORT
+                X_END
+
+P_LOOPNE        LABEL   BYTE
+                X_CALL  TLOOP
+                DB      "NE", Z_OP
+                X_SHORT
+                X_END
+
+                X_SUB   TLOOP
+                DB      "LOOP", Z_RET
+
+P_SET           DB      "SET"
+                X_CALL  COND
+                X_BYTE_OP
+                DB      Z_OP, Z_MOD_REG_RM, Z_MEM, Z_END
+
+P_JCOND8        DB      "J"
+                X_CALL  COND
+                X_OP
+                X_SHORT
+                X_END
+
+P_JCOND16       DB      "J"
+                X_CALL  COND
+                DB      Z_OP
+                X_NEAR
+                X_END
+
+P_JMP_INDN      LABEL   BYTE
+                X_CALL  TJMP
+P_INDN          LABEL   BYTE
+                X_WORD_OP
+                DB      Z_MEM, Z_END
+
+P_JMP_INDF      LABEL   BYTE
+                X_CALL  TJMP
+P_INDF          LABEL   BYTE
+                X_FAR_OP
+                DB      Z_MEM, Z_END
+
+P_CALL_INDN     LABEL   BYTE
+                X_CALL  TCALL
+                X_JUMP  P_INDN
+
+P_CALL_INDF     LABEL   BYTE
+                X_CALL  TCALL
+                X_JUMP  P_INDF
+
+                X_SUB   TCALL
+                DB      "CALL", Z_OP, Z_RET
+
+                X_SUB   TJMP
+                X_EMPTY
+                DB      "JMP", Z_OP, Z_RET
+
+                X_SUB   TMOV
+                DB      "MOV", Z_OP, Z_RET
+
+P_IN1           DB      "IN", Z_OP, Z_ACCUM
+                X_COMMA
+                DB      Z_BYTE, Z_END
+
+P_IN2           DB      "IN", Z_OP, Z_ACCUM
+                X_COMMA
+                DB      "DX", Z_END
+
+P_OUT1          DB      "OUT", Z_OP, Z_BYTE
+                X_COMMA
+                DB      Z_ACCUM, Z_END
+
+P_OUT2          DB      "OUT", Z_OP, "DX"
+                X_COMMA
+                DB      Z_ACCUM, Z_END
+
+P_INC1          DB      "INC"
+                X_CALL  OP_MEM
+
+P_DEC1          DB      "DEC"
+                X_CALL  OP_MEM
+P_INC2          DB      "INC", Z_OP
+                X_WORD_OP
+                DB      Z_REGA, Z_END
+
+P_DEC2          DB      "DEC", Z_OP
+                X_WORD_OP
+                DB      Z_REGA, Z_END
+
+P_BSF           DB      "BSF"
+                X_JUMP  P_BS_1
+P_BSR           DB      "BSR"
+P_BS_1          LABEL   BYTE
+                X_WORD_OP
+                X_CALL  OP_REG_MEM               ; (OP) reg, mem (END)
+
+P_BT1           DB      Z_MOD_REG_RM
+                X_LOAD_REG
+                X_CALL  BIT_TESTS
+                X_OP
+                X_MEM
+                X_COMMA
+                DB      Z_BYTE, Z_END
+
+P_BT2           DB      Z_MOD_REG_RM
+                X_BITS  38H
+                X_CALL  BIT_TESTS
+                X_OP
+                X_MEM
+                X_COMMA
+                DB      Z_REG, Z_END
+
+                X_SUB   BIT_TESTS
+                DB      "BT"
+                X_BITS  03H
+                X_TABLE
+                DW      BT00, BT01, BT02, BT03
+BT00            DB      Z_RET
+BT01            DB      "S", Z_RET
+BT02            DB      "R", Z_RET
+BT03            DB      "C", Z_RET
+
+
+P_ROTATE1       DB      Z_MOD_REG_RM
+                X_CALL  ROTATE
+                DB      Z_OP, Z_MEM
+                X_COMMA
+                DB      "1", Z_END
+
+P_ROTATE2       DB      Z_MOD_REG_RM
+                X_CALL  ROTATE
+                DB      Z_OP, Z_MEM
+                X_COMMA
+                DB      "CL", Z_END
+
+P_ROTATE3       DB      Z_MOD_REG_RM
+                X_CALL  ROTATE
+                DB      Z_OP, Z_MEM
+                X_COMMA
+                DB      Z_BYTE, Z_END
+
+
+                X_SUB   ROTATE
+                X_LOAD_REG
+                X_TABLE
+                DW      ROTATE00, ROTATE01, ROTATE02, ROTATE03
+                DW      ROTATE04, ROTATE05, ROTATE06, ROTATE07
+
+ROTATE00        DB      "ROL", Z_RET
+ROTATE01        DB      "ROR", Z_RET
+ROTATE02        DB      "RCL", Z_RET
+ROTATE03        DB      "RCR", Z_RET
+                X_SUB   TSHL
+ROTATE04        DB      "SHL", Z_RET
+                X_SUB   TSHR
+ROTATE05        DB      "SHR", Z_RET
+ROTATE06        DB      "???", Z_RET
+ROTATE07        DB      "SAR", Z_RET
+
+                X_SUB   TTEST
+                DB      "TEST", Z_OP, Z_RET
+
+;
+; TEST
+;       reg, reg
+;       reg, mem
+;
+P_TEST1         LABEL   BYTE
+                X_CALL  TTEST
+                X_CALL  REG_MEM                 ; reg, mem (END)
+
+;
+; Does not return!
+;
+; (OP) reg, mem (END)
+;
+                X_SUB   OP_REG_MEM
+                X_OP
+;
+; reg, mem (END)
+;
+                X_SUB   REG_MEM
+                DB      Z_MOD_REG_RM, Z_REG
+                X_COMMA
+                DB      Z_MEM, Z_END
+
+
+
+;
+; (OP) mem.w (END)
+;
+                X_SUB   WMEM
+                X_WORD_OP
+;
+; (OP) mem (END)
+;
+                X_SUB   OP_MEM
+                DB      Z_OP, Z_MEM, Z_END
+
+;
+; TEST
+;       reg, immed
+;       mem, immed
+;
+P_TEST2         LABEL   BYTE
+                X_CALL  TTEST
+                X_MEM
+                X_COMMA
+                DB      Z_IMMED, Z_END
+
+;
+; TEST
+;       accum, immed
+;
+P_TEST3         LABEL   BYTE
+                X_CALL  TTEST
+                X_ACCUM
+                X_COMMA
+                DB      Z_IMMED, Z_END
+
+;
+; XCHG
+;       reg, reg
+;       reg, mem
+;
+P_XCHG1         DB      "XCHG", Z_OP
+                X_CALL  REG_MEM                 ; reg, mem (END)
+
+;
+; XCHG
+;       accum, reg
+;
+P_XCHG2         DB      "XCHG", Z_OP, Z_ACCUM
+                X_COMMA
+                DB      Z_REGA, Z_END
+
+
+P_NOT           DB      "NOT"
+                X_CALL  OP_MEM
+
+P_NEG           DB      "NEG"
+                X_CALL  OP_MEM
+
+P_IMUL          DB      "I"
+P_MUL           DB      "MUL"
+                X_CALL  OP_MEM
+
+P_IDIV          DB      "I"
+P_DIV           DB      "DIV"
+                X_CALL  OP_MEM
+
+P_IMUL_IMMED    DB      "IMUL", Z_OP
+                X_WORD_OP
+                X_NOT
+                X_TEST  02H, P_IMUL_I_1
+                X_SIGNED
+P_IMUL_I_1      DB      Z_MOD_REG_RM
+                X_REG
+                X_COMMA
+                X_MEM
+                X_COMMA
+                DB      Z_IMMED, Z_END
+
+P_IMUL_MEM      DB      "IMUL"
+                X_WORD_OP
+                X_CALL  OP_REG_MEM
+
+P_RETN          DB      "RETN"
+                X_JUMP  P_RET
+P_RETF          DB      "RETF"
+P_RET           LABEL   BYTE
+                X_EMPTY
+                X_TEST  01H, P_RET_1
+                X_OP
+                X_WORD
+P_RET_1         DB      Z_END
+
+P_LEA           DB      "LEA", Z_OP
+                X_CALL  REG_MEM                 ; reg, mem (END)
+
+;
+; MOV
+;       reg, reg
+;       mem, reg
+;       reg, mem
+;
+P_MOV1          LABEL   BYTE
+                X_CALL  TMOV
+                X_JUMP  DIRECTION
+
+;
+; MOV
+;       mem, immed
+;
+P_MOV2          LABEL   BYTE
+                X_CALL  TMOV
+                DB      Z_MOD_REG_RM, Z_MEM
+                X_COMMA
+                DB      Z_IMMED, Z_END
+
+;
+; MOV
+;       reg, immed
+;
+P_MOV3B         LABEL   BYTE
+                X_BYTE_OP
+                X_JUMP  P_MOV3
+
+P_MOV3W         LABEL   BYTE
+                X_WORD_OP
+P_MOV3          LABEL   BYTE
+                X_CALL  TMOV
+                X_REGA
+                X_COMMA
+                DB      Z_IMMED, Z_END
+;
+; MOV
+;       mem, accum
+;       accum, mem
+P_MOV4          LABEL   BYTE
+                X_CALL  TMOV
+                X_TEST  02H, P_MOV4_1
+                X_ACCUM
+                X_COMMA
+                X_DISP
+                X_END
+P_MOV4_1        LABEL   BYTE
+                X_DISP
+                X_COMMA
+                DB      Z_ACCUM, Z_END
+
+;
+; MOV
+;       sreg, reg
+;       sreg, mem
+;       reg, sreg
+;       mem, sreg
+;
+P_MOV5          LABEL   BYTE
+                X_CALL  TMOV
+                X_MOD_REG_RM
+                X_WORD_OP
+                X_TEST  02H, P_MOV5_1
+                X_MEM
+                X_COMMA
+                X_LOAD_REG
+                X_CALL  SREG
+                X_END
+P_MOV5_1        LABEL   BYTE
+                X_LOAD_REG
+                X_CALL  SREG
+                X_COMMA
+                DB      Z_MEM, Z_END
+
+
+;
+; ADD, OR, ADC, SBB, AND, SUB, XOR, CMP
+;       reg, reg
+;       mem, reg
+;       reg, mem
+;
+P_ARITH1        LABEL   BYTE
+                X_BITS  38H
+                X_CALL  ARITH
+                X_OP
+DIRECTION       LABEL   BYTE
+                X_MOD_REG_RM
+                X_OPCODE
+                X_TEST  02H, DIR1                       ; d=1?
+                X_MEM
+                X_COMMA
+                DB      Z_REG, Z_END
+DIR1            DB      Z_REG
+                X_COMMA
+                DB      Z_MEM, Z_END
+
+;
+; ADD, OR, ADC, SBB, AND, SUB, XOR, CMP
+;       reg, immed
+;       mem, immed
+;
+P_ARITH2        LABEL   BYTE
+                X_NOT
+                X_TEST  02H, P_ARITH2_1                 ; s=0?
+                X_SIGNED
+P_ARITH2_1      LABEL   BYTE
+                X_MOD_REG_RM
+                X_LOAD_REG
+                X_CALL  ARITH
+                X_OP
+                X_MEM
+                X_COMMA
+                DB      Z_IMMED, Z_END
+
+;
+; ADD, OR, ADC, SBB, AND, SUB, XOR, CMP
+;       accum, immed
+;
+P_ARITH3        LABEL   BYTE
+                X_BITS  38H
+                X_CALL  ARITH
+                DB      Z_OP, Z_ACCUM
+                X_COMMA
+                DB      Z_IMMED, Z_END
+
+;
+; Insert arimthmetic instruction ?????aaa)
+;
+                X_SUB   ARITH
+                X_BITS  07H
+                X_TABLE
+                DW      ARITH00, ARITH01, ARITH02, ARITH03
+                DW      ARITH04, ARITH05, ARITH06, ARITH07
+
+ARITH00         DB      "ADD", Z_RET
+ARITH02         DB      "ADC", Z_RET
+ARITH03         DB      "SBB", Z_RET
+ARITH04         DB      "AND", Z_RET
+ARITH05         DB      "SUB", Z_RET
+ARITH06         DB      "X"
+ARITH01         DB      "OR", Z_RET
+ARITH07         DB      "CMP", Z_RET
+
+;
+; Insert condition code (accu = ????cccc)
+;
+                X_SUB   COND
+                X_BITS  0FH
+                X_TABLE
+                DW      COND00, COND01, COND02, COND03
+                DW      COND04, COND05, COND06, COND07
+                DW      COND08, COND09, COND0A, COND0B
+                DW      COND0C, COND0D, COND0E, COND0F
+COND01          DB      "N"
+COND00          DB      "O", Z_RET
+COND03          DB      "N"
+COND02          DB      "C", Z_RET
+COND05          DB      "N"
+COND04          DB      "E", Z_RET
+COND06          DB      "BE", Z_RET
+COND07          DB      "A", Z_RET
+COND09          DB      "N"
+COND08          DB      "S", Z_RET
+COND0A          DB      "PE", Z_RET
+COND0B          DB      "PO", Z_RET
+COND0C          DB      "L", Z_RET
+COND0D          DB      "GE", Z_RET
+COND0E          DB      "LE", Z_RET
+COND0F          DB      "G", Z_RET
+
+
+;
+; Insert segment register (accu = ?????sss)
+;
+                X_SUB   SREG
+                X_CALL  SREG_1
+                DB      "S", Z_RET
+
+                X_SUB   SREG_1
+                X_BITS  07H
+                X_TABLE
+                DW      SREG00, SREG01, SREG02, SREG03
+                DW      SREG04, SREG05, SREG06, SREG07
+
+SREG00          DB      "E", Z_RET
+SREG01          DB      "C", Z_RET
+SREG02          DB      "S", Z_RET
+SREG03          DB      "D", Z_RET
+SREG04          DB      "F", Z_RET
+SREG05          DB      "G", Z_RET
+SREG06          DB      "?", Z_RET
+SREG07          DB      "?", Z_RET
+
+;
+; Insert special register (reg = ?????qqq)
+; Caller must insert "C", "D", or "T" before calling this subroutine
+;
+                X_SUB   SPECIAL
+                DB      "R"
+                X_LOAD_REG
+                X_NIBBLE
+                X_RET
+
+
+;
+; Insert "D" if operand size = 32
+; Does not return!
+;
+                X_SUB   APPEND_D
+                X_O16   APPEND_D1
+                DB      "D"
+APPEND_D1       DB      Z_END
+
+;
+; Operand separator
+;
+                X_SUB   P_COMMA
+                DB      ", ", Z_RET
+
+
+;
+; Load reg field of mod,reg,r/m into accu
+;
+                X_SUB   P_LOAD_REG
+                X_LD_MOD_REG_RM
+                X_BITS  00111000B
+                X_RET
+
+
+;
+; Floating point
+;
+
+P_ESC           DB      "F"
+                X_OPCODE                        ; Opcode -> accu
+                X_PUSH                          ; Push opcode
+                X_MORE                          ; Get next byte
+                X_MASK_EQ 0C0H, 0C0H, ESC_REG   ; mod = 11 ->
+                X_BACK                          ; Back to mod,reg,r/m
+                X_MOD_REG_RM
+                X_NO_PTR
+                X_POP
+                X_BITS  07H
+                X_TABLE
+                DW      NPXMEM_D8, NPXMEM_D9, NPXMEM_DA, NPXMEM_DB
+                DW      NPXMEM_DC, NPXMEM_DD, NPXMEM_DE, NPXMEM_DF
+
+ESC_REG         LABEL   BYTE
+                X_XCHG                          ; Get 1st byte, save 2nd
+                X_BITS  07H
+                X_TABLE
+                DW      NPXREG_D8, NPXREG_D9, NPXREG_DA, NPXREG_DB
+                DW      NPXREG_DC, NPXREG_DD, NPXREG_DE, NPXREG_DF
+
+
+NPXMEM_DA       LABEL   BYTE                    ; 32-bit real
+NPXMEM_DE       LABEL   BYTE                    ; Integer
+                DB      "I"
+NPXMEM_D8       LABEL   BYTE                    ; 32-bit real
+NPXMEM_DC       LABEL   BYTE                    ; 64-bit real
+                X_LD_MOD_REG_RM
+                X_CALL  NPX1
+                X_OP
+                X_MEM
+                X_END
+
+
+NPXMEM_D9       LABEL   BYTE
+                X_LD_MOD_REG_RM
+                X_CALL  NPX3
+                X_OP
+                X_MEM
+                X_END
+
+                X_SUB   NPX3
+                X_BITS  38H
+                X_TABLE
+                DW      P_LD,        NPX_FAILURE, P_ST,        P_STP
+                DW      P_LDENV,     P_LDCW,      P_STENV,     P_STCW
+
+P_LDENV         DB      "LDENV", Z_RET
+P_LDCW          DB      "LDCW", Z_RET
+P_STENV         DB      "STENV", Z_RET
+P_STCW          DB      "STCW", Z_RET
+
+NPXMEM_DB       LABEL   BYTE
+                X_LD_MOD_REG_RM
+                X_CALL  NPX4
+                X_OP
+                X_MEM
+                X_END
+
+                X_SUB   NPX4
+                X_BITS  38H
+                X_TABLE
+                DW      P_ILD, NPX_FAILURE, P_IST, P_ISTP
+                DW      NPX_FAILURE, P_LD, NPX_FAILURE, P_STP
+
+P_ILD           DB      "I"
+P_LD            DB      "LD", Z_RET
+P_IST           DB      "I"
+P_ST            DB      "ST", Z_RET
+P_ISTP          DB      "I"
+P_STP           DB      "STP", Z_RET
+
+NPXMEM_DD       LABEL   BYTE
+                X_LD_MOD_REG_RM
+                X_CALL  NPX5
+                X_OP
+                X_MEM
+                X_END
+
+                X_SUB   NPX5
+                X_BITS  38H
+                X_TABLE
+                DW      P_LD, NPX_FAILURE, P_ST, P_STP
+                DW      P_RSTOR, NPX_FAILURE, P_SAVE, P_STSW
+
+P_RSTOR         DB      "RSTOR", Z_RET
+P_SAVE          DB      "SAVE", Z_RET
+P_STSW          DB      "STSW", Z_RET
+
+
+NPXMEM_DF       LABEL   BYTE
+                X_LD_MOD_REG_RM
+                X_CALL  NPX6
+                X_OP
+                X_MEM
+                X_END
+
+                X_SUB   NPX6
+                X_BITS  38H
+                X_TABLE
+                DW      P_ILD, NPX_FAILURE, P_IST, P_ISTP
+                DW      P_BLD, P_ILD, P_BSTP, P_ISTP
+
+P_BLD           DB      "BLD", Z_RET
+P_BSTP          DB      "BSTP", Z_RET
+
+NPXREG_D8       LABEL   BYTE
+                X_POP
+                X_PUSH
+                X_CALL  NPX1
+                X_POP
+                DB      Z_OP, "ST"
+                X_COMMA
+                X_CALL  FREG
+                X_END
+
+NPXREG_DC       LABEL   BYTE
+                X_POP
+                X_PUSH
+                X_CALL  NPX2
+                X_POP
+                X_OP
+                X_CALL  FREG
+                X_COMMA
+                DB      "ST"
+                X_END
+
+                X_SUB   NPX1
+                X_BITS  38H
+                X_TABLE
+                DW      NPX_ADD, NPX_MUL, NPX_COM, NPX_COMP
+                DW      NPX_SUB, NPX_SUBR, NPX_DIV, NPX_DIVR
+
+                X_SUB   NPX2
+                X_BITS  38H
+                X_TABLE
+                DW      NPX_ADD, NPX_MUL, NPX_COM, NPX_COMP
+                DW      NPX_SUBR, NPX_SUB, NPX_DIVR, NPX_DIV
+
+NPX_ADD         DB      "ADD", Z_RET
+NPX_MUL         DB      "MUL", Z_RET
+NPX_COM         DB      "COM", Z_RET
+NPX_COMP        DB      "COMP", Z_RET
+NPX_SUB         DB      "SUB", Z_RET
+NPX_SUBR        DB      "SUBR", Z_RET
+NPX_DIV         DB      "DIV", Z_RET
+NPX_DIVR        DB      "DIVR", Z_RET
+
+NPXREG_D9       LABEL   BYTE
+                X_POP
+                X_PUSH
+                X_BITS  38H
+                X_TABLE
+                DW      NPXREG_D9_0, NPXREG_D9_1, NPXREG_D9_2, NPX_FAILURE
+                DW      NPXREG_D9_4, NPXREG_D9_5, NPXREG_D9_67, NPXREG_D9_67
+
+NPXREG_D9_0     DB      "LD"
+                X_CALL  NPX_ST
+NPXREG_D9_1     DB      "XCH"
+                X_CALL  NPX_ST
+NPXREG_D9_2     DB      "NOP"
+                X_CALL  NPX_ST
+
+NPXREG_D9_4     LABEL   BYTE
+                X_POP
+                X_BITS  07H
+                X_TABLE
+                DW      NPXREG_D9_4_0, NPXREG_D9_4_1, NPX_FAILURE, NPX_FAILURE
+                DW      NPXREG_D9_4_4, NPXREG_D9_4_5, NPX_FAILURE, NPX_FAILURE
+
+NPXREG_D9_4_0   DB      "CHS", Z_END
+NPXREG_D9_4_1   DB      "ABS", Z_END
+NPXREG_D9_4_4   DB      "TST", Z_END
+NPXREG_D9_4_5   DB      "XAM", Z_END
+
+NPXREG_D9_5     DB      "LD"
+                X_POP
+                X_BITS  07H
+                X_TABLE
+                DW      NPXREG_D9_5_0, NPXREG_D9_5_1, NPXREG_D9_5_2, NPXREG_D9_5_3
+                DW      NPXREG_D9_5_4, NPXREG_D9_5_5, NPXREG_D9_5_6, NPX_FAILURE
+
+NPXREG_D9_5_0   DB      "1", Z_END
+NPXREG_D9_5_1   DB      "2T", Z_END
+NPXREG_D9_5_2   DB      "2E", Z_END
+NPXREG_D9_5_3   DB      "PI", Z_END
+NPXREG_D9_5_4   DB      "LG2", Z_END
+NPXREG_D9_5_5   DB      "LN2", Z_END
+NPXREG_D9_5_6   DB      "Z", Z_END
+
+NPXREG_D9_67    LABEL   BYTE
+                X_POP
+                X_BITS  0FH
+                X_TABLE
+                DW      NPXREG_D9_6_0, NPXREG_D9_6_1, NPXREG_D9_6_2, NPXREG_D9_6_3
+                DW      NPXREG_D9_6_4, NPXREG_D9_6_5, NPXREG_D9_6_6, NPXREG_D9_6_7
+                DW      NPXREG_D9_7_0, NPXREG_D9_7_1, NPXREG_D9_7_2, NPXREG_D9_7_3
+                DW      NPXREG_D9_7_4, NPXREG_D9_7_5, NPXREG_D9_7_6, NPXREG_D9_7_7
+
+NPXREG_D9_6_0   DB      "2XM1", Z_END
+NPXREG_D9_6_1   DB      "YL2X", Z_END
+NPXREG_D9_6_2   DB      "PTAN", Z_END
+NPXREG_D9_6_3   DB      "PATAN", Z_END
+NPXREG_D9_6_4   DB      "XTRACT", Z_END
+NPXREG_D9_6_5   DB      "PREM1", Z_END
+NPXREG_D9_6_6   DB      "DECSTP", Z_END
+NPXREG_D9_6_7   DB      "INCSTP", Z_END
+NPXREG_D9_7_0   DB      "PREM", Z_END
+NPXREG_D9_7_1   DB      "YL2XP1", Z_END
+NPXREG_D9_7_2   DB      "SQRT", Z_END
+NPXREG_D9_7_3   DB      "SINCOS", Z_END
+NPXREG_D9_7_4   DB      "RNDINT", Z_END
+NPXREG_D9_7_5   DB      "SCALE", Z_END
+NPXREG_D9_7_6   DB      "SIN", Z_END
+NPXREG_D9_7_7   DB      "COS", Z_END
+
+
+NPXREG_DA       LABEL   BYTE
+                X_POP
+                X_SWITCH
+                X_CASE  0E9H, NPXREG_DA_E9
+                X_JUMP  NPX_FAILURE
+
+NPXREG_DA_E9    DB      "U"
+NPXREG_DE_D9    DB      "COMPP", Z_END
+
+NPXREG_DB       LABEL   BYTE
+                X_POP
+                X_SWITCH
+                X_CASE  0E2H, NPXREG_DB_E2
+                X_CASE  0E3H, NPXREG_DB_E3
+                X_JUMP  NPX_FAILURE
+
+NPXREG_DB_E2    DB      "CLEX", Z_END
+NPXREG_DB_E3    DB      "INIT", Z_END
+
+NPXREG_DD       LABEL   BYTE
+                X_POP
+                X_PUSH
+                X_BITS  38H
+                X_TABLE
+                DW      NPXREG_DD_0, NPXREG_DD_1, NPXREG_DD_2, NPXREG_DD_3
+                DW      NPXREG_DD_4, NPXREG_DD_5, NPX_FAILURE, NPX_FAILURE
+
+NPXREG_DD_0     DB      "FREE"
+                X_CALL  NPX_ST
+NPXREG_DD_1     DB      "XCH"
+                X_CALL  NPX_ST
+NPXREG_DD_2     DB      "ST"
+                X_CALL  NPX_ST
+NPXREG_DD_3     DB      "STP"
+                X_CALL  NPX_ST
+NPXREG_DD_4     DB      "UCOM"
+                X_CALL  NPX_ST
+NPXREG_DD_5     DB      "UCOMP"
+                X_CALL  NPX_ST
+
+NPXREG_DE       LABEL   BYTE
+                X_POP
+                X_SWITCH
+                X_CASE  0D9H, NPXREG_DE_D9
+                X_PUSH
+                X_CALL  NPX2
+                X_POP
+                DB      "P"
+                X_CALL  NPX_ST
+
+NPXREG_DF       LABEL   BYTE
+                X_POP
+                X_SWITCH
+                X_CASE   0E0H, NPXREG_DF_E0
+                X_JUMP  NPX_FAILURE
+
+NPXREG_DF_E0    DB      "STSW", Z_OP, "AX", Z_END
+
+
+;
+; Insert "<Tab>ST(accu)" and end
+;
+
+                X_SUB   NPX_ST
+                X_OP
+                X_CALL  FREG
+                X_END
+
+;
+; Insert ST(accu)
+;
+                X_SUB   FREG
+                DB      "ST("
+                X_BITS  07H
+                X_NIBBLE
+                DB      ")"
+                X_RET
+
+
+NPX_FAILURE     DB      "???", Z_END
+
+
+; ============================================================================
+; End of disassembler language program
+; ============================================================================
+
+
+DISASM_CALL     LABEL   WORD
+CIDX            =       0
+                REPT    CALLCNT
+                VDW     CALLV, %CIDX
+CIDX            =       CIDX + 1
+                ENDM
+SV_DATA         ENDS
+
+
+
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:SV_DATA
+
+
+XCHAR           MACRO   CHR
+                MOV     BYTE PTR DS:[DI], CHR
+                INC     DI
+                ENDM
+
+
+XTEXT           PROC    NEAR
+                PUSH    AX
+                PUSH    BX
+                MOV     BX, DX
+XTEXT1:         MOV     AL, [BX]
+                OR      AL, AL
+                JZ      SHORT XTEXT9
+                XCHAR   AL
+                INC     BX
+                JMP     SHORT XTEXT1
+XTEXT9:         POP     BX
+                POP     AX
+                RET
+XTEXT           ENDP
+
+
+XDWORD          PROC    NEAR
+                ROR     EAX, 16
+                CALL    XWORD
+                ROR     EAX, 16
+                CALL    XWORD
+                RET
+XDWORD          ENDP
+
+XWORD           PROC    NEAR
+                XCHG    AL, AH
+                CALL    XBYTE
+                XCHG    AL, AH
+                CALL    XBYTE
+                RET
+XWORD           ENDP
+
+
+XBYTE           PROC    NEAR
+                PUSH    AX
+                SHR     AL, 4
+                CALL    XNIBBLE
+                POP     AX
+                PUSH    AX
+                CALL    XNIBBLE
+                POP     AX
+                RET
+XBYTE           ENDP
+
+XNIBBLE         PROC    NEAR
+                AND     AL, 0FH
+                ADD     AL, 30H
+                CMP     AL, 3AH
+                JB      SHORT XNIB1
+                ADD     AL, 7
+XNIB1:          XCHAR   AL
+                RET
+XNIBBLE         ENDP
+
+
+XSBYTE          PROC    NEAR
+                PUSH    AX
+                TEST    AL, 80H
+                JNZ     SHORT XSBYTE2
+                XCHAR   "+"
+XSBYTE1:        CALL    XBYTE
+                POP     AX
+                RET
+XSBYTE2:        XCHAR   "-"
+                NEG     AL
+                JMP     SHORT XSBYTE1
+XSBYTE          ENDP
+
+
+;
+; In:   AL              Bits 0..2: register number
+;       OPSIZE          operand size (0=BYTE, 1=WORD)
+;       PFX_OSIZE       Operand size
+;
+XREG            PROC    NEAR
+                PUSH    AX
+                PUSH    BX
+                LEA     BX, $REG8
+                CMP     OPSIZE, 0
+                JE      SHORT XREG1
+                LEA     BX, $REG16
+                CALL    OSIZE                   ; Operand size
+                JZ      SHORT XREG1             ; 16 ->
+                XCHAR   "E"
+XREG1:          AND     AX, 07H
+                SHL     AX, 1
+                ADD     BX, AX
+                MOV     AX, [BX]
+                XCHAR   AL
+                XCHAR   AH
+                POP     BX
+                POP     AX
+                RET
+XREG            ENDP
+
+
+;
+; In:   AL      Register number (bits 0..2)
+;
+REG32           PROC    NEAR
+                XCHAR   "E"
+REG16           PROC    NEAR
+                PUSH    AX
+                PUSH    BX
+                MOV     BL, AL
+                AND     BX, 07H
+                SHL     BX, 1
+                MOV     AX, WORD PTR $REG16[BX]
+                XCHAR   AL
+                XCHAR   AH
+                POP     BX
+                POP     AX
+                RET
+REG16           ENDP
+REG32           ENDP
+
+
+
+;
+; In:   OPSIZE  
+;       FLAGS
+;
+XIMMED          PROC    NEAR
+                CMP     OPSIZE, 0
+                JNE     SHORT XIMMED_WORD
+                MOV     AL, FS:[ESI]
+                INC     ESI
+                CALL    XBYTE
+                RET
+
+XIMMED_WORD:    TEST    FLAGS, F_SIGNED         ; s?
+                JZ      SHORT XIMMED_WORD1      ; No ->
+                MOV     AL, FS:[ESI]
+                INC     ESI
+                CALL    XSBYTE
+                RET
+
+XIMMED_WORD1:   CALL    OSIZE                   ; Operand size
+                JZ      SHORT XIMMED_WORD2      ; 16 ->
+                MOV     EAX, FS:[ESI]
+                ADD     ESI, 4
+                MOV     SYM_ADDR, EAX
+                MOV     SYM_FLAG, SYM_ANY
+                CALL    XDWORD
+                RET
+
+XIMMED_WORD2:   MOV     AX, FS:[ESI]
+                ADD     ESI, 2
+                CALL    XWORD
+                RET
+XIMMED          ENDP
+
+
+;
+; Return address size
+;
+; Out:  NZ      32 bit
+;       ZR      16 bit
+;
+ASIZE           PROC    NEAR
+                CMP     MODE_32, 0
+                JE      SHORT ASIZE16
+ASIZE32:        CMP     PFX_ASIZE, SIZE_ON
+                RET
+ASIZE16:        CMP     PFX_ASIZE, SIZE_OFF
+                RET
+ASIZE           ENDP
+
+
+;
+; Return operand size
+;
+; Out:  NZ      32 bit
+;       ZR      16 bit
+;
+OSIZE           PROC    NEAR
+                CMP     MODE_32, 0
+                JE      SHORT OSIZE16
+OSIZE32:        CMP     PFX_OSIZE, SIZE_ON
+                RET
+OSIZE16:        CMP     PFX_OSIZE, SIZE_OFF
+                RET
+OSIZE           ENDP
+
+
+
+;
+;
+; In:   FS:ESI  Source
+;       DS:DI   Destination
+;       ECX     Value of EIP at FS:ESI (ESI, if no relocation used)
+;       AL      address/operand size: 0:16, 1:32
+;
+; Out:  DS:DI   Pointer to terminating byte of destination (0)
+;       AL      SYM_NONE=no symbol; SYM_ANY, SYM_TEXT, SYM_DATA
+;       AH      Non-zero, if an empty line should be output after this line
+;       EDX     Symbol address (if AL<>SYM_NONE)
+;
+DISASM          PROC    NEAR
+                SUB     ECX, ESI
+                MOV     RELOCATION, ECX
+                MOV     MODE_32, AL
+                MOV     PFX_ASIZE, SIZE_OFF
+                MOV     PFX_OSIZE, SIZE_OFF
+                MOV     PFX_SEG, 0
+                MOV     DISASM_SP, OFFSET SV_DATA:DISASM_STACK
+                MOV     ACCU_SP, OFFSET SV_DATA:ACCU_STACK
+                MOV     NOT_FLAG, 0
+                MOV     FLAGS, 0
+                MOV     SYM_FLAG, SYM_NONE
+DISASM_FETCH::  LEA     BX, DISASM_PROGRAM
+DISASM_MORE::   MOV     AL, FS:[ESI]
+                INC     ESI
+                MOV     ACCU, AL
+                MOV     OPCODE, AL
+                AND     AL, 01H
+                MOV     OPSIZE, AL
+DISASM_NEXT:    MOV     CL, [BX]
+                INC     BX
+                CMP     CL, 20H                 ; Command?
+                JB      SHORT DISASM1           ; Yes ->
+                CMP     CL, 80H                 ; Subroutine call?
+                JAE     SHORT DISASM2           ; Yes ->
+                XCHAR   CL
+                JMP     SHORT DISASM_NEXT
+
+DISASM1:        MOVZX   ECX, CL
+                CALL    DISASM_JMP[ECX*2]
+                JMP     SHORT DISASM_NEXT
+
+DISASM2:        MOVZX   ECX, CL
+                MOV     DX, BX
+                SUB     DISASM_SP, 2
+                MOV     BX, DISASM_SP
+                MOV     [BX], DX
+                MOV     BX, DISASM_CALL[ECX*2-80H*2]
+                JMP     SHORT DISASM_NEXT
+
+DISASM          ENDP
+
+
+Q_END:          POP     AX
+                MOV     BYTE PTR [DI], 0
+                MOV     AL, SYM_FLAG
+                MOV     AH, FLAGS
+                AND     AH, F_EMPTY
+                MOV     EDX, SYM_ADDR
+                RET
+
+Q_MORE:         POP     AX
+                JMP     DISASM_MORE
+
+Q_EXT:          MOV     CL, [BX]
+                INC     BX
+                CMP     CL, 4
+                JAE     Q_END
+                MOVZX   ECX, CL
+                JMP     EXT_JMP[ECX*2]
+
+Q_PREFIX:       MOV     DX, [BX+0]
+                MOV     AL, [BX+2]
+                MOV     BX, DX
+                MOV     [BX], AL
+                POP     AX
+                JMP     DISASM_FETCH
+
+Q_RET:          MOV     BX, DISASM_SP
+                MOV     BX, [BX]
+                ADD     DISASM_SP, 2
+                RET
+
+Q_OPCODE:       MOV     AL, OPCODE
+                MOV     ACCU, AL
+                RET
+
+Q_NOT:          XOR     NOT_FLAG, 1
+                RET
+
+
+Q_OP:           XCHAR   TAB
+                RET
+
+Q_FLAGS:        MOV     AL, [BX]
+                INC     BX
+                OR      FLAGS, AL
+                RET
+
+Q_JMP_DST:      MOV     AL, [BX]
+                INC     BX
+                CMP     AL, 1
+                JE      SHORT Q_NEAR
+                CMP     AL, 2
+                JE      Q_FAR
+Q_SHORT:        MOVSX   EAX, BYTE PTR FS:[ESI]
+                INC     ESI
+                JMP     SHORT DNEAR2
+                
+Q_NEAR:         CALL    ASIZE
+                JNZ     SHORT DNEAR1
+                MOVSX   EAX, WORD PTR FS:[ESI]
+                ADD     ESI, 2
+                JMP     SHORT DNEAR2
+DNEAR1:         MOV     EAX, FS:[ESI]
+                ADD     ESI, 4
+DNEAR2:         ADD     EAX, ESI
+                ADD     EAX, RELOCATION
+                MOV     SYM_ADDR, EAX
+                MOV     SYM_FLAG, SYM_TEXT
+                CALL    XDWORD
+                RET
+
+
+Q_SWITCH:       MOVZX   ECX, BYTE PTR [BX]
+                INC     BX
+                JECXZ   DSWITCH9
+DSWITCH1:       MOV     AL, [BX+0]
+                CMP     ACCU, AL
+                JE      SHORT DSWITCH2
+                ADD     BX, 3
+                LOOP    DSWITCH1
+DSWITCH9:       RET
+
+DSWITCH2:       MOV     BX, [BX+1]
+                RET
+
+Q_MASK_EQ:      MOV     DL, [BX+0]
+                MOV     DH, [BX+1]
+                ADD     BX, 2
+                MOV     AL, ACCU
+                AND     AL, DL
+                CMP     AL, DH
+                SETE    AL
+COND_JUMP:      CMP     AL, NOT_FLAG
+                MOV     NOT_FLAG, 0
+                JNE     SHORT Q_JUMP
+                ADD     BX, 2
+                RET
+
+Q_JUMP:         MOV     BX, [BX]
+                RET
+
+Q_LD_MOD_REG_RM:MOV     AL, MOD_REG_RM
+                MOV     ACCU, AL
+                RET
+
+Q_TEST:         MOV     AL, [BX]
+                INC     BX
+                TEST    ACCU, AL
+                SETNE   AL
+                JMP     COND_JUMP
+
+Q_BITS:         MOVZX   DX, BYTE PTR [BX]
+                INC     BX
+                BSF     CX, DX
+                AND     ACCU, DL
+                SHR     ACCU, CL
+                RET
+
+Q_CMP:          MOV     DX, [BX+0]
+                MOV     AL, [BX+2]
+                ADD     BX, 3
+                XCHG    BX, DX
+                CMP     AL, [BX]
+                SETE    AL
+                XCHG    BX, DX
+                JMP     COND_JUMP
+
+Q_IMMED:        CALL    XIMMED
+                AND     FLAGS, NOT F_SIGNED
+                RET
+
+Q_MOD_REG_RM:   MOV     AL, FS:[ESI]            ; mod,reg,r/m
+                INC     ESI
+                MOV     MOD_REG_RM, AL
+                CALL    ASIZE                   ; Address size
+                JZ      SHORT Q_MOD_REG_RM_9    ; 16 ->
+                CMP     AL, 0C0H                ; mod=11?
+                JAE     SHORT Q_MOD_REG_RM_9    ; Yes -> no SIB
+                AND     AL, 07H                 ; r/m
+                CMP     AL, 04H                 ; SIB?
+                JNE     SHORT Q_MOD_REG_RM_9    ; No ->
+                MOV     AL, FS:[ESI]
+                INC     ESI
+                MOV     SIB, AL
+Q_MOD_REG_RM_9: RET
+
+
+Q_REG:          MOV     AL, MOD_REG_RM
+                SHR     AL, 3
+                CALL    XREG
+                RET
+
+Q_REGA:         MOV     AL, ACCU
+                CALL    XREG
+                RET
+
+Q_MEM:          MOV     AL, MOD_REG_RM
+                CMP     AL, 40H
+                JB      SHORT QMEM00
+                CMP     AL, 80H
+                JB      SHORT QMEM01
+                CMP     AL, 0C0H
+                JB      SHORT QMEM10
+QMEM11:         CALL    XREG
+                RET
+
+QMEM00:         AND     AL, 07H                 ; r/m
+                MOV     AH, 06H
+                CALL    ASIZE                   ; Address size
+                JZ      SHORT QMEM00_1          ; 16 -> 6 is special case
+                MOV     AH, 05H                 ; 32 -> 5 is special case
+QMEM00_1:       CMP     AL, AH
+                JE      SHORT QMEM00_2
+                CALL    QMEM_IND
+                JMP     SHORT QMEM_END
+
+QMEM00_2:       CALL    QMEM_BEGIN
+                CALL    QMEM_DISPW
+                JMP     SHORT QMEM_END
+
+QMEM01:         CALL    QMEM_IND
+                MOV     AL, FS:[ESI]
+                INC     ESI
+                CALL    XSBYTE
+QMEM_END:       XCHAR   "]"
+                RET
+
+QMEM10:         CALL    QMEM_IND
+                XCHAR   "+"
+                CALL    QMEM_DISPW
+                JMP     SHORT QMEM_END
+
+
+QMEM_BEGIN      PROC    NEAR
+                TEST    FLAGS, F_NO_PTR
+                JNZ     SHORT QMEM_B2A
+                LEA     DX, $BYTE
+                CMP     OPSIZE, 00H             ; byte
+                JE      SHORT QMEM_B2
+                LEA     DX, $DWORD
+                CMP     OPSIZE, 01H             ; word
+                JE      SHORT QMEM_B1
+                CALL    OSIZE                   ; Operand size
+                JZ      SHORT QMEM_B2           ; 16 ->
+                XCHAR   "f"
+                INC     DX
+                JMP     SHORT QMEM_B2
+QMEM_B1:        CALL    OSIZE                   ; Operand size
+                JNZ     SHORT QMEM_B2           ; 32 ->
+                INC     DX
+QMEM_B2:        CALL    XTEXT
+                LEA     DX, $PTR
+                CALL    XTEXT
+QMEM_B2A:       MOV     AL, PFX_SEG
+                OR      AL, AL
+                JZ      SHORT QMEM_B3
+                XCHAR   AL
+                XCHAR   "S"
+                XCHAR   ":"
+QMEM_B3:        XCHAR   "["
+                RET
+QMEM_BEGIN      ENDP
+
+QMEM_IND        PROC    NEAR
+                CALL    QMEM_BEGIN
+                MOV     AL, MOD_REG_RM
+                AND     AL, 07H                 ; r/m
+                CALL    ASIZE                   ; Address size
+                JNZ     SHORT QMEM_IND32        ; 32 ->
+                PUSH    BX
+                LEA     BX, RM_TAB
+                XLAT
+                MOV     BX, "BX"
+                MOV     AH, 01H
+                CALL    QMEM_IND1
+                MOV     BX, "BP"
+                MOV     AH, 02H
+                CALL    QMEM_IND1
+                MOV     BX, "SI"
+                MOV     AH, 04H
+                CALL    QMEM_IND1
+                MOV     BX, "DI"
+                MOV     AH, 08H
+                CALL    QMEM_IND1
+                POP     BX
+                RET
+
+QMEM_IND32:     CMP     AL, 04H
+                JE      SHORT QMEM_SIB
+                CALL    REG32
+                RET
+
+QMEM_SIB:       MOV     AL, SIB
+                AND     AL, 07H                 ; base
+                CMP     MOD_REG_RM, 40H         ; mod=0?
+                JAE     SHORT QMEM_SIB1         ; No -> normal case
+                CMP     AL, 05H                 ; base=5?
+                JNE     SHORT QMEM_SIB1         ; No -> normal case
+                CALL    QMEM_DISPW              ; disp32+(scale*index)
+                JMP     SHORT QMEM_SIB2
+
+QMEM_SIB1:      MOV     AL, SIB
+                CALL    REG32
+QMEM_SIB2:      MOV     AL, SIB
+                AND     AL, 7 SHL 3
+                CMP     AL, 4 SHL 3
+                JE      SHORT QMEM_SIB4
+                XCHAR   "+"
+                MOV     AL, SIB
+                SHR     AL, 6
+                AND     AL, 03H
+                JZ      SHORT QMEM_SIB3
+                MOV     CL, AL
+                MOV     AL, 01H
+                SHL     AL, CL
+                ADD     AL, "0"
+                XCHAR   AL
+                XCHAR   "*"
+QMEM_SIB3:      MOV     AL, SIB
+                SHR     AL, 3
+                CALL    REG32
+QMEM_SIB4:      RET
+
+QMEM_IND        ENDP
+
+
+
+QMEM_IND1       PROC    NEAR
+                TEST    AL, AH
+                JZ      SHORT QMEM_IND9
+                TEST    AL, 80H
+                JZ      SHORT QMEM_IND2
+                XCHAR   "+"
+QMEM_IND2:      OR      AL, 80H
+                CALL    ASIZE                   ; Address size
+                JZ      SHORT QMEM_IND3         ; 16 -> 
+                XCHAR   "E"
+QMEM_IND3:      XCHAR   BH
+                XCHAR   BL
+QMEM_IND9:      RET
+QMEM_IND1       ENDP
+
+
+Q_ACCUM:        MOV     AL, 0
+                CALL    XREG
+                RET
+
+Q_NIBBLE:       MOV     AL, ACCU
+                CALL    XNIBBLE
+                RET
+
+Q_O16:          CALL    OSIZE                   ; Operand size
+                SETZ    AL                      ; 16 -> AL:=1
+                JMP     COND_JUMP
+
+Q_A16:          CALL    ASIZE                   ; Address size
+                SETZ    AL                      ; 16 -> AL:=1
+                JMP     COND_JUMP
+
+Q_BYTE:         MOV     AL, FS:[ESI]
+                INC     ESI
+                CALL    XBYTE
+                RET
+
+QMEM_DISPW:     CALL    ASIZE                   ; Address size
+                JZ      SHORT Q_WORD            ; 16 ->
+                CALL    Q_DWORD
+                MOV     SYM_ADDR, EAX
+                MOV     SYM_FLAG, SYM_DATA
+                RET
+
+Q_DISP:         XCHAR   "["
+                CALL    QMEM_DISPW
+                XCHAR   "]"
+                RET
+
+Q_DWORD:        MOV     EAX, FS:[ESI]
+                ADD     ESI, 4
+                CALL    XDWORD
+                RET
+
+Q_WORD:         MOV     AX, FS:[ESI]
+                ADD     ESI, 2
+                CALL    XWORD
+                RET
+
+Q_TABLE:        MOVZX   AX, ACCU
+                SHL     AX, 1
+                ADD     BX, AX
+                MOV     BX, [BX]
+                RET
+
+Q_OP_SIZE:      MOV     AL, [BX]
+                INC     BX
+                MOV     OPSIZE, AL
+                RET
+
+Q_FAR:          CALL    ASIZE                   ; Address size
+                JNZ     SHORT DFAR1             ; 32 ->
+                MOVZX   ECX, WORD PTR FS:[ESI]  ; Oops, was MOVSX
+                ADD     ESI, 2
+                JMP     SHORT DFAR2
+DFAR1:          MOV     ECX, FS:[ESI]           ; Get offset
+                ADD     ESI, 4
+DFAR2:          MOV     AX, FS:[ESI]            ; Get selector
+                ADD     ESI, 2                  ; Skip selector
+                CALL    XWORD                   ; Output selector
+                XCHAR   ":"
+                MOV     EAX, ECX                ; Oops, adding ESI was wrong!
+                CALL    XDWORD                  ; Output offset
+                RET
+
+Q_PUSH:         PUSH    BX
+                DEC     ACCU_SP
+                MOV     BX, ACCU_SP
+                MOV     AL, ACCU
+                MOV     [BX], AL
+                POP     BX
+                RET
+
+Q_POP:          PUSH    BX
+                MOV     BX, ACCU_SP
+                MOV     AL, [BX]
+                MOV     ACCU, AL
+                INC     ACCU_SP
+                POP     BX
+                RET
+
+Q_XCHG:         PUSH    BX
+                MOV     BX, ACCU_SP
+                MOV     AL, ACCU
+                XCHG    AL, [BX]
+                MOV     ACCU, AL
+                POP     BX
+                RET
+
+Q_BACK:         DEC     ESI
+                RET
+
+SV_CODE         ENDS
+
+              ELSE
+
+;
+; No disassembler
+;
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+DISASM          PROC    NEAR
+                INC     ESI
+                RET
+DISASM          ENDP
+
+SV_CODE         ENDS
+
+              ENDIF
+
+                END
Index: trunk/src/emx/src/dos/disasm.inc
===================================================================
--- trunk/src/emx/src/dos/disasm.inc	(revision 18)
+++ trunk/src/emx/src/dos/disasm.inc	(revision 18)
@@ -0,0 +1,30 @@
+;
+; DISASM.INC -- Disassembler
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_CODE         SEGMENT
+
+                EXTRN   DISASM:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/dpmi.asm
===================================================================
--- trunk/src/emx/src/dos/dpmi.asm	(revision 18)
+++ trunk/src/emx/src/dos/dpmi.asm	(revision 18)
@@ -0,0 +1,62 @@
+;
+; DPMI.ASM -- Do not support DPMI
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE RPRINT.INC
+                INCLUDE VCPI.INC
+                INCLUDE MISC.INC
+
+                PUBLIC  CHECK_DPMI
+
+SV_DATA         SEGMENT
+
+$DPMI_NOT_SUPP  DB      "DPMI not supported", CR, LF, 0
+
+SV_DATA         ENDS
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+                ASSUME  DS:SV_DATA
+CHECK_DPMI      PROC    NEAR
+                CMP     VCPI_FLAG, FALSE
+                JNE     SHORT NO_DPMI
+                MOV     AX, 1687H
+                INT     2FH
+                OR      AX, AX
+                JNZ     SHORT NO_DPMI
+                LEA     DX, $DPMI_NOT_SUPP
+                CALL    RTEXT
+                MOV     AL, 0FFH
+                JMP     EXIT
+
+NO_DPMI:        RET
+CHECK_DPMI      ENDP
+
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/dpmi.inc
===================================================================
--- trunk/src/emx/src/dos/dpmi.inc	(revision 18)
+++ trunk/src/emx/src/dos/dpmi.inc	(revision 18)
@@ -0,0 +1,30 @@
+;
+; DPMI.INC -- Do not support DPMI
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+INIT_CODE       SEGMENT
+
+                EXTRN   CHECK_DPMI:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/emx.asm
===================================================================
--- trunk/src/emx/src/dos/emx.asm	(revision 18)
+++ trunk/src/emx/src/dos/emx.asm	(revision 18)
@@ -0,0 +1,1230 @@
+;
+; EMX.ASM -- Main module for emx.exe
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; <START_OF_EXCEPTION>
+; As a special exception, if you bind emx.exe to an executable file
+; (using emxbind), this does not cause the resulting executable file
+; to be covered by the GNU General Public License.  This exception
+; does not however invalidate any other reasons why the executable
+; file might be covered by the GNU General Public License.  However,
+; if you bind a modified copy of emx.exe to an executable file, you
+; have to include source code for emx.exe.
+;
+; If you modify this file, you have to remove the reference to the
+; special exception from all the source files and replace the text
+; between the outer <START_OF_EXCEPTION> and <END_OF_EXCEPTION> markers
+; with the following paragraph (which currently does not apply as you
+; have not modified this file):
+;
+; As a special exception, if you bind emx.exe to an executable file
+; (using emxbind), this does not cause the resulting executable file
+; to be covered by the GNU General Public License.  The source code
+; for emx.exe must be distributed with the executable file.  This
+; exception does not however invalidate any other reasons why the
+; executable file might be covered by the GNU General Public License.
+; <END_OF_EXCEPTION>
+;
+
+                INCLUDE EMX.INC
+                INCLUDE TABLES.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE PAGING.INC
+                INCLUDE OPRINT.INC
+                INCLUDE VPRINT.INC
+                INCLUDE MEMORY.INC
+                INCLUDE PMIO.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE SWAPPER.INC
+                INCLUDE EXCEPT.INC
+                INCLUDE RMINT.INC
+                INCLUDE PMINT.INC
+                INCLUDE VCPI.INC
+                INCLUDE DPMI.INC
+                INCLUDE RPRINT.INC
+                INCLUDE DEBUG.INC
+                INCLUDE LOADER.INC
+                INCLUDE XMS.INC
+                INCLUDE A20.INC
+                INCLUDE TERMIO.INC
+                INCLUDE VERSION.INC
+                INCLUDE HEADERS.INC
+                INCLUDE PMINT.INC
+                INCLUDE OPTIONS.INC
+                INCLUDE FILEIO.INC
+
+                PUBLIC  SV_TOS, RM_TOS
+                PUBLIC  FP_FLAG, FP_TMP, DOS_MAJOR, DOS_MINOR, ENV_EMXOPT
+                PUBLIC  CMDL_OPTIONS, ENV_PATH, ENV_EMXPATH
+                PUBLIC  PROT1
+                PUBLIC  CLEANUP, EXIT, RM_OUT_OF_MEM
+
+SV_DATA         SEGMENT
+
+;
+; Names of environment variables
+;
+$PATH           BYTE    "PATH", 0
+$EMXPATH        BYTE    "EMXPATH", 0
+$TMP            BYTE    "TMP", 0
+$EMXTMP         BYTE    "EMXTMP", 0
+$EMXOPT         BYTE    "EMXOPT", 0
+
+;
+; Program segment prefix and environment
+;
+                DALIGN  2
+
+EMXL_SEG        WORD    0                       ; PSP segment of emxl
+EMX_PSP         WORD    ?                       ; Our PSP segment
+ENV_SEG         WORD    ?                       ; Environment segment
+ENV_PATH        WORD    ?                       ; Pointer to PATH value
+ENV_EMXPATH     WORD    ?                       ; Pointer to EMXPATH value
+ENV_EMXOPT      WORD    ?                       ; Pointer to EMXOPT value
+ENV_TOTAL_SIZE  WORD    ?                       ; Size of environment, w/ exe
+
+;
+; The arguments of the initial process
+;
+ARG_STRINGS     BYTE    256 DUP (?)             ; Arguments
+
+;
+; Floating point
+;
+FP_TMP          WORD    ?                       ; 287/387 CW or SW
+FP_FLAG         BYTE    FP_NO                   ; No coprocessor
+
+;
+; This field is copied from HDR_SEG to SV_DATA
+;
+BIND_FLAG       BYTE    ?                       ; Bound application
+
+;
+; DOS version
+;
+DOS_MAJOR       BYTE    ?
+DOS_MINOR       BYTE    ?
+
+;
+; Options copied from the command line.  Non-option arguments don't
+; appear hear.  After starting the first process, CMDL_OPTIONS is
+; cleared by zeroing the first byte.
+;
+CMDL_OPTIONS    BYTE    64 DUP (0)
+
+;
+; Messages
+;
+$WRONG_CPU      BYTE    "This program requires an 80386 CPU", CR, LF, 0
+$WRONG_OPSYS    BYTE    "This program does not run in DOS mode of OS/2"
+                BYTE    CR, LF, 0
+$DOS_VERSION    BYTE    "This program requires DOS 3.0 or later", CR, LF, 0
+$NO_A20         BYTE    "Cannot enable A20", CR, LF, 0
+$RM_OUT_OF_MEM  BYTE    "Out of memory (RM)", CR, LF, 0
+
+SV_DATA         ENDS
+
+
+;
+; This area will be patched by emxbind when using emx.exe as DOS stub.
+;
+HDR_SEG         SEGMENT
+PATCH           LABEL   BIND_HEADER
+                BYTE    "emx ", VERSION, 0
+                BYTE    (SIZE BIND_HEADER - HDR_VERSION_LEN) DUP (0)
+HDR_SEG         ENDS
+
+
+                .386P
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; This is the proteced mode entry point
+;
+PROT1           LABEL   FAR
+                MOV     AX, G_SV_DATA_SEL
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                MOV     ES, AX
+                MOV     FS, AX
+                MOV     GS, AX
+                MOV     AX, G_SV_STACK_SEL
+                MOV     SS, AX
+                LEA     ESP, SV_TOS
+                AND     TSS_BUSY, NOT 2
+                MOV     AX, G_TSS_SEL
+                LTR     AX
+;
+; This must be done before any interrupt can be handled
+; (SLDT, LLDT in PMINT.ASM)
+;
+                MOV     AX, G_LDT_SEL           ; Minimal LDT
+                LLDT    AX                      ; Load LDTR
+;
+; Protected mode established
+;
+                CALL    DEBUG_INIT
+                XOR     EAX, EAX
+                MOV     DR6, EAX                ; Clear debug status register
+                CALL    INIT_FP
+;
+; From now onwards, we can switch back to real mode
+;
+; Enable paging
+;
+                MOV     PAGING, 1               ; Paging enabled
+                CMP     VCPI_FLAG, FALSE        ; VCPI?
+                JNE     SHORT PROT2             ; Yes -> paging already enabled
+                MOV     EAX, PAGE_DIR_PHYS
+                MOV     CR3, EAX                ; Load CR3
+                MOV     EAX, CR0
+                OR      EAX, CR0_PG             ; Enable paging
+                MOV     CR0, EAX
+;
+; Further initializations
+;
+PROT2:          STI                             ; Enable interrupts
+                CALL    INIT_LIN_MAP            ; Enable segment creation
+                CALL    INIT_PAGE_BMAP          ; Initialize freed page bitmap
+                CALL    INIT_SWAP               ; Enable swapping
+                CALL    INIT_TSS                ; Initialize new TSS
+                CALL    INIT_DBCS               ; Get DBCS lead bytes
+;
+; Create GDT entry for environment segment
+;
+                MOVZX   EBX, ENV_SEG
+                SHL     EBX, 4
+                MOVZX   ECX, ENV_TOTAL_SIZE
+                LEA     SI, G_ENV_DESC
+                MOV     AX, A_DATA32 OR DPL_0
+                CALL    CREATE_SEG
+;
+; Initialize termio structure for stdin (global data for all processes)
+;
+                LEA     BX, STDIN_TERMIO
+                CALL    TERMIO_INIT
+                MOV     STDIN_FL, 0
+;
+; Load program
+;
+                LEA     SI, ARG_STRINGS + 1     ; argv[0]
+                CALL    FIND_EXEC
+                MOV     NP1.NP_FNAME_OFF, EDX
+                MOV     NP1.NP_FNAME_SEL, DS
+                LEA     AX, PROC0               ; Dummy parent process
+                MOV     NP1.NP_PARENT, AX
+                MOV     NP1.NP_FPROC, AX
+                MOV     NP1.NP_MODE1, NP_SPAWN_SYNC
+                MOV     NP1.NP_MODE2, 0
+                LEA     SI, NP1                 ; Arguments
+                CALL    NEW_PROCESS             ; Load the program
+                OR      AX, AX                  ; Ok?
+                JZ      SHORT LOAD3
+                CALL    OTEXT                   ; Display error message
+                MOV     AX, 4C01H               ; Quit
+                INT     21H
+                JMP     SHORT $                 ; Never reached
+
+                ASSUME  DI:PTR PROCESS
+LOAD3:          MOV     CMDL_OPTIONS[0], 0      ; Ignore options from now on
+                MOV     [DI].P_STATUS, PS_RUN   ; Process is running!
+                MOV     PROCESS_PTR, DI         ; Current process (I/O etc.)
+                MOV     PROCESS_SIG, DI         ; Current process (Ctrl-Break)
+;
+; Now DS:DI points to the process table entry
+;
+; Switch to 32 bit code/data
+;
+                CMP     STEP_FLAG, FALSE        ; Debugging program?
+                JE      SHORT DISPATCH_1        ; No -> skip
+                MOV     DX, L_CODE_SEL          ; Set breakpoint
+                MOV     EAX, [DI].P_ENTRY_POINT ; on entry point
+                CALL    SET_BREAKPOINT
+                CALL    INS_BREAKPOINTS
+DISPATCH_1:     MOV     EAX, 0002H              ; This bit is always 1
+                PUSH    EAX
+                POPFD                           ; Clear all flag bits
+                LLDT    [DI].P_LDT              ; Use LDT
+; Stack empty!
+                MOV     EAX, L_DATA_SEL
+                PUSH    EAX                     ; SS
+                MOV     EBX, [DI].P_ESP
+                PUSH    EBX                     ; ESP
+                MOV     EAX, 0202H              ; IOPL=0, IF=1
+                CMP     STEP_FLAG, FALSE        ; Single stepping?
+                JE      SHORT DISPATCH_2        ; No -> skip
+                OR      EAX, FLAG_TF            ; Set trap flag
+DISPATCH_2:     PUSH    EAX                     ; EFLAGS
+                MOV     EAX, L_CODE_SEL
+                PUSH    EAX                     ; CS
+                MOV     EBX, [DI].P_ENTRY_POINT
+                PUSH    EBX                     ; EIP
+                MOV     AX, L_DATA_SEL
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                MOV     ES, AX
+                MOV     FS, AX
+                MOV     GS, AX
+                IRETD
+
+                ASSUME  DI:NOTHING
+
+;
+; We must not use FWAIT if there is no coprocessor. We use this loop
+; instead.
+;
+DELAY_FP        MACRO
+                MOV     ECX, 50
+                LOOP    $
+                ENDM
+
+;
+; Initialize CR0 for floating point math (287, 387, or emulator)
+;
+; Note: ET set by reset?
+;
+                ASSUME  DS:SV_DATA
+INIT_FP         PROC    NEAR
+                MOV     EAX, CR0                ; Get current CR0
+                AND     EAX, CR0_FPU            ; Keep only FPU related bits
+                MOV     RM_CR0, EAX             ; Save it
+                MOV     EAX, CR0                ; Get current CR0
+                AND     EAX, NOT (CR0_TS OR CR0_EM)
+                OR      EAX, CR0_MP             ; Assume FPU present
+                MOV     CR0, EAX
+;
+; Now check for coprocessor
+;
+                CMP     FP_IGNORE, FALSE        ; Check for coprocessor?
+                JNE     SHORT INIT_FP1          ; No  -> skip check
+                FNINIT
+                DELAY_FP                        ; Delay
+                MOV     FP_TMP, 0               ; 387 FNINIT sets CW to 037FH
+                FNSTCW  FP_TMP                  ; Copy CW to memory
+                DELAY_FP                        ; Delay
+                MOV     AX,  FP_TMP             ; Now check CW
+                AND     AX, 0F3FH               ; Keep PC and exception masks
+                CMP     AX, 033FH               ; Initialized?
+                JNE     SHORT INIT_FP1          ; No  -> no x87 coprocessor
+                MOV     FP_TMP, 0FFFFH          ; 387 FNINIT: SW &= 0x4700
+                FNSTSW  FP_TMP                  ; Copy SW to memory
+                DELAY_FP                        ; Delay
+                TEST    FP_TMP, NOT 47C0H       ; Initialized?
+                JNZ     SHORT INIT_FP1          ; No  -> no x87 coprocessor
+;
+; We have found *some* coprocessor (87, 287, 387, ...)
+;
+; If 1/0 equals -(1/0), we are dealing with a 287: FNINIT sets the 287
+; to projective mode, ie, -inf = +inf, whereas the 387 always uses
+; affine mode (-inf < +inf).
+;
+                MOV     FP_FLAG, FP_287         ; ST   ST(1)
+                FLD1                            ; 1.0
+                FLDZ                            ; 0.0  1.0
+                FDIV                            ; +inf
+                FLD     ST                      ; +inf +inf
+                FCHS                            ; -inf +inf  (287: +inf +inf)
+                FCOMPP                          ; (stack empty)
+                FSTSW   AX                      ; Status to AX
+                SAHF                            ; 387: NZ, 287: ZR
+                JE      SHORT INIT_FP1          ; 287 found -> skip
+                MOV     FP_FLAG, FP_387         ; 387 found
+INIT_FP1:
+;
+; Now set CR0
+;
+                MOV     EAX, CR0
+                AND     EAX, NOT CR0_FPU
+                CMP     FP_FLAG, FP_387         ; 387 coprocessor?
+                JNE     SHORT IFP_EMU           ; No  -> setup for emulation
+                OR      EAX, CR0_TS OR CR0_MP   ; Task switched, math present
+                JMP     SHORT IFP_SET
+IFP_EMU:        OR      EAX, CR0_TS OR CR0_EM   ; Task switched, emulate
+IFP_SET:        MOV     CR0, EAX                ; Set CR0
+                AND     EAX, CR0_FPU            ; Keep only FPU bits
+                MOV     PM_CR0, EAX             ; Save for switching to PM
+                RET                             ; Done
+INIT_FP         ENDP
+
+;
+; Initialize DBCS lead byte table.  Note that we can't call GET_DBCS_LEAD
+; directly.
+;
+INIT_DBCS       PROC    NEAR
+                PUSH    DS
+                MOV     EDX, 0
+                MOV     DS, DX
+                MOV     AX, 7F5AH
+                INT     21H
+                POP     DS
+                RET
+INIT_DBCS       ENDP
+
+SV_CODE         ENDS
+
+
+SV_STACK        SEGMENT
+                WORD    2048 DUP (?)
+SV_TOS          LABEL   WORD
+SV_STACK        ENDS
+
+
+
+RM_STACK        SEGMENT
+                WORD    1024 DUP (?)
+RM_TOS          LABEL   WORD
+RM_STACK        ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE
+
+
+
+;
+; Use backward jump to this code to make sure the prefetch queue
+; will be flushed
+;
+START_4:        JMPF16  G_SV_CODE_SEL, PROT1
+
+;
+; Entrypoint
+;
+
+                ASSUME  DS:NOTHING
+                .8086
+START:          MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                MOV     EMX_PSP, ES             ; Save PSP segment
+
+                CALL    EMXBIND
+                CALL    CHECK_CPU               ; 386 CPU required
+                CALL    CHECK_OPSYS             ; Check operating system
+
+                .386P
+
+                CALL    CHECK_EMXL              ; Run by emxl?
+                CALL    ENVIRONMENT             ; Read environment
+                CALL    ARGS                    ; Read command line arguments
+                CALL    GET_PATH                ; Get PATH/EMXPATH variables
+                CALL    GET_TMP                 ; Get TMP/EMXTMP variables
+                CALL    CHECK_DV                ; Check for DESQview
+                CALL    PROCESS_INIT            ; Initialize emx processes
+                CALL    HOOK_INT                ; Hook interrupts
+                CALL    CHECK_VCPI              ; Check for VCPI
+                CALL    CHECK_DPMI              ; Check for DPMI
+                                                ; (After CHECK_VCPI)
+                CALL    CHECK_VM
+                CALL    CHECK_XMS               ; Check for XMS
+                                                ; (After CHECK_VCPI)
+                CALL    INIT_TERMIO             ; Get keyboard type
+                CALL    INIT_A20                ; Find out which machine
+                                                ; (after CHECK_XMS)
+                CALL    INIT_BUFFER             ; Allocate buffers
+                CALL    INIT_MEMORY             ; Initialize memory allocation
+                CALL    INIT_PAGING             ; Initialize page tables
+                                                ; (after CHECK_VCPI, INIT_MEMORY)
+                CALL    INIT_ADDR               ; Initialize physical/linear
+                                                ; addresses (after INIT_MEMORY,
+                                                ; INIT_PAGING)
+                CALL    INIT_MEM_PHYS
+                CALL    INIT_VIDEO              ; Init video segments
+                CMP     XMS_FLAG, FALSE
+                JE      SHORT START_2
+                CALL    INIT_XMS                ; After CHECK_VCPI, INIT_MEMORY
+START_2:        CALL    INIT_BASES              ; After INIT_PAGING
+                CMP     HIMEM_COUNT, 0          ; Extended memory used?
+                JE      SHORT START_3           ; No  -> skip
+                CALL    INIT_HIMEM              ; Update high memory table
+                CALL    A20_ON                  ; Enable address line A20
+                CALL    CHECK_A20               ; Check if A20 is working
+                STI                             ; CHECK_A20 disables interrupts
+                OR      AX, AX                  ; Bad news?
+                JNE     SHORT START_3           ; No - > skip
+                LEA     DX, $NO_A20             ; Cannot enable A20
+                CALL    RTEXT
+                MOV     AL, 0FFH
+                JMP     SHORT EXIT
+START_3:        CALL    INIT_FILEIO             ; Initialize file handles
+                CALL    INIT_INT                ; Initialize interrupts
+                CALL    INIT_TIMER              ; Initialize timer interrupt
+
+                CMP     VCPI_FLAG, FALSE
+                JNE     START_VCPI
+                LGDT    GDT_PTR
+                LIDT    IDT_PTR
+                MOV     EAX, CR0
+                OR      AL, CR0_PE              ; Enable protected mode
+                MOV     CR0, EAX
+                JMP     START_4                 ; Flush prefetch queue
+
+
+;
+; Cleanup and exit to DOS
+;
+                ASSUME  DS:NOTHING
+EXIT:           PUSH    AX
+                CALL    CLEANUP
+                ASSUME  DS:SV_DATA
+                POP     AX
+                STI
+                MOV     AH, 4CH
+                INT     21H
+                JMP     SHORT $                 ; Never reached
+
+
+;
+; Convert some real-mode addresses to physical or linear addresses
+;
+                ASSUME  DS:SV_DATA
+INIT_ADDR       PROC    NEAR
+                LEA     DI, GDT_LIN
+                CALL    INIT_LIN_1
+                LEA     DI, IDT_LIN
+                CALL    INIT_LIN_1
+                LEA     DI, V2P_GDTR
+                CALL    INIT_LIN_1
+                LEA     DI, V2P_IDTR
+                CALL    INIT_LIN_1
+                LEA     DI, V2P_LIN
+                CALL    INIT_LIN_1
+                LEA     DI, LOMEM_HEAD_PHYS
+                CALL    INIT_PHYS_1
+                LEA     DI, HIMEM_HEAD_PHYS
+                CALL    INIT_PHYS_1
+                RET
+INIT_ADDR       ENDP
+
+;
+; Convert one real-mode address to a physical address
+;
+; Note: the object pointed to by the address must be contained completely
+;       in *one* physical page.
+;
+; In:   DI      Pointer to a DWORD which contains in the lower word the
+;               real-mode offset
+;
+INIT_PHYS_1     PROC    NEAR
+                MOV     DX, [DI]                ; Get real-mode offset
+                MOV     AX, SV_DATA             ; Use this segment
+                CALL    RM_TO_PHYS              ; Convert to physical address
+                MOV     [DI], EAX               ; Store physical address
+                RET
+INIT_PHYS_1     ENDP
+
+;
+; Convert one real-mode address to a linear address
+;
+; Note: the object pointed to by the address must not be accessed with
+;       G_PHYS_SEL. (Why?)
+;
+; In:   DI      Pointer to a DWORD which contains in the lower word the
+;               real-mode offset
+;
+INIT_LIN_1      PROC    NEAR
+                XOR     EAX, EAX
+                MOV     AX, SV_DATA             ; Use this segment
+                SHL     EAX, 4
+                MOVZX   EDX, WORD PTR [DI]      ; Get real-mode offset
+                ADD     EAX, EDX
+                MOV     [DI], EAX               ; Store linear address
+                RET
+INIT_LIN_1      ENDP
+
+
+;
+; Put the base addresses of some segments into the GDT. This is done
+; by using the BASE_TABLE table. Each table entry consists of two (16-bit)
+; words: The first word is the real-mode segment, the second word points
+; to the GDT entry, which already contains the offset in the base 0..15 field.
+;
+
+                ASSUME  DS:SV_DATA
+INIT_BASES      PROC    NEAR
+                LEA     SI, BASE_TABLE          ; Table of segment/offset pairs
+IB_LOOP:        MOV     AX, [SI+0]              ; Get real-mode segment
+                OR      AX, AX                  ; End of table?
+                JZ      SHORT IB_END            ; Yes -> done
+                MOV     DI, [SI+2]              ; Offset of GDT entry (SV_DATA)
+                CALL    INIT_DESC               ; Set base field
+                ADD     SI, 4                   ; Next table entry
+                JMP     SHORT IB_LOOP           ; Repeat for all entries
+IB_END:         RET                             ; Done
+INIT_BASES      ENDP
+
+
+;
+; If called by emxl.exe, the command line is formatted this way:
+;
+;   -/xxxx/
+;
+; where xxxx is the (hexadecimal) PSP segment of emxl.exe.  Note that there
+; is no blank before the dash.  If called by emxl.exe, we used the (patched)
+; options and the command line arguments of emxl.exe -- under DOS we can
+; access memory of other `processes'.
+;
+
+                ASSUME  DS:SV_DATA
+CHECK_EMXL      PROC    NEAR
+                MOV     ES, EMX_PSP             ; Access PSP (command line)
+                MOV     DI, 80H                 ; Point to length field
+                MOV     AL, 7                   ; Length must be 7
+                SCAS    BYTE PTR ES:[DI]
+                JNE     SHORT CE_RET
+                MOV     AL, "-"                 ; Check for "-/"
+                SCAS    BYTE PTR ES:[DI]
+                JNE     SHORT CE_RET
+                MOV     AL, "/"
+                SCAS    BYTE PTR ES:[DI]
+                JNE     SHORT CE_RET
+                MOV     DX, 0
+                MOV     CX, 0404H
+CE_1:           MOV     AL, ES:[DI]
+                INC     DI
+                SUB     AL, "0"
+                JB      SHORT CE_RET
+                CMP     AL, 10
+                JB      SHORT CE_2
+                SUB     AL, "A" - ("0" + 10)
+                CMP     AL, 10
+                JB      SHORT CE_RET
+                CMP     AL, 15
+                JA      SHORT CE_RET
+CE_2:           SHL     DX, CL
+                OR      DL, AL
+                DEC     CH
+                JNZ     SHORT CE_1
+                MOV     AL, "/"                 ; Check for "/", CR
+                SCAS    BYTE PTR ES:[DI]
+                JNE     SHORT CE_RET
+                MOV     AL, CR
+                SCAS    BYTE PTR ES:[DI]
+                JNE     SHORT CE_RET
+;
+; Check for emx signature
+;
+                MOV     DI, 100H                ; Data segment of emxl
+                PUSH    DS                      ; Save DS
+                MOV     AX, HDR_SEG
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                LEA     SI, PATCH.BND_SIGNATURE
+                MOV     CX, HDR_EMX_LEN
+                CLD
+                REPE    CMPS BYTE PTR DS:[SI], BYTE PTR ES:[DI]
+                POP     DS                      ; Restore DS
+                ASSUME  DS:SV_DATA
+                JNE     SHORT CE_RET
+                MOV     EMXL_SEG, DX            ; It looks right
+CE_RET:         RET
+CHECK_EMXL      ENDP
+
+;
+; Parse EMXOPT and command line
+;
+; When run manually (or by an old version of emxl), process the following
+; items (note that we don't know about the emxbind patch area here):
+;
+;   1/ EMXOPT environment variable
+;   2/ command line
+
+; When run by emxl.exe, process the following items:
+;
+;   1/ emxbind patch area of emxl.exe
+;   2/ EMXOPT environment variable
+;   3/ command line of emxl.exe
+;
+; When bound with an a.out file (without emxl.exe), process the following
+; items:
+;
+;   1/ emxbind patch area of this program
+;   2/ EMXOPT environment variable
+;
+                ASSUME  DS:SV_DATA
+
+ARGS            PROC    NEAR
+                MOV     NP1.NP_ARG_COUNT, 0     ; No arguments
+                MOV     AX, EMXL_SEG
+                OR      AX, AX
+                JNZ     SHORT ARGS_01
+                CMP     BIND_FLAG, FALSE        ; Bound?
+                JE      SHORT ARGS_10           ; No  -> skip
+                MOV     AX, HDR_SEG
+                LEA     SI, PATCH.BND_OPTIONS
+                JMP     SHORT ARGS_02
+ARGS_01:        LEA     SI, (BIND_HEADER PTR ES:[100H]).BND_OPTIONS
+ARGS_02:        MOV     ES, AX
+                CALL    RM_OPTIONS              ; Parse options in patch area
+                CALL    RM_SKIP_BLANKS
+                OR      AL, AL                  ; End of string?
+                JNZ     USAGE                   ; No  -> error
+;
+; Process options in the EMXOPT environment variable
+;
+ARGS_10:        LEA     BX, $EMXOPT
+                CALL    GETENV                  ; Get EMXOPT environment var.
+                OR      DI, DI                  ; Found?
+                JZ      SHORT ARGS_11           ; No  -> skip
+                MOV     SI, DI
+                CALL    RM_OPTIONS              ; Parse options in EMXOPT
+                CALL    RM_SKIP_BLANKS
+                OR      AL, AL                  ; End of string?
+                JNZ     USAGE                   ; No  -> error
+;
+; Process command line
+;
+ARGS_11:        MOV     AX, EMXL_SEG            ; Try emxl's PSP
+                OR      AX, AX                  ; Run by emxl.exe?
+                JNZ     SHORT ARGS_12           ; Yes -> use emxl's cmd line
+                MOV     AX, EMX_PSP             ; Use our PSP
+ARGS_12:        MOV     ES, AX                  ; Access PSP (command line)
+                MOV     SI, 81H                 ; Start of command line
+                MOV     BL, ES:[SI-1]           ; Fetch length of command line
+                MOV     BH, 0
+                MOV     BYTE PTR ES:[SI+BX], 0  ; Terminate string with 0
+                CALL    RM_SKIP_BLANKS          ; Skip leading blanks
+                CMP     BIND_FLAG, FALSE        ; Bound?
+                JNE     SHORT ARGS_13           ; Yes -> don't read options
+                CMP     EMXL_SEG, 0             ; Run by new emxl?
+                JNE     SHORT ARGS_13           ; Yes -> don't read options
+                PUSH    SI
+                CALL    RM_OPTIONS              ; Parse options
+                POP     AX
+                PUSH    SI                      ; Save pointer
+                MOV     CX, SI                  ; Copy options
+                SUB     CX, AX
+                CMP     CX, SIZE CMDL_OPTIONS
+                JAE     USAGE
+                XCHG_DS_ES
+                ASSUME  DS:NOTHING
+                MOV     SI, AX
+                LEA     DI, CMDL_OPTIONS
+                CLD
+                REP     MOVSB
+                XOR     AL, AL
+                STOSB
+                XCHG_DS_ES
+                ASSUME  DS:SV_DATA
+                POP     SI                      ; Restore pointer
+ARGS_13:        CALL    NAMES                   ; Parse arguments
+                RET
+ARGS            ENDP
+
+
+;
+; Parse command line for user program
+;
+; In:  ES:SI    Pointer to command line (null terminated)
+;
+NAMES           PROC    NEAR
+                XOR     EDI, EDI
+                LEA     DI, ARG_STRINGS         ; Put arguments here
+                MOV     NP1.NP_ARG_OFF, EDI
+                MOV     NP1.NP_ARG_SEL, G_SV_DATA_SEL
+                CMP     EMXL_SEG, 0             ; Run by emxl?
+                JNE     SHORT NAMES0            ; Yes -> copy argv[0]
+                CMP     BIND_FLAG, FALSE        ; Bound?
+                JE      SHORT NAMES1            ; No  -> skip
+;
+; Copy argv[0]
+;
+NAMES0:         MOV     FS, ENV_SEG
+                MOV     BX, NP1.NP_ENV_SIZE     ; End of environment
+                ADD     BX, 2                   ; Skip word count
+                MOV     BYTE PTR [DI], 80H      ; No flags set
+                INC     DI                      ; Skip flags byte
+COPY_ARGV0:     MOV     AL, FS:[BX]             ; Copy program name
+                MOV     DS:[DI], AL
+                INC     BX
+                INC     DI
+                OR      AL, AL                  ; End of program name?
+                JNZ     COPY_ARGV0              ; No  -> carry on copying
+                INC     NP1.NP_ARG_COUNT        ; One argument
+;
+; Command line
+;
+NAMES1:         CALL    RM_SKIP_BLANKS          ; Skip blanks
+                OR      AL, AL                  ; End of command line?
+                JZ      SHORT NAMES9            ; Yes -> done
+;
+; Parse one argument
+;
+; "..."                         Quoted string, may contain blanks
+; \"                            Odd number 2n+1 of \ followed by " is read as
+;                               n backslashes followed by "
+; \\"                           Even number 2n of \ followed by " is read as
+;                               n backslashes followed by start/end of string
+;
+NAMES2:         MOV     CX, 0                   ; Number of backslashes := 0
+                MOV     DL, 0                   ; Not within quoted string
+                MOV     DH, 00H                 ; No quotes used
+                INC     NP1.NP_ARG_COUNT        ; We've found an argument
+                MOV     BX, DI                  ; Save pointer to flags
+                INC     DI                      ; Space for flags
+NAMES3:         MOV     AL, ES:[SI]             ; Fetch character
+;
+; First test for characters which don't automatically insert backslashes
+;
+                CMP     AL, "\"                 ; Backslash?
+                JE      SHORT NAMES_BACKSLASH   ; Yes -> special treatment
+                CMP     AL, '"'                 ; Quote?
+                JE      SHORT NAMES_QUOTE       ; Yes -> special treatment
+                JCXZ    NAMES5
+NAMES4:         MOV     BYTE PTR DS:[DI], "\"
+                INC     DI
+                LOOP    NAMES4
+NAMES5:         OR      AL, AL                  ; End of command line?
+                JZ      SHORT NAMES_END         ; Yes -> special treatment
+                CMP     AL, " "                 ; Blank?
+                JE      SHORT NAMES_WHITE       ; Yes -> special treatment
+                CMP     AL, TAB                 ; Tab?
+                JE      SHORT NAMES_WHITE       ; Yes -> special treatment
+NAMES_PUT:      MOV     DS:[DI], AL             ; Store character
+                INC     DI                      ; Next destination location
+                INC     SI                      ; Skip to next character
+                JMP     SHORT NAMES3            ; Repeat
+
+NAMES_BACKSLASH:INC     CX                      ; Count backslashes
+                INC     SI                      ; Skip to next character
+                JMP     SHORT NAMES3            ; Repeat
+
+NAMES_WHITE:    OR      DL, DL                  ; Within string?
+                JNZ     SHORT NAMES_PUT         ; Yes -> store character
+NAMES_END:      OR      DH, 80H                 ; Store flags (non-zero,
+                MOV     DS:[BX], DH             ; otherwise end of string!)
+                MOV     BYTE PTR DS:[DI], 0     ; End of argument
+                INC     DI                      ; Next destination location
+                JMP     SHORT NAMES1            ; Skip blanks, check for end
+
+NAMES_QUOTE:    SUB     CX, 2                   ; Insert CX/2 backslashes
+                JB      SHORT NAMES_Q1
+                MOV     BYTE PTR DS:[DI], "\"
+                INC     DI
+                JMP     SHORT NAMES_QUOTE
+
+NAMES_Q1:       TEST    CX, 1                   ; Odd CX?
+                MOV     CX, 0
+                JNZ     SHORT NAMES_PUT         ; Yes -> store quote
+                OR      DH, 01H                 ; Quotes used
+                NOT     DL                      ; Toggle quote flag
+                INC     SI                      ; Skip to next character
+                JMP     SHORT NAMES3            ; Repeat
+
+NAMES9:         SUB     DI, OFFSET SV_DATA:ARG_STRINGS
+                MOV     NP1.NP_ARG_SIZE, DI
+                CMP     NP1.NP_ARG_COUNT, 1     ; Program name given?
+                JB      USAGE                   ; No  -> complain
+                RET
+
+NAMES           ENDP
+
+;
+; Read the environment, compute the size and number of variables
+;
+; We use emxl's environment if we're run by emxl.exe.  This way, we
+; get the executable path name of the program bound with emxl.
+;
+;
+ENVIRONMENT     PROC    NEAR
+                MOV     AX, EMXL_SEG            ; Get emxl's PSP segment
+                OR      AX, AX                  ; Run by emxl.exe?
+                JNZ     SHORT ENV_1             ; Yes -> use emxl's environment
+                MOV     AX, EMX_PSP             ; No: use our environment
+ENV_1:          MOV     ES, AX
+                MOV     BX, ES:[2CH]            ; Get segment of environment
+                MOV     ENV_SEG, BX
+                MOV     ES, BX
+                MOV     NP1.NP_ENV_OFF, 0
+                MOV     NP1.NP_ENV_SEL, G_ENV_SEL
+                MOV     NP1.NP_ENV_SIZE, 0
+                MOV     NP1.NP_ENV_COUNT, 0
+                MOV     ENV_TOTAL_SIZE, 0
+                CALL    SCAN_ENV
+                MOV     NP1.NP_ENV_SIZE, BX
+                MOV     NP1.NP_ENV_COUNT, DX
+                MOV     ENV_TOTAL_SIZE, DI
+;
+; Build EMX_DIR which is the path name of the directory from which
+; emx.exe was run or loaded.  If emx.exe was bound to the program,
+; EMX_DIR will be empty.
+;
+                CMP     BIND_FLAG, FALSE        ; Bound?
+                JE      SHORT EMXDIR_1          ; No -> scan environment
+                CMP     EMXL_SEG, 0             ; Run by emxl.exe?
+                JZ      SHORT EMXDIR_FAIL       ; No -> EMX_DIR empty
+EMXDIR_1:       MOV     ES, EMX_PSP
+                MOV     ES, ES:[2CH]            ; Get segment of environment
+                CALL    SCAN_ENV
+                TEST    BX, BX
+                JZ      SHORT EMXDIR_FAIL
+;
+; Find the length of the directory name
+;
+                ADD     BX, 2                   ; Skip word count
+                MOV     SI, BX                  ; Save start address
+                MOV     CX, BX                  ; Points to last delim + 1
+EMXDIR_LOOP:    MOV     AL, ES:[BX]             ; Fetch next character
+                TEST    AL, AL                  ; End of string?
+                JZ      SHORT EMXDIR_EOS        ; Yes -> done
+                CMP     AL, ":"                 ; Delimiter?
+                JE      SHORT EMXDIR_DELIM      ; Yes -> remember position
+                CMP     AL, "\"                 ; Delimiter?
+                JE      SHORT EMXDIR_DELIM      ; Yes -> remember position
+                CMP     AL, "/"                 ; Delimiter? (Can this happen?)
+                JE      SHORT EMXDIR_DELIM      ; Yes -> remember position
+                INC     BX                      ; Skip the character
+                JMP     SHORT EMXDIR_LOOP       ; Loop again
+
+EMXDIR_DELIM:   INC     BX                      ; Skip the character
+                MOV     CX, BX                  ; Remember position
+                JMP     SHORT EMXDIR_LOOP       ; Loop again
+
+EMXDIR_EOS:     SUB     CX, SI                  ; Is there a directory?
+                JZ      EMXDIR_CWD              ; No  -> use current directory
+;
+; The program name includes a directory.  For simplicity, assume
+; it's an absolute path name.
+;
+                LEA     DI, EMX_DIR
+EMXDIR_COPY:    MOV     AL, ES:[SI]
+                MOV     [DI], AL
+                INC     SI
+                INC     DI
+                LOOP    EMXDIR_COPY
+                MOV     BYTE PTR [DI], 0
+                JMP     SHORT EMXDIR_DONE
+
+;
+; The program name does not include a directory.  Use the current
+; directory.
+;
+EMXDIR_CWD:     MOV     AH, 19H                 ; Get current disk
+                INT     21H
+                ADD     AL, "A"
+                MOV     EMX_DIR[0], AL
+                MOV     EMX_DIR[1], ":"
+                MOV     EMX_DIR[2], "\"
+                LEA     SI, EMX_DIR + 3
+                MOV     DL, 0                   ; Current drive
+                MOV     AH, 47H                 ; Get current directory
+                INT     21H
+                JC      SHORT EMXDIR_FAIL
+;
+; Add a backslash to the end if required
+;
+                LEA     SI, EMX_DIR + 2
+EMXDIR_BS:      LODS    BYTE PTR DS:[SI]
+                TEST    AL, AL
+                JNZ     SHORT EMXDIR_BS
+                CMP     BYTE PTR [SI-2], "\"
+                JE      SHORT EMXDIR_DONE
+                MOV     BYTE PTR [SI-1], "\"
+                MOV     BYTE PTR [SI-0], 0
+                JMP     SHORT EMXDIR_DONE
+
+EMXDIR_FAIL:    MOV     EMX_DIR[0], 0
+EMXDIR_DONE:    RET
+ENVIRONMENT     ENDP
+
+
+;
+; In:  ES       Segment of environment
+;
+; Out: DX       Number of environment variables
+;      BX       Pointer to end of environment
+;      DI       Pointer to end of program name
+;
+SCAN_ENV        PROC    NEAR
+                MOV     CX, 8000H
+                XOR     DX, DX
+                XOR     DI, DI
+                XOR     AL, AL
+                CLD
+                CMP     WORD PTR ES:[DI], 0
+                JE      SHORT SE_2
+SE_1:           INC     DX
+                REPNE   SCAS BYTE PTR ES:[DI]
+                JNE     SHORT SE_9
+                SCAS    BYTE PTR ES:[DI]
+                JE      SHORT SE_3
+                LOOP    SE_1
+                JMP     SHORT SE_9
+SE_2:           INC     DI
+SE_3:           MOV     BX, DI
+                ADD     DI, 2                   ; Skip word count
+                REPNE   SCAS BYTE PTR ES:[DI]
+                JNE     SHORT SE_9
+                RET
+;
+; Bad environment
+;
+SE_9:           XOR     DX, DX
+                XOR     BX, BX
+                XOR     DI, DI
+                RET
+SCAN_ENV        ENDP
+
+
+;
+; Get PATH and EMXPATH environment variables
+;
+GET_PATH        PROC    NEAR
+                LEA     BX, $PATH
+                CALL    GETENV
+                MOV     ENV_PATH, DI
+                LEA     BX, $EMXPATH
+                CALL    GETENV
+                MOV     ENV_EMXPATH, DI
+                LEA     BX, $EMXOPT
+                CALL    GETENV
+                MOV     ENV_EMXOPT, DI
+                RET
+GET_PATH        ENDP
+
+;
+; Get EMXTMP environment variable. If EMXTMP is not set, TMP will
+; be used instead.
+;
+GET_TMP         PROC    NEAR
+                LEA     BX, $EMXTMP
+                CALL    GETENV
+                OR      DI, DI
+                JNZ     SHORT GET_TMP1
+                LEA     BX, $TMP
+                CALL    GETENV
+GET_TMP1:       CALL    SET_TMP_DIR
+                RET
+GET_TMP         ENDP
+
+
+;
+; Search environment
+;
+; In:   DS:BX   Pointer to name of environment variable
+;
+; Out:  DI=0    Variable not found
+;       ES:DI   Pointer to value of environment variable
+;
+GETENV          PROC    NEAR
+                MOV     ES, ENV_SEG
+                XOR     DI, DI                  ; ES:DI points to environment
+                CLD
+GETENV_NEXT:    CMP     BYTE PTR ES:[DI], 0     ; Empty environment?
+                JE      SHORT GETENV_FAILURE    ; Yes -> not found
+                PUSH    BX                      ; Save pointer to name
+GETENV_COMPARE: MOV     AL, [BX]
+                CMP     AL, ES:[DI]             ; Compare names
+                JNE     SHORT GETENV_DIFF       ; Mismatch -> try next one
+                OR      AL, AL                  ; Shouldn't happen (`='!)
+                JZ      SHORT GETENV_DIFF       ; (name matches completely)
+                INC     BX
+                INC     DI
+                JMP     SHORT GETENV_COMPARE    ; Compare next character
+GETENV_DIFF:    POP     BX                      ; Restore pointer to name
+                OR      AL, AL                  ; End of name reached?
+                JE      SHORT GETENV_EQUAL      ; Yes -> candidate found
+GETENV_SKIP:    XOR     AL, AL
+                MOV     ECX, 32767              ; Search for next entry
+                REPNE   SCAS BYTE PTR ES:[DI]
+                JMP     SHORT GETENV_NEXT       ; Check that entry
+
+GETENV_EQUAL:   CMP     BYTE PTR ES:[DI], "="   ; Exact match?
+                JNE     SHORT GETENV_SKIP       ; No  -> go to next entry
+                INC     DI                      ; Skip `='
+                JMP     SHORT GETENV_RET        ; Return pointer to value
+
+GETENV_FAILURE: XOR     DI, DI                  ; Not found
+GETENV_RET:     RET
+GETENV          ENDP
+
+
+
+
+;
+; Read emxbind patch area
+;
+; Note: This code must use only 8086/88 instrutions
+;
+                ASSUME  DS:SV_DATA
+                .8086
+EMXBIND         PROC    NEAR
+                MOV     AX, HDR_SEG
+                MOV     ES, AX                  ; Access emxbind patch area
+                ASSUME  ES:HDR_SEG
+                MOV     AL, PATCH.BND_BIND_FLAG
+                MOV     BIND_FLAG, AL           ; Copy to data segment
+EMXBIND_RET:    RET
+                ASSUME  ES:NOTHING
+EMXBIND         ENDP
+
+                .386P
+
+;
+; Abort if not running on a 386 or later
+;
+; Note: This code must use only 8086/88 instrutions
+;
+                ASSUME  DS:SV_DATA
+                .8086
+CHECK_CPU       PROC    NEAR
+                PUSHF                           ; Save flags
+                XOR     AX, AX                  ; Clear all bits
+                PUSH    AX                      ; Clear all flag bits
+                POPF
+                STI                             ; Enable interrupts
+                PUSHF                           ; Copy flags to AX
+                POP     AX
+                POPF                            ; Restore flags
+                STI                             ; Enable interrupts
+                NOT     AX                      ; Complement all bits
+                AND     AX, 0F000H              ; Flags!=F000 -> 286/386/...
+                JZ      WRONG_CPU               ; 86/186 -> error
+                PUSHF                           ; Save flags
+                MOV     AX,7000H                ; Set NT:=1, IOPL:=3
+                PUSH    AX
+                POPF
+                STI                             ; Enable interrupts
+                PUSHF                           ; Copy flags to AX
+                POP     AX
+                POPF                            ; Restore flags
+                STI                             ; Enable interrupts
+                AND     AX, 7000H               ; NT and IOPL sticky?
+                JZ      WRONG_CPU               ; No  -> 286, error
+                RET                             ; Ok, it's an 80386
+
+WRONG_CPU:      LEA     DX, $WRONG_CPU          ; Display message: 386 required
+                JMP     SHORT ABORT             ; and abort
+
+CHECK_CPU       ENDP
+
+                .386P
+
+;
+; Abort if unsupported operating system
+;
+                ASSUME  DS:SV_DATA
+CHECK_OPSYS     PROC    NEAR
+                MOV     AH, 30H
+                INT     21H                     ; Get operating system version
+                MOV     DOS_MAJOR, AL
+                MOV     DOS_MINOR, AH
+                CMP     AL, 10                  ; OS/2 1.x?
+                JE      WRONG_OPSYS             ; Yes -> won't work
+                CMP     AL, 3                   ; DOS 3.0 or later?
+                JAE     OPSYS_OK                ; Yes -> ok
+                CMP     BIND_FLAG, FALSE        ; Bound?
+                JE      SHORT OPSYS_OK          ; No  -> ok
+                LEA     DX, $DOS_VERSION        ; Display error message
+                JMP     SHORT ABORT             ; and abort
+
+OPSYS_OK:       RET
+
+WRONG_OPSYS:    LEA     DX, $WRONG_OPSYS        ; Display error message
+ABORT::         CALL    RTEXT
+                MOV     AX, 4CFFH               ; Abort
+                INT     21H
+                JMP     SHORT $                 ; Never reached
+
+CHECK_OPSYS     ENDP
+
+
+;
+; Check for DESQview
+;
+                ASSUME  DS:SV_DATA
+CHECK_DV        PROC    NEAR
+                MOV     AH, 2BH                 ; `Set current date'
+                MOV     AL, 01H                 ; Subfunction: get version
+                MOV     CX, 4445H               ; 'DE'
+                MOV     DX, 5351H               ; 'SQ'
+                INT     21H
+                CMP     AL, 0FFH                ; DESQview installed?
+                JE      SHORT CDV_RET           ; No -> return
+                MOV     DV_FLAG, NOT FALSE
+CDV_RET:        RET
+CHECK_DV        ENDP
+
+
+;
+; Determine the linear address of video memory and set the
+; base address of G_VIDEO_SEL
+;
+; Must not be called before INIT_PAGING as G_PHYS_DESC is used!
+;
+                ASSUME  DS:SV_DATA
+INIT_VIDEO      PROC    NEAR
+                MOV     EAX, 0B8000H            ; ???
+                CMP     MACHINE, MACH_PC98      ; NEC PC-98?
+                JE      SHORT VIOMEM1           ; Yes ->
+                CMP     MACHINE, MACH_FMR70     ; FMR70?
+                JE      SHORT VIOMEM1           ; Yes ->
+                INT     11H                     ; Equipment determination
+                AND     AL, 30H                 ; Initial video mode
+                CMP     AL, 30H                 ; Monochrome adapter?
+                MOV     EAX, 0B0000H
+                JE      SHORT VIOMEM1           ; Yes ->
+                MOV     EAX, 0B8000H
+VIOMEM1:        ADD     EAX, G_PHYS_BASE        ; Compute linear address
+                MOV     VIDEO_LIN, EAX          ; Store linear address
+                LEA     DI, G_VIDEO_DESC
+                CALL    RM_SEG_BASE
+                CALL    VINIT                   ; Get the width and height
+                RET
+INIT_VIDEO      ENDP
+
+;
+; Cleanup before returning to DOS
+;
+                ASSUME  DS:NOTHING
+CLEANUP         PROC    NEAR
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                CALL    CLEANUP_TIMER
+                CALL    CLEANUP_INT
+                CALL    CLEANUP_SIGNAL
+                CALL    CLEANUP_SWAP
+                CALL    CLEANUP_MEMORY
+                CALL    CLEANUP_VCPI
+                CALL    CLEANUP_XMS
+                CALL    CLEANUP_A20
+                RET
+CLEANUP         ENDP
+
+;
+; Out of memory (real mode)
+;
+                ASSUME  DS:SV_DATA
+RM_OUT_OF_MEM:  LEA     DX, $RM_OUT_OF_MEM
+                CALL    RTEXT
+                MOV     AL, 0FFH
+                JMP     EXIT
+
+
+INIT_CODE       ENDS
+
+                END     START
Index: trunk/src/emx/src/dos/emx.inc
===================================================================
--- trunk/src/emx/src/dos/emx.inc	(revision 18)
+++ trunk/src/emx/src/dos/emx.inc	(revision 18)
@@ -0,0 +1,312 @@
+;
+; EMX.INC -- Global definitions for emx
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+FALSE           =       0
+
+;
+; Assembly-time options (for debugging)
+;
+DEBUG_MEM       =       FALSE
+DEBUG_MEM_WAIT  =       FALSE
+DEBUG_MAP       =       FALSE
+STOP_SWAP       =       FALSE
+DEBUG_SWAP      =       FALSE
+
+;
+; Floating point support
+;
+FLOATING_POINT  =       NOT FALSE
+
+;
+; GDT Selectors
+;
+G_NULL_SEL      =       00H             ; NULL
+G_GDT_MEM_SEL   =       08H             ; The GDT as memory segment
+G_IDT_MEM_SEL   =       10H             ; The IDT as memory segment
+G_PHYS_SEL      =       18H             ; Physical memory
+G_SV_CODE_SEL   =       20H             ; Supervisor code segment
+G_REAL_SEL      =       28H             ; Used for switching to real mode
+G_INIT_SEL      =       30H             ; Mixed mode init/exit code
+G_SV_DATA_SEL   =       38H             ; Supervisor data
+G_SV_STACK_SEL  =       40H             ; Supervisor stack
+G_VIDEO_SEL     =       48H             ; Video memory
+G_TSS_SEL       =       50H             ; TSS
+G_SERVER_SEL    =       58H             ; VCPI Server (3 selectors)
+G_ENV_SEL       =       70H             ; Environment
+G_HDR_SEL       =       78H             ; emxbind patch area
+G_TMP1_SEL      =       80H             ; For copying arguments/environment
+G_TMP2_SEL      =       88H             ; For copying arguments/environment
+G_ZERO_SEL      =       90H             ; For VCPI (prot mode -> real mode)
+G_BUF1_SEL      =       98H             ; 1st communication buffer
+G_BUF2_SEL      =      0A0H             ; 2nd communication buffer
+G_PAGEDIR_SEL   =      0A8H             ; The page directory (memory segment)
+G_SWAP_BMP_SEL  =      0B0H             ; The swapper file bitmap
+G_LIN_MAP_SEL   =      0B8H             ; Linear address map
+G_PAGE_BMP_SEL  =      0C0H             ; Free page bitmap
+G_TSS_EX8_SEL   =      0C8H             ; TSS for exception 8 (double fault)
+G_TSS_EX10_SEL  =      0D0H             ; TSS for exception 10 (invalid TSS)
+G_EX8_STACK_SEL =      0D8H             ; Stack for exception 8 task
+G_EX10_STACK_SEL =     0E0H             ; Stack for exception 10 task
+G_TSS_MEM_SEL   =      0E8H             ; The TSS as memory segment
+G_LOWMEM_SEL    =      0F0H             ; The lower 1MB (+64KB)
+G_LDT_SEL       =      0F8H             ; LDT (MAX_PROCESSES entries)
+
+;
+; LDT selectors
+;
+L_NULL_SEL      =       07H             ; NULL
+L_CODE_SEL      =       0FH             ; User code segment
+L_DATA_SEL      =       17H             ; User data segment
+L_VIDEO_SEL     =       1FH             ; Video memory
+L_SYM_SEL       =       27H             ; Symbols
+L_CLIENT_SEL    =       2FH             ; Client process' data (for FPU emu)
+
+;
+; Swapper info table entry
+;
+SRC_MASK        =      300H             ; ...in swapper info table entry
+
+SRC_NONE        =      000H             ; No source (inaccessible, stack)
+SRC_ZERO        =      100H             ; Zero
+SRC_EXEC        =      200H             ; Executable file
+SRC_SWAP        =      300H             ; Swapper file
+
+SWAP_ALLOC      =      400H             ; Swap space allocated
+
+;
+; Flags
+;
+FLAG_C          =        0001H          ; Carry flag
+FLAG_TF         =        0100H          ; Trap flag
+FLAG_IF         =        0200H          ; Interrupt enable
+
+;
+; Control characters
+;
+TAB             =       09H             ; Tab
+LF              =       0AH             ; Linefeed
+CR              =       0DH             ; Carriage return
+
+;
+; Other constants
+;
+NO_FILE_HANDLE  =       0FFFFH          ; Invalid file handle (file not open)
+
+;
+; Machines
+;
+MACH_PC         =       0               ; COMPAQ or IBM or 100% compatible
+MACH_FMR70      =       1               ; Fujitsu FMR70
+MACH_PC98       =       2               ; NEC PC-98
+MACH_INBOARD    =       3               ; Inboard 386/PC
+MACH_MAX        =       3               ; (Last machine code)
+
+FMR70_MEM_MAX   =       6144            ; 6 MB
+
+;
+; Values of FP_FLAG
+;
+FP_NO           =       0               ; No coprocessor
+FP_287          =       2               ; 287
+FP_387          =       3               ; 387
+
+
+                .386
+                .387
+
+;
+; More flags (386)
+;
+FLAG_RF         =       10000H          ; Resume flag
+FLAG_VM         =       20000H          ; Virtual mode flag
+
+;
+; Control register 0
+;
+CR0_PE          =       00000001H       ; Protected mode
+CR0_MP          =       00000002H       ; Math present
+CR0_EM          =       00000004H       ; Emulate
+CR0_TS          =       00000008H       ; Task switched
+CR0_ET          =       00000010H       ; Extension type
+CR0_PG          =       80000000H       ; Paging
+
+;
+; All FPU bits but CR0_ET
+;
+CR0_FPU         =       CR0_TS OR CR0_EM OR CR0_MP
+
+;
+; The biggest unsigned 32 bit number
+;
+MAX_32          =       0FFFFFFFFH
+
+;
+; Structures
+;
+DESCRIPTOR      STRUCT
+LIMIT_0_15      DW      ?
+BASE_0_15       DW      ?
+BASE_16_23      DB      ?
+DACCESS         DB      ?
+GRAN            DB      ?
+BASE_24_31      DB      ?
+DESCRIPTOR      ENDS
+
+;
+; Segments
+;
+                .SEQ                    ; Sequential ordering
+
+HDR_SEG         SEGMENT PARA USE16 PUBLIC 'HEADER'
+HDR_SEG         ENDS
+
+
+INIT_CODE       SEGMENT PARA USE16 PUBLIC 'CODE'
+INIT_CODE       ENDS
+
+
+SV_DATA         SEGMENT PARA USE16 PUBLIC 'DATA'
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT PARA USE16 PUBLIC 'PROTCODE'
+SV_CODE         ENDS
+
+SV_STACK        SEGMENT PARA USE16 PUBLIC 'PROTSTACK'
+SV_STACK        ENDS
+
+
+RM_STACK        SEGMENT PARA USE16 STACK 'STACK'
+RM_STACK        ENDS
+
+LSTACK          SEGMENT PARA USE16 PUBLIC 'LSTACK'
+LSTACK          ENDS
+
+
+EX8_STACK       SEGMENT PARA USE16 PUBLIC 'EX8STACK'
+EX8_STACK       ENDS
+
+
+EX10_STACK      SEGMENT PARA USE16 PUBLIC 'EX10STACK'
+EX10_STACK      ENDS
+
+;
+; ES := DS
+;
+MOV_ES_DS       MACRO
+                PUSH    DS
+                POP     ES
+                ENDM
+
+; DS := ES
+MOV_DS_ES       MACRO
+                PUSH    ES
+                POP     DS
+                ENDM
+
+;
+; FS := DS
+;
+MOV_FS_DS       MACRO
+                PUSH    DS
+                POP     FS
+                ENDM
+
+;
+; Exchange DS and ES
+;
+XCHG_DS_ES      MACRO
+                PUSH    DS
+                PUSH    ES
+                POP     DS
+                POP     ES
+                ENDM
+
+;
+; JMP and CALL instructions with <selector>:<offset16> instead of
+; <segment>:<offset16>
+;
+JMPF16          MACRO   SEL, OFF
+                DB      0EAH                    ; JMP FAR
+                DW      OFF, SEL
+                ENDM
+
+
+CALLF16         MACRO   SEL, OFF
+                DB      9AH                     ; CALL FAR
+                DW      OFF, SEL
+                ENDM
+
+;
+; Acoustic output for debugging
+;
+BEEP            MACRO
+                LOCAL   L1, L2
+                IN      AL, 61H
+                MOV     AH, AL
+                OR      AL, 3
+                JMP     SHORT L1
+L1:             JMP     SHORT L2
+L2:             OUT     61H, AL
+                MOV     CX, 0
+                LOOP    $
+                LOOP    $
+                MOV     AL, AH
+                OUT     61H, AL
+                ENDM
+
+
+
+;
+; Serial output for debugging
+;
+; Modifies AL, DX and flags
+;
+
+;SER_PORT       =       03F8H                   ; COM1
+SER_PORT        =       02F8H                   ; COM2
+
+SERIAL          MACRO   C1
+                LOCAL   L1
+                MOV     DX, SER_PORT+4
+                MOV     AL, 3
+                OUT     DX, AL
+                INC     DX
+L1:             IN      AL, DX                  ; Read line status
+                TEST    AL, 20H                 ; Transmitter empty?
+                JZ      SHORT L1                ; No  -> repeat
+                MOV     DX, SER_PORT            ; Transmitter register
+                MOV     AL, C1                  ; Write character
+                OUT     DX, AL                  ; to transmitter register
+                ENDM
+
+
+DALIGN          MACRO   VAL:REQ
+                ALIGN   VAL
+                ENDM
+
+TALIGN          MACRO   VAL:REQ
+                ALIGN   VAL
+                ENDM
Index: trunk/src/emx/src/dos/emxl.asm
===================================================================
--- trunk/src/emx/src/dos/emxl.asm	(revision 18)
+++ trunk/src/emx/src/dos/emxl.asm	(revision 18)
@@ -0,0 +1,550 @@
+;
+; EMXL.ASM -- emx loader (emxl.exe)
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; <START_OF_EXCEPTION>
+; As a special exception, if you bind emxl.exe to an executable file
+; (using emxbind), this does not cause the resulting executable file
+; to be covered by the GNU General Public License.  This exception
+; does not however invalidate any other reasons why the executable
+; file might be covered by the GNU General Public License.  However,
+; if you bind a modified copy of emxl.exe to an executable file, you
+; have to include source code for emxl.exe.  When distributing
+; emxl.exe as separate file, the GPL applies without exceptions to
+; emxl.exe.
+;
+; If you modify this file, you have to replace the text between
+; the outer <START_OF_EXCEPTION> and <END_OF_EXCEPTION> markers with
+; the following paragraph (which currently does not apply as you have
+; not modified this file):
+;
+; As a special exception, if you bind emxl.exe to an executable file
+; (using emxbind), this does not cause the resulting executable file
+; to be covered by the GNU General Public License.  The source code
+; for emxl.exe must be distributed with the executable file.  This
+; exception does not however invalidate any other reasons why the
+; executable file might be covered by the GNU General Public License.
+; <END_OF_EXCEPTION>
+;
+
+                INCLUDE EMX.INC
+                INCLUDE HEADERS.INC
+                INCLUDE VERSION.INC
+
+                .8086
+
+;
+; Data (the name SV_DATA stems from emx, we're using EMX.INC!)
+;
+SV_DATA         SEGMENT
+
+PSP_SEG         WORD    ?                       ; Program prefix segment
+ENV_SEG         WORD    ?                       ; Environment segment
+NAME_OFF        WORD    ?                       ; Offset of prog name (ENV_SEG)
+NAME_LEN        WORD    ?                       ; Length of prog name
+
+;
+; Parameter block for INT 21H, AX=4B00H
+;
+PAR_BLOCK       WORD    0                       ; Copy parent's environment
+                WORD    OFFSET CMD_LINE         ; Command line
+                WORD    SEG CMD_LINE
+                WORD    5CH                     ; FCB1
+PB_SEG1         WORD    ?
+                WORD    6CH                     ; FCB2
+PB_SEG2         WORD    ?
+
+;
+; DPMI_FLAG is non-zero if a DPMI server has been found, but no
+; VCPI server
+;
+DPMI_FLAG       BYTE    FALSE                   ; Initially FALSE
+
+;
+; Messages
+;
+$EMX_NOT_FOUND  BYTE    "emx not found", CR, LF, "$"
+$RSX_NOT_FOUND  BYTE    "rsx not found, DPMI not supported by emx", CR, LF, "$"
+$USE_EMXBIND    BYTE    "Use emxbind", CR, LF, "$"
+$BAD_ENV        BYTE    "Bad environment", CR, LF, "$"
+
+;
+; Names of devices implemented by expanded memory managers
+;
+EMS_FNAME       BYTE    "EMMXXXX0", 0           ; EMS enabled
+NOEMS_FNAME1    BYTE    "EMMQXXX0", 0           ; EMS disabled
+NOEMS_FNAME2    BYTE    "$MMXXXX0",0            ; EMS disabled
+
+;
+; Names of environment variables
+;
+$EMX            BYTE    "EMX", 0
+$PATH           BYTE    "PATH", 0
+
+;
+; Name of emx.exe for searching in the current working directory and PATH
+;
+$EMX_EXE        BYTE    "emx.exe", 0
+EMX_EXE_LEN     =       THIS BYTE - $EMX_EXE    ; Length of name, with 0
+
+;
+; This command line is passed to emx.exe
+;
+CMD_LINE        BYTE    7                       ; 7 bytes
+                BYTE    "-/"                    ; Special marker
+CMD_LINE_PSP    BYTE    "0000"                  ; PSP_SEG, hexadecimal
+                BYTE    "/"                     ; Another special marker
+                BYTE    CR                      ; End of command line
+
+;
+; Build path name here when using directory from PATH environment variable
+;
+PGM_NAME        BYTE    128 DUP (?)
+PGM_NAME_END    LABEL   BYTE
+
+SV_DATA         ENDS
+
+
+;
+; This area will be patched by emxbind
+;
+HDR_SEG         SEGMENT
+PATCH           LABEL   BIND_HEADER
+                BYTE    "emx ", VERSION, 0
+                BYTE    (SIZE BIND_HEADER - HDR_VERSION_LEN) DUP (0)
+HDR_SEG         ENDS
+
+;
+; Code
+;
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE
+                ASSUME  DS:NOTHING, ES:NOTHING
+
+;
+; Setup data segment.  Note: This macro modifies AX.
+;
+SET_DS          MACRO
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                ENDM
+
+;
+; The program starts here
+;
+ENTRY:          SET_DS                          ; Setup data segment
+                MOV     PSP_SEG, ES             ; Save program prefix segment
+                CALL    INIT                    ; Initialize
+                CALL    CHECK_DPMI              ; Check for DPMI
+                CALL    GET_NAME                ; Get program name
+                CALL    BIND_HDR                ; Check patch area
+                CALL    TRY_EMX_ENV             ; Use EMX environment variable
+                CALL    TRY_CWD                 ; Search current directory
+                CALL    TRY_PATH                ; Use PATH environment variable
+                LEA     DX, $EMX_NOT_FOUND      ; Give up
+                CMP     DPMI_FLAG, FALSE
+                JE      FAIL
+                LEA     DX, $RSX_NOT_FOUND
+FAIL:           JMP     ABORT
+
+;
+; Initialization
+;
+INIT            PROC    NEAR
+                MOV     AX, PSP_SEG
+                MOV     PB_SEG1, AX             ; Fill in parameter block
+                MOV     PB_SEG2, AX             ; for DOS function 4BH (EXEC)
+                MOV     ES, AX
+                MOV     AX, ES:[2CH]            ; Get environment segment
+                MOV     ENV_SEG, AX
+                LEA     BX, CMD_LINE_PSP        ; Insert PSP_SEG, hexadecimal
+                MOV     CX, 0404H               ; 4 digits, shift by 4 bits
+                MOV     DX, PSP_SEG
+INIT_1:         ROL     DX, CL
+                MOV     AL, DL
+                AND     AL, 0FH
+                ADD     AL, "0"
+                CMP     AL, "9"
+                JBE     INIT_2
+                ADD     AL, "A" - ("0" + 10)
+INIT_2:         MOV     [BX], AL
+                INC     BX
+                DEC     CH
+                JNZ     INIT_1
+                RET
+INIT            ENDP
+
+
+;
+; Check for DPMI server
+;
+CHECK_DPMI      PROC    NEAR
+                MOV     AX, 1687H               ; Check for DPMI server
+                INT     2FH
+                OR      AX, AX                  ; Server present?
+                JNZ     DPMI_RET                ; No  -> call emx.exe
+                TEST    BX, 1                   ; 32-bit programs supported?
+                JZ      DPMI_RET                ; No  -> hope we can get VCPI
+;
+; Now we have detected a DPMI server.  Run rsx if we don't find a
+; VCPI server.  First we have to check for an EMM.
+;
+; First, check the EMS interrupt vector
+;
+                MOV     AX, 3567H               ; Get interrupt vector 67H
+                INT     21H
+                MOV     AX, ES
+                OR      AX, BX                  ; Is the vector 0:0 ?
+                JZ      NO_VCPI                 ; Yes -> no VCPI
+;
+; Check for an EMM with EMS enabled
+;
+                LEA     DX, EMS_FNAME
+                CALL    CHECK_EMM               ; EMS present?
+                JC      EMM_DISABLED            ; No  -> try disabled EMS
+;
+; Check EMM status
+;
+                MOV     AH, 40H                 ; Get EMM status
+                INT     67H
+                CMP     AH, 0                   ; Successful?
+                JE      EMM_OK                  ; Yes -> check VCPI
+                JMP     NO_VCPI                 ; No VCPI
+
+;
+; Check for an EMM with EMS disabled (using undocumented "features")
+;
+EMM_DISABLED:   LEA     DX, NOEMS_FNAME1
+                CALL    CHECK_EMM
+                JNC     EMM_OK                  ; EMM present
+                LEA     DX, NOEMS_FNAME2
+                CALL    CHECK_EMM
+                JC      NO_VCPI                 ; No EMM present -> no VCPI
+;
+; There is an EMM with EMS enabled or disabled.  Check for VCPI
+;
+EMM_OK:         MOV     AX, 0DE00H              ; VCPI presence detection
+                INT     67H
+                CMP     AH, 0                   ; VCPI present?
+                JE      DPMI_RET                ; Yes -> use emx
+;
+; Now we have found a DPMI server, but no VCPI server.  We
+; should use rsx instead of emx
+;
+NO_VCPI:        MOV     DPMI_FLAG, NOT FALSE    ; Set flag
+                MOV     AX, "SR"                ; First 2 letters of "RSX"
+                MOV     WORD PTR $EMX, AX       ; Patch name of env. variable
+                MOV     AX, "sr"                ; First 2 letters of "rsx.exe"
+                MOV     WORD PTR $EMX_EXE, AX   ; Patch name of executable
+DPMI_RET:       RET
+CHECK_DPMI      ENDP
+
+
+;
+; Check for the presence of an expanded memory manager (emx.exe
+; will perform more complete checks)
+;
+; In:   DX      Pointer to device name
+;
+; Out:  NC      EMM present
+;
+CHECK_EMM       PROC    NEAR
+                MOV     AX, 3D00H               ; Open
+                INT     21H
+                JC      CE_RET
+;
+; A file or device with that name exists.  Check for a device
+;
+                MOV     BX, AX                  ; Handle
+                MOV     AX, 4400H               ; IOCTL: get device data
+                INT     21H
+                JC      CE_FAIL                 ; Failure -> no EMM
+                TEST    DL, 80H                 ; Device?
+                JZ      CE_FAIL                 ; No -> no EMM
+                MOV     AX, 4407H               ; IOCTL: check output status
+                INT     21H
+                JC      CE_FAIL                 ; Failure -> no EMM
+                CMP     AL, 0FFH                ; Ready?
+                JNE     CE_FAIL                 ; No  -> no EMM
+                MOV     AH, 3EH                 ; Close
+                INT     21H
+                CLC
+CE_RET:         RET
+
+CE_FAIL:        MOV     AH, 3EH                 ; Close
+                INT     21H
+                STC
+                RET
+CHECK_EMM       ENDP
+
+
+;
+; Find program name
+;
+GET_NAME        PROC    NEAR
+                MOV     ES, ENV_SEG             ; Scan environment
+                XOR     DI, DI                  ; starting at offset 0
+                MOV     CX, 8000H               ; Maximum environment size
+                XOR     AL, AL                  ; Search for bytes of zeros
+                CLD                             ; Incrementing
+GET_NAME_1:     REPNE   SCAS BYTE PTR ES:[DI]   ; Skip string
+                JNE     GET_NAME_ERR            ; Count exhausted -> error
+                SCAS    BYTE PTR ES:[DI]        ; End of environment?
+                JE      GET_NAME_9              ; Yes -> program name found
+                LOOP    GET_NAME_1              ; Next string, 1st char skipped
+GET_NAME_ERR:   LEA     DX, $BAD_ENV            ; Bad environment
+                JMP     ABORT
+
+GET_NAME_9:     ADD     DI, 2                   ; Skip count
+                MOV     NAME_OFF, DI            ; Offset of program name
+                CALL    STRLEN                  ; Compute length
+                MOV     NAME_LEN, CX
+                RET
+GET_NAME        ENDP
+
+
+;
+; Check emxbind patch area
+;
+BIND_HDR        PROC    NEAR
+                MOV     AX, HDR_SEG
+                MOV     ES, AX                  ; Access emxbind patch area
+                ASSUME  ES:HDR_SEG
+                CMP     PATCH.BND_BIND_FLAG, FALSE ; Bound?
+                JNE     BIND_HDR_1              ; Yes -> continue
+                LEA     DX, $USE_EMXBIND        ; Must be bound to a.out
+                JMP     ABORT
+BIND_HDR_1:     RET
+BIND_HDR        ENDP
+
+                ASSUME  ES:NOTHING
+
+;
+; Display error message and abort program
+;
+; In:   DX      Offset of dollar-delimited error message in SV_DATA
+;
+ABORT:          SET_DS                          ; This can't hurt
+                MOV     AH, 09H                 ; Display string
+                INT     21H
+                MOV     AX, 4C01H               ; Terminate process, rc=1
+                INT     21H
+
+;
+; Try to find emx.exe using EMX environment variable
+;
+TRY_EMX_ENV     PROC    NEAR
+                LEA     BX, $EMX
+                CALL    GETENV
+                JC      TRY_EMX_ENV_RET
+                MOV     DX, DI
+                MOV_DS_ES
+                ASSUME  DS:NOTHING
+                CALL    SPAWN
+                ASSUME  DS:SV_DATA
+TRY_EMX_ENV_RET:RET
+TRY_EMX_ENV     ENDP
+
+;
+; Try to find emx.exe in current working directory
+;
+TRY_CWD         PROC    NEAR
+                LEA     DX, $EMX_EXE
+                CALL    SPAWN
+                RET
+TRY_CWD         ENDP
+
+;
+; Try to find emx.exe in the directories listed in the PATH environment
+; variable
+;
+TRY_PATH        PROC    NEAR
+                LEA     BX, $PATH
+                CALL    GETENV
+                JC      TRY_PATH_RET
+                MOV     SI, DI
+FIND_2:         LEA     DI, PGM_NAME
+FIND_3:         MOV     AL, ES:[SI]
+                INC     SI
+                OR      AL, AL
+                JZ      TRY_PATH_RET
+                CMP     AL, " "
+                JE      FIND_3
+                CMP     AL, TAB
+                JE      FIND_3
+                CMP     AL, ";"
+                JE      FIND_3
+FIND_4:         CMP     DI, OFFSET PGM_NAME_END
+                JAE     FIND_5
+                MOV     [DI], AL
+                MOV     AH, AL
+                INC     DI
+FIND_5:         MOV     AL, ES:[SI]
+                INC     SI
+                OR      AL, AL
+                JZ      FIND_6
+                CMP     AL, " "
+                JE      FIND_5
+                CMP     AL, TAB
+                JE      FIND_5
+                CMP     AL, ";"
+                JNE     FIND_4
+FIND_6:         DEC     SI
+                CMP     DI, OFFSET PGM_NAME_END - EMX_EXE_LEN
+                JAE     FIND_2
+;
+; We don't support DBCS in emxl.exe: PATH should not contain directories
+; whose name ends with a DBCS characters whose 2nd byte is 2F, 3AH, or 5CH.
+;
+                CMP     AH, "\"
+                JE      FIND_7
+                CMP     AH, "/"
+                JE      FIND_7
+                CMP     AH, ":"
+                JE      FIND_7
+                CMP     DI, OFFSET PGM_NAME_END
+                JAE     FIND_7
+                MOV     BYTE PTR DS:[DI], "\"
+                INC     DI
+FIND_7:         PUSH    ES
+                PUSH    SI
+                LEA     SI, $EMX_EXE
+                MOV     CX, EMX_EXE_LEN
+FIND_8:         LODSB
+                MOV     [DI], AL
+                INC     DI
+                LOOP    FIND_8
+                LEA     DX, PGM_NAME
+                CALL    SPAWN
+                POP     SI
+                POP     ES
+                JMP     FIND_2
+
+TRY_PATH_RET:   RET
+
+TRY_PATH        ENDP
+
+
+
+;
+; Find environment entry
+;
+; In:   BX      Points to zero-terminated name of environment variable
+;
+; Out:  CY      Not found
+;       NC      Found
+;       DI      Points to value of environment variable
+;
+
+                ASSUME  DS:SV_DATA
+
+GETENV          PROC    NEAR
+                MOV     ES, ENV_SEG
+                XOR     DI, DI
+                CLD
+GETENV_NEXT:    CMP     BYTE PTR ES:[DI], 0     ; Empty environment?
+                JE      GETENV_FAILURE          ; Yes -> not found
+                PUSH    BX                      ; Save pointer to name
+GETENV_COMPARE: MOV     AL, [BX]
+                CMP     AL, ES:[DI]             ; Compare names
+                JNE     GETENV_DIFF             ; Mismatch -> try next one
+                OR      AL, AL                  ; Shouldn't happen (`='!)
+                JZ      GETENV_DIFF             ; (name matches completely)
+                INC     BX
+                INC     DI
+                JMP     GETENV_COMPARE          ; Compare next character
+GETENV_DIFF:    POP     BX                      ; Restore pointer to name
+                OR      AL, AL                  ; End of name reached?
+                JE      GETENV_EQUAL            ; Yes -> candidate found
+GETENV_SKIP:    XOR     AL, AL
+                MOV     CX, 32767               ; Search for next entry
+                REPNE   SCAS BYTE PTR ES:[DI]
+                JMP     GETENV_NEXT             ; Check that entry
+
+GETENV_EQUAL:   CMP     BYTE PTR ES:[DI], "="   ; Exact match?
+                JNE     GETENV_SKIP             ; No  -> go to next entry
+                INC     DI                      ; Skip `='
+                CLC
+                JMP     GETENV_RET              ; Return pointer to value
+
+GETENV_FAILURE: STC                             ; Not found
+GETENV_RET:     RET
+
+GETENV          ENDP
+
+;
+; Compute the length of a zero-terminated string
+;
+; In:   ES:SI   Points to string
+;
+; Out:  CX      Length
+;
+STRLEN          PROC    NEAR
+                XOR     CX, CX
+                XOR     AL, AL
+STRLEN_1:       SCASB
+                JE      STRLEN_2
+                INC     CX
+                JMP     STRLEN_1
+STRLEN_2:       RET
+STRLEN          ENDP
+
+;
+; Try to run a program. Exit if successful, return if failed.
+;
+; In:   DS:DX   Points to path name of program
+;
+; Out:  DS      SV_DATA
+;
+
+                ASSUME  DS:NOTHING
+
+SPAWN           PROC    NEAR
+                MOV     AX, SV_DATA
+                MOV     ES, AX
+                ASSUME  ES:SV_DATA
+                LEA     BX, PAR_BLOCK           ; ES:BX -> parameter block
+                MOV     AX, 4B00H               ; Load and execute program
+                INT     21H
+                SET_DS                          ; Restore data segment
+                JNC     DONE                    ; Success -> terminate
+                RET
+
+DONE:           MOV     AH, 4DH                 ; Get return code of child
+                INT     21H                     ; process
+                MOV     AH, 4CH                 ; terminate process
+                INT     21H
+
+SPAWN           ENDP
+
+                ASSUME  ES:NOTHING
+
+
+INIT_CODE       ENDS
+
+
+RM_STACK        SEGMENT
+                WORD    256 DUP (?)
+RM_STACK        ENDS
+
+                END     ENTRY
Index: trunk/src/emx/src/dos/errors.asm
===================================================================
--- trunk/src/emx/src/dos/errors.asm	(revision 18)
+++ trunk/src/emx/src/dos/errors.asm	(revision 18)
@@ -0,0 +1,211 @@
+;
+; ERRORS.ASM -- Translate error codes
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__ERRORS        =       1
+                INCLUDE EMX.INC
+                INCLUDE ERRORS.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE PMINT.INC
+
+                PUBLIC  DOS_ERROR_TO_ERRNO, XLATE_ERRNO
+
+SV_DATA         SEGMENT
+
+ERRNO_TAB       LABEL   BYTE
+                DB      EINVAL, EINVAL, ENOENT, ENOENT, EMFILE  ; 0..4
+                DB      EACCES, EBADF,  EIO,    ENOMEM, EIO     ; 5..9
+                DB      EINVAL, ENOEXEC,EINVAL, EINVAL, EINVAL  ; 10..14
+                DB      EACCES, EBUSY,  EXDEV,  ENOENT, EIO     ; 15..19
+                DB      EIO,    EIO,    EIO,    EIO,    EIO     ; 20..24
+                DB      EIO,    EIO,    EIO,    ENOSPC, EIO     ; 25..29
+                DB      EIO,    EIO,    EACCES, EACCES, EIO     ; 30..34
+                DB      EIO,    EIO,    EIO,    EIO,    ENOSPC  ; 35..39
+                DB      EIO,    EIO,    EIO,    EIO,    EIO     ; 40..44
+                DB      EIO,    EIO,    EIO,    EIO,    EIO     ; 45..49
+                DB      EIO,    EIO,    EIO,    EIO,    EBUSY   ; 50..54
+                DB      EIO,    EIO,    EIO,    EIO,    EIO     ; 55..59
+                DB      EIO,    ENOSPC, ENOSPC, EIO,    EIO     ; 60..64
+                DB      EACCES, EIO,    EIO,    EIO,    EIO     ; 65..69
+                DB      EIO,    EIO,    EIO,    EACCES, EIO     ; 70..74
+                DB      EIO,    EIO,    EIO,    EIO,    EIO     ; 75..79
+                DB      EEXIST, EIO,    ENOENT, EIO,    EIO     ; 80..84
+                DB      EIO,    EIO,    EINVAL, EIO             ; 85..88
+ERRNO_TAB_LEN   =       THIS BYTE - ERRNO_TAB
+                .ERRE   ERRNO_TAB_LEN-1 EQ 88
+
+; This table translates errno values for `interface 0'.  Changed
+; entries are marked (*).
+
+ERRNO_INTERFACE_0 LABEL   BYTE
+                DB      0               ; 0:  0
+                DB      EACCES          ; 1:  EPERM (*)
+                DB      ENOENT          ; 2:  ENOENT
+                DB      ESRCH           ; 3:  ESRCH
+                DB      EINTR           ; 4:  EINTR
+                DB      EIO             ; 5:  EIO
+                DB      EINVAL          ; 6:  ENXIO (*)
+                DB      E2BIG           ; 7:  E2BIG
+                DB      ENOEXEC         ; 8:  ENOEXEC
+                DB      EBADF           ; 9:  EBADF
+                DB      ECHILD          ; 10: ECHILD
+                DB      EAGAIN          ; 11: EAGAIN
+                DB      ENOMEM          ; 12: ENOMEM
+                DB      EACCES          ; 13: EACCES
+                DB      EINVAL          ; 14: EFAULT (*)
+                DB      EINVAL          ; 15: ENOLCK (*)
+                DB      EACCES          ; 16: EBUSY (*)
+                DB      EEXIST          ; 17: EEXIST
+                DB      EXDEV           ; 18: EXDEV
+                DB      EINVAL          ; 19: ENODEV (*)
+                DB      EACCES          ; 20: ENOTDIR (*)
+                DB      EACCES          ; 21: EISDIR (*)
+                DB      EINVAL          ; 22: EINVAL
+                DB      EMFILE          ; 23: ENFILE (*)
+                DB      EMFILE          ; 24: EMFILE
+                DB      EINVAL          ; 25: ENOTTY (*)
+                DB      EINVAL          ; 26: EDEADLK (*)
+                DB      EINVAL          ; 27: EFBIG (*)
+                DB      ENOSPC          ; 28: ENOSPC
+                DB      EINVAL          ; 29: ESPIPE (*)
+                DB      EACCES          ; 30: EROFS (*)
+                DB      EINVAL          ; 31: EMLINK (*)
+                DB      EPIPE           ; 32: EPIPE
+                DB      EINVAL          ; 33: EDOM (*)
+                DB      ERANGE          ; 34: ERANGE
+                DB      EACCES          ; 35: ENOTEMPTY (*)
+                DB      EINVAL          ; 36: EINPROGRESS (*)
+                DB      ENOSYS          ; 37: ENOSYS
+                DB      EINVAL          ; 38: ENAMETOOLONG (*)
+
+; This table translates errno values for `interface 1' (up to and
+; including 0.8h).  Changed entries are marked (*).
+
+ERRNO_INTERFACE_1 LABEL   BYTE
+                DB      0               ; 0:  0
+                DB      EPERM           ; 1:  EPERM
+                DB      ENOENT          ; 2:  ENOENT
+                DB      ESRCH           ; 3:  ESRCH
+                DB      EINTR           ; 4:  EINTR
+                DB      EIO             ; 5:  EIO
+                DB      EINVAL          ; 6:  ENXIO (*)
+                DB      E2BIG           ; 7:  E2BIG
+                DB      ENOEXEC         ; 8:  ENOEXEC
+                DB      EBADF           ; 9:  EBADF
+                DB      ECHILD          ; 10: ECHILD
+                DB      EAGAIN          ; 11: EAGAIN
+                DB      ENOMEM          ; 12: ENOMEM
+                DB      EACCES          ; 13: EACCES
+                DB      EINVAL          ; 14: EFAULT (*)
+                DB      EINVAL          ; 15: ENOLCK (*)
+                DB      EACCES          ; 16: EBUSY (*)
+                DB      EEXIST          ; 17: EEXIST
+                DB      EXDEV           ; 18: EXDEV
+                DB      EINVAL          ; 19: ENODEV (*)
+                DB      ENOTDIR         ; 20: ENOTDIR
+                DB      EISDIR          ; 21: EISDIR
+                DB      EINVAL          ; 22: EINVAL
+                DB      EMFILE          ; 23: ENFILE (*)
+                DB      EMFILE          ; 24: EMFILE
+                DB      EINVAL          ; 25: ENOTTY (*)
+                DB      EINVAL          ; 26: EDEADLK (*)
+                DB      EINVAL          ; 27: EFBIG (*)
+                DB      ENOSPC          ; 28: ENOSPC
+                DB      ESPIPE          ; 29: ESPIPE
+                DB      EROFS           ; 30: EROFS
+                DB      EINVAL          ; 31: EMLINK (*)
+                DB      EPIPE           ; 32: EPIPE
+                DB      EDOM            ; 33: EDOM
+                DB      ERANGE          ; 34: ERANGE
+                DB      EACCES          ; 35: ENOTEMPTY (*)
+                DB      EINVAL          ; 36: EINPROGRESS (*)
+                DB      ENOSYS          ; 37: ENOSYS
+                DB      ENAMETOOLONG    ; 38: ENAMETOOLONG
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Translate DOS error code to errno number
+;
+; In:   AX      DOS error code
+;
+; Out:  EAX     errno value
+;       BX      modified
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+DOS_ERROR_TO_ERRNO PROC NEAR
+                CMP     AX, ERRNO_TAB_LEN       ; My table ends here
+                JAE     SHORT ERRNO_1
+                LEA     BX, ERRNO_TAB
+                ADD     BX, AX
+                MOVZX   EAX, BYTE PTR [BX]
+                CALL    XLATE_ERRNO
+                RET
+
+ERRNO_1:        MOV     EAX, EINVAL             ; Invalid argument
+                RET
+DOS_ERROR_TO_ERRNO ENDP
+
+;
+; Translate an errno value according to the interface.  This function
+; should be called when returning an errno value marked (*) in the
+; ERRNO_INTERFACE_0 table.
+;
+; In:   AX      errno value
+;       PROCESS_PTR
+;
+; Out:  EAX     errno value
+;       BX      modified
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+XLATE_ERRNO     PROC    NEAR
+                MOV     BX, PROCESS_PTR
+                CMP     BX, NO_PROCESS
+                JE      SHORT FIN
+                ASSUME  BX:PTR PROCESS
+                CMP     [BX].P_INTERFACE, 0
+                JE      SHORT XE_0
+                CMP     [BX].P_INTERFACE, 1
+                ASSUME  BX:NOTHING
+                JNE     SHORT FIN
+XE_1:           LEA     BX, ERRNO_INTERFACE_1
+                JMP     SHORT XE_TRANS
+XE_0:           LEA     BX, ERRNO_INTERFACE_0
+XE_TRANS:       ADD     BX, AX
+                MOVZX   EAX, BYTE PTR [BX]
+FIN:            RET
+XLATE_ERRNO     ENDP
+
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/errors.inc
===================================================================
--- trunk/src/emx/src/dos/errors.inc	(revision 18)
+++ trunk/src/emx/src/dos/errors.inc	(revision 18)
@@ -0,0 +1,78 @@
+;
+; ERRORS.INC -- Translate error codes
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; errno values
+;
+EPERM           =       1               ; Operation not permitted
+ENOENT          =       2               ; No such file or directory
+ESRCH           =       3               ; No such process
+EINTR           =       4               ; Interrupted system call
+EIO             =       5               ; I/O error
+ENXIO           =       6               ; No such device or address
+E2BIG           =       7               ; Arguments or environment too big
+ENOEXEC         =       8               ; Invalid executable format
+EBADF           =       9               ; Bad file number
+ECHILD          =       10              ; No child processes
+EAGAIN          =       11              ; No more processes
+ENOMEM          =       12              ; Not enough memory
+EACCES          =       13              ; Permission denied
+EFAULT          =       14              ; Bad address
+ENOLCK          =       15              ; No locks available
+EBUSY           =       16              ; Resource busy
+EEXIST          =       17              ; File exists
+EXDEV           =       18              ; Cross-device link
+ENODEV          =       19              ; No such device
+ENOTDIR         =       20              ; Not a directory
+EISDIR          =       21              ; Is a directory
+EINVAL          =       22              ; Invalid argument
+ENFILE          =       23              ; Too many open files in system
+EMFILE          =       24              ; Too many open files
+ENOTTY          =       25              ; Inappropriate ioctl
+EDEADLK         =       26              ; Resource deadlock avoided
+EFBIG           =       27              ; File too large
+ENOSPC          =       28              ; Disk full
+ESPIPE          =       29              ; Invalid seek
+EROFS           =       30              ; Read-only file system
+EMLINK          =       31              ; Too many links
+EPIPE           =       32              ; Broken pipe
+EDOM            =       33              ; Domain error
+ERANGE          =       34              ; Result too large
+ENOTEMPTY       =       35              ; Directory not empty
+; EINPROGRESS   =       36              ;
+ENOSYS          =       37              ; Function not implemented
+ENAMETOOLONG    =       38              ; File name too long
+
+
+              IFNDEF __ERRORS
+
+SV_CODE         SEGMENT
+
+                EXTRN   DOS_ERROR_TO_ERRNO:NEAR ; Translate error code to errno
+                EXTRN   XLATE_ERRNO:NEAR        ; Translate errno value
+
+SV_CODE         ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/except.asm
===================================================================
--- trunk/src/emx/src/dos/except.asm	(revision 18)
+++ trunk/src/emx/src/dos/except.asm	(revision 18)
@@ -0,0 +1,838 @@
+;
+; EXCEPT.ASM -- Handle excetions
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE SWAPPER.INC
+                INCLUDE DEBUG.INC
+                INCLUDE VPRINT.INC
+                INCLUDE OPRINT.INC
+                INCLUDE PMIO.INC
+                INCLUDE PMINT.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE CORE.INC
+                INCLUDE TABLES.INC
+                INCLUDE MISC.INC
+
+                PUBLIC  EXC_TAB, STDOUT_DUMP
+                PUBLIC  EXCEPT_FAKE, EXCEPT_RET, EXCEPT_TASK, EXCEPT_NAME
+
+
+SER_FLAG        =       FALSE                   ; Don't use serial interface
+DEBUG_PTRACE    =       FALSE
+
+SV_DATA         SEGMENT
+
+EXCEPT2         EQU     NMI
+
+EXC_TAB         LABEL   WORD
+                IRP     X,<0,1,2,3,4,5,6,7,9,11,12,13,14,15,16,17>
+                DW      X, EXCEPT&X
+                ENDM
+                DW      0FFFFH, 0FFFFH
+
+$EXCEPTION      DB      "Exception ",0
+$ERRCODE        DB      "ERRCODE=",0
+$CS             DB      "CS=", 0
+$EIP            DB      "  EIP=", 0
+$SS             DB      "SS=", 0
+$ESP            DB      "  ESP=", 0
+$EFLAGS         DB      "EFLAGS=", 0
+$CR2            DB      "CR2=", 0
+
+$DS             DB      "DS=", 0
+$ES             DB      "ES=", 0
+$FS             DB      "FS=", 0
+$GS             DB      "GS=", 0
+$EAX            DB      "EAX=", 0
+$EBX            DB      "EBX=", 0
+$ECX            DB      "ECX=", 0
+$EDX            DB      "EDX=", 0
+$ESI            DB      "ESI=", 0
+$EDI            DB      "EDI=", 0
+$EBP            DB      "EBP=", 0
+
+$EXCEPT0        DB      "divide error", 0
+$EXCEPT1        DB      "debug exception", 0
+$EXCEPT2        DB      "nonmaskable interrupt", 0
+$EXCEPT3        DB      "breakpoint", 0
+$EXCEPT4        DB      "overflow", 0
+$EXCEPT5        DB      "bounds check", 0
+$EXCEPT6        DB      "invalid opcode", 0
+$EXCEPT7        DB      "coprocessor not available", 0
+$EXCEPT8        DB      "double fault", 0
+$RESERVED       DB      "reserved", 0
+$EXCEPT10       DB      "invalid TSS", 0
+$EXCEPT11       DB      "segment not present", 0
+$EXCEPT12       DB      "stack exception", 0
+$EXCEPT13       DB      "general protection", 0
+$EXCEPT14       DB      "page fault", 0
+$EXCEPT15       DB      "reserved", 0
+$EXCEPT16       DB      "coprocessor error", 0
+$EXCEPT17       DB      "alignment check", 0
+
+EXCEPT_TEXTS    DW      $EXCEPT0, $EXCEPT1, $EXCEPT2, $EXCEPT3
+                DW      $EXCEPT4, $EXCEPT5, $EXCEPT6, $EXCEPT7
+                DW      $EXCEPT8, $RESERVED, $EXCEPT10, $EXCEPT11
+                DW      $EXCEPT12, $EXCEPT13, $EXCEPT14, $EXCEPT15
+                DW      $EXCEPT16, $EXCEPT17
+
+REG_16          EQU     10000H
+REG_NL          EQU     20000H
+
+REG_TAB         LABEL   DWORD
+                DD      OFFSET $DS,   6 OR REG_16
+                DD      OFFSET $ES,   4 OR REG_16
+                DD      OFFSET $FS,   2 OR REG_16
+                DD      OFFSET $GS,   0 OR REG_16 OR REG_NL
+                DD      OFFSET $EAX, 36
+                DD      OFFSET $EBX, 24
+                DD      OFFSET $ECX, 32
+                DD      OFFSET $EDX, 28 OR REG_NL
+                DD      OFFSET $ESI, 12
+                DD      OFFSET $EDI,  8
+                DD      OFFSET $EBP, 16
+                DD      0, 0
+
+;
+; Table for converting exception numbers to signal numbers
+;
+EXC_TO_SIG_TAB  DB      SIGILL          ;  0 Unused
+                DB      SIGTRAP         ;  1 Debug
+                DB      SIGBUS          ;  2 NMI
+                DB      SIGTRAP         ;  3 Breakpoint
+                DB      SIGFPE          ;  4 Overflow
+                DB      SIGFPE          ;  5 BOUND
+                DB      SIGILL          ;  6 Invalid instruction
+                DB      SIGFPE          ;  7 Numeric coprocessor not available
+                DB      SIGSEGV         ;  8 Double fault
+                DB      SIGSEGV         ;  9 Coproc. operand seg. limit viol.
+                DB      SIGILL          ; 10 Invalid task state segment
+                DB      SIGSEGV         ; 11 Segment not present
+                DB      SIGSEGV         ; 12 Stack fault
+                DB      SIGSEGV         ; 13 General protection
+                DB      SIGSEGV         ; 14 Page fault
+                DB      SIGBUS          ; 15 Unused
+                DB      SIGFPE          ; 16 Numeric coprocessor error
+                DB      SIGSEGV         ; 17 Alignment check (486)
+
+;
+; Send register dump of exception to stdout (not to CON) if NOT FALSE
+;
+STDOUT_DUMP     DB      FALSE
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+                .386P
+
+                ASSUME  DS:NOTHING
+
+
+                IRP     X,<0,1,3,4,5,6,7,9,11,12,13,14,15,16,17>
+                TALIGN  2
+EXCEPT&X:
+              IF &X LE 7 OR &X EQ 15 OR &X EQ 16 ; Assume EX 17 w/errcd
+                PUSH   DWORD PTR 0              ; Mock error code
+              ENDIF
+                PUSHAD                          ; Save the general registers
+                MOV     AL, X                   ; Exception number to AL
+                JMP     EXCEPT                  ; Common code
+                ENDM
+
+;
+; Common code for all exceptions
+;
+; This code is called via an interrupt gate, therefore interrupts are
+; disabled.
+;
+
+
+                ASSUME  DS:NOTHING
+                ASSUME  BP:PTR ISTACKFRAME
+                TALIGN  4
+EXCEPT:         PUSH    DS                      ; Save segment registers
+                PUSH    ES
+                PUSH    FS
+                PUSH    GS
+              IF SER_FLAG
+                PUSH    AX
+                SERIAL  "E"
+                POP     AX
+              ENDIF
+                MOV     EBP, ESP                ; Setup stack frame
+                SUB     ESP, FRAME_SIZE         ; Local variables
+                MOV     BX, G_SV_DATA_SEL
+                MOV     DS, BX                  ; Make data segment accessible
+                ASSUME  DS:SV_DATA
+                MOV     EXCEPT_NO, AL           ; Save exception number
+                CLD
+;
+; Check for debugging
+;
+              IF DEBUG_PTRACE
+                CMP     AL, 1                   ; Debug exception?
+                JE      SHORT EXCEPT_4          ; Yes -> built-in debugger
+              ENDIF
+;
+; Check for page faults
+;
+                CMP     AL, 14                  ; Page fault?
+                JNE     SHORT EXCEPT_1
+                CALL    PAGE_FAULT              ; Yes -> try to handle this
+;
+; Check for floating-point exceptions
+;
+EXCEPT_1:     IF FLOATING_POINT
+                CMP     EXCEPT_NO, 7            ; Coprocessor not available?
+                JNE     SHORT EXCEPT_2          ; No  -> skip
+                CALL    EXCEPT_DNA              ; Task switch / emulator
+              ENDIF
+;
+; Check for return from signal handler
+;
+EXCEPT_2:       CMP     EXCEPT_NO, 13           ; General protection violation?
+                JNE     SHORT EXCEPT_3          ; No  -> skip
+                MOV     EAX, I_ERRCD            ; Get error code
+                OR      AX, AX                  ; Tried to load a selector?
+                JNE     SHORT EXCEPT_3          ; Yes -> skip
+                MOVZX   EAX, I_CS               ; Get CS
+                LSL     EAX, EAX                ; Get code segment limit
+                JNZ     SHORT EXCEPT_3          ; Avoid another exception
+                MOV     ESI, I_EIP              ; Put CS:EIP into ES:ESI
+                MOV     ES, I_CS                ; NB: All segments are readable
+                CMP     ESI, EAX                ; EIP beyond limit?
+                JA      SHORT EXCEPT_3          ; Yes -> avoid another exception
+                CMP     BYTE PTR ES:[ESI], 0C3H ; Pointing to RETN?
+                JNE     SHORT EXCEPT_3          ; No  -> skip
+                MOVZX   EAX, I_SS               ; Get SS
+                LSL     EAX, EAX                ; Get stack segment limit
+                JNZ     SHORT EXCEPT_3          ; Avoid another exception
+                SUB     EAX, size SIGFRAME - 1  ; We examine a SIGFRAME
+                JC      SHORT EXCEPT_3          ; Cannot happen
+                MOV     ESI, I_ESP              ; Put SS:ESP into ES:ESI
+                ASSUME  ESI:NEAR32 PTR SIGFRAME
+                MOV     ES, I_SS                ; NB: Expand=Up
+                CMP     ESI, EAX                ; ESP beyond limit?
+                JA      SHORT EXCEPT_3          ; Yes -> avoid another exception
+                CMP     ES:[ESI].SF_EIP, SIG_EIP ; Our special EIP?
+                JNE     SHORT EXCEPT_3          ; No  -> skip
+                CMP     ES:[ESI].SF_SIGNATURE, SIG_SIGNATURE ; Signature?
+                JNE     SHORT EXCEPT_3          ; No  -> skip
+                CALL    SIG_RETURN              ; Return from signal handler
+                ASSUME  ESI:NOTHING
+                JMP     EXCEPT_12               ; Signal not handled
+
+;
+; This entry point is used for SIGFPE (see PMINT.ASM).
+;
+EXCEPT_FAKE:    MOV     EXCEPT_NO, AL
+
+;
+; Check for ptraced process
+;
+EXCEPT_3:       TEST    I_CS, 3                 ; In supervisor?
+                JZ      SHORT EXCEPT_4          ; Yes -> skip
+                MOV     BX, PROCESS_PTR         ; Current process
+                CMP     BX, NO_PROCESS          ; No process?
+                JE      SHORT EXCEPT_4          ; Yes -> skip (cannot happen)
+                TEST    (PROCESS PTR [BX]).P_FLAGS, PF_DEBUG
+                JZ      SHORT EXCEPT_4          ; Process not in debug mode ->
+                CALL    EXCEPT_PTRACE           ; Return to ptracing process
+EXCEPT_4:       CMP     EXCEPT_NO, 1            ; Debug exception?
+                JNE     SHORT EXCEPT_5          ; No  -> skip
+                CALL    DEBUG_EXCEPTION
+                JMP     SHORT EXCEPT_10
+
+;
+; Give the debugger a chance
+;
+EXCEPT_5:       CMP     STEP_FLAG, FALSE        ; -S option?
+                JE      SHORT EXCEPT_6
+                CALL    DEBUG_EXCEPTION
+;
+; Check for exceptions to be mapped to signals
+;
+EXCEPT_6:       TEST    I_CS, 3                 ; Called from user code?
+                JZ      SHORT EXCEPT_10         ; No  -> skip
+                MOV     BX, PROCESS_PTR         ; Current process
+                CMP     BX, NO_PROCESS          ; No process?
+                JE      SHORT EXCEPT_10         ; Yes -> skip
+                ASSUME  BX:PTR PROCESS
+                MOV     AL, EXCEPT_NO           ; Compute signal number
+                CALL    EXC_TO_SIG              ; from exception number
+                MOV     EDX, EAX                ; EDX := signal number
+;
+; Deliver the signal if a signal handler is set.  Deliver the
+; signal even if it is blocked.
+;
+                MOV     SI, DX
+                SHL     SI, 2
+                MOV     EAX, [BX].P_SIG_HANDLERS[SI] ; Get address
+                CMP     EAX, SIG_IGN            ; Ignore signal
+                JE      SHORT EXCEPT_10         ; Yes -> skip
+                CMP     EAX, SIG_DFL            ; Default processing?
+                JE      SHORT EXCEPT_10         ; Yes -> skip
+                CALL    EXCEPT_SIGNAL           ; Deliver the signal
+                ASSUME  BX:NOTHING
+;
+; Display register dump if appropriate
+;
+EXCEPT_10:      CMP     I_CS, L_CODE_SEL        ; In user code?
+                JE      SHORT EXCEPT_11         ; Yes -> don't show registers
+                CALL    EX_DUMP
+EXCEPT_11:      CMP     I_CS, L_CODE_SEL        ; In user code?
+                JNE     SHORT STOP              ; No  -> loop forever
+;
+; Display message.  Dump core unless disabled
+;
+                MOV     AL, EXCEPT_NO
+                CALL    EXC_TO_SIG
+EXCEPT_12:      CALL    SIG_MSG                 ; Display "Stopped by SIG..."
+                CMP     EAX, SIGNALS            ; Valid signal number?
+                JAE     SHORT EXCEPT_13         ; No  -> dump core
+                CMP     SIG_CORE[EAX], FALSE    ; Dump core for this signal?
+                JE      SHORT NOCORE            ; No  -> skip
+EXCEPT_13:      MOV     BX, PROCESS_PTR         ; Current process
+                CMP     BX, NO_PROCESS          ; No process?
+                JE      SHORT NOCORE            ; Yes -> skip
+                TEST    (PROCESS PTR [BX]).P_FLAGS, PF_NO_CORE
+                JNZ     SHORT NOCORE            ; Core dumps disabled -> skip
+                CALL    CORE_REGS_I
+                CALL    CORE_DUMP
+NOCORE:         MOV     AX, 4CFFH
+                INT     21H
+
+STOP:           JMP     STOP
+
+;
+; Return from exception handler.  This code is either CALLed from the
+; exception handler or JuMPed to by a procedure CALLed by the exception
+; handler.
+;
+                TALIGN  2
+EXCEPT_RET:     ADD     ESP, 2 + FRAME_SIZE     ; Remove return address and
+                                                ; local data
+;
+; Deliver pending signals.  This is required for delivering signals
+; on return from a signal handler.
+;
+                CALL    SIG_DELIVER_PENDING
+                POP     GS
+                POP     FS
+                POP     ES
+                POP     DS
+                POPAD
+                NOP                             ; Avoid 386 bug
+                ADD     ESP, 4                  ; Skip error code
+                IRETD
+
+
+;
+; Switch back to the process that issued ptrace(P_STEP)
+;
+; In:   BX      PROCESS_PTR
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+EXCEPT_PTRACE:  MOV     [BX].P_STATUS, PS_STOP  ; Process stopped
+                OR      [BX].P_FLAGS, PF_WAIT_WAIT
+                MOV     AL, EXCEPT_NO           ; Get exception number
+                CALL    EXC_TO_SIG              ; Convert to signal number
+                MOV     [BX].P_SIG_NO, AL       ; and store it
+                PUSH    EAX                     ; Save it for ptrace result
+                CALL    SAVE_PROCESS            ; Save outgoing process
+                MOV     EAX, [BX].P_PPID        ; Parent process ID
+                CALL    FIND_PROCESS            ; Find table entry
+                POP     EAX                     ; Signal number
+                CMP     BX, NO_PROCESS          ; Not found?
+                JE      SHORT EXCEPT_PTRACE_1   ; Should not happen
+                MOV     PROCESS_PTR, BX         ; Switch to parent process
+                MOV     PROCESS_SIG, BX
+                MOV     CX, [BX].P_STATUS       ; Get process status
+                CALL    REST_PROCESS            ; Restore incoming process
+                CMP     CX, PS_WAIT_PTRACE      ; Has been waiting in ptrace?
+                JNZ     SHORT EXCEPT_PTRACE_1   ; No -> should not happen
+                MOV     I_EAX, EAX              ; Return signal number
+                MOV     I_ECX, 0                ; No error
+                CALL    BREAK_AFTER_IRET        ; For built-in debugger
+                JMP     EXCEPT_RET              ; Return to ptrace
+EXCEPT_PTRACE_1:RET                             ; Continue exception handler
+                ASSUME  BX:NOTHING
+                ASSUME  BP:NOTHING
+
+
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+EX_DUMP         PROC    NEAR
+                CMP     I_CS, L_CODE_SEL
+                JE      SHORT EX_DUMP3
+                MOV     VOUTPUT, NOT FALSE
+                MOV     ETEXT, OFFSET SV_CODE:VTEXT
+                MOV     EBYTE, OFFSET SV_CODE:VBYTE
+                MOV     EWORD, OFFSET SV_CODE:VWORD
+                MOV     EDWORD, OFFSET SV_CODE:VDWORD
+                MOV     ECRLF, OFFSET SV_CODE:VCRLF
+                MOV     ECHAR, OFFSET SV_CODE:VCHAR
+                MOV     AX, G_VIDEO_SEL
+                MOV     ES, AX
+                CALL    VCLS
+                JMP     SHORT EX_DUMP5
+
+EX_DUMP3:       MOV     VOUTPUT, FALSE
+                MOV     ETEXT, OFFSET SV_CODE:OTEXT
+                MOV     EBYTE, OFFSET SV_CODE:OBYTE
+                MOV     EWORD, OFFSET SV_CODE:OWORD
+                MOV     EDWORD, OFFSET SV_CODE:ODWORD
+                MOV     ECRLF, OFFSET SV_CODE:OCRLF
+                MOV     ECHAR, OFFSET SV_CODE:OCHAR
+                CMP     STDOUT_DUMP, FALSE
+                JNE     SHORT EX_DUMP4
+                CALL    FORCE_STDOUT
+EX_DUMP4:       CALL    OCRLF
+EX_DUMP5:       LEA     EDX, $EXCEPTION
+                CALL    ETEXT
+                MOV     AL, EXCEPT_NO
+                CALL    EBYTE
+                CMP     AL, 17
+                JA      SHORT EX_DUMP6
+                MOV     AL, ":"
+                CALL    ECHAR
+                MOV     AL, " "
+                CALL    ECHAR
+                MOV     AL, EXCEPT_NO
+                CALL    EXCEPT_NAME
+                CALL    ETEXT
+EX_DUMP6:       CALL    ECRLF
+                MOV     AL, EXCEPT_NO
+                CMP     AL, 8
+                JB      SHORT NO_ERRCODE
+                CMP     AL, 14
+                JA      SHORT NO_ERRCODE
+                LEA     EDX, $ERRCODE
+                CALL    ETEXT
+                MOV     EAX, I_ERRCD
+                CALL    EDWORD
+                CALL    ECRLF
+NO_ERRCODE:     LEA     EDX, $CS
+                CALL    ETEXT
+                MOV     AX, I_CS
+                CALL    EWORD
+                LEA     EDX, $EIP
+                CALL    ETEXT
+                MOV     EAX, I_EIP
+                CALL    EDWORD
+                CALL    ECRLF
+;
+; Display SS:ESP
+;
+                MOV     SI, I_SS
+                MOV     EDI, I_ESP
+                TEST    I_CS, 3                 ; RPL = 0?
+                JNZ     SHORT EXD_SS_ESP_1      ; No -> use values from stack
+;
+; For RPL=0 the stack has not been switched
+;
+                MOV     SI, SS
+                LEA     EDI, [EBP+56]
+EXD_SS_ESP_1:   LEA     EDX, $SS
+                CALL    ETEXT
+                MOV     AX, SI
+                CALL    EWORD
+                LEA     EDX, $ESP
+                CALL    ETEXT
+                MOV     EAX, EDI
+                CALL    EDWORD
+                CALL    ECRLF
+
+                LEA     EDX, $EFLAGS
+                CALL    ETEXT
+                MOV     EAX, I_EFLAGS
+                CALL    EDWORD
+                CALL    ECRLF
+                CMP     EXCEPT_NO, 14
+                JNE     SHORT EX_NO_CR2
+                LEA     EDX, $CR2
+                CALL    ETEXT
+                MOV     EAX, CR2
+                CALL    EDWORD
+                CALL    ECRLF
+EX_NO_CR2:      LEA     EDI, REG_TAB
+REG_DUMP_1:     MOV     EDX, [EDI+0]
+                OR      EDX, EDX
+                JZ      SHORT REG_DUMP_END
+                CALL    ETEXT
+                MOV     EAX, [EDI+4]
+                TEST    EAX, REG_16
+                JNZ     SHORT REG_DUMP_16
+                AND     EAX, 0FFFFH
+                MOV     EAX, SS:[EBP+EAX]
+                CALL    EDWORD
+                JMP     SHORT REG_DUMP_2
+REG_DUMP_16:    AND     EAX, 0FFFFH
+                MOV     AX, SS:[EBP+EAX]
+                CALL    EWORD
+REG_DUMP_2:     TEST    DWORD PTR [EDI+4], REG_NL
+                JZ      SHORT REG_DUMP_3
+                CALL    ECRLF
+                JMP     SHORT REG_DUMP_9
+REG_DUMP_3:     MOV     AL, TAB
+                CALL    ECHAR
+REG_DUMP_9:     ADD     EDI, 8
+                JMP     SHORT REG_DUMP_1
+
+REG_DUMP_END:   CALL    ECRLF
+                LEA     ESI, I_EFLAGS + 4
+                TEST    I_CS, 3                 ; RPL of return CS
+                JZ      SHORT SAME_LEVEL_2      ; Called from supervisor
+                ADD     ESI, 8                  ; Skip ESP and SS
+SAME_LEVEL_2:   XOR     EAX, EAX
+                MOV     AX, SS
+                MOV     FS, AX
+                LSL     ECX, EAX
+                INC     ECX
+                SUB     ECX, ESI
+                JBE     SHORT NOSDUMP
+                SHR     ECX, 1
+                CMP     ECX, 128
+                JBE     SHORT SDUMP1
+                MOV     ECX, 128
+SDUMP1:         CALL    MEM_DUMP                ; (FS, ESI, ECX)
+NOSDUMP:        RET
+                ASSUME  BP:NOTHING
+EX_DUMP         ENDP
+
+
+;
+; Raise a signal from exception handler
+;
+; Note that this must be a procedure to get the stack right at EXCEPT_RET.
+;
+; In:  EAX      Address of the signal handler
+;      EDX      Signal number
+;      BX       Pointer to process table entry
+;
+EXCEPT_SIGNAL   PROC    NEAR
+                MOV     ECX, NOT FALSE          ; Trap
+                CALL    SIG_USER_CALL           ; Call user signal handler
+                JMP     EXCEPT_RET              ; (This enables interrupts)
+EXCEPT_SIGNAL   ENDP
+
+;
+; Numeric coprocessor not available (DNA=device not available)
+;
+; Handle task switching and emulation
+;
+              IF FLOATING_POINT
+
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+EXCEPT_DNA      PROC    NEAR
+                CMP     FP_FLAG, FP_387         ; 387 coprocessor present?
+                JNE     SHORT EDNA_EMU          ; No -> emulate
+                CLTS                            ; Clear TS bit of CR0
+                MOV     BX, PROCESS_FP          ; Last process using FPU
+                CMP     BX, PROCESS_PTR         ; Same process?
+                JE      SHORT EDNA_NO_REST      ; Yes -> do nothing
+                CMP     BX, NO_PROCESS          ; Save status?
+                JE      SHORT EDNA_NO_SAVE      ; No  -> skip
+                ASSUME  BX:PTR PROCESS
+                DB      66H
+                FNSAVE  [BX].P_CW               ; Save FPU context, initialize
+                FWAIT
+EDNA_NO_SAVE:   MOV     BX, PROCESS_PTR         ; Current process
+                MOV     PROCESS_FP, BX          ; FPU switched to new process
+                CMP     BX, NO_PROCESS          ; Any process?
+                JE      SHORT EDNA_SV           ; No  -> in supervisor
+                TEST    [BX].P_FLAGS, PF_387_USED ; Initialize?
+                JNZ     SHORT EDNA_REST         ; No  -> restore
+                CALL    SETUP_FP                ; Initialize 387
+                OR      [BX].P_FLAGS, PF_387_USED ; 387 initialized
+                JMP     SHORT EDNA_NO_REST      ; Don't restore
+
+EDNA_SV:        CALL    SETUP_FP                ; Initialize 387
+                JMP     SHORT EDNA_NO_REST      ; Don't restore
+;
+; Note: 32-bit mode? 287?
+;
+EDNA_REST:
+                DB      66H
+                FRSTOR  [BX].P_CW
+EDNA_NO_REST:   JMP     EXCEPT_RET              ; Return to fp instruction
+
+;
+; Call coprocessor emulator.
+;
+; If there is no coprocess emulator, the untyped call and return
+; constructs of GCC 2.6.0 use the FNSAVE and FRSTOR instructions
+; even if no floating point code is used by the application.
+; Therefore, we silently ignore FNSAVE and FRSTOR.
+;
+; However, GCC 2.6.1 generates more complicated code which I don't
+; want to handle here.  That doesn't matter as we have a real FPU
+; emulator now.
+;
+                TALIGN  4
+EDNA_EMU:       TEST    I_CS, 3                 ; In supervisor?
+                JZ      SHORT EDNA_EMU_RET      ; Yes -> skip
+                CMP     FPUEMU_STATE, FES_ON
+                JE      SHORT EDNA_EMU_CALL
+                CMP     FPUEMU_STATE, FES_OFF
+                JNE     SHORT EDNA_EMU_NO
+                CALL    FPUEMU_LOAD             ; Try to load a FPU emulator
+                CMP     FPUEMU_STATE, FES_LOADING
+                JNE     SHORT EDNA_EMU_NO
+                JMP     EXCEPT_RET              ; Run the emulator
+
+; TODO: Abort if FP exception in emulator
+                TALIGN  4
+EDNA_EMU_CALL:  CALL    FPUEMU_CALL             ; Switch to the FPU emulator
+                JMP     EXCEPT_RET
+
+                TALIGN  4
+EDNA_EMU_NO:    MOV     ESI, I_EIP              ; Put CS:EIP into ES:ESI
+                MOV     ES, I_CS                ; NB: All segments are readable
+                CMP     BYTE PTR ES:[ESI], 0DDH ; 1st byte of FNSAVE, FRSTOR
+                JNE     SHORT EDNA_EMU_RET      ; Other -> default processing
+                INC     ESI
+                MOV     AH, ES:[ESI]            ; Get MOD, XXX, R/M
+                INC     ESI
+                MOV     AL, AH
+                AND     AL, 11000000B           ; Extract MOD
+                CMP     AL, 11000000B           ; MOD=11?
+                JE      SHORT EDNA_EMU_RET      ; Yes -> not FSAVE/FRSTOR
+                MOV     AL, AH
+                AND     AL, 00111000B           ; Extract XXX (opcode)
+                CMP     AL, 00100000B           ; FRSTOR?
+                JE      SHORT FPEMU_1           ; Yes ->
+                CMP     AL, 00110000B           ; FSAVE?
+                JE      SHORT FPEMU_1           ; Yes ->
+EDNA_EMU_RET:   RET                             ; Default exception processing
+                ASSUME  BX:NOTHING
+
+;
+; FSAVE and FRSTOR
+;
+FPEMU_1:        MOV     AL, AH
+                AND     AL, 00000111B           ; Extract R/M
+                CMP     AL, 00000100B           ; Use SIB?
+                JE      SHORT FPEMU_SIB         ; Yes -> look at SIB
+                MOV     AL, AH
+                AND     AL, 11000000B           ; Extract MOD
+                JZ      SHORT FPEMU_MOD00       ; MOD=00 ->
+                CMP     AL, 01000000B           ; MOD=01?
+                JE      SHORT FPEMU_MOD01       ; Yes ->
+;
+; MOD=10: [REG+DISP32]
+;
+FPEMU_MOD10:    ADD     ESI, 4                  ; Skip DISP32
+                JMP     SHORT FPEMU_IGNORE
+
+;
+; MOD=01: [REG+DISP8]
+;
+FPEMU_MOD01:    INC     ESI                     ; Skip DISP8
+                JMP     SHORT FPEMU_IGNORE
+
+;
+; MOD=00: [REG] or [DISP32]
+;
+FPEMU_MOD00:    MOV     AL, AH
+                AND     AL, 00000111B           ; Extract R/M
+                CMP     AL, 00000101B           ; EBP (meaning DISP32)?
+                JNE     SHORT FPEMU_IGNORE      ; No -> no displacement
+                ADD     ESI, 4                  ; Skip DISP32
+                JMP     SHORT FPEMU_IGNORE
+
+;
+; R/M=100: SIB
+;
+FPEMU_SIB:      MOV     DL, ES:[ESI]            ; Fetch SIB
+                INC     ESI
+                MOV     AL, AH
+                AND     AL, 11000000B           ; Extract MOD
+                JZ      SHORT FPEMU_SIB_MOD00   ; MOD=00 ->
+                CMP     AL, 01000000B           ; MOD=01?
+                JE      SHORT FPEMU_SIB_MOD01   ; Yes ->
+;
+; MOD=10: [REG+SCALE*INDEX+DISP32]
+;
+FPEMU_SIB_MOD10:ADD     ESI, 4                  ; Skip DISP32
+                JMP     SHORT FPEMU_IGNORE
+
+;
+; MOD=01: [REG+SCALE*INDEX+DISP8]
+;
+FPEMU_SIB_MOD01:INC     ESI                     ; Skip DISP8
+                JMP     SHORT FPEMU_IGNORE
+
+;
+; MOD=00: [REG+SCALE*INDEX] or [DISP32+SCALE*INDEX]
+;
+FPEMU_SIB_MOD00:MOV     AL, DL
+                AND     AL, 00000111B           ; Extract BASE
+                CMP     AL, 00000100B           ; EBP (meaning DISP32)?
+                JNE     SHORT FPEMU_IGNORE      ; No -> no displacement
+                ADD     ESI, 4                  ; Skip DISP32
+                JMP     SHORT FPEMU_IGNORE
+
+;
+; Continue the application at EIP:=ESI
+;
+FPEMU_IGNORE:   MOV     I_EIP, ESI
+                JMP     EXCEPT_RET
+
+
+;
+; Initialize 387 for new process
+;
+SETUP_FP        PROC    NEAR
+                FNINIT
+                FSTCW   FP_TMP
+                FWAIT
+                OR      FP_TMP, 3FH             ; Use default error handlers
+                FLDCW   FP_TMP
+                RET
+SETUP_FP        ENDP
+
+                ASSUME  BP:NOTHING
+EXCEPT_DNA      ENDP
+
+              ENDIF
+
+;
+; Convert exception number to signal number
+;
+; In:   AL      Exception number (0..17, not checked!)
+;
+; Out:  EAX     Signal number
+;
+                ASSUME  DS:SV_DATA
+EXC_TO_SIG      PROC    NEAR
+                PUSH    BX
+                LEA     BX, EXC_TO_SIG_TAB
+                XLAT    EXC_TO_SIG_TAB
+                MOVZX   EAX, AL
+                POP     BX
+                RET
+EXC_TO_SIG      ENDP
+
+;
+; Memory (stack) dump
+;
+; In:   FS:ESI  Source
+;       CX      Word count
+;       ES:BX   Destination
+;
+                ASSUME  DS:NOTHING
+MEM_DUMP        PROC    NEAR
+                PUSH    EAX
+                PUSH    ESI
+                JCXZ    MDUMP9
+MDUMP1:         CMP     VOUTPUT, FALSE
+                JE      SHORT MDUMP2
+                MOV     AX, 5
+                CALL    VWRAP
+                CALL    VGETCOL
+MDUMP2:         MOV     AX, FS:[ESI]
+                CALL    EWORD
+                DEC     CX
+                JZ      SHORT MDUMP9
+                MOV     AL, " "
+                CALL    ECHAR
+                ADD     ESI, 2
+                JMP     MDUMP1
+MDUMP9:         POP     ESI
+                POP     EAX
+                RET
+MEM_DUMP        ENDP
+
+
+;
+; Task for exceptions 8 (double fault) and 10 (invalid TSS)
+;
+                ASSUME  DS:SV_DATA              ; Loaded from TSS
+EXCEPT_TASK:    CLI                             ; Not required
+              IF SER_FLAG
+                SERIAL  "T"
+              ENDIF
+                PUSH    AX                      ; Exception number
+                MOV     AX, G_VIDEO_SEL
+                MOV     ES, AX
+                CALL    VCLS
+                LEA     EDX, $EXCEPTION
+                CALL    VTEXT
+                POP     AX                      ; Loaded from TSS
+                CALL    VBYTE
+                PUSH    AX
+                MOV     AL, ":"
+                CALL    VCHAR
+                MOV     AL, " "
+                CALL    VCHAR
+                POP     AX
+                CALL    EXCEPT_NAME
+                CALL    VTEXT
+                CALL    VCRLF
+                LEA     EDX, $CS
+                CALL    VTEXT
+                MOV     AX, G_TSS_MEM_SEL
+                MOV     FS, AX
+                MOV     AX, (TSS_STRUC PTR FS:[0]).TSS_CS
+                CALL    VWORD
+                LEA     EDX, $EIP
+                CALL    VTEXT
+                MOV     EAX, (TSS_STRUC PTR FS:[0]).TSS_EIP
+                CALL    VDWORD
+                CALL    VCRLF
+                JMP     $
+                ASSUME  ESI:NOTHING
+
+;
+; Return name of exception
+;
+; In:   AL      Exception number
+;
+; Out:  EDX     Text
+;
+EXCEPT_NAME     PROC    NEAR
+                LEA     EDX, $RESERVED
+                CMP     AL, 17
+                JA      SHORT ENAME1
+                PUSH    BX
+                MOV     BL, AL
+                XOR     BH, BH
+                SHL     BX, 1
+                MOV     DX, EXCEPT_TEXTS[BX]    ; Keep upper word of EDX
+                POP     BX
+ENAME1:         RET
+EXCEPT_NAME     ENDP
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/except.inc
===================================================================
--- trunk/src/emx/src/dos/except.inc	(revision 18)
+++ trunk/src/emx/src/dos/except.inc	(revision 18)
@@ -0,0 +1,41 @@
+;
+; EXCEPT.INC -- Handle exceptions
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_DATA         SEGMENT
+
+                EXTRN   EXC_TAB:WORD
+                EXTRN   STDOUT_DUMP:BYTE
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   EXCEPT_FAKE:NEAR
+                EXTRN   EXCEPT_RET:NEAR
+                EXTRN   EXCEPT_TASK:NEAR
+                EXTRN   EXCEPT_NAME:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/extapi.asm
===================================================================
--- trunk/src/emx/src/dos/extapi.asm	(revision 18)
+++ trunk/src/emx/src/dos/extapi.asm	(revision 18)
@@ -0,0 +1,108 @@
+;
+; EXTAPI.ASM -- DOS extender API
+;
+; Copyright (c) 1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE PMINT.INC
+
+                PUBLIC  EXTAPI
+
+SV_CODE         SEGMENT
+
+                .386P
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+EXT_JUMP        WORD    EXT00, EXT01, EXT02, EXT03, EXT04
+                WORD    EXT05, EXT06, EXT07, EXT08, EXT09
+                WORD    EXT0A, EXT0B, EXT0C, EXT0D, EXT0E
+
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+EXTAPI          PROC    NEAR
+                AND     I_EFLAGS, NOT FLAG_C    ; Clear carry flag (no error)
+                MOV     AX, WORD PTR I_EAX
+                CMP     AH, 0EH
+                JA      SHORT EXT_INVALID
+                MOV     BL, AH
+                MOV     BH, 0
+                SHL     BX, 1
+                JMP     EXT_JUMP[BX]
+
+EXT00::
+EXT01::
+EXT02::
+EXT03::
+EXT05::
+EXT06::
+EXT07::
+EXT08::
+EXT09::
+EXT0A::
+EXT0B::
+EXT0C::
+EXT0D::
+EXT0E::
+EXT_INVALID:    MOV     AX, 8001H               ; Unsupported function
+EXT_ERROR:      AND     EAX, 0FFFFH
+                MOV     I_EAX, EAX
+                OR      I_EFLAGS, FLAG_C        ; Set carray flag
+                RET
+
+EXT04::         CMP     AL, 00H
+                JE      SHORT EXT0400
+                CMP     AL, 01H
+                JE      SHORT EXT0401
+                JMP     EXT_INVALID
+
+;
+; Get version
+;
+EXT0400:        MOV     I_EAX, 0100H            ; DPMI 1.0
+                MOV     I_EBX, 0005H            ; TODO
+                MOV     I_ECX, 0003H            ; TODO
+                MOV     I_EDX, 0000H            ; TODO
+                RET
+
+;
+; Get DPMI capabilities
+;
+EXT0401:        MOV     EDI, I_EDI
+                MOV     ES, I_ES
+                MOV     I_EAX, 0000H            ; TODO
+                MOV     I_ECX, 0                ; Reserved
+                MOV     I_EDX, 0                ; Reserved
+                MOV     BYTE PTR ES:[EDI+0], 0  ; Major version (TODO)
+                MOV     BYTE PTR ES:[EDI+1], 0  ; Minor version (TODO)
+                MOV     BYTE PTR ES:[EDI+2], "e"
+                MOV     BYTE PTR ES:[EDI+3], "m"
+                MOV     BYTE PTR ES:[EDI+4], "x"
+                MOV     BYTE PTR ES:[EDI+5], 0
+                RET
+
+EXTAPI          ENDP
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/extapi.inc
===================================================================
--- trunk/src/emx/src/dos/extapi.inc	(revision 18)
+++ trunk/src/emx/src/dos/extapi.inc	(revision 18)
@@ -0,0 +1,30 @@
+;
+; MISC.INC -- DOS extender API
+;
+; Copyright (c) 1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_CODE         SEGMENT
+
+                EXTRN   EXTAPI:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/fileio.asm
===================================================================
--- trunk/src/emx/src/dos/fileio.asm	(revision 18)
+++ trunk/src/emx/src/dos/fileio.asm	(revision 18)
@@ -0,0 +1,991 @@
+;
+; FILEIO.ASM -- Handle files and file handles
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE SWAPPER.INC
+                INCLUDE ERRORS.INC
+                INCLUDE OPTIONS.INC
+                INCLUDE OPRINT.INC
+                INCLUDE PMINT.INC
+                INCLUDE UTILS.INC
+
+TOTAL_FILES     =       128
+
+SV_DATA         SEGMENT
+
+;
+; For each DOS file handle, this array contains the number of times
+; the handle is referenced.
+;
+DOS_REF_COUNT   DW      TOTAL_FILES DUP (?)
+
+$CHECK_HANDLES  DB      "Internal error: wrong handle reference count", 0
+
+$DIR_DEV        BYTE    "DEV", 0
+$DIR_PIPE       BYTE    "PIPE", 0
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Implementation of __dup()
+;
+; In:   AX      File handle
+;       BX      Pointer to process table entry
+;
+; Out:  AX      errno if CY set
+;       AX      File handle if CY clear
+;       CY      Error
+;
+; Find an available file handle, then use common code for
+; DO_DUP and DO_DUP2.
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+DO_DUP          PROC    NEAR
+;
+; Check the file handle
+;
+                CMP     AX, MAX_FILES
+                JAE     SHORT DUP_EBADF
+                MOV     SI, AX
+                SHL     SI, 1
+                CMP     [BX].P_HANDLES[SI], NO_FILE_HANDLE
+                JE      SHORT DUP_EBADF
+;
+; Find an available file handle
+;
+                MOV     SI, 0
+                MOV     CX, 0
+DUP_LOOP:       CMP     [BX].P_HANDLES[SI], NO_FILE_HANDLE
+                JE      DUP_FOUND
+                ADD     SI, 2
+                INC     CX
+                CMP     CX, MAX_FILES
+                JB      SHORT DUP_LOOP
+                MOV     AX, EMFILE              ; Too many open files
+                STC
+                RET
+
+DUP_EBADF:      MOV     AX, EBADF
+                STC
+                RET
+
+;
+; File handle found, call common code
+;
+DUP_FOUND:      CALL    DUP_COMMON
+                CLC
+                RET
+                ASSUME  BX:NOTHING
+DO_DUP          ENDP
+
+
+;
+; Implementation of __dup2()
+;
+; In:   AX      Source handle
+;       CX      Target handle
+;       BX      Pointer to process table entry
+;
+; Out:  AX      errno if CY set
+;       AX      File handle if CY clear
+;
+; Check the file handles, then use common code for
+; DO_DUP and DO_DUP2.
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+DO_DUP2         PROC    NEAR
+;
+; Check the source file handle
+;
+                CMP     AX, MAX_FILES
+                JAE     SHORT DUP2_EBADF
+                MOV     SI, AX
+                SHL     SI, 1
+                CMP     [BX].P_HANDLES[SI], NO_FILE_HANDLE
+                JE      SHORT DUP2_EBADF
+;
+; Do nothing if the two handles are identical
+;
+                CMP     AX, CX                  ; Handles identical?
+                JE      SHORT DUP2_OK           ; Yes -> return the handle
+;
+; Check the target file handle.  Close the target handle if it is open
+;
+                CMP     CX, MAX_FILES
+                JAE     SHORT DUP2_EBADF
+                MOV     SI, CX
+                SHL     SI, 1
+                CMP     [BX].P_HANDLES[SI], NO_FILE_HANDLE
+                JE      SHORT DUP2_CONT
+                PUSH    AX
+                PUSH    CX
+                MOV     AX, CX
+                CALL    DO_CLOSE
+                POP     CX
+                POP     DX
+                JC      SHORT DUP2_RET          ; Error
+                MOV     AX, DX
+;
+; Call common code
+;
+DUP2_CONT:      CALL    DUP_COMMON
+DUP2_OK:        CLC
+DUP2_RET:       RET
+
+DUP2_EBADF:     MOV     AX, EBADF
+                STC
+                RET
+
+                ASSUME  BX:NOTHING
+DO_DUP2         ENDP
+
+
+;
+; Common code for DO_DUP and DO_DUP2, both handles have been checked,
+; no error is possible.  The target handle is available.
+;
+; In:   AX      Source handle
+;       CX      Target handle
+;       BX      Pointer to process table entry
+;
+; Out:  AX      File handle
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+DUP_COMMON      PROC    NEAR
+                MOV     SI, AX
+                SHL     SI, 1
+                MOV     AX, [BX].P_HFLAGS[SI]
+                MOV     DX, [BX].P_HANDLES[SI]
+                MOV     SI, CX
+                SHL     SI, 1
+                MOV     [BX].P_HANDLES[SI], DX
+                AND     AX, NOT HF_NOINHERIT    ; Clear FD_CLOEXEC
+                MOV     [BX].P_HFLAGS[SI], AX
+                MOV     SI, DX
+                SHL     SI, 1
+                INC     DOS_REF_COUNT[SI]
+                MOV     AX, CX
+                CALL    MAYBE_CHECK_HANDLES
+                RET
+                ASSUME  BX:NOTHING
+DUP_COMMON      ENDP
+
+;
+; Close a file handle
+;
+; In:   AX      File handle
+;       BX      Pointer to process table entry
+;
+; Out:  AX      errno if CY set
+;       CY      Error
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+DO_CLOSE        PROC    NEAR
+                PUSH    DX
+                PUSH    SI
+                CMP     AX, MAX_FILES
+                JAE     SHORT CLOSE_EBADF
+                MOV     SI, AX
+                SHL     SI, 1
+                MOV     DX, [BX].P_HANDLES[SI]
+                CMP     DX, NO_FILE_HANDLE
+                JE      SHORT CLOSE_EBADF
+                MOV     [BX].P_HANDLES[SI], NO_FILE_HANDLE
+                MOV     [BX].P_HFLAGS[SI], 0
+                MOV     SI, DX
+                SHL     SI, 1
+;
+; The reference count should not be zero here.  Handle that case, anyway.
+;
+                CMP     DOS_REF_COUNT[SI], 0
+                JE      SHORT CLOSE_CLOSE
+                DEC     DOS_REF_COUNT[SI]
+                JNZ     SHORT CLOSE_OK
+;
+; Close the DOS file handle
+;
+CLOSE_CLOSE:    PUSH    BX
+                MOV     BX, DX
+                MOV     AH, 3EH
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                INT     21H
+                POP     PROCESS_PTR
+                POP     BX
+                JMP     SHORT CLOSE_RET
+
+CLOSE_OK:       CALL    MAYBE_CHECK_HANDLES
+                XOR     AX, AX
+CLOSE_RET:      POP     SI
+                POP     DX
+                RET
+
+CLOSE_EBADF:    MOV     AX, EBADF
+                STC
+                JMP     SHORT CLOSE_RET
+                ASSUME  BX:NOTHING
+DO_CLOSE        ENDP
+
+
+;
+; Translate file handle (process PROCESS_PTR) to DOS file handle
+;
+; In:   AX      File handle
+;       PROCESS_PTR
+;
+; Out:  AX      DOS file handle (NO_FILE_HANDLE if file not open)
+;       CY      Not a valid handle
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+GET_HANDLE      PROC    NEAR
+                CMP     AX, MAX_FILES
+                JAE     SHORT GET_HANDLE_ERR
+                PUSH    BX
+                PUSH    SI
+                MOV     SI, AX
+                SHL     SI, 1
+                MOV     BX, PROCESS_PTR
+                MOV     AX, (PROCESS PTR [BX]).P_HANDLES[SI]
+                POP     SI
+                POP     BX
+                CLC
+                RET
+GET_HANDLE_ERR: MOV     AX, NO_FILE_HANDLE
+                STC
+                RET
+GET_HANDLE      ENDP
+
+
+;
+; Put new handle into handle translation table
+;
+; In:   AX      DOS file handle
+;       PROCESS_PTR
+;
+; Out:  CY      No empty slot found
+;       EAX     emx file handle
+;
+; Note:
+;       When called with AX=NO_FILE_HANDLE, this function just looks for an
+;       empty slot, but does not use that slot.
+;
+
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+NEW_HANDLE      PROC    NEAR
+                PUSH    BX
+                PUSH    DX
+                PUSH    SI
+                MOV     BX, PROCESS_PTR
+                MOV     SI, 0
+                MOV     DX, 0
+                ASSUME  BX:PTR PROCESS
+                TALIGN  4
+NH_LOOP:        CMP     [BX].P_HANDLES[SI], NO_FILE_HANDLE ; Empty slot?
+                JE      SHORT NH_FOUND          ; Yes -> use it
+                ADD     SI, 2                   ; Next slot
+                INC     DX
+                CMP     DX, MAX_FILES
+                JB      SHORT NH_LOOP
+NH_ERROR:       STC                             ; Out of file handles
+                JMP     SHORT NH_RET
+
+                TALIGN  4
+NH_FOUND:       CMP     AX, NO_FILE_HANDLE
+                JE      SHORT NH_OK
+                CMP     AX, TOTAL_FILES
+                JAE     SHORT NH_ERROR
+                MOV     [BX].P_HANDLES[SI], AX  ; Store DOS file handle
+                MOV     [BX].P_HFLAGS[SI], 0    ; Clear handle flags
+                MOV     SI, AX
+                SHL     SI, 1
+                MOV     DOS_REF_COUNT[SI], 1
+NH_OK:          MOVZX   EAX, DX
+                CALL    MAYBE_CHECK_HANDLES
+                CLC
+NH_RET:         POP     SI
+                POP     DX
+                POP     BX
+                RET
+                ASSUME  BX:NOTHING
+NEW_HANDLE      ENDP
+
+;
+; Remap file handles to make the DOS handle identical to the user process'
+; handle.
+;
+; In:   AX      File handle
+;       PROCESS_PTR
+;
+; Out:  AX      errno if CY is set
+;       CY      Error
+;
+; TODO: Handle HF_NOINHERIT.
+;
+MH_HANDLE       EQU     (WORD PTR [BP-1*2])
+MH_RELOC        EQU     (WORD PTR [BP-2*2])
+MH_DOSHANDLE    EQu     (WORD PTR [BP-3*2])
+
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+MAP_HANDLE      PROC    NEAR
+                PUSH    BX
+                PUSH    CX
+                PUSH    DX
+                PUSH    SI
+                PUSH    BP
+                MOV     BP, SP
+                SUB     SP, 3 * 2
+                MOV     MH_HANDLE, AX
+                MOV     BX, PROCESS_PTR
+                ASSUME  BX:PTR PROCESS
+                MOV     SI, AX
+                SHL     SI, 1
+                MOV     DX, [BX].P_HANDLES[SI]  ; Fetch curent DOS handle
+                CMP     AX, DX                  ; Mapping required?
+                JE      MH_OK                   ; No -> done
+                MOV     MH_DOSHANDLE, DX
+;
+; Check whether we have to relocate the DOS handle.  It must be relocated
+; if it is used.
+;
+                CMP     DOS_REF_COUNT[SI], 0    ; DOS handle used at all?
+                JNE     SHORT MH_RELOCATE       ; Yes -> relocate
+                CMP     AX, SWAP_HANDLE         ; Used for swap file?
+                JE      SHORT MH_RELOCATE       ; Yes -> relocate
+;
+; Check whether the handle is used for an executable file
+;
+                LEA     BX, PROCESS_TABLE
+                MOV     CX, MAX_PROCESSES
+MH_EXEC_LOOP:   CMP     AX, [BX].P_EXEC_HANDLE
+                JE      SHORT MH_RELOCATE
+                ADD     BX, SIZE PROCESS
+                LOOP    MH_EXEC_LOOP
+                JMP     SHORT MH_NO_RELOC
+;
+; Relocate the DOS handle to make it available, updating the translation
+; tables of all processes
+;
+MH_RELOCATE:    MOV     BX, MH_HANDLE
+                ASSUME  BX:NOTHING
+                MOV     AH, 45H
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                INT     21H
+                POP     PROCESS_PTR
+                JC      MH_RET
+                CMP     AX, TOTAL_FILES
+                JAE     MH_ERROR
+                MOV     MH_RELOC, AX            ; Relocated handle
+
+                MOV     AH, 3EH                 ; Close the original handle
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                INT     21H
+                POP     PROCESS_PTR
+                MOV     AX, MH_HANDLE
+                MOV     DX, MH_RELOC
+                CALL    MAP_TRANSLATE
+;
+; Move the DOS handle previously associated with MH_HANDLE to DOS handle
+; MH_HANDLE.
+;
+MH_NO_RELOC:    MOV     BX, MH_DOSHANDLE        ; Is the handle associated
+                CMP     BX, NO_FILE_HANDLE      ; with a DOS handle?
+                JE      SHORT MH_OK             ; No  -> done (it's closed now)
+                CMP     BX, MH_HANDLE           ; Same handle?
+                JE      SHORT MH_OK             ; Yes -> done
+                MOV     CX, MH_HANDLE
+                MOV     AH, 46H
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                INT     21H
+                POP     PROCESS_PTR
+                JC      SHORT MH_RET
+;
+; Update the P_HANDLES entry for this one handle, leaving the other entries
+; of this process and other processes point to the duplicate made above.
+; If there are no other entries, we can close the handle.
+;
+                MOV     BX, PROCESS_PTR
+                ASSUME  BX:PTR PROCESS
+                MOV     AX, MH_HANDLE
+                MOV     SI, AX
+                SHL     SI, 1
+                MOV     [BX].P_HANDLES[SI], AX
+                ASSUME  BX:NOTHING
+                MOV     SI, AX
+                SHL     SI, 1
+                INC     DOS_REF_COUNT[SI]
+;
+; Update the reference count for the handle and check whether we can close it.
+;
+                MOV     SI, MH_DOSHANDLE
+                SHL     SI, 1
+                CMP     DOS_REF_COUNT[SI], 0
+                JE      SHORT MH_CLOSE
+                DEC     DOS_REF_COUNT[SI]
+                JNZ     SHORT MH_OK
+;
+; The duplicate is no longer referenced, close it now.  Note that the
+; handle can only be referenced by P_HANDLES.
+;
+MH_CLOSE:       MOV     BX, MH_DOSHANDLE
+                MOV     AH, 3EH
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                INT     21H
+                POP     PROCESS_PTR
+
+MH_OK:          CALL    MAYBE_CHECK_HANDLES
+                XOR     AX, AX
+MH_RET:         MOV     SP, BP
+                POP     BP
+                POP     SI
+                POP     DX
+                POP     CX
+                POP     BX
+                ASSUME  BX:NOTHING
+                RET
+
+MH_ERROR:       MOV     AX, EMFILE              ; ENFILE is not implemented
+                STC
+                JMP     SHORT MH_RET
+
+MAP_HANDLE      ENDP
+
+
+;
+; Update handle translation tables of all processes and other file
+; handles.  Also update DOS_REF_COUNT.
+;
+; In:   AX      Old DOS handle
+;       DX      New DOS handle
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+MAP_TRANSLATE   PROC    NEAR
+                LEA     BX, PROCESS_TABLE
+                ASSUME  BX:PTR PROCESS
+                MOV     DI, 0                   ; Number of changes
+                MOV     CX, MAX_PROCESSES + 1   ; Include PROC0 (for OCHAR)!
+MT_LOOP_PROC:   MOV     SI, 0
+MT_LOOP_HANDLE: CMP     [BX].P_HANDLES[SI], AX
+                JNE     SHORT MT_NO_UPDATE_1
+                MOV     [BX].P_HANDLES[SI], DX
+                INC     DI
+MT_NO_UPDATE_1: ADD     SI, 2
+                CMP     SI, 2 * MAX_FILES
+                JB      SHORT MT_LOOP_HANDLE
+                CMP     AX, [BX].P_EXEC_HANDLE  ; Executable file?
+                JNE     SHORT MT_NO_UPDATE_2
+                MOV     [BX].P_EXEC_HANDLE, DX
+MT_NO_UPDATE_2: ADD     BX, SIZE PROCESS
+                LOOP    MT_LOOP_PROC
+;
+; Update DOS_REF_COUNT
+;
+                MOV     SI, AX
+                SHL     SI, 1
+                SUB     DOS_REF_COUNT[SI], DI
+                MOV     SI, DX
+                SHL     SI, 1
+                ADD     DOS_REF_COUNT[SI], DI
+;
+; Update other file handles
+;
+                CMP     AX, SWAP_HANDLE         ; Swap file?
+                JNE     SHORT MT_NO_UPDATE_3
+                MOV     SWAP_HANDLE, DX
+MT_NO_UPDATE_3:
+                RET
+                ASSUME  BX:NOTHING
+MAP_TRANSLATE   ENDP
+
+
+;
+; Remap file handles 0 through 2 of the current process to make the
+; DOS handles identical to the current process' handle.  We don't
+; remap all file handles because that would certainly run out of
+; DOS handles: To pass closed handles as closed to the child process,
+; all used handles must be moved out of 0..MAX_FILES-1, leaving no
+; space for non-user handles.
+;
+; In:   PROCESS_PTR
+;
+; Out:  AX      errno if CY is set
+;       CY      Error
+;       
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+MAP_ALL_HANDLES PROC    NEAR
+                PUSH    BX
+                MOV     BX, 0
+MAH_LOOP:       MOV     AX, BX
+                CALL    MAP_HANDLE
+                JC      SHORT MAH_RET
+                INC     BX
+                CMP     BX, 3
+                JB      SHORT MAH_LOOP
+                XOR     AX, AX
+MAH_RET:        POP     BX
+                RET
+MAP_ALL_HANDLES ENDP
+
+
+;
+; Duplicate inheritable file handles for a child process
+;
+; In:   SI      Pointer to source process table entry (parent)
+;       DI      Pointer to destination process table entry (child)
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  SI:PTR PROCESS
+                ASSUME  DI:PTR PROCESS
+INHERIT_HANDLES PROC    NEAR
+                MOV     BX, 0
+IH_LOOP:        MOV     AX, [SI].P_HANDLES[BX]  ; Get DOS handle
+                MOV     DX, [SI].P_HFLAGS[BX]   ; Get handle flags
+                TEST    DX, HF_NOINHERIT        ; Inherit?
+                JNZ     SHORT IH_NOINHERIT      ; No  -> skip
+                CMP     AX, NO_FILE_HANDLE      ; Valid handle?
+                JE      SHORT IH_SET            ; No  -> don't update ref count
+;
+; Update the reference count
+;
+                PUSH    BX
+                MOV     BX, AX
+                SHL     BX, 1
+                INC     DOS_REF_COUNT[BX]
+                POP     BX
+;
+; Update the process table entry of the child
+;
+IH_SET:         MOV     [DI].P_HANDLES[BX], AX
+                MOV     [DI].P_HFLAGS[BX], DX
+                JMP     SHORT IH_NEXT
+
+;
+; Don't inherit the file handle
+;
+IH_NOINHERIT:   MOV     AX, NO_FILE_HANDLE
+                MOV     DX, 0
+                JMP     SHORT IH_SET
+
+;
+; Process next file handle
+;
+IH_NEXT:        ADD     BX, 2
+                CMP     BX, 2 * MAX_FILES
+                JB      IH_LOOP
+;
+; Redirect stderr to stdout if the -e option is given
+;
+                TEST    [DI].P_FLAGS, PF_REDIR_STDERR ; Redirect stderr?
+                JE      SHORT IH_DONT_REDIR     ; No -> skip
+                MOV     AX, 1                   ; stdout
+                MOV     CX, 2                   ; stderr
+                MOV     BX, DI
+                CALL    DO_DUP2
+IH_DONT_REDIR:  RET
+                ASSUME  SI:NOTHING
+                ASSUME  DI:NOTHING
+INHERIT_HANDLES ENDP
+
+;
+; Close all open file handles of a process
+;
+; In:   BX      Pointer to process table entry
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+CLOSE_HANDLES   PROC    NEAR
+                PUSH    SI
+                MOV     SI, 0
+CH_LOOP:        MOV     AX, SI
+                CALL    DO_CLOSE
+                INC     SI
+                CMP     SI, MAX_FILES
+                JB      CH_LOOP
+                POP     SI
+                RET
+                ASSUME  BX:NOTHING
+CLOSE_HANDLES   ENDP
+
+;
+; Dump handle tables for debugging
+;
+              IF FALSE
+                ASSUME  DS:SV_DATA
+DUMP_HANDLES    PROC    NEAR
+                PUSHA
+                LEA     BX, PROCESS_TABLE
+                ASSUME  BX:PTR PROCESS
+                MOV     CL, 0
+DH_LOOP_PROC:   MOV     SI, 0
+                MOV     AL, "0"
+                CMP     CL, MAX_PROCESSES
+                JE      SHORT DH_PROC0
+                MOV     AL, CL
+                ADD     AL, "1"
+DH_PROC0:       CALL    OCHAR
+                MOV     Al, ":"
+                CALL    OCHAR
+                MOV     AL, " "
+                CALL    OCHAR
+DH_LOOP_HANDLE: MOV     AX, [BX].P_HANDLES[SI]
+                CMP     AX, NO_FILE_HANDLE
+                JE      SHORT DH_NO_HANDLE
+                AAM
+                XCHG    AL, AH
+                ADD     AL, "0"
+                CALL    OCHAR
+                XCHG    AL, AH
+                ADD     AL, "0"
+                CALL    OCHAR
+                JMP     SHORT DH_NEXT_HANDLE
+
+DH_NO_HANDLE:   MOV     AL, "-"
+                CALL    OCHAR
+                CALL    OCHAR
+DH_NEXT_HANDLE: MOV     AL, " "
+                CALL    OCHAR
+                ADD     SI, 2
+                CMP     SI, 2 * 24
+                JB      SHORT DH_LOOP_HANDLE
+                CALL    OCRLF
+                ADD     BX, SIZE PROCESS
+                INC     CL
+                CMP     CL, MAX_PROCESSES + 1   ; Include PROC0
+                JB      SHORT DH_LOOP_PROC
+                POPA
+                ASSUME  BX:NOTHING
+                RET
+DUMP_HANDLES    ENDP
+
+              ENDIF
+
+;
+; Check reference counts
+;
+                ASSUME  DS:SV_DATA
+CHECK_HANDLES   PROC    NEAR
+                PUSHF
+                PUSHA
+                MOV     AX, 0
+CH_LOOP_REF:    MOV     DX, 0
+                MOV     CX, MAX_PROCESSES + 1   ; Include PROC0
+                LEA     BX, PROCESS_TABLE
+                ASSUME  BX:PTR PROCESS
+CH_LOOP_PROC:   MOV     SI, 0
+CH_LOOP_HANDLE: CMP     AX, [BX].P_HANDLES[SI]
+                JNE     SHORT CH_NEXT_HANDLE
+                INC     DX
+CH_NEXT_HANDLE: ADD     SI, 2
+                CMP     SI, 2 * MAX_FILES
+                JB      SHORT CH_LOOP_HANDLE
+                ADD     BX, SIZE PROCESS
+                LOOP    CH_LOOP_PROC
+                MOV     DI, AX
+                SHL     DI, 1
+                CMP     DOS_REF_COUNT[DI], DX
+                JNE     SHORT CH_FAILURE
+                INC     AX
+                CMP     AX, TOTAL_FILES
+                JB      CH_LOOP_REF
+                ASSUME  BX:NOTHING
+CH_RET:         POPA
+                POPF
+                RET
+CH_FAILURE:     LEA     EDX, $CHECK_HANDLES
+                CALL    OTEXT
+                CALL    OCRLF
+                JMP     SHORT CH_RET
+CHECK_HANDLES   ENDP
+
+;
+; Call CHECK_HANDLES for -!1
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+MAYBE_CHECK_HANDLES PROC NEAR
+                TEST    TEST_FLAGS, TEST_CHECK_HANDLES
+                JZ      SHORT FIN
+                CALL    CHECK_HANDLES
+FIN:            RET
+MAYBE_CHECK_HANDLES ENDP
+
+
+;
+; Truncate a path name
+;
+; In:   ES:EDI          Pathname
+;       PROCESS_PTR     Pointer to process table entry
+;
+
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+TRUNCATE        PROC    NEAR
+                PUSHAD
+                PUSH    FS
+                MOV     BX, PROCESS_PTR         ; Get PTE of current process
+                CMP     BX, NO_PROCESS          ; Is there a current process?
+                JE      TRUNC_NO                ; No  -> do nothing
+                MOV     ECX, -1                 ; Drive letter unknown
+                MOV     AL, ES:[EDI]            ; Does the pathname start
+                CMP     AL, "/"                 ; with / or \ ?
+                JE      SHORT TRUNC_1           ; Yes -> look for special name
+                CMP     AL, "\"
+                JNE     SHORT TRUNC_CHECK       ; No  -> skip
+TRUNC_1:        MOV     AL, ES:[EDI+1]          ; Check for UNC pathname
+                CMP     AL, "/"
+                JE      SHORT TRUNC_UNC         ; Yes -> UNC
+                CMP     AL, "\"
+                JE      SHORT TRUNC_UNC         ; Yes -> UNC
+                LEA     BX, $DIR_DEV
+                CALL    DIR_CHECK               ; \dev\ ?
+                JZ      TRUNC_NO                ; Yes -> do nothing
+                LEA     BX, $DIR_PIPE           ; (TODO: This is DOS, not OS/2)
+                CALL    DIR_CHECK               ; \pipe\ ?
+                JZ      TRUNC_NO                ; Yes -> do nothing
+;
+; We have a pathname that starts with / or \ and is not special.  Prepend
+; the drive letter defined by the -r option, if -r is given.
+;
+                MOV     BX, PROCESS_PTR         ; Get PTE of current process
+                ASSUME  BX:PTR PROCESS
+                CMP     [BX].P_DRIVE, 0         ; Prepend drive?
+                JE      SHORT TRUNC_CHECK       ; No ->
+;
+; Prepend drive letter
+;
+                MOV     DL, [BX].P_DRIVE        ; Get drive letter (A-Z)
+                MOV     CL, DL
+                AND     ECX, 1FH                ; Bit for -t option
+                ASSUME  BX:NOTHING
+                MOV     DH, ":"                 ; Insert drive and colon
+                PUSH    EDI
+DRIVE_MOVE:     MOV     AL, DL                  ; Insert two bytes
+                XCHG    DL, ES:[EDI]
+                INC     EDI
+                XCHG    DL, DH
+                TEST    AL, AL
+                JNZ     SHORT DRIVE_MOVE
+                POP     EDI
+                JMP     SHORT TRUNC_CHECK
+
+;
+; It's a UNC pathname
+;
+TRUNC_UNC:      MOV     ECX, 0                  ; Check bit 0
+                JMP     SHORT TRUNC_CHECK
+
+;
+; Check if we should truncate the pathname.
+;
+TRUNC_CHECK:    MOV     BX, PROCESS_PTR         ; Get PTE of current process
+                ASSUME  BX:PTR PROCESS
+                CMP     [BX].P_TRUNC, 0         ; Never truncate?
+                JE      TRUNC_NO                ; Yes -> do nothing
+                CMP     [BX].P_TRUNC, -1        ; Always truncate?
+                JE      SHORT TRUNC_YES         ; Yes -> truncate
+                CMP     ECX, -1                 ; Drive known?
+                JNE     SHORT TRUNC_CHECK_2     ; Yes -> skip
+;
+; Try to get the drive letter from the pathname
+;
+                MOV     AL, ES:[EDI]
+                SUB     AL, "A"
+                CMP     AL, 26
+                JB      SHORT TRUNC_CHECK_1
+                MOV     AL, ES:[EDI]
+                SUB     AL, "a"
+                CMP     AL, 26
+                JAE     SHORT TRUNC_CURDISK
+TRUNC_CHECK_1:  CMP     BYTE PTR ES:[EDI+1], ":"
+                JE      SHORT TRUNC_PLUS1
+;
+; We don't know the drive letter -- use the current disk
+;
+TRUNC_CURDISK:  MOV     AH, 19H
+                INT     21H
+TRUNC_PLUS1:    MOV     CL, AL
+                INC     CL
+                AND     ECX, 1FH
+;
+; Check the bit specified by ECX
+;
+TRUNC_CHECK_2:  BT      [BX].P_TRUNC, ECX       ; Truncate for this drive?
+                JNC     SHORT TRUNC_NO          ; No  -> do nothing
+                ASSUME  BX:NOTHING
+TRUNC_YES:      PUSH    DS
+                MOV     ESI, EDI                ; Setup source pointer
+                MOV_FS_DS                       ; Access DBCS_LEAD_TAB with FS
+                ASSUME  FS:SV_DATA
+                MOV_DS_ES
+                ASSUME  DS:NOTHING
+                JMP     SHORT TRUNC_NAME        ; At start of name
+
+                TALIGN  4
+TRUNC_LOOP:     LODS    BYTE PTR DS:[ESI]       ; Fetch character
+                TEST    AL, AL                  ; End?
+                JE      SHORT TRUNC_END         ; Yes -> done
+                CMP     AL, ":"
+                JE      SHORT TRUNC_DIR
+                CMP     AL, "\"
+                JE      SHORT TRUNC_DIR
+                CMP     AL, "/"
+                JE      SHORT TRUNC_DIR
+                CMP     AL, "."
+                JE      SHORT TRUNC_EXT
+                MOV     AH, 0
+                BT      DBCS_LEAD_TAB, AX       ; DBCS lead byte?
+                JC      SHORT TRUNC_DBCS
+TRUNC_STORE:    TEST    CL, CL                  ; Beyond maximum length?
+                JZ      SHORT TRUNC_LOOP        ; Yes -> don't store
+                STOS    BYTE PTR ES:[EDI]       ; Store character
+                DEC     CL                      ; Adjust length counter
+                JMP     SHORT TRUNC_LOOP        ; Next character
+
+TRUNC_DBCS:     CMP     BYTE PTR DS:[ESI], 0    ; Invalid DBCS char?
+                JE      SHORT TRUNC_STORE       ; Yes -> store anyway
+                INC     ESI                     ; Skip 2nd byte
+                CMP     CL, 2                   ; Can we store 2 bytes?
+                JB      SHORT TRUNC_LOOP        ; No -> drop both bytes
+                STOS    BYTE PTR ES:[EDI]       ; Store 1st byte
+                MOV     AL, DS:[ESI-1]
+                STOS    BYTE PTR ES:[EDI]       ; Store 2nd byte
+                SUB     CL, 2                   ; Adjust length counter
+                JMP     SHORT TRUNC_LOOP        ; Next character
+
+TRUNC_DIR:      STOS    BYTE PTR ES:[EDI]       ; Store character
+TRUNC_NAME:     MOV     CX, 0008H               ; Extension not seen, 8 chars
+                JMP     SHORT TRUNC_LOOP        ; Next character
+
+TRUNC_EXT:      CMP     CX, 0103H               ; Previous character a dot?
+                JE      SHORT TRUNC_DOTS        ; Yes -> keep ".."
+                TEST    CH, CH                  ; Extension seen?
+                JNZ     SHORT TRUNC_STOP        ; Yes -> stop storing
+TRUNC_DOTS:     STOS    BYTE PTR ES:[EDI]       ; Store dot character
+                MOV     CX, 0103H               ; Extension seen, 3 characters
+                JMP     SHORT TRUNC_LOOP        ; Next character
+
+TRUNC_STOP:     MOV     CL, 0                   ; Don't store characters
+                JMP     SHORT TRUNC_LOOP        ; Next character
+
+TRUNC_END:      STOS    BYTE PTR ES:[EDI]
+                POP     DS
+TRUNC_NO:       POP     FS
+                POPAD
+                RET
+TRUNCATE        ENDP
+
+                ASSUME  FS:NOTHING
+
+                TALIGN  4
+DIR_CHECK       PROC    NEAR
+                PUSH    EDI
+DIR_CHECK_1:    INC     EDI
+                MOV     AL, ES:[EDI]
+                CMP     BYTE PTR [BX], 0
+                JE      SHORT DIR_CHECK_2
+                CALL    UPPER
+                CMP     AL, [BX]
+                JNE     SHORT DIR_CHECK_8
+                INC     BX
+                JMP     SHORT DIR_CHECK_1
+
+DIR_CHECK_2:    CMP     AL, "/"
+                JE      SHORT DIR_CHECK_8
+                CMP     AL, "\"
+DIR_CHECK_8:    POP     EDI
+                RET
+DIR_CHECK       ENDP
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Initialize the DOS_REF_COUNT table and the file handles of PROC0.
+;
+; To speed things up, assume that at most handles 0, 1, and 2 are
+; inherited.
+;
+                ASSUME  DS:SV_DATA
+INIT_FILEIO     PROC    NEAR
+;
+; Initially, no file is referenced.
+;
+                MOV     BX, 0
+IF_ZERO_REF:    MOV     DOS_REF_COUNT[BX], 0
+                ADD     BX, 2
+                CMP     BX, 2 * TOTAL_FILES
+                JB      IF_ZERO_REF
+;
+; Initialize the P_HANDLES array of PROC0, setting reference counts
+; as required.
+;
+                MOV     BX, 0                   ; File handle
+                MOV     DI, 0                   ; Index
+IF_LOOP:        MOV     PROC0.P_HFLAGS[DI], 0   ; Clear handle flags
+                MOV     AX, 4400H               ; Get device data
+                INT     21H
+                JC      SHORT IF_NOT_OPEN
+                MOV     PROC0.P_HANDLES[DI], BX
+                INC     DOS_REF_COUNT[DI]
+                JMP     SHORT IF_NEXT
+
+IF_NOT_OPEN:    MOV     PROC0.P_HANDLES[DI], NO_FILE_HANDLE
+IF_NEXT:        ADD     DI, 2
+                INC     BX
+                CMP     BX, MAX_FILES           ; File handles per process!
+                JB      SHORT IF_LOOP
+                RET
+INIT_FILEIO     ENDP
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/fileio.inc
===================================================================
--- trunk/src/emx/src/dos/fileio.inc	(revision 18)
+++ trunk/src/emx/src/dos/fileio.inc	(revision 18)
@@ -0,0 +1,46 @@
+;
+; FILEIO.INC -- Handle files and file handles
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_CODE         SEGMENT
+
+                EXTRN   DO_DUP:NEAR
+                EXTRN   DO_DUP2:NEAR
+                EXTRN   DO_CLOSE:NEAR
+                EXTRN   GET_HANDLE:NEAR
+                EXTRN   NEW_HANDLE:NEAR
+                EXTRN   MAP_HANDLE:NEAR
+                EXTRN   MAP_ALL_HANDLES:NEAR
+                EXTRN   INHERIT_HANDLES:NEAR
+                EXTRN   CLOSE_HANDLES:NEAR
+                EXTRN   CHECK_HANDLES:NEAR
+                EXTRN   TRUNCATE:NEAR           ; Truncate path name
+
+SV_CODE         ENDS
+
+INIT_CODE       SEGMENT
+
+                EXTRN   INIT_FILEIO:NEAR        ; Initialize file table
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/headers.inc
===================================================================
--- trunk/src/emx/src/dos/headers.inc	(revision 18)
+++ trunk/src/emx/src/dos/headers.inc	(revision 18)
@@ -0,0 +1,157 @@
+;
+; HEADERS.INC -- Header structures
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; emxbind header
+;
+BIND_HEADER     STRUC
+BND_SIGNATURE   BYTE    16 DUP (?)
+BND_BIND_FLAG   BYTE    FALSE
+BND_FILL_1      BYTE    ?
+BND_HDR_LOC     DWORD   ?
+BND_OPTIONS     BYTE    64 DUP (0)
+BIND_HEADER     ENDS
+
+;
+; EXE header
+;
+EXE1_HEADER     STRUC
+EXE_MAGIC       DW      ?
+EXE_LAST_PAGE   DW      ?
+EXE_PAGES       DW      ?
+EXE_RELOC_SIZE  DW      ?
+EXE_HDR_SIZE    DW      ?
+EXE_MIN_ALLOC   DW      ?
+EXE_MAX_ALLOC   DW      ?
+EXE_SS          DW      ?
+EXE_SP          DW      ?
+EXE_CHKSUM      DW      ?
+EXE_IP          DW      ?
+EXE_CS          DW      ?
+EXE_RELOC_PTR   DW      ?
+EXE_OVL         DW      ?
+EXE1_HEADER     ENDS
+
+;
+; Additional data of EXE header
+;
+EXE2_HEADER     STRUC
+EXE_RES1        DW      16 DUP (?)
+EXE_NEW_LO      DW      ?
+EXE_NEW_HI      DW      ?
+EXE2_HEADER     ENDS
+
+;
+; a.out header
+;
+A_OUT_HEADER    STRUC
+A_MAGIC         DW      ?
+A_MACHTYPE      DB      ?
+A_FLAGS         DB      ?
+A_TEXT_SIZE     DD      ?
+A_DATA_SIZE     DD      ?
+A_BSS_SIZE      DD      ?
+A_SYM_SIZE      DD      ?
+A_ENTRY         DD      ?
+A_TRSIZE        DD      ?
+A_DRSIZE        DD      ?
+A_OUT_HEADER    ENDS
+
+A_OUT_MAGIC     =       010BH
+A_OUT_OFFSET    =       0400H                   ; First page of code
+UMAGIC          =       010FH
+U_OFFSET        =       0400H                   ; First page of data
+KERNEL_U_ADDR   =       0E0000000H              ; Subtract this from U_AR0
+
+;
+; This structure that starts a core file
+;
+USER_AREA       STRUC
+U_MAGIC         DW      ?
+U_RESERVED1     DW      ?
+U_DATA_BASE     DD      ?
+U_DATA_END      DD      ?
+U_DATA_OFF      DD      ?
+U_HEAP_BASE     DD      ?
+U_HEAP_END      DD      ?
+U_HEAP_OFF      DD      ?
+U_HEAP_BRK      DD      ?
+U_STACK_BASE    DD      ?
+U_STACK_END     DD      ?
+U_STACK_OFF     DD      ?
+U_STACK_LOW     DD      ?
+U_AR0           DD      ?
+U_FPVALID       DB      ?
+U_RESERVED2     DB      3 DUP (?)
+U_FPSTATE       DD      27 DUP (?)
+U_FPSTATUS      DD      ?
+U_RESERVED3     DD      23 DUP (?)
+U_GS            DW      ?, 0
+U_FS            DW      ?, 0
+U_ES            DW      ?, 0
+U_DS            DW      ?, 0
+U_EDI           DD      ?
+U_ESI           DD      ?
+U_EBP           DD      ?
+U_ESP           DD      ?
+U_EBX           DD      ?
+U_EDX           DD      ?
+U_ECX           DD      ?
+U_EAX           DD      ?
+U_TRAPNO        DD      ?
+U_ERRCD         DD      ?
+U_EIP           DD      ?
+U_CS            DW      ?, 0
+U_EFL           DD      ?
+U_UESP          DD      ?
+U_SS            DW      ?, 0
+USER_AREA       ENDS
+
+U_REGS          EQU     U_GS
+
+L_FLAG_DLL      =       0001H                   ; Executable is a DLL
+L_FLAG_LINK386  =       0002H                   ; Linked by LINK386
+
+;
+; This table is at the beginning of the data section
+;
+LAYOUT_TABLE    STRUC
+L_TEXT_BASE     DD      ?
+L_TEXT_END      DD      ?
+L_DATA_BASE     DD      ?
+L_DATA_END      DD      ?
+L_BSS_BASE      DD      ?
+L_BSS_END       DD      ?
+L_HEAP_BASE     DD      ?
+L_HEAP_END      DD      ?
+L_HEAP_BRK      DD      ?
+L_HEAP_OFF      DD      ?
+L_OS2_DLL       DD      ?
+L_STACK_BASE    DD      ?
+L_STACK_END     DD      ?
+L_FLAGS         DD      ?
+L_RESERVED      DD      2 DUP (?)
+L_OPTIONS       DB      64 DUP (?)
+LAYOUT_TABLE    ENDS
Index: trunk/src/emx/src/dos/loader.asm
===================================================================
--- trunk/src/emx/src/dos/loader.asm	(revision 18)
+++ trunk/src/emx/src/dos/loader.asm	(revision 18)
@@ -0,0 +1,711 @@
+;
+; LOADER.ASM -- Load executable files
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE TABLES.INC
+                INCLUDE PAGING.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE MEMORY.INC
+                INCLUDE PMIO.INC
+                INCLUDE MISC.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE SYMBOLS.INC
+                INCLUDE DEBUG.INC
+                INCLUDE PMINT.INC
+                INCLUDE HEADERS.INC
+                INCLUDE OPTIONS.INC
+                INCLUDE ERRORS.INC
+                INCLUDE VERSION.INC
+
+                PUBLIC  LOADER
+
+HEADER_SIZE     =       SIZE A_OUT_HEADER
+              IF (SIZE EXE1_HEADER) GT HEADER_SIZE
+HEADER_SIZE     =       SIZE EXE1_HEADER
+              ENDIF
+
+SV_DATA         SEGMENT
+
+SYM_SIZE        DWORD   ?
+STR_SIZE        DWORD   ?
+TEXT_PAGE       DWORD   ?
+DATA_PAGE       DWORD   ?
+
+;
+; The file header (this buffer is used for different types of headers)
+;
+HDR_E           LABEL   EXE1_HEADER
+HDR_A           LABEL   A_OUT_HEADER
+HDR             BYTE    HEADER_SIZE DUP (?)
+
+;
+; The emxbind patch area
+;
+HDR_B           BIND_HEADER     <>
+
+;
+; The layout table (aka OS/2 patch area)
+;
+HDR_L           LAYOUT_TABLE    <>
+
+$CANT_OPEN      BYTE    "Cannot open program file", CR, LF, 0
+$CANT_READ      BYTE    "Cannot read program file", CR, LF, 0
+$INVALID_PROG   BYTE    "Invalid program file", CR, LF, 0
+$INVALID_VER    BYTE    "Wrong emx version", CR, LF, 0
+$LOADER_MEM     BYTE    "Out of memory", CR, LF, 0
+$INV_OPT        BYTE    "Invalid emx option", CR, LF, 0
+
+SV_DATA         ENDS
+
+
+
+SV_CODE         SEGMENT
+
+;
+; Load executable file, called by NEW_PROCESS
+;
+; In:   DI      Pointer to process entry
+;       AX:EDX  Pointer to file name
+;
+; Out:  AX      Return code (0:ok)
+;       EDX     Error message (for AX > 0)
+;
+
+                ASSUME  CS:SV_CODE, DS:SV_DATA
+
+                ASSUME  DI:PTR PROCESS
+LOADER          PROC    NEAR
+                CALL    L_OPEN                  ; Open the file
+                OR      AX, AX
+                JNZ     SHORT LOADER_RET
+                CALL    L_HEADER                ; Read header
+                OR      AX, AX
+                JNZ     SHORT LOADER_CLOSE
+                CALL    L_OPTIONS               ; Parse emx options
+                OR      AX, AX
+                JNZ     SHORT LOADER_CLOSE
+                CALL    L_LAYOUT                ; Compute memory layout
+                OR      AX, AX
+                JNZ     SHORT LOADER_CLOSE
+                CALL    L_VMEM                  ; Allocate virtual memory
+                OR      AX, AX
+                JNZ     SHORT LOADER_CLOSE
+                CALL    L_SYMBOLS               ; Load symbols
+                OR      AX, AX
+                JNZ     SHORT LOADER_CLOSE
+                CALL    L_PRELOAD               ; Preload
+                OR      AX, AX
+                JZ      SHORT LOADER_RET
+LOADER_CLOSE:   PUSH    AX
+                PUSH    EDX
+                MOV     BX, [DI].P_EXEC_HANDLE
+                CALL    CLOSE
+                POP     EDX
+                POP     AX
+LOADER_RET:     RET
+                ASSUME  DI:NOTHING
+
+;
+; Open the file
+;
+                ASSUME  DI:PTR PROCESS
+L_OPEN          PROC    NEAR
+                MOV     CL, 20H                 ; Deny write; read access
+                CALL    OPEN                    ; Open executable file
+                JC      SHORT L_OPEN_ERROR      ; Error -> fail
+                MOV     [DI].P_EXEC_HANDLE, AX  ; Save handle
+                MOV     BX, AX                  ; Return handle in BX
+                XOR     AX, AX                  ; No error
+                RET
+
+L_OPEN_ERROR:   MOV     AX, ENOENT              ; Return error code
+                LEA     EDX, $CANT_OPEN         ; and error message
+                RET
+                ASSUME  DI:NOTHING
+L_OPEN          ENDP
+
+
+;
+; Read the header
+;
+                ASSUME  DI:PTR PROCESS
+L_HEADER        PROC    NEAR
+                MOV     HDR_B.BND_OPTIONS[0], 0 ; This is for plain a.out files
+                XOR     EDX, EDX                ; Read header at location 0
+NEXT_HEADER:    MOV     [DI].P_EXEC_OFFSET, EDX ; Set offset
+                CALL    SEEK                    ; Move to header
+                MOV     ECX, SIZE HDR           ; Size of biggest header
+                LEA     EDX, HDR
+                MOV     AX, DS
+                CALL    READ                    ; Read header
+                JC      READ_ERROR              ; Error -> fail
+                JNZ     INVALID_PROG
+                CMP     HDR_E.EXE_MAGIC, 5A4DH  ; exe?
+                JNE     SHORT LH_10             ; No  -> not bound
+;
+; It's an exe file, which works only if it's a bound executable
+;
+                CMP     [DI].P_EXEC_OFFSET, 0   ; First header?
+                JNE     INVALID_PROG            ; No  -> error
+                MOVZX   EDX, HDR_E.EXE_HDR_SIZE ; Header size (paragraphs)
+                SHL     EDX, 4                  ; Header size (bytes)
+                CALL    SEEK                    ; Start of image
+                MOV     ECX, SIZE HDR_B
+                LEA     EDX, HDR_B
+                MOV     AX, DS
+                CALL    READ                    ; Read patch area
+                JC      READ_ERROR              ; Error -> fail
+                JNZ     INVALID_PROG
+                ASSUME  DI:NOTHING
+                PUSH    ES
+                PUSH    SI
+                PUSH    DI
+                MOV     AX, G_HDR_SEL
+                MOV     ES, AX
+                ASSUME  ES:HDR_SEG
+                XOR     DI, DI
+                LEA     SI, HDR_B               ; Compare signature and
+                MOV     CX, HDR_VERSION_LEN     ; version
+                CLD
+                REPE    CMPS BYTE PTR DS:[SI], BYTE PTR ES:[DI]
+                POP     DI
+                POP     SI
+                POP     ES
+                JE      SHORT SIG_OK            ; Match -> ok
+                MOV     AX, HDR_VERSION_LEN
+                SUB     AX, CX                  ; Length of common prefix + 1
+                CMP     AX, HDR_EMX_LEN
+                JBE     INVALID_PROG            ; Different signature -> fail
+;
+; Version check is disabled.  Leave checking the version to the C runtime
+; startup code, assuming that all DOS calls and system calls required for
+; checking the version and displaying the error message are supported by
+; all versions of emx.exe (or, vice versa: emx.exe supports the check done
+; by the startup code for all versions of the C runtime library).
+;
+;;;;            JMP     INVALID_VERSION         ; Different version -> fail
+
+                ASSUME  ES:NOTHING
+SIG_OK:         CMP     HDR_B.BND_BIND_FLAG, FALSE
+                JE      INVALID_PROG            ; Not bound ->
+                MOV     EDX, HDR_B.BND_HDR_LOC
+                JMP     NEXT_HEADER             ; Redo with next header
+
+;
+; Check for a.out header
+;
+                ASSUME  DI:PTR PROCESS
+LH_10:          CMP     HDR_A.A_MAGIC, A_OUT_MAGIC ; GNU a.out -z ?
+                JNE     INVALID_PROG            ; No  -> error
+                ADD     [DI].P_EXEC_OFFSET, A_OUT_OFFSET - 1000H
+                CMP     HDR_A.A_TEXT_SIZE, 0
+                JZ      INVALID_PROG
+                CMP     HDR_A.A_ENTRY, 10000H   ; Guard against old a.out files
+                JNE     INVALID_PROG
+;
+; Read the layout table, which is required for retrieving the brk
+; pointer of a dumped heap.  The layout table is located at the
+; beginning of the data segment.
+;
+                MOV     EDX, HDR_A.A_TEXT_SIZE
+                ADD     EDX, 0FFFH              ; Round
+                AND     EDX, NOT 0FFFH
+                ADD     EDX, [DI].P_EXEC_OFFSET
+                ADD     EDX, 1000H              ; See P_EXEC_OFFSET above
+                CALL    SEEK                    ; Move to layout table
+                MOV     ECX, SIZE HDR_L
+                LEA     EDX, HDR_L
+                MOV     AX, DS
+                CALL    READ                    ; Read header
+                JC      READ_ERROR              ; Error -> fail
+                JNZ     INVALID_PROG
+;
+; Check the layout table
+;
+                CMP     HDR_L.L_TEXT_BASE, 10000H
+                JNE     INVALID_PROG
+                MOV     AL, BYTE PTR HDR_L.L_FLAGS[3]
+                MOV     [DI].P_INTERFACE, AL    ; Set interface version
+                XOR     AX, AX                  ; No error
+                RET
+L_HEADER        ENDP
+
+;
+; Parse options.
+;
+;   1/ emxbind patch area
+;   2/ EMXOPT environment variable
+;   3/ command line (first process only)
+;
+L_OPTIONS       PROC    NEAR
+;
+; Process the emxbind patch area
+;
+                MOV_ES_DS
+                LEA     ESI, HDR_B.BND_OPTIONS
+                CALL    PM_OPTIONS
+                JC      SHORT LO_ERROR
+;
+;
+; Process the EMXOPT environment variable if present.
+;
+                MOV     AX, G_ENV_SEL
+                MOV     ES, AX
+                MOVZX   ESI, ENV_EMXOPT
+                OR      ESI, ESI
+                JZ      SHORT LO_10
+                CALL    PM_OPTIONS
+                JC      SHORT LO_ERROR
+;
+; Process the command line options.  Note that CMDL_OPTIONS[0] is
+; set to 0 after starting the first process.  That is, all processes
+; but the initial one ignore the command line options.
+;
+LO_10:          MOV_ES_DS
+                LEA     ESI, CMDL_OPTIONS
+                CALL    PM_OPTIONS
+                JC      SHORT LO_ERROR
+                XOR     AX, AX                  ; No error
+                RET
+
+LO_ERROR:       MOV     AX, ENOEXEC             ; Error:
+                LEA     EDX, $INV_OPT           ; Invalid emx option
+                RET
+L_OPTIONS       ENDP
+
+;
+; Compute the memory layout of the process
+;
+L_LAYOUT        PROC    NEAR
+                MOV     EAX, HDR_A.A_ENTRY
+                MOV     [DI].P_ENTRY_POINT, EAX ; Set entry point
+                MOV     [DI].P_TEXT_OFF, EAX
+                MOV     EAX, HDR_A.A_TEXT_SIZE
+                MOV     [DI].P_TEXT_SIZE, EAX   ; Set size of text segment
+                MOV     EAX, HDR_A.A_DATA_SIZE
+                MOV     [DI].P_DATA_SIZE, EAX
+                MOV     EAX, [DI].P_TEXT_OFF
+                ADD     EAX, HDR_A.A_TEXT_SIZE
+                DEC     EAX
+                AND     EAX, NOT 0FFFFH
+                ADD     EAX, 10000H
+                MOV     [DI].P_DATA_OFF, EAX
+;
+; Compute offset of bss segment
+;
+                ADD     EAX, HDR_A.A_DATA_SIZE
+                MOV     [DI].P_BSS_OFF, EAX
+;
+; Compute address of heap: If the heap is loaded from the executable,
+; use the heap base address and the brk pointer from the layout table.
+; Otherwise, put the heap after the BSS
+;
+                MOV     EAX, HDR_L.L_HEAP_BRK
+                OR      EAX, EAX                ; Preloaded heap?
+                JZ      SHORT LL_HEAP_1         ; No  ->
+                MOV     [DI].P_BRK, EAX
+                MOV     EAX, HDR_L.L_HEAP_BASE
+                MOV     [DI].P_INIT_BRK, EAX
+                JMP     SHORT LL_HEAP_9
+
+LL_HEAP_1:      MOV     EAX, [DI].P_BSS_OFF
+                ADD     EAX, HDR_A.A_BSS_SIZE
+                DEC     EAX                     ; Align to 64K
+                AND     EAX, NOT 0FFFFH
+                ADD     EAX, 10000H
+                MOV     [DI].P_BRK, EAX
+                MOV     [DI].P_INIT_BRK, EAX
+LL_HEAP_9:
+;
+; Compute address of stack
+;
+                MOV     EAX, [DI].P_INIT_BRK    ; Heap base address
+                AND     EAX, NOT 0FFFH
+                ADD     EAX, 1000H
+                ADD     EAX, [DI].P_STACK_SIZE
+                MOV     [DI].P_STACK_ADDR, EAX
+                MOV     [DI].P_DSEG_SIZE, EAX
+;
+; Compute page numbers
+;
+                MOV     ECX, 1
+                MOV     TEXT_PAGE, ECX
+                MOV     EAX, [DI].P_TEXT_SIZE
+                ADD     EAX, 0FFFH
+                SHR     EAX, 12
+                ADD     ECX, EAX
+                MOV     DATA_PAGE, ECX
+                MOV     EAX, [DI].P_DATA_SIZE
+                ADD     EAX, 0FFFH
+                SHR     EAX, 12
+                ADD     ECX, EAX
+                MOV     [DI].P_SYM_PAGE, ECX
+;
+; Set sizes of bss and symbols areas
+;
+                MOV     EAX, HDR_A.A_BSS_SIZE
+                MOV     [DI].P_BSS_SIZE, EAX
+                MOV     EAX, HDR_A.A_DRSIZE
+                ADD     EAX, HDR_A.A_TRSIZE
+                MOV     [DI].P_RELOC_SIZE, EAX
+                MOV     EAX, HDR_A.A_SYM_SIZE
+                MOV     SYM_SIZE, EAX
+                MOV     STR_SIZE, 0
+;
+; ...
+;
+                MOV     [DI].P_LAST_PAGE, 0
+                OR      EAX, EAX
+                JZ      SHORT LL_29
+                CMP     STEP_FLAG, FALSE
+                JE      SHORT LL_29
+                MOV     EDX, [DI].P_SYM_PAGE
+                SHL     EDX, 12
+                ADD     EDX, [DI].P_EXEC_OFFSET
+                ADD     EDX, [DI].P_RELOC_SIZE
+                ADD     EDX, EAX                ; EAX=SYM_SIZE
+                CALL    SEEK
+                JC      INVALID_PROG
+                PUSH    ECX
+                LEA     EDX, STR_SIZE
+                MOV     AX, DS
+                MOV     ECX, 4
+                CALL    READ
+                POP     ECX
+                JC      READ_ERROR
+                JNZ     INVALID_PROG
+                MOV     EAX, SYM_SIZE
+                ADD     EAX, STR_SIZE
+                MOV     EDX, EAX
+                ADD     EAX, 0FFFH
+                SHR     EAX, 12
+                ADD     EAX, [DI].P_SYM_PAGE
+                DEC     EAX                     ; Number of last page
+                AND     EDX, 0FFFH              ; Complete page?
+                JZ      SHORT LL_29             ; Yes -> skip
+                MOV     [DI].P_LAST_PAGE, EAX   ; Special handling of
+                MOV     [DI].P_LAST_BYTES, DX   ; last page
+LL_29:          XOR     AX, AX                  ; No error
+                RET
+                ASSUME  DI:NOTHING
+L_LAYOUT        ENDP
+
+
+;
+; Prepare page tables for virtual memory
+;
+                ASSUME  DI:PTR PROCESS
+L_VMEM          PROC    NEAR
+;
+; Check parameters
+;
+                TEST    [DI].P_STACK_SIZE, 0FFFH
+                JNZ     INVALID_PROG
+                TEST    [DI].P_STACK_ADDR, 0FFFH
+                JNZ     INVALID_PROG
+                TEST    [DI].P_TEXT_OFF, 0FFFH
+                JNZ     INVALID_PROG
+                TEST    [DI].P_DATA_OFF, 0FFFH
+                JNZ     INVALID_PROG
+                MOV     EAX, [DI].P_TEXT_OFF
+                MOV     ECX, [DI].P_TEXT_SIZE
+                ADD     EAX, ECX
+                ADD     EAX, 0FFFH
+                AND     EAX, NOT 0FFFH
+                CMP     EAX, [DI].P_DATA_OFF
+                JA      INVALID_PROG
+;
+; Allocate linear address space and initialize page tables
+;
+                MOV     EAX, [DI].P_DSEG_SIZE   ; Add 1.5 MB for __memaccess
+                ADD     EAX, 180000H            ; and ADD_PAGES
+                MOV     [DI].P_LIN_SIZE, EAX
+                ADD     EAX, [DI].P_DATA_OFF
+                MOV     ECX, EAX                ; Combined size
+                MOV     AL, [DI].P_PIDX         ; Get process index
+                CALL    ALLOC_PAGES
+                MOV     [DI].P_LINEAR, EAX
+                CALL    INIT_PAGES
+                JC      OUT_OF_MEM
+;
+; SRC_EXEC pages (code)
+;
+                MOV     EAX, [DI].P_TEXT_OFF
+                ADD     EAX, [DI].P_LINEAR
+                MOV     ECX, [DI].P_TEXT_SIZE
+                ADD     ECX, 0FFFH
+                SHR     ECX, 12
+                MOV     EBX, PAGE_USER          ; Page table entry
+                MOV     EDX, TEXT_PAGE
+                SHL     EDX, 12
+                OR      EDX, SRC_EXEC           ; Swap table entry
+                MOV     DL, [DI].P_PIDX         ; PIDX
+                CALL    SET_PAGES
+                MOV     EBX, [DI].P_LINEAR
+                MOV     ECX, [DI].P_TEXT_OFF
+                ADD     ECX, [DI].P_TEXT_SIZE
+                TEST    [DI].P_HW_ACCESS, HW_ACCESS_CODE ; Data executable?
+                JZ      SHORT TEXT_EXEC         ; No  -> restrict CS to .text
+                MOV     ECX, [DI].P_DSEG_SIZE   ; Big code segment, with stack
+TEXT_EXEC:      MOV     SI, [DI].P_LDT_PTR
+                ADD     SI, L_CODE_SEL AND NOT 07H
+                MOV     AX, A_CODE32 OR DPL_3
+                CALL    CREATE_SEG
+
+                MOV     ECX, [DI].P_DSEG_SIZE
+                MOV     EAX, [DI].P_LINEAR
+                ADD     EAX, [DI].P_DATA_OFF
+                SUB     ECX, [DI].P_DATA_OFF
+                ADD     ECX, 0FFFH
+                SHR     ECX, 12
+                MOV     EBX, 000H               ; Page table entry
+                MOV     EDX, 000H               ; Swap table entry
+                CALL    SET_PAGES               ; Inaccessible
+
+;
+; SRC_NONE pages (stack)
+;
+                MOV     EAX, [DI].P_STACK_ADDR
+                ADD     EAX, [DI].P_LINEAR
+                MOV     ECX, [DI].P_STACK_SIZE
+                SUB     EAX, ECX
+                SHR     ECX, 12
+                MOV     EBX, PAGE_WRITE OR PAGE_USER
+                MOV     EDX, SRC_NONE           ; SRC
+                TEST    [DI].P_FLAGS, PF_DONT_ZERO
+                JNZ     SHORT LV_04
+                MOV     EDX, SRC_ZERO           ; Swap table entry
+LV_04:          MOV     DL, [DI].P_PIDX         ; PIDX
+                CALL    SET_PAGES               ; Stack
+;
+; Commit stack pages
+;
+                TEST    [DI].P_FLAGS, PF_COMMIT
+                JZ      SHORT LV_09
+                MOV     ECX, [DI].P_COMMIT_SIZE
+                ADD     ECX, 4*4096
+                CMP     ECX, [DI].P_STACK_SIZE
+                JB      SHORT LV_05
+                MOV     ECX, [DI].P_STACK_SIZE
+LV_05:          MOV     EAX, [DI].P_STACK_ADDR
+                ADD     EAX, [DI].P_LINEAR
+                SUB     EAX, ECX
+                SHR     ECX, 12
+                CALL    SET_COMMIT              ; Set PAGE_ALLOC bit
+                CALL    SET_PAGES
+                JC      OUT_OF_MEM
+LV_09:
+;
+; SRC_ZERO pages (bss)
+;
+                MOV     EAX, [DI].P_BSS_OFF
+                ADD     EAX, [DI].P_LINEAR
+                MOV     ECX, [DI].P_BSS_SIZE
+                JECXZ   LV_11
+                ADD     ECX, EAX
+                DEC     ECX
+                SHR     ECX, 12                 ; Last bss page
+                MOV     EDX, EAX
+                SHR     EDX, 12                 ; First bss page
+                SUB     ECX, EDX
+                INC     ECX
+                MOV     EBX, PAGE_WRITE OR PAGE_USER ; Page table entry
+                MOV     EDX, SRC_ZERO           ; Swap table entry
+                MOV     DL, [DI].P_PIDX         ; PIDX
+                CALL    SET_COMMIT              ; Set PAGE_ALLOC bit
+                CALL    SET_PAGES               ; Stack
+                JC      OUT_OF_MEM              ; ...deallocate memory
+LV_11:
+
+;
+; SRC_EXEC pages (data)
+;
+                MOV     EAX, [DI].P_DATA_OFF
+                ADD     EAX, [DI].P_LINEAR
+                MOV     ECX, [DI].P_DATA_SIZE
+                ADD     ECX, 0FFFH
+                SHR     ECX, 12
+                MOV     EBX, PAGE_WRITE OR PAGE_USER
+                MOV     EDX, DATA_PAGE
+                SHL     EDX, 12
+                OR      EDX, SRC_EXEC
+                MOV     DL, [DI].P_PIDX         ; PIDX
+                CALL    SET_COMMIT              ; Set PAGE_ALLOC bit
+                CALL    SET_PAGES
+                JC      OUT_OF_MEM              ; ...deallocate memory
+
+                MOV     EBX, [DI].P_LINEAR
+                MOV     ECX, [DI].P_DSEG_SIZE
+                MOV     SI, [DI].P_LDT_PTR
+                ADD     SI, L_DATA_SEL AND NOT 07H
+                MOV     AX, A_DATA32 OR DPL_3
+                CALL    CREATE_SEG
+                CALL    CLEAR_TLB
+                XOR     AX, AX
+                RET
+                ASSUME  DI:NOTHING
+L_VMEM          ENDP
+
+;
+; Load symbols
+;
+                ASSUME  DI:PTR PROCESS
+L_SYMBOLS       PROC    NEAR
+                CMP     STEP_FLAG, FALSE        ; Debugging?
+                JE      SHORT L_SYMBOLS_RET     ; No -> done
+                MOV     EAX, SYM_SIZE
+                OR      EAX, EAX
+                JZ      SHORT L_SYMBOLS_RET
+                MOV     [DI].P_STR_OFF, EAX
+                XOR     EDX, EDX
+                MOV     EBX, SIZE NLIST
+                DIV     EBX
+                MOV     [DI].P_SYMBOLS, EAX
+                MOV     ECX, SYM_SIZE
+                ADD     ECX, STR_SIZE
+                MOV     AL, [DI].P_PIDX         ; Get process index
+                CALL    ALLOC_PAGES
+                CALL    INIT_PAGES
+                JC      OUT_OF_MEM
+                MOV     EBX, PAGE_USER          ; Read only
+                MOV     EDX, [DI].P_SYM_PAGE
+                SHL     EDX, 12
+                OR      EDX, SRC_EXEC           ; SRC
+                MOV     DL, [DI].P_PIDX         ; PIDX
+                CALL    SET_PAGES
+                MOV     ECX, SYM_SIZE
+                ADD     ECX, STR_SIZE
+                MOV     EBX, EAX
+                MOV     SI, [DI].P_LDT_PTR
+                ADD     SI, L_SYM_SEL AND NOT 07H
+                MOV     AX, A_READ32 OR DPL_3
+                CALL    CREATE_SEG
+                CALL    CLEAR_TLB
+L_SYMBOLS_RET:  XOR     AX, AX
+                RET
+                ASSUME  DI:NOTHING
+L_SYMBOLS       ENDP
+
+
+;
+; Preload code and initialized data
+;
+                ASSUME  DI:PTR PROCESS
+L_PRELOAD       PROC    NEAR
+                TEST    [DI].P_FLAGS, PF_PRELOAD; Preloading disabled?
+                JNZ     L_PRELOAD_RET           ; Yes -> return
+                CALL    PM_AVAIL                ; Number of available pages
+                MOV     EDX, EAX                ; of memory
+                MOV     EAX, [DI].P_DATA_OFF
+                ADD     EAX, [DI].P_DATA_SIZE
+                ADD     EAX, 0FFFH              ; Number of pages required
+                SHR     EAX, 12
+                CMP     EAX, EDX                ; Enough memory?
+                JA      L_PRELOAD_RET           ; No  -> don't preload
+                OR      [DI].P_FLAGS, PF_PRELOADING     ; Preloading...
+                MOV     BX, [DI].P_EXEC_HANDLE  ; Get file handle
+                .386P
+                SLDT    AX
+                PUSH    AX                      ; Save LDTR
+                LLDT    [DI].P_LDT              ; Switch to new process
+                .386
+;
+; Preload code
+;
+                MOV     EDX, TEXT_PAGE
+                SHL     EDX, 12
+                ADD     EDX, [DI].P_EXEC_OFFSET ; Get location of image
+                CALL    SEEK                    ; Seek to code segment
+                JC      SHORT L_PRELOAD_ERR
+                MOV     ECX, [DI].P_TEXT_SIZE   ; Size of code
+                MOV     EDX, [DI].P_TEXT_OFF    ; Destination address
+                MOV     AX, L_DATA_SEL
+                CALL    READ                    ; Read image
+                JC      SHORT L_PRELOAD_ERR
+                JNZ     SHORT L_PRELOAD_ERR
+                MOV     EAX, [DI].P_TEXT_OFF
+                ADD     EAX, [DI].P_LINEAR
+                MOV     ECX, [DI].P_TEXT_SIZE
+                ADD     ECX, 0FFFH
+                SHR     ECX, 12
+                CALL    CLEAR_DIRTY
+;
+; Preload data
+;
+                MOV     EDX, DATA_PAGE
+                SHL     EDX, 12
+                ADD     EDX, [DI].P_EXEC_OFFSET ; Get location of image
+                CALL    SEEK                    ; Seek to data segment
+                JC      SHORT L_PRELOAD_ERR
+                MOV     ECX, [DI].P_DATA_SIZE   ; Size of data
+                MOV     EDX, [DI].P_DATA_OFF    ; Destination address
+                MOV     AX, L_DATA_SEL
+                CALL    READ                    ; Read image
+                JC      SHORT L_PRELOAD_ERR
+                JNZ     SHORT L_PRELOAD_ERR
+                MOV     EAX, [DI].P_DATA_OFF
+                ADD     EAX, [DI].P_LINEAR
+                MOV     ECX, [DI].P_DATA_SIZE
+                ADD     ECX, 0FFFH
+                SHR     ECX, 12
+                CALL    CLEAR_DIRTY
+                XOR     AX, AX                  ; NC, ZR
+L_PRELOAD_ERR:  POP     AX
+                .386P
+                LLDT    AX                      ; Restore LDT
+                .386
+                JC      SHORT READ_ERROR
+                JNZ     SHORT INVALID_PROG
+                AND     [DI].P_FLAGS, NOT PF_PRELOADING ; End of preloading
+L_PRELOAD_RET:  XOR     AX, AX                  ; No error
+                RET
+                ASSUME  DI:NOTHING
+L_PRELOAD       ENDP
+
+
+READ_ERROR::    MOV     AX, ENOEXEC
+                LEA     EDX, $CANT_READ
+                RET
+
+INVALID_PROG::  MOV     AX, ENOEXEC
+                LEA     EDX, $INVALID_PROG
+                RET
+
+INVALID_VERSION::
+                MOV     AX, ENOEXEC
+                LEA     EDX, $INVALID_VER
+                RET
+
+OUT_OF_MEM::    MOV     AX, ENOMEM
+                LEA     EDX, $LOADER_MEM
+                RET
+
+LOADER          ENDP
+
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/loader.inc
===================================================================
--- trunk/src/emx/src/dos/loader.inc	(revision 18)
+++ trunk/src/emx/src/dos/loader.inc	(revision 18)
@@ -0,0 +1,34 @@
+;
+; LOADER.INC -- Load executable files
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_DATA         SEGMENT
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                EXTRN   LOADER:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/makefile
===================================================================
--- trunk/src/emx/src/dos/makefile	(revision 18)
+++ trunk/src/emx/src/dos/makefile	(revision 18)
@@ -0,0 +1,205 @@
+#
+# /emx/src/dos/makefile
+#
+# Copyright (c) 1991-1999 by Eberhard Mattes
+#
+# This file is part of emx.
+#
+# emx is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emx is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emx; see the file COPYING.  If not, write to
+# the Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+# See emx.asm for a special exception.
+#
+
+.SUFFIXES: .obj .asm
+
+MLOPT=
+LINKOPT=
+BIN=.\ #
+
+ML=ml -c -Cp -W3 -WX -VM -nologo $(MLOPT)
+
+.asm.obj:
+	$(ML) $<
+
+default:	all
+all:		emx emxd emxl
+emx:		$(BIN)emx.exe
+emxd:		$(BIN)emxd.exe
+emxl:		$(BIN)emxl.exe
+
+debug:
+		@$(MAKE) $(MAKEFLAGS) /NOLOGO MLOPT=-Zi LINKOPT=/CO
+
+a20.obj:	a20.asm a20.inc emx.inc xms.inc vcpi.inc \
+		options.inc
+
+core.obj:	core.asm emx.inc oprint.inc headers.inc \
+		core.inc pmint.inc signal.inc process.inc
+
+debug.obj:	debug.asm emx.inc except.inc oprint.inc utils.inc \
+		pmio.inc disasm.inc segments.inc symbols.inc \
+		process.inc paging.inc tables.inc pmint.inc \
+		signal.inc debug.inc swapper.inc fileio.inc
+
+disasm.obj:	disasm.asm emx.inc symbols.inc
+
+dpmi.obj:	dpmi.asm emx.inc rprint.inc misc.inc vcpi.inc
+
+emx.obj:	emx.asm emx.inc oprint.inc tables.inc \
+		paging.inc a20.inc segments.inc pmio.inc \
+		memory.inc process.inc vprint.inc swapper.inc \
+		except.inc rmint.inc debug.inc options.inc \
+		version.inc vcpi.inc signal.inc pmint.inc \
+		loader.inc xms.inc rprint.inc headers.inc \
+		termio.inc fileio.inc utils.inc
+
+emxl.obj:	emxl.asm emx.inc headers.inc version.inc
+
+errors.obj:     errors.asm emx.inc errors.inc pmint.inc signal.inc \
+		process.inc
+
+except.obj:	except.asm emx.inc except.inc vprint.inc \
+		swapper.inc debug.inc oprint.inc pmio.inc \
+		pmint.inc tables.inc process.inc signal.inc \
+		misc.inc core.inc
+
+extapi.obj:	extapi.asm emx.inc pmint.inc
+
+fileio.obj:	fileio.asm emx.inc signal.inc process.inc swapper.inc \
+		errors.inc options.inc oprint.inc pmint.inc utils.inc
+
+loader.obj:	loader.asm emx.inc tables.inc paging.inc \
+		misc.inc signal.inc segments.inc pmio.inc \
+		memory.inc process.inc symbols.inc debug.inc \
+		headers.inc pmint.inc options.inc errors.inc \
+		version.inc
+
+memory.obj:	memory.asm emx.inc swapper.inc vcpi.inc \
+		xms.inc memory.inc rprint.inc rmint.inc \
+                paging.inc segments.inc misc.inc oprint.inc options.inc
+
+ndebug.obj:	ndebug.asm emx.inc debug.inc pmint.inc
+
+oprint.obj:	oprint.asm emx.inc signal.inc process.inc
+
+options.obj:	options.asm emx.inc memory.inc a20.inc except.inc \
+		pmio.inc debug.inc process.inc rprint.inc xms.inc \
+		signal.inc misc.inc version.inc loader.inc
+
+paging.obj:	paging.asm emx.inc oprint.inc memory.inc \
+		vcpi.inc tables.inc segments.inc paging.inc \
+		misc.inc swapper.inc
+
+pmint.obj:	pmint.asm emx.inc vprint.inc tables.inc extapi.inc \
+		vcpi.inc process.inc oprint.inc paging.inc \
+		syscall.inc pmint.inc rprint.inc a20.inc profil.inc \
+		debug.inc segments.inc misc.inc signal.inc \
+		rmint.inc core.inc termio.inc options.inc utils.inc \
+		stat.inc except.inc fileio.inc errors.inc
+
+pmio.obj:	pmio.asm emx.inc signal.inc process.inc
+
+process.obj:	process.asm emx.inc loader.inc process.inc errors.inc \
+		signal.inc tables.inc segments.inc pmint.inc profil.inc \
+		pmio.inc paging.inc fileio.inc misc.inc utils.inc
+
+profil.obj:     profil.asm emx.inc process.inc signal.inc profil.inc \
+		pmint.inc errors.inc
+
+ptrace.obj:	ptrace.asm emx.inc pmint.inc signal.inc process.inc \
+		debug.inc headers.inc errors.inc
+
+rmint.obj:	rmint.asm emx.inc vcpi.inc rmint.inc \
+		tables.inc pmint.inc except.inc rprint.inc \
+		misc.inc signal.inc process.inc options.inc
+
+rprint.obj:	rprint.asm emx.inc rprint.inc
+
+segments.obj:	segments.asm emx.inc tables.inc paging.inc \
+		segments.inc misc.inc signal.inc process.inc
+
+signal.obj:	signal.asm emx.inc pmint.inc rmint.inc misc.inc errors.inc \
+                signal.inc process.inc except.inc oprint.inc core.inc
+
+swapper.obj:	swapper.asm emx.inc pmio.inc except.inc \
+		oprint.inc segments.inc paging.inc memory.inc \
+		pmint.inc process.inc tables.inc signal.inc \
+		debug.inc
+
+symbols.obj:	symbols.asm symbols.inc emx.inc process.inc \
+		signal.inc
+
+syscall.obj:	syscall.asm emx.inc process.inc paging.inc vprint.inc \
+		segments.inc pmint.inc tables.inc loader.inc fileio.inc \
+		except.inc swapper.inc signal.inc errors.inc vcpi.inc \
+		xms.inc memory.inc misc.inc core.inc timeb.inc version.inc \
+		termio.inc stat.inc ulimit.inc profil.inc utils.inc
+
+tables.obj:	tables.asm emx.inc tables.inc process.inc \
+		pmint.inc misc.inc headers.inc signal.inc \
+		except.inc
+
+termio.obj:	termio.asm emx.inc signal.inc process.inc \
+		termio.inc errors.inc
+
+utils.obj:	utils.asm emx.inc
+
+vcpi.obj:	vcpi.asm emx.inc tables.inc pmint.inc \
+		paging.inc misc.inc rprint.inc memory.inc \
+		segments.inc oprint.inc
+
+vprint.obj:	vprint.asm emx.inc tables.inc vprint.inc
+
+xms.obj:	xms.asm xms.inc emx.inc memory.inc \
+		rprint.inc vcpi.inc options.inc
+
+EMXOBJ1 =	emx.obj tables.obj loader.obj oprint.obj utils.obj
+EMXOBJ2 =	segments.obj paging.obj pmio.obj memory.obj ptrace.obj
+EMXOBJ3 =	profil.obj process.obj vprint.obj swapper.obj except.obj
+EMXOBJ4 =	extapi.obj rmint.obj vcpi.obj syscall.obj signal.obj
+EMXOBJ5 =	fileio.obj pmint.obj rprint.obj dpmi.obj symbols.obj
+EMXOBJ6 =	errors.obj xms.obj a20.obj core.obj termio.obj options.obj
+EMXDEP =	$(EMXOBJ1) $(EMXOBJ2) $(EMXOBJ3) $(EMXOBJ4) $(EMXOBJ5) \
+		$(EMXOBJ6) emx.lnk
+
+emx.lnk:	makefile
+	@echo $(EMXOBJ1) + >emx.lnk
+	@echo $(EMXOBJ2) + >>emx.lnk
+	@echo $(EMXOBJ3) + >>emx.lnk
+	@echo $(EMXOBJ4) + >>emx.lnk
+	@echo $(EMXOBJ5) + >>emx.lnk
+	@echo $(EMXOBJ6) + >>emx.lnk
+
+$(BIN)emx.exe:	$(EMXDEP) ndebug.obj
+	link @emx.lnk ndebug, $(BIN)emx, emx /cp:1 /map $(LINKOPT);
+
+$(BIN)emxd.exe: $(EMXDEP) debug.obj disasm.obj
+	link @emx.lnk debug disasm, $(BIN)emxd, emxd /cp:1 /map $(LINKOPT);
+
+$(BIN)emxl.exe: emxl.obj
+	link emxl, $(BIN)emxl, emxl /cp:1 /map $(LINKOPT);
+
+clean:
+	-del *.obj
+	-del *.map
+	-del emx.lnk
+
+realclean:
+	-del $(BIN)emx.exe
+	-del $(BIN)emxd.exe
+	-del $(BIN)emxl.exe
+
+# End of /emx/src/dos/makefile
Index: trunk/src/emx/src/dos/memory.asm
===================================================================
--- trunk/src/emx/src/dos/memory.asm	(revision 18)
+++ trunk/src/emx/src/dos/memory.asm	(revision 18)
@@ -0,0 +1,940 @@
+;
+; MEMORY.ASM -- Manage memory
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__MEMORY        =       1
+                INCLUDE EMX.INC
+                INCLUDE SWAPPER.INC
+                INCLUDE VCPI.INC
+                INCLUDE XMS.INC
+                INCLUDE MEMORY.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE PAGING.INC
+                INCLUDE RPRINT.INC
+                INCLUDE OPRINT.INC
+                INCLUDE RMINT.INC
+                INCLUDE OPTIONS.INC
+                INCLUDE MISC.INC
+
+                PUBLIC  LOMEM_HEAD_PHYS, HIMEM_HEAD_PHYS, DISABLE_EXT_MEM
+                PUBLIC  HIMEM_COUNT, HIMEM_TAB, VDISK_FLAG, TAVAIL
+                PUBLIC  DISABLE_LOW_MEM
+                PUBLIC  PM_ALLOC, PM_ALLOC_NOSWAP, INIT_HIMEM, PM_AVAIL
+                PUBLIC  RM_ALLOC, INIT_MEMORY, CLEANUP_MEMORY, INIT_MEM_PHYS
+
+
+DEBUG_EXT_MEM   =       FALSE
+DEBUG_LOW_MEM   =       FALSE
+
+;
+; This data structure should fit into one paragraph (16 bytes). The first
+; paragraph of any block allocated from DOS memory will contain this
+; structure. The fields are used for allocating pages in real mode (or
+; virtual mode). When no more pages are required, the blocks will either
+; be converted into a linked list of pages for allocating in protected mode
+; or shrunk to the size used to save low memory, allowing executing DOS
+; programs.
+;
+RM_BLOCK_HEADER STRUCT
+RBH_NEXT        DW      ?               ; Segment address of next block
+RBH_PAGE        DW      ?               ; Segment of next free page
+RBH_MAX         DW      ?               ; Maximum number of pages
+RBH_FREE        DW      ?               ; Number of free pages
+RM_BLOCK_HEADER ENDS
+
+                .ERRE   SIZE RM_BLOCK_HEADER LE 16
+
+SV_DATA         SEGMENT
+
+LOMEM_HEAD_PHYS LABEL   DWORD           ; Physical address of LOMEM_HEAD
+                DW      LOMEM_HEAD, 0
+
+HIMEM_HEAD_PHYS LABEL   DWORD           ; Physical address of HIMEM_HEAD
+                DW      HIMEM_HEAD, 0
+
+                DALIGN  16              ; Real-mode offset is 0!
+LOMEM_HEAD      MEMORY_BLOCK    <>
+
+                DALIGN  16              ; Real-mode offset is 0!
+HIMEM_HEAD      MEMORY_BLOCK    <>
+
+                DALIGN  16              ; Real-mode offset is 0!
+BLOCKS_HEAD     DW      NULL_RM         ; Head of linked list of memory blocks
+
+EXT_1K_BLOCKS   DW      ?               ; Extended memory (1K blocks)
+DISABLE_EXT_MEM DB      FALSE           ; Don't use memory above 1M: off
+DISABLE_LOW_MEM DB      FALSE           ; Don't use memory below 1M: off
+INT15_HOOKED    DB      FALSE
+VDISK_FLAG      DB      FALSE           ; VDISK 3.3 detected: no
+
+                DALIGN  2
+HIMEM_COUNT     DW      0               ; Total number of entries
+HIMEM_TAB       HIMEM_ENTRY HIMEM_MAX DUP (<>)
+
+HIMEM_AVAIL_COUNT       DW      0       ; Entries remaining for allocation
+HIMEM_AVAIL_START       DW      0       ; Pointer to first available entry
+
+EXT_START       EQU     HIMEM_TAB[0].HM_ADDR
+EXT_SIZE        EQU     HIMEM_TAB[0].HM_SIZE
+
+                DALIGN  2
+BLOCK_MOVE_GDT  DQ      0               ; null
+BM_GDT          DD      ?, ?            ; GDT
+BM_SRC          DD      ?, ?            ; source
+BM_DST          DD      ?, ?            ; destination
+BM_BIOS         DD      ?, ?            ; BIOS code segment
+BM_STACK        DD      ?, ?            ; stack
+
+                DALIGN  2
+VDISK_BOOT      DB      3 DUP (?)       ; jump
+VDISK_NAME      DB      8 DUP (?)       ; name
+                DB      19 DUP (?)      ; BPB
+VDISK_NEXT      DW      ?               ; First free byte (1K increments)
+                DALIGN  2               ; Make size even (move words!)
+VDISK_WORDS     =       (THIS BYTE - VDISK_BOOT)/2
+
+VDISK_ANY       DB      "VDISK"
+VDISK_33_LABEL  DB      "VDISK  V3.3"
+VDISK_33_BOOT   DB      "VDISK3.3"
+
+VDISK_DRIVER    STRUC
+VD_NEXT         DD      ?
+VD_ADDR         DW      ?
+VD_STRATEGY     DW      ?
+VD_INTERRUPT    DW      ?
+VD_DEV_NAME     DB      8 DUP (?)       ; First byte: number of block devices
+VD_VOL_NAME     DB      11 DUP (?)      ; Volume label
+VD_VOL_ATTR     DB      ?
+VD_VOL_RES      DB      10 DUP (?)
+VD_VOL_TIME     DW      ?
+VD_VOL_DATE     DW      ?
+VD_AVAIL_LO     DW      ?
+VD_AVAIL_HI     DB      ?
+VDISK_DRIVER    ENDS
+
+                DALIGN  4
+TAVAIL          DD      ?                       ; Number of available pages
+
+;
+; Messages
+;
+$VDISK_ERROR    DB      "Unsupported VDISK.SYS version", CR, LF, 0
+
+              IF DEBUG_MEM
+$MEMI1          DB      "Address=", 0
+$MEMI2          DB      " size=", 0
+              ENDIF
+
+              IF DEBUG_EXT_MEM
+$NO_VDISK       DB      "No VDISK found", CR, LF, 0
+$VDISK1         DB      "VDISK found, next=", 0
+$VDISK2         DB      "INT 19H: next=", 0
+$EXT_MEM        DB      " 1K pages of extended memory", CR, LF, 0
+$EXT_START      DB      "Use extended memory at ", 0
+$EXT_SIZE       DB      "Size=", 0
+              ENDIF
+
+              IF DEBUG_LOW_MEM
+$RM_ALLOC_1     DB      "RM_ALLOC(", 0
+$RM_ALLOC_2     DB      ")=", 0
+$INIT_MEM_1     DB      "INIT_MEM: seg=", 0
+$INIT_MEM_2     DB      ", len=", 0
+              ENDIF
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Allocate 4096 bytes of memory (either high or low memory, swap out a
+; page if required)
+;
+; Out:  EAX     Physical address or NULL_PHYS if out of memory
+;
+
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+PM_ALLOC        PROC    NEAR
+                CALL    PM_ALLOC_NOSWAP         ; Try without swapping
+                CMP     EAX, NULL_PHYS          ; Memory found?
+                JNE     SHORT PA_RET            ; Yes -> done
+                CALL    SWAP_OUT                ; Try to swap out
+PA_RET:         RET
+PM_ALLOC        ENDP
+
+;
+; Allocate 4096 bytes of memory (either high or low memory, without
+; swapping)
+;
+; Out:  EAX     Physical address or NULL_PHYS if out of memory
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+PM_ALLOC_NOSWAP PROC    NEAR
+                PUSH    ES
+                PUSH    EBX
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    ESI
+PAN_RESTART:
+              IF DEBUG_MEM
+                CALL    MEM_INFO
+              ENDIF
+                CMP     DISABLE_EXT_MEM, FALSE  ; Extended memory disabled?
+                JNE     SHORT PAN_LOW           ; Yes -> use low memory
+;
+; Try XMS before EMS as we have already acquired all available XMS
+; memory and EMS memory is allocated on demand.  That leaves more
+; (EMS) memory to DOS programs.
+;
+PAN_HIGH:       MOV     EBX, HIMEM_HEAD_PHYS
+                CALL    PA_LOOK_LIST            ; Look for high memory in list
+                CMP     EAX, NULL_PHYS          ; Page found?
+                JNE     SHORT PAN_DONE          ; Yes -> done
+                CALL    PA_LOOK_TAB             ; Look for high memory in table
+                CMP     EAX, NULL_PHYS          ; Page found?
+                JNE     SHORT PAN_DONE          ; Yes -> done
+;
+; No XMS page available, try VCPI
+;
+PAN_EMS:        CMP     VCPI_FLAG, FALSE        ; Running under VCPI?
+                JE      SHORT PAN_LOW           ; No  -> use low memory
+                CALL    VCPI_ALLOC              ; Allocate one page
+                CMP     EAX, NULL_PHYS          ; Success?
+                JNE     SHORT PAN_DONE          ; Yes -> done
+;
+; Neither XMS nor EMS memory is available, try low memory
+;
+PAN_LOW:        MOV     EBX, LOMEM_HEAD_PHYS
+                CALL    PA_LOOK_LIST            ; Look for low memory
+                CMP     EAX, NULL_PHYS          ; Page found ?
+                JNE     SHORT PAN_DONE          ; Yes -> done
+                CALL    GET_FREE_PAGE           ; Look in free page bitmap
+;
+; Map the page if not already done.  If the allocated page was used
+; for its page table, we have to start over.
+;
+PAN_DONE:       CMP     EAX, NULL_PHYS          ; Out of memory?
+                JE      PAN_RET                 ; Yes -> done
+                MOV     EBX, EAX
+                ADD     EBX, G_PHYS_BASE        ; EBX := linear address
+                JC      SHORT PAN_ERROR         ; Must not happen
+                CALL    MAYBE_MAP_PAGE
+                CMP     EAX, NULL_PHYS          ; Used for page table?
+                JE      PAN_RESTART             ; Yes -> repeat
+PAN_RET:
+              IF DEBUG_MEM
+                CALL    MEM_INFO
+              ENDIF
+                POP     ESI
+                POP     EDX
+                POP     ECX
+                POP     EBX
+                POP     ES
+                RET
+
+PAN_ERROR:      INT     3
+                JMP     SHORT $
+PM_ALLOC_NOSWAP ENDP
+
+
+
+;
+; Get page from table of blocks
+;
+; Out   EAX     Physical address (NULL_PHYS: no page found)
+;
+                ASSUME  DS:SV_DATA
+PA_LOOK_TAB     PROC    NEAR
+                PUSH    ECX                     ; Save ECX
+                MOV     EAX, NULL_PHYS
+                MOV     CX, HIMEM_AVAIL_COUNT   ; Get table info
+                JCXZ    PALT_RET                ; Table used up -> done
+                MOV     SI, HIMEM_AVAIL_START
+                ASSUME  SI:PTR HIMEM_ENTRY
+PALT_1:         CMP     [SI].HM_AVAIL, 0
+                JNE     PALT_2                  ; Hit!
+                ADD     SI, SIZE HIMEM_ENTRY
+                LOOP    PALT_1
+                JMP     SHORT PALT_3
+
+PALT_2:         MOV     EAX, [SI].HM_USED
+                ADD     [SI].HM_USED, 4096
+                SUB     [SI].HM_AVAIL, 4096
+PALT_3:         MOV     HIMEM_AVAIL_COUNT, CX   ; Update table info
+                MOV     HIMEM_AVAIL_START, SI
+PALT_RET:       POP     ECX                     ; Restore ECX
+                RET
+                ASSUME  SI:NOTHING
+PA_LOOK_TAB     ENDP
+
+
+;
+; Get page from list of pages
+;
+; In:   EBX     Physical address of chain head
+;
+; Out   EAX     Physical address (NULL_PHYS: no page found)
+;       ES      G_PHYS_SEL
+;
+                ASSUME  EBX:NEAR32 PTR MEMORY_BLOCK
+PA_LOOK_LIST    PROC    NEAR
+                PUSH    ECX                      ; Save ECX
+                MOV     AX, G_PHYS_SEL           ; Use phyiscal addresses
+                MOV     ES, AX
+                MOV     EAX, ES:[EBX].NEXT_BLOCK ; Pointer to first page
+                CMP     EAX, NULL_PHYS           ; Chain empty?
+                JE      SHORT PALL_RET           ; Yes -> no page found
+                ASSUME  EAX:NEAR32 PTR MEMORY_BLOCK
+                MOV     ECX, ES:[EAX].NEXT_BLOCK ; Remove this page from
+                MOV     ES:[EBX].NEXT_BLOCK, ECX ; the chain
+                ASSUME  EAX:NOTHING
+PALL_RET:       POP     ECX                      ; Restore ECX
+                RET
+                ASSUME  EBX:NOTHING
+PA_LOOK_LIST    ENDP
+
+
+;
+; Available memory w/o swapping
+;
+; Out:  EAX     Number of available pages
+;
+                ASSUME  DS:SV_DATA
+PM_AVAIL        PROC    NEAR
+                MOV     TAVAIL, 0               ; No pages available
+                CMP     DISABLE_EXT_MEM, FALSE  ; Extended memory disabled?
+                JNE     SHORT PV_LOW            ; Yes -> low memory only
+                CMP     VCPI_FLAG, FALSE        ; Running under VCPI?
+                JE      SHORT PV_HIGH           ; No  -> skip
+                CALL    VCPI_AVAIL              ; VCPI memory available
+PV_HIGH:        MOV     EBX, HIMEM_HEAD_PHYS
+                CALL    PV_LOOK
+PV_LOW:         MOV     EBX, LOMEM_HEAD_PHYS
+                CALL    PV_LOOK
+                CALL    FREE_AVAIL
+                MOV     EAX, TAVAIL
+                RET
+PM_AVAIL        ENDP
+
+
+;
+; Add the number of available pages in a list of pages to TAVAIL
+;
+; In:   EBX     Physical address of chain head
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  EBX:NEAR32 PTR MEMORY_BLOCK
+PV_LOOK         PROC    NEAR
+                PUSH    ES                      ; Save ES
+                PUSH    EAX                     ; Save EAX
+                MOV     AX, G_PHYS_SEL          ; Use physical addresses
+                MOV     ES, AX
+                TALIGN  2
+PV_LOOK_NEXT:   MOV     EBX, ES:[EBX].NEXT_BLOCK ; Get address of next page
+                CMP     EBX, NULL_PHYS          ; End of chain?
+                JE      SHORT PV_LOOK_RET       ; Yes -> done
+                INC     TAVAIL                  ; Increment number of pages
+                JMP     SHORT PV_LOOK_NEXT      ; Repeat
+PV_LOOK_RET:    POP     EAX                     ; Restore EAX
+                POP     ES                      ; Restore ES
+                RET
+                ASSUME  EBX:NOTHING
+PV_LOOK         ENDP
+
+                ASSUME  DS:NOTHING
+
+             IF DEBUG_MEM
+
+MEM_INFO        PROC    NEAR
+                PUSH    DS
+                PUSH    FS
+                PUSHAD
+                MOV     AX, G_SV_DATA_SEL
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                CALL    OCRLF
+                MOV     CX, HIMEM_AVAIL_COUNT
+                MOV     DI, HIMEM_AVAIL_START
+                CALL    MEM_INFO_TAB
+                MOV     AX, G_PHYS_SEL
+                MOV     FS, AX
+                MOV     EDI, LOMEM_HEAD_PHYS
+                CALL    MEM_INFO_LIST
+                MOV     EDI, HIMEM_HEAD_PHYS
+                CALL    MEM_INFO_LIST
+              IF DEBUG_MEM_WAIT
+                MOV     AH, 01H
+                INT     21H
+              ENDIF
+                POPAD
+                NOP                             ; Avoid 386 bug
+                POP     FS
+                POP     DS
+                RET
+MEM_INFO        ENDP
+
+                ASSUME  EDI:NEAR32 PTR MEMORY_BLOCK
+MEM_INFO_LIST   PROC    NEAR
+MIL_1:          LEA     EDX, $MEMI1
+                CALL    OTEXT
+                MOV     EAX, EDI
+                CALL    ODWORD
+                CALL    OCRLF
+                MOV     EDI, FS:[EDI].NEXT_BLOCK
+                CMP     EDI, NULL_PHYS
+                JNE     MIL_1
+                RET
+MEM_INFO_LIST   ENDP
+                ASSUME  EDI:NOTHING
+
+                ASSUME  DI:PTR HIMEM_ENTRY
+MEM_INFO_TAB    PROC    NEAR
+                JCXZ    MIT_RET
+MIT_1:          CMP     [DI].HM_AVAIL, 0
+                JE      MIT_2
+                LEA     EDX, $MEMI1
+                CALL    OTEXT
+                MOV     EAX, [DI].HM_USED
+                CALL    ODWORD
+                LEA     EDX, $MEMI2
+                CALL    OTEXT
+                MOV     EAX, [DI].HM_AVAIL
+                CALL    ODWORD
+                CALL    OCRLF
+MIT_2:          ADD     DI, SIZE HIMEM_ENTRY
+                LOOP    MIT_1
+MIT_RET:        RET
+MEM_INFO_TAB    ENDP
+                ASSUME  DI:NOTHING
+
+              ENDIF
+
+
+SV_CODE         ENDS
+
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+OLD_INT15       LABEL   DWORD
+OLD_INT15_OFF   DW      ?
+OLD_INT15_SEG   DW      ?
+
+
+;
+; Allocate low memory
+;
+; In:   AX      Number of 4K pages to allocate
+;
+; Out:  AX      Real-mode segment or NULL_RM if no pages found
+;
+; Note: Must *not* be called after calling INIT_MEM_PHYS.
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  2
+RM_ALLOC        PROC    NEAR
+                PUSH    ES
+                PUSH    CX
+                PUSH    DX
+                MOV     DX, BLOCKS_HEAD         ; Head of list
+                MOV     CX, AX
+                TALIGN  2
+RA_LOOP:        CMP     DX, NULL_RM             ; End of list?
+                JE      SHORT RA_FAIL           ; Yes -> fail
+                MOV     ES, DX
+                MOV     DX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_NEXT
+                                                ; Segment of next block
+                CMP     CX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_FREE
+                                                ; Are there enough free pages?
+                JA      SHORT RA_LOOP           ; No  -> next block
+                SUB     (RM_BLOCK_HEADER PTR ES:[0]).RBH_FREE, AX
+                                                ; Adjust number of free pages
+                SHL     AX, 12 - 4              ; Convert to paragraphs
+                MOV     DX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_PAGE
+                                                ; Get segment address of page
+                ADD     (RM_BLOCK_HEADER PTR ES:[0]).RBH_PAGE, AX
+                                                ; Adjust page address
+                MOV     AX, DX                  ; Return segment in AX
+                JMP     SHORT RA_RET
+;
+; Not enough pages found -> return NULL_RM
+;
+RA_FAIL:        MOV     AX, NULL_RM             ; Fail
+RA_RET:         
+              IF DEBUG_LOW_MEM
+                LEA     DX, $RM_ALLOC_1
+                CALL    RTEXT
+                PUSH    AX
+                MOV     AX, CX
+                CALL    RWORD
+                POP     AX
+                LEA     DX, $RM_ALLOC_2
+                CALL    RTEXT
+                CALL    RWORD
+                CALL    RCRLF
+              ENDIF
+                POP     DX
+                POP     CX
+                POP     ES
+                RET
+RM_ALLOC        ENDP
+
+
+;
+; Initialize memory allocation
+;
+                ASSUME  DS:SV_DATA
+
+INIT_MEMORY     PROC    NEAR
+                PUSH    ES                      ; Save ES
+                LEA     AX, BLOCKS_HEAD
+                SHR     AX, 4                   ; ALIGN 16!
+                ADD     AX, SV_DATA
+                MOV     ES, AX                  ; Previous block
+;
+; Allocate blocks of memory and add to list of low memory blocks
+;
+IM_ALLOC:       MOV     BX, 0FFFFH              ; Try to allocate 0FFFFH
+                MOV     AH, 48H                 ; paragraphs (always fails)
+                INT     21H
+                CMP     BX, (16+4096)/16        ; Not enough memory available?
+                JB      SHORT IM_CONT           ; Yes -> done
+                MOV     AH, 48H                 ; Allocate largest block
+                INT     21H
+                JC      SHORT IM_CONT           ; Out of memory -> done
+              IF DEBUG_LOW_MEM
+                LEA     DX, $INIT_MEM_1
+                CALL    RTEXT
+                CALL    RWORD
+                LEA     DX, $INIT_MEM_2
+                CALL    RTEXT
+                PUSH    AX
+                MOV     AX, BX
+                CALL    RWORD
+                CALL    RCRLF
+                POP     AX
+              ENDIF
+                MOV     DX, AX                  ; Save the segment
+;
+; Compute linear address and size of block, hide header
+;
+                MOVZX   EBX, BX
+                SHL     EBX, 4                  ; Size of block (bytes)
+                SUB     EBX, 16                 ; Header
+                MOVZX   EAX, AX
+                SHL     EAX, 4                  ; Linear address of block
+                ADD     EAX, 16                 ; Header
+;
+; Align start and end to page size
+;
+                TEST    EAX, 0FFFH              ; Page aligned?
+                JZ      SHORT IM_ALIGNED
+                ADD     EBX, EAX                ; EBX := end of block
+                OR      EAX, 0FFFH
+                INC     EAX                     ; Now EAX is page aligned
+                SUB     EBX, EAX                ; EBX := new block size
+IM_ALIGNED:     AND     EBX, NOT 0FFFH          ; Align end of block
+                JZ      SHORT IM_ALLOC          ; Too small -> next block
+;
+; Add block to list
+;
+                MOV     (RM_BLOCK_HEADER PTR ES:[0]).RBH_NEXT, DX
+                                                ; Add header to list
+                MOV     ES, DX                  ; Now initialize the fields
+                SHR     EAX, 4                  ; Compute first segment
+                MOV     (RM_BLOCK_HEADER PTR ES:[0]).RBH_PAGE, AX
+                                                ; Next (first, now) free page
+                SHR     EBX, 12                 ; Number of pages
+                MOV     (RM_BLOCK_HEADER PTR ES:[0]).RBH_MAX, BX
+                MOV     (RM_BLOCK_HEADER PTR ES:[0]).RBH_FREE, BX
+                JMP     IM_ALLOC                ; Allocate another block
+
+IM_CONT:        MOV     (RM_BLOCK_HEADER PTR ES:[0]).RBH_NEXT, NULL_RM
+                                                ; End of chain
+                CMP     VCPI_FLAG, FALSE        ; VCPI active?
+                JNE     IM_RET                  ; Yes -> himem managed by VCPI
+                CMP     XMS_FLAG, FALSE         ; XMS active?
+                JNE     IM_RET                  ; Yes -> himem managed by XMS
+;
+; Neither XMS nor VCPI. Do extended memory the hard way
+;
+                CMP     DISABLE_EXT_MEM, FALSE  ; Extended memory disabled?
+                JNE     IM_RET                  ; Yes -> skip
+                CMP     MACHINE, MACH_FMR70     ; Fujitsu FMR70?
+                JNE     SHORT IM_HIMEM1         ; No  ->
+;
+; Fujitsu FMR70
+;
+                MOV     AX, FMR70_MEM_MAX
+                JMP     SHORT IM_SET_EXT
+
+IM_HIMEM1:      CMP     MACHINE, MACH_PC98      ; NEC PC-98?
+                JNE     SHORT IM_PC             ; No  -> COMPAQ / IBM
+                XOR     AX, AX
+                MOV     ES, AX
+                XCHG    AL, BYTE PTR ES:[401H]  ; Get memory size (128KB)
+                SHL     AX, 7                   ; Multiply by 128KB
+                JMP     SHORT IM_SET_EXT
+;
+; First check whether we have extended memory at all
+;
+IM_PC:          MOV     AH, 88H
+                INT     15H
+IM_SET_EXT:     MOV     EXT_1K_BLOCKS, AX
+              IF DEBUG_EXT_MEM
+                CALL    RWORD
+                LEA     DX, $EXT_MEM
+                CALL    RTEXT
+              ENDIF
+                OR      AX, AX
+                JZ      IM_RET
+                MOVZX   EAX, AX
+                SHL     EAX, 10                 ; Multiply by 1K
+                MOV     EXT_SIZE, EAX
+                MOV     EXT_START, 100000H      ; 1M
+;
+; Look for VDISK in extended memory
+;
+                CMP     MACHINE, MACH_PC        ; COMPAQ / IBM?
+                JE      SHORT VDISK_PC          ; Yes -> look for VDISK
+                CMP     MACHINE, MACH_INBOARD   ; Inboard 386/PC?
+                JNE     NO_VDISK                ; No  -> skip
+VDISK_PC:       MOV     ESI, 100000H            ; 1M
+                LEA     DI, VDISK_BOOT
+                MOV     CX, VDISK_WORDS
+                CALL    GET_EXT
+                MOV_ES_DS
+                LEA     SI, VDISK_NAME
+                LEA     DI, VDISK_ANY
+                MOV     CX, SIZE VDISK_ANY
+                CLD
+                REPE    CMPS VDISK_NAME, ES:VDISK_ANY
+                JNE     NO_VDISK
+                LEA     SI, VDISK_NAME
+                LEA     DI, VDISK_33_BOOT
+                MOV     CX, SIZE VDISK_33_BOOT
+                CLD
+                REPE    CMPS VDISK_NAME, ES:VDISK_33_BOOT
+                JNE     SHORT VDISK_ERROR
+                MOVZX   EAX, VDISK_NEXT
+                SHL     EAX, 10                 ; Multiply by 1K
+                MOV     EXT_START, EAX          ; Set start address
+              IF DEBUG_EXT_MEM
+                LEA     DX, $VDISK1
+                CALL    RTEXT
+                MOV     AL, BYTE PTR EXT_START[2]
+                CALL    RBYTE
+                MOV     AX, WORD PTR EXT_START[0]
+                CALL    RWORD
+                CALL    RCRLF
+              ENDIF
+;
+; Look for VDISK (INT 19H)
+;
+                MOV     AH, 35H
+                MOV     AL, 19H                 ; Get INT 19H
+                INT     21H
+                XOR     BX, BX                  ; Use offset 0
+                MOV     DI, BX
+                ADD     DI, VDISK_DRIVER.VD_VOL_NAME
+                LEA     SI, VDISK_33_LABEL
+                MOV     CX, SIZE VDISK_33_LABEL
+                CLD
+                REPE    CMPS VDISK_33_LABEL, ES:[DI]
+                JE      SHORT VDISK_1
+VDISK_ERROR:    LEA     DX, $VDISK_ERROR
+                CALL    RTEXT
+                MOV     AL, 0FFH
+                JMP     EXIT
+
+                ASSUME  BX:PTR VDISK_DRIVER
+VDISK_1:      IF DEBUG_EXT_MEM
+                LEA     DX, $VDISK2
+                CALL    RTEXT
+                MOV     AL, ES:[BX].VD_AVAIL_HI
+                CALL    RBYTE
+                MOV     AX, ES:[BX].VD_AVAIL_LO
+                CALL    RWORD
+                CALL    RCRLF
+              ENDIF
+                MOV     VDISK_FLAG, NOT FALSE
+                MOVZX   EAX, ES:[BX].VD_AVAIL_HI
+                SHL     EAX, 16
+                MOV     AX, ES:[BX].VD_AVAIL_LO ; Compute start address
+                ASSUME  BX:NOTHING
+                CMP     EAX, EXT_START          ; Inconsistent?
+                JBE     SHORT VDISK_2           ; No ->
+                MOV     EXT_START, EAX          ; Be defensive
+VDISK_2:        MOV     EAX, EXT_START
+                SUB     EAX, 100000H            ; Bytes used by VDISK.SYS
+                JBE     SHORT VDISK_ERROR       ; Be cautious
+                SUB     EXT_SIZE, EAX           ; Reduce memory size
+                JB      SHORT VDISK_ERROR       ; Be cautious
+                JZ      SHORT IM_RET            ; No extended memory left
+                JMP     SHORT USE_EXT_MEM
+;
+; Allocate extended memory by hooking INT 15H
+;
+NO_VDISK:
+              IF DEBUG_EXT_MEM
+                LEA     DX, $NO_VDISK
+                CALL    RTEXT
+              ENDIF
+USE_EXT_MEM:
+              IF DEBUG_EXT_MEM
+                LEA     DX, $EXT_START
+                CALL    RTEXT
+                MOV     AX, WORD PTR EXT_START[2]
+                CALL    RWORD
+                MOV     AX, WORD PTR EXT_START[0]
+                CALL    RWORD
+                CALL    RCRLF
+                LEA     DX, $EXT_SIZE
+                CALL    RTEXT
+                MOV     AX, WORD PTR EXT_SIZE[2]
+                CALL    RWORD
+                MOV     AX, WORD PTR EXT_SIZE[0]
+                CALL    RWORD
+                CALL    RCRLF
+              ENDIF
+                MOV     HIMEM_COUNT, 1          ; One himem block
+                CMP     MACHINE, MACH_PC        ; COMPAQ / IBM?
+                JE      SHORT IM_HOOK           ; Yes -> hook INT 15H
+                CMP     MACHINE, MACH_INBOARD   ; Inboard 386/PC?
+                JNE     SHORT IM_RET            ; No  -> don't hook INT 15H
+IM_HOOK:        MOV     AL, 15H
+                LEA     DX, MY_INT15
+                CALL    SET_RM_INT
+                MOV     OLD_INT15_SEG, AX
+                MOV     OLD_INT15_OFF, DX
+                MOV     INT15_HOOKED, NOT FALSE
+IM_RET:         POP     ES                      ; Restore ES
+                RET
+INIT_MEMORY     ENDP
+
+
+;
+; Convert the blocks allocated from DOS memory (linked list of blocks) to
+; protected-mode format (linked list of pages using physical addresses).
+;
+INIT_MEM_PHYS   PROC    NEAR
+                CMP     DISABLE_LOW_MEM, FALSE  ; Use low memory?
+                JNE     SHORT IMP_FREE          ; No  -> give back to DOS
+                LEA     BX, LOMEM_HEAD
+                SHR     BX, 4
+                ADD     BX, SEG LOMEM_HEAD      ; BX:0 is destination
+                MOV     AX, NULL_RM
+                XCHG    AX, BLOCKS_HEAD
+IMP_OUTER:      CMP     AX, NULL_RM             ; End of list?
+                JE      SHORT IMP_OUTER_END     ; Yes -> done
+                MOV     ES, AX
+                PUSH    (RM_BLOCK_HEADER PTR ES:[0]).RBH_NEXT
+                                                ; Next block
+                MOV     CX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_FREE
+                                                ; Number of free pages
+                JCXZ    IMP_OUTER_NEXT
+                MOV     AX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_PAGE
+                                                ; Segment of first free page
+IMP_INNER:      PUSH    AX
+                XOR     DX, DX
+                CALL    RM_TO_PHYS              ; Convert AX:DX to phys. addr
+                MOV     ES, BX
+                MOV     (MEMORY_BLOCK PTR ES:[0]).NEXT_BLOCK, EAX
+                POP     AX
+                MOV     BX, AX
+                ADD     AX, 1000H / 10H         ; Next page in block
+                LOOP    IMP_INNER
+IMP_OUTER_NEXT: POP     AX
+                JMP     SHORT IMP_OUTER
+
+IMP_OUTER_END:  MOV     ES, BX
+                MOV     (MEMORY_BLOCK PTR ES:[0]).NEXT_BLOCK, NULL_PHYS
+                                                ; End of chain
+                RET
+
+;
+; Give back unused low memory to DOS
+;
+IMP_FREE:       MOV     LOMEM_HEAD.NEXT_BLOCK, NULL_PHYS ; Don't use low mem
+                MOV     AX, NULL_RM
+                XCHG    AX, BLOCKS_HEAD         ; Head of list
+IMP_FREE_LOOP:  CMP     AX, NULL_RM             ; End of list?
+                JE      SHORT IMP_FREE_END      ; Yes -> done
+                MOV     ES, AX
+                PUSH    (RM_BLOCK_HEADER PTR ES:[0]).RBH_NEXT
+                                                ; Pointer to next block
+                MOV     AX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_MAX
+                OR      AX, AX                  ; Any pages in block?
+                JZ      SHORT IMP_FREE_FREE     ; No -> free block
+                MOV     AX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_FREE
+                OR      AX, AX                  ; Are there free pages?
+                JZ      IMP_OUTER_NEXT          ; No free pages -> next block
+                CMP     AX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_MAX
+                                                ; Any pages used?
+                JNE     SHORT IMP_FREE_SET      ; Yes -> shrink block
+IMP_FREE_FREE:  MOV     AH, 49H
+                INT     21H                     ; Free allocated memory
+                JMP     SHORT IMP_FREE_NEXT
+
+IMP_FREE_SET:   MOV     BX, (RM_BLOCK_HEADER PTR ES:[0]).RBH_PAGE
+                                                ; Address of next free page
+                MOV     AX, ES
+                SUB     BX, AX                  ; Number of paragraphs
+                MOV     AH, 4AH
+                INT     21H                     ; Set block
+IMP_FREE_NEXT:  POP     AX                      ; Get pointer to next block
+                JMP     SHORT IMP_FREE_LOOP     ; Repeat until end reached
+
+IMP_FREE_END:   RET
+
+INIT_MEM_PHYS   ENDP
+
+;
+; Update the table of extended memory blocks.  Up to emx 0.9d, this procedure
+; put all the pages into a linked list (HIMEM_HEAD_PHYS).  Now, we can no
+; longer do this, as the memory is not yet accessible (the page tables
+; do not yet exist as high memory cannot be allocated -- chicken and egg!).
+; Instead, we allocate memory directly from the table of extended memory
+; blocks.
+;
+INIT_HIMEM      PROC    NEAR
+                MOV     CX, HIMEM_COUNT         ; Number of XMS blocks
+                LEA     SI, HIMEM_TAB           ; Table of XMS blocks
+                ASSUME  SI:PTR HIMEM_ENTRY
+                MOV     HIMEM_AVAIL_COUNT, CX
+                MOV     HIMEM_AVAIL_START, SI
+                JCXZ    IHM_END                 ; None -> done
+IHM_1:          MOV     EBX, [SI].HM_ADDR       ; Get address of block
+                MOV     EDX, [SI].HM_SIZE       ; Get size of block
+;
+; Align block
+;
+                TEST    EBX, 0FFFH              ; Page aligned?
+                JZ      SHORT IHM_2
+                ADD     EDX, EBX                ; EDX := end of block
+                OR      EBX, 0FFFH
+                INC     EBX                     ; Now EBX is page aligned
+                SUB     EDX, EBX                ; EDX := new block size
+IHM_2:          AND     EDX, NOT 0FFFH          ; Align end of block
+;
+; Initialize HM_USED and HM_AVAIL
+;
+                MOV     [SI].HM_USED, EBX
+                MOV     [SI].HM_AVAIL, EDX
+;
+; End of loop
+;
+                ADD     SI, SIZE HIMEM_ENTRY    ; Move to next block
+                LOOP    IHM_1                   ; Repeat for all blocks
+                ASSUME  SI:NOTHING
+IHM_END:        RET
+INIT_HIMEM      ENDP
+
+;
+; INT 15H handler. Request 88H (get extended memory size) returns 0,
+; all other requests are passed on to the original INT 15H handler.
+;
+                TALIGN  2
+MY_INT15        PROC    FAR
+                CMP     AH, 88H                 ; Get extended memory size
+                JNE     SHORT MY_INT15_OLD
+                XOR     AX, AX                  ; No extended memory
+                IRET
+                TALIGN  2
+MY_INT15_OLD:   JMP     OLD_INT15
+MY_INT15        ENDP
+
+;
+; Remove INT 15H hook.
+;
+CLEANUP_MEMORY  PROC    NEAR
+                CMP     INT15_HOOKED, FALSE
+                JE      SHORT CUM_RET
+                MOV     AL, 15H
+                MOV     BX, OLD_INT15_SEG
+                MOV     DX, OLD_INT15_OFF
+                CALL    RESTORE_RM_INT
+CUM_RET:        RET
+CLEANUP_MEMORY  ENDP
+
+
+;
+; Read extended memory (real mode!)
+;
+; Supports lower 16MB only!
+;
+; In:   ESI     Source address (>=1MB)
+;       DS:DI   Destination address
+;       CX      Number of words
+;
+
+MAKE_DES        MACRO   @E
+                MOV     WORD PTR @E[0], 0FFFFH  ; Segment limit
+                MOV     WORD PTR @E[2], AX      ; Segment base 0..15
+                SHR     EAX, 16
+                MOV     BYTE PTR @E[4], AL      ; Segment base 16..23
+                MOV     BYTE PTR @E[5], 93H
+                MOV     WORD PTR @E[6], 0       ; It's a 16 bit segment
+                ENDM
+
+GET_EXT         PROC    NEAR
+                PUSH    ES
+                PUSH    EAX
+                PUSH    EBX
+                PUSH    ESI
+                XOR     EAX, EAX
+                MOV     BM_GDT[0], EAX
+                MOV     BM_GDT[4], EAX
+                MOV     BM_BIOS[0], EAX
+                MOV     BM_BIOS[4], EAX
+                MOV     BM_STACK[0], EAX
+                MOV     BM_STACK[4], EAX
+                MOVZX   EDI, DI
+                MOV     AX, DS                  ; EAX=0!
+                SHL     EAX, 4
+                ADD     EAX, EDI                ; Destination address
+                MAKE_DES BM_DST
+                MOV     EAX, ESI
+                MAKE_DES BM_SRC
+                MOV     AH, 87H
+                MOV_ES_DS
+                LEA     SI, BLOCK_MOVE_GDT
+                INT     15H
+                POP     ESI
+                POP     EBX
+                POP     EAX
+                POP     ES
+                RET
+GET_EXT         ENDP
+
+INIT_CODE       ENDS
+
+
+                END
Index: trunk/src/emx/src/dos/memory.inc
===================================================================
--- trunk/src/emx/src/dos/memory.inc	(revision 18)
+++ trunk/src/emx/src/dos/memory.inc	(revision 18)
@@ -0,0 +1,81 @@
+;
+; MEMORY.INC -- Manage memory
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+NULL_PHYS       =       0FFFFFFFFH      ; Physical address n/a (end of chain)
+NULL_RM         =       0               ; Segment n/a (end of chain)
+
+HIMEM_MAX       =       16
+
+;
+; Note: all blocks are of size 4K and are 4K-page-aligned.
+;
+MEMORY_BLOCK    STRUCT
+NEXT_BLOCK      DD      NULL_PHYS       ; Physical address of next block
+MEMORY_BLOCK    ENDS
+
+HIMEM_ENTRY     STRUCT
+HM_ADDR         DD      ?       ; Physical address (w/o alignment)
+HM_SIZE         DD      ?       ; Size of block in bytes (w/o alignment)
+HM_USED         DD      ?       ; Used up to this phys addr (with alignment)
+HM_AVAIL        DD      ?       ; This many bytes available (with alignment)
+HM_HANDLE       DW      ?       ; For XMS
+HIMEM_ENTRY     ENDS
+
+              IFNDEF __MEMORY
+
+SV_DATA         SEGMENT
+
+                EXTRN   LOMEM_HEAD_PHYS:DWORD
+                EXTRN   HIMEM_HEAD_PHYS:DWORD
+                EXTRN   DISABLE_EXT_MEM:BYTE    ; Don't use memory above 1M
+                EXTRN   DISABLE_LOW_MEM:BYTE    ; Don't use memory below 1M
+                EXTRN   VDISK_FLAG:BYTE         ; VDISK.SYS 3.3 detected
+                EXTRN   HIMEM_TAB:HIMEM_ENTRY
+                EXTRN   HIMEM_COUNT:WORD
+                EXTRN   TAVAIL:DWORD
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   PM_ALLOC:NEAR
+                EXTRN   PM_ALLOC_NOSWAP:NEAR
+                EXTRN   PM_AVAIL:NEAR
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   RM_ALLOC:NEAR           ; Allocate pages
+                EXTRN   INIT_MEMORY:NEAR        ; Initialize memory management
+                EXTRN   INIT_HIMEM:NEAR         ; Update high memory table
+                EXTRN   CLEANUP_MEMORY:NEAR     ; Cleanup memory management
+                EXTRN   INIT_MEM_PHYS:NEAR      ; Convert lists to PM format
+
+INIT_CODE       ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/misc.inc
===================================================================
--- trunk/src/emx/src/dos/misc.inc	(revision 18)
+++ trunk/src/emx/src/dos/misc.inc	(revision 18)
@@ -0,0 +1,67 @@
+;
+; MISC.INC -- Miscellaneous definitions (for emx.asm)
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_STACK        SEGMENT
+
+                EXTRN   SV_TOS:WORD
+
+SV_STACK        ENDS
+
+
+RM_STACK        SEGMENT
+
+                EXTRN   RM_TOS:WORD
+
+RM_STACK        ENDS
+
+
+SV_DATA         SEGMENT
+
+                EXTRN   FP_FLAG:BYTE
+                EXTRN   FP_TMP:WORD
+                EXTRN   DOS_MAJOR:BYTE
+                EXTRN   DOS_MINOR:BYTE
+                EXTRN   ENV_PATH:WORD
+                EXTRN   ENV_EMXPATH:WORD
+                EXTRN   ENV_EMXOPT:WORD
+                EXTRN   CMDL_OPTIONS:BYTE
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   PROT1:NEAR
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   EXIT:NEAR               ; Cleanup and exit
+                EXTRN   CLEANUP:NEAR
+                EXTRN   RM_OUT_OF_MEM:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/ndebug.asm
===================================================================
--- trunk/src/emx/src/dos/ndebug.asm	(revision 18)
+++ trunk/src/emx/src/dos/ndebug.asm	(revision 18)
@@ -0,0 +1,94 @@
+;
+; NDEBUG.ASM -- No debugger
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE PMINT.INC
+
+                PUBLIC  STEP_FLAG, DEBUG_AVAIL, DEBUG_SER_FLAG, DEBUG_SER_PORT
+                PUBLIC  DEBUG_EXCEPTION, SET_BREAKPOINT, INS_BREAKPOINTS
+                PUBLIC  DEBUG_RESUME, DEBUG_STEP, DEBUG_QUIT, DEBUG_INIT
+
+SV_DATA         SEGMENT
+
+STEP_FLAG       DB      FALSE
+DEBUG_AVAIL     DB      FALSE
+DEBUG_SER_FLAG  DB      FALSE
+DEBUG_SER_PORT  DW      0
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Set EFLAGS for resuming current process (without stepping)
+;
+; In:   SS:BP   Interrupt/exception stack frame
+;
+                ASSUME  BP:PTR ISTACKFRAME
+DEBUG_RESUME    PROC    NEAR
+                AND     I_EFLAGS, NOT FLAG_TF
+                OR      I_EFLAGS, FLAG_RF
+                RET
+                ASSUME  BP:NOTHING
+DEBUG_RESUME    ENDP
+
+
+;
+; Set EFLAGS for single stepping current process
+;
+; In:   SS:BP   Interrupt/exception stack frame
+;
+                ASSUME  BP:PTR ISTACKFRAME
+DEBUG_STEP      PROC    NEAR
+                OR      I_EFLAGS, FLAG_TF
+                RET
+                ASSUME  BP:NOTHING
+DEBUG_STEP      ENDP
+
+DEBUG_EXCEPTION PROC    NEAR
+                RET                             ; Return and dump registers
+DEBUG_EXCEPTION ENDP
+
+SET_BREAKPOINT  PROC    NEAR
+                RET
+SET_BREAKPOINT  ENDP
+
+INS_BREAKPOINTS PROC    NEAR
+                RET
+INS_BREAKPOINTS ENDP
+
+DEBUG_INIT      PROC    NEAR
+                RET
+DEBUG_INIT      ENDP
+
+DEBUG_QUIT      PROC    NEAR
+                RET
+DEBUG_QUIT      ENDP
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/oprint.asm
===================================================================
--- trunk/src/emx/src/dos/oprint.asm	(revision 18)
+++ trunk/src/emx/src/dos/oprint.asm	(revision 18)
@@ -0,0 +1,154 @@
+;
+; OPRINT.ASM -- Text output via DOS
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+
+                PUBLIC  ODWORD, OWORD, OBYTE, ONIBBLE
+                PUBLIC  OCHAR, OTEXT, OCRLF
+
+
+SV_DATA         SEGMENT
+
+O_TMP_CHAR      DB      ?
+
+$CRLF           DB      CR, LF, 0
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Output using DOS
+;
+
+                ASSUME  DS:SV_DATA
+ODWORD          PROC    NEAR
+                ROR     EAX, 16
+                CALL    OWORD
+                ROR     EAX, 16
+                CALL    OWORD
+                RET
+ODWORD          ENDP
+
+                ASSUME  DS:SV_DATA
+OWORD           PROC    NEAR
+                XCHG    AL, AH
+                CALL    OBYTE
+                XCHG    AL, AH
+                CALL    OBYTE
+                RET
+OWORD           ENDP
+
+                ASSUME  DS:SV_DATA
+OBYTE           PROC    NEAR
+                PUSH    AX
+                SHR     AL, 4
+                CALL    ONIBBLE
+                POP     AX
+                PUSH    AX
+                CALL    ONIBBLE
+                POP     AX
+                RET
+OBYTE           ENDP
+
+                ASSUME  DS:SV_DATA
+ONIBBLE         PROC    NEAR
+                AND     AL, 0FH
+                ADD     AL, 30H
+                CMP     AL, 3AH
+                JB      SHORT ONIB1
+                ADD     AL, 7
+ONIB1:          CALL    OCHAR
+                RET
+ONIBBLE         ENDP
+
+
+;
+; In:   EDX     Pointer to null-terminated string
+;
+                ASSUME  DS:SV_DATA
+OTEXT           PROC    NEAR
+                PUSH    EAX
+                PUSH    EBX
+                PUSH    ECX
+                MOV     ECX, EDX
+                XOR     AL, AL
+OTEXT1:         CMP     AL, DS:[EDX]
+                JE      SHORT OTEXT2
+                INC     EDX
+                JMP     SHORT OTEXT1
+OTEXT2:         XCHG    EDX, ECX
+                SUB     ECX, EDX
+                MOV     BX, PROC0.P_HANDLES[1*2]
+                MOV     AH, 40H
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                INT     21H
+                POP     PROCESS_PTR
+                POP     ECX
+                POP     EBX
+                POP     EAX
+                RET
+OTEXT           ENDP
+
+                ASSUME  DS:SV_DATA
+OCHAR           PROC    NEAR
+                PUSH    EAX
+                PUSH    EBX
+                PUSH    ECX
+                PUSH    EDX
+                MOV     O_TMP_CHAR, AL
+                LEA     EDX, O_TMP_CHAR
+                MOV     ECX, 1
+                MOV     BX, PROC0.P_HANDLES[1*2]
+                MOV     AH, 40H
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                INT     21H
+                POP     PROCESS_PTR
+                POP     EDX
+                POP     ECX
+                POP     EBX
+                POP     EAX
+                RET
+OCHAR           ENDP
+
+
+                ASSUME  DS:SV_DATA
+OCRLF           PROC    NEAR
+                PUSH    EDX
+                LEA     EDX, $CRLF
+                CALL    OTEXT
+                POP     EDX
+                RET
+OCRLF           ENDP
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/oprint.inc
===================================================================
--- trunk/src/emx/src/dos/oprint.inc	(revision 18)
+++ trunk/src/emx/src/dos/oprint.inc	(revision 18)
@@ -0,0 +1,31 @@
+;
+; OPRINT.INC -- Text output via DOS
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_CODE         SEGMENT
+
+                EXTRN   ODWORD:NEAR, OWORD:NEAR, OBYTE:NEAR, ONIBBLE:WORD
+                EXTRN   OTEXT:NEAR, OCHAR:NEAR, OCRLF:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/options.asm
===================================================================
--- trunk/src/emx/src/dos/options.asm	(revision 18)
+++ trunk/src/emx/src/dos/options.asm	(revision 18)
@@ -0,0 +1,747 @@
+;
+; OPTIONS.ASM -- Parse options
+;
+; Copyright (c) 1991-2000 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE A20.INC
+                INCLUDE PMIO.INC
+                INCLUDE DEBUG.INC
+                INCLUDE MEMORY.INC
+                INCLUDE SIGNAL.INC              ; Required by PROCESS.INC
+                INCLUDE PROCESS.INC
+                INCLUDE LOADER.INC
+                INCLUDE EXCEPT.INC
+                INCLUDE RPRINT.INC
+                INCLUDE VERSION.INC
+                INCLUDE XMS.INC
+                INCLUDE MISC.INC
+
+                PUBLIC  TEST_FLAGS, OVERRIDE_FLAG, FP_IGNORE, MACHINE
+                PUBLIC  PM_OPTIONS
+                PUBLIC  RM_OPTIONS, RM_SKIP_BLANKS, USAGE
+
+SV_DATA         SEGMENT
+
+;
+; Options
+;
+                DALIGN  4
+TEST_FLAGS      DWORD   0                       ; Test flags
+OVERRIDE_FLAG   BYTE    FALSE                   ; Override some checks
+FP_IGNORE       BYTE    FALSE                   ; Don't check for coprocessor
+
+;
+; Hardware
+;
+MACHINE         BYTE    MACH_PC                 ; Default: AT compatible
+
+OPTT_CALL_NOARG =       0                       ; Call function: address
+OPTT_CALL_ARG   =       1                       ; Call function: address
+OPTT_GFLAG      =       2                       ; Global flag: address
+OPTT_LFLAG      =       3                       ; Local flag: mask
+
+DOPTION         STRUCT
+OPT_NAME        BYTE    ?
+OPT_TYPE        BYTE    ?
+OPT_PM          BYTE    ?
+OPT_DATA        WORD    ?
+DOPTION         ENDS
+
+OPTIONS_TABLE   LABEL   DOPTION
+                DOPTION  <"!", OPTT_CALL_ARG,   0, OPTF_TEST>
+                DOPTION  <"a", OPTT_CALL_ARG,   1, OPTF_ACCESS>
+                DOPTION  <"c", OPTT_LFLAG,      1, PF_NO_CORE>
+                DOPTION  <"d", OPTT_GFLAG,      0, DISABLE_EXT_MEM>
+                DOPTION  <"e", OPTT_LFLAG,      1, PF_REDIR_STDERR>
+                DOPTION  <"h", OPTT_CALL_ARG,   0, OPTF_HANDLES>
+                DOPTION  <"m", OPTT_CALL_ARG,   0, OPTF_MACHINE>
+                DOPTION  <"o", OPTT_GFLAG,      0, STDOUT_DUMP>
+                DOPTION  <"p", OPTT_GFLAG,      0, DISABLE_LOW_MEM>
+                DOPTION  <"q", OPTT_LFLAG,      1, PF_QUOTE>
+                DOPTION  <"r", OPTT_CALL_ARG,   1, OPTF_DRIVE>
+                DOPTION  <"s", OPTT_CALL_ARG,   1, OPTF_STACK>
+                DOPTION  <"t", OPTT_CALL_ARG,   1, OPTF_TRUNC>
+                DOPTION  <"C", OPTT_CALL_ARG,   1, OPTF_COMMIT>
+                DOPTION  <"D", OPTT_GFLAG,      0, DEBUG_FLAG>
+                DOPTION  <"E", OPTT_GFLAG,      0, FP_IGNORE>
+                DOPTION  <"F", OPTT_GFLAG,      0, USE_FAST_A20>
+                DOPTION  <"L", OPTT_LFLAG,      1, PF_PRELOAD>
+                DOPTION  <"O", OPTT_GFLAG,      0, OVERRIDE_FLAG>
+                DOPTION  <"P", OPTT_GFLAG,      0, USE_A20_PATCH>
+                DOPTION  <"R", OPTT_CALL_ARG,   0, OPTF_RSX>
+                DOPTION  <"S", OPTT_CALL_ARG,   0, OPTF_DEBUG>
+                DOPTION  <"V", OPTT_CALL_NOARG, 0, OPTF_VERSION>
+                DOPTION  <"X", OPTT_GFLAG,      0, DISABLE_XMS_MEM>
+                DOPTION  <"Z", OPTT_LFLAG,      1, PF_DONT_ZERO>
+                DOPTION  <0, 0, 0>
+
+;
+; Program titel
+;
+$TITLE          BYTE    "emx ", VERSION, " (rev ", REV_INDEX_TXT, ")"
+                BYTE    " -- Copyright (c) 1991-2000 by Eberhard Mattes"
+                BYTE    CR, LF, 0
+
+$USAGE          BYTE    "Usage: emx [-cdeoqOV] [-s<stack_size>] "
+                BYTE    "<program> [<arguments>]", CR, LF, 0
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Skip over blanks
+;
+; In:   ES:SI   Pointer to string
+;
+; Out:  ES:SI   Pointer to first non-blank character
+;       AL      First non-blank character
+;
+PM_SKIP_BLANKS  PROC    NEAR
+PSB_1:          MOV     AL, ES:[SI]
+                INC     SI
+                CMP     AL, " "
+                JE      SHORT PSB_1
+                CMP     AL, TAB
+                JE      SHORT PSB_1
+                DEC     SI
+                RET
+PM_SKIP_BLANKS  ENDP
+
+
+;
+; Parse options.
+;
+; In:   ES:SI   Pointer to null-terminated string
+;       DI      Pointer to process table entry
+;
+; Out:  CY      Error
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  DI:PTR PROCESS
+PM_OPTIONS      PROC    NEAR
+                PUSH    BX
+;
+; We're looking at the beginning of an argument (or at the whitespace
+; preceding the argument) or at the end of the string.  If the argument
+; does not start with a dash, return.
+;
+PMO_MAIN:       CALL    PM_SKIP_BLANKS          ; Skip blanks
+                OR      AL, AL                  ; End of line?
+                JZ      PMO_END                 ; Yes -> done
+                CMP     AL, "-"                 ; Option?
+                JNE     PMO_ERROR               ; No  -> error
+                INC     SI                      ; Skip dash
+;
+; We're looking at the name of an option.  It's either preceded by
+; a dash or by another option which does not take an argument.
+;
+PMO_OPTION:     MOV     AL, ES:[SI]             ; Get name
+                OR      AL, AL                  ; End of line?
+                JZ      PMO_ERROR
+                INC     SI                      ; Skip name
+                LEA     BX, OPTIONS_TABLE       ; Search table
+                ASSUME  BX:PTR DOPTION
+PMO_FIND:       CMP     [BX].OPT_NAME, 0        ; End of table?
+                JE      PMO_ERROR               ; Yes -> error
+                CMP     [BX].OPT_NAME, AL       ; Matching entry?
+                JE      SHORT PMO_FOUND         ; Yes -> found
+                ADD     BX, SIZE DOPTION        ; Move to next table entry
+                JMP     PMO_FIND                ; Loop through the table
+
+;
+; We've found a table entry for the current option.
+;
+PMO_FOUND:      CMP     [BX].OPT_PM, 0          ; Is it a PM option?
+                JE      SHORT PMO_SKIP          ; No  -> ignore & skip it
+                CMP     [BX].OPT_TYPE, OPTT_CALL_ARG    ; Call handler?
+                JE      SHORT PMO_CALL_ARG      ; Yes ->
+                CMP     [BX].OPT_TYPE, OPTT_CALL_NOARG  ; Call handler?
+                JE      SHORT PMO_CALL_NOARG    ; Yes ->
+                CMP     [BX].OPT_TYPE, OPTT_LFLAG ; Local flag?
+                JE      SHORT PMO_LFLAG         ; Yes -> set it
+                JMP     SHORT PMO_ERROR
+
+;
+; Set a local flag. OPT_DATA is the bit mask for P_FLAGS
+;
+PMO_LFLAG:      MOVZX   EAX, [BX].OPT_DATA      ; Get bit mask
+                OR      [DI].P_FLAGS, EAX       ; and set the flag
+;
+; Look for next option.  The option we've just handled does not take
+; an argument, therefore we can cluster options without requiring a
+; blank and a dash.
+;
+PMO_NEXT:       CMP     BYTE PTR ES:[SI], 0     ; End of line?
+                JE      SHORT PMO_END           ; Yes -> done
+                CMP     BYTE PTR ES:[SI], " "   ; Blank?
+                JE      PMO_MAIN                ; Yes -> new argument
+                CMP     BYTE PTR ES:[SI], TAB   ; Tab?
+                JE      PMO_MAIN                ; Yes -> new argument
+                JMP     PMO_OPTION              ; Clustered options
+
+;
+; Call handler for an option with argument.
+;
+PMO_CALL_ARG:   CALL    [BX].OPT_DATA           ; Call the handler function
+                JC      SHORT PMO_ERROR         ; Error -> return
+                CMP     BYTE PTR ES:[SI], 0     ; End of line?
+                JE      SHORT PMO_END           ; Yes -> done
+                CMP     BYTE PTR ES:[SI], " "   ; Blank?
+                JE      SHORT PMO_MAIN          ; Yes -> new argument
+                CMP     BYTE PTR ES:[SI], TAB   ; Tab?
+                JE      SHORT PMO_MAIN          ; Yes -> new argument
+                JMP     SHORT PMO_ERROR         ; Error
+
+;
+; Call handler for an option without argument.
+;
+PMO_CALL_NOARG: CALL    [BX].OPT_DATA           ; Call the handler function
+                JC      SHORT PMO_ERROR         ; Error -> return
+                JMP     SHORT PMO_NEXT          ; Next option
+
+;
+; Skip an option.
+;
+PMO_SKIP:       CMP     [BX].OPT_TYPE, OPTT_CALL_ARG    ; With argument?
+                JNE     PMO_NEXT                ; No  -> simply ignore it
+;
+; Skip the argument.
+;
+PMO_SKIP_ARG:   MOV     AL, ES:[SI]             ; Fetch next character
+                OR      AL, AL                  ; End of line?
+                JZ      SHORT PMO_END           ; Yes -> done
+                CMP     AL, " "                 ; Blank?
+                JE      PMO_MAIN                ; Yes -> new argument
+                CMP     AL, TAB                 ; Tab?
+                JE      PMO_MAIN                ; Yes -> new argument
+                INC     SI                      ; Skip the character
+                JMP     SHORT PMO_SKIP_ARG      ; Repeat
+
+;
+; Done.
+;
+PMO_END:        CLC
+PMO_RET:        POP     BX
+                RET
+
+;
+; Error.
+;
+PMO_ERROR:      STC
+                JMP     PMO_RET
+
+                ASSUME  BX:NOTHING
+PM_OPTIONS      ENDP
+
+;
+; -C option
+;
+OPTF_COMMIT     PROC    NEAR
+                MOV     EAX, 0                  ; Default: 0
+                MOV     AL, ES:[SI]
+                CALL    PM_OPT_ISEND
+                JE      SHORT OC_1
+                CALL    PM_OPT_NUMBER
+                JC      SHORT OC_ERROR
+                CMP     EAX, 512*1024           ; 512 MB maximum
+                JA      SHORT OC_ERROR
+                SHL     EAX, 10                 ; Multiply by 1K
+                ADD     EAX, 0FFFH              ; Round to multiple
+                AND     EAX, NOT 0FFFH          ; of page size (4096)
+OC_1:           MOV     [DI].P_COMMIT_SIZE, EAX ; Set size
+                OR      [DI].P_FLAGS, PF_COMMIT ; Set flag
+                CLC
+                RET
+OC_ERROR:       STC
+                RET
+OPTF_COMMIT     ENDP
+
+
+
+;
+; -a option
+;
+OPTF_ACCESS     PROC    NEAR
+                MOV     AH, 0
+OA_1:           MOV     AL, ES:[SI]
+                MOV     DL, HW_ACCESS_CODE
+                CMP     AL, "c"
+                JE      SHORT OA_2
+                MOV     DL, HW_ACCESS_MEM
+                CMP     AL, "m"
+                JE      SHORT OA_2
+                MOV     DL, HW_ACCESS_MEM OR HW_ACCESS_WRITE
+                CMP     AL, "w"
+                JE      SHORT OA_2
+                MOV     DL, HW_ACCESS_IO
+                CMP     AL, "i"
+                JE      SHORT OA_2
+                CMP     AH, 0
+                JE      SHORT OA_ERROR
+                OR      [DI].P_HW_ACCESS, AH
+                CLC
+                RET
+
+OA_2:           OR      AH, DL
+                INC     SI
+                JMP     SHORT OA_1
+
+OA_ERROR:       STC
+                RET
+OPTF_ACCESS     ENDP
+
+;
+; -r option
+;
+OPTF_DRIVE      PROC    NEAR
+                MOV     AL, ES:[SI]
+                SUB     AL, "A"
+                CMP     AL, 26
+                JB      SHORT OD_1
+                MOV     AL, ES:[SI]
+                SUB     AL, "a"
+                CMP     AL, 26
+                JAE     SHORT OD_ERROR
+OD_1:           ADD     AL, "A"
+                MOV     [DI].P_DRIVE, AL
+                INC     SI
+                CLC
+                RET
+
+OD_ERROR:       STC
+                RET
+OPTF_DRIVE      ENDP
+
+;
+; -s option
+;
+OPTF_STACK      PROC    NEAR
+                CALL    PM_OPT_NUMBER
+                JC      SHORT OS_ERROR
+                CMP     EAX, 8                  ; 8 KB minimum
+                JB      SHORT OS_ERROR
+                CMP     EAX, 512*1024           ; 512 MB maximum
+                JA      SHORT OS_ERROR
+                SHL     EAX, 10                 ; Multiply by 1K
+                ADD     EAX, 0FFFH              ; Round to multiple
+                AND     EAX, NOT 0FFFH          ; of page size (4096)
+                MOV     [DI].P_STACK_SIZE, EAX  ; Set stack size
+                CLC
+                RET
+OS_ERROR:       STC
+                RET
+OPTF_STACK      ENDP
+
+;
+; -t option
+;
+OPTF_TRUNC      PROC    NEAR
+                XOR     EAX, EAX
+                MOV     AL, ES:[SI]
+                CALL    PM_OPT_ISEND
+                JZ      SHORT OT_ALL
+                CMP     AL, "-"
+                JE      OT_MINUS
+                MOV     CH, 1
+OT_LOOP:        SUB     AL, "A"
+                CMP     AL, 26
+                JB      SHORT OT_LETTER
+                MOV     AL, ES:[SI]
+                SUB     AL, "a"
+                CMP     AL, 26
+                JB      SHORT OT_LETTER
+                CMP     BYTE PTR ES:[SI], "/"
+                JNE     SHORT OT_ERROR
+                MOV     AL, -1
+OT_LETTER:      INC     AL
+                AND     AL, 1FH
+                TEST    CH, CH
+                JZ      OT_CLEAR
+                BTS     [DI].P_TRUNC, EAX
+OT_NEXT:        INC     SI
+                MOV     AL, ES:[SI]
+                CALL    PM_OPT_ISEND
+                JNZ     OT_LOOP
+                CLC
+                RET
+
+OT_CLEAR:       BTR     [DI].P_TRUNC, EAX
+                JMP     OT_NEXT
+
+OT_MINUS:       INC     SI
+                MOV     AL, ES:[SI]
+                CALL    PM_OPT_ISEND
+                JZ      SHORT OT_ZERO
+                MOV     CH, 0
+                JMP     OT_LOOP
+
+OT_ZERO:        MOV     [DI].P_TRUNC, 0
+                CLC
+                RET
+
+OT_ALL:         MOV     [DI].P_TRUNC, NOT 0
+                CLC
+                RET
+
+OT_ERROR:       STC
+                RET
+OPTF_TRUNC      ENDP
+
+                ASSUME  DI:NOTHING
+
+;
+; Set the ZR flag if AL ends the argument of an option
+;
+PM_OPT_ISEND    PROC    NEAR
+                TEST    AL, AL
+                JZ      SHORT POE_RET
+                CMP     AL, " "
+                JE      SHORT POE_RET
+                CMP     AL, TAB
+POE_RET:        RET
+PM_OPT_ISEND    ENDP
+
+;
+; Parse a number for options (blank or zero terminated)
+;
+; In:   ES:SI   Pointer to string
+;
+; Out:  EAX     Number
+;       CY      Error
+;       ES:SI   Points to blank or zero
+;
+PM_OPT_NUMBER   PROC    NEAR
+                PUSH    CX
+                PUSH    EDX
+                XOR     CX, CX
+                XOR     EAX, EAX
+PON_1:          MOVZX   EDX, BYTE PTR ES:[SI]
+                OR      DL, DL
+                JE      SHORT PON_END
+                CMP     DL, " "
+                JE      SHORT PON_END
+                CMP     DL, TAB
+                JE      SHORT PON_END
+                SUB     DL, "0"
+                CMP     DL, 9
+                JA      SHORT PON_ERROR
+                IMUL    EAX, 10
+                JC      SHORT PON_ERROR
+                ADD     EAX, EDX
+                JC      SHORT PON_ERROR
+                INC     SI
+                INC     CX
+                JMP     PON_1
+PON_END:        OR      CX, CX
+                JNZ     SHORT PON_RET
+PON_ERROR:      STC
+PON_RET:        POP     EDX
+                POP     CX
+                RET
+PM_OPT_NUMBER   ENDP
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Skip over blanks
+;
+; In:   ES:SI   Pointer to string
+;
+; Out:  ES:SI   Pointer to first non-blank character
+;       AL      First non-blank character
+;
+RM_SKIP_BLANKS  PROC    NEAR
+RSB_1:          MOV     AL, ES:[SI]
+                INC     SI
+                CMP     AL, " "
+                JE      SHORT RSB_1
+                CMP     AL, TAB
+                JE      SHORT RSB_1
+                DEC     SI
+                RET
+RM_SKIP_BLANKS  ENDP
+
+
+;
+; Parse startup options.  Jump to USAGE if there is an error.
+;
+; In:   ES:SI   Pointer to null-terminated string
+;
+; Out:  ES:SI   Pointer to first non-option argument
+;
+                ASSUME  DS:SV_DATA
+RM_OPTIONS      PROC    NEAR
+;
+; We're looking at the beginning of an argument (or at the whitespace
+; preceding the argument) or at the end of the string.  If the argument
+; does not start with a dash, return.
+;
+RMO_MAIN:       CALL    RM_SKIP_BLANKS          ; Skip blanks
+                CMP     AL, "-"                 ; Option?
+                JNE     RMO_END                 ; No  -> done
+                INC     SI                      ; Skip dash
+;
+; We're looking at the name of an option.  It's either preceded by
+; a dash or by another option which does not take an argument.
+;
+RMO_OPTION:     MOV     AL, ES:[SI]             ; Get and skip name (skipping 0
+                INC     SI                      ; is benign: we jump to USAGE)
+                LEA     BX, OPTIONS_TABLE       ; Search table
+                ASSUME  BX:PTR DOPTION
+RMO_FIND:       CMP     [BX].OPT_NAME, 0        ; End of table?
+                JE      SHORT RMO_ERROR         ; Yes -> error
+                CMP     [BX].OPT_NAME, AL       ; Matching entry?
+                JE      SHORT RMO_FOUND         ; Yes -> found
+                ADD     BX, SIZE DOPTION        ; Move to next table entry
+                JMP     RMO_FIND                ; Loop through the table
+
+;
+; We've found a table entry for the current option.
+;
+RMO_FOUND:      CMP     [BX].OPT_PM, 0          ; Is it a PM option?
+                JNE     SHORT RMO_SKIP          ; Yes -> ignore & skip it
+                CMP     [BX].OPT_TYPE, OPTT_CALL_ARG    ; Call handler?
+                JE      SHORT RMO_CALL_ARG      ; Yes ->
+                CMP     [BX].OPT_TYPE, OPTT_CALL_NOARG  ; Call handler?
+                JE      SHORT RMO_CALL_NOARG    ; Yes ->
+                CMP     [BX].OPT_TYPE, OPTT_GFLAG ; Global flag?
+                JE      SHORT RMO_GFLAG         ; Yes -> set it
+RMO_ERROR:      JMP     USAGE                   ; Error, abort!
+
+;
+; Set a global flag. OPT_DATA is the offset in the SV_DATA segment.
+;
+RMO_GFLAG:      MOV     DI, [BX].OPT_DATA       ; Get pointer
+                MOV     BYTE PTR [DI], NOT FALSE ; and set the flag to true
+;
+; Look for next option.  The option we've just handled does not take
+; an argument, therefore we can cluster options without requiring a
+; blank and a dash.
+;
+RMO_NEXT:       CMP     BYTE PTR ES:[SI], 0     ; End of line?
+                JE      SHORT RMO_END           ; Yes -> done
+                CMP     BYTE PTR ES:[SI], " "   ; Blank?
+                JE      RMO_MAIN                ; Yes -> new argument
+                CMP     BYTE PTR ES:[SI], TAB   ; Tab?
+                JE      RMO_MAIN                ; Yes -> new argument
+                JMP     RMO_OPTION              ; Clustered options
+
+;
+; Call handler for an option with argument.
+;
+RMO_CALL_ARG:   CALL    [BX].OPT_DATA           ; Call the handler function
+                CMP     BYTE PTR ES:[SI], 0     ; End of line?
+                JE      SHORT RMO_END           ; Yes -> done
+                CMP     BYTE PTR ES:[SI], " "   ; Blank?
+                JE      SHORT RMO_MAIN          ; Yes -> new argument
+                CMP     BYTE PTR ES:[SI], TAB   ; Tab?
+                JE      SHORT RMO_MAIN          ; Yes -> new argument
+                JMP     RMO_ERROR               ; Error
+
+;
+; Call handler for an option without argument.
+;
+RMO_CALL_NOARG: CALL    [BX].OPT_DATA           ; Call the handler function
+                JMP     SHORT RMO_NEXT          ; Next option
+
+;
+; Skip an option.
+;
+RMO_SKIP:       CMP     [BX].OPT_TYPE, OPTT_CALL_ARG    ; With argument?
+                JNE     RMO_NEXT                ; No  -> simply ignore it
+;
+; Skip the argument.
+;
+RMO_SKIP_ARG:   CALL    RM_SKIP_ARG             ; Fetch next non-white char
+                OR      AL, AL
+                JNZ     SHORT RMO_MAIN
+;
+; Done.
+;
+RMO_END:        RET
+                ASSUME  BX:NOTHING
+RM_OPTIONS      ENDP
+
+;
+; Skip the argument of an option
+;
+; In:  ES:SI    Pointer to string
+;
+; Out: SI       Pointer to next non-white character
+;      AL       Next non-white character
+;
+RM_SKIP_ARG     PROC    NEAR
+SKIP_LOOP:      MOV     AL, ES:[SI]             ; Fetch next character
+                OR      AL, AL                  ; End of line?
+                JZ      SHORT FIN               ; Yes -> done
+                CMP     AL, " "                 ; Blank?
+                JE      SHORT FIN               ; Yes -> done
+                CMP     AL, TAB                 ; Tab?
+                JE      SHORT FIN               ; Yes -> done
+                INC     SI                      ; Skip the character
+                JMP     SHORT SKIP_LOOP         ; Repeat
+FIN:            RET
+RM_SKIP_ARG     ENDP
+
+;
+; Parse a number for options (blank or zero terminated)
+;
+; In:   ES:SI   Pointer to string
+;
+; Out:  EAX     Number
+;       ES:SI   Points to blank or zero
+;
+RM_OPT_NUMBER   PROC    NEAR
+                PUSH    CX
+                PUSH    EDX
+                XOR     CX, CX
+                XOR     EAX, EAX
+RON_1:          MOVZX   EDX, BYTE PTR ES:[SI]
+                OR      DL, DL
+                JE      SHORT RON_END
+                CMP     DL, " "
+                JE      SHORT RON_END
+                SUB     DL, "0"
+                CMP     DL, 9
+                JA      USAGE
+                IMUL    EAX, 10
+                JC      USAGE
+                ADD     EAX, EDX
+                JC      USAGE
+                INC     SI
+                INC     CX
+                JMP     RON_1
+RON_END:        OR      CX, CX
+                JZ      USAGE
+                POP     EDX
+                POP     CX
+                RET
+RM_OPT_NUMBER   ENDP
+
+;
+; -! option
+;
+OPTF_TEST       PROC    NEAR
+                CALL    RM_OPT_NUMBER
+                MOV     TEST_FLAGS, EAX
+                RET
+OPTF_TEST       ENDP
+
+;
+; -h option
+;
+OPTF_HANDLES    PROC    NEAR
+                CALL    RM_OPT_NUMBER
+                CMP     EAX, 10
+                JB      USAGE
+                CMP     EAX, 65536
+                JA      USAGE
+                MOV     BX, AX
+                MOV     AH, DOS_MAJOR
+                MOV     AL, DOS_MINOR
+                CMP     AX, 031EH               ; 3.30 or later?
+                JB      SHORT OH_RET            ; No  -> ignore
+                MOV     AH, 67H                 ; Set handle count
+                INT     21H
+OH_RET:         RET
+OPTF_HANDLES    ENDP
+
+;
+; -m option
+;
+OPTF_MACHINE    PROC    NEAR
+                CALL    RM_OPT_NUMBER
+                CMP     EAX, MACH_MAX           ; Valid machine code?
+                JA      USAGE                   ; No  -> error
+                MOV     MACHINE, AL             ; Set machine code
+                RET
+OPTF_MACHINE    ENDP
+
+
+;
+; -R option (rsx options, ignored by emx)
+;
+OPTF_RSX        PROC    NEAR
+                CALL    RM_SKIP_ARG             ; Skip the argument if any
+                RET
+OPTF_RSX        ENDP
+
+
+;
+; -S option (only available if debugger is loaded)
+;
+OPTF_DEBUG      PROC    NEAR
+                CMP     DEBUG_AVAIL, FALSE      ; Debugger loaded?
+                JE      USAGE                   ; No  -> error
+                MOV     AL, ES:[SI]
+                INC     SI
+                MOV     DX, 03F8H               ; COM1
+                CMP     AL, "1"
+                JE      SHORT OD_1
+                MOV     DX, 02F8H               ; COM2
+                CMP     AL, "2"
+                JE      SHORT OD_1
+                DEC     SI                      ; Back up
+                MOV     DEBUG_SER_FLAG, FALSE
+                JMP     SHORT OD_2
+
+OD_1:           MOV     DEBUG_SER_PORT, DX      ; Set port address
+                MOV     DEBUG_SER_FLAG, NOT FALSE
+OD_2:           MOV     STEP_FLAG, NOT FALSE
+                RET
+OPTF_DEBUG      ENDP
+
+
+;
+; -V option
+;
+OPTF_VERSION    PROC    NEAR
+                LEA     DX, $TITLE
+                CALL    RTEXT
+                RET
+OPTF_VERSION    ENDP
+
+
+;
+;
+;
+USAGE           PROC    NEAR
+                XOR     EDX, EDX
+                LEA     DX, $USAGE
+                CALL    RTEXT
+                MOV     AL, 1
+                JMP     EXIT
+USAGE           ENDP
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/options.inc
===================================================================
--- trunk/src/emx/src/dos/options.inc	(revision 18)
+++ trunk/src/emx/src/dos/options.inc	(revision 18)
@@ -0,0 +1,50 @@
+;
+; OPTIONS.INC -- Parse options
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+TEST_CHECK_HANDLES      =       0001H
+
+SV_DATA         SEGMENT
+
+                EXTRN   OVERRIDE_FLAG:BYTE
+                EXTRN   FP_IGNORE:BYTE
+                EXTRN   TEST_FLAGS:DWORD
+                EXTRN   MACHINE:BYTE
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                EXTRN   PM_OPTIONS:NEAR
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   RM_SKIP_BLANKS:NEAR
+                EXTRN   RM_OPTIONS:NEAR
+                EXTRN   USAGE:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/paging.asm
===================================================================
--- trunk/src/emx/src/dos/paging.asm	(revision 18)
+++ trunk/src/emx/src/dos/paging.asm	(revision 18)
@@ -0,0 +1,931 @@
+;
+; PAGING.ASM -- Manage page tables
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__PAGING        =       1
+
+                INCLUDE EMX.INC
+                INCLUDE OPRINT.INC
+                INCLUDE MEMORY.INC
+                INCLUDE TABLES.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE VCPI.INC
+                INCLUDE PAGING.INC
+                INCLUDE SWAPPER.INC
+                INCLUDE MISC.INC
+
+                PUBLIC  PAGE_DIR_PHYS, PAGE_DIR_SEG, PAGE_TAB0_SEG
+                PUBLIC  LIN_START, PAGING
+                PUBLIC  ALLOC_PAGES, INIT_PAGES, SET_PAGES, CLEAR_TLB
+                PUBLIC  INIT_LIN_MAP, FREE_LIN, FREE_PAGES, GET_FREE_PAGE
+                PUBLIC  INIT_PAGE_BMAP, FREE_AVAIL, CLEAR_DIRTY
+                PUBLIC  INIT_PAGING, MAP_PAGES, RM_TO_PHYS, MAYBE_MAP_PAGE
+
+;
+; This constant limits physical memory (unless VCPI is used).  The
+; value is specified in MB.  Must be a multiple of 4.
+;
+MAX_PHYS_MEM    =       1024            ; 1 GB
+        
+SV_DATA         SEGMENT
+
+PAGE_DIR_PHYS   DD      ?               ; Physical address of page directory
+                                        ; Use only for putting into CR3!
+PAGE_DIR_SEG    DW      ?               ; Real-mode segment of page directory
+                                        ; and swap directory
+PAGE_TAB0_SEG   DW      ?               ; Real-mode segment of page table 0
+
+TEMP_PAGE_SEG   DW      ?               ; Page for use as temporary page table
+TEMP_PAGE_PHYS  DD      ?               ; during memory allocation
+;
+; Managing linear addresses. Linear addresses are divided into 4096 blocks
+; of size 1M each. There's a table containing 4096 bytes, one for each
+; block. This byte is either 0 (not allocated), 1..254 (allocated to
+; the process with that process index), or 255 (reserved or allocated
+; to supervisor).
+;
+; This could also be done by scanning page tables, but that seems to be
+; more complicated.
+;
+; There's a chicken and egg problem: We have to allocate some linear
+; addresses for creating this segment. Allocating linear addresses
+; requires this segment. Solution: Allocate the segment in real mode.
+; This is simple but wastes low memory. The segment contents are not
+; initialized in real mode to avoid duplication of code.
+;
+LIN_MAP_SEG     DW      ?               ; Real-mode segment
+
+;
+; First usable linear address, used for initializing linear address map etc.
+;
+; Linear address below this address map identically to physical addresses
+; (G_PHYS_SEL)
+;
+LIN_START       DD      ?
+
+;
+; We use a bitmap for keeping track of freed pages (FREE_PAGES). We do
+; not use SWAP_OUT for allocating freed pages, as SWAP_OUT just swaps
+; out the next page with PAGE_ACCESSED cleared (even if it must be
+; reloaded from a file or is dirty). For efficiency (memory/disk space),
+; freed pages must be reused before trying to swap out pages. To avoid
+; scanning the bitmap each time we need a page of physical memory, we
+; use a variable for counting freed pages.
+;
+FREED_PAGES     DD      0
+PAGE_BMAP_FLAG  DB      FALSE           ; Page bitmap enabled?
+
+;
+; Paging enable flag.
+;
+PAGING          DB      FALSE           ; Paging disabled
+
+$ALLOC_PAGES    DB      "Linear address space exhausted", CR, LF, 0
+
+              IF DEBUG_MAP
+$MMP1           DB      "Map phys=", 0
+$MMP2           DB      " lin=", 0
+              ENDIF
+SV_DATA         ENDS
+
+
+
+SV_CODE         SEGMENT
+
+                .386P
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+
+;
+; Initialize linear address map. Creating segments (SV_SEGMENT) is possible
+; only after calling this routine.
+;
+; Reserved linear addresses: 0 ... LIN_START-1
+;
+; Available linear addresses: LIN_START ... 0FFFFFFFFH
+;
+; This code requires LIN_START to be a multiple of the linear address
+; block size (1M).  Other code requires it to be a multiple of 4M.
+; Both INIT_PAGING and INIT_VCPI make LIN_START a multiple of 4M.
+;
+                ASSUME  DS:SV_DATA
+INIT_LIN_MAP    PROC    NEAR
+                MOV     AX, G_LIN_MAP_SEL
+                MOV     ES, AX
+                CLD
+                MOV     EBX, LIN_START
+                TEST    EBX, (1 SHL 22)-1       ; Must be a multiple of 4M
+                JNZ     SHORT $                 ; Impossible!
+                SHR     EBX, 20                 ; Divide by 1M
+                MOV     CX, BX
+                XOR     DI, DI
+                MOV     AL, PIDX_SV             ; Address reserved
+                REP     STOS BYTE PTR ES:[DI]
+                MOV     AL, 00H                 ; Address available
+                MOV     CX, 4096
+                SUB     CX, BX
+                REP     STOS BYTE PTR ES:[DI]
+                RET
+INIT_LIN_MAP    ENDP
+
+
+;
+; Allocate a range of pages
+;
+; In:   ECX     Number of bytes
+;       AL      Process index
+;
+; Out:  EAX     Linear address
+;       ECX     Number of pages
+;
+
+                ASSUME  DS:SV_DATA
+ALLOC_PAGES     PROC    NEAR
+                PUSH    ES
+                PUSH    DX
+                PUSH    DI
+                ADD     ECX, 0FFFH              ; Round up (pages)
+                AND     ECX, NOT 0FFFH
+                PUSH    ECX                     ; Save size
+                ADD     ECX, (1 SHL 20) - 1     ; Round up (1M)
+                SHR     ECX, 20                 ; Number of 1M blocks
+                MOV     DX, G_LIN_MAP_SEL
+                MOV     ES, DX
+                XOR     DI, DI
+                XOR     DX, DX                  ; 0 blocks found
+                MOV     AH, AL                  ; Save process index in AH
+                XOR     AL, AL                  ; Search for empty blocks
+AP_LOOP:        CMP     DI, 4096
+                JAE     SHORT AP_FAIL           ; Nothing found -> abort
+                SCAS    BYTE PTR ES:[DI]        ; Block available?
+                JE      SHORT AP_AVAILABLE      ; Yes -> increment counter
+                XOR     DX, DX                  ; Reset counter
+                JMP     SHORT AP_LOOP
+
+AP_AVAILABLE:   INC     DX                      ; Increment counter
+                CMP     DX, CX                  ; Enough blocks found?
+                JB      SHORT AP_LOOP           ; No  -> continue
+                SUB     DI, CX                  ; Starting block number
+                MOV     DX, DI                  ; Save it
+                CLD
+                MOV     AL, AH                  ; Get process index
+                REP     STOS BYTE PTR ES:[DI]   ; Allocate linear addresses
+                MOVZX   EAX, DX                 ; Get block number
+                SHL     EAX, 20                 ; Compute linear address
+                POP     ECX
+                SHR     ECX, 12                 ; ECX := number of pages
+                POP     DI
+                POP     DX
+                POP     ES
+                RET
+
+AP_FAIL:        LEA     EDX, $ALLOC_PAGES       ; Linear address space
+                CALL    OTEXT                   ; exhausted
+                MOV     AX, 4CFFH               ; Abort
+                INT     21H
+
+ALLOC_PAGES     ENDP
+
+
+;
+; Free linear address space of a (dead) process
+;
+; In:   AL      Process index (most not be 0FFH!)
+;
+                ASSUME  DS:SV_DATA
+FREE_LIN        PROC    NEAR
+                PUSH    ES
+                PUSH    CX
+                PUSH    DI
+                MOV     CX, G_LIN_MAP_SEL
+                MOV     ES, CX
+                MOV     CX, 4096                ; Examine 4096 entries
+                XOR     DI, DI                  ; Start with entry 0
+FL_LOOP:        SCAS    BYTE PTR ES:[DI]        ; Matching entry?
+                JNE     SHORT FL_NEXT           ; No  -> skip
+                MOV     BYTE PTR ES:[DI-1], 0   ; Make block available
+FL_NEXT:        LOOP    FL_LOOP
+                POP     DI
+                POP     CX
+                POP     ES
+                RET
+FREE_LIN        ENDP
+
+
+;
+; Adjust page tables of killed process
+;
+; In:   AL      Process index (must not be 00H!)
+;
+                ASSUME  DS:SV_DATA
+FREE_PAGES      PROC    NEAR
+                PUSH    ES
+                PUSH    FS
+                PUSH    GS
+                PUSHAD
+                MOV     CX, G_PAGEDIR_SEL
+                MOV     FS, CX                  ; FS: page directory
+                MOV     CX, G_PHYS_SEL
+                MOV     ES, CX                  ; ES: page tables
+                XOR     EBX, EBX
+                MOV     DL, AL                  ; Save process index
+FP_LOOP1:       MOV     ESI, FS:[EBX]           ; Get page directory entry
+                TEST    ESI, 1                  ; Page table present?
+                JZ      FP_NEXT_TABLE           ; No -> skip to next table
+                MOV     EDI, FS:[EBX+4096]      ; Address of swap table
+                OR      EDI, EDI                ; Does it exist?
+                JZ      FP_NEXT_TABLE           ; No -> skip to next table
+                AND     ESI, NOT 0FFFH          ; Address of page table
+                MOV     CX, 1024
+FP_LOOP2:       CMP     DL, ES:[EDI]            ; Matching process index?
+                JNE     SHORT FP_NEXT_PAGE
+                TEST    WORD PTR ES:[EDI], SWAP_ALLOC ; Swap space allocated?
+                JZ      SHORT FP_FREE1          ; No -> skip
+                MOV     AX, G_SWAP_BMP_SEL
+                MOV     GS, AX                  ; GS: swap file bitmap
+                MOV     EAX, ES:[EDI]
+                SHR     EAX, 12                 ; Block number
+                BTS     DWORD PTR GS:[0], EAX   ; Free swap file entry
+                JC      SHORT $                 ; Cannot happen
+FP_FREE1:       MOV     EAX, ES:[ESI]           ; Get page table entry
+                TEST    AX, PAGE_ALLOC          ; Memory allocated?
+                JZ      SHORT FP_ZERO           ; No  -> zero page table entry
+                SHR     EAX, 12                 ; Compute page number
+                CMP     EAX, 4096*8             ; Address beyond bitmap (128M)?
+                JAE     SHORT FP_KEEP           ; Yes -> keep page table entry
+                CMP     PAGE_BMAP_FLAG, FALSE   ; Page bitmap enabled?
+                JE      SHORT FP_KEEP           ; No  -> keep page table entry
+                INC     FREED_PAGES             ; One additional freed page
+                MOV     BP, G_PAGE_BMP_SEL
+                MOV     GS, BP                  ; GS: freed pages bitmap
+                BTS     DWORD PTR GS:[0], EAX   ; Free page
+                JC      SHORT $                 ; Cannot happen
+FP_ZERO:        XOR     EAX, EAX
+                MOV     DWORD PTR ES:[EDI], EAX
+                MOV     DWORD PTR ES:[ESI], EAX
+FP_NEXT_PAGE:   ADD     ESI, 4                  ; Next entry
+                ADD     EDI, 4
+                INC     EBP                     ; Increment page number
+                LOOP    FP_LOOP2                ; All page table entries
+FP_NEXT_TABLE:  ADD     EBX, 4                  ; Next page table
+                CMP     EBX, 4096               ; End of page directory?
+                JB      FP_LOOP1                ; No -> repeat
+                CALL    CLEAR_TLB               ; Clear the TLB
+                POPAD
+                NOP                             ; Avoid 386 bug
+                POP     GS
+                POP     FS
+                POP     ES
+                RET
+
+;
+; The physical address of the page is beyond 128M (ie, beyond the bitmap).
+; Let the swapper recycle this page.  Unfortunately, this almost doesn't
+; work, as the PAGE_PRESENT bit is cleared as soon as new linear memory
+; is allocated (SET_PAGES).  Nothing evil will happen, but memory beyond
+; 128M will almost never be reused.
+;
+FP_KEEP:        MOV     DWORD PTR ES:[EDI], SRC_NONE
+                AND     DWORD PTR ES:[ESI], PAGE_PRESENT OR PAGE_ALLOC OR NOT 0FFFH
+                JMP     SHORT FP_NEXT_PAGE
+
+FREE_PAGES      ENDP
+
+
+;
+; Initialize bitmap for freed pages
+;
+                ASSUME  DS:SV_DATA
+INIT_PAGE_BMAP  PROC    NEAR
+                MOV     ECX, 4096
+                LEA     SI, G_PAGE_BMP_DESC
+                CALL    SV_SEGMENT
+                JC      SHORT IPB_RET
+                MOV     AX, G_PAGE_BMP_SEL
+                MOV     ES, AX
+                MOV     ECX, 4096 / 4
+                XOR     EAX, EAX                ; All pages used
+                XOR     DI, DI
+                CLD
+                REP     STOS DWORD PTR ES:[DI]
+                MOV     PAGE_BMAP_FLAG, NOT FALSE
+IPB_RET:        RET
+INIT_PAGE_BMAP  ENDP
+
+;
+; Search bitmap for freed page
+;
+; Out:  EAX     Physical address of page (or NULL_PHYS if no page found)
+;
+                ASSUME  DS:SV_DATA
+GET_FREE_PAGE   PROC    NEAR
+                MOV     EAX, NULL_PHYS          ; No page found
+                CMP     FREED_PAGES, 0          ; Are there freed pages?
+                JE      SHORT GFP_RET           ; No  -> done
+                PUSH    ES
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    EDI
+                MOV     AX, G_PAGE_BMP_SEL
+                MOV     ES, AX
+                XOR     EDI, EDI
+                MOV     ECX, 4096 / 4
+                XOR     EAX, EAX
+                CLD
+                REPE    SCAS DWORD PTR ES:[EDI]
+                JE      SHORT $                 ; Cannot happen
+                BSF     EAX, DWORD PTR ES:[EDI-4]
+                JZ      SHORT $                 ; Cannot happen
+                BTR     ES:[EDI-4], EAX         ; Clear bit (use page)
+                DEC     FREED_PAGES             ; Adjust counter
+                LEA     EDX, [EDI-4]
+                SHL     EDX, 3                  ; 8 bits per byte
+                ADD     EAX, EDX
+                SHL     EAX, 12                 ; Convert to physical address
+                POP     EDI
+                POP     EDX
+                POP     ECX
+                POP     ES
+GFP_RET:        RET
+GET_FREE_PAGE   ENDP
+
+
+;
+; Add the number of freed pages to TAVAIL
+;
+                ASSUME  DS:SV_DATA
+FREE_AVAIL      PROC    NEAR
+                PUSH    EAX
+                MOV     EAX, FREED_PAGES
+                ADD     TAVAIL, EAX
+                POP     EAX
+                RET
+FREE_AVAIL      ENDP
+
+
+;
+; Create page tables
+;
+; In:   EAX     Linear address
+;       ECX     Number of pages
+;
+; Out:  CY=1    Out of memory
+;
+
+                ASSUME  DS:SV_DATA
+
+INIT_PAGES      PROC    NEAR
+                PUSHAD
+                PUSH    ES
+                PUSH    FS
+                JECXZ   SHORT IP_OK             ; No pages -> done
+                MOV     BX, G_PAGEDIR_SEL
+                MOV     FS, BX
+                MOV     BX, G_PHYS_SEL
+                MOV     ES, BX                  ; Address page tables with ES
+                MOV     EDI, EAX                ; Bits 22..31 of linear addr.
+                SHR     EDI, 22                 ; EDI := page directory index
+                MOV     EDX, EAX
+                SHR     EDX, 12                 ; Bits 12..21 of linear addr.
+                AND     EDX, 03FFH              ; Page table index
+;
+;    EDI = page directory index
+; FS:0   = page directory
+;    ECX = number of pages
+;    EDX = page table index
+;
+IP_1:           MOV     EBX, FS:[4*EDI]         ; Get page directory entry
+                OR      EBX, EBX                ; Does the entry exist?
+                JNZ     SHORT IP_10             ; Yes -> use it
+                CALL    PM_ALLOC                ; Allocate swap table
+                CMP     EAX, NULL_PHYS          ; Out of memory?
+                JE      SHORT IP_ERROR          ; Yes -> error
+                CALL    INIT_PAGE_TABLE         ; Clear all entries
+                MOV     FS:[4*EDI+4096], EAX    ; Store address
+                CALL    PM_ALLOC                ; Allocate page table
+                CMP     EAX, NULL_PHYS          ; Out of memory?
+                JE      SHORT IP_ERROR          ; Yes -> error
+                CALL    INIT_PAGE_TABLE         ; Clear all entries
+                MOV     EBX, EAX                ; EBX := addr. of page table
+                OR      EBX, PAGE_PRESENT OR PAGE_WRITE OR PAGE_USER
+                MOV     FS:[4*EDI+0], EBX       ; Make page directory entry
+IP_10:          MOV     EBX, 1024
+                SUB     EBX, EDX                ; Number of remaining entries
+                SUB     ECX, EBX
+                JBE     SHORT IP_OK
+                INC     EDI                     ; Next page table
+                MOV     EDX, 0                  ; Page table index := 0
+                JMP     SHORT IP_1
+
+IP_ERROR:       STC                             ; Error return
+                JMP     SHORT IP_RET
+
+IP_OK:          CALL    CLEAR_TLB               ; Clear the TLB
+                CLC                             ; Ok
+IP_RET:         POP     FS
+                POP     ES
+                POPAD
+                NOP                             ; Avoid 386 bug
+                RET
+INIT_PAGES      ENDP
+
+
+
+
+;
+; Set page table entries
+;
+; The page tables must exist (cf. INIT_PAGES)!
+;
+; In:   EAX     Linear address
+;       EBX     Page table entry (if address != 0: autoincrement)
+;       ECX     Number of pages
+;       EDX     Swap table entry (if page number != 0: autoincrement)
+;
+; Out:  CY      Error (out of memory -- only if PAGE_ALLOC is set)
+;
+; The PAGE_ALLOC bit in EBX is handled specially.  It tells SET_PAGES
+; to allocate memory or swap space for the pages.
+;
+
+
+                ASSUME  DS:SV_DATA
+
+SET_PAGES       PROC    NEAR
+                PUSHAD                          ; Save registers
+                PUSH    ES
+                PUSH    FS
+                OR      ECX, ECX
+                JZ      SP_OK                   ; No pages -> done
+                MOV     BP, G_PAGEDIR_SEL
+                MOV     FS, BP
+                MOV     BP, G_PHYS_SEL
+                MOV     ES, BP                  ; Address page tables with ES
+                XCHG    EAX, EBX                ; EAX:=pt entry, EBX:=linear
+                MOV     EBP, EBX                ; Linear address
+                SHR     EBP, 12
+                AND     EBP, 03FFH              ; EBP := page table index
+                SHR     EBX, 22                 ; EBX := page directory index
+;
+; FS:0   = pointer to page directory
+;    EBX = page directory index
+; ES:ESI = pointer to page table entry
+; ES:EDI = pointer to swap table entry
+;    EAX = page table entry (=:PTE)
+;    ECX = number of pages
+;    EDX = swap table entry
+;    EBP = page table index
+;
+SP_1:           MOV     ESI, FS:[4*EBX+0]       ; Get page directory entry
+                AND     ESI, NOT 0FFFH          ; Page table address
+                JZ      SHORT $                 ; Must not happen
+                MOV     EDI, FS:[4*EBX+4096]    ; Get pointer to swap table
+                OR      EDI, EDI
+                JZ      SHORT $                 ; Must not happen
+SP_2:           TEST    AX, PAGE_ALLOC          ; Allocate memory?
+                JNZ     SHORT SP_MEM            ; Yes -> allocate
+                TEST    DX, SWAP_ALLOC          ; Allocate swap space?
+                JNZ     SHORT SP_SWAP           ; Yes -> allocate
+SP_CONT:        MOV     ES:[ESI+4*EBP], EAX     ; Store page table entry
+                MOV     ES:[EDI+4*EBP], EDX     ; Store swap table entry
+                DEC     ECX                     ; Any pages left?
+                JZ      SP_OK                   ; No  -> done
+                TEST    EAX, NOT 0FFFH          ; Physical address = 0?
+                JZ      SHORT SP_3              ; Yes -> skip
+                ADD     EAX, 4096               ; No  -> next physical address
+SP_3:           TEST    EDX, NOT 0FFFH          ; Page number = 0?
+                JZ      SHORT SP_4              ; Yes -> skip
+                ADD     EDX, 4096               ; No  -> next page number
+SP_4:           INC     EBP                     ; Increment page table index
+                CMP     EBP, 1024               ; End of page table?
+                JB      SHORT SP_2              ; No  -> continue
+                INC     EBX                     ; Next page table
+                XOR     EBP, EBP                ; First PTE of this table
+                JMP     SHORT SP_1              ; New page table
+
+SP_MEM:         AND     EAX, 0FFFH              ; Clear address
+                PUSH    EAX                     ; Save page table entry
+                CALL    PM_ALLOC_NOSWAP         ; Allocate memory
+                CMP     EAX, NULL_PHYS          ; Success?
+                JE      SHORT SP_MEM_FAIL       ; No  -> allocate swap space
+                OR      EAX, [ESP]              ; Insert address into PTE
+                ADD     ESP, 4                  ; Remove PTE from stack
+                JMP     SP_CONT                 ; Store PTE
+
+SP_MEM_FAIL:    POP     EAX                     ; Restore page table entry
+                AND     AX, NOT PAGE_ALLOC      ; Stop allocating memory
+                OR      DX, SWAP_ALLOC          ; Allocate swap space instead
+SP_SWAP:        PUSH    EAX                     ; Save page table entry
+                CALL    ALLOC_SWAP              ; Allocate swap space
+                JC      SHORT SP_FAIL           ; No space -> error
+                AND     EDX, 0FFFH              ; Clear address
+                OR      EDX, EAX                ; Make swap table entry
+                POP     EAX                     ; Restore page table entry
+                JMP     SP_CONT                 ; Continue
+
+SP_FAIL:        POP     EAX                     ; Remove PTE from stack
+                ;...undo changes to page tables, deallocate
+                ;   swap pages (not yet done)
+                STC
+                JMP     SHORT SP_RET
+
+SP_OK:          CLC
+SP_RET:         CALL    CLEAR_TLB               ; Clear the TLB
+                POP     FS                      ; Restore registers
+                POP     ES
+                POPAD
+                NOP                             ; Avoid 386 bug
+                RET
+SET_PAGES       ENDP
+
+
+;
+; Clear the dirty & accessed bits
+;
+; In:   EAX     Linear address
+;       ECX     Number of pages
+;
+                ASSUME  DS:SV_DATA
+CLEAR_DIRTY     PROC    NEAR
+                PUSHAD                          ; Save registers
+                PUSH    ES
+                PUSH    FS
+                OR      ECX, ECX
+                JZ      CD_RET                  ; No pages -> done
+                MOV     DX, G_PAGEDIR_SEL
+                MOV     FS, DX
+                MOV     DX, G_PHYS_SEL
+                MOV     ES, DX                  ; Address page tables with ES
+                MOV     EBX, EAX                ; EBX:=linear address
+                MOV     EDX, EBX                ; Linear address
+                SHR     EDX, 12
+                AND     EDX, 03FFH              ; EDX := page table index
+                SHR     EBX, 22                 ; EBX := page directory index
+;
+; FS:0   = pointer to page directory
+;    EBX = page directory index
+; ES:ESI = pointer to page table entry
+;    ECX = number of pages
+;    EDX = page table index
+;
+CD_1:           MOV     ESI, FS:[4*EBX]         ; Get page directory entry
+                AND     ESI, NOT 0FFFH          ; Page table address
+                JZ      SHORT $                 ; Must not happen
+CD_2:           AND     BYTE PTR ES:[ESI+4*EDX], NOT (PAGE_DIRTY+PAGE_ACCESSED)
+                DEC     ECX                     ; Any pages left?
+                JZ      CD_RET                  ; No  -> done
+                INC     EDX                     ; Increment page table index
+                CMP     EDX, 1024               ; End of page table?
+                JB      SHORT CD_2              ; No  -> continue
+                INC     EBX                     ; Next page table
+                XOR     EDX, EDX                ; First PTE of this table
+                JMP     SHORT CD_1              ; New page table
+
+CD_RET:         CALL    CLEAR_TLB               ; Clear the TLB
+                POP     FS                      ; Restore registers
+                POP     ES
+                POPAD
+                NOP                             ; Avoid 386 bug
+                RET
+CLEAR_DIRTY     ENDP
+
+
+;
+; Clear the translation lookaside buffer
+;
+; Note: This procedure must not change the flags (see SET_PAGES).
+;
+CLEAR_TLB       PROC    NEAR
+                PUSH    EAX
+                MOV     EAX, CR3
+                MOV     CR3, EAX                ; This statement clears the TLB
+                POP     EAX
+                RET
+CLEAR_TLB       ENDP
+
+
+                ASSUME  DS:NOTHING
+
+;
+; Initialize a page table (all pages not present)
+; Set 1024 DWORDs to 0
+;
+; In:   ES:EAX  Address of page table or swap table
+;
+INIT_PAGE_TABLE PROC    NEAR
+                PUSH    EAX
+                PUSH    ECX
+                PUSH    EDI
+                MOV     EDI, EAX
+                MOV     ECX, 1024               ; Number of DWORDs
+                XOR     EAX, EAX
+                CLD
+                REP     STOS DWORD PTR ES:[EDI]
+                POP     EDI
+                POP     ECX
+                POP     EAX
+                RET
+INIT_PAGE_TABLE ENDP
+
+;
+; Create a page table for a page, if not already done, which maps
+; a page of physical memory below the LIN_START limit.  This function
+; returns NULL_PHYS if the page is used for its own page table.
+;
+; In:   EAX     Physical address
+;       EBX     Linear address
+;
+; Out:  EAX     Physical address (or NULL_PHYS to repeat allocation)
+;
+                ASSUME  DS:SV_DATA
+MAYBE_MAP_PAGE  PROC    NEAR
+                PUSH    FS
+                PUSH    EDX
+                CMP     EAX, LIN_START          ; Address valid in range?
+                JAE     SHORT MMP_ERROR         ; No  -> must not happen
+                MOV     DX, G_PAGEDIR_SEL       ; Access page directory
+                MOV     FS, DX                  ; at FS:0
+                MOV     EDX, EBX                ; Compute page directory index
+                SHR     EDX, 22
+                CMP     DWORD PTR FS:[4*EDX+0], 0  ; Page table initialized?
+                JE      MMP_INIT                ; No  -> initialize
+MMP_RET:        POP     EDX
+                POP     FS
+                RET
+
+MMP_ERROR:      INT     3
+                JMP     SHORT $
+
+;
+; Use the page as its own page table.
+;
+; First, use the temporary page for the page table to solve the
+; chicken and egg problem.
+;
+; As the linear address is smaller than LIN_START, there will be
+; no swap table, so one page is sufficient.
+;
+; In:   EAX     Physical address
+;       EBX     Linear address
+;       EDX     Page directory index
+;       FS:0    Page directory
+
+MMP_INIT:       PUSH    ES
+                PUSH    ECX
+                PUSH    ESI
+                PUSH    EDI
+
+              IF DEBUG_MAP
+                PUSH    EDX
+                LEA     EDX, $MMP1
+                CALL    OTEXT
+                CALL    ODWORD
+                LEA     EDX, $MMP2
+                CALL    OTEXT
+                XCHG    EAX, EBX
+                CALL    ODWORD
+                XCHG    EAX, EBX
+                CALL    OCRLF
+                POP     EDX
+              ENDIF
+;
+; Zero the temporary page
+;
+                PUSH    EAX
+                MOV     AX, G_PHYS_SEL
+                MOV     ES, AX
+                XOR     EAX, EAX
+                MOV     ECX, 1024
+                MOV     EDI, TEMP_PAGE_PHYS
+                CLD
+                REP     STOS DWORD PTR ES:[EDI]
+                POP     EAX
+;
+; Set all the page table entries, including the one which points
+; to the target page.  This assumes that LIN_START points to a
+; 4 MB (page table) boundary.
+;
+                PUSH    EAX
+                MOV     EDI, TEMP_PAGE_PHYS
+                MOV     ESI, EBX                ; Linear address
+                SHR     ESI, 12
+                AND     ESI, 03FFH              ; Page table index               MOV     EDX, EAX                ; EDX := physical address
+                SHL     ESI, 10                 ; Relative physical address
+                SUB     EAX, ESI                ; First physical address
+                OR      EAX, PAGE_PRESENT OR PAGE_WRITE OR PAGE_USER
+                MOV     ECX, 1024
+                TALIGN  4
+MMPI_1:         STOS    DWORD PTR ES:[EDI]
+                ADD     EAX, 4096
+                LOOP    MMPI_1
+                POP     EAX
+;
+; Set the page directory entry to point to the temporary page
+;
+                MOV     ECX, TEMP_PAGE_PHYS
+                OR      ECX, PAGE_PRESENT OR PAGE_WRITE OR PAGE_USER
+                MOV     FS:[4*EDX+0], ECX
+                CALL    CLEAR_TLB
+;
+; Now, the page is accessible and we can copy the temporary page,
+; which is simpler than initializing it from scrach
+;
+                MOV     ESI, TEMP_PAGE_PHYS
+                MOV     EDI, EAX                ; Physical address
+                MOV     ECX, 1024
+                PUSH    DS
+                MOV_DS_ES
+                ASSUME  DS:NOTHING
+                REP     MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
+                POP     DS
+                ASSUME  DS:SV_DATA
+;
+; Finally, we let the page directory point to the new page
+;
+                MOV     ECX, EAX                ; Physical address
+                OR      ECX, PAGE_PRESENT OR PAGE_WRITE OR PAGE_USER
+                MOV     FS:[4*EDX+0], ECX
+                CALL    CLEAR_TLB
+                POP     EDI
+                POP     ESI
+                POP     ECX
+                POP     ES
+                MOV     EAX, NULL_PHYS
+                JMP     MMP_RET
+MAYBE_MAP_PAGE  ENDP
+
+SV_CODE         ENDS
+
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Initialize paging
+;
+                ASSUME  DS:SV_DATA
+
+INIT_PAGING     PROC    NEAR
+                MOV     AX, 1
+                CALL    RM_ALLOC                ; Allocate linear address map
+                CMP     AX, NULL_RM             ; Out of memory?
+                JE      RM_OUT_OF_MEM           ; Yes -> abort
+                MOV     LIN_MAP_SEG, AX         ; Save segment
+
+                MOV     AX, 2                   ; Allocate page directory
+                CALL    RM_ALLOC                ; and swap directory
+                CMP     AX, NULL_RM             ; Out of memory?
+                JE      RM_OUT_OF_MEM           ; Yes -> abort
+                MOV     PAGE_DIR_SEG, AX        ; Save segment
+                MOV     ES, AX
+                MOV     EAX, 0                  ; Zero page directory and
+                MOV     DI, 0                   ; swap directory
+                CLD
+                MOV     ECX, 2*1024
+                REP     STOS DWORD PTR ES:[DI]
+
+                CMP     VCPI_FLAG, FALSE        ; VCPI?
+                JE      SHORT IPG_1             ; No  -> setup page tables
+                CALL    INIT_VCPI               ; Special handling for VCPI
+                JMP     SHORT IPG_2             ; Continue
+
+IPG_1:          MOV     FS, PAGE_DIR_SEG
+                MOV     SI, 0                   ; FS:SI = pointer to page dir
+                MOV     CX, 1                   ; 1 page table (4 MB)
+                MOV     EBP, 0                  ; Address = 0
+                CALL    MAP_PAGES
+                .ERRE   MAX_PHYS_MEM GE 4       ; At least one page table
+                .ERRE   MAX_PHYS_MEM LE 2048    ; No point in having more
+                .ERRNZ  MAX_PHYS_MEM MOD 4
+                MOV     ECX, MAX_PHYS_MEM * 1024 * 1024
+                MOV     LIN_START, ECX          ; First unused linear address
+                LEA     DI, G_PHYS_DESC
+                CALL    RM_SEG_SIZE
+
+IPG_2:          MOV     AX, PAGE_DIR_SEG
+                XOR     DX, DX
+                CALL    RM_TO_PHYS
+                MOV     PAGE_DIR_PHYS, EAX
+                MOV     V2P_CR3, EAX            ; For VCPI
+                MOV     TSS_EX8_CR3, EAX        ; CR3 for exception 8
+                MOV     TSS_EX10_CR3, EAX       ; CR3 for exception 10
+
+                MOVZX   EAX, PAGE_DIR_SEG
+                SHL     EAX, 4
+                LEA     DI, G_PAGEDIR_DESC
+                CALL    RM_SEG_BASE
+                MOVZX   EAX, LIN_MAP_SEG
+                SHL     EAX, 4
+                LEA     DI, G_LIN_MAP_DESC
+                CALL    RM_SEG_BASE
+;
+; Allocate a page to be used as temporary page table during memory
+; allocation
+;
+                MOV     AX, 1
+                CALL    RM_ALLOC
+                CMP     AX, NULL_RM             ; Out of memory?
+                JE      RM_OUT_OF_MEM           ; Yes -> abort
+                MOV     TEMP_PAGE_SEG, AX       ; Save segment
+                MOV     DX, 0
+                CALL    RM_TO_PHYS
+                MOV     TEMP_PAGE_PHYS, EAX     ; Save physical address
+                RET
+INIT_PAGING     ENDP
+
+
+
+;
+; Map pages (called in real mode)
+;
+; This function creates only complete page tables (for simplicity)
+; Uses RM_TO_PHYS
+;
+; In:   CX      Number of page tables
+;       EBP     Physical address
+;       FS:SI   Pointer to page directory entry
+;
+; Out:  EBP     Next physical address
+;       FS:SI   Pointer to next page directory entry
+;
+; Note: Successive calls initialize successive page tables.
+;
+MAP_PAGES       PROC    NEAR
+                PUSH    DX
+MP_OUTER_LOOP:  PUSH    CX                      ; Save page table counter
+                MOV     AX, 1                   ; Allocate a page table
+                CALL    RM_ALLOC
+                CMP     AX, NULL_RM             ; Out of memory?
+                JE      RM_OUT_OF_MEM           ; Yes -> abort
+                PUSH    AX                      ; Save segment
+                XOR     DX, DX                  ; Offset = 0
+                CALL    RM_TO_PHYS              ; Get physical address
+                OR      EAX, PAGE_PRESENT OR PAGE_WRITE OR PAGE_USER
+                MOV     FS:[SI], EAX            ; Store page directory entry
+                ADD     SI, 4                   ; Next page directory entry
+                POP     ES
+                MOV     EAX, EBP                ; Get entry/address
+                OR      EAX, PAGE_PRESENT OR PAGE_WRITE OR PAGE_USER
+                MOV     CX, 1024                ; Initialize 1024 entries
+                MOV     DI, 0
+MP_INNER_LOOP:  STOS    DWORD PTR ES:[DI]       ; Store page table entry
+                ADD     EAX, 4096               ; Next page
+                LOOP    MP_INNER_LOOP           ; Initialize all table entries
+                ADD     EBP, 4096*1024          ; Save entry/address
+                POP     CX                      ; Restore page table counter
+                LOOP    MP_OUTER_LOOP           ; Create all page tables
+                POP     DX
+                RET
+MAP_PAGES       ENDP
+
+
+;
+; Convert a real-mode address to the physical address
+;
+; In:   AX      Real-mode segment
+;       DX      Real-mode offset
+;
+; Out:  EAX     Physical address
+;       EDX     Upper word cleared
+;
+                ASSUME  DS:SV_DATA
+RM_TO_PHYS      PROC    NEAR
+                MOVZX   EAX, AX                 ; Clear upper word
+                MOVZX   EDX, DX                 ; Clear upper word
+                SHL     EAX, 4                  ; Compute linear address
+                ADD     EAX, EDX
+                CMP     VCPI_FLAG, FALSE        ; VCPI active?
+                JE      SHORT RTP_RET           ; No -> physical = linear
+                CALL    VCPI_LIN_TO_PHYS
+RTP_RET:        RET
+
+RM_TO_PHYS      ENDP
+
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/paging.inc
===================================================================
--- trunk/src/emx/src/dos/paging.inc	(revision 18)
+++ trunk/src/emx/src/dos/paging.inc	(revision 18)
@@ -0,0 +1,84 @@
+;
+; PAGING.INC -- Manage page tables
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; Bits in a page table entry which are used by the processor
+;
+PAGE_PRESENT    =        01H            ; Page present
+PAGE_WRITE      =        02H            ; Page writable
+PAGE_USER       =        04H            ; Not a supervisor page
+PAGE_ACCESSED   =        20H            ; Page has been accessed
+PAGE_DIRTY      =        40H            ; Page is dirty
+;
+; Bits in a page table entry which are available for OS use
+;
+PAGE_LOCKED     =       200H            ; Page not swappable
+PAGE_ALLOC      =       400H            ; Memory allocated
+PAGE_UNUSED_2   =       800H            ; Unused
+
+;
+; PAGE_CLEAR is used with AND for clearing the address and the
+; present, dirty, and accessed bits of a page table entry
+;
+PAGE_PDA        =       PAGE_PRESENT OR PAGE_DIRTY OR PAGE_ACCESSED
+PAGE_CLEAR      =       0FFFH AND NOT PAGE_PDA
+
+;
+; User ID for supervisor (used in swapper table entries)
+;
+PIDX_SV         =       0FFH            ; Supervisor page
+
+
+              IFNDEF __PAGING
+
+SV_DATA         SEGMENT
+
+                EXTRN   LIN_START:DWORD         ; First usable linear address
+                EXTRN   PAGE_DIR_PHYS:DWORD     ; Phys. addr. of page directory
+                EXTRN   PAGE_DIR_SEG:WORD       ; Segment of page directory
+                EXTRN   PAGING:BYTE             ; Paging enabled
+                EXTRN   PAGE_TAB0_SEG:WORD      ; Seg. of 0th page table (VCPI)
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   INIT_PAGES:NEAR, ALLOC_PAGES:NEAR, INIT_PAGE_BMAP:NEAR
+                EXTRN   SET_PAGES:NEAR, CLEAR_TLB:NEAR, INIT_LIN_MAP:NEAR
+                EXTRN   FREE_LIN:NEAR, FREE_PAGES:NEAR, GET_FREE_PAGE:NEAR
+                EXTRN   FREE_AVAIL:NEAR, CLEAR_DIRTY:NEAR
+                EXTRN   MAYBE_MAP_PAGE:NEAR
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   INIT_PAGING:NEAR, MAP_PAGES:NEAR, RM_TO_PHYS:NEAR
+
+INIT_CODE       ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/pmint.asm
===================================================================
--- trunk/src/emx/src/dos/pmint.asm	(revision 18)
+++ trunk/src/emx/src/dos/pmint.asm	(revision 18)
@@ -0,0 +1,2599 @@
+;
+; PMINT.ASM -- Handle interrupts
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; Handle interrupts in protected mode (hardware and software interrupts).
+; Includes DOS interface.
+;
+
+__PMINT         =       1
+                INCLUDE EMX.INC
+                INCLUDE TABLES.INC
+                INCLUDE VPRINT.INC
+                INCLUDE OPRINT.INC
+                INCLUDE PAGING.INC
+                INCLUDE SYSCALL.INC
+                INCLUDE EXTAPI.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE PROFIL.INC
+                INCLUDE VCPI.INC
+                INCLUDE PMINT.INC
+                INCLUDE EXCEPT.INC
+                INCLUDE RPRINT.INC
+                INCLUDE A20.INC
+                INCLUDE DEBUG.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE OPTIONS.INC
+                INCLUDE MISC.INC
+                INCLUDE CORE.INC
+                INCLUDE RMINT.INC
+                INCLUDE FILEIO.INC
+                INCLUDE UTILS.INC
+                INCLUDE TERMIO.INC
+                INCLUDE STAT.INC
+                INCLUDE ERRORS.INC
+
+                PUBLIC  IRQ0_ADD, IRQ8_ADD
+                PUBLIC  INTERRUPT, PMINT_21H, PMINT_10H, PMINT_11H
+                PUBLIC  PMINT_14H, PMINT_16H, PMINT_17H, PMINT_31H, PMINT_33H
+                PUBLIC  DOSF_ERROR, BREAK_AFTER_IRET, NMI, INT_RM
+                PUBLIC  BUF_SEG, BUF1_SEG, BUF2_SEG, BUF_SEL, RM_CR0, PM_CR0
+                PUBLIC  V2P_CONT, V2V_CONT, INIT_BUFFER
+                PUBLIC  PMINT0_TAB, PMINT8_TAB, DBCS_LEAD_TAB
+                PUBLIC  DOS_INT         ; put into map file for debugging
+
+SER_FLAG        =       FALSE                   ; Don't use serial interface
+DEBUG_DOSDUMP   =       FALSE
+
+SV_DATA         SEGMENT
+
+PMINT0_TAB      LABEL   WORD
+                IRP     X,<0,1,2,3,4,5,6,7>
+                WORD    OFFSET SV_CODE:PMINT&X
+                ENDM
+PMINT8_TAB      LABEL   WORD
+                IRP     X,<8,9,10,11,12,13,14,15>
+                WORD    OFFSET SV_CODE:PMINT&X
+                ENDM
+
+PMHWINT_LSS     LABEL   FWORD
+PMHWINT_ESP     DWORD   ?
+PMHWINT_SS      WORD    ?
+;
+; This variable points to the interrupt stack frame of protected mode
+; (in the protected-mode stack SV_STACK). It is used for accessing the
+; stack frame in real mode. Be sure to save this variable when passing
+; signals from real mode to protected mode!
+;
+FRAME_PTR       WORD    ?
+
+;
+; Before switching back to real/virtual mode, we restore the floating point
+; related bits of CR0 saved at the beginning. We can save the bits only
+; in protected mode, as CR0 isn't readable in virtual mode. After switching
+; to protected mode, we restore the floating point related bits of CR0
+; from PM_CR0.
+;
+                DALIGN  4
+RM_CR0          DWORD   ?                       ; Real-mode CR0 (AND CR0_FPU)
+PM_CR0          DWORD   ?                       ; Prot-mode CR0 (AND CR0_FPU)
+
+;
+; Table of conversions
+;
+
+DF_INVALID      =       00H     ; syscall function not supported
+DF_NULL         =       01H     ; No parameters to be converted
+DF_WRITE        =       02H     ; Input:  src=DS:EDX, length=ECX -> DS:DX, CX
+DF_PATH         =       03H     ; Input:  pathname=DS:EDX -> DS:DX
+DF_TEXT         =       04H     ; Input:  text=DS:EDX ($ terminated) -> DS:DX
+DF_READ         =       05H     ; Output: dst=DS:DX, length=AX (CY=0 only) -> DS:EDX
+DF_SEEK         =       06H     ; Input: EDX -> CX:DX; output: DX:AX -> EAX (CY=0)
+DF_TMP          =       07H     ; Input/output: DS:DX (0 term.) + 13 bytes
+DF_INPUT        =       08H     ; Input/output: DS:DX, length=DX[0]+2
+DF_MOVE         =       09H     ; Input: DS:EDX -> DS:DX, DS:EDI -> ES:DI file names
+DF_DUP2         =       0AH     ; Force duplicate file handle
+DF_CLOSE        =       0BH     ; Close file handle
+DF_IOCTL        =       0CH     ; IOCTL, use additional table
+DF_GETCWD       =       0DH     ; Output: DS:SI -> DS:ESI (64 bytes)
+DF_EXIT         =       0EH     ; Exit
+DF_FFIRST       =       0FH     ; Find first (DS:EDX, DTA DS:ESI)
+DF_FNEXT        =       10H     ; Find next (DTA DS:ESI)
+DF_VERSION      =       11H     ; Return DOS version (and emx)
+DF_EXEC         =       12H     ; Load and execute program
+DF_RETCODE      =       13H     ; Get return code of child process
+DF_STR_BP       =       14H     ; Input: EBP null-terminated string -> ES:BP
+DF_VESA         =       15H     ; VESA BIOS (10H, AH=4FH), use additional table
+DF_VESAINFO     =       16H     ; VESA function 00H (return 256 bytes)
+DF_VESAMODE     =       17H     ; VESA function 01H (return 256 bytes)
+DF_MOU_GCURSOR  =       18H     ; Mouse function 09H (in: ES:DX -> 64 bytes)
+DF_MOU_LGCURSOR =       19H     ; Mouse function 12H (in: ES:DX -> var. bytes)
+DF_COUNTRY      =       1AH     ; Output: EDX->DS:DX (34 bytes) unless DX=-1
+DF_LOCK         =       1BH     ; Input: EDX->CX:DX, EDI->SI:DI
+DF_TRUENAME     =       1CH     ; DOS function 60H
+DF_PATH_SI      =       1DH     ; Input:  pathname=DS:ESI -> DS:SI
+DF_DUP          =       1EH     ; Duplicate file handle
+DF_VIO11        =       1FH     ; INT 10H AH=11H, use additional table (AL)
+DF_VIO12        =       20H     ; INT 10H AH=12H, use additional table (BL)
+DF_LAST         =       20H
+DF_SPARSE_END   =      0FFH     ; End of sparse table
+
+;
+; The following flag bits are used for INT 21H only.  They also apply
+; to the INT 21H IOCTL calls.
+;
+DFE             =     8000H     ; CY indicates error, convert to errno
+DFM_STDIN       =     4000H     ; Map stdin before invoking INT 21H
+DFM_STDOUT      =     2000H     ; Map stdout before invoking INT 21H
+DFM_STDIO       =     DFM_STDIN OR DFM_STDOUT
+
+DFH_IN          =     0100H     ; BX contains file handle (in)
+DFH_OUT         =     0200H     ; New file handle returned in EAX (out, CY=0)
+DFH_IN_OUT      =     DFH_IN OR DFH_OUT
+
+;
+; Get conversion flag from a table
+;
+; In:   BL      Function number
+;
+; Out:  AX      Conversion flag
+;       BX      Modified
+;
+TBGET           MACRO   TABLE
+                TABLE&_GET
+                ENDM
+
+;
+; Start a dense table
+;
+; In:   TABLE   Name of the table
+;       MAXFUN  Highest function number
+;
+DENSE_TABLE     MACRO   TABLE, MAXFUN
+TABLE           LABEL   WORD
+DENSE_NEXT      =       0
+DENSE_MAXFUN    =       MAXFUN
+TBENTRY         MACRO   FUNC, FLAG
+                DENSE_ENTRY FUNC, FLAG
+                ENDM
+TBEND           MACRO
+                DENSE_END
+                ENDM
+TABLE&_MAXFUN   =       MAXFUN
+TABLE&_GET      MACRO
+                DENSE_GET TABLE
+                ENDM
+                ENDM
+
+;
+; Add an entry to a dense table
+;
+DENSE_ENTRY     MACRO   FUNC, FLAG
+                .ERRE   FUNC GE DENSE_NEXT
+              IF FUNC NE DENSE_NEXT
+                WORD    FUNC-DENSE_NEXT DUP (DF_INVALID)
+DENSE_NEXT      =       FUNC
+              ENDIF
+                WORD    FLAG
+DENSE_NEXT      =       DENSE_NEXT+1
+                ENDM
+
+;
+; End a dense table
+;
+DENSE_END       MACRO
+              IF DENSE_NEXT NE DENSE_MAXFUN + 1
+                DENSE_ENTRY DENSE_MAXFUN, <DF_INVALID>
+              ENDIF
+                ENDM
+
+;
+; Get conversion flag from a dense table
+;
+; In:   BL      Function number
+;
+; Out:  AX      Conversion flag
+;       BX      Modified
+;
+DENSE_GET       MACRO   TABLE
+              IF TABLE&_MAXFUN NE 0FFH
+                CMP     BL, TABLE&_MAXFUN
+                JA      D_INVALID
+              ENDIF
+                XOR     BH, BH
+                SHL     BX, 1
+                MOV     AX, TABLE[BX]
+                ENDM
+
+;
+; Start a sparse table
+;
+; In:   TABLE   Name of the table
+;
+SPARSE_TABLE    MACRO   TABLE
+TABLE           LABEL   BYTE
+TBENTRY         MACRO   FUNC, FLAG
+                SPARSE_ENTRY FUNC, FLAG
+                ENDM
+TBEND           MACRO
+                SPARSE_END
+                ENDM
+TABLE&_GET      MACRO
+                SPARSE_GET TABLE
+                ENDM
+                ENDM
+
+;
+; Add an entry to a sparse table
+;
+SPARSE_ENTRY    MACRO   FUNC, FLAG
+                BYTE    FUNC
+                WORD    FLAG
+                ENDM
+
+;
+; End a sparse table
+;
+SPARSE_END      MACRO
+                SPARSE_ENTRY 00H, DF_SPARSE_END
+                ENDM
+
+;
+; Get conversion flag from a sparse table
+;
+; In:   BL      Function number
+;
+; Out:  AX      Conversion flag
+;       BX      Modified
+;
+SPARSE_GET      MACRO   TABLE
+                LOCAL   LOOP1, DONE
+                MOV     AL, BL
+                LEA     BX, TABLE - 3
+LOOP1:          ADD     BX, 3
+                CMP     BYTE PTR [BX+1], DF_SPARSE_END
+                JE      D_INVALID
+                CMP     [BX+0], AL
+                JNE     LOOP1
+                MOV     AX, [BX+1]
+                ENDM
+
+
+        DENSE_TABLE     DOS_FUNCS, 6CH
+        TBENTRY 01H, <DF_NULL OR DFM_STDIO>          ; Read keyboard and echo
+        TBENTRY 02H, <DF_NULL OR DFM_STDOUT>         ; Display character
+        TBENTRY 03H, <DF_NULL>                       ; Auxiliary input
+        TBENTRY 04H, <DF_NULL>                       ; Auxiliary output
+        TBENTRY 05H, <DF_NULL>                       ; Print character
+        TBENTRY 06H, <DF_NULL OR DFM_STDIO>          ; Direct console i/o
+        TBENTRY 07H, <DF_NULL OR DFM_STDIN>          ; Direct console input
+        TBENTRY 08H, <DF_NULL OR DFM_STDIN>          ; Read keyboard
+        TBENTRY 09H, <DF_TEXT OR DFM_STDOUT>         ; Display string
+        TBENTRY 0AH, <DF_INPUT OR DFM_STDIO>         ; Buffered keyboard input
+        TBENTRY 0BH, <DF_NULL OR DFM_STDIN>          ; Check keyboard status
+        TBENTRY 0CH, <DF_NULL OR DFM_STDIO>          ; Flush keyboard buffer
+        TBENTRY 0DH, <DF_NULL>                       ; Reset disk
+        TBENTRY 0EH, <DF_NULL>                       ; Select disk
+        TBENTRY 19H, <DF_NULL>                       ; Get current disk
+        TBENTRY 2AH, <DF_NULL>                       ; Get date
+        TBENTRY 2BH, <DF_NULL>                       ; Set date
+        TBENTRY 2CH, <DF_NULL>                       ; Get time
+        TBENTRY 2DH, <DF_NULL>                       ; Set time
+        TBENTRY 2EH, <DF_NULL>                       ; Set/reset verify flag
+        TBENTRY 30H, <DF_VERSION>                    ; Get DOS version number
+        TBENTRY 33H, <DF_NULL>                       ; Control-C check
+        TBENTRY 36H, <DF_NULL>                       ; Get disk free space
+        TBENTRY 37H, <DF_NULL>                       ; Get/set switch character
+        TBENTRY 38H, <DFE OR DF_COUNTRY>             ; Get/set country data
+        TBENTRY 39H, <DFE OR DF_PATH>                ; Create directory
+        TBENTRY 3AH, <DFE OR DF_PATH>                ; Remove directory
+        TBENTRY 3BH, <DFE OR DF_PATH>                ; Change current directory
+        TBENTRY 3CH, <DFE OR DF_PATH OR DFH_OUT>     ; Create handle
+        TBENTRY 3DH, <DFE OR DF_PATH OR DFH_OUT>     ; Open handle
+        TBENTRY 3EH, <DFE OR DF_CLOSE>               ; Close handle
+        TBENTRY 3FH, <DFE OR DF_READ OR DFH_IN>      ; Read handle
+        TBENTRY 40H, <DFE OR DF_WRITE OR DFH_IN>     ; Write handle
+        TBENTRY 41H, <DFE OR DF_PATH>                ; Delete directory entry
+        TBENTRY 42H, <DFE OR DF_SEEK OR DFH_IN>      ; Move file pointer
+        TBENTRY 43H, <DFE OR DF_PATH>                ; Get/set file attributes
+        TBENTRY 44H, <DF_IOCTL>                      ; IOCTL
+        TBENTRY 45H, <DF_DUP>                        ; Duplicate file handle
+        TBENTRY 46H, <DF_DUP2>                       ; Force duplicate handle
+        TBENTRY 47H, <DFE OR DF_GETCWD>              ; Get current directory
+        TBENTRY 4BH, <DFE OR DF_EXEC>                ; Load and execute program
+        TBENTRY 4CH, <DF_EXIT>                       ; End process
+        TBENTRY 4DH, <DF_RETCODE>                    ; Get rc of child process
+        TBENTRY 4EH, <DFE OR DF_FFIRST>              ; Find first file
+        TBENTRY 4FH, <DFE OR DF_FNEXT>               ; Find next file
+        TBENTRY 54H, <DF_NULL>                       ; Get verify state
+        TBENTRY 56H, <DFE OR DF_MOVE>                ; Change directory entry
+        TBENTRY 57H, <DFE OR DF_NULL OR DFH_IN>      ; Time/date of file
+        TBENTRY 58H, <DFE OR DF_NULL>                ; Get/set alloc strat
+        TBENTRY 59H, <DF_NULL>                       ; Get extended error
+        TBENTRY 5AH, <DFE OR DF_TMP OR DFH_OUT>      ; Create temporary file
+        TBENTRY 5BH, <DFE OR DF_PATH OR DFH_OUT>     ; Create new file
+        TBENTRY 5CH, <DFE OR DF_LOCK OR DFH_IN>      ; Lock
+        TBENTRY 60H, <DFE OR DF_TRUENAME>            ; Canonicalize path
+        TBENTRY 66H, <DFE OR DF_NULL>                ; Get/set global cp table
+        TBENTRY 67H, <DFE OR DF_NULL>                ; Set handle count
+        TBENTRY 68H, <DFE OR DF_NULL OR DFH_IN>      ; Commit file
+        TBENTRY 6AH, <DFE OR DF_NULL OR DFH_IN>      ; Commit file
+        TBENTRY 6CH, <DFE OR DF_PATH_SI OR DFH_OUT>  ; Extended open/create
+        TBEND
+
+        DENSE_TABLE     IOCTL_FUNCS, 0BH
+        TBENTRY 00H, <DFE OR DF_NULL OR DFH_IN>      ; Get device data
+        TBENTRY 01H, <DFE OR DF_NULL OR DFH_IN>      ; Set device data
+        TBENTRY 02H, <DFE OR DF_WRITE OR DFH_IN>     ; Send control data (char)
+        TBENTRY 03H, <DFE OR DF_READ OR DFH_IN>      ; Receive ctl data (char)
+        TBENTRY 04H, <DFE OR DF_WRITE>               ; Send ctl data (block)
+        TBENTRY 05H, <DFE OR DF_READ>                ; Receive ctl data (block)
+        TBENTRY 06H, <DFE OR DF_NULL OR DFH_IN>      ; Check input status
+        TBENTRY 07H, <DFE OR DF_NULL OR DFH_IN>      ; Check output status
+        TBENTRY 08H, <DFE OR DF_NULL>                ; Is changable
+        TBENTRY 09H, <DFE OR DF_NULL>                ; Is redirected block
+        TBENTRY 0AH, <DFE OR DF_NULL OR DFH_IN>      ; Is redirected handle
+        TBENTRY 0BH, <DFE OR DF_NULL>                ; Retry
+        TBEND
+
+        DENSE_TABLE     VIO_FUNCS, 0FFH
+        TBENTRY 00H, <DF_NULL>                       ; Set video mode
+        TBENTRY 01H, <DF_NULL>                       ; Set cursor shape
+        TBENTRY 02H, <DF_NULL>                       ; Set cursor position
+        TBENTRY 03H, <DF_NULL>                       ; Set cursor pos and size
+        TBENTRY 04H, <DF_NULL>                       ; Read light pen position
+        TBENTRY 05H, <DF_NULL>                       ; Select display page
+        TBENTRY 06H, <DF_NULL>                       ; Scroll up
+        TBENTRY 07H, <DF_NULL>                       ; Scroll down
+        TBENTRY 08H, <DF_NULL>                       ; Read char and attribute
+        TBENTRY 09H, <DF_NULL>                       ; Write char and attribute
+        TBENTRY 0AH, <DF_NULL>                       ; Write character
+        TBENTRY 0BH, <DF_NULL>                       ; Set palette
+        TBENTRY 0CH, <DF_NULL>                       ; Write graphics pixel
+        TBENTRY 0DH, <DF_NULL>                       ; Read graphics pixel
+        TBENTRY 0EH, <DF_NULL>                       ; Teletype output
+        TBENTRY 0FH, <DF_NULL>                       ; Get current video mode
+        TBENTRY 10H, <DF_NULL>                       ; Palette (AL != 02H,
+                                                     ; 09H, 12H, 17H)
+        TBENTRY 11H, <DF_VIO11>                      ; Font
+        TBENTRY 12H, <DF_VIO12>                      ; Miscellaneous stuff
+        TBENTRY 13H, <DF_STR_BP>                     ; Write string
+        TBENTRY 14H, <DF_INVALID>                    ; LCD
+        TBENTRY 15H, <DF_INVALID>                    ; Get parameters
+        TBENTRY 1AH, <DF_NULL>                       ; Display combination
+        TBENTRY 1BH, <DF_INVALID>                    ; State information
+        TBENTRY 1CH, <DF_INVALID>                    ; Save/restore state
+        TBENTRY 1FH, <DF_INVALID>                    ; XGA DMQS
+        TBENTRY 30H, <DF_INVALID>                    ; 3270 stuff
+        TBENTRY 40H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 41H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 42H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 43H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 44H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 45H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 46H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 47H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 48H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 49H, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 4AH, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 4BH, <DF_NULL>                       ; Hercules GRAFIX / FRIEZE
+        TBENTRY 4CH, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 4DH, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 4EH, <DF_NULL>                       ; Hercules GRAFIX
+        TBENTRY 4FH, <DF_VESA>                       ; VESA
+        TBENTRY 6FH, <DF_NULL>                       ; Various functions
+        TBENTRY 0F0H, <DF_NULL>                      ; EGA register interface
+        TBENTRY 0F1H, <DF_NULL>                      ; EGA register interface
+        TBENTRY 0F6H, <DF_NULL>                      ; EGA register interface
+        TBEND
+
+        DENSE_TABLE     VESA_FUNCS, 08H
+        TBENTRY 00H, <DF_VESAINFO>                   ; Get SVGA info
+        TBENTRY 01H, <DF_VESAMODE>                   ; Get SVGA mode info
+        TBENTRY 02H, <DF_NULL>                       ; Set mode
+        TBENTRY 03H, <DF_NULL>                       ; Get mode
+        TBENTRY 04H, <DF_INVALID>                    ; Save/restore state
+        TBENTRY 05H, <DF_NULL>                       ; Memory control
+        TBENTRY 06H, <DF_NULL>                       ; Scan line length
+        TBENTRY 07H, <DF_NULL>                       ; Display start
+        TBENTRY 08H, <DF_NULL>                       ; DAC palette control
+        TBEND
+
+        DENSE_TABLE     VIO11_FUNCS, 24H
+        TBENTRY 01H, <DF_NULL>                       ; Load ROM patterns 8x14
+        TBENTRY 02H, <DF_NULL>                       ; Load ROM patterns 8x8
+        TBENTRY 03H, <DF_NULL>                       ; Set block specifier
+        TBENTRY 04H, <DF_NULL>                       ; Load ROM charset 8x14
+        TBENTRY 11H, <DF_NULL>                       ; Load ROM patterns 8x14
+        TBENTRY 12H, <DF_NULL>                       ; Load ROM patterns 8x8
+        TBENTRY 14H, <DF_NULL>                       ; Load ROM charset 8x14
+        TBENTRY 22H, <DF_NULL>                       ; Set ROM graph chars 8x14
+        TBENTRY 23H, <DF_NULL>                       ; Set ROM graph chars 8x8
+        TBENTRY 24H, <DF_NULL>                       ; Set ROM graph chars 8x16
+        TBEND
+
+        SPARSE_TABLE     VIO12_FUNCS
+        TBENTRY 10H, <DF_NULL>                       ; Get EGA info
+        TBENTRY 20H, <DF_NULL>                       ; Alternate PrtSc
+        TBENTRY 30H, <DF_NULL>                       ; Select vert. resolution
+        TBENTRY 31H, <DF_NULL>                       ; Palette loading
+        TBENTRY 32H, <DF_NULL>                       ; Video addressing
+        TBENTRY 33H, <DF_NULL>                       ; Gray-scale summing
+        TBENTRY 34H, <DF_NULL>                       ; Cursor emulation
+        TBENTRY 36H, <DF_NULL>                       ; Video refresh control
+        TBENTRY 37H, <DF_NULL>                       ; Mainframe interact. sup
+        TBEND
+
+        DENSE_TABLE     MOU_FUNCS, 6DH
+        TBENTRY 00H, <DF_NULL>                       ; Reset
+        TBENTRY 01H, <DF_NULL>                       ; Show mouse cursor
+        TBENTRY 02H, <DF_NULL>                       ; Hide mouse cursor
+        TBENTRY 03H, <DF_NULL>                       ; Get position & status
+        TBENTRY 04H, <DF_NULL>                       ; Position mouse cursor
+        TBENTRY 05H, <DF_NULL>                       ; Get button down data
+        TBENTRY 06H, <DF_NULL>                       ; Get button up data
+        TBENTRY 07H, <DF_NULL>                       ; Define hor. range
+        TBENTRY 08H, <DF_NULL>                       ; Define ver. range
+        TBENTRY 09H, <DF_MOU_GCURSOR>                ; Define graphics cursor
+        TBENTRY 0AH, <DF_NULL>                       ; Define text cursor
+        TBENTRY 0BH, <DF_NULL>                       ; Read motion counters
+        TBENTRY 0CH, <DF_INVALID>                    ; Define IRQ routine
+        TBENTRY 0DH, <DF_NULL>                       ; Light pen emulation on
+        TBENTRY 0EH, <DF_NULL>                       ; Light pen emulation off
+        TBENTRY 0FH, <DF_NULL>                       ; Define mickeys/pixel
+        TBENTRY 10H, <DF_NULL>                       ; Define update region
+        TBENTRY 11H, <DF_NULL>                       ; GENIUS: # of buttons
+        TBENTRY 12H, <DF_MOU_LGCURSOR>               ; Graphics cursor block
+        TBENTRY 13H, <DF_NULL>                       ; Double-speed threshold
+        TBENTRY 14H, <DF_INVALID>                    ; Exchange IRQ routines
+        TBENTRY 15H, <DF_NULL>                       ; Get state buffer size
+        TBENTRY 16H, <DF_INVALID>                    ; Save state
+        TBENTRY 17H, <DF_INVALID>                    ; Restore state
+        TBENTRY 18H, <DF_INVALID>                    ; Set event handler
+        TBENTRY 19H, <DF_INVALID>                    ; Return event handler
+        TBENTRY 1AH, <DF_NULL>                       ; Set sensitivity
+        TBENTRY 1BH, <DF_NULL>                       ; Return sensitivity
+        TBENTRY 1CH, <DF_NULL>                       ; Set interrupt rate
+        TBENTRY 1DH, <DF_NULL>                       ; Define display page
+        TBENTRY 1EH, <DF_NULL>                       ; Return display page
+        TBENTRY 1FH, <DF_NULL>                       ; Disable mouse driver
+        TBENTRY 20H, <DF_NULL>                       ; Enable mouse driver
+        TBENTRY 21H, <DF_NULL>                       ; Software reset
+        TBENTRY 22H, <DF_NULL>                       ; Set language
+        TBENTRY 23H, <DF_NULL>                       ; Get language
+        TBENTRY 24H, <DF_NULL>                       ; Get misc. info
+        TBENTRY 25H, <DF_NULL>                       ; Get general driver info
+        TBENTRY 26H, <DF_NULL>                       ; Get maximum coordinates
+        TBENTRY 27H, <DF_NULL>                       ; Get masks & counts
+        TBENTRY 28H, <DF_NULL>                       ; Set video mode
+        TBENTRY 29H, <DF_INVALID>                    ; Enumerate video modes
+        TBENTRY 2AH, <DF_NULL>                       ; Get cursor hot spot
+        TBENTRY 2BH, <DF_INVALID>                    ; Load acceleration prof.
+        TBENTRY 2CH, <DF_INVALID>                    ; Get acceleration prof.
+        TBENTRY 2DH, <DF_INVALID>                    ; Select acc. profile
+        TBENTRY 2EH, <DF_INVALID>                    ; Set acc. profile names
+        TBENTRY 2FH, <DF_NULL>                       ; Hardware reset
+        TBENTRY 30H, <DF_NULL>                       ; Ballpoint information
+        TBENTRY 31H, <DF_NULL>                       ; Max. virtual coordinates
+        TBENTRY 32H, <DF_NULL>                       ; Get active adv. funcs.
+        TBENTRY 33H, <DF_INVALID>                    ; Switch settings etc.
+        TBENTRY 34H, <DF_INVALID>                    ; Get initialization file
+        TBENTRY 35H, <DF_NULL>                       ; LCD large pointer
+        TBENTRY 4DH, <DF_INVALID>                    ; Get copyright string
+        TBENTRY 6DH, <DF_INVALID>                    ; Get version string
+        TBEND
+
+;
+; Buffer for DOS interface
+;
+BUF_SEG         WORD    ?               ; Current buffer (BUF?_SEG)
+BUF_SEL         WORD    ?               ; Current buffer (G_BUF?_SEL)
+
+BUF1_SEG        WORD    ?               ; 1st buffer (64KB)
+BUF2_SEG        WORD    ?               ; 2nd buffer (4KB, for swapper)
+
+COUNTRYDATA     LABEL   BYTE
+CD_DATE         WORD    ?
+CD_CURRENCY     BYTE    5 DUP (?)
+CD_1000_SEP     BYTE    2 DUP (?)
+CD_DECIMAL_SEP  BYTE    2 DUP (?)
+CD_DATE_SEP     BYTE    2 DUP (?)
+CD_TIME_SEP     BYTE    2 DUP (?)
+CD_FLAGS        BYTE    ?
+CD_CURRENCY_N   BYTE    ?
+CD_TIME         BYTE    ?
+CD_CASEMAP      DWORD   ?
+CD_LIST_SEP     BYTE    2 DUP (?)
+CD_RESERVED     BYTE    10 DUP (?)
+
+;
+; This table contains 256 bits; if bit i is set, byte i is a DBCS
+; lead byte.
+;
+DBCS_LEAD_TAB   WORD    (256 / 8 / 2) DUP (?)
+
+$INTERRUPT      BYTE    "Unexpected interrupt", 0
+$NMI            BYTE    "Nonmaskable interrupt (NMI) at ", 0
+$BAD_MOU_FUNC   BYTE    "Illegal moucall function code: ", 0
+$BAD_DOS_FUNC   BYTE    "Illegal syscall function code: ", 0
+$BAD_VIO_FUNC   BYTE    "Illegal viocall function code: ", 0
+$DOS_PARAM      BYTE    "Invalid arguments for syscall ", 0
+$EMERGENCY      BYTE    "Emergency exit", 0
+
+
+              IF DEBUG_DOSDUMP
+$DOSDUMP        BYTE    "DOSDUMP.000"
+$DOSDUMP_C      =       THIS BYTE - 1
+                BYTE    0
+              ENDIF
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                .386P
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+                TALIGN  2
+CONV_TAB        WORD    D_INVALID       ; DF_INVALID
+                WORD    D_NULL          ; DF_NULL
+                WORD    D_WRITE         ; DF_WRITE
+                WORD    D_PATH          ; DF_PATH
+                WORD    D_TEXT          ; DF_TEXT
+                WORD    D_READ          ; DF_READ
+                WORD    D_SEEK          ; DF_SEEK
+                WORD    D_TMP           ; DF_TMP
+                WORD    D_INPUT         ; DF_INPUT
+                WORD    D_MOVE          ; DF_MOVE
+                WORD    D_DUP2          ; DF_DUP2
+                WORD    D_CLOSE         ; DF_CLOSE
+                WORD    D_INVALID       ; DF_IOCTL (handled before jumping)
+                WORD    D_GETCWD        ; DF_GETCWD
+                WORD    D_EXIT          ; DF_EXIT
+                WORD    D_FFIRST        ; DF_FFIRST
+                WORD    D_FNEXT         ; DF_FNEXT
+                WORD    D_VERSION       ; DF_VERSION
+                WORD    D_EXEC          ; DF_EXEC
+                WORD    D_RETCODE       ; DF_RETCODE
+                WORD    D_STR_BP        ; DF_STR_BP
+                WORD    D_VESA          ; DF_VESA
+                WORD    D_VESAINFO      ; DF_VESAINFO
+                WORD    D_VESAMODE      ; DF_VESAMODE
+                WORD    D_MOU_GCURSOR   ; DF_MOU_GCURSOR
+                WORD    D_MOU_LGCURSOR  ; DF_MOU_LGCURSOR
+                WORD    D_COUNTRY       ; DF_COUNTRY
+                WORD    D_LOCK          ; DF_LOCK
+                WORD    D_TRUENAME      ; DF_TRUENAME
+                WORD    D_PATH_SI       ; DF_PATH_SI
+                WORD    D_DUP           ; DF_DUP
+                WORD    D_VIO11         ; DF_VIO11
+                WORD    D_VIO12         ; DF_VIO12
+
+                .ERRE   ($-CONV_TAB)/2 EQ DF_LAST+1
+
+
+;
+; All undefined interrupts go here
+;
+; This cannot happen, as undefined interrupts cannot be called
+; from the user program (CPL=3 & DPL=0) and all hardware interrupts
+; have their own vector. Yes, the supervisor could issue an
+; undefined software interrupt, but it doesn't. At least I hope so.
+;
+
+                ASSUME  DS:NOTHING
+INTERRUPT:      MOV     AX, G_SV_DATA_SEL
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                LEA     EDX, $INTERRUPT
+                CALL    INT_MSG
+                JMP     SHORT $
+
+                ASSUME  DS:NOTHING
+NMI:            MOV     AX, G_SV_DATA_SEL
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                LEA     EDX, $NMI
+                CALL    INT_MSG
+                MOV     AX, SS:[ESP+4]          ; CS
+                CALL    VWORD
+                MOV     AL, ":"
+                CALL    VCHAR
+                MOV     EAX, SS:[ESP+0]         ; EIP
+                CALL    VDWORD
+              IF FALSE
+                MOV     AL, " "
+                CALL    VCHAR
+                MOV     EAX, SS:[ESP+8]         ; EFLAGS
+                CALL    VDWORD
+              ENDIF
+                JMP     SHORT $
+
+;
+; Display fatal error message (unexpected interrupt / NMI)
+;
+                ASSUME  DS:SV_DATA
+INT_MSG         PROC    NEAR
+                MOV     AX, G_VIDEO_SEL
+                MOV     ES, AX
+                CALL    VCLS
+                CALL    VTEXT
+                RET
+INT_MSG         ENDP
+
+
+;
+; Backward jump here (for processors with BIG prefetch queue)
+;
+RM_INT1:        XOR     EAX, EAX
+                MOV     CR3, EAX                ; Clear TLB
+                JMP     FAR PTR RM_INT2         ; Reload CS, real mode!
+
+;
+; Call the real-mode interrupt INT_NO
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+INT_RM0         PROC    FAR
+                CLI
+                CMP     PROFIL_COUNT, 0         ; Suspend generating RTC
+                JE      SHORT NOPROF            ; interrupts for the profiler
+                CALL    PROFIL_SUSPEND
+                TALIGN  4
+NOPROF:         MOV     PMHWINT_ESP, ESP        ; Save stack pointer
+                MOV     PMHWINT_SS, SS          ; and stack segment
+                MOV     FRAME_PTR, BP           ; After CLI!!!
+                MOV     EAX, CR0
+                AND     EAX, CR0_FPU            ; Keep only FPU bits
+                MOV     PM_CR0, EAX             ; Save for switching back to PM
+                MOV     EAX, CR0
+                AND     EAX, NOT CR0_FPU        ; Restore floating point
+                OR      EAX, RM_CR0             ; bits of real/virtual mode
+                MOV     CR0, EAX
+                XOR     AX, AX
+                LLDT    AX                      ; Zero LDTR
+                CMP     VCPI_FLAG, FALSE        ; Running under VCPI server?
+                JNE     INT_VCPI                ; Yes -> let the server do it
+                MOV     AX, G_REAL_SEL          ; Load values suitable for
+                MOV     DS, AX                  ; real mode into all the
+                ASSUME  DS:NOTHING              ; segment registers
+                MOV     ES, AX                  ; (see below for CS)
+                MOV     FS, AX
+                MOV     GS, AX
+                MOV     SS, AX
+                MOV     EAX, CR0
+                AND     EAX, NOT (CR0_PG OR CR0_PE) ; Turn off paging and PM
+                MOV     CR0, EAX
+                JMP     SHORT RM_INT1           ; Flush prefetch queue
+;
+; ... real mode ...
+;
+                ASSUME  DS:NOTHING
+                TALIGN  4
+RM_INT9::       MOV     AX, G_SV_DATA_SEL
+                MOV     DS, AX                  ; Make data accessible
+                ASSUME  DS:SV_DATA
+                LSS     ESP, PMHWINT_LSS        ; Restore stack
+                AND     TSS_BUSY, NOT 2         ; Otherwise exception on LTR
+                MOV     AX, G_TSS_SEL
+                LTR     AX                      ; Setup task
+                CMP     PAGING, FALSE           ; Use paging?
+                JE      SHORT RM_INT10          ; No  -> skip
+                MOV     EAX, PAGE_DIR_PHYS
+                MOV     CR3, EAX                ; Setup page directory
+                MOV     EAX, CR0
+                OR      EAX, CR0_PG             ; Enable paging
+                MOV     CR0, EAX
+;
+; Common code for `manual' return from real mode and for VCPI
+;
+RM_INT10:       MOV     EAX, CR0
+                AND     EAX, NOT CR0_FPU        ; Restore floating point
+                OR      EAX, PM_CR0             ; bits of protected mode
+                MOV     CR0, EAX
+                RET                             ; FAR return!!!
+
+;
+; When running under a VCPI server, we return here from virtual mode
+;
+
+                ASSUME  DS:NOTHING
+                TALIGN  4
+V2P_CONT::      MOV     AX, G_SV_DATA_SEL
+                MOV     DS, AX                  ; Make data accessible
+                ASSUME  DS:SV_DATA
+                MOV     ES, AX
+                MOV     FS, AX
+                MOV     GS, AX
+                LSS     ESP, PMHWINT_LSS        ; Setup stack
+                JMP     SHORT RM_INT10          ; Floating point bits of CR0
+
+INT_RM0         ENDP
+
+
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+INT_RM          PROC    NEAR
+                PUSH    EBP                     ; Save EBP
+                PUSHFD                          ; Save flags
+                SLDT    AX
+                PUSH    AX                      ; Save LDTR
+                CALLF16 G_SV_CODE_SEL, INT_RM0  ; FAR call!
+                MOV     AX, G_SV_DATA_SEL       ; Initialize all segment
+                MOV     DS, AX                  ; registers
+                MOV     ES, AX
+                MOV     FS, AX
+                MOV     GS, AX
+;
+; Important: Restore LDTR of interrupted program. Real/virtual mode may have
+; changed LDTR (INT 15H: extended memory). Actually, we zero LDTR after
+; entering real mode. We need the LDTR for popping the segment registers
+; of the interrupted program, which may reference the LDT.
+;
+                POP     AX
+                LLDT    AX                      ; Restore LDTR
+                CMP     PROFIL_COUNT, 0
+                JE      SHORT NOPROF
+                CLI                             ; Resume generating RTC
+                CALL    PROFIL_RESUME           ; interrupts for the profiler
+                TALIGN  4
+NOPROF:         POPFD                           ; Restore flags
+                POP     EBP                     ; Restore EBP
+                RET                             ; Done
+INT_RM          ENDP
+
+;
+; This is the first interrupt vector used for redirecting IRQ0..IRQ7
+; and IRQ8..IRQ15, respectively. These variables are located in SV_CODE
+; as they are accessed with unknown segment registers (only CS is known
+; to be SV_CODE_SEL).
+;
+IRQ0_ADD        BYTE    ?                       ; Initialized by INIT_INT
+IRQ8_ADD        BYTE    ?                       ; Initialized by INIT_INT
+
+
+;
+; Entry points for hardware interrupts IRQ 0 to IRQ 7.
+;
+
+                ASSUME  DS:NOTHING
+
+                IRP     X, <0,1,2,3,4,5,6,7>
+                TALIGN  4
+PMINT&X:        PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, &X * 0100H + &X     ; Compute real-mode interrupt
+                ADD     CL, IRQ0_ADD            ; number (in SV_CODE segment!)
+                JMP     PMINT                   ; Common code
+                ENDM
+
+;
+; Entry points for hardware interrupts IRQ 8 to IRQ 15.
+;
+
+                ASSUME  DS:NOTHING
+
+                IRP     X, <8,9,10,11,12,13,14,15>
+                TALIGN  4
+PMINT&X:        PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, &X * 0100H + &X-8   ; Compute real-mode interrupt
+                ADD     CL, IRQ8_ADD            ; number (in SV_CODE segment!)
+                JMP     PMINT                   ; Common code
+                ENDM
+
+;
+; Entry point for software interrupt 10H (video interface).
+;
+                TALIGN  4
+PMINT_10H:      PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, 1010H               ; Real-mode interrupt number
+                JMP     SHORT PMINT             ; Common code
+
+;
+; Entry point for software interrupt 11H (equipment).
+;
+                TALIGN  4
+PMINT_11H:      PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, 1111H               ; Real-mode interrupt number
+                JMP     SHORT PMINT             ; Common code
+
+;
+; Entry point for software interrupt 14H (RS-232 interface).
+;
+                TALIGN  4
+PMINT_14H:      PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, 1414H               ; Real-mode interrupt number
+                JMP     SHORT PMINT             ; Common code
+
+;
+; Entry point for software interrupt 16H (keyboard interface).
+;
+                TALIGN  4
+PMINT_16H:      PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, 1616H               ; Real-mode interrupt number
+                JMP     SHORT PMINT             ; Common code
+
+;
+; Entry point for software interrupt 17H (printer interface).
+;
+                TALIGN  4
+PMINT_17H:      PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, 1717H               ; Real-mode interrupt number
+                JMP     SHORT PMINT             ; Common code
+
+;
+; Entry point for software interrupt 21H (DOS interface).
+;
+                TALIGN  4
+PMINT_21H:      PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, 2121H               ; Real-mode interrupt number
+                JMP     SHORT PMINT             ; Common code
+
+;
+; Entry point for software interrupt 31H (DOS extender interface).
+;
+                TALIGN  4
+PMINT_31H:      PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, 3131H               ; Real-mode interrupt number
+                JMP     SHORT PMINT             ; Common code
+
+;
+; Entry point for software interrupt 33H (mouse interface).
+;
+                TALIGN  4
+PMINT_33H:      PUSH    EAX                     ; Mock error code
+                PUSHAD                          ; Save all general registers
+                MOV     CX, 3333H               ; Real-mode interrupt number
+                JMP     SHORT PMINT             ; Common code
+
+;
+; Common code for protected-mode interrupts (hardware and software interrupts).
+;
+; Note: this code runs with interrupts masked.
+;
+                TALIGN  4
+PMINT:          PUSH    DS                      ; Save segment registers
+                PUSH    ES
+                PUSH    FS
+                PUSH    GS
+              IF SER_FLAG
+                SERIAL  "I"
+              ENDIF
+                CLD
+                MOV     AX, G_SV_DATA_SEL
+                MOV     DS, AX                  ; Make data segment available
+                ASSUME  DS:SV_DATA
+                MOV     EBP, ESP                ; Setup stack frame pointer
+                SUB     ESP, FRAME_SIZE         ; Local variables
+PMINT_STACK_SNAP_SHOT:                          ; For documentation only
+                MOV     INT_NO, CL              ; Save interrupt number
+                MOV     HW_INT_VEC, CH
+                CMP     CH, 8                   ; RTC interrupt?
+                JE      RTC_INT                 ; Yes -> profile or reflect
+              IF FLOATING_POINT
+                CMP     CH, 13                  ; Coprocessor interrupt?
+                JE      COPROC                  ; Yes -> map to SIGFPE
+SKIP_COPROC:
+              ENDIF
+                CMP     CL, 21H                 ; DOS call interrupt?
+                JE      DOSCALL                 ; Yes ->
+                CMP     CL, 10H                 ; Video API interrupt?
+                JE      VIOCALL                 ; Yes ->
+                CMP     CL, 11H                 ; Equiment interrupt?
+                JE      GENERIC_CALL            ; Yes ->
+                CMP     CL, 14H                 ; RS-232 API interrupt?
+                JE      GENERIC_CALL            ; Yes ->
+                CMP     CL, 16H                 ; Keyboard API interrupt?
+                JE      GENERIC_CALL            ; Yes ->
+                CMP     CL, 17H                 ; Printer API interrupt?
+                JE      GENERIC_CALL            ; Yes ->
+                CMP     CL, 31H                 ; DOS extender API interrupt?
+                JE      EXT_CALL                ; Yes ->
+                CMP     CL, 33H                 ; Mouse API interrupt?
+                JE      MOUCALL                 ; Yes ->
+;
+; This is the simple case: just reissue the interrupt in real mode.
+;
+REFLECT:        CALL    INT_RM
+;
+; The STI in the following line has been removed in emx 0.8b to fix a stack
+; overflow problem with high speed communications and an interrupt controller
+; reprogrammed to AEOI mode.
+;
+;***            STI                             ; At the risk of stack overflow
+;
+; Back in protected mode, return to interrupted code (and check for signals)
+;
+PMINT_RET:      CMP     EMERGENCY_FLAG, FALSE   ; Emergency exit pending?
+                JE      SHORT SKIP_EMGCY
+                CALL    EMERGENCY_EXIT
+SKIP_EMGCY:     ADD     ESP, FRAME_SIZE         ; Remove local variables
+                CALL    SIG_DELIVER_PENDING
+              IF SER_FLAG
+                SERIAL  "i"
+              ENDIF
+                POP     GS                      ; Restore segment registers
+                POP     FS
+                POP     ES
+                POP     DS
+                POPAD                           ; Restore general registers
+                NOP                             ; Avoid 386 bug
+                ADD     ESP, 4                  ; Remove error code
+                IRETD                           ; End of interrupt routine
+                                                ; 32-bit interrupt gate!!!
+
+
+;
+; Syscall functions
+;
+                TALIGN  4
+SYSCALL_1:      CALL    DO_SYSCALL
+                JMP     PMINT_RET
+
+;
+; Emergency exit
+;
+EMERGENCY_EXIT  PROC    NEAR
+                MOV     EMERGENCY_FLAG, FALSE
+                LEA     EDX, $EMERGENCY
+                CALL    OTEXT
+                CALL    OCRLF
+                MOV     AX, 4CFFH
+                INT     21H
+EMERGENCY_EXIT  ENDP
+
+;
+; Real-time clock interrupt (IRQ8).
+;
+                TALIGN  4
+RTC_INT:        CMP     PROFIL_COUNT, 0
+                JE      REFLECT
+                CALL    PROFIL_TICK
+                JMP     PMINT_RET
+
+;
+; Coprocessor interrupt (IRQ13).  Reset the BUSY pin and raise SIGFPE.
+;
+                TALIGN  4
+COPROC:         CMP     MACHINE, MACH_PC        ; PC architecture?
+                JNE     SKIP_COPROC             ; No  -> give up
+;
+; Reset the interrupt condition
+;
+                MOV     AL, 00H                 ; Send a byte of zeros
+                OUT     0F0H, AL                ; to reset the BUSY pin
+                MOV     AL, 20H                 ; Send EOI command to the
+                OUT     0A0H, AL                ; slave interrupt controller,
+                OUT     20H, AL                 ; master interrupt controller
+                FNCLEX                          ; Clear exceptions
+;
+; Raise SIGFPE
+;
+                MOV     AL, 16                  ; Exception 16: Coproc error
+                JMP     EXCEPT_FAKE             ; Fake an exception
+
+COPROC_DONE:    JMP     PMINT_RET
+
+;
+; DOS extender interface.
+;
+                TALIGN  4
+EXT_CALL:       STI
+                CALL    EXTAPI
+                JMP     PMINT_RET
+
+;
+; DOS interface.
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+                TALIGN  4
+DOSCALL:        STI                             ; Be venturous!
+                AND     I_EFLAGS, NOT FLAG_C    ; Clear carry flag (no error)
+                MOV     EAX, I_EAX              ; Get EAX (we need only AX)
+                CMP     AH, 7FH                 ; Syscall functions?
+                JE      SHORT SYSCALL_1         ; Yes ->
+                CALL    REGS_TO_RM              ; Set real-mode registers
+;
+; Apply umask for __creat()
+;
+                CMP     BYTE PTR RM_AX[1], 3CH  ; Create handle?
+                JNE     SHORT SKIP_CREAT        ; No  -> skip
+                MOV     BX, PROCESS_PTR         ; Current process
+                CMP     BX, NO_PROCESS          ; In user code?
+                JE      SHORT SKIP_CREAT        ; No  -> keep mode
+                TEST    (PROCESS PTR [BX]).P_UMASK, S_IWRITE
+                JZ      SHORT SKIP_CREAT        ; Write perm. -> keep mode
+                OR      RM_CX, 1                ; Set read-only attribute
+                TALIGN  4
+;
+; Get conversion flag for INT 21H functions, convert handles if appropriate.
+;
+SKIP_CREAT:     MOV     INP_HANDLE, NO_FILE_HANDLE  ; Handle not converted
+                MOV     BL, BYTE PTR RM_AX[1]   ; AH
+                TBGET   DOS_FUNCS               ; Get conversion flag
+                CMP     AL, DF_IOCTL            ; Use second table?
+                JNE     SHORT DOSCALL_1
+                MOV     BL, BYTE PTR RM_AX[0]   ; AL
+                TBGET   IOCTL_FUNCS             ; Get conversion flag
+DOSCALL_1:      MOV     CONV_FLAG, AX           ; Save conversion flag
+                CMP     PROCESS_PTR, NO_PROCESS ; Translate handles?
+                JE      SHORT DOSCALL_9         ; No -> skip
+                TEST    CONV_FLAG, DFH_IN       ; Convert handle (input)?
+                JZ      SHORT DOSCALL_2         ; No -> check for output
+                MOV     AX, RM_BX               ; Get process' handle
+                MOV     INP_HANDLE, AX          ; Save this value
+                CALL    GET_HANDLE              ; Convert to DOS handle
+                MOV     RM_BX, AX               ; and store to BX
+DOSCALL_2:      TEST    CONV_FLAG, DFH_OUT      ; Convert handle (output)?
+                JZ      SHORT DOSCALL_3         ; No -> skip
+                MOV     AX, NO_FILE_HANDLE
+                CALL    NEW_HANDLE              ; Slot available?
+                JNC     SHORT DOSCALL_3         ; Yes -> continue
+                MOV     I_EAX, EMFILE           ; Too many open files
+                OR      BYTE PTR I_EFLAGS, FLAG_C ; Set carry flag
+                JMP     PMINT_RET               ; Return to caller
+;
+; Check whether identical mapping should be used for handles 0 and 1.
+; This can be done after calling GET_HANDLE because all functions
+; for which DFM_STDIN or DFM_STDOUT is set, don't use an explicit
+; file handle (that's why DFM_STDIN and DFM_STDOUT are required in
+; the first place).
+;
+DOSCALL_3:      TEST    CONV_FLAG, DFM_STDIN    ; Remap handle 0?
+                JZ      SHORT DOSCALL_4
+                MOV     AX, 0
+                CALL    MAP_HANDLE
+                JC      SHORT MAP_ERROR
+DOSCALL_4:      TEST    CONV_FLAG, DFM_STDOUT   ; Remap handle 1?
+                JZ      SHORT DOSCALL_9
+                MOV     AX, 1
+                CALL    MAP_HANDLE
+                JNC     SHORT DOSCALL_9
+MAP_ERROR:      MOV     WORD PTR I_EAX+0, AX
+                MOV     WORD PTR I_EAX+2, 0
+                OR      BYTE PTR I_EFLAGS, FLAG_C ; Set carry flag
+                JMP     PMINT_RET
+
+;
+; Dispatcher for INT 21H
+;
+                TALIGN  4
+DOSCALL_9:      MOVZX   BX, BYTE PTR CONV_FLAG  ; Get conversion flag
+                SHL     BX, 1
+                JMP     CONV_TAB[BX]
+
+;
+; Dispatcher for other interrupts (use AX as conversion flag)
+;
+                TALIGN  4
+INTCALL:        MOV     CONV_FLAG, AX           ; No conversion at DOSCALL_RET
+                MOV     BX, AX
+                SHL     BX, 1
+                JMP     CONV_TAB[BX]
+
+;
+; INT 10H -- video BIOS
+;
+VIOCALL:        MOV     INP_HANDLE, NO_FILE_HANDLE
+                CALL    REGS_TO_RM
+                MOV     BL, BYTE PTR RM_AX[1]   ; AH
+                TBGET   VIO_FUNCS               ; Get conversion flag
+                JMP     SHORT INTCALL
+
+D_VESA:         MOV     BL, BYTE PTR RM_AX[0]   ; AL
+                TBGET   VESA_FUNCS              ; Get conversion flag
+                JMP     SHORT INTCALL
+
+D_VIO11:        MOV     BL, BYTE PTR RM_AX[0]   ; AL
+                TBGET   VIO11_FUNCS             ; Get conversion flag
+                JMP     SHORT INTCALL
+
+D_VIO12:        MOV     BL, BYTE PTR RM_BX[0]   ; BL
+                TBGET   VIO12_FUNCS             ; Get conversion flag
+                JMP     SHORT INTCALL
+
+;
+; INT 33H -- mouse driver
+;
+MOUCALL:        MOV     INP_HANDLE, NO_FILE_HANDLE
+                CALL    REGS_TO_RM
+                MOV     BX, RM_AX               ; Get AX
+                CMP     BH, 0                   ; AH=0?
+                JNE     D_INVALID               ; No -> error
+                TBGET   MOU_FUNCS               ; Get conversion flag
+                JMP     INTCALL
+
+;
+; Generic software interrupt, no conversion
+;
+GENERIC_CALL:   MOV     INP_HANDLE, NO_FILE_HANDLE
+                CALL    REGS_TO_RM
+                MOV     AX, DF_NULL             ; No conversion
+                JMP     INTCALL
+
+;
+; Duplicate file handle
+;
+D_DUP:          MOV     BX, PROCESS_PTR
+                CMP     BX, NO_PROCESS          ; Called from user process?
+                JE      D_NULL                  ; No -> directly call DOS
+                MOV     AX, RM_BX               ; Handle
+                CALL    DO_DUP
+D_DUP_COMMON:   MOV     WORD PTR I_EAX + 0, AX
+                MOV     WORD PTR I_EAX + 2, 0
+                JNC     SHORT D_DUP_FIN
+                OR      BYTE PTR I_EFLAGS, FLAG_C ; Set carry flag
+D_DUP_FIN:      JMP     PMINT_RET               ; DFE not set for D_DUP!
+
+;
+; Force duplicate file handle
+;
+D_DUP2:         MOV     BX, PROCESS_PTR
+                CMP     BX, NO_PROCESS          ; Called from user process?
+                JE      D_NULL                  ; No -> directly call DOS
+                MOV     AX, RM_BX               ; Handle1
+                MOV     CX, RM_CX               ; Handle2
+                CALL    DO_DUP2
+                JMP     D_DUP_COMMON
+
+;
+; Invalid function
+;
+D_INVALID:      MOV     BL, BYTE PTR RM_AX[0]
+                LEA     EDX, $BAD_MOU_FUNC      ; MOU function not supported
+                CMP     INT_NO, 33H
+                JE      SHORT DOSF_ERROR
+                MOV     BL, BYTE PTR RM_AX[1]
+                LEA     EDX, $BAD_VIO_FUNC      ; VIO function not supported
+                CMP     INT_NO, 10H
+                JE      SHORT DOSF_ERROR
+                LEA     EDX, $BAD_DOS_FUNC      ; DOS function not supported
+DOSF_ERROR:     PUSH    BX                      ; Save function number (BL)
+                CALL    OTEXT                   ; Display message
+                POP     AX                      ; Restore function number (AL)
+                CALL    OBYTE                   ; Display hex byte
+                MOV     AX, 4CFFH               ; Terminate program (255)
+                INT     21H                     ; This is recursive!
+
+;
+; Invalid arguments
+;
+DOSF_PARAM:     LEA     EDX, $DOS_PARAM         ; Invalid arguments
+                JMP     DOSF_ERROR              ; Abort
+
+;
+; Convert output:
+;
+; Insert emx version
+;
+D_VERSION:      CALL    INT_RM                  ; Call DOS
+                CALL    REGS_FROM_RM            ; Copy all general registers
+                MOV     WORD PTR I_EAX+2, 6D65H ; Indicate emx: "em"
+                JMP     DOSCALL_RET             ; Done
+
+
+;
+; Convert input:
+;
+; DS:EDX points to "$" terminated string
+;
+                TALIGN  4
+D_TEXT:         MOV     AL, "$"                 ; Look for "$"
+                MOV     AH, FALSE               ; Not a path name
+                XOR     EBX, EBX                ; Don't add
+                CALL    G_DELIM
+                JMP     DOSCALL_RET             ; Done
+
+
+;
+; Convert input and output:
+;
+; DS:EDX points to 0 terminated string (path)
+; DS:ESI points to DTA (43 bytes)
+;
+                TALIGN  4
+D_FFIRST:       CALL    SET_DTA_1               ; Uses OFFSET_1
+                MOV     ESI, I_EDX
+                MOV     AL, 00H                 ; Terminator
+                MOV     AH, NOT FALSE           ; It's a path name
+                XOR     EBX, EBX
+                MOV     EDI, OFFSET_2
+                MOV     RM_DX, DI               ; Offset of buffer
+                CALL    I_DELIM
+D_FFIRST_1:     PUSH    I_EDX                   ; Save EDX (argument)
+                CALL    INT_RM                  ; Call DOS
+                CALL    REGS_FROM_RM            ; Retrieve real-mode registers
+                POP     I_EDX                   ; Restore EDX (of caller)
+                MOV     AX, I_DS                ; AX:EDI = destination
+                MOV     EDI, I_ESI
+                MOV     ECX, 43
+                CALL    MOVE_FROM_RM            ; Copy from real-mode buffer
+                JMP     DOSCALL_RET
+
+;
+; Convert input and output:
+;
+; DS:ESI points to DTA (43 bytes)
+;
+                TALIGN  4
+D_FNEXT:        CALL    SET_DTA_1               ; Uses OFFSET_1
+                MOV     AX, I_DS
+                MOV     ESI, I_ESI
+                MOV     EDI, OFFSET_1
+                MOV     ECX, 43
+                CALL    MOVE_TO_RM
+                JMP     SHORT D_FFIRST_1
+
+;
+;
+; Convert input:
+;
+; DS:EDX points to 0 terminated string (path) -> DS:DX
+; DS:EDI points to 0 terminated string (path) -> ES:DI
+;
+                TALIGN  4
+D_MOVE:         MOV     ESI, I_EDI
+                MOV     AL, 00H                 ; Terminator
+                MOV     AH, NOT FALSE           ; It's a path name
+                XOR     EBX, EBX
+                MOV     EDI, OFFSET_2
+                MOV     RM_DI, DI               ; Offset of buffer
+                CALL    I_DELIM
+                ; fall through to D_PATH
+;
+; Convert input:
+;
+; DS:EDX points to 0 terminated string (path)
+;
+                TALIGN  4
+D_PATH:         MOV     AL, 0                   ; Look for zeros
+                MOV     AH, NOT FALSE           ; It's a path name
+                XOR     EBX, EBX                ; Don't add
+                CALL    G_DELIM
+                JMP     DOSCALL_RET
+
+;
+; Convert input:
+;
+; DS:ESI points to 0 terminated string (path)
+;
+D_PATH_SI:      MOV     AL, 0                   ; Look for zeros
+                MOV     AH, NOT FALSE           ; It's a path name
+                XOR     EBX, EBX                ; Don't add
+                MOV     ESI, I_ESI
+                MOV     EDI, OFFSET_1
+                MOV     RM_SI, DI               ; Offset of buffer
+                CALL    I_DELIM
+                PUSH    I_ESI                   ; Save ESI (argument)
+                CALL    INT_RM                  ; Call DOS
+                CALL    REGS_FROM_RM            ; Retrieve real-mode registers
+                POP     I_ESI                   ; Restore ESI (of caller)
+                JMP     DOSCALL_RET
+
+;
+; Convert input/output:
+;
+; DS:EDX points to 0 terminated string (path) + 13 bytes
+;
+                TALIGN  4
+D_TMP:          MOV     AL, 0                   ; Look for zeros
+                MOV     AH, NOT FALSE           ; It's a path name
+                MOV     EBX, 13                 ; Add 13 bytes
+                CALL    G_DELIM
+                MOV     AX, I_DS                ; AX:EDI = destination
+                MOV     EDI, I_EDX
+                CALL    MOVE_FROM_RM            ; Copy from real-mode buffer
+                JMP     DOSCALL_RET
+
+;
+; Convert input/output:
+;
+; DS:EDX points to buffer, length: first byte + 2
+;
+                TALIGN  4
+D_INPUT:        MOV     AX, I_DS
+                MOV     ESI, I_EDX
+                MOV     ES, AX
+                MOVZX   ECX, BYTE PTR ES:[ESI]
+                ADD     ECX, 2
+                PUSH    ECX
+                MOV     EDI, OFFSET_1
+                MOV     RM_DX, DI               ; Offset of buffer
+                CALL    MOVE_TO_RM
+                CALL    INT_RM
+                POP     ECX
+                MOV     AX, I_DS
+                MOV     EDI, I_EDX
+                CALL    MOVE_FROM_RM
+                JMP     DOSCALL_RET
+
+;
+; Convert output:
+;
+; DS:ESI points to zero terminated string
+;
+                TALIGN  4
+D_GETCWD:       MOV     RM_SI, OFFSET_1         ; Offset of buffer
+                CALL    INT_RM
+                TEST    RM_FLAGS, FLAG_C
+                JNZ     DOSCALL_RET
+                MOV     EDI, I_ESI
+                MOV     AX, I_DS
+                CALL    MOVEZ_FROM_RM
+                JMP     DOSCALL_RET
+
+;
+; Input (registers of caller):
+;   BX     = handle
+;   DS:EDX = buffer
+;   ECX    = number of bytes
+;
+; Output (registers of caller):
+;   EAX    = number of bytes or error code
+;   CY=1   : error
+;
+; Truncate the file at the current position of the file pointer (in contrast
+; to the statement in system.doc). This is required for the implementation
+; of _ftruncate().
+;
+                TALIGN  4
+D_WRITE:        MOV     AX, WORD PTR I_EAX
+                MOV     N_AX, AX
+                MOV     EAX, I_ECX
+                MOV     NREQ, EAX
+                PUSH    EAX                     ; Save caller's ECX
+                MOV     EAX, I_EDX
+                MOV     NPTR, EAX
+                PUSH    EAX                     ; Save caller's EDX
+                MOV     I_EAX, 0                ; Result := 0 (EAX)
+D_WRITE1:       MOV     EAX, NREQ
+                CMP     EAX, 0FFFFH - OFFSET_1
+                JBE     SHORT D_WRITE2
+                MOV     AX, 0FE00H              ; 64K - 512
+D_WRITE2:       MOV     RM_CX, AX
+                MOV     RM_DX, OFFSET_1         ; Offset of buffer
+                MOV     AX, I_DS                ; AX:ESI = source
+                MOV     ESI, NPTR
+                MOVZX   ECX, RM_CX              ; Size of buffer
+                MOV     EDI, OFFSET_1
+                MOV     RM_DX, DI               ; Offset of buffer
+                CALL    MOVE_TO_RM              ; Copy to real-mode buffer
+                MOV     AX, N_AX
+                MOV     RM_AX, AX
+                CALL    INT_RM                  ; Call DOS
+                TEST    RM_FLAGS, FLAG_C        ; Error?
+                JNZ     SHORT D_WRITE_ERR
+                MOV     AX, RM_AX               ; Number of bytes written
+                TEST    AX, AX                  ; Zero?
+                JZ      SHORT D_WRITE_END       ; Yes -> done
+                MOVZX   ECX, AX
+                ADD     I_EAX, ECX              ; Update return value
+                CMP     AX, RM_CX               ; Less than requested?
+                JB      SHORT D_WRITE_END       ; Yes -> done
+                ADD     NPTR, ECX
+                SUB     NREQ, ECX
+                JNZ     SHORT D_WRITE1
+                JMP     SHORT D_WRITE_END
+
+D_WRITE_ERR:    MOVZX   EAX, RM_AX              ; Copy error code
+                MOV     I_EAX, EAX
+D_WRITE_END:    MOV     AL, RM_FLAGS            ; Copy flags
+                MOV     BYTE PTR I_EFLAGS[0], AL
+                POP     I_EDX                   ; Restore caller's EDX
+                POP     I_ECX                   ; Restore caller's ECX
+                JMP     DOSCALL_RET             ; Done
+
+;
+; Input (registers of caller):
+;   BX     = handle
+;   DS:EDX = buffer
+;   ECX    = number of bytes
+;
+; Output (registers of caller):
+;   EAX    = number of bytes or error code
+;   CY=1   : error
+;
+                TALIGN  4
+D_READ:         CMP     BYTE PTR RM_AX[1], 3FH  ; AH=3FH (read handle)?
+                JNE     SHORT D_READ_10
+                CMP     RM_BX, 0                ; Handle = stdin?
+                JNE     SHORT D_READ_10
+                TEST    STDIN_TERMIO.C_LFLAG, IDEFAULT
+                JNZ     SHORT D_READ_10
+                CMP     PROCESS_PTR, NO_PROCESS
+                JE      SHORT D_READ_10
+                TEST    I_CS, 3                 ; Called from user code?
+                JZ      SHORT D_READ_10         ; No  ->
+                PUSH    RM_BX
+                MOV     RM_AX, 4400H            ; IOCTL: Get device data
+                CALL    INT_RM
+                TEST    RM_FLAGS, FLAG_C        ; Error?
+                JNZ     SHORT D_READ_09         ; Yes -> continue
+                TEST    RM_DX, 80H              ; Device?
+                JZ      SHORT D_READ_09         ; No  -> continue
+                TEST    RM_DX, 01H              ; Console input device?
+                JZ      SHORT D_READ_09         ; No  -> continue
+                POP     RM_BX                   ; Cleanup stack
+                MOV     ES, I_DS
+                MOV     EDI, I_EDX
+                MOV     ECX, I_ECX
+                CALL    TERMIO_READ
+                MOV     I_EAX, EAX
+                JNC     D_READ_01
+                OR      I_EFLAGS, FLAG_C
+D_READ_01:      MOV     AX, INP_HANDLE
+                CMP     AX, NO_FILE_HANDLE      ; Input handle converted?
+                JE      SHORT D_READ_02         ; No -> skip
+                MOV     WORD PTR I_EBX, AX      ; Store to (E)BX
+D_READ_02:      JMP     PMINT_RET
+
+D_READ_09:      CALL    REGS_TO_RM
+                POP     RM_BX
+D_READ_10:      MOV     AX, WORD PTR I_EAX
+                MOV     N_AX, AX
+                MOV     EAX, I_ECX
+                MOV     NREQ, EAX
+                PUSH    EAX                     ; Save caller's ECX
+                MOV     EAX, I_EDX
+                MOV     NPTR, EAX
+                PUSH    EAX                     ; Save caller's EDX
+                MOV     I_EAX, 0                ; 0 bytes read
+D_READ1:        MOV     EAX, NREQ
+                CMP     EAX, 0FFFFH - OFFSET_1
+                JBE     SHORT D_READ2
+                MOV     AX, 0FE00H              ; 64K - 512
+D_READ2:        MOV     RM_CX, AX
+                MOV     RM_DX, OFFSET_1         ; Offset of buffer
+                MOV     AX, N_AX
+                MOV     RM_AX, AX
+                CALL    INT_RM                  ; Call DOS
+                TEST    RM_FLAGS, FLAG_C        ; Error?
+                JNZ     SHORT D_READ_ERR
+                MOVZX   ECX, RM_AX              ; Get number of bytes read
+                JECXZ   D_READ3                 ; EOF -> done
+                MOV     AX, I_DS                ; AX:EDI = destination
+                MOV     EDI, NPTR
+                CALL    MOVE_FROM_RM            ; Copy from real-mode buffer
+                ADD     I_EAX, ECX              ; Adjust return value (EAX)
+                CMP     CX, RM_CX               ; All bytes of this chunk read?
+                JNE     SHORT D_READ3           ; No -> done
+                ADD     NPTR, ECX               ; Move pointer
+                SUB     NREQ, ECX               ; Decrement byte count
+                JNZ     SHORT D_READ1           ; Not done -> repeat
+D_READ3:        JMP     SHORT D_READ_END
+
+D_READ_ERR:     MOVZX   EAX, RM_AX              ; Copy error code
+                MOV     I_EAX, EAX
+D_READ_END:     MOV     AL, RM_FLAGS            ; Copy flags
+                MOV     BYTE PTR I_EFLAGS[0], AL
+                POP     I_EDX                   ; Restore caller's EDX
+                POP     I_ECX                   ; Restore caller's ECX
+                JMP     DOSCALL_RET             ; Done
+
+
+;
+; Convert input/output:
+;
+; EDX -> CX:DX
+; Call DOS
+; DX:AX -> EAX
+;
+                TALIGN  4
+D_SEEK:         MOV     EAX, I_EDX              ; Get EDX
+                MOV     RM_DX, AX               ; Store lower word
+                SHR     EAX, 16                 ; Get upper word
+                MOV     RM_CX, AX               ; Store upper word
+                CALL    INT_RM                  ; Call DOS
+                XOR     EAX, EAX                ; Clear upper word of EAX
+                TEST    RM_FLAGS, FLAG_C        ; Error?
+                JNZ     SHORT D_SEEK_1          ; Yes -> no conversion
+                MOV     AX, RM_DX               ; Get DX
+                SHL     EAX, 16                 ; and put it into upper word
+D_SEEK_1:       MOV     AX, RM_AX               ; Put AX into lower word
+                MOV     I_EAX, EAX              ; of EAX
+                MOV     AL, RM_FLAGS            ; Copy flags
+                MOV     BYTE PTR I_EFLAGS[0], AL
+                JMP     DOSCALL_RET             ; Done
+
+;
+; Close a file handle
+;
+; Note: When called from user code no translation of error codes
+;       is done because DO_CLOSE already returns errno value.
+;       DO_CLOSE in turn may invoke this code via INT 21H.  In that
+;       case (called from the kernel), error translation is performed,
+;       but the handle is not translated.
+;
+                TALIGN  4
+D_CLOSE:        MOV     BX, PROCESS_PTR
+                CMP     BX, NO_PROCESS          ; Called from user process?
+                JE      D_NULL                  ; No -> no translation
+                MOV     AX, RM_BX               ; This is the handle
+                CALL    DO_CLOSE                ; Close the handle
+                JNC     SHORT D_CLOSE_FIN       ; No error -> done
+D_CLOSE_ERROR:  MOV     WORD PTR I_EAX+0, AX    ; Return errno in EAX
+                MOV     WORD PTR I_EAX+2, 0
+                OR      BYTE PTR I_EFLAGS, FLAG_C ; Set carry flag
+D_CLOSE_FIN:    JMP     PMINT_RET               ; Don't translate error code!
+
+;
+; Exit
+;
+                TALIGN  4
+D_EXIT:         TEST    I_CS, 3                 ; Called from user program?
+                JZ      SHORT D_EXIT_QUIT       ; No  -> exit to DOS
+                MOV     SI, PROCESS_PTR         ; Current process
+                CMP     SI, NO_PROCESS          ; No current process?
+                JE      SHORT D_EXIT_QUIT       ; Yes -> impossible (go DOS)
+                ASSUME  SI:PTR PROCESS
+;
+; ...to do: process 0 becomes parent process of all children
+;
+                MOV     AL, BYTE PTR I_EAX      ; Get return code
+                MOV     [SI].P_RC, AL           ; Store it
+                MOV     EAX, [SI].P_PPID        ; Get parent process ID
+                TEST    EAX, EAX                ; Root process?
+                JZ      SHORT D_EXIT_QUIT       ; Yes -> return to DOS
+                CALL    FIND_PROCESS            ; Find parent process
+                CMP     BX, NO_PROCESS          ; Does parent process exist?
+                JZ      SHORT D_EXIT_QUIT       ; No  -> cannot happen, quit
+                ASSUME  BX:PTR PROCESS
+                MOV     PROCESS_PTR, BX         ; Switch to parent process
+                MOV     PROCESS_SIG, BX
+                MOV     EAX, I_EAX              ; Get return code
+                AND     EAX, 0FFH               ; Use only lower 8 bits
+                TEST    [BX].P_FLAGS, PF_PSEUDO_ASYNC   ; Pseudo async?
+                JNZ     SHORT D_EXIT_PSEUDO     ; Yes -> don't overwrite PID
+                MOV     [BX].P_SPAWN_RC, EAX    ; Store the return code
+                JMP     SHORT D_EXIT_RESTORE    ; Continue
+D_EXIT_PSEUDO:  MOV     [BX].P_RC, AL           ; Store the return code
+D_EXIT_RESTORE: CALL    REST_PROCESS            ; Restore parent process
+                MOV     BX, SI                  ; The dying process
+                PUSH    [BX].P_NUMBER           ; Save for FPUEMU_ENDPROC
+                TEST    [BX].P_FLAGS, PF_DEBUG  ; In debugging mode?
+                JZ      SHORT D_EXIT_1          ; No -> kill process
+                CALL    ZOMBIE_PROCESS          ; Make process defunct
+                JMP     SHORT D_EXIT_2
+D_EXIT_1:       CALL    REMOVE_PROCESS          ; Thoroughly kill process
+D_EXIT_2:       CALL    BREAK_AFTER_IRET        ; Allow debugging
+                POP     EAX                     ; P_NUMBER of the dead process
+                CALL    FPUEMU_ENDPROC          ; Notify FPU emulator
+                JMP     DOSCALL_RET             ; Continue with parent
+                ASSUME  BX:NOTHING
+                ASSUME  SI:NOTHING
+;
+; Exit to DOS
+;
+D_EXIT_QUIT:    CMP     FP_FLAG, FP_387         ; 387 available?
+                JNE     SHORT EQUIT1            ; No  -> skip
+                FNINIT                          ; Initialize
+EQUIT1:         CALL    DEBUG_QUIT              ; Swapper statistics
+                XOR     EAX, EAX
+                MOV     DR7, EAX                ; Avoid unexpected behaviour
+                JMP     SHORT D_NULL
+
+;
+; No conversion
+;
+                TALIGN  4
+D_NULL:         CALL    INT_RM                  ; Call DOS
+                CALL    REGS_FROM_RM            ; Copy all general registers
+                JMP     DOSCALL_RET             ; Done
+
+;
+; Just check for supervisor code
+;
+                TALIGN  4
+D_RETCODE:      TEST    I_CS, 3                 ; Called from supervisor?
+                JNZ     D_INVALID               ; No  -> bad function code
+                JMP     SHORT D_NULL            ; No conversion
+
+;
+; Load and execute (a DOS) program
+;
+                TALIGN  4
+D_EXEC:         TEST    I_CS, 3                 ; Called from supervisor?
+                JNZ     D_INVALID               ; No  -> bad function code
+                MOV     AX, SV_DATA             ; Load real-mode segment
+                MOV     RM_DS, AX               ; registers
+                MOV     RM_ES, AX
+                CALL    INT_RM
+                MOV     AX, RM_AX
+                MOV     WORD PTR I_EAX, AX
+                MOV     AL, RM_FLAGS
+                MOV     BYTE PTR I_EFLAGS[0], AL
+                JMP     DOSCALL_RET
+
+;
+; Convert input:
+;
+; EBP points to null-terminated string (-> ES:BP)
+;
+                TALIGN  4
+D_STR_BP:       MOV     AL, 0                   ; Look for 0
+                MOV     AH, FALSE               ; Not a path name
+                XOR     EBX, EBX                ; Don't add
+                MOV     ESI, I_EBP
+                MOV     EDI, OFFSET_1
+                MOV     RM_BP, DI               ; Offset of buffer
+                CALL    I_DELIM
+                PUSH    I_EBP                   ; Save EBP (of caller)
+                CALL    INT_RM                  ; Call interrupt
+                CALL    REGS_FROM_RM            ; Retrieve real-mode registers
+                POP     I_EBP                   ; Restore EBP (of caller)
+                JMP     DOSCALL_RET             ; Done
+
+
+;
+; Convert output of VESA function 0.
+;
+; EDI (-> ES:DI) points to a 256-byte buffer on entry which is filled-in
+; by the function.  There are two pointers to secondary buffers in the
+; buffer.  We have to copy the data pointed to by these pointers into
+; the process' address space.
+;
+                TALIGN  4
+D_VESAINFO:     MOV     RM_DI, OFFSET_1         ; Offset of buffer
+                PUSH    I_EDI                   ; Save EDI (of caller)
+                CALL    INT_RM                  ; Call interrupt
+                CALL    REGS_FROM_RM            ; Retrieve real-mode registers
+                POP     I_EDI                   ; Restore EDI (of caller)
+;
+; Copy 256-byte buffer
+;
+                MOV     AX, I_DS                ; AX:EDI = destination
+                MOV     EDI, I_EDI
+                MOV     ECX, 256
+                CALL    MOVE_FROM_RM            ; Copy from real-mode buffer
+                CMP     RM_AX, 004FH            ; Successful?
+                JNE     DOSCALL_RET             ; No -> don't convert pointers
+;
+; Allocate a page in the process address space for the secondary buffers
+;
+                MOV     DI, PROCESS_PTR
+                ASSUME  DI:PTR PROCESS
+                MOV     EAX, [DI].P_VESAINFO_PTR
+                TEST    EAX, EAX
+                JNZ     SHORT DVI_REUSE
+                MOV     ECX, 1
+                CALL    ADD_PAGES
+                TEST    EAX, EAX
+                JZ      SHORT DVI_FAIL
+                MOV     [DI].P_VESAINFO_PTR, EAX
+DVI_REUSE:      MOV     EDI, EAX
+;
+; Copy the OEM name
+;
+                MOV     ES, I_DS
+                MOV     ESI, I_EDI
+                XCHG    EAX, ES:[ESI+06H]       ; Pointer to OEM name
+                CALL    ACCESS_LOWMEM
+                MOV     AX, G_LOWMEM_SEL
+                MOV     FS, AX
+                MOV     ECX, 128                ; Maximum string length
+DVI_OEM_1:      MOV     AL, FS:[EBX]
+                TEST    AL, AL
+                JZ      SHORT DVI_OEM_2
+                INC     EBX
+                STOS    BYTE PTR ES:[EDI]
+                LOOP    DVI_OEM_1
+DVI_OEM_2:      XOR     AL, AL
+                STOS    BYTE PTR ES:[EDI]
+;
+; Copy the mode list
+;
+                INC     EDI                     ; Make the address even
+                AND     EDI, NOT 1
+                MOV     EAX, EDI
+                XCHG    EAX, ES:[ESI+0EH]       ; Pointer to video modes
+                CALL    ACCESS_LOWMEM
+                MOV     ECX, (4096 - 128) / 2 - 1
+DVI_MODES_1:    MOV     AX, FS:[EBX]
+                CMP     AX, 0FFFFH
+                JE      SHORT DVI_MODES_2
+                ADD     EBX, 2
+                STOS    WORD PTR ES:[EDI]
+                LOOP    DVI_MODES_1
+DVI_MODES_2:    MOV     AX, 0FFFFH
+                STOS    WORD PTR ES:[EDI]
+                JMP     DOSCALL_RET             ; Done
+
+;
+; Function call failed, invalidate the two pointers.
+;
+DVI_FAIL:       MOV     ES, I_DS
+                MOV     ESI, I_EDI
+                MOV     DWORD PTR ES:[ESI+06H], 0
+                MOV     DWORD PTR ES:[ESI+0EH], 0
+                JMP     DOSCALL_RET
+
+                ASSUME  DI:NOTHING
+
+;
+; Convert output of VESA function 1.
+;
+; EDI (-> ES:DI) points to a 256-byte buffer on entry which is filled-in
+; by the function.  There's one pointer in the buffer which points to
+; a function.  Set that pointer to NULL.
+;
+                TALIGN  4
+D_VESAMODE:     MOV     RM_DI, OFFSET_1         ; Offset of buffer
+                PUSH    I_EDI                   ; Save EDI (of caller)
+                CALL    INT_RM                  ; Call interrupt
+                CALL    REGS_FROM_RM            ; Retrieve real-mode registers
+                POP     I_EDI                   ; Restore EDI (of caller)
+;
+; Copy 256-byte buffer
+;
+                MOV     AX, I_DS                ; AX:EDI = destination
+                MOV     EDI, I_EDI
+                MOV     ECX, 256
+                CALL    MOVE_FROM_RM            ; Copy from real-mode buffer
+                MOV     ES, I_DS
+                MOV     ESI, I_EDI
+;
+; Invalidate pointer to window positioning function (same as AX=4F05H)
+;
+                MOV     DWORD PTR ES:[ESI+0CH], 0
+                JMP     DOSCALL_RET             ; Done
+
+;
+; Convert input
+;
+; EDX points 64-byte buffer (-> ES:DX)
+;
+                TALIGN  4
+D_MOU_GCURSOR:  MOV     AX, I_DS
+                MOV     ESI, I_EDX
+                PUSH    ESI                     ; Save EDX (of caller)
+                MOV     ES, AX                  ; Source: AX:ESI
+                MOV     ECX, 64                 ; Copy 2*16 16-bit words
+                MOV     EDI, OFFSET_1           ; to real-mode buffer
+                MOV     RM_DX, DI               ; Offset of buffer
+                CALL    MOVE_TO_RM
+                CALL    INT_RM
+                POP     I_EDX                   ; Restore EDX (of caller)
+                JMP     DOSCALL_RET
+
+;
+; Convert input
+;
+; EDX points to a buffer (-> ES:DX).  The size of the buffer is
+; BH * CH * 4 bytes.
+;
+                TALIGN  4
+D_MOU_LGCURSOR: MOV     AL, BYTE PTR RM_BX[1]   ; BH
+                MUL     BYTE PTR RM_CX[1]       ; CH
+                MOVZX   ECX, AX                 ; ECX = BH * CH
+                SHL     ECX, 2                  ; Multiply by 4
+                MOV     AX, I_DS
+                MOV     ESI, I_EDX
+                PUSH    ESI                     ; Save EDX (of caller)
+                MOV     ES, AX                  ; Source: AX:ESI
+                MOV     EDI, OFFSET_1           ; to real-mode buffer
+                MOV     RM_DX, DI               ; Offset of buffer
+                CALL    MOVE_TO_RM
+                CALL    INT_RM
+                POP     I_EDX                   ; Restore EDX (of caller)
+                JMP     DOSCALL_RET
+
+;
+; Convert output:
+;
+; DS:EDX (input) points to buffer, length: 34 bytes
+;
+                TALIGN  4
+D_COUNTRY:      CMP     RM_DX, 0FFFFH
+                JE      SHORT D_COUNTRY_SET
+                MOV     RM_DX, OFFSET_1
+                CALL    INT_RM
+                MOV     AX, I_DS
+                MOV     EDI, I_EDX
+                MOV     ECX, 34
+                CALL    MOVE_FROM_RM
+D_COUNTRY_1:    CALL    REGS_FROM_RM
+                JMP     DOSCALL_RET
+
+D_COUNTRY_SET:  CALL    INT_RM
+                JMP     D_COUNTRY_1
+
+;
+; Convert input:
+;
+; EDX -> CX:DX
+; EDI -> SI:DI
+;
+                TALIGN  4
+D_LOCK:         MOV     EAX, I_EDX
+                PUSH    EAX
+                MOV     RM_DX, AX
+                SHR     EAX, 16
+                MOV     RM_CX, AX
+                MOV     EAX, I_EDI
+                PUSH    EAX
+                MOV     RM_DI, AX
+                SHR     EAX, 16
+                MOV     RM_SI, AX
+                CALL    INT_RM
+                CALL    REGS_FROM_RM
+                POP     I_EDI
+                POP     I_EDX
+                JMP     DOSCALL_RET
+
+;
+; Convert input:  ASCIZ ESI -> DS:SI, EDI -> ES:DI
+; Convert output: ASCIZ EDI
+; 
+                TALIGN  4
+D_TRUENAME:     MOV     AL, 0                   ; Look for 0
+                MOV     AH, NOT FALSE           ; It's a path name
+                XOR     EBX, EBX                ; Don't add
+                MOV     ESI, I_ESI
+                MOV     EDI, OFFSET_2
+                MOV     RM_SI, DI               ; Offset of buffer
+                CALL    I_DELIM
+                MOV     RM_DI, OFFSET_1
+                PUSH    I_ESI                   ; Save EDI and ESI (of caller)
+                PUSH    I_EDI
+                CALL    INT_RM
+                CALL    REGS_FROM_RM
+                POP     I_EDI
+                POP     I_ESI
+                TEST    I_EFLAGS, FLAG_C        ; Error?
+                JNZ     SHORT D_TRUENAME_1      ; Yes -> skip
+                MOV     AX, I_ES
+                MOV     EDI, I_EDI
+                CALL    MOVEZ_FROM_RM           ; Copies from OFFSET_1
+D_TRUENAME_1:   JMP     DOSCALL_RET
+
+
+;
+; Return from DOS call
+;
+                TALIGN  4
+DOSCALL_RET:    MOV     AX, INP_HANDLE
+                CMP     AX, NO_FILE_HANDLE      ; Input handle converted?
+                JE      SHORT DOSCALL_RET1      ; No -> skip
+                MOV     WORD PTR I_EBX, AX      ; Store to (E)BX
+DOSCALL_RET1:   TEST    CONV_FLAG, DFH_OUT      ; New handle?
+                JZ      SHORT DOSCALL_RET2
+                CMP     PROCESS_PTR, NO_PROCESS ; Called from user process?
+                JE      SHORT DOSCALL_RET2      ; No -> skip
+                TEST    I_EFLAGS, FLAG_C        ; Error?
+                JNZ     SHORT DOSCALL_RET2      ; Yes -> skip
+                MOV     AX, WORD PTR I_EAX      ; Get DOS handle
+                CALL    NEW_HANDLE              ; New slot
+                MOV     I_EAX, EAX              ; Return translated handle
+DOSCALL_RET2:   TEST    CONV_FLAG, DFE          ; Convert error code?
+                JZ      SHORT DOSCALL_RET3      ; No  -> skip
+                TEST    I_EFLAGS, FLAG_C        ; Error?
+                JZ      SHORT DOSCALL_RET3      ; No  -> skip
+                MOV     AX, WORD PTR I_EAX      ; Get error code
+                CALL    DOS_ERROR_TO_ERRNO      ; Translate error code
+                MOV     I_EAX, EAX              ; Put errno into EAX
+DOSCALL_RET3:   JMP     PMINT_RET
+
+                ASSUME  BP:NOTHING
+
+;
+; In:   EBX     Number of bytes to move beyond terminator
+;       AL      Terminator
+;       AH      Path name flag
+;
+; Out:  ECX     Buffer size
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+G_DELIM         PROC    NEAR
+                MOV     ESI, I_EDX
+                MOV     EDI, OFFSET_1
+                MOV     RM_DX, DI               ; Offset of buffer
+                CALL    I_DELIM
+                PUSH    ECX                     ; Save ECX (buffer size)
+                PUSH    I_EDX                   ; Save EDX (argument)
+                CALL    INT_RM                  ; Call DOS
+                CALL    REGS_FROM_RM            ; Retrieve real-mode registers
+                POP     I_EDX                   ; Restore EDX (of caller)
+                POP     ECX                     ; Restore ECX (buffer size)
+                RET
+                ASSUME  BP:NOTHING
+G_DELIM         ENDP
+
+
+;
+; In:   ESI     Pointer to argument
+;       EDI     Offset in buffer
+;       EBX     Number of bytes to move beyond terminator
+;       AL      Terminator
+;       AH      Path name flag (for truncation). Non-zero if path name
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+I_DELIM         PROC    NEAR
+                PUSH    AX                      ; Save terminator and flag
+                PUSH    EDI                     ; Save offset
+                MOV     ES, I_DS                ; ES:EDI points to argument
+                MOV     ECX, 0FFFFH
+                SUB     ECX, EDI                ; Maximum length
+                MOV     EDI, ESI
+                CLD                             ; Incrementing
+                REPNE   SCAS BYTE PTR ES:[EDI]  ; Look for terminator
+                JECXZ   IDELIM_2                ; Not found -> abort
+                MOV     ECX, EDI
+                SUB     ECX, ESI                ; Length of string
+                ADD     ECX, EBX                ; Add
+                MOV     AX, I_DS                ; AX:ESI = source
+                POP     EDI                     ; Offset
+                CALL    MOVE_TO_RM              ; Copy to real-mode buffer
+                POP     AX                      ; Terminator and flag
+                CMP     AH, FALSE               ; Path name?
+                JE      SHORT IDELIM_1          ; No  -> return
+                PUSH    ES
+                MOV     ES, BUF_SEL
+                CALL    TRUNCATE
+                POP     ES
+IDELIM_1:       RET
+
+IDELIM_2:       POP     EDI
+                POP     AX
+                JMP     DOSF_PARAM
+                ASSUME  BP:NOTHING
+I_DELIM         ENDP
+
+;
+; Set disk transfer address to OFFSET_1
+;
+SET_DTA_1       PROC    NEAR
+                PUSH    RM_AX                   ; Save real-mode AX
+                PUSH    RM_DX                   ; Save real-mode DX
+                MOV     RM_AX, 1A00H            ; Set disk transfer address
+                MOV     RM_DX, OFFSET_1         ; to OFFSET_1
+                CALL    INT_RM                  ; Call DOS
+                POP     RM_DX                   ; Restore real-mode DX
+                POP     RM_AX                   ; Restore real-mode AX
+                RET
+SET_DTA_1       ENDP
+
+
+;
+; Copy protected-mode registers to real-mode registers
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+                TALIGN  4
+REGS_TO_RM      PROC    NEAR
+                IRP     R, <AX,BX,CX,DX,SI,DI,BP>
+                MOV     AX, WORD PTR I_E&R      ; Load general real-mode
+                MOV     RM_&R, AX               ; registers
+                ENDM
+                MOV     AX, BUF_SEG             ; Load real-mode segment
+                MOV     RM_DS, AX               ; registers
+                MOV     RM_ES, AX
+                RET
+                ASSUME  BP:NOTHING
+REGS_TO_RM      ENDP
+
+;
+; Copy real-mode registers to protected-mode stack frame
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+                TALIGN  4
+REGS_FROM_RM    PROC    NEAR
+                IRP     R, <AX,BX,CX,DX,SI,DI,BP>
+                MOV     AX, RM_&R
+                MOV     WORD PTR I_E&R, AX
+                ENDM
+                MOV     AL, RM_FLAGS
+                MOV     BYTE PTR I_EFLAGS[0], AL
+                RET
+                ASSUME  BP:NOTHING
+REGS_FROM_RM    ENDP
+
+
+
+;
+; Copy buffer from protected mode to real mode
+;
+; In:   AX:ESI  Source (protected mode)
+;       EDI     OFFSET_1 or OFFSET_2
+;       ECX     Number of bytes
+;
+
+                ASSUME  DS:SV_DATA
+
+                TALIGN  4
+MOVE_TO_RM      PROC    NEAR PUBLIC
+                PUSH    DS
+                PUSH    ES
+                PUSH    EAX
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    ESI
+                PUSH    EDI
+                MOV     ES, BUF_SEL
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                CLD
+                MOV     EAX, ECX
+                SHR     ECX, 2
+                REP     MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
+                MOV     ECX, EAX
+                AND     ECX, 3
+                REP     MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
+                POP     EDI
+                POP     ESI
+                POP     EDX
+                POP     ECX
+                POP     EAX
+                POP     ES
+                POP     DS
+                RET
+MOVE_TO_RM      ENDP
+
+
+;
+; Copy buffer from real mode to protected mode
+;
+; In:   AX:EDI  Destination address
+;       ECX     Number of bytes
+;
+; Note: always uses OFFSET_1
+;
+
+                ASSUME  DS:SV_DATA
+
+MOVE_FROM_RM    PROC    NEAR PUBLIC
+                PUSH    DS
+                PUSH    ES
+                PUSH    EAX
+                PUSH    ECX
+                PUSH    ESI
+                PUSH    EDI
+                MOV     ES, AX
+                MOV     ESI, OFFSET_1
+                MOV     DS, BUF_SEL
+                ASSUME  DS:NOTHING
+                CLD
+                MOV     EAX, ECX
+                SHR     ECX, 2
+                REP     MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
+                MOV     ECX, EAX
+                AND     ECX, 3
+                REP     MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
+                POP     EDI
+                POP     ESI
+                POP     ECX
+                POP     EAX
+                POP     ES
+                POP     DS
+                RET
+MOVE_FROM_RM    ENDP
+
+
+;
+; Copy zero-terminated buffer from real mode to protected mode
+;
+; In:   AX:EDI  Destination address
+;
+; Note: always uses OFFSET_1
+;
+
+                ASSUME  DS:SV_DATA
+
+MOVEZ_FROM_RM   PROC    NEAR
+                PUSH    DS
+                PUSH    ES
+                PUSH    EAX
+                PUSH    ESI
+                PUSH    EDI
+                MOV     ES, AX
+                MOV     ESI, OFFSET_1
+                MOV     DS, BUF_SEL
+                ASSUME  DS:NOTHING
+                CLD
+                TALIGN  4
+MZFRM1:         LODS    BYTE PTR DS:[ESI]
+                STOS    BYTE PTR ES:[EDI]
+                TEST    AL, AL
+                JNZ     SHORT MZFRM1
+                POP     EDI
+                POP     ESI
+                POP     EAX
+                POP     ES
+                POP     DS
+                RET
+MOVEZ_FROM_RM   ENDP
+
+;
+; Set a breakpoint to the return address of the current interrupt/exception
+; frame (only if -S option is used)
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+                TALIGN  4
+BREAK_AFTER_IRET PROC    NEAR
+                CMP     STEP_FLAG, FALSE
+                JE      SHORT BAI_RET
+                MOV     DX, I_CS
+                MOV     EAX, I_EIP
+                CALL    SET_BREAKPOINT
+                CALL    INS_BREAKPOINTS
+BAI_RET:        RET
+                ASSUME  BP:NOTHING
+BREAK_AFTER_IRET ENDP
+
+
+;
+; Set the DBCS lead byte table.  This function must be called from PMINT.
+;
+; Out: AX       Zero if successful, non-zero on error
+;
+                ASSUME  DS:SV_DATA
+GET_DBCS_LEAD   PROC    NEAR
+;
+; First clear all bits in case we can't retrieve the DBCS lead bytes
+;
+                PUSH    DS
+                POP     ES
+                MOV     DI, DBCS_LEAD_TAB
+                MOV     CX, 256 / 8 / 2
+                MOV     AX, 0
+                REP     STOSW
+;
+; Call DOS to get the DBCS lead bytes
+;
+                MOV     RM_AX, 6300H
+                MOV     RM_DS, 0FFFEH
+                MOV     RM_SI, 0FFFFH
+                CALL    INT_RM
+;
+; Note that some DOS versions return AL=0 even if this function is
+; not supported.  Do some sanity checking on DS:SI
+;
+                CMP     BYTE PTR RM_AX[0], 0
+                JNE     SHORT GDL_FAIL
+                CMP     RM_SI, -12
+                JA      SHORT GDL_FAIL
+                MOV     AX, RM_DS
+                CMP     AX, 0FFFEH
+                JE      SHORT GDL_FAIL
+                SHL     EAX, 16
+                MOV     AX, RM_SI
+                CALL    ACCESS_LOWMEM
+                MOV     ESI, EBX
+                MOV     AX, G_LOWMEM_SEL
+                MOV     ES, AX
+                MOV     CX, 6
+GDL_CHECK1:     MOV     AX, ES:[EBX]
+                TEST    AX, AX
+                JZ      SHORT GDL_CHECK1_OK
+                CMP     AL, 80H
+                JB      SHORT GDL_FAIL
+                CMP     AL, AH
+                JA      SHORT GDL_FAIL
+                ADD     EBX, 2
+                LOOP    GDL_CHECK1
+GDL_FAIL:       MOV     AX, 1
+                RET
+
+;
+; The table looks OK; now set the bits
+;
+GDL_CHECK1_OK:  MOV     CX, 0
+GDL_LOOP1:      MOV     AX, ES:[ESI]
+                TEST    AX, AX
+                JZ      SHORT GDL_DONE
+                ADD     ESI, 2
+                MOV     CL, AL
+GDL_LOOP2:      BTS     DBCS_LEAD_TAB, CX
+                CMP     CL, AH
+                JAE     SHORT GDL_LOOP1
+                INC     CL
+                JMP     SHORT GDL_LOOP2
+
+GDL_DONE:       XOR     AX, AX
+                RET
+
+GET_DBCS_LEAD   ENDP
+
+SV_CODE         ENDS
+
+
+;
+; Yes, this module contains real-mode code.
+;
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+;
+;
+
+;
+; Use backward jump to this code for processors with BIG prefetch queue
+;
+                TALIGN  4
+INT_BACK_1:     JMPF16  G_SV_CODE_SEL, RM_INT9
+
+;
+; Generic software interrupt without conversion
+;
+                ASSUME  DS:SV_DATA
+FLUSH2:         CALL    GET_REGS                ; Load registers from variables
+                ASSUME  DS:NOTHING
+INT_OP_2        LABEL   BYTE
+                INT     0                       ; Call interrupt routine
+                CALL    PUT_REGS                ; Store registers to variables
+                JMP     SHORT INT_BACK          ; Back to protected mode
+
+;
+; Hardware interrupt
+;
+                ASSUME  DS:NOTHING
+                TALIGN  4
+FLUSH1:         PUSH    ES
+                PUSH    BP
+INT_OP_1        LABEL   BYTE
+                INT     0
+                STI                             ; Allow interrupts here
+                POP     BP
+                POP     ES
+                CMP     ES:HW_INT_VEC, 01H      ; Keyboard interrupt (IRQ1)?
+                JNE     SHORT POSTINT_10
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                TEST    STDIN_TERMIO.C_LFLAG, IDEFAULT
+                JNZ     SHORT POSTINT_10
+                TEST    STDIN_TERMIO.C_LFLAG, ISIG
+                JZ      SHORT POSTINT_10
+                CALL    POLL_KEYBOARD
+                ASSUME  DS:NOTHING
+POSTINT_10:
+;
+;
+;
+                ASSUME  DS:NOTHING
+INT_BACK:       MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                CALL    CHECK_A20               ; A20 enabled?
+                TEST    AX, AX
+                JNZ     SHORT INT_BACK_GO       ; Yes -> skip
+                CALL    A20_ON                  ; Enable A20
+INT_BACK_GO:    CLI
+                CMP     VCPI_FLAG, FALSE        ; VCPI?
+                JNE     INT_BACK_VCPI           ; Yes -> use server
+                LGDT    GDT_PTR
+                LIDT    IDT_PTR
+                MOV     EAX, CR0
+                OR      EAX, CR0_PE             ; Enable protected mode
+                MOV     CR0, EAX
+                JMP     INT_BACK_1              ; Flush prefetch queue
+
+
+                TALIGN  4
+RM_INT2         LABEL   FAR
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                MOV     FS, AX
+                MOV     GS, AX
+                MOV     AX, RM_STACK
+                MOV     SS, AX
+                LEA     SP, RM_TOS
+                LIDT    REAL_IDT_PTR
+;
+; Entrypoint from VCPI server
+;
+V2V_CONT:       MOV     BP, FRAME_PTR           ; Access registers of prot mode
+                MOV     AX, SV_STACK
+                MOV     ES, AX
+                CMP     MACHINE, MACH_PC        ; PC?
+                JE      SHORT INT_BEG_1         ; Yes -> keep A20 enabled
+                CMP     MACHINE, MACH_INBOARD   ; Inboard 386/PC?
+                JE      SHORT INT_BEG_1         ; Yes -> keep A20 enabled
+                CALL    A20_OFF                 ; No  -> disable A20
+INT_BEG_1:      MOV     AL, ES:INT_NO           ; Uses BP!
+                CMP     AL, 10H
+                JE      VIO_INT
+                CMP     AL, 11H
+                JE      SOFTWARE_INT
+                CMP     AL, 14H
+                JE      SOFTWARE_INT
+                CMP     AL, 16H
+                JE      SOFTWARE_INT
+                CMP     AL, 17H
+                JE      SOFTWARE_INT
+                CMP     AL, 21H
+                JE      SHORT DOS_INT
+                CMP     AL, 33H
+                JE      SOFTWARE_INT
+                MOV     CS:INT_OP_1+1, AL       ; Self-modifying code,
+                JMP     FLUSH1                  ; flush prefetch queue!
+
+
+
+                ASSUME  DS:SV_DATA
+
+                TALIGN  4
+DOS_INT:        STI                             ; Enable interrupts
+                MOV     AX, ES:RM_AX
+                CMP     AX, 7F16H               ; Poll keyboard?
+                JE      SHORT DOS_INT_PK
+                CMP     AX, 7F2AH               ; __nls_memupr()?
+                JE      SHORT DOS_INT_MEMUPR
+                PUSH    AX
+                CMP     AH, 4BH                 ; Exec?
+                JNE     SHORT DOS_INT_1
+                PUSH    ES
+                CALL    CLEANUP_INT             ; Cleanup interrupts
+                POP     ES
+DOS_INT_1:      CALL    GET_REGS                ; Load registers from variables
+                ASSUME  DS:NOTHING
+                CMP     AH, 4CH                 ; Terminate process?
+                JE      EXIT                    ; Yes ->
+                INT     21H
+                CALL    PUT_REGS
+                POP     AX
+                CMP     AH, 4BH                 ; Exec?
+                JNE     SHORT DOS_INT_2
+                CALL    INIT_INT                ; Reinitialize interrupts
+DOS_INT_2:      JMP     INT_BACK
+
+
+DOS_INT_PK:     CALL    POLL_KEYBOARD
+                JMP     SHORT DOS_INT_2
+
+;
+; Real-mode part of __nls_memupr()
+;
+                ASSUME  DS:SV_DATA
+
+DOS_INT_MEMUPR: CMP     ES:RM_CX, 0
+                JE      SHORT DOS_INT_2
+                LEA     DX, COUNTRYDATA
+                MOV     AX, 3800H
+                INT     21H
+                JC      SHORT DOS_INT_2
+                MOV     BX, ES:RM_DX
+                MOV     CX, ES:RM_CX
+                MOV     ES, BUF_SEG
+MEMUPR_LOOP:    MOV     AL, ES:[BX]
+                TEST    AL, AL
+                JS      SHORT MEMUPR_HIGH
+                CMP     AL, "a"
+                JB      SHORT MEMUPR_NEXT
+                CMP     AL, "z"
+                JA      SHORT MEMUPR_NEXT
+                SUB     AL, "a" - "A"
+MEMUPR_STORE:   MOV     ES:[BX], AL
+MEMUPR_NEXT:    INC     BX
+                LOOP    MEMUPR_LOOP
+                JMP     SHORT DOS_INT_2
+
+MEMUPR_HIGH:    CALL    CD_CASEMAP
+                JMP     SHORT MEMUPR_STORE
+
+;
+; Software interrupt 10H
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+VIO_INT:        STI                             ; Enable interrupts
+                CALL    GET_REGS                ; Load registers from variables
+                ASSUME  DS:NOTHING
+                PUSH    AX                      ; Save AH (function number)
+                INT     10H                     ; Call BIOS
+                CALL    PUT_REGS                ; Store registers to variables
+                POP     AX                      ; Restore AH (function number)
+                CMP     AH, 00H                 ; Set mode?
+                JNE     INT_BACK                ; No  -> back to protected mode
+                CALL    VINIT                   ; Get new width and height
+                JMP     INT_BACK                ; Back to protected mode
+
+;
+; Generic software interrupt
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+SOFTWARE_INT:   STI                             ; Enable interrupts
+                MOV     CS:INT_OP_2+1, AL       ; Self-modifying code,
+                JMP     FLUSH2                  ; flush prefetch queue!
+
+
+;
+; Load registers from variables
+;
+; Attention: ES:BP points to protected mode stack frame!
+; 
+                ASSUME  DS:NOTHING
+                TALIGN  4
+GET_REGS        PROC    NEAR
+                MOV     AX, ES:RM_AX
+                MOV     BX, ES:RM_BX
+                MOV     CX, ES:RM_CX
+                MOV     DX, ES:RM_DX
+                MOV     SI, ES:RM_SI
+                MOV     DI, ES:RM_DI
+                MOV     DS, ES:RM_DS
+                PUSH    ES:RM_BP
+                MOV     ES, ES:RM_ES
+                POP     BP
+                RET
+GET_REGS        ENDP
+
+
+;
+; Has to load ES:BP with address of protected-mode stack frame!
+; 
+                ASSUME  DS:NOTHING
+                TALIGN  4
+PUT_REGS        PROC    NEAR
+                PUSH    DS
+                PUSH    ES
+                PUSH    BP
+                PUSH    AX
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                MOV     AX, SV_STACK
+                MOV     ES, AX
+                MOV     BP, FRAME_PTR
+                LAHF
+                MOV     ES:RM_FLAGS, AH
+                POP     ES:RM_AX
+                POP     ES:RM_BP
+                POP     ES:RM_ES
+                POP     ES:RM_DS
+                MOV     ES:RM_BX, BX
+                MOV     ES:RM_CX, CX
+                MOV     ES:RM_DX, DX
+                MOV     ES:RM_SI, SI
+                MOV     ES:RM_DI, DI
+                RET
+PUT_REGS        ENDP
+
+
+
+;
+; Allocate buffers for real-mode interface.
+;
+; We need two buffers:
+;
+;  - the first buffer is used for the user program's i/o
+;
+;  - the second buffer is used for the swapper's i/o. The swapper
+;    may be activated while copying the user program's i/o buffer
+;
+; The two buffers have there own selectors (and GDT entries)
+;
+
+                ASSUME  DS:SV_DATA
+INIT_BUFFER     PROC    NEAR
+                MOV     BX, 1000H               ; 64 KB
+                LEA     DI, G_BUF1_DESC
+                CALL    INIT_BUF_1
+                MOV     BUF1_SEG, AX            ; Main buffer segment
+                MOV     BX, 0101H               ; 4 KB + 16 Bytes
+                LEA     DI, G_BUF2_DESC
+                CALL    INIT_BUF_1
+                MOV     BUF2_SEG, AX            ; Swapper buffer segment
+;
+; Select 1st buffer (64KB)
+;
+                MOV     AX, BUF1_SEG
+                MOV     BUF_SEG, AX
+                MOV     BUF_SEL, G_BUF1_SEL
+                RET
+
+
+INIT_BUF_1      PROC    NEAR
+                MOV     AH, 48H
+                INT     21H
+                JC      RM_OUT_OF_MEM
+                PUSH    AX
+                MOVZX   EAX, AX
+                SHL     EAX, 4
+                CALL    RM_SEG_BASE
+                POP     AX
+                RET
+INIT_BUF_1      ENDP
+
+INIT_BUFFER     ENDP
+
+
+              IF DEBUG_DOSDUMP
+
+                ASSUME  DS:NOTHING
+DOSDUMP         PROC    NEAR
+                PUSHAD
+                PUSH    DS
+                PUSH    ES
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                LEA     BX, $DOSDUMP_C
+DOSDUMP_10:     MOV     AL, [BX]
+                INC     BYTE PTR [BX]
+                CMP     AL, "9"
+                JNE     SHORT DOSDUMP_11
+                MOV     BYTE PTR [BX], "0"
+                DEC     BX
+                JMP     SHORT DOSDUMP_10
+
+DOSDUMP_11:     LEA     DX, $DOSDUMP
+                MOV     CX, 0
+                MOV     AH, 3CH
+                INT     21H
+                JC      SHORT DOSDUMP_ERR
+                MOV     BX, AX
+                MOV     CX, 640 / 32
+                MOV     SI, 0
+DOSDUMP_20:     PUSH    CX
+                PUSH    DS
+                MOV     DS, SI
+                ASSUME  DS:NOTHING
+                MOV     DX, 0
+                MOV     CX, 32 * 1024
+                MOV     AH, 40H
+                INT     21H
+                POP     DS
+                ASSUME  DS:SV_DATA
+                POP     CX
+                JC      SHORT DOSDUMP_ERR
+                ADD     SI, 32 * 1024 / 16
+                LOOP    DOSDUMP_20
+                MOV     AH, 3EH
+                INT     21H
+                JMP     SHORT DOSDUMP_RET
+
+DOSDUMP_ERR:
+DOSDUMP_RET:    POP     ES
+                POP     DS
+                POPAD
+                RET
+DOSDUMP         ENDP
+
+              ENDIF
+
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/pmint.inc
===================================================================
--- trunk/src/emx/src/dos/pmint.inc	(revision 18)
+++ trunk/src/emx/src/dos/pmint.inc	(revision 18)
@@ -0,0 +1,205 @@
+;
+; PMINT.INC -- Handle interrupts
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+; 
+; Stack (at PMINT_STACK_SNAP_SHOT):
+;
+;  GS FS ES DS EDI ESI EBP ESP EBX EDX ECX EAX ERRCD EIP CS EFLAGS ESP(U) SS(U)
+;  0  2  4  6  8   12  16  20  24  28  32  36  40    44  48 52     56     60
+;  ^                                           -----               ------------
+;  |                                           simulated           only for
+;  EBP                                         for interrupts      user program
+;                                              and exc. 0..7, 16
+;
+; See also PROCESS.INC, SPECIAL.ASM, /emx/include/sys/reg.h.
+;
+
+ISTACKFRAME     STRUC
+IS_GS           DW      ?                       ; 0
+IS_FS           DW      ?                       ; 2
+IS_ES           DW      ?                       ; 4
+IS_DS           DW      ?                       ; 6
+IS_EDI          DD      ?                       ; 8
+IS_ESI          DD      ?                       ; 12
+IS_EBP          DD      ?                       ; 16
+IS_ESP_1        DD      ?                       ; 20
+IS_EBX          DD      ?                       ; 24
+IS_EDX          DD      ?                       ; 28
+IS_ECX          DD      ?                       ; 32
+IS_EAX          DD      ?                       ; 36
+IS_ERRCD        DD      ?                       ; 40
+IS_EIP          DD      ?                       ; 44
+IS_CS           DW      ?                       ; 48
+IS_CS_PAD       DW      ?                       ; 50
+IS_EFLAGS       DD      ?                       ; 52
+IS_ESP          DD      ?                       ; 56
+IS_SS           DW      ?                       ; 60
+IS_SS_PAD       DW      ?                       ; 62
+ISTACKFRAME     ENDS
+
+I_GS            EQU     [BP].IS_GS
+I_FS            EQU     [BP].IS_FS
+I_ES            EQU     [BP].IS_ES
+I_DS            EQU     [BP].IS_DS
+I_EDI           EQU     [BP].IS_EDI
+I_ESI           EQU     [BP].IS_ESI
+I_EBP           EQU     [BP].IS_EBP
+I_ESP_1         EQU     [BP].IS_ESP_1
+I_EBX           EQU     [BP].IS_EBX
+I_EDX           EQU     [BP].IS_EDX
+I_ECX           EQU     [BP].IS_ECX
+I_EAX           EQU     [BP].IS_EAX
+I_ERRCD         EQU     [BP].IS_ERRCD
+I_EIP           EQU     [BP].IS_EIP
+I_CS            EQU     [BP].IS_CS
+I_EFLAGS        EQU     [BP].IS_EFLAGS
+I_ESP           EQU     [BP].IS_ESP
+I_SS            EQU     [BP].IS_SS
+
+I_REG_DWORDS    =       16                              ; Cf. PROCESS.ASM
+
+;
+; Size of local variables of exception/interrupt handler
+;
+FRAME_SIZE      =       38
+
+;
+; Local variables for exceptions
+;
+VOUTPUT         EQU     (BYTE PTR  [BP-2])
+SWAP_PIDX       EQU     (BYTE PTR  [BP-3])
+EXCEPT_NO       EQU     (BYTE PTR  [BP-4])
+FAULT_ADDR      EQU     (DWORD PTR [BP-8])
+ETEXT           EQU     (WORD PTR  [BP-10])
+EBYTE           EQU     (WORD PTR  [BP-12])
+EWORD           EQU     (WORD PTR  [BP-14])
+EDWORD          EQU     (WORD PTR  [BP-16])
+ECRLF           EQU     (WORD PTR  [BP-18])
+ECHAR           EQU     (WORD PTR  [BP-20])
+EXC_UNUSED_1    EQU     (DWORD PTR [BP-24])
+FAULT_PROC      EQU     (WORD PTR [BP-26])
+
+;
+; Local variables for interrupts
+;
+INT_NO          EQU     (BYTE PTR [BP-1])
+HW_INT_VEC      EQU     (BYTE PTR [BP-2])
+;unused         EQU     (BYTE PTR [BP-3])
+RM_FLAGS        EQU     (BYTE PTR [BP-4])
+INP_HANDLE      EQU     (WORD PTR [BP-6])
+RM_AX           EQU     (WORD PTR [BP-8])
+RM_BX           EQU     (WORD PTR [BP-10])
+RM_CX           EQU     (WORD PTR [BP-12])
+RM_DX           EQU     (WORD PTR [BP-14])
+RM_SI           EQU     (WORD PTR [BP-16])
+RM_DI           EQU     (WORD PTR [BP-18])
+RM_BP           EQU     (WORD PTR [BP-20])
+RM_DS           EQU     (WORD PTR [BP-22])
+RM_ES           EQU     (WORD PTR [BP-24])
+NREQ            EQU     (DWORD PTR [BP-28])
+NPTR            EQU     (DWORD PTR [BP-32])
+N_TMP           EQU     (WORD PTR [BP-34])
+N_AX            EQU     (WORD PTR [BP-36])
+CONV_FLAG       EQU     (WORD PTR [BP-38])
+
+;
+; Communication area for __fpuemu()
+;
+FPUEMU_COM      STRUCT
+FEC_NOTIFY      DD      ?
+FEC_PNUM        DD      ?
+FEC_SIGNAL      DD      ?
+FEC_FRAME       DD      I_REG_DWORDS DUP (?)
+FPUEMU_COM      ENDS
+
+FPUC_INIT       =       0
+FPUC_NEXT       =       1
+FPUC_SIGNAL     =       2
+
+FPUN_NEWPROC    =       0
+FPUN_ENDPROC    =       1
+FPUN_EMU        =       2
+
+;
+; These are the offsets of the PM/RM communication buffer
+;
+; Note: There's a bug in DOS function 5AH (COMPAQ DOS 3.31):
+;       It stores a backslash DS:[DX+0FFFFH] if DX=0 !!!
+;       0 < OFFSET_1 < 16 (cf. D_READ, D_WRITE, INIT_BUFFER)
+;
+OFFSET_1        =       0004H           ; Used if one buffer is required
+OFFSET_2        =       8000H           ; Used for second buffer if two
+                                        ; buffers are required
+              IFNDEF __PMINT
+
+SV_DATA         SEGMENT
+
+                EXTRN   BUF_SEG:WORD
+                EXTRN   BUF_SEL:WORD
+                EXTRN   BUF1_SEG:WORD
+                EXTRN   BUF2_SEG:WORD
+                EXTRN   PMINT0_TAB:WORD
+                EXTRN   PMINT8_TAB:WORD
+                EXTRN   RM_CR0:DWORD
+                EXTRN   PM_CR0:DWORD
+                EXTRN   DBCS_LEAD_TAB:WORD
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                EXTRN   IRQ0_ADD:BYTE
+                EXTRN   IRQ8_ADD:BYTE
+
+                EXTRN   INTERRUPT:NEAR          ; Unexpected interrupt
+                EXTRN   V2P_CONT:NEAR           ; Return from VCPI server
+                EXTRN   DOSF_ERROR:NEAR         ; Invalid function code
+                EXTRN   BREAK_AFTER_IRET:NEAR   ; Set breakpoint to ret addr
+                EXTRN   NMI:NEAR                ; NMI handler
+                EXTRN   PMINT_10H:NEAR          ; VIO interface interrupt
+                EXTRN   PMINT_11H:NEAR          ; Equipment interrupt
+                EXTRN   PMINT_14H:NEAR          ; ASY interface interrupt
+                EXTRN   PMINT_16H:NEAR          ; KBD interface interrupt
+                EXTRN   PMINT_17H:NEAR          ; PRN interface interrupt
+                EXTRN   PMINT_21H:NEAR          ; DOS interface interrupt
+                EXTRN   PMINT_31H:NEAR          ; EXT interface interrupt
+                EXTRN   PMINT_33H:NEAR          ; MOU interface interrupt
+                EXTRN   INT_RM:NEAR             ; Call RM interrupt routine
+                EXTRN   GET_DBCS_LEAD:NEAR      ; Get DBCS lead bytes
+
+MOVE_TO_RM      PROTO   NEAR
+MOVE_FROM_RM    PROTO   NEAR
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   V2V_CONT:NEAR
+                EXTRN   INIT_BUFFER:NEAR
+
+INIT_CODE       ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/pmio.asm
===================================================================
--- trunk/src/emx/src/dos/pmio.asm	(revision 18)
+++ trunk/src/emx/src/dos/pmio.asm	(revision 18)
@@ -0,0 +1,320 @@
+;
+; PMIO.ASM -- File I/O for the kernel
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+
+                PUBLIC  DEBUG_FLAG
+                PUBLIC  OPEN, SEEK, READ, WRITE, CREATE_TMP, CLOSE
+                PUBLIC  FORCE_STDOUT, FIND_FILE, ACCESS
+
+
+SV_DATA         SEGMENT
+
+DEBUG_FLAG      DB      FALSE
+STDOUT_NAME     DB      "CON", 0
+
+SV_DATA         ENDS
+
+
+
+PMIO_BEGIN      MACRO
+                PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                ENDM
+
+PMIO_END        MACRO
+                POP     PROCESS_PTR
+                ENDM
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING, ES:SV_DATA
+
+
+;
+; Open file
+;
+; In:   AX:EDX  Pointer to name
+;       CL      Access code
+;
+; Out:  CY      Error
+;       EAX     File handle or error code
+;
+                ASSUME  DS:SV_DATA
+OPEN            PROC    NEAR
+                PMIO_BEGIN
+                PUSH    DS
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                MOV     AH, 3DH
+                MOV     AL, CL
+                INT     21H
+                POP     DS
+                ASSUME  DS:SV_DATA
+                PMIO_END
+                RET
+OPEN            ENDP
+
+;
+; Close file
+;
+; In:   BX      File handle
+;
+                ASSUME  DS:SV_DATA
+CLOSE           PROC    NEAR
+                PMIO_BEGIN
+                MOVZX   EBX, BX
+                MOV     AH, 3EH
+                INT     21H
+                PMIO_END
+                RET
+CLOSE           ENDP
+
+;
+; Create temporary file
+;
+; In:   AX:EDX  Pointer to name
+;
+                ASSUME  DS:SV_DATA
+CREATE_TMP      PROC    NEAR
+                PMIO_BEGIN
+                PUSH    DS
+                PUSH    ECX
+                MOV     CX, 0000H
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                MOV     AH, 5AH
+                INT     21H
+                POP     ECX
+                POP     DS
+                ASSUME  DS:SV_DATA
+                PMIO_END
+                RET
+CREATE_TMP      ENDP
+
+
+;
+; In:   BX      File handle
+;       EDX     Position
+;
+                ASSUME  DS:SV_DATA
+SEEK            PROC    NEAR
+                PMIO_BEGIN
+                PUSH    EAX
+                MOVZX   EBX, BX
+                MOV     AL, 0
+                MOV     AH, 42H
+                INT     21H
+                POP     EAX
+                PMIO_END
+                RET
+SEEK            ENDP
+
+
+;
+; In:   BX      File handle
+;       ECX     Number of bytes
+;       AX:EDX  Pointer to buffer
+;
+; Out:  CY      Error
+;       NC NZ   EOF
+;       NC ZR   OK
+;
+                ASSUME  DS:SV_DATA
+READ            PROC    NEAR
+                PMIO_BEGIN
+                PUSH    EAX
+                PUSH    DS
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                MOVZX   EBX, BX
+                MOV     AH, 3FH
+                INT     21H
+                JC      SHORT READ_RET
+                CMP     ECX, EAX
+                CLC
+READ_RET:       POP     DS
+                ASSUME  DS:SV_DATA
+                POP     EAX
+                PMIO_END
+                RET
+READ            ENDP
+
+
+;
+; In:   BX      File handle
+;       ECX     Number of bytes
+;       AX:EDX  Pointer to buffer
+;
+; Out:  CY      Error
+;       NC NZ   Disk full
+;       NC ZR   OK
+;
+                ASSUME  DS:SV_DATA
+WRITE           PROC    NEAR
+                PMIO_BEGIN
+                PUSH    EAX
+                PUSH    DS
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                MOVZX   EBX, BX
+                MOV     AH, 40H
+                INT     21H
+                JC      SHORT WRITE_RET
+                CMP     ECX, EAX
+                CLC
+WRITE_RET:      POP     DS
+                ASSUME  DS:SV_DATA
+                POP     EAX
+                PMIO_END
+                RET
+WRITE           ENDP
+
+
+;
+; Force stdout to refer to the CON device (put error message on screen)
+;
+                ASSUME  DS:SV_DATA
+FORCE_STDOUT    PROC    NEAR
+                PMIO_BEGIN
+                XOR     EDX, EDX
+                LEA     DX, STDOUT_NAME
+                MOV     AH, 3DH
+                MOV     AL, 41H                 ; Deny none; write
+                INT     21H
+                JC      SHORT FS_RET
+                MOV     EBX, EAX
+                MOV     ECX, 1                  ; stdout
+                MOV     AH, 46H                 ; Force duplicate file handle
+                INT     21H
+FS_RET:         PMIO_END
+                RET
+FORCE_STDOUT    ENDP
+
+
+;
+; Find file in directories listed by an environment variable
+;
+; In:   DS:SI   File name
+;       DS:BX   Buffer (filled by FIND_FILE), must be large enough
+;       ES:EDI  Search path (separated by ';', 0 terminated)
+;
+; Out:  CY      Not found
+;
+; Note: ES:EDI must point to the value of the environment variable
+;       The buffer pointed to by DS:BX will contain the path name on success
+;       Blanks are not removed
+;
+FIND_FILE       PROC    NEAR
+                PUSH    EDI
+                PUSH    CX
+FF_NEXT_DIR:    
+;
+; Now ES:DI points to the next directory
+; Build path name at DS:BX
+;
+                PUSH    BX
+                PUSH    SI
+                XOR     CX, CX
+FF_DIR_COPY:    MOV     AL, ES:[EDI]
+                OR      AL, AL
+                JZ      SHORT FF_DIR_END
+                CMP     AL, ";"
+                JE      SHORT FF_DIR_END
+                MOV     [BX], AL
+                INC     EDI
+                INC     BX
+                INC     CX
+                JMP     SHORT FF_DIR_COPY
+FF_DIR_END:     JCXZ    FF_EMPTY
+                MOV     AL, [BX-1]
+                CMP     AL, "\"
+                JE      SHORT FF_FNAME_COPY
+                CMP     AL, "/"
+                JE      SHORT FF_FNAME_COPY
+                CMP     AL, ":"
+                JE      SHORT FF_FNAME_COPY
+                MOV     BYTE PTR [BX], "\"
+                INC     BX
+FF_FNAME_COPY:  MOV     AL, [SI]
+                MOV     [BX], AL
+                INC     SI
+                INC     BX
+                OR      AL, AL
+                JNZ     SHORT FF_FNAME_COPY
+FF_EMPTY:       POP     SI
+                POP     BX
+                JCXZ    FF_SKIP_DIR
+;
+; Look for file
+;
+                PUSH    EDX
+                MOVZX   EDX, BX
+                CALL    ACCESS
+                POP     EDX
+                JNC     SHORT FF_RET
+;
+; Try next directory
+;
+FF_SKIP_DIR:    CMP     BYTE PTR ES:[EDI], 0
+                JE      SHORT FF_FAILURE
+                INC     EDI
+                JMP     SHORT FF_NEXT_DIR
+
+FF_FAILURE:     MOV     BYTE PTR [BX], 0
+                STC
+FF_RET:         POP     CX
+                POP     EDI
+                RET
+FIND_FILE       ENDP
+
+
+
+;
+; In:   DS:EDX  Name
+;
+; Out:  CY      Not found or not a file
+;
+ACCESS          PROC    NEAR
+                PUSH    AX
+                PUSH    CX
+                MOV     AH, 43H                 ; Get/set file attributes
+                MOV     AL, 00H                 ; Get file attributes
+                INT     21H
+                JC      SHORT ACCESS_RET
+                TEST    CX, 18H                 ; Volume label, directory?
+                JZ      SHORT ACCESS_RET
+                STC
+ACCESS_RET:     POP     CX
+                POP     AX
+                RET
+ACCESS          ENDP
+
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/pmio.inc
===================================================================
--- trunk/src/emx/src/dos/pmio.inc	(revision 18)
+++ trunk/src/emx/src/dos/pmio.inc	(revision 18)
@@ -0,0 +1,40 @@
+;
+; PMIO.INC -- File I/O for the kernel
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_DATA         SEGMENT
+
+                EXTRN   DEBUG_FLAG:BYTE
+
+SV_DATA         ENDS
+
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   OPEN:NEAR, CREATE_TMP:NEAR, CLOSE:NEAR
+                EXTRN   READ:NEAR, SEEK:NEAR, WRITE:NEAR
+                EXTRN   FORCE_STDOUT:NEAR, FIND_FILE:NEAR, ACCESS:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/process.asm
===================================================================
--- trunk/src/emx/src/dos/process.asm	(revision 18)
+++ trunk/src/emx/src/dos/process.asm	(revision 18)
@@ -0,0 +1,1305 @@
+;
+; PROCESS.ASM -- Manage processes
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__PROCESS       =       1
+                INCLUDE EMX.INC
+                INCLUDE LOADER.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE PROFIL.INC
+                INCLUDE TABLES.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE PAGING.INC
+                INCLUDE PMINT.INC
+                INCLUDE PMIO.INC
+                INCLUDE FILEIO.INC
+                INCLUDE MISC.INC
+                INCLUDE UTILS.INC
+                INCLUDE ERRORS.INC
+
+                PUBLIC  PROCESS_TABLE, PROC0, PROCESS_PTR, PROCESS_SIG
+                PUBLIC  PROCESS_FP, PROCESS_FPUEMU, PROCESS_FPUCLIENT
+                PUBLIC  FPUEMU_STATE, EMX_DIR, NP1
+                PUBLIC  VIDEO_LIN, TIMER_TABLE, TIMER_MIN, TIMER_TICKS
+                PUBLIC  NEW_PROCESS, CREATE_PID, FIND_EXEC
+                PUBLIC  REMOVE_PROCESS, ZOMBIE_PROCESS, KILL_PROCESS
+                PUBLIC  FIND_PROCESS, WAIT_PROCESS
+                PUBLIC  SAVE_PROCESS, REST_PROCESS, SET_TIMER, SLEEP
+                PUBLIC  PROCESS_INIT
+
+
+SV_DATA         SEGMENT
+
+NO_PID          =       0FFFFFFFFH
+MIN_PID         =       2
+
+NEXT_PID        DD      MIN_PID                 ; Next process ID
+PROCESS_PTR     DW      ?                       ; PTE of current process
+PROCESS_SIG     DW      ?                       ; Ditto, not changed for I/O
+PROCESS_FP      DW      ?                       ; The coprocessor contains
+                                                ; the status of this process
+PROCESS_FPUEMU  DW      ?                       ; FPU emulator PTE
+PROCESS_FPUCLIENT DW    ?                       ; FPU client PTE
+VIDEO_LIN       DD      ?                       ; Linear address of video mem
+
+TIMER_MIN       DD      0
+TIMER_TICKS     DD      0
+
+CLOCK_LO        DWORD   0
+CLOCK_HI        DWORD   0
+
+;
+; The offset of this table must be > 1 !
+; (PROCESS_PTR = NO_PROCESS = 0 means handle translation turned off,
+;  PROCESS_PTR = NO_WPROCESS = 1 is a special return value of WAIT_PROCESS)
+;
+PROCESS_TABLE   DB      MAX_PROCESSES DUP (SIZE PROCESS DUP (0))
+;
+; Dummy process (used for starting first process).  This must follow
+; directly after PROCESS_TABLE, see MAP_TRANSLATE.
+;
+PROC0           LABEL   PROCESS
+                DB      SIZE PROCESS DUP (0)
+
+;
+; This doesn't work (linker bug?):
+;
+; PROCESS_TABLE PROCESS MAX_PROCESSES DUP (<NO_PID>)
+; PROC0           PROCESS <>
+;
+
+;
+; The table of timers
+;
+                DALIGN  4
+TIMER_TABLE     TIMER MAX_TIMERS DUP (<TT_NONE, NO_PROCESS>)
+
+;
+; Temporary variables
+;
+ARGV_SIZE       DD      ?
+ENVP_SIZE       DD      ?
+
+;
+; This is the name of the directory from which emx.exe was loaded.
+; It is empty if emx.exe is bound to the executable.  The directory
+; name ends with a backslash.
+;
+EMX_DIR         DB      100 DUP (?)
+
+;
+; The result of FIND_EXEC is stored here.
+;
+EXEC_FNAME      BYTE    256 DUP (?)
+
+;
+; State of the FPU emulator
+;
+FPUEMU_STATE    DB      FES_OFF
+
+;
+; File name of the FPU emulator
+;
+$FPUEMU_NAME    DB      "emxfpemu", 0
+
+;
+; Arguments to pass to the FPU emulator (argc=0).
+;
+$FPUEMU_ARG     DB      0, 0
+
+$PROC_FULL      DB      "Too many processes", CR, LF, 0
+$INV_MODE       DB      "Invalid spawn mode", CR, LF, 0
+
+;
+; This structure is used for starting the initial process and
+; the FPU emulator.  Some members initialized by emx.asm for
+; the initial process are later used again without modification
+; for starting the FPU emulator: NP_ENV_OFF, NP_ENV_SEL, NP_ENV_COUNT,
+; NP_ENV_SIZE, NP_PARENT, and NP_FPROC.
+;
+NP1             NEW_PROC <>
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+NP_FRAME_SIZE   =       4
+NP_ARGS         EQU     (WORD PTR [BP-2])
+
+;
+; In:   SI      Pointer to arguments (STRUC NEW_PROC)
+;
+; Out:  DI      Pointer to process entry
+;       AX      Return code (0=ok)
+;       EDX     Error message (for AX > 0)
+;
+; Note: This function is not reentrant (uses global variables; GDT, for
+;       instance).
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  SI:PTR NEW_PROC
+NEW_PROCESS     PROC    NEAR
+                PUSH    EBP                     ; Build stack frame
+                MOV     BP, SP                  ; (we use some local
+                SUB     ESP, NP_FRAME_SIZE      ; variables)
+                MOV     NP_ARGS, SI             ; Save pointer to param. table
+;
+                CALL    NP_CHECK_MODE
+                OR      AX, AX
+                JNZ     SHORT NP_RET
+                CALL    NP_FIND_SLOT
+                OR      AX, AX
+                JNZ     SHORT NP_RET
+                ASSUME  DI:PTR PROCESS
+                CALL    CREATE_PID
+                CALL    NP_SET_TAB
+                CALL    NP_SEGMENTS
+
+                MOV     SI, NP_ARGS
+                MOV     AX, [SI].NP_FNAME_SEL   ; File name, selector
+                MOV     EDX, [SI].NP_FNAME_OFF  ; File name, offset
+                CALL    LOADER
+                OR      AX, AX                  ; Error?
+                JZ      SHORT LOAD_OK
+                MOV     [DI].P_PID, NO_PID      ; Remove process
+                MOV     [DI].P_STATUS, PS_NONE
+                JMP     SHORT NP_RET
+
+LOAD_OK:        CALL    NP_FILES
+                CALL    NP_SIGNALS
+                CALL    NP_STACK
+                CALL    NP_REGS
+                XOR     AX, AX                  ; Success
+NP_RET:         ADD     ESP, NP_FRAME_SIZE
+                POP     EBP
+                RET
+                ASSUME  SI:NOTHING
+                ASSUME  DI:NOTHING
+NEW_PROCESS     ENDP
+
+;
+; Check mode
+;
+                ASSUME  SI:PTR NEW_PROC
+NP_CHECK_MODE   PROC    NEAR
+                XOR     AX, AX
+                CMP     BYTE PTR [SI].NP_MODE1, NP_SPAWN_SYNC
+                JE      SHORT NP_CM_RET
+                CMP     BYTE PTR [SI].NP_MODE1, NP_SPAWN_ASYNC
+                JE      SHORT NP_CM_RET
+                CMP     BYTE PTR [SI].NP_MODE1, NP_EXEC
+                JE      SHORT NP_CM_RET
+                CMP     BYTE PTR [SI].NP_MODE1, NP_DEBUG
+                JE      SHORT NP_CM_RET
+                MOV     AX, EINVAL
+                LEA     EDX, $INV_MODE
+NP_CM_RET:      RET
+                ASSUME  SI:NOTHING
+NP_CHECK_MODE   ENDP
+
+
+;
+; Find empty process table slot
+;
+; Out: DI       Pointer to process table entry
+; 
+NP_FIND_SLOT    PROC    NEAR
+                XOR     AX, AX                  ; No error
+                LEA     DI, PROCESS_TABLE       ; The table of processes
+                ASSUME  DI:PTR PROCESS
+                MOV     DL, 1                   ; First process index
+                MOV     CX, MAX_PROCESSES       ; There are this many slots
+NP_FS_LOOP:     CMP     [DI].P_STATUS, PS_NONE  ; Empty slot?
+                JE      SHORT NP_FS_RET         ; Yes -> use it!
+                ADD     DI, SIZE PROCESS        ; Next slot
+                INC     DL                      ; Next process index
+                LOOP    NP_FS_LOOP              ; Repeat
+                ASSUME  DI:NOTHING
+                MOV     AX, EAGAIN              ; Error:
+                LEA     EDX, $PROC_FULL         ; Too many processes
+NP_FS_RET:      RET                             ; Done
+NP_FIND_SLOT    ENDP
+
+
+;
+; Create unique process ID
+;
+                TALIGN  2
+CREATE_PID      PROC    NEAR
+                PUSH    BX
+NP_CP_LOOP:     MOV     EAX, NEXT_PID           ; Get next process ID
+                INC     NEXT_PID
+                CMP     EAX, NO_PID             ; Wrap around?
+                JE      SHORT NP_CP_WRAP        ; Yes -> restart
+                CALL    FIND_PROCESS            ; PID already used?
+                CMP     BX, NO_PROCESS
+                JNE     SHORT NP_CP_LOOP        ; Yes -> next PID
+                POP     BX
+                RET
+
+NP_CP_WRAP:     MOV     NEXT_PID, MIN_PID
+                JMP     SHORT NP_CP_LOOP
+CREATE_PID      ENDP
+
+
+;
+; Initialize process table entry
+;
+                TALIGN  2
+                ASSUME  SI:PTR NEW_PROC
+                ASSUME  DI:PTR PROCESS
+NP_SET_TAB      PROC    NEAR
+                MOV     [DI].P_PID, EAX         ; Set PID
+                MOV     [DI].P_PIDX, DL         ; Set process index
+                DEC     DL                      ; Process number (0..)
+                AND     EDX, 0FFH
+                MOV     [DI].P_NUMBER, EDX
+                SHL     DX, 3                   ; 8 bytes per GDT entry
+                ADD     DX, G_LDT_SEL           ; LDT selector
+                MOV     [DI].P_LDT, DX          ; Save LDT selector
+                MOV     [DI].P_EXEC_HANDLE, NO_FILE_HANDLE
+                MOV     [DI].P_PAGE_FAULTS, 0   ; No page faults yet
+                MOV     [DI].P_FLAGS, 0         ; No flags set (see L_OPTIONS)
+                MOV     [DI].P_TRUNC, 0         ; Set -t- (see L_OPTIONS)
+                MOV     [DI].P_UFLAGS, 0        ; No user flags set
+                MOV     [DI].P_STATUS, PS_INIT  ; Process not running yet
+                MOV     [DI].P_HW_ACCESS, 0     ; See L_OPTIONS
+                MOV     [DI].P_DRIVE, 0         ; No default drive (-r option)
+                MOV     [DI].P_COMMIT_SIZE, 0   ; No add. pages (-C option)
+                MOV     [DI].P_STACK_SIZE, 00800000H ; (default; see -s option)
+                CMP     BYTE PTR [SI].NP_MODE1, NP_DEBUG ; Debugging?
+                JNE     SHORT NP_ST_1           ; No -> skip
+                MOV     [DI].P_STATUS, PS_STOP  ; Process `stopped'
+                MOV     [DI].P_SIG_NO, SIGTRAP  ; by SIGTRAP
+                OR      [DI].P_FLAGS, PF_DEBUG OR PF_WAIT_WAIT
+                OR      [DI].P_HW_ACCESS, HW_ACCESS_CODE ; Set -ac option
+NP_ST_1:        MOV     BX, [SI].NP_FPROC       ; Process which owns the files
+                ASSUME  BX:PTR PROCESS
+                MOV     AX, [BX].P_UMASK        ; Copy umask of that process
+                MOV     [DI].P_UMASK, AX        ; to new process
+                MOV     AX, [BX].P_UMASK1       ; Copy umask of that process
+                MOV     [DI].P_UMASK1, AX       ; to new process
+                MOV     BX, [SI].NP_PARENT      ; Parent process
+                MOV     EAX, [BX].P_PID         ; Copy ID of parent to
+                MOV     [DI].P_PPID, EAX        ; parent ID of new process
+                MOV     [DI].P_SYMBOLS, 0       ; No symbols (yet)
+                MOV     [DI].P_VESAINFO_PTR, 0  ; No VESA info data area
+                MOV     [DI].P_PRF_SCALE, 0     ; Profiling not active
+                RET
+                ASSUME  BX:NOTHING
+                ASSUME  SI:NOTHING
+                ASSUME  DI:NOTHING
+NP_SET_TAB      ENDP
+
+;
+; Create segments
+;
+                ASSUME  DI:PTR PROCESS
+NP_SEGMENTS     PROC    NEAR
+                LEA     SI, GDT + (G_SV_DATA_SEL AND NOT 07H)
+                CALL    GET_BASE                ; SV_DATA base address -> EBX
+
+                MOV     DX, [DI].P_LDT          ; Get LDT selector
+                MOV     SI, DX
+                LEA     SI, GDT[SI]             ; SI -> GDT
+
+                SUB     DX, G_LDT_SEL
+                IMUL    DX, LDT_ENTRIES
+                ADD     DX, OFFSET SV_DATA:LDTS
+                MOV     [DI].P_LDT_PTR, DX
+                MOVZX   EDX, DX
+                ADD     EBX, EDX                ; EBX -> LDT (linear)
+                MOV     AX, A_LDT OR DPL_0
+                MOV     ECX, 8*LDT_ENTRIES
+                CALL    CREATE_SEG              ; LDT entry in GDT
+                MOV     SI, DX                  ; SI -> LDT (SV_CODE)
+                CALL    NULL_SEG                ; null
+                ADD     SI, 8
+                CALL    NULL_SEG                ; code
+                ADD     SI, 8
+                CALL    NULL_SEG                ; data
+                ADD     SI, 8
+                MOV     EBX, VIDEO_LIN
+                MOV     ECX, 4000-1
+                MOV     AX, A_DATA32 OR DPL_3
+                CALL    CREATE_SEG              ; Video segment
+                ADD     SI, 8
+                CALL    NULL_SEG                ; Symbols and strings
+                ADD     SI, 8
+                CALL    NULL_SEG                ; Client process
+                RET
+                ASSUME  DI:NOTHING
+NP_SEGMENTS     ENDP
+
+
+;
+; Create stdin/stdout/stderr handles, inherit open files
+;
+                ASSUME  DI:PTR PROCESS
+NP_FILES        PROC    NEAR
+                MOV     SI, NP_ARGS
+                ASSUME  SI:PTR NEW_PROC
+                MOV     SI, [SI].NP_FPROC       ; Process which owns the files
+                ASSUME  SI:PTR PROCESS
+                CALL    INHERIT_HANDLES
+                RET
+                ASSUME  SI:NOTHING
+                ASSUME  DI:NOTHING
+NP_FILES        ENDP
+
+
+;
+; Setup signal handling
+;
+                ASSUME  DI:PTR PROCESS
+NP_SIGNALS      PROC    NEAR
+                MOV     SI, NP_ARGS
+                ASSUME  SI:PTR NEW_PROC
+                MOV     SI, [SI].NP_FPROC       ; Parent process
+                ASSUME  SI:PTR PROCESS
+;
+; Inherit signal handlers from parent process.  SIG_IGN is inherited
+; as SIG_IGN, everything else as SIG_DFL.
+;
+                MOV     CX, SIGNALS
+                MOV     BX, 0
+NP_SIG1:        MOV     EAX, [SI].P_SIG_HANDLERS[BX]
+                CMP     EAX, SIG_IGN
+                JE      SHORT NP_SIG2
+                MOV     EAX, SIG_DFL            ; Default signal handler
+NP_SIG2:        MOV     [DI].P_SIG_HANDLERS[BX], EAX
+                MOV     [DI].P_SA_MASK[BX], 0
+                MOV     [DI].P_SA_FLAGS[BX], SA_ACK
+                ADD     BX, 4
+                LOOP    NP_SIG1
+                MOV     [DI].P_SIG_PENDING, 0   ; No signals pending
+                MOV     [DI].P_SIG_BLOCKED, 0   ; No signals blocked
+                RET
+                ASSUME  DI:NOTHING
+NP_SIGNALS      ENDP
+
+
+;
+; Construct initial stack for C runtime startup code
+; containing environment and arguments
+;
+                ASSUME  DI:PTR PROCESS
+NP_STACK        PROC    NEAR
+;
+; Make the stack segment of the process accessible
+;
+                PUSH    SI
+                MOV     SI, [DI].P_LDT
+                MOV     AX, L_DATA_SEL
+                CALL    GET_DESC
+                MOV_ES_DS
+                PUSH    DI
+                LEA     DI, G_TMP2_DESC
+                CLD
+                MOVS    DWORD PTR ES:[DI], DWORD PTR DS:[SI]
+                MOVS    DWORD PTR ES:[DI], DWORD PTR DS:[SI]
+                POP     DI
+                POP     SI
+;
+; End ->
+;        Argument strings
+;        Environment
+;        argv[]
+; ESP -> envp[]
+;
+                MOV     SI, NP_ARGS
+                ASSUME  SI:PTR NEW_PROC
+                MOVZX   EAX, [SI].NP_ENV_COUNT  ; Get number of env strings
+                LEA     EAX, [4*EAX+4]          ; sizeof (envp[])
+                MOV     ENVP_SIZE, EAX
+                MOVZX   EAX, [SI].NP_ARG_COUNT  ; Get argc
+                LEA     EAX, [4*EAX+4]          ; sizeof (argv[])
+                MOV     ARGV_SIZE, EAX
+
+                MOV     EBX, [DI].P_STACK_ADDR
+                MOVZX   EAX, [SI].NP_ARG_SIZE   ; Size of arguments
+                SUB     EBX, EAX                ; Argument strings
+                MOVZX   EAX, [SI].NP_ENV_SIZE   ; Size of environment
+                SUB     EBX, EAX                ; Environment strings
+                SUB     EBX, ARGV_SIZE          ; argv[]
+                SUB     EBX, ENVP_SIZE          ; envp[]
+                AND     EBX, NOT 3              ; Alignment
+                MOV     [DI].P_ESP, EBX         ; Initial stack pointer
+                ASSUME  DI:NOTHING
+                PUSH    DI                      ; Save DI
+                MOV     EDI, EBX                ; Destination address
+                ADD     EDI, ENVP_SIZE
+                ADD     EDI, ARGV_SIZE
+                CLD
+                MOV     CX, [SI].NP_ENV_COUNT
+                MOV     EAX, [SI].NP_ENV_OFF
+                MOV     DX, [SI].NP_ENV_SEL
+                MOV     EBP, 0                  ; No extra bytes
+                CALL    PCOPY
+                XOR     AL, AL
+                STOS    BYTE PTR ES:[EDI]
+                MOV     CX, [SI].NP_ARG_COUNT
+                MOV     EAX, [SI].NP_ARG_OFF
+                MOV     DX, [SI].NP_ARG_SEL
+                MOV     EBP, 1                  ; One extra byte
+                PUSH    EBX                     ; Save EBX for PQUOTE
+                CALL    PCOPY
+                POP     EBX
+;
+; If the -q option is set for the parent process, quote all arguments
+;
+                TEST    [SI].NP_MODE2, NP2_QUOTE
+                JNZ     SHORT QUOTE_YES
+                CMP     PROCESS_PTR, NO_PROCESS
+                JE      SHORT QUOTE_NO
+                PUSH    BX
+                MOV     BX, PROCESS_PTR
+                TEST    (PROCESS PTR [BX]).P_FLAGS, PF_QUOTE
+                POP     BX
+                JNZ     SHORT QUOTE_YES
+QUOTE_NO:       MOV     AL, 00H
+                JMP     SHORT QUOTE_1
+QUOTE_YES:      MOV     AL, 01H
+QUOTE_1:        CALL    PQUOTE                  ; In: EBX
+;
+; Remove temporary GDT entries for security
+;
+                MOV     AX, G_NULL_SEL
+                MOV     ES, AX
+                PUSH    SI
+                LEA     SI, G_TMP1_DESC
+                CALL    NULL_SEG
+                LEA     SI, G_TMP2_DESC
+                CALL    NULL_SEG
+                POP     SI
+                POP     DI                      ; Restore DI
+                RET
+                ASSUME  SI:NOTHING
+NP_STACK        ENDP
+
+
+;
+; Set initial values of registers
+;
+; ESP is set in NP_STACK.
+;
+                ASSUME  DI:PTR PROCESS
+NP_REGS         PROC    NEAR
+                MOV     [DI].P_CS, L_CODE_SEL
+                MOV     AX, L_DATA_SEL
+                MOV     [DI].P_DS, AX
+                MOV     [DI].P_ES, AX
+                MOV     [DI].P_FS, AX
+                MOV     [DI].P_GS, AX
+                MOV     [DI].P_SS, AX
+                MOV     EAX, [DI].P_ENTRY_POINT
+                MOV     [DI].P_EIP, EAX
+                MOV     [DI].P_EFLAGS, 0202H    ; IOPL=0, IF=1
+                RET
+                ASSUME  DI:NOTHING
+NP_REGS         ENDP
+
+
+;
+; Copy arguments / environment
+;
+; In:   CX      Number of strings
+;       EAX     Offset of strings
+;       DX      Segment of strings
+;       EBP     Add this to the table entry (skipping leading bytes)
+;       EDI     Destination address for strings
+;       EBX     Destination address for table
+;
+PCOPY           PROC    NEAR
+                PUSH    ESI
+                PUSH    DS                      ; Save DS & ESI
+                PUSH    EAX
+                .386P
+                SLDT    SI
+                .386
+                MOV     AX, DX
+                CALL    GET_DESC
+                MOV_ES_DS
+                PUSH    DI
+                LEA     DI, G_TMP1_DESC
+                CLD
+                MOVS    DWORD PTR ES:[DI], DWORD PTR DS:[SI]
+                MOVS    DWORD PTR ES:[DI], DWORD PTR DS:[SI]
+                POP     DI
+                POP     ESI
+                MOV     AX, G_TMP1_SEL
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                MOV     AX, G_TMP2_SEL
+                MOV     ES, AX
+                JCXZ    PCOPY3
+PCOPY1:         MOV     ES:[EBX], EDI           ; Put pointer
+                ADD     DWORD PTR ES:[EBX], EBP ; Skip flag byte
+                ADD     EBX, 4
+PCOPY2:         LODS    BYTE PTR DS:[ESI]
+                STOS    BYTE PTR ES:[EDI]
+                OR      AL, AL
+                JNZ     SHORT PCOPY2
+                LOOP    PCOPY1
+PCOPY3:         XOR     EAX, EAX
+                MOV     ES:[EBX], EAX
+                ADD     EBX, 4
+                POP     DS
+                ASSUME  DS:SV_DATA
+                POP     ESI
+                RET
+PCOPY           ENDP
+
+
+;
+; Quote or unquote all arguments in the child process' stack.
+;
+; In:   EBX  Pointer to argv[] (in segment G_TMP2_SEL)
+;       AL   00H (unquote) or 01H (quote)
+;
+PQUOTE          PROC    NEAR
+                PUSH    EDI
+                MOV     DI, G_TMP2_SEL
+                MOV     ES, DI
+PQ_LOOP:        MOV     EDI, ES:[EBX]
+                TEST    EDI, EDI
+                JZ      SHORT PQ_RET
+                AND     BYTE PTR ES:[EDI-1], NOT 01H
+                OR      BYTE PTR ES:[EDI-1], AL
+                ADD     EBX, 4
+                JMP     SHORT PQ_LOOP
+PQ_RET:         POP     EDI
+                RET
+PQUOTE          ENDP
+
+;
+; Find process table entry for given process ID
+;
+; In:   EAX     Process ID
+;
+; Out:  BX      Pointer to process table entry (NO_PROCESS: not found)
+;
+                ASSUME  DS:SV_DATA
+FIND_PROCESS    PROC    NEAR
+                PUSH    ECX
+                LEA     BX, PROCESS_TABLE
+                ASSUME  BX:PTR PROCESS
+                MOV     CX, MAX_PROCESSES
+FP1:            CMP     EAX, [BX].P_PID
+                JE      SHORT FP2
+                ADD     BX, SIZE PROCESS
+                LOOP    FP1
+                MOV     BX, NO_PROCESS
+FP2:            POP     ECX
+                RET
+                ASSUME  BX:NOTHING
+FIND_PROCESS    ENDP
+
+
+;
+; Turn process into defunct process (zombie)
+;
+; In:   BX      Pointer to process table entry
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+ZOMBIE_PROCESS  PROC    NEAR
+                CALL    FREE_PROCESS
+                MOV     [BX].P_STATUS, PS_DEFUNCT
+                OR      [BX].P_FLAGS, PF_WAIT_WAIT
+                RET
+                ASSUME  BX:NOTHING
+ZOMBIE_PROCESS  ENDP
+
+
+;
+; Remove (kill) process
+;
+; In:   BX      Pointer to process table entry
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+REMOVE_PROCESS  PROC    NEAR
+                CALL    FREE_PROCESS
+                MOV     [BX].P_PID, NO_PID
+                MOV     [BX].P_STATUS, PS_NONE
+                RET
+                ASSUME  BX:NOTHING
+REMOVE_PROCESS  ENDP
+
+
+;
+; Remove last vestiges of a defunct process (zombie)
+;
+; In:   BX      Pointer to process table entry
+;
+; Note: Never call this without calling ZOMBIE_PROCESS first!
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+KILL_PROCESS    PROC    NEAR
+                MOV     [BX].P_PID, NO_PID      ; Remove last vestiges
+                MOV     [BX].P_STATUS, PS_NONE  ; of process
+                RET
+                ASSUME  BX:NOTHING
+KILL_PROCESS    ENDP
+
+;
+; Free all resources used by a process (but keep the process table entry)
+;
+; In:   BX      Pointer to process table entry
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+FREE_PROCESS    PROC    NEAR
+                PUSH    AX
+                PUSH    CX
+                PUSH    SI
+;
+; Unassign the FPU
+;
+                CMP     PROCESS_FP, BX          ; FPU assigned to this process?
+                JNE     SHORT FP_FPU_1          ; No  -> skip
+                MOV     PROCESS_FP, NO_PROCESS  ; Don't store FPU context
+FP_FPU_1:
+;
+; Turn off profiling
+;
+                XOR     EAX, EAX
+                XCHG    EAX, [BX].P_PRF_SCALE
+                TEST    EAX, EAX
+                JZ      SHORT FP_PROFIL_1
+                CALL    PROFIL_STOP
+FP_PROFIL_1:
+;
+; Reclaim timers
+;
+                LEA     SI, TIMER_TABLE
+                ASSUME  SI:PTR TIMER
+                MOV     CX, MAX_TIMERS
+FP_TIMER_LOOP:  CMP     [SI].T_PROCESS, BX
+                JNE     SHORT FP_TIMER_NEXT
+                MOV     [SI].T_TYPE, TT_NONE
+                MOV     [SI].T_PROCESS, NO_PROCESS
+FP_TIMER_NEXT:  ADD     SI, SIZE TIMER
+                LOOP    FP_TIMER_LOOP
+                ASSUME  SI:NOTHING
+;
+; Reclaim memory
+;
+                MOV     AL, [BX].P_PIDX         ; Get process index
+                CALL    FREE_LIN                ; Free linear address space
+                CALL    FREE_PAGES              ; Adjust page table entries
+;
+; Close all files
+;
+                CALL    CLOSE_HANDLES
+;
+; Close exec file
+;
+                MOV     AX, NO_FILE_HANDLE
+                XCHG    AX, [BX].P_EXEC_HANDLE
+                CMP     AX, NO_FILE_HANDLE
+                JE      SHORT RP_1
+                PUSH    BX
+                MOV     BX, AX
+                CALL    CLOSE
+                POP     BX
+RP_1:           POP     SI
+                POP     CX
+                POP     AX
+                RET
+                ASSUME  BX:NOTHING
+FREE_PROCESS    ENDP
+
+
+;
+; Store the registers saved on the stack by an interrupt
+; in the process table entry
+;
+; In:   SS:BP   Pointer to interrupt stack frame
+;       DS:BX   Pointer to process table entry
+;
+; Note: Only for user (ring 3) processes (ESP, SS!)
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+SAVE_PROCESS    PROC    NEAR
+                PUSH    DS
+                PUSH    ES
+                PUSH    SI
+                PUSH    DI
+                PUSH    CX
+                LEA     DI, [BX].P_GS
+                MOV_ES_DS
+                MOV     SI, BP
+                PUSH    SS
+                POP     DS
+                CLD
+                MOV     CX, I_REG_DWORDS
+                REP     MOVS DWORD PTR ES:[DI], DWORD PTR DS:[SI]
+                POP     CX
+                POP     DI
+                POP     SI
+                POP     ES
+                POP     DS
+                RET
+                ASSUME  BX:NOTHING
+SAVE_PROCESS    ENDP
+
+
+;
+; Copy the registers from a process table entry to the interrupt
+; stack frame, set TS bit of CR0, set spawnve() return value if required
+;
+; In:   SS:BP   Pointer to interrupt stack frame
+;       DS:BX   Pointer to process table entry
+;
+; Out:  LDTR
+;       CR0     TS set
+;
+; Note: Only for user (ring 3) processes (ESP, SS!)
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+                ASSUME  BP:PTR ISTACKFRAME
+REST_PROCESS    PROC    NEAR
+                PUSH    DS
+                PUSH    ES
+                PUSH    SI
+                PUSH    DI
+                PUSH    EAX
+                PUSH    ECX
+                LEA     SI, [BX].P_GS
+                MOV     DI, BP
+                PUSH    SS
+                POP     ES
+                CLD
+                MOV     CX, I_REG_DWORDS
+                REP     MOVS DWORD PTR ES:[DI], DWORD PTR DS:[SI]
+                .386P
+                LLDT    [BX].P_LDT
+                MOV     ECX, CR0
+                OR      ECX, CR0_TS             ; For coprocessor task switches
+                MOV     CR0, ECX
+                .386
+                CMP     [BX].P_STATUS, PS_WAIT_SPAWN    ; In spawnve()?
+                JNE     SHORT RP_RET
+                MOV     EAX, [BX].P_SPAWN_RC    ; Return code or PID of child
+                MOV     I_EAX, EAX              ; returned in EAX
+                TEST    [BX].P_FLAGS, PF_PSEUDO_ASYNC   ; Pseudo async child?
+                JZ      SHORT RP_RET            ; No  -> continue
+                CMP     [BX].P_SIG_HANDLERS[4*SIGCLD], SIG_IGN
+                JE      SHORT RP_RET
+                CMP     [BX].P_SIG_HANDLERS[4*SIGCLD], SIG_DFL
+                JE      SHORT RP_RET
+                BTS     [BX].P_SIG_PENDING, SIGCLD      ; Generate SIGCLD
+RP_RET:         MOV     [BX].P_STATUS, PS_RUN   ; Running again
+                POP     ECX
+                POP     EAX
+                POP     DI
+                POP     SI
+                POP     ES
+                POP     DS
+                RET
+                ASSUME  BX:NOTHING
+                ASSUME  BP:NOTHING
+REST_PROCESS    ENDP
+
+;
+; Wait for a child process
+;
+; In:   EAX     Parent process ID
+;
+; Out:  BX      Pointer to process table entry or:
+;               NO_PROCESS: no child process found
+;               NO_WPROCESS: no child process stopped/terminated
+;
+                ASSUME  DS:SV_DATA
+WAIT_PROCESS    PROC    NEAR
+                PUSH    ECX
+                PUSH    DX
+                MOV     DX, NO_PROCESS          ; Default return value
+                LEA     BX, PROCESS_TABLE
+                ASSUME  BX:PTR PROCESS
+                MOV     CX, MAX_PROCESSES
+WP_LOOP:        CMP     [BX].P_STATUS, PS_NONE  ; Empty slot?
+                JE      SHORT WP_NEXT           ; Yes -> skip
+                CMP     EAX, [BX].P_PPID        ; Child process?
+                JNE     SHORT WP_NEXT           ; No  -> skip
+                MOV     DX, NO_WPROCESS         ; Change default return value
+                TEST    [BX].P_FLAGS, PF_WAIT_WAIT      ; stopped/terminated?
+                JNZ     SHORT WP_RET            ; Yes -> found
+WP_NEXT:        ADD     BX, SIZE PROCESS
+                LOOP    WP_LOOP
+                ASSUME  BX:NOTHING
+                MOV     BX, DX
+WP_RET:         POP     DX
+                POP     ECX
+                RET
+WAIT_PROCESS    ENDP
+
+;
+; Suspend process
+;
+; In:  BX       Pointer to process table entry
+;      EAX      Number of timer ticks
+;
+; Out: EAX      Number of timer ticks remaining
+;
+                ASSUME  BX:PTR PROCESS
+SLEEP           PROC    NEAR
+                PUSH    CLOCK_LO
+                PUSH    EAX
+                AND     [BX].P_FLAGS, NOT PF_SLEEP_FLAG
+                MOV     DX, TT_SLEEP
+                CALL    SET_TIMER
+                JC      SHORT SLEEP_DONE
+SLEEP_WAIT:     MOV     EAX, [BX].P_SIG_BLOCKED ; Compute set of pending,
+                NOT     EAX                     ; unblocked signals
+                AND     EAX, [BX].P_SIG_PENDING
+                JNZ     SHORT SLEEP_DONE
+                TEST    [BX].P_FLAGS, PF_SLEEP_FLAG
+                JZ      SHORT SLEEP_WAIT
+SLEEP_DONE:     POP     EAX
+                POP     ECX
+                SUB     ECX, CLOCK_LO
+                NEG     ECX                     ; Elapsed time
+                SUB     EAX, ECX
+                JNC     SHORT SLEEP_RET
+                XOR     EAX, EAX
+SLEEP_RET:      RET
+SLEEP           ENDP
+                ASSUME  BX:NOTHING
+
+
+;
+; Set a timer. If there is already a timer of the given type, the timer
+; value is set to the new value.
+;
+; In:   BX      Pointer to process table entry
+;       DX      Timer type
+;       EAX     Timer value (ticks), stop the timer if this is zero
+;
+; Out:  CY      Table overflow
+;       EAX     Time remaining previously
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  2
+SET_TIMER       PROC    NEAR
+                PUSH    CX
+                PUSH    SI
+                LEA     SI, TIMER_TABLE
+                ASSUME  SI:PTR TIMER
+                MOV     CX, MAX_TIMERS
+                PUSH    EAX
+                CLI
+                MOV     EAX, TIMER_TICKS
+ST_ADJUST:      SUB     [SI].T_TICKS, EAX
+                ADD     SI, SIZE TIMER
+                LOOP    ST_ADJUST
+                MOV     TIMER_TICKS, 0
+                POP     EAX
+                LEA     SI, TIMER_TABLE
+                MOV     CX, MAX_TIMERS
+ST_FIND_LOOP:   CMP     [SI].T_TYPE, DX
+                JNE     SHORT ST_FIND_NEXT
+                CMP     [SI].T_PROCESS, BX
+                JE      SHORT ST_EXISTS
+ST_FIND_NEXT:   ADD     SI, SIZE TIMER
+                LOOP    ST_FIND_LOOP
+                OR      EAX, EAX                ; Stop the timer?
+                JZ      SHORT ST_OK_ZERO        ; Yes -> don't start it
+ST_NEW:         LEA     SI, TIMER_TABLE
+                MOV     CX, MAX_TIMERS
+ST_NEW_LOOP:    CMP     [SI].T_TYPE, TT_RUNNING
+                JB      SHORT ST_NEW_FOUND
+                ADD     SI, SIZE TIMER
+                LOOP    ST_NEW_LOOP
+                STC
+                JMP     SHORT ST_RET
+
+ST_NEW_FOUND:   MOV     [SI].T_TICKS, EAX
+                MOV     [SI].T_PROCESS, BX
+                MOV     [SI].T_TYPE, DX
+                CMP     TIMER_MIN, 0
+                JE      SHORT ST_NEW_1
+                CMP     EAX, TIMER_MIN
+                JAE     SHORT ST_OK_ZERO
+ST_NEW_1:       MOV     TIMER_MIN, EAX
+ST_OK_ZERO:     XOR     EAX, EAX
+                JMP     SHORT ST_OK
+
+ST_CLEAR:       MOV     [SI].T_TYPE, TT_NONE
+                MOV     EAX, [SI].T_TICKS
+                JMP     SHORT ST_OK
+
+ST_EXISTS:      OR      EAX, EAX
+                JZ      SHORT ST_CLEAR
+                PUSH    [SI].T_TICKS
+                MOV     [SI].T_TICKS, EAX
+                MOV     [SI].T_PROCESS, BX
+                MOV     [SI].T_TYPE, DX
+                CMP     TIMER_MIN, 0
+                JE      SHORT ST_RESET_1
+                CMP     EAX, TIMER_MIN
+                JAE     SHORT ST_RESET_2
+ST_RESET_1:     MOV     TIMER_MIN, EAX
+ST_RESET_2:     POP     EAX
+ST_OK:          CLC
+ST_RET:         STI
+                POP     SI
+                POP     CX
+                RET
+                ASSUME  SI:NOTHING
+SET_TIMER       ENDP
+
+;
+; Set the PAGE_ALLOC bit of EBX (for SET_PAGES) if PF_COMMIT is set.
+;
+; In:  EBX      Process table entry
+;      DI       Pointer to process table entry
+;
+; Out: EBX      Process table entry
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  DI:PTR PROCESS
+                TALIGN  2
+SET_COMMIT      PROC    NEAR
+                TEST    [DI].P_FLAGS, PF_COMMIT
+                JZ      SHORT SC_RET
+                OR      BX, PAGE_ALLOC
+SC_RET:         RET
+                ASSUME  DI:NOTHING
+SET_COMMIT      ENDP
+
+;
+; Find an executable file
+;
+; In:  SI       Pointer to program name
+;
+; Out: DX       Pointer to path name
+;
+                ASSUME  DS:SV_DATA
+FIND_EXEC       PROC    NEAR
+;
+; Use program name as is if it contains \, /, or :
+;
+                MOV     BX, SI
+FE_1:           MOV     AL, [BX]
+                INC     BX
+                CMP     AL, "/"
+                JE      SHORT FE_DEFAULT
+                CMP     AL, "\"
+                JE      SHORT FE_DEFAULT
+                CMP     AL, ":"
+                JE      SHORT FE_DEFAULT
+                OR      AL, AL
+                JNZ     SHORT FE_1
+;
+; Executable file in current directory?
+;
+                MOVZX   EDX, SI
+                CALL    ACCESS
+                JNC     SHORT FE_RET
+;
+; Search EMXPATH and PATH for executable file
+;
+                MOV     AX, G_ENV_SEL
+                MOV     ES, AX
+                LEA     BX, EXEC_FNAME          ; Buffer
+                MOVZX   EDI, ENV_EMXPATH
+                OR      EDI, EDI
+                JZ      SHORT FE_2
+                CALL    FIND_FILE
+                JNC     SHORT FE_OK
+FE_2:           MOVZX   EDI, ENV_PATH
+                OR      EDI, EDI
+                JZ      SHORT FE_DEFAULT
+                CALL    FIND_FILE
+                JNC     SHORT FE_OK
+;
+; Executable file not found (or name contains "\/:"); be naive
+;
+FE_DEFAULT:     MOVZX   EDX, SI
+                JMP     SHORT FE_RET
+;
+; Executable file found in path
+;
+FE_OK:          XOR     EDX, EDX
+                LEA     DX, EXEC_FNAME
+FE_RET:         RET
+FIND_EXEC       ENDP
+
+
+;
+; Try to load a floating point unit emulator
+;
+                ASSUME  DS:SV_DATA
+FPUEMU_LOAD     PROC    NEAR
+                MOV     FPUEMU_STATE, FES_LOADING
+;
+; Find the FPU emulator
+;
+                CMP     EMX_DIR[0], 0
+                JE      SHORT USE_PATH
+                LEA     DI, EXEC_FNAME
+                LEA     SI, EMX_DIR
+                CALL    NSTRCPY
+                MOV     DI, AX
+                LEA     SI, $FPUEMU_NAME
+                CALL    NSTRCPY
+                LEA     EDX, EXEC_FNAME
+                CALL    ACCESS
+                JNC     SHORT LOAD
+USE_PATH:       LEA     SI, $FPUEMU_NAME
+                CALL    FIND_EXEC
+;
+; Set up NP1 for loading the FPU emulator.  Don't touch the members
+; related to the environment and to the parent process, they have been
+; already initialized for the initial process and can be reused.
+;
+LOAD:           MOV     NP1.NP_FNAME_OFF, EDX
+                MOV     NP1.NP_FNAME_SEL, DS
+                MOV     NP1.NP_ARG_OFF, OFFSET $FPUEMU_ARG
+                MOV     NP1.NP_ARG_SEL, DS
+                MOV     NP1.NP_ARG_COUNT, 0
+                MOV     NP1.NP_ARG_SIZE, 0
+                MOV     NP1.NP_MODE1, NP_SPAWN_SYNC
+                MOV     NP1.NP_MODE2, 0
+                LEA     SI, NP1                 ; Arguments
+                CALL    NEW_PROCESS             ; Load the program
+                OR      AX, AX                  ; Ok?
+                JNZ     SHORT FAIL
+;
+; Put the interrupted process to sleep
+;
+                MOV     BX, PROCESS_PTR
+                MOV     PROCESS_FPUCLIENT, BX
+                MOV     (PROCESS PTR [BX]).P_STATUS, PS_FPUEMU_CLIENT
+                CALL    SAVE_PROCESS
+;
+; Run the FPU emulator.  Don't set PROCESS_SIG as SIGINT should be sent
+; to the client process instead of the FPU emulator.
+;
+                MOV     PROCESS_PTR, DI
+                MOV     BX, DI
+                CALL    REST_PROCESS
+                CALL    BREAK_AFTER_IRET                ; TODO
+                RET
+
+FAIL:           MOV     FPUEMU_STATE, FES_NONE
+                RET
+FPUEMU_LOAD     ENDP
+
+;
+; Switch to the floating point unit emulator for emulating one or more
+; floating point instructions
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+FPUEMU_CALL     PROC    NEAR
+;
+; Put the interrupted process to sleep
+;
+                MOV     DI, PROCESS_PTR
+                ASSUME  DI:PTR PROCESS
+                MOV     PROCESS_FPUCLIENT, DI
+                MOV     [DI].P_STATUS, PS_FPUEMU_CLIENT
+                MOV     BX, DI
+                CALL    SAVE_PROCESS
+;
+; Set up segment and FS register for the emulator
+;
+                MOV     BX, PROCESS_FPUEMU
+                ASSUME  BX:PTR PROCESS
+                MOV     SI, [DI].P_LDT_PTR
+                ADD     SI, L_DATA_SEL AND NOT 07H
+                MOV     EAX, [SI+0]
+                MOV     EDX, [SI+4]
+                MOV     SI, [BX].P_LDT_PTR
+                ADD     SI, L_CLIENT_SEL AND NOT 07H
+                MOV     [SI+0], EAX
+                MOV     [SI+4], EDX
+                MOV     [BX].P_FS, L_CLIENT_SEL
+;
+; Wake up the emulator
+;
+                MOV     PROCESS_PTR, BX
+                CALL    REST_PROCESS
+;;;;            CALL    BREAK_AFTER_IRET
+;
+; Fill-in the communication area
+;
+                MOV     EAX, [DI].P_NUMBER
+                ASSUME  DI:NOTHING
+                MOV     ES, I_DS
+                MOV     EDI, I_EDX
+                ASSUME  EDI:NEAR32 PTR FPUEMU_COM
+                MOV     ES:[EDI].FEC_PNUM, EAX
+                MOV     ES:[EDI].FEC_NOTIFY, FPUN_EMU
+                MOV     ES:[EDI].FEC_SIGNAL, 0
+                LEA     EDI, [EDI].FEC_FRAME
+                MOVZX   ESI, PROCESS_FPUCLIENT
+                LEA     SI, (PROCESS PTR [SI]).P_GS
+                MOV     ECX, I_REG_DWORDS
+                REP     MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
+                MOV     I_EAX, 0                ; Return 0 from __fpuemu()
+                MOV     I_ECX, 0
+                RET
+                ASSUME  BP:NOTHING
+                ASSUME  BX:NOTHING
+                ASSUME  EDI:NOTHING
+FPUEMU_CALL     ENDP
+
+
+;
+; A process has terminated, a different process is about to be run
+;
+; In:  EAX      P_NUMBER of the terminated process
+;      BP       Pointer to stack frame
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+FPUEMU_ENDPROC  PROC    NEAR
+                CMP     FPUEMU_STATE, FES_ON
+                JNE     SHORT FIN
+                MOV     FPUEMU_STATE, FES_ENDPROC
+                PUSH    EAX
+                MOV     BX, PROCESS_PTR         ; Save the incoming process
+                MOV     PROCESS_FPUCLIENT, BX
+                MOV     (PROCESS PTR [BX]).P_STATUS, PS_FPUEMU_CLIENT
+                CALL    SAVE_PROCESS
+                MOV     BX, PROCESS_FPUEMU      ; Restore the FPU emulator
+                MOV     PROCESS_PTR, BX
+                CALL    REST_PROCESS
+                MOV     ES, I_DS
+                MOV     EDI, I_EDX
+                ASSUME  EDI:NEAR32 PTR FPUEMU_COM
+                POP     ES:[EDI].FEC_PNUM
+                MOV     ES:[EDI].FEC_NOTIFY, FPUN_ENDPROC
+                MOV     ES:[EDI].FEC_SIGNAL, 0
+                MOV     I_EAX, 0
+                MOV     I_ECX, 0
+FIN:            RET
+FPUEMU_ENDPROC  ENDP
+
+
+;
+; A new process is about to start
+;
+; In:  EAX      P_NUMBER of the terminated process
+;      BP       Pointer to stack frame
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+FPUEMU_NEWPROC  PROC    NEAR
+                CMP     FPUEMU_STATE, FES_ON
+                JNE     SHORT FIN
+                MOV     FPUEMU_STATE, FES_NEWPROC
+                PUSH    EAX
+                MOV     BX, PROCESS_PTR         ; Save the incoming process
+                MOV     PROCESS_FPUCLIENT, BX
+                MOV     (PROCESS PTR [BX]).P_STATUS, PS_FPUEMU_CLIENT
+                CALL    SAVE_PROCESS
+                MOV     BX, PROCESS_FPUEMU      ; Restore the FPU emulator
+                MOV     PROCESS_PTR, BX
+                CALL    REST_PROCESS
+                MOV     ES, I_DS
+                MOV     EDI, I_EDX
+                ASSUME  EDI:NEAR32 PTR FPUEMU_COM
+                POP     ES:[EDI].FEC_PNUM
+                MOV     ES:[EDI].FEC_NOTIFY, FPUN_NEWPROC
+                MOV     ES:[EDI].FEC_SIGNAL, 0
+                MOV     I_EAX, 0
+                MOV     I_ECX, 0
+FIN:            RET
+FPUEMU_NEWPROC  ENDP
+
+
+SV_CODE         ENDS
+
+;
+; Real-mode code
+;
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+
+                ASSUME  DS:SV_DATA
+
+PROCESS_INIT    PROC    NEAR
+                LEA     BX, PROCESS_TABLE
+                ASSUME  BX:PTR PROCESS
+                MOV     CX, MAX_PROCESSES
+PI_LOOP_PROC:   MOV     [BX].P_PID, NO_PID
+                MOV     [BX].P_STATUS, PS_NONE
+                MOV     [BX].P_EXEC_HANDLE, NO_FILE_HANDLE
+                MOV     SI, 0
+PI_LOOP_HANDLE: MOV     [BX].P_HANDLES[SI], NO_FILE_HANDLE
+                MOV     [BX].P_HFLAGS[SI], 0
+                ADD     SI, 2
+                CMP     SI, 2 * MAX_FILES
+                JB      SHORT PI_LOOP_HANDLE
+                ADD     BX, SIZE PROCESS
+                LOOP    PI_LOOP_PROC
+                ASSUME  BX:NOTHING
+                MOV     PROCESS_PTR, NO_PROCESS
+                MOV     PROCESS_SIG, NO_PROCESS
+                MOV     PROCESS_FP, NO_PROCESS  ; Noone is using the FPU
+                MOV     PROCESS_FPUEMU, NO_PROCESS ; No emulator loaded
+;
+; Initialize dummy parent process.  INIT_FILEIO has already initialized
+; the P_HANDLES and P_HFLAGS arrays of PROC0.
+;
+                MOV     PROC0.P_PID, 0
+                MOV     PROC0.P_STATUS, PS_INIT
+                MOV     PROC0.P_FLAGS, 0
+                MOV     PROC0.P_TRUNC, 0
+                MOV     PROC0.P_UMASK, 022Q
+                MOV     PROC0.P_UMASK1, 644Q
+                MOV     PROC0.P_PRF_SCALE, 0
+
+                MOV     CX, SIGNALS
+                MOV     BX, 0
+PI_LOOP_SIG:    MOV     PROC0.P_SIG_HANDLERS[BX], SIG_DFL
+                MOV     PROC0.P_SA_MASK[BX], 0
+                MOV     PROC0.P_SA_FLAGS[BX], SA_ACK
+                ADD     BX, 4
+                LOOP    PI_LOOP_SIG
+
+                MOV     PROC0.P_SIG_PENDING, 0
+                MOV     PROC0.P_SIG_BLOCKED, NOT 0 ; No signals allowed
+                MOV     PROC0.P_EXEC_HANDLE, NO_FILE_HANDLE
+                RET
+PROCESS_INIT    ENDP
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/process.inc
===================================================================
--- trunk/src/emx/src/dos/process.inc	(revision 18)
+++ trunk/src/emx/src/dos/process.inc	(revision 18)
@@ -0,0 +1,340 @@
+;
+; PROCESS.INC -- Manage processes
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; Requires: SIGNAL.INC (for SIGNALS)
+;
+
+;
+; Capacity
+;
+MAX_FILES       =       40              ; Max number of open files per process
+MAX_PROCESSES   =       6               ; Max number of processes
+MAX_TIMERS      =       2 * MAX_PROCESSES       ; Max number of timers
+
+;
+; Special process pointers
+;
+NO_PROCESS      =       0               ; Used for PROCESS_PTR, PROCESS_SIG,
+                                        ; FIND_PROCESS, etc.
+NO_WPROCESS     =       1               ; Used for WAIT_PROCESS
+
+;
+; P_FLAGS bits
+;
+PF_DEBUG        =       0001H           ; Process is being debugged
+PF_WAIT_WAIT    =       0002H           ; Process waits for being waited for
+PF_387_USED     =       0004H           ; 387 used, don't FNINIT
+PF_PRELOADING   =       0008H           ; Preloading in progress (for swapper)
+PF_TERMIO_TIME  =       0010H           ; VTIME expired
+PF_SLEEP_FLAG   =       0020H           ; sleep interval expired
+PF_PSEUDO_ASYNC =       0040H           ; wait() can be done for pseudo async
+PF_REDIR_STDERR =       0200H           ; Redirect stderr to stdout
+PF_QUOTE        =       0400H           ; Quote arguments for children
+PF_COMMIT       =       0800H           ; Commit memory
+PF_DONT_ZERO    =       1000H           ; Don't zero unitialized data
+PF_PRELOAD      =       4000H           ; Disable preloading (-L)
+PF_NO_CORE      =       8000H           ; Disable core dumps (-c)
+PF_FPUEMU_INIT  =      10000H           ; FPU emu initialized for this process
+
+;
+; P_UFLAGS bits
+;
+UF_SIG_MODEL    =       00003H          ; Mask for signal() semantics
+UF_SIG_EMX      =       00000H          ; signal() semantics: emx (SIG_ACK)
+UF_SIG_SYSV     =       00001H          ; signal() semantics: System V
+UF_SIG_BSD      =       00002H          ; signal() semantics: BSD
+
+;
+; P_STATUS values
+;
+PS_NONE         =       0               ; empty slot
+PS_DEFUNCT      =       1               ; terminated, zombie (til wait)
+PS_INIT         =       2               ; initialized but not started
+PS_RUN          =       3               ; running
+PS_STOP         =       4               ; stopped (debugging)
+PS_WAIT_SPAWN   =       5               ; executes synchronous spawn
+PS_WAIT_CHILD   =       6               ; executes wait()
+PS_WAIT_PTRACE  =       7               ; executes ptrace()
+PS_FPUEMU_CLIENT =      8               ; application being serviced by FPU emu
+PS_FPUEMU_NEXT  =       9               ; FPU emulator waiting for notification
+
+;
+; Bits in the P_HW_ACCESS byte
+;
+HW_ACCESS_MEM   =       01H             ; Memory read access allowed
+HW_ACCESS_IO    =       02H             ; Port access allowed
+HW_ACCESS_WRITE =       04H             ; Memory write access allowed
+HW_ACCESS_CODE  =       08H             ; Data segment and stack executable
+
+;
+; Bits in the P_HFLAGS array, cf. <sys/fcntl.h>
+;
+HF_APPEND       =       0008H           ; O_APPEND
+HF_NDELAY       =       0004H           ; O_NONBLOCK and O_NDELAY
+HF_NOINHERIT    =       1000H           ; O_NOINHERIT and FD_CLOEXEC
+
+;
+; Process table entry
+;
+; Note: P_PID must come first to simplify initialization
+;
+PROCESS         STRUC
+P_PID           DD      ?               ; Process ID (NO_PID: slot not used)
+P_LINEAR        DD      ?               ; Linear address
+P_DSEG_SIZE     DD      ?               ; Size of data segment
+P_LIN_SIZE      DD      ?               ; Allocated linear addresses
+P_BRK           DD      ?               ; Current break value
+P_INIT_BRK      DD      ?               ; Initial break value
+P_STACK_ADDR    DD      ?               ; Top of stack
+P_STACK_SIZE    DD      ?               ; Stack size
+P_TEXT_OFF      DD      ?               ; Start of code area
+P_TEXT_SIZE     DD      ?               ; Size of code area
+P_DATA_OFF      DD      ?               ; Start of data area
+P_DATA_SIZE     DD      ?               ; Size of data area
+P_BSS_OFF       DD      ?               ; Start of bss area
+P_BSS_SIZE      DD      ?               ; Size of bss area
+P_ENTRY_POINT   DD      ?               ; Entry point
+P_NUMBER        DD      ?               ; Process number for __fpuemu()
+P_SYMBOLS       DD      ?               ; Number of symbols
+P_STATUS        DW      ?               ; Process status (PS_*)
+P_EXEC_HANDLE   DW      ?               ; Handle of executable file
+P_LDT           DW      ?               ; Selector of local descriptor table
+P_LDT_PTR       DW      ?               ; Pointer to LDT
+P_UMASK         DW      ?               ; umask
+P_UMASK1        DW      ?               ; umask (old semantics)
+P_LAST_BYTES    DW      ?               ; Number of bytes in last page
+P_PIDX          DB      ?               ; Process index for paging
+P_RC            DB      ?               ; Return code (P_STATUS = PS_DEFUNCT)
+P_SIG_NO        DB      ?               ; Signal number (P_STATUS = PS_STOP)
+P_HW_ACCESS     DB      ?               ; -a option bits
+P_DRIVE         DB      ?               ; -r option
+P_INTERFACE     DB      ?               ; Interface version, from layout table
+P_PAD           DB      0 DUP (?)       ; Padding
+P_COMMIT_SIZE   DD      ?               ; Additional pages
+P_SPAWN_RC      DD      ?               ; Return code of child process (note 1)
+P_PAGE_FAULTS   DD      ?               ; Number of page faults
+P_PPID          DD      ?               ; Parent process id
+P_STR_OFF       DD      ?               ; Offset of strings in symbol segment
+P_EXEC_OFFSET   DD      ?               ; Offset of first page in exec file
+P_LAST_PAGE     DD      ?               ; Last page of exec file (0=ignore)
+P_SYM_PAGE      DD      ?               ; Page number for symbols
+P_RELOC_SIZE    DD      ?               ; Size of relocation information
+P_FLAGS         DD      ?               ; Flags (PF_*)
+P_TRUNC         DD      ?               ; Bits set by -t option
+P_SIG_HANDLERS  DD      SIGNALS DUP (?) ; Signal handlers
+P_SA_MASK       DD      SIGNALS DUP (?) ; sa_mask of struct sigaction
+P_SA_FLAGS      DD      SIGNALS DUP (?) ; sa_flags of struct sigaction
+P_SIG_PENDING   DD      ?               ; Pending signals (bitwise)
+P_SIG_BLOCKED   DD      ?               ; Blocked signals (bitwise)
+P_UFLAGS        DD      ?               ; These flags can be changed by process
+P_VESAINFO_PTR  DD      ?               ; Pointer to VESA info data area
+P_PRF_BUFF      DD      ?               ; profil(): Pointer to counters
+P_PRF_BUFSIZ    DD      ?               ; profil(): Size of buffer
+P_PRF_OFFSET    DD      ?               ; profil(): First address
+P_PRF_SCALE     DD      ?               ; profil(): Scaling factor
+P_HANDLES       DW      MAX_FILES DUP (?)   ; DOS file handles
+P_HFLAGS        DW      MAX_FILES DUP (?)   ; Handle flags (note 2)
+;
+; Cf. PMINT.INC!!! (sequence, padding!)
+;
+P_GS            DW      ?
+P_FS            DW      ?
+P_ES            DW      ?
+P_DS            DW      ?
+P_EDI           DD      ?
+P_ESI           DD      ?
+P_EBP           DD      ?
+P_ESP_1         DD      ?
+P_EBX           DD      ?
+P_EDX           DD      ?
+P_ECX           DD      ?
+P_EAX           DD      ?
+P_ERRCD         DD      ?
+P_EIP           DD      ?
+P_CS            DW      ?, 0
+P_EFLAGS        DD      ?
+P_ESP           DD      ?
+P_SS            DW      ?, 0
+;
+; Floating point status
+;
+              IF FLOATING_POINT
+P_CW            DW      ?, 0            ; Control-word register
+P_SW            DW      ?, 0            ; Status-word register
+P_TW            DW      ?, 0            ; Tag-word register
+P_FIP           DD      ?               ; Last instruction (EIP)
+P_FCS           DW      ?               ; Last instruction (CS)
+P_FOP           DW      ?               ; Last instruction (opcode)
+P_FOO           DD      ?               ; Memory operand offset
+P_FOS           DW      ?, 0            ; Memory operand segment
+P_FST           DT      8 DUP (?)       ; Stack
+              ENDIF
+PROCESS         ENDS
+;
+; Note 1: The P_SPAWN_RC field contains the process ID of the child,
+;         if a child has been spawned for debugging (NP_DEBUG)
+;         or if an asynchronous child process has ended.
+;
+; Note 2: P_HFLAGS is 16 bits wide to simplify things -- everytime we
+;         access P_HFLAGS, we also access P_HANDLES, therefore we already
+;         have computed the offset (2 * handle)
+;
+
+;
+; Cf. <sys/process.h>
+;
+NP_SPAWN_SYNC   =       0                       ; P_WAIT
+NP_SPAWN_ASYNC  =       1                       ; P_NOWAIT
+NP_EXEC         =       2                       ; P_OVERLAY
+NP_DEBUG        =       3                       ; P_DEBUG
+
+NP2_QUOTE       =       0001H                   ; P_QUOTE >> 16
+
+;
+; Cf. struct _new_proc in <sys/emx.h>
+;
+; Note: Fields sorted by size to avoid problems with alignment (gcc!)
+;
+NEW_PROC        STRUC
+NP_ARG_OFF      DD      ?               ; Pointer to arguments (offset)
+NP_ENV_OFF      DD      ?               ; Pointer to environment (offset)
+NP_FNAME_OFF    DD      ?               ; Pointer to file name (offset)
+NP_ARG_SEL      DW      ?               ; Pointer to arguments (selector)
+NP_ENV_SEL      DW      ?               ; Pointer to environment (selector)
+NP_FNAME_SEL    DW      ?               ; Pointer to file name (selector)
+NP_ARG_COUNT    DW      ?               ; Number of arguments
+NP_ARG_SIZE     DW      ?               ; Size of arguments
+NP_ENV_COUNT    DW      ?               ; Number of environment strings
+NP_ENV_SIZE     DW      ?               ; Size of environment
+NP_MODE1        DW      ?               ; Lower 16 bits of mode (see above)
+NP_MODE2        DW      ?               ; Upper 16 bits of mode (note 2)
+; The fields below are in addition to the structure passed to function 7F06H
+NP_PARENT       DW      ?               ; Pointer to parent process (note 3)
+NP_FPROC        DW      ?               ; Pointer to files process (note 4)
+NEW_PROC        ENDS
+
+NP_USER_SIZE    =        NEW_PROC.NP_MODE2      ; Size of structure passed to
+                                                ; function 7F06H
+;
+; Note 2: The NP_MODE2 field of the NEW_PROC structure is ignored unless
+;         Bit 15 of NP_MODE1 is set.
+;
+; Note 3: The NP_PARENT field of the NEW_PROC structure points to the
+;         process table entry of the process starting the new process.
+;         If the new process is exec'ed (not spawned), this is *not*
+;         the parent process.
+;
+; Note 4: The NP_FPROC field of the NEW_PROC structure points to the
+;         process table entry of the process from which the file handles
+;         and signal settings are to be inherited.
+;
+
+;
+; Timers
+;
+TT_NONE         =       0
+TT_EXPIRED      =       1
+TT_ALARM        =       2
+TT_SLEEP        =       3
+TT_TERMIO_TIME  =       4
+
+TT_RUNNING      =       TT_ALARM        ; T_TYPE >= TT_RUNNING -> running
+
+TIMER           STRUC
+T_TYPE          DW      ?               ; Type of timer
+T_PROCESS       DW      ?               ; Pointer to process table entry
+T_TICKS         DD      ?               ; Remaining timer ticks
+TIMER           ENDS
+
+;
+; Status of floating point unit emulator.  Some of the status information
+; should be kept in P_STATUS of the PTE for the client process instead.
+;
+FES_OFF         =       0               ; FPU emu not loaded
+FES_NONE        =       1               ; Failed to load the FPU emu
+FES_LOADING     =       2               ; Loading the FPU emu
+FES_INIT1       =       3               ; Initialization, sending FPUN_NEWPROC
+FES_ON          =       4               ; Normal state of the FPU emu
+FES_NEWPROC     =       5               ; New process started
+FES_ENDPROC     =       6               ; Process ended
+
+SV_DATA         SEGMENT
+                EXTERNDEF CLOCK_LO:DWORD
+                EXTERNDEF CLOCK_HI:DWORD
+SV_DATA         ENDS
+
+              IFNDEF __PROCESS
+
+SV_DATA         SEGMENT
+
+                EXTRN   PROCESS_TABLE:DWORD
+                EXTRN   PROC0:PROCESS
+                EXTRN   PROCESS_PTR:WORD
+                EXTRN   PROCESS_SIG:WORD
+                EXTRN   PROCESS_FP:WORD
+                EXTRN   PROCESS_FPUEMU:WORD
+                EXTRN   PROCESS_FPUCLIENT:WORD
+                EXTRN   VIDEO_LIN:DWORD
+                EXTRN   TIMER_TABLE:DWORD
+                EXTRN   TIMER_MIN:DWORD
+                EXTRN   TIMER_TICKS:DWORD
+                EXTRN   FPUEMU_STATE:BYTE
+                EXTRN   NP1:NEW_PROC
+                EXTRN   EMX_DIR:BYTE
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   NEW_PROCESS:NEAR
+                EXTRN   FIND_PROCESS:NEAR
+                EXTRN   REMOVE_PROCESS:NEAR
+                EXTRN   ZOMBIE_PROCESS:NEAR
+                EXTRN   KILL_PROCESS:NEAR
+                EXTRN   SAVE_PROCESS:NEAR
+                EXTRN   REST_PROCESS:NEAR
+                EXTRN   WAIT_PROCESS:NEAR
+                EXTRN   SET_TIMER:NEAR
+                EXTRN   SLEEP:NEAR
+                EXTRN   SET_COMMIT:NEAR
+                EXTRN   CREATE_PID:NEAR
+                EXTRN   FIND_EXEC:NEAR
+                EXTRN   FPUEMU_LOAD:NEAR
+                EXTRN   FPUEMU_CALL:NEAR
+                EXTRN   FPUEMU_ENDPROC:NEAR
+                EXTRN   FPUEMU_NEWPROC:NEAR
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   PROCESS_INIT:NEAR
+
+INIT_CODE       ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/profil.asm
===================================================================
--- trunk/src/emx/src/dos/profil.asm	(revision 18)
+++ trunk/src/emx/src/dos/profil.asm	(revision 18)
@@ -0,0 +1,378 @@
+;
+; PROFIL.ASM -- Implement profil()
+;
+; Copyright (c) 1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__PROFIL        =       1
+                INCLUDE EMX.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE PMINT.INC
+                INCLUDE PROFIL.INC
+                INCLUDE ERRORS.INC
+
+                PUBLIC  DO_PROFIL, PROFIL_SUSPEND, PROFIL_RESUME, PROFIL_TICK
+                PUBLIC  PROFIL_COUNT
+
+;
+; I/O port addresses of the MC146818 RTC chip
+;
+RTC_ADDR        =       70H
+RTC_DATA        =       71H
+
+
+SV_DATA         SEGMENT
+;
+; Number of processes being profiled.  We don't need the RTC interrupt
+; if the number is zero.
+;
+PROFIL_COUNT    DW      0
+
+;
+; The following two variables attempt to avoid lossage when using
+; the kernel debugge on the profiling code.
+;
+PROFIL_SUSPENDED DB     FALSE
+PROFIL_RESUMED  DB      FALSE
+
+;
+; The original values of registers 0A and 0B of the RTC chip.
+;
+OLD_RTC_REG0A   DB      ?
+OLD_RTC_REG0B   DB      ?
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; profil()
+;
+; In:  ES:ESI   Pointer to PROFIL structure
+;      DI       Pointer to process table entry
+;
+; Out: EAX      errno
+;
+                TALIGN  4
+                ASSUME  ESI:NEAR32 PTR PROFIL
+                ASSUME  DI:PTR PROCESS
+                ASSUME  DS:SV_DATA
+DO_PROFIL       PROC    NEAR
+                CMP     ES:[ESI].PRF_CB, SIZE PROFIL
+                JNE     SHORT PROFIL_EINVAL
+;
+; Turn off profiling if scale <= 2 or bufsiz = 0
+;
+                CMP     ES:[ESI].PRF_SCALE, 1
+                JBE     SHORT PROFIL_OFF
+                CMP     ES:[ESI].PRF_BUFSIZ, 0
+                JE      SHORT PROFIL_OFF
+;
+; Copy the values into the process table
+;
+                MOV     EAX, ES:[ESI].PRF_BUFF
+                MOV     [DI].P_PRF_BUFF, EAX
+                MOV     EAX, ES:[ESI].PRF_BUFSIZ
+                AND     EAX, NOT 3
+                MOV     [DI].P_PRF_BUFSIZ, EAX
+                MOV     EAX, ES:[ESI].PRF_OFFSET
+                MOV     [DI].P_PRF_OFFSET, EAX
+                MOV     EAX, ES:[ESI].PRF_SCALE
+                MOV     [DI].P_PRF_SCALE, EAX
+;
+; Start profiling
+;
+                CALL    PROFIL_START
+                JC      SHORT PROFIL_EINVAL
+                XOR     EAX, EAX
+                RET
+
+;
+; Stop profiling
+;
+                TALIGN  4
+PROFIL_OFF:     XOR     EAX, EAX
+                XCHG    EAX, [DI].P_PRF_SCALE
+                TEST    EAX, EAX
+                JZ      SHORT PROFIL_OK
+                CALL    PROFIL_STOP
+PROFIL_OK:      XOR     EAX, EAX
+                RET
+
+PROFIL_EINVAL:  MOV     EAX, EINVAL
+                RET
+DO_PROFIL       ENDP
+
+                ASSUME  ESI:NOTHING
+                ASSUME  DI:NOTHING
+
+;
+; Start profiling one process
+;
+; Out:  CY      Error
+;
+                ASSUME  DS:SV_DATA
+PROFIL_START    PROC    NEAR
+                INC     PROFIL_COUNT
+                CMP     PROFIL_COUNT, 1
+                JNE     SHORT DONE
+                CLI
+                CALL    PROFIL_RESUME
+                JNC     SHORT OK
+                MOV     PROFIL_COUNT, 0
+OK:             STI
+DONE:           RET
+PROFIL_START    ENDP
+
+;
+; Stop profiling one process
+;
+                ASSUME  DS:SV_DATA
+PROFIL_STOP     PROC    NEAR
+                CMP     PROFIL_COUNT, 0
+                JE      SHORT DONE
+                DEC     PROFIL_COUNT
+                JNZ     SHORT DONE
+                CLI
+                CALL    PROFIL_SUSPEND
+                STI
+DONE:           RET
+PROFIL_STOP     ENDP
+
+;
+; Timer tick for profiler, called by PMINT for IRQ8 if PROFIL_COUNT
+; is non-zero
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+PROFIL_TICK     PROC    NEAR
+                MOV     AL, 0CH                 ; Read status register
+                CALL    RTC_READ
+                TEST    AL, 40H                 ; Periodic interrupt pending?
+                JZ      SHORT DONE              ; No  -> done
+                CMP     I_CS, L_CODE_SEL        ; Profile user code only
+                JNE     SHORT DONE
+                MOV     BX, PROCESS_PTR
+                CMP     BX, NO_PROCESS          ; User process active?
+                JE      SHORT DONE              ; No  -> done
+                ASSUME  BX:PTR PROCESS
+                CMP     [BX].P_PRF_SCALE, 0     ; Profiling that process?
+                JE      SHORT DONE              ; No  -> done
+                MOV     EAX, I_EIP              ; Compute counter offset
+                SUB     EAX, [BX].P_PRF_OFFSET
+                JC      SHORT DONE
+                MUL     [BX].P_PRF_SCALE
+                SHRD    EAX, EDX, 16
+                AND     EAX, NOT 3
+                CMP     EAX, [BX].P_PRF_BUFSIZ  ; Within buffer?
+                JAE     SHORT DONE              ; No  -> done
+                MOV     EDX, [BX].P_PRF_BUFF
+                MOV     CX, L_DATA_SEL
+                MOV     ES, CX
+                INC     DWORD PTR ES:[EDX+EAX]  ; Increment counter
+DONE:           MOV     AL, 20H                 ; EOI
+                OUT     0A0H, AL                ; Slave PIC
+                OUT     20H, AL                 ; Master PIC
+                RET
+PROFIL_TICK     ENDP
+                ASSUME  BP:NOTHING
+                ASSUME  BX:NOTHING
+
+
+;
+; Suspend generating profiler interrupts.
+;
+; This should be done before executing real-mode-code.  Call with
+; interrupts disabled!
+;
+; Important: PROFIL_RESUME must have been called at least once!
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+PROFIL_SUSPEND  PROC    NEAR
+                MOV     PROFIL_RESUMED, FALSE
+                CMP     PROFIL_SUSPENDED, FALSE
+                JNE     SHORT DONE
+                MOV     PROFIL_SUSPENDED, NOT FALSE
+;
+; Disable the RTC interrupt (IRQ8) in the slave interrupt controller
+;
+                IN      AL, 0A1H
+                OR      AL, 01H
+                CALL    IO_DELAY
+                OUT     0A1H, AL
+;
+; Stop the RTC from generating interrupts
+;
+                MOV     AL, 0BH
+                MOV     AH, OLD_RTC_REG0B
+                CALL    RTC_WRITE
+;
+; Restore the original interrupt rate
+;
+                MOV     AL, 0AH
+                MOV     AH, OLD_RTC_REG0A
+                CALL    RTC_WRITE
+                CALL    IO_DELAY
+                CALL    RTC_CLEAN
+DONE:           RET
+PROFIL_SUSPEND  ENDP
+
+
+;
+; Resume generating profiler interrupts.
+;
+; This should be done after executing real-mode-code.  Call with
+; interrupts disabled!
+;
+; Out:  CY      Cannot enable profiler interrupts
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+PROFIL_RESUME   PROC    NEAR
+                MOV     PROFIL_SUSPENDED, FALSE
+                CMP     PROFIL_RESUMED, FALSE
+                JNE     SHORT DONE
+                MOV     PROFIL_RESUMED, NOT FALSE
+;
+; Read and save the current values of RTC registers 0A and 0B
+;
+                MOV     AL, 0AH
+                CALL    RTC_READ
+                MOV     OLD_RTC_REG0A, AL
+
+                MOV     AL, 0BH
+                CALL    RTC_READ
+                MOV     OLD_RTC_REG0B, AL
+;
+; Don't profile if RTC interrupts are used by someone else
+; or if square-wave output is enabled
+;
+                TEST    AL, 78H
+                JNZ     SHORT FAIL
+;
+; Set the interrupt rate to 1024Hz
+;
+                MOV     AH, OLD_RTC_REG0A
+                AND     AH, 0F0H
+                OR      AH, 06H
+                MOV     AL, 0AH
+                CALL    RTC_WRITE
+;
+; Enable the RTC's periodic interrupt
+;
+                MOV     AH, OLD_RTC_REG0B
+                OR      AH, 40H                 ; Enable periodic interrupt
+                AND     AH, NOT 30H             ; Disable alarm & update-ended
+                MOV     AL, 0BH                 ; interrupts
+                CALL    RTC_WRITE
+;
+; Clear pending interrupts
+;
+                MOV     AL, 0CH
+                CALL    RTC_READ
+;
+; Enable the RTC interrupt (IRQ8) in the slave interrupt controller
+;
+                IN      AL, 0A1H
+                AND     AL, NOT 01H
+                CALL    IO_DELAY
+                OUT     0A1H, AL
+DONE:           CLC
+                RET
+
+FAIL:           CALL    RTC_CLEAN
+                STC
+                RET
+PROFIL_RESUME   ENDP
+
+
+;
+; Read an RTC register
+;
+; In:   AL      Register number
+;
+; Out:  AL      Register contents
+;
+; Note: This routine enables NMIs
+;       Call with interrupts disabled!
+;
+        TALIGN  4
+RTC_READ PROC   NEAR
+        OUT     RTC_ADDR, AL
+        CALL    IO_DELAY
+        IN      AL, RTC_DATA
+        RET
+RTC_READ ENDP
+
+;
+; Write an RTC register
+;
+; In:   AL      Register number
+;       AH      Value
+;
+; Note: This routine enables NMIs
+;       Call with interrupts disabled!
+;
+        TALIGN  4
+RTC_WRITE PROC  NEAR
+        OUT     RTC_ADDR, AL
+        CALL    IO_DELAY
+        MOV     AL, AH
+        OUT     RTC_DATA, AL
+        RET
+RTC_WRITE ENDP
+
+;
+; Set the RTC address register to 0CH
+;
+; (BIOS does this after reading or writing a RTC register.)
+;
+; Note: This routine enables NMIs
+;
+        TALIGN  4
+RTC_CLEAN PROC  NEAR
+        MOV     AL, 0CH
+        OUT     RTC_ADDR, AL
+        RET
+RTC_CLEAN ENDP
+
+;
+; Delay between two accesses to I/O ports of the same chip
+;
+                TALIGN  4
+IO_DELAY        PROC    NEAR
+                MOV     CX, 4
+                TALIGN  4
+LOOP1:          DEC     CX
+                JNZ     LOOP1
+                RET
+IO_DELAY        ENDP
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/profil.inc
===================================================================
--- trunk/src/emx/src/dos/profil.inc	(revision 18)
+++ trunk/src/emx/src/dos/profil.inc	(revision 18)
@@ -0,0 +1,53 @@
+;
+; PROFIL.INC -- Implement profil()
+;
+; Copyright (c) 1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; Cf. struct _profil in <sys/emx.h>
+;
+PROFIL          STRUC
+PRF_CB          DWORD   ?               ; Size of structure
+PRF_BUFF        DWORD   ?               ; Pointer to buffer
+PRF_BUFSIZ      DWORD   ?               ; Size of buffer
+PRF_OFFSET      DWORD   ?               ; Start address
+PRF_SCALE       DWORD   ?               ; Scaling factor
+PROFIL          ENDS
+
+              IFNDEF __PROFIL
+
+SV_DATA         SEGMENT
+                EXTRN   PROFIL_COUNT:WORD
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                EXTRN   PROFIL_STOP:NEAR
+                EXTRN   PROFIL_SUSPEND:NEAR
+                EXTRN   PROFIL_RESUME:NEAR
+                EXTRN   PROFIL_TICK:NEAR
+                EXTRN   DO_PROFIL:NEAR
+
+SV_CODE         ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/ptrace.asm
===================================================================
--- trunk/src/emx/src/dos/ptrace.asm	(revision 18)
+++ trunk/src/emx/src/dos/ptrace.asm	(revision 18)
@@ -0,0 +1,424 @@
+;
+; PTRACE.ASM -- Implement ptrace()
+;
+; Copyright (c) 1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE PMINT.INC
+                INCLUDE DEBUG.INC
+                INCLUDE HEADERS.INC
+                INCLUDE ERRORS.INC
+
+SV_DATA         SEGMENT
+
+                TALIGN  2
+POKE_VALUE      DD      ?
+
+REG_TABLE       STRUCT
+RT_ADDR         DD      ?
+RT_PROC         DW      ?
+RT_LEN          DB      ?
+REG_TABLE       ENDS
+
+PTRACE_REGS     REG_TABLE       <USER_AREA.U_GS,   PROCESS.P_GS,     2>
+                REG_TABLE       <USER_AREA.U_FS,   PROCESS.P_FS,     2>
+                REG_TABLE       <USER_AREA.U_ES,   PROCESS.P_ES,     2>
+                REG_TABLE       <USER_AREA.U_DS,   PROCESS.P_DS,     2>
+                REG_TABLE       <USER_AREA.U_EDI,  PROCESS.P_EDI,    4>
+                REG_TABLE       <USER_AREA.U_ESI,  PROCESS.P_ESI,    4>
+                REG_TABLE       <USER_AREA.U_EBP,  PROCESS.P_EBP,    4>
+                REG_TABLE       <USER_AREA.U_ESP,  PROCESS.P_ESP,    4>
+                REG_TABLE       <USER_AREA.U_EBX,  PROCESS.P_EBX,    4>
+                REG_TABLE       <USER_AREA.U_EDX,  PROCESS.P_EDX,    4>
+                REG_TABLE       <USER_AREA.U_ECX,  PROCESS.P_ECX,    4>
+                REG_TABLE       <USER_AREA.U_EAX,  PROCESS.P_EAX,    4>
+                REG_TABLE       <USER_AREA.U_EIP,  PROCESS.P_EIP,    4>
+                REG_TABLE       <USER_AREA.U_CS,   PROCESS.P_CS,     2>
+                REG_TABLE       <USER_AREA.U_EFL,  PROCESS.P_EFLAGS, 4>
+                REG_TABLE       <USER_AREA.U_UESP, PROCESS.P_ESP,    4>
+                REG_TABLE       <USER_AREA.U_SS,   PROCESS.P_SS,     2>
+                REG_TABLE       <-1, 0, 0>
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+                PUBLIC  PTRACE
+
+                TALIGN  2
+PTRACE_JMP      DW      PTRACE00                ; PTRACE_TRACEME
+                DW      PTRACE01                ; PTRACE_PEEKTEXT
+                DW      PTRACE02                ; PTRACE_PEEKDATA
+                DW      PTRACE03                ; PTRACE_PEEKUSER
+                DW      PTRACE04                ; PTRACE_POKETEXT
+                DW      PTRACE05                ; PTRACE_POKEDATA
+                DW      PTRACE06                ; PTRACE_POKEUSER
+                DW      PTRACE07                ; PTRACE_RESUME
+                DW      PTRACE08                ; PTRACE_EXIT
+                DW      PTRACE09                ; PTRACE_STEP
+                DW      PTRACE0A                ; PTRACE_SESSION
+PTRACE_LAST     =       ($-PTRACE_JMP)/2-1
+
+;
+; Bits in EFLAGS that may be changed by ptrace()
+;
+EFLAGS_USER     =       0000110011010101B       ; OF, DF, SF, ZF, AF, PF, CF
+
+; ----------------------------------------------------------------------------
+; AX=7F08H: ptrace()
+;
+; Debugging support
+;
+; In:   EBX     request code (see /emx/include/sys/ptrace.h)
+;       EDI     pid
+;       EDX     address
+;       ECX     data
+;
+; Out:  EAX     result
+;       ECX     errno, if non-zero
+;
+; ----------------------------------------------------------------------------
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+
+                TALIGN  4
+PTRACE:         MOV     ECX, I_ECX              ; ECX := data
+                MOV     I_ECX, 0                ; No error
+                MOV     EDI, I_EBX
+                CMP     EDI, 0                  ; PTRACE_TRACEME?
+                JE      SHORT SYS08_JMP         ; Yes -> ignore pid
+                CMP     EDI, PTRACE_LAST        ; Valid request code?
+                JA      SHORT SYS08_IO_ERR      ; No  -> I/O error
+                MOV     EAX, I_EDI              ; Get process ID
+                CALL    FIND_PROCESS            ; Lookup process table entry
+                CMP     BX, NO_PROCESS          ; Found?
+                JE      SHORT SYS08_ESRCH       ; No -> no such process
+                ASSUME  BX:PTR PROCESS
+                TEST    [BX].P_FLAGS, PF_DEBUG  ; Process in debugging mode?
+                JZ      SHORT SYS08_IO_ERR      ; No -> I/O error
+SYS08_JMP:      MOV     ESI, I_EDX              ; ESI := Address
+                JMP     PTRACE_JMP[EDI*2]       ; Dispatch
+
+SYS08_ESRCH:    MOV     I_ECX, ESRCH            ; No such process
+                JMP     SHORT SYS08_ERROR       ; Failure
+
+SYS08_EINVAL:   MOV     I_ECX, EINVAL           ; Invalid argument
+                JMP     SHORT SYS08_ERROR       ; Failure
+
+SYS08_IO_ERR:   MOV     I_ECX, EIO              ; I/O error
+SYS08_ERROR:    MOV     I_EAX, -1               ; Failure
+                RET
+
+
+;
+; Request code 0 is used (by Unix) to switch the current process to debugging
+; mode. This is not used by emx. Ignored.
+;
+PTRACE00:       MOV     I_EAX, 0
+                RET
+
+;
+; Request code 10 is used to switch to and from the child session. Only
+; for OS/2.
+;
+PTRACE0A:       MOV     I_EAX, 0
+                RET
+
+
+;
+; Request codes 1 and 2 are used for reading a word from code/data space.
+;
+PTRACE01:                                       ; Same as PTRACE02
+PTRACE02:       CALL    PTRACE_ADDR             ; Check address
+                .386P
+                SLDT    DI                      ; Save LDT
+                LLDT    [BX].P_LDT              ; Get LDT of child process
+                MOV     ES, [BX].P_DS
+                MOV     EAX, ES:[ESI]           ; Read the word
+                LLDT    DI                      ; Note 2
+                MOV     I_EAX, EAX              ; and return it in EAX
+                RET
+                .386
+;
+; Note 2: It is essential, that the LDT of the client process is active
+;         until after accessing the memory of the client process.
+;         Why is this necessary, the 386 uses the LDT only when loading
+;         a segment register; the LDT isn't referenced after loading
+;         the segment register? Correct. But accessing the memory of
+;         the child could cause a page fault (or an interrupt may occur
+;         between restoring the LDTR and accessing memory). The exception
+;         (or interrupt) handler saves all the segment registers (and the
+;         LDTR). When returning to the interrupted code, the segment registers
+;         are restored using the LDTR saved on entry to the interrupt routine.
+;         Therefore, one must be very cautious when switching LDTs!
+;
+
+;
+; Request code 3 is used for reading from the process table (registers).
+;
+                TALIGN  2
+PTRACE03:       MOV     EAX, ESI
+                CMP     EAX, USER_AREA.U_AR0    ; Pointer to registers?
+                JE      SHORT PEEKU_AR0         ; Yes -> special handling
+                CMP     EAX, USER_AREA.U_FPVALID  ; Floating point flag?
+                JE      SHORT PEEKU_FPVALID     ; Yes -> special handling
+                CMP     EAX, USER_AREA.U_FPSTATUS ; Floating point status?
+                JE      SHORT PEEKU_FPSTATUS      ; Yes -> special handling
+                CMP     EAX, USER_AREA.U_FPSTATE  ; Floating point?
+                JB      SHORT PEEKU_10
+                CMP     EAX, USER_AREA.U_FPSTATE + 108 - 4
+                JBE     SHORT PEEKU_FLOAT       ; Yes -> special handling
+PEEKU_10:       CALL    USER_ADDR               ; Convert address
+                JNZ     SYS08_IO_ERR
+                ASSUME  SI:PTR REG_TABLE
+                MOVZX   CX, [SI].RT_LEN         ; Get size of register (bytes)
+                MOV     SI, [SI].RT_PROC        ; Pointer in process structure
+PEEKU_11:       ADD     SI, BX
+                MOV     I_EAX, 0                ; Clear return value
+                LEA     DI, I_EAX
+PEEKU_12:       LODS    BYTE PTR DS:[SI]
+                MOV     SS:[DI], AL
+                INC     DI
+                LOOP    PEEKU_12
+                ASSUME  SI:NOTHING
+                RET
+
+;
+; A MASM bug strikes here if DWORD PTR isn't used: MASM omits the operand
+; size prefix and inserts 4 bytes of immediate data.
+;
+PEEKU_AR0:      MOV     I_EAX, DWORD PTR (USER_AREA.U_REGS + KERNEL_U_ADDR)
+                RET
+
+PEEKU_FPSTATUS: MOV     I_EAX, 0
+                RET
+
+PEEKU_FPVALID:
+              IF FLOATING_POINT
+                MOV     I_EAX, 0FFH
+              ELSE
+                MOV     I_EAX, 0
+              ENDIF
+                RET
+
+PEEKU_FLOAT:
+              IF FLOATING_POINT
+                FNOP                            ; Save 387 registers
+                ADD     ESI, PROCESS.P_CW - USER_AREA.U_FPSTATE
+                MOV     CX, 4
+                JMP     SHORT PEEKU_11
+              ELSE
+                JMP     SYS08_IO_ERR
+              ENDIF
+
+;
+; Request code 6 is used for writing to the process table (registers).
+;
+; Note: Only some bits of EFLAG can be written. Segment registers and
+;       387 registers cannot be written.
+;
+                TALIGN  2
+PTRACE06:       MOV     POKE_VALUE, ECX
+                MOV     EAX, ESI
+                CALL    USER_ADDR               ; Convert address
+                JNZ     SYS08_IO_ERR
+                ASSUME  SI:PTR REG_TABLE
+                MOVZX   CX, [SI].RT_LEN
+                MOV     DI, [SI].RT_PROC
+                CMP     DI, PROCESS.P_EFLAGS
+                JNE     SHORT POKEU_10
+                ADD     DI, BX
+                MOV     EAX, [DI]
+                MOV     ECX, POKE_VALUE
+                AND     ECX, EFLAGS_USER        ; Keep only changable bits
+                AND     EAX, NOT EFLAGS_USER    ; Keep only unchangabe bits
+                OR      EAX, ECX                ; Insert new bits
+                MOV     [DI], EAX
+                JMP     SHORT POKEU_ZERO
+
+                ASSUME  SI:NOTHING
+
+POKEU_10:       ADD     DI, BX
+                LEA     SI, POKE_VALUE
+                MOV_ES_DS
+                REP     MOVSB
+POKEU_ZERO:     MOV     I_EAX, 0                ; Return 0
+                RET
+
+;
+; Request codes 4 and 5 are used for writing a word to code/data space.
+;
+PTRACE04:                                       ; Same as PTRACE05
+PTRACE05:
+                CALL    PTRACE_ADDR             ; Check address
+                .386P
+                SLDT    DI                      ; Save LDT
+                LLDT    [BX].P_LDT              ; Get LDT of child process
+                MOV     ES, [BX].P_DS
+                MOV     ES:[ESI], ECX           ; Write the word
+                LLDT    DI                      ; Note 2
+                MOV     I_EAX, ECX              ; and return it
+                RET
+                .386
+
+;
+; Request code 8 is used for terminating a process.
+;
+PTRACE08:       CALL    REMOVE_PROCESS          ; Kill child process
+                RET
+
+;
+; Request code 9 is used for single stepping a process.
+;
+; Note: ECX (data) is passed to PTRACE_SWITCH
+;
+PTRACE09:       CALL    PTRACE_SWITCH           ; Switch to child process
+                JC      SYS08_EINVAL            ; Error ->
+                CALL    DEBUG_STEP              ; Set EFLAGS for stepping
+                RET
+
+
+;
+; Request code 7 is used for resuming a process.
+;
+; Note: ECX (data) is passed to PTRACE_SWITCH
+;
+PTRACE07:       CALL    PTRACE_SWITCH           ; Switch to child process
+                JC      SYS08_EINVAL            ; Error ->
+                CALL    DEBUG_RESUME            ; Set EFLAGS for resuming
+                CALL    BREAK_AFTER_IRET        ; For debugging debuggers
+                RET
+
+                ASSUME  BX:NOTHING
+
+;
+; Switch to the program being debugged.
+;
+; In:   BX      Pointer to process table entry of child process
+;       ECX     4th argument (DATA) of ptrace(): signal number
+;       SS:BP   Interrupt stack frame
+;
+; Out:  CY      Error (invalid signal number)
+;
+                ASSUME  BX:PTR PROCESS
+PTRACE_SWITCH   PROC    NEAR
+                MOV     [BX].P_SIG_PENDING, 0   ; Cancel pending signals
+                JECXZ   NOSIG                   ; No signal -> skip
+                CMP     ECX, SIGNALS            ; Valid signal number?
+                JAE     SHORT FAIL              ; No  -> failure
+                CMP     SIG_VALID[EAX], FALSE
+                JE      SHORT FAIL              ; No  -> failure
+                BTS     [BX].P_SIG_PENDING, ECX ; Generate signal
+NOSIG:          PUSH    BX                      ; Child process table entry
+                MOV     BX, PROCESS_PTR
+                MOV     (PROCESS PTR [BX]).P_STATUS, PS_WAIT_PTRACE
+                CALL    SAVE_PROCESS            ; Save current process
+                POP     BX
+                MOV     PROCESS_PTR, BX         ; Switch to child process
+                MOV     PROCESS_SIG, BX
+                CALL    REST_PROCESS
+                CLC                             ; No error
+                RET
+
+FAIL:           STC                             ; Error
+                RET
+PTRACE_SWITCH   ENDP
+                ASSUME  BX:NOTHING
+
+;
+; Check address
+;
+; In:   DS:BX   Pointer to process table entry
+;       ESI     Address
+;
+                ASSUME  BX:PTR PROCESS
+PTRACE_ADDR     PROC    NEAR
+                PUSH    EAX
+                PUSH    EDX
+                MOV     EAX, ESI
+                ADD     EAX, 3                  ; Last byte of word
+                JC      SHORT PTRACE_ADDR_ERR   ; Beyond end -> error
+;
+; Try code area: [BX].P_CODE_OFF ... [BX].P_CODE_OFF + [BX].P_CODE_SIZE - 1
+;
+                MOV     EDX, [BX].P_TEXT_OFF
+                CMP     ESI, EDX
+                JB      SHORT PTRACE_ADDR_1     ; Not in code area ->
+                ADD     EDX, [BX].P_TEXT_SIZE
+                CMP     EAX, EDX
+                JBE     SHORT PTRACE_ADDR_OK    ; In code area ->
+;
+; Try data area: [BX].P_DATA_OFF ... [BX].P_BRK - 1
+;
+PTRACE_ADDR_1:  CMP     ESI, [BX].P_DATA_OFF
+                JB      SHORT PTRACE_ADDR_2     ; Not in data area ->
+                CMP     EAX, [BX].P_BRK
+                JB      SHORT PTRACE_ADDR_OK    ; In data area ->
+;
+; Try stack: [BX].P_STACK_ADDR - [BX].P_STACK_SIZE ... [BX].P_STACK_ADDR - 1
+;
+PTRACE_ADDR_2:  MOV     EDX, [BX].P_STACK_ADDR
+                CMP     EAX, EDX
+                JAE     SHORT PTRACE_ADDR_3     ; Not in stack ->
+                SUB     EDX, [BX].P_STACK_SIZE
+                CMP     ESI, EDX
+                JAE     SHORT PTRACE_ADDR_OK
+PTRACE_ADDR_3:
+PTRACE_ADDR_ERR:POP     EDX                     ; Restore registers
+                POP     EAX
+                ADD     SP, 2                   ; Remove return address
+                JMP     SYS08_IO_ERR
+
+PTRACE_ADDR_OK: POP     EDX
+                POP     EAX
+                RET
+                ASSUME  BX:NOTHING
+PTRACE_ADDR     ENDP
+
+;
+;
+;
+                TALIGN  2
+USER_ADDR       PROC    NEAR
+                LEA     SI, PTRACE_REGS
+                ASSUME  SI:PTR REG_TABLE
+USER_ADDR_1:    CMP     [SI].RT_ADDR, -1        ; End of table?
+                JE      USER_ADDR_ERR
+                CMP     EAX, [SI].RT_ADDR
+                JE      SHORT USER_ADDR_OK
+                ADD     SI, SIZE REG_TABLE
+                JMP     SHORT USER_ADDR_1
+USER_ADDR_ERR:  CMP     [SI].RT_ADDR, 0         ; Set NZ
+USER_ADDR_OK:   RET
+                ASSUME  SI:NOTHING
+USER_ADDR       ENDP
+
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/rmint.asm
===================================================================
--- trunk/src/emx/src/dos/rmint.asm	(revision 18)
+++ trunk/src/emx/src/dos/rmint.asm	(revision 18)
@@ -0,0 +1,823 @@
+;
+; RMINT.ASM -- Initialize interrupts and handle real-mode interrupts
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE TABLES.INC
+                INCLUDE VCPI.INC
+                INCLUDE PMINT.INC
+                INCLUDE EXCEPT.INC
+                INCLUDE RPRINT.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE OPTIONS.INC
+                INCLUDE MISC.INC
+
+                PUBLIC  INIT_INT, CLEANUP_INT, INIT_TIMER, CLEANUP_TIMER
+                PUBLIC  SET_RM_INT, RESTORE_RM_INT
+
+RM_DEBUGGER     =       FALSE
+
+;
+; The interrupt redirection machinery has four states:
+;
+; - IC_NOT
+;       This is the initial state: interrupt vectors have not been
+;       changed yet.  Do not restore interrupt vectors on exit!
+;
+; - IC_VCPI_SERVER
+;       There is a VCPI server (EMS emulator) which has already reprogrammed
+;       the interrupt controller to redirect hardware interrupts. Or a
+;       different client of the VCPI server has redirected the hardware
+;       interrupts. This is the simple case as we don't have to touch
+;       the interrupt controller.
+;
+; - IC_VCPI_CLIENT
+;       There is a VCPI server (EMS emulator) which hasn't reprogrammed
+;       the interrupt controller. We have to reprogram the interrupt
+;       controller in order to distinguish hardware interrupts from
+;       processor exceptions. PC design flaw...
+;
+; - IC_MYSELF
+;       There is no VCPI server (EMS emulator). We have to reprogram the
+;       interrupt controller in order to distinguish hardware interrupts from
+;       processor exceptions. PC design flaw...
+;
+
+IC_NOT          =       0               ; Interrupt vectors not changed
+IC_VCPI_SERVER  =       1               ; VCPI server has changed vectors
+IC_VCPI_CLIENT  =       2               ; VCPI server hasn't changed vectors
+IC_MYSELF       =       3               ; This program has changed vectors
+
+
+
+SV_DATA         SEGMENT
+
+              IF RM_DEBUGGER
+;
+; The original debug interrupt vectors.
+;
+OLD_RM_INT01_OFF        DW      ?
+OLD_RM_INT01_SEG        DW      ?
+
+OLD_RM_INT03_OFF        DW      ?
+OLD_RM_INT03_SEG        DW      ?
+
+              ENDIF
+
+;
+;
+; The original interrupt vectors IRQ0_BASE .. IRQ0_BASE+7.
+;
+SAVED_IVECS     DD      8 DUP (?)
+
+;
+; Check the interrupt vectors in this table in this sequence for
+; 8 successive unused interrupts vectors. The first entry should
+; be the safest, the last the most dangerous. But all vectors
+; are checked, so that nothing evil should happen if a vector
+; is already in use. The danger is that some other program may
+; change an interrupt vector used by this program for redirecting
+; a hardware interrupt. This would cause a system crash.
+;
+UNUSED_INT_TAB  DB      50H, 88H, 90H, 98H
+                DB      0A8H, 0B8H, 0C0H, 0C8H, 0D0H, 0D8H
+                DB      80H, 0A0H, 0B0H, 0E0H, 0E8H, 38H, 78H, 58H, 0F0H
+                DB      00H
+
+;
+; These are the offsets for the new interrupt vectors used for IRQ0..IRQ7.
+; The code at that address just issues INT 08H .. INT 0FH.
+;
+NEW_IVECS       DW      HWINT0, HWINT1, HWINT2, HWINT3
+                DW      HWINT4, HWINT5, HWINT6, HWINT7
+
+;
+; These are the first interrupt vector used for redirecting IRQ0..IRQ7
+; and IRQ8..IRQ15, respectively.
+;
+IRQ0_BASE       DB      ?
+IRQ8_BASE       DB      ?
+
+;
+; This is the interrupt redirection status.
+;
+INT_CHANGED     DB      IC_NOT
+;
+; This is the future interrupt redirection status.
+;
+NEW_INT_CHANGED DB      IC_NOT
+
+;
+; This message should never be required: The VCPI server (or one of its
+; clients) has changed the interrupt vectors. But that mappings aren't
+; usable.
+;
+$BAD_VCPI       DB      "Unusable interrupt vector mappings set by VCPI server", CR, LF, 0
+
+              IF RM_DEBUGGER
+;
+; There's no real-mode debugger
+;
+$RM_DEBUG       DB      "Real-mode breakpoint at ", 0
+
+              ENDIF
+
+SV_DATA         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; The original timer interrupt vector. This is in the code segment because
+; we need OLD_RM_INT1C for jumping to the next interrupt handler in the
+; chain.
+;
+OLD_RM_INT1C            LABEL   DWORD
+OLD_RM_INT1C_OFF        DW      ?
+OLD_RM_INT1C_SEG        DW      ?
+OLD_RM_INT1C_FLAG       DB      FALSE
+
+
+;
+; Redirect hardware interrupt IRQ X to real-mode interrupt Y
+;
+                ASSUME  DS:NOTHING
+HWINTX          MACRO   X,Y
+                TALIGN  2
+HWINT&X:        INT     Y                       ; Issue software interrupt
+                IRET                            ; Return
+                ENDM
+;
+; Redirect IRQ 0 (-> INT 08H) to IRQ 7 (-> INT 0FH)
+;
+                IRPC    X, <01234567>
+                HWINTX  X, %&X+8
+                ENDM
+
+
+;
+; Access rights for 32-bit interrupt gates
+;
+INT_GATE_0      =       08EH                    ; DPL=0 (hardware interrupt)
+INT_GATE_1      =       0AEH                    ; DPL=1
+INT_GATE_2      =       0CEH                    ; DPL=2
+INT_GATE_3      =       0EEH                    ; DPL=3 (software interrupt)
+
+
+;
+; Initialize IDT, redirect hardware interrupts
+;
+; This procedure is also called after spawning a DOS program
+;
+
+                ASSUME  DS:SV_DATA
+
+                TALIGN  2
+INIT_INT        PROC    NEAR
+                MOV     IRQ0_BASE, 40H
+                MOV     IRQ8_BASE, 48H
+                CMP     MACHINE, MACH_FMR70     ; Fujitsu FMR70?
+                JE      II_TABLE                ; Yes -> use above values
+                MOV     IRQ0_BASE, 40H
+                MOV     IRQ8_BASE, 48H
+                CMP     MACHINE, MACH_PC98      ; NEC PC-98?
+                JE      II_TABLE                ; Yes -> use above values
+                MOV     IRQ8_BASE, 70H          ; The standard configuration
+                MOV     NEW_INT_CHANGED, IC_MYSELF
+                CMP     VCPI_FLAG, FALSE        ; Use VCPI?
+                JE      SHORT II_CHECK_INT      ; No -> redirect interrupts
+                CALL    GET_INT_MAP             ; Get interrupt vector mappings
+                MOV     IRQ0_BASE, BL           ; Controller 1 address
+                MOV     IRQ8_BASE, CL           ; Controller 2 address
+                CMP     BL, 17                  ; Conflict with exceptions?
+                JBE     SHORT II_NEED_REMAP     ; Yes -> remapping required
+                CMP     CL, 17                  ; Conflict with exceptions?
+                JBE     SHORT II_NEED_REMAP     ; Yes -> remapping required
+;
+; Interrupt vector mapping is usable, VCPI server has done this.
+;
+                MOV     NEW_INT_CHANGED, IC_VCPI_SERVER
+                JMP     SHORT II_TABLE          ; VCPI server has done the work
+
+II_NEED_REMAP:  CMP     BL, 08H                 ; Standard configuration?
+                JNE     II_ERROR                ; No  -> almost impossible
+                CMP     CL, 70H                 ; Standard configuration?
+                JNE     II_ERROR                ; No  -> almost impossible
+                MOV     NEW_INT_CHANGED, IC_VCPI_CLIENT
+                JMP     SHORT II_MYSELF
+
+;
+; There may be programs which redirect IRQ0..IRQ7. As we're not
+; running under a VCPI server, we should find this out by hand.
+; Here's how:
+; - save all the interrupt vectors
+; - setup 256 *different* interrupt handlers
+; - set a variable V in the code segment to some number I unequal 0..255
+; - each handler stores its vector number to V if V equals I
+;   (this must be done in an atomic operation) and then jumps to the
+;   original handler for that interrupt vector
+; - the main program loops until V != I or a loop counter expires
+; - restore interrupt vectors
+; - if V == 8, we have the original mapping
+; Actually, we aren't doing all this. It isn't worth the trouble.
+; There's an explicit check for DESQview in VCPI.ASM, instead.
+;
+II_CHECK_INT:
+
+;
+; We have to redirect hardware interrupts. Find 8 sucessive unused
+; interrupt vectors for redirecting IRQ0..IRQ7.
+;
+II_MYSELF:      LEA     SI, UNUSED_INT_TAB      ; Table of vectors to check
+                XOR     AX, AX                  ; AH:=0
+                MOV     ES, AX                  ; Access interrupt table
+II_FIND_1:      LODS    UNUSED_INT_TAB          ; Get interupt vector
+                OR      AL, AL                  ; End of table?
+                JZ      SHORT II_FIND_FAIL      ; Yes -> be brutal
+                MOV     BX, AX                  ; AH=0
+                SHL     BX, 2                   ; Compute address of vector
+                MOV     EDX, ES:[BX]            ; Fetch first vector
+                MOV     CX, 7                   ; Compare to the following 7
+II_FIND_2:      ADD     BX, 4                   ; Next vector
+                CMP     EDX, ES:[BX]            ; Same as first vector?
+                JNE     II_FIND_1               ; No -> try next table entry
+                LOOP    II_FIND_2               ; Repeat for 7 vectors
+                MOV     IRQ0_BASE, AL           ; Use this vector
+                JMP     SHORT II_TABLE          ; Continue
+
+;
+; No unused interrupt vectors found. We don't have mercy and use some
+; interrupt vectors reserved for BASIC. Starting BASIC while this
+; program is running will cause a system crash.
+;
+II_FIND_FAIL:   MOV     IRQ0_BASE, 0D0H
+
+;
+; Initialize all IDT entries.
+;
+II_TABLE:       LEA     DI, IDT+0
+                MOV     CX, 256
+                MOV     AL, INT_GATE_0
+                MOV     DX, OFFSET SV_CODE:INTERRUPT
+II_UNUSED_1:    CALL    SET_INT_GATE
+                ADD     DI, 8
+                LOOP    II_UNUSED_1
+;
+; Put exceptions into IDT.
+;
+; Use interrupt gate instead of trap gate to disable interrupts
+;
+                LEA     SI, EXC_TAB             ; Table of handlers
+II_EXC_1:       LODS    EXC_TAB                 ; Get exception number
+                CMP     AX, 0FFFFH              ; End of table?
+                JE      SHORT II_EXC_3
+                MOV     BX, AX
+                SHL     AX, 3                   ; Compute offset into IDT
+                LEA     DI, IDT
+                ADD     DI, AX                  ; Compute pointer into IDT
+                LODS    EXC_TAB                 ; Get offset of handler
+                MOV     DX, AX
+                MOV     AL, INT_GATE_0          ; Interrupt gate, DPL=0
+                CMP     BL, 3                   ; Breakpoint?
+                JNE     SHORT II_EXC_2          ; No -> use DPL=0
+                MOV     AL, INT_GATE_3          ; Use DPL=3 (for breakpoints)
+II_EXC_2:       CALL    SET_INT_GATE            ; Insert into IDT
+                JMP     SHORT II_EXC_1          ; Repeat for all table entries
+II_EXC_3:
+;
+; Put task gates for exceptions 8 & 10 into IDT.
+;
+                LEA     DI, IDT+8*8
+                MOV     AX, G_TSS_EX8_SEL
+                CALL    SET_TASK_GATE
+                LEA     DI, IDT+10*8
+                MOV     AX, G_TSS_EX10_SEL
+                CALL    SET_TASK_GATE
+;
+; Put hardware interrupts into IDT.
+;
+                LEA     SI, PMINT0_TAB
+                MOVZX   BX, IRQ0_BASE
+                CALL    PUT_HW_INT
+                LEA     SI, PMINT8_TAB
+                MOVZX   BX, IRQ8_BASE
+                CALL    PUT_HW_INT
+;
+; Put software interrupts into IDT.
+;
+                IRP     SWINT, <10H, 11H, 14H, 16H, 17H, 21H, 31H, 33H>
+                LEA     DI, IDT + SWINT*8
+                MOV     DX, OFFSET SV_CODE:PMINT_&SWINT
+                MOV     AL, INT_GATE_3
+                CALL    SET_INT_GATE
+                ENDM
+;
+; Setup debug interrupt
+;
+              IF RM_DEBUGGER
+                LEA     DX, RM_DEBUG
+                MOV     AL, 01H
+                CALL    SET_RM_INT
+                MOV     OLD_RM_INT01_OFF, DX
+                MOV     OLD_RM_INT01_SEG, AX
+                LEA     DX, RM_DEBUG
+                MOV     AL, 03H
+                CALL    SET_RM_INT
+                MOV     OLD_RM_INT03_OFF, DX
+                MOV     OLD_RM_INT03_SEG, AX
+              ENDIF
+;
+; Copy IRQ0_BASE and IRQ8_BASE to IRQ0_ADD and IRQ8_ADD (in the SV_CODE
+; segment), respectively, to make them accessible in the protected-mode
+; interrupt handler without setting any segment register (CS will be set
+; automatically to SV_CODE_SEL).
+;
+                MOV     AX, SV_CODE             ; Used for setting IRQ0_ADD
+                MOV     ES, AX                  ; and IRQ8_ADD
+                ASSUME  ES:SV_CODE
+                MOV     AL, IRQ0_BASE
+                MOV     IRQ0_ADD, AL            ; Set IRQ0_ADD
+                MOV     AL, IRQ8_BASE
+                MOV     IRQ8_ADD, AL            ; Set IRQ8_ADD
+                ASSUME  ES:NOTHING              ; Access to SV_CODE finished
+;
+; Redirect hardware interrupts if required: reprogram interrupt controller 1
+; and notify VCPI server (if present).
+;
+                CLI
+                CMP     NEW_INT_CHANGED, IC_MYSELF
+                JNE     SHORT II_REDIR_1
+                CALL    REDIR_INT_VEC
+                MOV     CL, IRQ0_BASE
+                CALL    SET_HW_INT_BASE
+                JMP     SHORT II_REDIR_END
+
+II_REDIR_1:     CMP     NEW_INT_CHANGED, IC_VCPI_CLIENT
+                JNE     SHORT II_REDIR_END
+                CALL    REDIR_INT_VEC
+                MOV     CL, IRQ0_BASE
+                CALL    SET_HW_INT_BASE
+                MOVZX   BX, IRQ0_BASE
+                MOVZX   CX, IRQ8_BASE           ; This is always 70H
+                CALL    SET_INT_MAP             ; Inform VCPI server
+;
+; Now we can copy NEW_INT_CHANGED to INT_CHANGED.
+;
+II_REDIR_END:   MOV     AL, NEW_INT_CHANGED
+                MOV     INT_CHANGED, AL
+                RET
+
+;
+; We cannot cooperate with a buggy VCPI server; give up.
+;
+II_ERROR:       LEA     DX, $BAD_VCPI
+                CALL    RTEXT
+                MOV     AL, 0FFH
+                JMP     EXIT
+
+INIT_INT        ENDP
+
+;
+; Put hardware interrupts into IDT
+;
+; In:   BX      First interrupt number
+;       DS:SI   Table of vectors
+;
+                ASSUME  DS:SV_DATA
+PUT_HW_INT      PROC    NEAR
+                SHL     BX, 3
+                LEA     DI, IDT[BX]
+                MOV     CX, 8
+PHI_1:          LODS    PMINT0_TAB              ; ...or PMINT8_TAB
+                MOV     DX, AX
+                MOV     AL, INT_GATE_0          ; Not accessible from ring 3
+                CALL    SET_INT_GATE
+                ADD     DI, 8
+                LOOP    PHI_1
+                RET
+PUT_HW_INT      ENDP
+
+;
+; Put interrupt gate (disables interrupts) into IDT
+;
+; In:   DS:DI   Pointer to IDT entry
+;       DX      Offset of interrupt routine (SV_CODE:DX)
+;       AL      INT_GATE_0 ... INT_GATE_3
+;
+                ASSUME  DS:NOTHING
+
+SET_INT_GATE    PROC    NEAR
+                MOV     WORD PTR [DI+0], DX
+                MOV     WORD PTR [DI+2], G_SV_CODE_SEL
+                MOV     BYTE PTR [DI+4], 0
+                MOV     BYTE PTR [DI+5], AL
+                MOV     WORD PTR [DI+6], 0
+                RET
+SET_INT_GATE    ENDP
+
+
+;
+; Put task gate into IDT
+;
+; In:   DS:DI   Pointer to IDT entry
+;       AX      TSS selector
+;
+                ASSUME  DS:NOTHING
+SET_TASK_GATE   PROC    NEAR
+                MOV     WORD PTR [DI+0], 0
+                MOV     WORD PTR [DI+2], AX
+                MOV     BYTE PTR [DI+4], 0
+                MOV     BYTE PTR [DI+5], 85H
+                MOV     WORD PTR [DI+6], 0
+                RET
+SET_TASK_GATE   ENDP
+
+
+;
+; Setup real-mode interrupt vectors for redirecting IRQ0..IRQ7.
+;
+                ASSUME  DS:SV_DATA
+REDIR_INT_VEC   PROC    NEAR
+                XOR     AX, AX
+                MOV     ES, AX
+                LEA     SI, NEW_IVECS
+                LEA     DI, SAVED_IVECS
+                MOV     CX, 8
+                MOVZX   BX, IRQ0_BASE
+                SHL     BX, 2
+II_41:          MOV     AX, ES:[BX+0]
+                MOV     [DI+0], AX
+                MOV     AX, ES:[BX+2]
+                MOV     [DI+2], AX
+                MOV     AX, [SI]
+                MOV     ES:[BX+0], AX
+                MOV     ES:[BX+2], CS
+                ADD     BX, 4
+                ADD     DI, 4
+                ADD     SI, 2
+                LOOP    II_41
+                RET
+REDIR_INT_VEC   ENDP
+
+;
+; Restore interrupt vectors
+;
+                ASSUME  DS:SV_DATA
+RESTORE_INT_VEC PROC    NEAR
+                XOR     AX, AX
+                MOV     ES, AX
+                MOVZX   DI, IRQ0_BASE
+                SHL     DI, 2
+                LEA     SI, SAVED_IVECS
+                MOV     CX, 8
+                CLD
+                REP     MOVSD
+                RET
+RESTORE_INT_VEC ENDP
+
+;
+; Delay for accessing interrupt controller registers
+;
+IO_DELAY        MACRO
+                LOCAL   SKIP
+                JMP     SHORT SKIP
+SKIP:
+                ENDM
+
+
+;
+; Reprogram interrupt controller #1
+;
+; In:   CL      Interrupt base
+;
+                ASSUME  DS:SV_DATA
+SET_HW_INT_BASE PROC    NEAR
+                IN      AL, 21H         ; Read IMR
+                MOV     AH, AL          ; Save old IMR
+                CMP     MACHINE, MACH_INBOARD   ; Inboard 386/PC
+                JE      SHORT SET_HIB_INB
+                MOV     AL, 11H         ; ICW1
+                OUT     20H, AL
+                IO_DELAY
+                MOV     AL, CL          ; ICW2
+                OUT     21H, AL
+                IO_DELAY
+                MOV     AL, 04H         ; ICW3
+                OUT     21H, AL
+                IO_DELAY
+                MOV     AL, 01H         ; ICW4
+                OUT     21H, AL
+                IO_DELAY
+SET_HIB_END:    MOV     AL, AH
+                OUT     21H, AL         ; Write IMR
+                RET
+
+;
+; Use the values of the original PC for the Inboard 386/PC
+;
+SET_HIB_INB:    MOV     AL, 13H         ; ICW1
+                OUT     20H,AL
+                IO_DELAY
+                MOV     AL, CL          ; ICW2
+                OUT     21H,AL
+                IO_DELAY
+                MOV     AL, 09H         ; ICW4
+                OUT     21H, AL
+                JMP     SHORT SET_HIB_END
+
+SET_HW_INT_BASE ENDP
+
+
+;
+; Install real-mode interrupt handler
+;
+; In:   AL      Interrupt number
+;       DX      Offset of interrupt handler (CS=INIT_CODE)
+;
+; Out:  AX      Segment of original interrupt handler
+;       DX      Offset of original interrupt handler
+;
+                ASSUME  DS:NOTHING
+SET_RM_INT      PROC    NEAR
+                PUSH    DS
+                PUSH    ES
+                PUSH    BX
+                MOV     AH, 35H
+                INT     21H
+                PUSH    CS
+                POP     DS
+                PUSH    BX
+                PUSH    ES
+                MOV     AH, 25H
+                INT     21H
+                POP     AX
+                POP     DX
+                POP     BX
+                POP     ES
+                POP     DS
+                RET
+SET_RM_INT      ENDP
+
+;
+; Restore real-mode interrupt vector
+;
+; This is done only if the interrupt vector still points into INIT_CODE
+; (avoid restoring the vector if it has been hooked by somebody else)
+;
+; In:   AL      Interrupt number
+;       DX      Original offset
+;       BX      Original segment
+;
+                ASSUME  DS:NOTHING
+RESTORE_RM_INT  PROC    NEAR
+                PUSH    ES
+                PUSH    BX
+                MOV     AH, 35H
+                INT     21H
+                MOV     BX, ES
+                CMP     BX, INIT_CODE
+                POP     BX
+                POP     ES
+                JNE     SHORT RRI_RET
+                PUSH    DS
+                MOV     DS, BX
+                MOV     AH, 25H
+                INT     21H
+                POP     DS
+RRI_RET:        RET
+RESTORE_RM_INT  ENDP
+
+
+;
+; Restore interrupts
+;
+; This procedure is also called before spawning a DOS program
+;
+                ASSUME  DS:SV_DATA
+CLEANUP_INT     PROC    NEAR
+                CMP     INT_CHANGED, IC_NOT     ; Interrupt vectors remapped?
+                JE      SHORT CI_9              ; No  -> skip
+                CLI                             ; Interrupts must be disabled
+                CMP     INT_CHANGED, IC_MYSELF  ; Done without VCPI?
+                JNE     SHORT CI_1              ; No  -> try next case
+                CALL    RESTORE_INT_VEC         ; Restore interrupt vectors
+                MOV     CL, 8                   ; Restore interrupt controller
+                CALL    SET_HW_INT_BASE
+                JMP     SHORT CI_8              ; Done
+
+CI_1:           CMP     INT_CHANGED, IC_VCPI_CLIENT     ; Done with VCPI?
+                JNE     SHORT CI_8              ; No  -> skip
+                CALL    RESTORE_INT_VEC         ; Restore interrupt vectors
+                MOV     CL, 8                   ; Restore interrupt controller
+                CALL    SET_HW_INT_BASE
+                MOV     BX, 8                   ; Tell VCPI server about change
+                MOV     CX, 70H
+                CALL    SET_INT_MAP
+
+CI_8:           MOV     INT_CHANGED, IC_NOT     ; Back at original state
+                STI                             ; Interrupts allowed again
+CI_9:         IF RM_DEBUGGER
+                MOV     DX, OLD_RM_INT01_OFF
+                MOV     BX, OLD_RM_INT01_SEG
+                MOV     AL, 01H
+                CALL    RESTORE_RM_INT
+                MOV     DX, OLD_RM_INT03_OFF
+                MOV     BX, OLD_RM_INT03_SEG
+                MOV     AL, 03H
+                CALL    RESTORE_RM_INT
+              ENDIF
+                RET
+
+CLEANUP_INT     ENDP
+
+
+;
+; Initialize timer interrupt
+;
+; This procedure is not called after spawning a DOS program
+;
+
+                ASSUME  DS:SV_DATA
+                TALIGN  2
+INIT_TIMER      PROC    NEAR
+                CMP     MACHINE, MACH_PC98      ; NEC PC-98?
+                JE      SHORT IT_DONE           ; Yes -> don't set INT 1CH
+                LEA     DX, RM_TIMER
+                MOV     AL, 1CH
+                CALL    SET_RM_INT
+                MOV     OLD_RM_INT1C_FLAG, NOT FALSE
+                MOV     OLD_RM_INT1C_OFF, DX
+                MOV     OLD_RM_INT1C_SEG, AX
+IT_DONE:        RET
+INIT_TIMER      ENDP
+
+;
+; Restore timer interrupt
+;
+; This procedure is not called before spawning a DOS program
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  2
+CLEANUP_TIMER   PROC    NEAR
+                CMP     OLD_RM_INT1C_FLAG, FALSE
+                JE      SHORT CT_DONE
+                MOV     OLD_RM_INT1C_FLAG, FALSE
+                MOV     DX, OLD_RM_INT1C_OFF
+                MOV     BX, OLD_RM_INT1C_SEG
+                MOV     AL, 1CH
+                CALL    RESTORE_RM_INT
+CT_DONE:        RET
+CLEANUP_TIMER   ENDP
+
+;
+; The timer interrupt handler.  Note that interrupt 1CH is not
+; available on NEC PC-98.
+;
+                ASSUME  DS:NOTHING
+                TALIGN  4
+RM_TIMER        PROC    NEAR
+                PUSH    EAX
+                PUSH    DS
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+;
+; Update clock for __clock()
+;
+                ADD     CLOCK_LO, 1
+                ADC     CLOCK_HI, 0
+;
+; Decrement timer for emergency exit
+;
+                CMP     EMERGENCY_TIMER, 0
+                JE      SHORT RMT_SKIP_EMERGENCY
+                DEC     EMERGENCY_TIMER
+                TALIGN  4
+RMT_SKIP_EMERGENCY:
+;
+; Update software timers
+;
+                CMP     TIMER_MIN, 0
+                JE      SHORT RMT_DONE
+                INC     TIMER_TICKS
+                DEC     TIMER_MIN
+                JNZ     SHORT RMT_DONE
+                CALL    RMT_CHECK
+                TALIGN  4
+RMT_DONE:       POP     DS
+                ASSUME  DS:NOTHING
+                POP     EAX
+                JMP     OLD_RM_INT1C
+RM_TIMER        ENDP
+
+;
+; At least one timer expired; examine all timers
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+RMT_CHECK       PROC    NEAR
+                PUSH    BX
+                PUSH    CX
+                PUSH    EDX
+                PUSH    DI
+                MOV     CX, MAX_TIMERS
+                LEA     BX, TIMER_TABLE
+                ASSUME  BX:PTR TIMER
+                XOR     EDX, EDX
+                MOV     TIMER_MIN, EDX
+                XCHG    EDX, TIMER_TICKS
+RMT_LOOP:       CMP     [BX].T_TYPE, TT_RUNNING
+                JB      SHORT RMT_NEXT
+                SUB     [BX].T_TICKS, EDX
+                JA      SHORT RMT_MIN
+                MOV     AX, TT_EXPIRED
+                XCHG    AX, [BX].T_TYPE
+                CMP     AX, TT_TERMIO_TIME
+                JE      SHORT RMT_TERMIO
+                CMP     AX, TT_SLEEP
+                JE      SHORT RMT_SLEEP
+                CMP     AX, TT_ALARM
+                JNE     SHORT RMT_NEXT
+RMT_ALARM:      MOV     DI, [BX].T_PROCESS
+                ASSUME  DI:PTR PROCESS
+                CMP     [DI].P_SIG_HANDLERS[4*SIGALRM], SIG_IGN
+                JE      SHORT RMT_NEXT
+                BTS     [DI].P_SIG_PENDING, SIGALRM     ; Generate SIGALRM
+                ASSUME  DI:NOTHING
+                JMP     SHORT RMT_NEXT
+
+RMT_TERMIO:     MOV     DI, [BX].T_PROCESS
+                OR      (PROCESS PTR [DI]).P_FLAGS, PF_TERMIO_TIME
+                JMP     SHORT RMT_NEXT
+
+RMT_SLEEP:      MOV     DI, [BX].T_PROCESS
+                OR      (PROCESS PTR [DI]).P_FLAGS, PF_SLEEP_FLAG
+                JMP     SHORT RMT_NEXT
+
+RMT_MIN:        MOV     EAX, [BX].T_TICKS
+                CMP     TIMER_MIN, 0
+                JE      SHORT RMT_SET
+                CMP     EAX, TIMER_MIN
+                JAE     SHORT RMT_NEXT
+RMT_SET:        MOV     TIMER_MIN, EAX
+RMT_NEXT:       ADD     BX, SIZE TIMER
+                LOOP    RMT_LOOP
+                ASSUME  BX:NOTHING
+                POP     DI
+                POP     EDX
+                POP     CX
+                POP     BX
+                RET
+RMT_CHECK       ENDP
+
+              IF RM_DEBUGGER
+;
+; Debug interrupt in real mode
+;
+                ASSUME  DS:NOTHING
+RM_DEBUG        PROC    NEAR
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                LEA     DX, $RM_DEBUG
+                CALL    RTEXT
+                MOV     BP, SP
+                MOV     AX, [BP+2]
+                CALL    RWORD
+                MOV     AL, ":"
+                CALL    RCHAR
+                MOV     AX, [BP+0]
+                CALL    RWORD
+                CALL    RCRLF
+                JMP     EXIT
+RM_DEBUG        ENDP
+
+              ENDIF
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/rmint.inc
===================================================================
--- trunk/src/emx/src/dos/rmint.inc	(revision 18)
+++ trunk/src/emx/src/dos/rmint.inc	(revision 18)
@@ -0,0 +1,35 @@
+;
+; RMINT.INC -- Initialize interrupts and handle real-mode interrupts
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+INIT_CODE       SEGMENT
+
+                EXTRN   INIT_INT:NEAR
+                EXTRN   CLEANUP_INT:NEAR
+                EXTRN   INIT_TIMER:NEAR
+                EXTRN   CLEANUP_TIMER:NEAR
+                EXTRN   SET_RM_INT:NEAR
+                EXTRN   RESTORE_RM_INT:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/rprint.asm
===================================================================
--- trunk/src/emx/src/dos/rprint.asm	(revision 18)
+++ trunk/src/emx/src/dos/rprint.asm	(revision 18)
@@ -0,0 +1,125 @@
+;
+; RPRINT.ASM -- Text output via DOS (real mode)
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; Note: This module must not use 386 instructions
+;
+
+                INCLUDE EMX.INC
+
+                PUBLIC  RWORD, RBYTE, RNIBBLE
+                PUBLIC  RCHAR, RTEXT, RCRLF
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+                .8086                           ; !!!
+
+RWORD           PROC    NEAR
+                XCHG    AL, AH
+                CALL    RBYTE
+                XCHG    AL, AH
+                CALL    RBYTE
+                RET
+RWORD           ENDP
+
+
+RBYTE           PROC    NEAR
+                PUSH    AX
+                REPT    4
+                SHR     AL, 1
+                ENDM
+                CALL    RNIBBLE
+                POP     AX
+                PUSH    AX
+                CALL    RNIBBLE
+                POP     AX
+                RET
+RBYTE           ENDP
+
+RNIBBLE         PROC    NEAR
+                AND     AL, 0FH
+                ADD     AL, 30H
+                CMP     AL, 3AH
+                JB      RNIB1
+                ADD     AL, 7
+RNIB1:          CALL    RCHAR
+                RET
+RNIBBLE         ENDP
+
+
+;
+; In:   DS:DX   Text (0 terminated)
+;
+RTEXT           PROC    NEAR
+                PUSH    AX
+                PUSH    BX
+                PUSH    CX
+                XCHG    BX, DX
+                MOV     CX, BX
+                XOR     AL, AL
+RTEXT1:         CMP     AL, DS:[BX]
+                JE      RTEXT2
+                INC     BX
+                JMP     RTEXT1
+RTEXT2:         XCHG    BX, CX
+                SUB     CX, BX
+                XCHG    BX, DX
+                MOV     BX, 1                   ; stdout
+                MOV     AH, 40H
+                INT     21H
+                POP     CX
+                POP     BX
+                POP     AX
+                RET
+RTEXT           ENDP
+
+RCHAR           PROC    NEAR
+                PUSH    AX
+                PUSH    DX
+                MOV     DL, AL
+                MOV     AH, 02H
+                INT     21H
+                POP     DX
+                POP     AX
+                RET
+RCHAR           ENDP
+
+
+RCRLF           PROC    NEAR
+                PUSH    AX
+                MOV     AL, CR
+                CALL    RCHAR
+                MOV     AL, LF
+                CALL    RCHAR
+                POP     AX
+                RET
+RCRLF           ENDP
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/rprint.inc
===================================================================
--- trunk/src/emx/src/dos/rprint.inc	(revision 18)
+++ trunk/src/emx/src/dos/rprint.inc	(revision 18)
@@ -0,0 +1,31 @@
+;
+; RPRINT.INC -- Text output via DOS (real mode)
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+INIT_CODE       SEGMENT
+
+                EXTRN   RWORD:NEAR, RBYTE:NEAR, RNIBBLE:WORD
+                EXTRN   RTEXT:NEAR, RCHAR:NEAR, RCRLF:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/segments.asm
===================================================================
--- trunk/src/emx/src/dos/segments.asm	(revision 18)
+++ trunk/src/emx/src/dos/segments.asm	(revision 18)
@@ -0,0 +1,532 @@
+;
+; SEGMENTS.ASM -- Manage segments
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__SEGMENTS      =       1
+
+                INCLUDE EMX.INC
+                INCLUDE TABLES.INC
+                INCLUDE MISC.INC
+                INCLUDE PAGING.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE SIGNAL.INC              ; Required by PROCESS.INC
+                INCLUDE PROCESS.INC
+
+                PUBLIC  NEW_TSS, G_PHYS_BASE
+                PUBLIC  CREATE_SEG, SEG_SIZE, SEG_BASE, SEG_ATTR, GET_BASE
+                PUBLIC  NULL_SEG, GET_LIN, GET_DESC, SV_SEGMENT, ADD_PAGES
+                PUBLIC  ACCESS_LOWMEM, MAP_PHYS
+                PUBLIC  INIT_DESC, RM_SEG_BASE, RM_SEG_SIZE, INIT_TSS
+
+SV_DATA         SEGMENT
+
+;
+; Base address of G_PHYS_SEL (see also G_PHYS_DESC)
+;
+G_PHYS_BASE     DD      0
+;
+; New TSS (with I/O bitmap) active
+;
+NEW_TSS         DB      FALSE                   ; Initially not active
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+
+;
+; Create a segment (make GDT/LDT entry)
+;
+; In:   SI      Pointer to GDT/LDT entry
+;       AX      Segment attributes (A_CODE32, A_DATA32, DPL_0, ..., DPL_3)
+;       EBX     Base address of segment
+;       ECX     Size of segment (limit+1)
+;
+                ASSUME  DS:NOTHING
+
+CREATE_SEG      PROC    NEAR
+                CALL    SEG_ATTR
+                CALL    SEG_BASE
+                CALL    SEG_SIZE
+                RET
+CREATE_SEG      ENDP
+
+
+;
+; Set the type/attributes of a segment
+;
+; In:   DS:SI   Pointer to descriptor
+;       AX      Type / attributes (A_CODE32, A_DATA32, DPL_0, ..., DPL_3)
+;
+SEG_ATTR        PROC    NEAR
+                AND     WORD PTR [SI+5], 0CF00H ; Clear all but G, B|D, limit
+                OR      [SI+5], AX              ; Set segment type/attributes
+                RET
+SEG_ATTR        ENDP
+
+
+;
+; Set the base address of a segment
+;
+; In:   DS:SI   Pointer to GDT entry
+;       EBX     Base address of segment
+;
+                ASSUME  SI:PTR DESCRIPTOR
+SEG_BASE        PROC    NEAR
+                PUSH    EBX
+                MOV     [SI].BASE_0_15, BX      ; Base 0..15
+                SHR     EBX, 16
+                MOV     [SI].BASE_16_23, BL     ; Base 16..23
+                MOV     [SI].BASE_24_31, BH     ; Base 24..31
+                POP     EBX
+                RET
+                ASSUME  SI:NOTHING
+SEG_BASE        ENDP
+
+
+;
+; Set the size of a segment
+;
+; In:   DS:SI   Pointer to GDT entry (already contains access & other info)
+;       ECX     Size of segment (limit+1)
+;
+                ASSUME  SI:PTR DESCRIPTOR
+SEG_SIZE        PROC    NEAR
+                PUSH    ECX
+                AND     [SI].GRAN, 70H          ; Keep B|0|AVL, clear G|limit
+                CMP     ECX, 1 SHL 20           ; Byte granular?
+                JA      SHORT SS_BIG            ; No -> page granular
+                DEC     ECX                     ; ECX := limit (byte granular)
+                MOV     [SI].LIMIT_0_15, CX     ; Limit 0..15
+                SHR     ECX, 16
+                OR      [SI].GRAN, CL           ; Limit 16..19
+                JMP     SHORT SS_RET
+
+SS_BIG:         ADD     ECX, 0FFFH              ; Round up
+                SHR     ECX, 12                 ; Convert to number of pages
+                DEC     ECX                     ; ECX := limit (page granular)
+                MOV     [SI].LIMIT_0_15, CX     ; Limit 0..15
+                SHR     ECX, 16
+                OR      CL, 80H                 ; Set G
+                OR      [SI].GRAN, CL           ; Limit 16..19
+SS_RET:         POP     ECX
+                RET
+                ASSUME  SI:NOTHING
+SEG_SIZE        ENDP
+
+
+;
+; Get the base address of a segment
+;
+; In:   DS:SI   Pointer to GDT entry
+;
+; Out:  EBX     Base address of segment
+;
+                ASSUME  SI:PTR DESCRIPTOR
+GET_BASE        PROC    NEAR
+                MOV     BL, [SI].BASE_16_23     ; Base 16..23
+                MOV     BH, [SI].BASE_24_31     ; Base 24..31
+                SHL     EBX, 16
+                MOV     BX, [SI].BASE_0_15      ; Base 0..15
+                RET
+                ASSUME  SI:NOTHING
+GET_BASE        ENDP
+
+;
+; Convert virtual address to linear address
+;
+; In:   AX      Selector
+;       EBX     Offset
+;       LDTR    Local descriptor table
+;
+; Out:  EBX     Linear address
+;       CY      Error
+;
+                ASSUME  DS:SV_DATA
+GET_LIN         PROC    NEAR
+                PUSH    EAX
+                PUSH    ESI
+                .386P
+                SLDT    SI
+                .386
+                CALL    GET_DESC
+                MOV     EAX, EBX
+                CALL    GET_BASE
+                ADD     EBX, EAX
+                CLC
+                POP     ESI
+                POP     EAX
+                RET
+GET_LIN         ENDP
+
+;
+; Get LDT/GDT entry
+;
+; In:   AX      Selector
+;       SI      Local descriptor table (selector)
+;
+; Out:  SI      Pointer to table entry
+;
+                ASSUME  DS:SV_DATA
+GET_DESC        PROC    NEAR
+                PUSH    AX
+                TEST    AX, 04H                 ; GDT?
+                JZ      SHORT GDES_1            ; Yes ->
+                AND     SI, NOT 07H
+                SUB     SI, G_LDT_SEL
+                IMUL    SI, LDT_ENTRIES
+                LEA     SI, LDTS[SI]
+                JMP     SHORT GDES_2
+GDES_1:         LEA     SI, GDT
+GDES_2:         AND     AX, NOT 07H
+                ADD     SI, AX
+                POP     AX
+                RET
+GET_DESC        ENDP
+
+;
+; Create a null segment (make GDT/LDT entry)
+;
+; In:   DS:SI   Pointer to GDT/LDT entry
+;
+                ASSUME  DS:NOTHING
+NULL_SEG        PROC    NEAR
+                MOV     DWORD PTR [SI+0], 0
+                MOV     DWORD PTR [SI+4], 0
+                RET
+NULL_SEG        ENDP
+
+
+;
+; Create supervisor data segment (not swappable)
+;
+; In:   ECX     Size (bytes)
+;       DS:SI   Pointer to GDT entry
+;
+; Out:  CY      Out of memory
+;
+; Note: No physical memory is allocated for the pages, so the pages must
+;       be present if accessed from within the page fault handler (to avoid
+;       recursion)
+;
+                ASSUME  DS:SV_DATA
+SV_SEGMENT      PROC    NEAR
+                PUSH    EAX
+                PUSH    EBX
+                PUSH    ECX
+                MOV     AL, PIDX_SV
+                CALL    ALLOC_PAGES             ; Get linear addresses
+                CALL    INIT_PAGES              ; Create page tables
+                JC      SHORT SVS_RET           ; Out of memory -> return
+                MOV     EBX, PAGE_LOCKED        ; Create locked pages
+                MOV     EDX, PIDX_SV OR SRC_ZERO
+                CALL    SET_PAGES
+                MOV     EBX, EAX                ; Linear address to EBX
+                POP     ECX                     ; Number of bytes
+                PUSH    ECX
+                MOV     AX, A_DATA32 OR DPL_0   ; Supervisor data segment
+                CALL    CREATE_SEG              ; Create segment descriptor
+SVS_RET:        POP     ECX
+                POP     EBX
+                POP     EAX
+                RET
+SV_SEGMENT      ENDP
+
+;
+; Allocate, initialize and switch to new TSS.
+;
+; If there isn't enough memory, NEW_TSS stays FALSE.
+;
+                ASSUME  DS:SV_DATA
+INIT_TSS        PROC    NEAR
+;
+; Allocate memory
+;
+                MOV     ECX, SIZE TSS_STRUC + 2001H
+                LEA     SI, G_TMP1_DESC         ; Use temporary descriptor
+                CALL    SV_SEGMENT              ; Create supervisor segment
+                JC      SHORT IT_RET            ; Out of memory -> done
+;
+; Copy initial TSS to new segment
+;
+                PUSH    DS                      ; Save DS
+                MOV     AX, G_TSS_MEM_SEL
+                MOV     DS, AX
+                MOV     AX, G_TMP1_SEL
+                MOV     ES, AX
+                XOR     SI, SI
+                XOR     DI, DI
+                MOV     CX, SIZE TSS_STRUC
+                REP     MOVSB
+;
+; Initialize I/O bitmap (all 64K ports disabled)
+;
+                MOV     AX, 0FFH
+                MOV     CX, 2001H
+                REP     STOSB
+                POP     DS                      ; Restore DS
+;
+; Copy to G_TSS_MEM_SEL descriptor
+;
+                MOV_ES_DS                       ; ES := DS
+                LEA     SI, G_TMP1_DESC
+                LEA     DI, G_TSS_MEM_DESC
+                MOVSD
+                MOVSD
+;
+; Copy to G_TSS_SEL descriptor
+;
+                CLI                             ; Disable interrupts
+                LEA     SI, G_TMP1_DESC
+                LEA     DI, G_TSS_DESC
+                MOVSD
+                MOVSD
+                LEA     SI, G_TSS_DESC
+                MOV     AX, A_TSS               ; Turn it into a TSS desciptor
+                CALL    SEG_ATTR
+;
+; Switch to new TSS
+;
+                AND     TSS_BUSY, NOT 2
+                MOV     AX, G_TSS_SEL
+                .386P
+                LTR     AX
+                .386
+                STI                             ; Enable interrupts
+                MOV     NEW_TSS, NOT FALSE      ; New TSS active
+IT_RET:         RET
+INIT_TSS        ENDP
+
+;
+; Add some pages of memory to a process.  The pages will be added at the
+; end of the data segment, above the stack.
+;
+; In:  DI       Pointer to process table entry
+;      ECX      Number of pages
+;
+; Out: EAX      Address in process space of the memory (or 0 on failure)
+; 
+                ASSUME  DS:SV_DATA
+ADD_PAGES       PROC    NEAR
+                ASSUME  DI:PTR PROCESS
+                PUSH    SI
+                MOV     EAX, [DI].P_DSEG_SIZE
+                ADD     EAX, 1000H              ; One empty page
+                PUSH    EAX                     ; Save the return value
+                SHL     ECX, 12                 ; Compute number of bytes
+                ADD     EAX, ECX                ; Adjust end address
+                JC      SHORT AP_FAIL           ; Overflow -> fail
+                CMP     EAX, [DI].P_LIN_SIZE    ; Beyond end of address space?
+                JA      SHORT AP_FAIL           ; Yes -> fail
+                MOV     EDX, EAX                ; New data segment size
+                POP     EAX                     ; Address of new pages
+                PUSH    EAX
+                PUSH    EDX
+                ADD     EAX, [DI].P_LINEAR      ; Compute linear address
+                SHR     ECX, 12                 ; Number of pages
+                MOV     EBX, PAGE_WRITE OR PAGE_USER
+                MOV     EDX, SRC_NONE
+                TEST    [DI].P_FLAGS, PF_DONT_ZERO
+                JNZ     SHORT AP_1
+                MOV     EDX, SRC_ZERO
+AP_1:           MOV     DL, [DI].P_PIDX
+                CALL    SET_COMMIT              ; Set PAGE_ALLOC bit
+                CALL    SET_PAGES
+                POP     EAX                     ; New data segment size
+                JC      SHORT AP_FAIL
+                MOV     [DI].P_DSEG_SIZE, EAX   ; Update data segment size
+                MOV     ECX, [DI].P_DSEG_SIZE
+                MOV     SI, [DI].P_LDT_PTR
+                ADD     SI, L_DATA_SEL AND NOT 07H
+                CALL    SEG_SIZE
+                POP     EAX
+                POP     SI
+                RET
+
+AP_FAIL:        POP     EAX
+                POP     SI
+                XOR     EAX, EAX                        ; Return 0
+                RET
+                ASSUME  DI:NOTHING
+ADD_PAGES       ENDP
+
+
+;
+; Map pages into the address space of a process
+;
+; In:   DI      Pointer to process table entry
+;       EBX     Physical address
+;       ECX     Number of pages
+;
+; Out:  EAX     Adress in process space (0 if no space)
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  DI:PTR PROCESS
+MAP_PHYS        PROC    NEAR
+                MOV     EAX, [DI].P_DSEG_SIZE
+                ADD     EAX, 1000H
+                PUSH    EAX
+                MOV     EDX, ECX
+                SHL     EDX, 12
+                ADD     EAX, EDX
+                JC      SHORT MP_FAIL
+                CMP     EAX, [DI].P_LIN_SIZE
+                JA      SHORT MP_FAIL
+                MOV     [DI].P_DSEG_SIZE, EAX
+                SUB     EAX, EDX
+                ADD     EAX, [DI].P_LINEAR
+                MOV     DL, [DI].P_PIDX
+                TEST    EBX, NOT 0FFFH          ; Is the address = 0?
+                JNZ     SHORT MP_MORE           ; No  -> continue
+                PUSH    ECX
+                MOV     ECX, 1                  ; Set one page table entry
+                CALL    SET_PAGES               ; This is required because
+                POP     ECX                     ; SET_PAGES doesn't increment
+                DEC     ECX                     ; the address if it is 0
+                JZ      SHORT MP_DONE
+                ADD     EAX, 1000H
+                ADD     EBX, 1000H
+MP_MORE:        CALL    SET_PAGES
+MP_DONE:        MOV     ECX, [DI].P_DSEG_SIZE
+                MOV     SI, [DI].P_LDT_PTR
+                ADD     SI, L_DATA_SEL AND NOT 07H
+                CALL    SEG_SIZE
+                POP     EAX
+                RET
+
+MP_FAIL:        POP     EAX
+                XOR     EAX, EAX
+                RET
+                ASSUME  DI:NOTHING
+MAP_PHYS       ENDP
+
+
+;
+; Convert real-mode pointer to protected-mode pointer
+;
+; In:  EAX      Real-mode Segment:Offset
+;
+; Out: EBX      Offset into G_LOWMEM_SEL segment
+;      EAX      Modified
+;
+ACCESS_LOWMEM   PROC    NEAR
+                ROL     EAX, 16                 ; EAX = offset:segment
+                MOVZX   EBX, AX                 ; EBX = segment
+                SHL     EBX, 4                  ; EBX = base address of segment
+                SHR     EAX, 16                 ; EAX = offset
+                ADD     EBX, EAX
+                RET
+ACCESS_LOWMEM   ENDP
+
+SV_CODE         ENDS
+
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Convert the base field of a GDT entry. It already contains the
+; offset into the real-mode segment given in AX.
+;
+; In:   AX      Real-mode segment
+;       DI      Pointer to descriptor table entry (SV_DATA)
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  DI:PTR DESCRIPTOR
+INIT_DESC       PROC    NEAR
+                PUSH    EAX
+                PUSH    EDX
+                MOVZX   EAX, AX
+                SHL     EAX, 4
+                MOVZX   EDX, [DI].BASE_0_15     ; Get real-mode offset
+                ADD     EAX, EDX
+                CALL    RM_SEG_BASE             ; Set base address
+                POP     EDX
+                POP     EAX
+                RET
+                ASSUME  DI:NOTHING
+INIT_DESC       ENDP
+
+
+
+;
+; Set the base address of a segment (real-mode version)
+;
+; In:   DS:DI   Pointer to GDT entry
+;       EAX     Base address of segment
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  DI:PTR DESCRIPTOR
+RM_SEG_BASE     PROC    NEAR
+                PUSH    EAX
+                MOV     [DI].BASE_0_15, AX      ; Base 0..15
+                SHR     EAX, 16
+                MOV     [DI].BASE_16_23, AL     ; Base 16..23
+                MOV     [DI].BASE_24_31, AH     ; Base 24..31
+                POP     EAX
+                RET
+                ASSUME  DI:NOTHING
+RM_SEG_BASE     ENDP
+
+
+;
+; Set the size of a segment (real-mode version)
+;
+; In:   DS:DI   Pointer to GDT entry
+;       ECX     Size of segment (limit+1)
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  DI:PTR DESCRIPTOR
+RM_SEG_SIZE     PROC    NEAR
+                PUSH    ECX
+                AND     [DI].GRAN, 70H          ; Keep B|0|AVL, clear G|limit
+                CMP     ECX, 1 SHL 20           ; Byte granular?
+                JA      SHORT RSS_BIG           ; No -> page granular
+                DEC     ECX                     ; ECX := limit (byte granular)
+                MOV     [DI].LIMIT_0_15, CX     ; Limit 0..15
+                SHR     ECX, 16
+                OR      [DI].GRAN, CL           ; Limit 16..19
+                JMP     SHORT RSS_RET
+
+RSS_BIG:        ADD     ECX, 0FFFH              ; Round up
+                SHR     ECX, 12                 ; Convert to number of pages
+                DEC     ECX                     ; ECX := limit (page granular)
+                MOV     [DI].LIMIT_0_15, CX     ; Limit 0..15
+                SHR     ECX, 16
+                OR      CL, 80H                 ; Set G
+                OR      [DI].GRAN, CL           ; Limit 16..19
+RSS_RET:        POP     ECX
+                RET
+                ASSUME  DI:NOTHING
+RM_SEG_SIZE     ENDP
+
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/segments.inc
===================================================================
--- trunk/src/emx/src/dos/segments.inc	(revision 18)
+++ trunk/src/emx/src/dos/segments.inc	(revision 18)
@@ -0,0 +1,65 @@
+;
+; SEGMENTS.INC -- Manage segments
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+A_DATA32        =   4093H   ; Accessed, writable, expand up, big
+A_READ32        =   4091H   ; Accessed, expand up, big
+A_CODE32        =   409BH   ; Accessed, readable, non-conforming, default=32
+A_LDT           =   0082H   ; LDT
+A_TSS           =   0089H   ; TSS
+
+DPL_0           =   0000H
+DPL_1           =   0020H
+DPL_2           =   0040H
+DPL_3           =   0060H
+
+
+              IFNDEF __SEGMENTS
+
+SV_DATA         SEGMENT
+
+                EXTRN   NEW_TSS:BYTE
+                EXTRN   G_PHYS_BASE:DWORD
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                EXTRN   CREATE_SEG:NEAR, SV_SEGMENT:NEAR
+                EXTRN   SEG_SIZE:NEAR, SEG_BASE:NEAR, SEG_ATTR:NEAR
+                EXTRN   GET_BASE:NEAR, NULL_SEG:NEAR, GET_LIN:NEAR
+                EXTRN   GET_DESC:NEAR, INIT_TSS:NEAR, ADD_PAGES:NEAR
+                EXTRN   ACCESS_LOWMEM:NEAR, MAP_PHYS:NEAR
+
+SV_CODE         ENDS
+
+INIT_CODE       SEGMENT
+
+                EXTRN   INIT_DESC:NEAR
+                EXTRN   RM_SEG_BASE:NEAR
+                EXTRN   RM_SEG_SIZE:NEAR
+
+INIT_CODE       ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/signal.asm
===================================================================
--- trunk/src/emx/src/dos/signal.asm	(revision 18)
+++ trunk/src/emx/src/dos/signal.asm	(revision 18)
@@ -0,0 +1,929 @@
+;
+; SIGNAL.ASM -- Signal processing
+;
+; Copyright (c) 1991-1998 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__SIGNAL        =       1
+                INCLUDE EMX.INC
+                INCLUDE EXCEPT.INC
+                INCLUDE PMINT.INC
+                INCLUDE RMINT.INC
+                INCLUDE MISC.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE CORE.INC
+                INCLUDE OPRINT.INC
+                INCLUDE ERRORS.INC
+
+                PUBLIC  SIG_DELIVER_PENDING, SIG_USER_CALL, SIG_RETURN, SIG_MSG
+                PUBLIC  CRIT_ERR_FLAG, SIG_CORE, SIG_VALID, EMERGENCY_TIMER
+                PUBLIC  EMERGENCY_FLAG
+                PUBLIC  HOOK_INT
+                PUBLIC  CLEANUP_SIGNAL
+
+LSTACKS         =       2                       ; Number of local stacks
+LSTACK_SIZE     =       512                     ; Size of a local stack (bytes)
+
+LSTACK          SEGMENT
+                DB      LSTACKS DUP (LSTACK_SIZE DUP (?))
+LSTACK          ENDS
+
+
+SV_DATA         SEGMENT
+
+;
+; Original interrupt 1BH vector
+;
+OLD_BREAK       LABEL   DWORD
+OLD_BREAK_OFF   DW      0
+OLD_BREAK_SEG   DW      0
+
+;
+; This flag is set when cleaning up while executing the critical
+; error handler
+;
+CRIT_ERR_FLAG   DB      FALSE
+
+;
+; Timer and counter for emergency exit.  EMERGENCY_TIMER set to 18 if
+; it is zero when Ctrl-Break is hit.  Each timer tick decrements
+; EMERGENCY_TIMER.  If Ctrl-Break is hit four times while EMERGENCY_TIMER
+; is non-zero, EMERGENCY_FLAG will be set to make emx abort.
+; EMERGENCY_COUNTER is used for counting Ctrl-Break interrupts after
+; setting EMERGENCY_TIMER.
+;
+; This implementation is simple but does not work correctly if Ctrl-Break
+; is hit less than five times in a second, followed by more Ctrl-Break
+; interrupts in the next second.  A perfect solution involves keeping
+; time stamps for the last 4 Ctrl-Break interrupts.
+;
+
+EMERGENCY_TIMER   DB    0
+EMERGENCY_COUNTER DB    0
+EMERGENCY_FLAG    DB    FALSE
+
+;
+; Don't use RTEXT, as only function calls 01H..0CH, 59H are allowed.
+;
+$ABORTED        DB      "Program aborted", CR, LF, "$"
+$STACKS         DB      "Out of stacks", CR, LF, "$"
+
+$STOPPED_BY     BYTE    CR, LF, "Process terminated by ", 0
+$ABNORMAL       BYTE    CR, LF, "Abnormal program termination", CR, LF, 0
+
+$SIG_UNKNOWN    BYTE    "unknown signal", 0
+
+$SIGHUP         BYTE    "SIGHUP", 0
+$SIGINT         BYTE    "SIGINT", 0
+$SIGQUIT        BYTE    "SIGQUIT", 0
+$SIGILL         BYTE    "SIGILL", 0
+$SIGTRAP        BYTE    "SIGTRAP", 0
+$SIGABRT        BYTE    "SIGABRT", 0
+$SIGEMT         BYTE    "SIGEMT", 0
+$SIGFPE         BYTE    "SIGFPE", 0
+$SIGKILL        BYTE    "SIGKILL", 0
+$SIGBUS         BYTE    "SIGBUS", 0
+$SIGSEGV        BYTE    "SIGSEGV", 0
+$SIGSYS         BYTE    "SIGSYS", 0
+$SIGPIPE        BYTE    "SIGPIPE", 0
+$SIGALRM        BYTE    "SIGALRM", 0
+$SIGTERM        BYTE    "SIGTERM", 0
+$SIGUSR1        BYTE    "SIGUSR1", 0
+$SIGUSR2        BYTE    "SIGUSR2", 0
+$SIGCLD         BYTE    "SIGCLD", 0
+$SIGBREAK       BYTE    "SIGBREAK", 0
+$SIGWINCH       BYTE    "SIGWINCH", 0
+
+                TALIGN  2
+SIG_NAMES       WORD    $SIG_UNKNOWN, $SIGHUP, $SIGINT, $SIGQUIT    ; 0..3
+                WORD    $SIGILL, $SIGTRAP, $SIGABRT, $SIGEMT        ; 4..7
+                WORD    $SIGFPE, $SIGKILL, $SIGBUS, $SIGSEGV        ; 8..11
+                WORD    $SIGSYS, $SIGPIPE, $SIGALRM, $SIGTERM       ; 12..15
+                WORD    $SIGUSR1, $SIGUSR2, $SIGCLD                 ; 16..18
+                WORD    $SIG_UNKNOWN, $SIG_UNKNOWN, $SIGBREAK       ; 19..21
+                WORD    $SIG_UNKNOWN, $SIG_UNKNOWN, $SIG_UNKNOWN    ; 22..24
+                WORD    $SIG_UNKNOWN, $SIG_UNKNOWN, $SIG_UNKNOWN    ; 25..27
+                WORD    $SIGWINCH                                   ; 28
+
+;
+; Valid signal numbers have a non-FALSE entry in this table.
+;
+SIG_VALID       BYTE    FALSE,     NOT FALSE, NOT FALSE, NOT FALSE  ; 0..3
+                BYTE    NOT FALSE, NOT FALSE, NOT FALSE, NOT FALSE  ; 4..7
+                BYTE    NOT FALSE, NOT FALSE, NOT FALSE, NOT FALSE  ; 8..11
+                BYTE    NOT FALSE, NOT FALSE, NOT FALSE, NOT FALSE  ; 12..15
+                BYTE    NOT FALSE, NOT FALSE, NOT FALSE, FALSE      ; 16..19
+                BYTE    FALSE,     NOT FALSE, FALSE,     FALSE      ; 20..23
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 24..27
+                BYTE    NOT FALSE                                   ; 28
+
+;
+; If SIG_CORE[signo] is FALSE, no core dump file will be written for
+; the signal signo.
+;
+
+SIG_CORE        BYTE    FALSE,     FALSE,     FALSE,     NOT FALSE  ; 0..3
+                BYTE    NOT FALSE, NOT FALSE, NOT FALSE, NOT FALSE  ; 4..7
+                BYTE    NOT FALSE, FALSE,     NOT FALSE, NOT FALSE  ; 8..11
+                BYTE    NOT FALSE, FALSE,     FALSE,     FALSE      ; 12..15
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 16..19
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 20..23
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 24..27
+                BYTE    FALSE                                       ; 28
+
+;
+; If SIG_DFL_ACTION[signo] is FALSE, the program will be terminated
+; for signal signo if SIG_DFL is set.  If the table entry is not FALSE,
+; the signal will be ignored.
+;
+SIG_DFL_ACTION  BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 0..3
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 4..7
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 8..11
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 12..15
+                BYTE    NOT FALSE, NOT FALSE, NOT FALSE, FALSE      ; 16..19
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 20..23
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 24..27
+                BYTE    NOT FALSE                                   ; 28
+
+;
+; If SIG_IGN_ACTION[signo] is FALSE, the program will be terminated
+; for signal signo if SIG_IGN is set.  If the entry is not FALSE, the
+; signal will be ignored.
+;
+SIG_IGN_ACTION  BYTE    FALSE,     NOT FALSE, NOT FALSE, NOT FALSE  ; 0..3
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 4..7
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 8..11
+                BYTE    FALSE,     NOT FALSE, NOT FALSE, FALSE      ; 12..15
+                BYTE    NOT FALSE, NOT FALSE, NOT FALSE, FALSE      ; 16..19
+                BYTE    FALSE,     NOT FALSE, FALSE,     FALSE      ; 20..23
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 24..27
+                BYTE    NOT FALSE                                   ; 28
+
+;
+; If SIG_FUN_ACTION[signo] is FALSE, the program will be terminated
+; for after calling the signal handler for signal signo.  If the entry
+; is not FALSE, the program will be continued.
+;
+SIG_FUN_ACTION  BYTE    FALSE,     NOT FALSE, NOT FALSE, NOT FALSE  ; 0..3
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 4..7
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 8..11
+                BYTE    FALSE,     NOT FALSE, NOT FALSE, NOT FALSE  ; 12..15
+                BYTE    NOT FALSE, NOT FALSE, NOT FALSE, FALSE      ; 16..19
+                BYTE    FALSE,     NOT FALSE, FALSE,     FALSE      ; 20..23
+                BYTE    FALSE,     FALSE,     FALSE,     FALSE      ; 24..27
+                BYTE    NOT FALSE                                   ; 28
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+;
+; Check for pending signals
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+SIG_DELIVER_PENDING PROC NEAR
+                MOV     BX, PROCESS_PTR         ; Current process
+                CMP     BX, NO_PROCESS          ; In user code?
+                JE      SHORT SDP_RET           ; No  -> no signals
+                ASSUME  BX:PTR PROCESS
+;
+; Check signals only if called from user code [0.8b]
+;
+                TEST    I_CS, 3                 ; Called from user code?
+                JZ      SHORT SDP_RET           ; No  -> no signals
+;
+; Start of Critical section
+;
+                CLI
+                MOV     EAX, [BX].P_SIG_BLOCKED ; Get set of pending,
+                NOT     EAX                     ; unblocked signals
+                AND     EAX, [BX].P_SIG_PENDING
+                JZ      SHORT SDP_RET_STI       ; No signals -> just return
+;
+; Find a pending signal, reset its `signal pending' bit and
+; fetch the signal handler
+;
+                BSF     EDX, EAX                ; Find first bit
+                JZ      SHORT SDP_RET_STI       ; Cannot happen
+                BTR     [BX].P_SIG_PENDING, EDX ; Reset `signal pending' bit
+                MOV     SI, DX
+                SHL     SI, 2
+                MOV     EAX, [BX].P_SIG_HANDLERS[SI] ; Get address
+                CMP     EAX, SIG_IGN            ; Ignore signal?
+                JE      SHORT SDP_IGNORE        ; Yes -> see table
+                CMP     EAX, SIG_DFL            ; Default handler?
+                JNE     SDP_USER                ; No  -> call signal handler
+;
+; SIG_DFL
+;
+                STI                             ; End of critical section
+                CMP     EDX, SIGTERM            ; SIGTERM?
+                JE      SHORT SDP_SIGTERM       ; Yes -> terminate program
+                CMP     SIG_DFL_ACTION[EDX], FALSE ; Ingore signal?
+                JNE     SHORT SDP_RET           ; Yes -> ignore
+                JMP     SHORT SDP_TERM          ; No  -> terminate process
+
+SDP_RET_STI:    STI                             ; End of critical section
+SDP_RET:        RET
+
+;
+; SIG_IGN
+;
+SDP_IGNORE:     STI                             ; End of critical section
+                CMP     SIG_IGN_ACTION[EDX], FALSE ; Ignore signal?
+                JNE     SHORT SDP_RET
+;
+; Terminate / abort process due to signal EDX
+;
+                ASSUME  BX:PTR PROCESS
+SDP_TERM:       MOV     EAX, EDX
+                CALL    SIG_MSG
+                TEST    [BX].P_FLAGS, PF_NO_CORE
+                JNZ     SHORT SDP_TERM_2
+                CMP     EAX, SIGNALS
+                JAE     SHORT SDP_TERM_2
+                CMP     SIG_CORE[EAX], FALSE
+                JE      SHORT SDP_TERM_2
+                CALL    CORE_REGS_I
+                CALL    CORE_DUMP
+SDP_TERM_2:
+;
+; Default signal handler for SIGTERM
+;
+SDP_SIGTERM:    MOV     AX, 4C03H               ; exit(3)
+                INT     21H
+
+;
+; Call user specified signal handler
+;
+SDP_USER:       MOV     ECX, FALSE              ; Not a trap
+                CALL    SIG_USER_CALL
+                JMP     SDP_RET
+
+                ASSUME  BX:NOTHING
+                ASSUME  BP:NOTHING
+SIG_DELIVER_PENDING ENDP
+
+;
+; Display "Stopped by" message
+;
+; In:  EAX      Signal number
+;
+                ASSUME  DS:SV_DATA
+SIG_MSG         PROC    NEAR
+                LEA     EDX, $ABNORMAL
+                CMP     EAX, SIGABRT
+                JE      SHORT SIG_MSG_1
+                LEA     EDX, $STOPPED_BY
+                CALL    OTEXT
+                LEA     EDX, $SIG_UNKNOWN
+                CMP     EAX, SIGNALS
+                JAE     SHORT SIG_MSG_1
+                MOVZX   EDX, SIG_NAMES[EAX*2]
+SIG_MSG_1:      CALL    OTEXT
+                CALL    OCRLF
+                RET
+SIG_MSG         ENDP
+
+
+;
+; Call user specified signal handler on return from interrupt or exception.
+;
+; In:   EAX     Address of signal handler
+;       EDX     Signal number
+;       ECX     Non-FALSE if signal generated by an exception
+;       BX      Pointer to process table entry
+;
+; We copy the saved registers to the interrupted program's stack
+; to save supervisor stack space and to enable the program to reclaim
+; the stack space by resetting the stack pointer: setjmp/longjmp.
+;
+; This function reenables interrupts as soon as possible.  It is
+; assumed that interrupts are disabled when entering this function.
+;
+SUC_TRAP        EQU     (DWORD PTR [BP-1*4])
+SUC_SIGNO       EQU     (DWORD PTR [BP-2*4])
+SUC_HANDLER     EQU     (DWORD PTR [BP-3*4])
+SUC_MASK        EQU     (DWORD PTR [BP-4*4])
+SUC_FLAGS       EQU     (DWORD PTR [BP-5*4])
+
+                ASSUME  DS:SV_DATA
+                ASSUME  BX:PTR PROCESS
+                ASSUME  BP:PTR ISTACKFRAME
+SIG_USER_CALL   PROC    NEAR
+                MOV     DI, BP
+                ASSUME  DI:PTR ISTACKFRAME
+                PUSH    BP
+                MOV     BP, SP
+                ASSUME  BP:NOTHING
+                SUB     SP, 5 * 4
+                MOV     SUC_HANDLER, EAX
+                MOV     SUC_TRAP, ECX
+                MOV     SUC_SIGNO, EDX
+;
+; Compute and set new signal mask
+;
+                MOV     SI, DX                  ; Signal number
+                SHL     SI, 2
+                MOV     EAX, [BX].P_SIG_BLOCKED
+                MOV     SUC_MASK, EAX           ; Previous signal mask
+                TEST    [BX].P_SA_FLAGS[SI], SA_SYSV
+                JNZ     SHORT SUC_SYSV
+                BTS     EAX, EDX                ; Block the signal
+                TEST    [BX].P_SA_FLAGS[SI], SA_ACK
+                JNZ     SHORT SUC_SETMASK
+                OR      EAX, [BX].P_SA_MASK[SI] ; Block signals in sa_mask
+                JMP     SHORT SUC_SETMASK
+
+SUC_SYSV:       MOV     [BX].P_SIG_HANDLERS[SI], SIG_DFL
+                JMP     SHORT SUC_1
+
+SUC_SETMASK:    MOV     [BX].P_SIG_BLOCKED, EAX
+SUC_1:          MOV     EAX, [BX].P_SA_FLAGS[SI]
+                STI                             ; Enable interrupts
+;
+; Compute sa_flags (set SA_TRAP if signal generated by an exception)
+;
+                AND     EAX, NOT SA_TRAP
+                CMP     SUC_TRAP, FALSE
+                JE      SHORT SUC_2
+                OR      EAX, SA_TRAP
+SUC_2:          MOV     SUC_FLAGS, EAX
+;
+; Copy registers to the stack
+;
+                MOV     EAX, SS:[DI].IS_ESP     ; User stack
+                SUB     EAX, I_REG_DWORDS * 4   ; Allocate stack frame
+                MOV     SS:[DI].IS_ESP, EAX     ; and adjust ESP
+                PUSH    DS                      ; Save DS
+                PUSH    EDI                     ; Save EDI
+                MOV     ECX, I_REG_DWORDS       ; Copy saved registers
+                PUSH    SS                      ; Copy from supervisor stack
+                POP     DS
+                ASSUME  DS:NOTHING
+                MOVZX   ESI, DI                 ; Pointer to stack frame
+                MOV     ES, SS:[DI].IS_SS       ; Access program's stack
+                MOV     EDI, EAX
+                CLD
+                REP     MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
+                POP     EDI                     ; Restore EDI
+                POP     DS                      ; Restore DS
+                ASSUME  DS:SV_DATA
+;
+; Then, build a stack frame for the signal handler and return.
+; Problem: on return from the signal handler, it should restore all
+; registers from the stack. Where shall we put that code?
+;
+; 1. put it into the startup code (at a fixed location or introduce
+;    a system function called by startup code for telling the supervisor
+;    where that code resides)
+;
+; 2. put it into the application's stack
+;
+; 3. put it into the supervisor. The signal handler must return to the
+;    supervisor. This is tricky, as the signal handler normally returns
+;    with a *near* `RET', which doesn't change privilege levels. Here's
+;    the trick: The `RET' instruction must generate an exception. There's
+;    little choice: Either a segmentation fault (EIP beyond CS limit)
+;    or a page fault (page not present). For the second alternative,
+;    we would have to reserve a page *inside* the code segment for
+;    that purpose to avoid a segmentation fault and we wouldn't know why
+;    and from where we got to that address. Therefore, we'll return
+;    to an address outside the code segment. CS:EIP will point to the
+;    offending instruction (`RET') and SS:ESP will pointer to the address
+;    we chose for that purpose. We assume that all signal handlers return
+;    by means of `RET', not by `RET n' or `JMP'. For additional security,
+;    we put a signature word onto the stack.
+;
+; This is the stack frame we need:
+;
+;       +-------------------------------------------+
+;       |                                           |
+;       | Saved registers of interrupted program    |
+;       | (see PMINT.INC for details)               |
+;       |                                           |
+;       +-------------------------------------------+
+;       |                                           |
+;       | SIGFRAME:                                 |
+;       | - Old signal mask                         |
+;       | - sa_flags                                |
+;       | - Signal number                           |
+;       | - Signature word                          |
+;       | - Signal number (signal handler argument) |
+;       | - Our special EIP                         |
+;       |                                           |
+; ESP-> +-------------------------------------------+
+;
+; The signal number is stored twice as the signal handler may
+; change its argument.
+;
+                MOV     ESI, SS:[DI].IS_ESP     ; Now points to saved regs
+                SUB     ESI, SIZE SIGFRAME      ; Push SIGFRAME
+                MOV     SS:[DI].IS_ESP, ESI     ; Adjust ESP
+                ASSUME  ESI:NEAR32 PTR SIGFRAME
+                MOV     ES:[ESI].SF_EIP, SIG_EIP ; Our special EIP
+                MOV     EAX, SUC_SIGNO
+                MOV     ES:[ESI].SF_ARG, EAX    ; Signal number (arg)
+                MOV     ES:[ESI].SF_SIGNO, EAX  ; Signal number
+                MOV     ES:[ESI].SF_SIGNATURE, SIG_SIGNATURE ; Signature
+                MOV     EAX, SUC_MASK
+                MOV     ES:[ESI].SF_MASK, EAX   ; Old signal mask
+                MOV     EAX, SUC_FLAGS
+                MOV     ES:[ESI].SF_FLAGS, EAX  ; sa_flags
+                ASSUME  ESI:NOTHING
+                MOV     EAX, SUC_HANDLER
+                MOV     SS:[DI].IS_EIP, EAX     ; Address of signal handler
+                CALL    BREAK_AFTER_IRET        ; Allow debugging signals
+                MOV     SP, BP
+                POP     BP
+                RET                             ; Done
+                ASSUME  BX:NOTHING
+                ASSUME  DI:NOTHING
+SIG_USER_CALL   ENDP
+
+
+;
+; Return from signal handler
+;
+; Remove our special stack frame and restore registers from user program's
+; stack
+;
+; In:  ES:ESI   Pointer to special stack frame
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+                ASSUME  ESI:NEAR32 PTR SIGFRAME
+SIG_RETURN      PROC    NEAR
+                MOV     BX, PROCESS_PTR         ; Current process
+                CMP     BX, NO_PROCESS          ; No process?
+                JE      SIGRET_TERMINATE        ; Yes -> cannot happen
+                ASSUME  BX:PTR PROCESS
+
+                MOV     EAX, ES:[ESI].SF_SIGNO  ; Get the signal number
+                CMP     EAX, SIGNALS            ; Signal number out of range?
+                JAE     SHORT SIGRET_TERMINATE  ; Yes -> terminate process
+                MOV     ECX, ES:[ESI].SF_FLAGS  ; Saved sa_flags
+                TEST    ECX, SA_TRAP            ; Generated by exception?
+                JZ      SHORT SIGRET_1          ; No  -> continue
+                CMP     SIG_FUN_ACTION[EAX], FALSE ; Continue program?
+                JE      SHORT SIGRET_TERMINATE  ; No  -> terminate process
+SIGRET_1:       TEST    ECX, SA_SYSV OR SA_ACK
+                JNZ     SHORT SIGRET_REGS       ; Don't restore signal mask
+                MOV     EAX, ES:[ESI].SF_MASK   ; Restore signal mask
+                MOV     [BX].P_SIG_BLOCKED, EAX
+
+SIGRET_REGS:    PUSH    DS                      ; Save DS
+                ADD     ESI, SIZE SIGFRAME      ; Skip special stack frame
+                ASSUME  ESI:NOTHING
+                MOV     EDI, EBP                ; Copy to supervisor stack
+                PUSH    SS
+                POP     ES
+                MOV     DS, I_SS                ; Copy from user stack segment
+                ASSUME  DS:NOTHING
+                CLD
+                MOV     ECX, I_REG_DWORDS       ; Copy saved registers
+                REP     MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
+                POP     DS
+                ASSUME  DS:SV_DATA
+                MOV     I_ESP, ESI              ; Adjust stack pointer
+                CALL    BREAK_AFTER_IRET        ; Continue debugging
+                JMP     EXCEPT_RET              ; Return to interrupted program
+
+SIGRET_TERMINATE:
+                RET                             ; Continue exception handler
+                ASSUME  BX:NOTHING
+                ASSUME  BP:NOTHING
+SIG_RETURN      ENDP
+
+
+
+;
+; Implementation of __signal()
+;
+; In:   EAX     Signal number
+;       EDX     Signal handler
+;       DI      Pointer to process table entry
+;
+; Out:  EAX     Previous handler or SIG_ERR
+;
+ISA             EQU     (SIGACTION PTR [BP-1*SIZE SIGACTION])
+OSA             EQU     (SIGACTION PTR [BP-2*SIZE SIGACTION])
+
+                ASSUME  DS:SV_DATA
+                ASSUME  DI:PTR PROCESS
+                TALIGN  4
+DO_SIGNAL       PROC    NEAR
+                PUSH    BP
+                MOV     BP, SP
+                SUB     SP, 2 * SIZE SIGACTION
+                MOV     ISA.SA_MASK, 0
+                MOV     ISA.SA_HANDLER, EDX
+;
+; Set sa_flags according to __uflags()
+;
+                MOV     EDX, [DI].P_UFLAGS
+                AND     EDX, UF_SIG_MODEL
+                MOV     ECX, SA_ACK
+                CMP     EDX, UF_SIG_EMX
+                JE      SHORT SIGNAL_1
+                MOV     ECX, SA_SYSV
+                CMP     EDX, UF_SIG_SYSV
+                JE      SHORT SIGNAL_1
+                MOV     ECX, 0
+SIGNAL_1:       MOV     ISA.SA_FLAGS, ECX
+;
+; Call __sigaction()
+;
+                PUSH    SS
+                POP     ES
+                LEA     EDX, ISA
+                LEA     EBX, OSA
+                CALL    DO_SIGACTION
+                OR      EAX, EAX
+                MOV     EAX, SIG_ERR
+                JNZ     SHORT SIGNAL_RET
+                MOV     EAX, OSA.SA_HANDLER
+SIGNAL_RET:     MOV     SP, BP
+                POP     BP
+                RET
+                ASSUME  DI:NOTHING
+DO_SIGNAL       ENDP                
+
+
+;
+; This function implements __sigaction()
+;
+; In:   EAX     Signal number
+;       ES:EDX  Pointer to sigaction structure (input)
+;       ES:EBX  Pointer to sigaction structure (output)
+;
+; Out:  EAX     errno (0 if no error)
+;
+SIGA_O_HANDLER  EQU     (DWORD PTR [BP-1*4])
+SIGA_O_MASK     EQU     (DWORD PTR [BP-2*4])
+SIGA_O_FLAGS    EQU     (DWORD PTR [BP-3*4])
+SIGA_OACT       EQU     (DWORD PTR [BP-4*4])
+SIGA_SIGNO      EQU     (DWORD PTR [BP-5*4])
+
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+DO_SIGACTION    PROC    NEAR
+                PUSH    BP
+                MOV     BP, SP
+                SUB     SP, 5 * 4
+                MOV     SIGA_SIGNO, EAX
+                MOV     SIGA_OACT, EBX
+                CMP     EAX, SIGNALS            ; Valid signal number?
+                JAE     SIGACT_ERROR            ; No  -> failure
+                CMP     SIG_VALID[EAX], FALSE
+                JE      SIGACT_ERROR            ; No  -> failure
+                MOV     BX, AX
+                SHL     BX, 2
+;
+; Save the current action (in case both pointers point to the same object).
+;
+                CLI                             ; Start of critical section
+                MOV     EAX, [DI].P_SIG_HANDLERS[BX]
+                MOV     SIGA_O_HANDLER, EAX
+                MOV     EAX, [DI].P_SA_MASK[BX]
+                MOV     SIGA_O_MASK, EAX
+                MOV     EAX, [DI].P_SA_FLAGS[BX]
+                MOV     SIGA_O_FLAGS, EAX
+;
+; Set the new action if present
+;
+                TEST    EDX, EDX
+                JZ      SHORT SIGACT_NO_INPUT
+                CMP     SIGA_SIGNO, SIGKILL     ; Cannot modify SIGKILL
+                JE      SIGACT_ERROR_STI
+                ASSUME  EDX:NEAR32 PTR SIGACTION
+                MOV     EAX, ES:[EDX].SA_MASK
+                SHL     EAX, 1
+                AND     EAX, SIG_BLOCK_MASK
+                MOV     [DI].P_SA_MASK[BX], EAX
+                MOV     ECX, ES:[EDX].SA_FLAGS
+                MOV     [DI].P_SA_FLAGS[BX], ECX
+                MOV     EAX, ES:[EDX].SA_HANDLER
+                MOV     [DI].P_SIG_HANDLERS[BX], EAX
+                ASSUME  EDX:NOTHING
+;
+; Discard a pending signal when setting the handler to SIG_IGN or,
+; if the default action is ignoring the signal, to SIG_DFL.
+;
+                CMP     EAX, SIG_DFL
+                JE      SHORT SIGACT_DISCARD
+                CMP     EAX, SIG_IGN
+                JE      SHORT SIGACT_NO_DISCARD
+SIGACT_DISCARD: MOV     EAX, SIGA_SIGNO
+                BTR     [DI].P_SIG_PENDING, EAX
+SIGACT_NO_DISCARD:
+;
+; Store the previous action if OACT is not NULL
+;
+SIGACT_NO_INPUT:STI                             ; End of critical section
+                MOV     ESI, SIGA_OACT
+                TEST    ESI, ESI
+                JZ      SHORT SIGACT_NO_OUTPUT
+                ASSUME  ESI:NEAR32 PTR SIGACTION
+                MOV     EAX, SIGA_O_HANDLER
+                MOV     ES:[ESI].SA_HANDLER, EAX
+                MOV     EAX, SIGA_O_MASK
+                SHR     EAX, 1
+                MOV     ES:[ESI].SA_MASK, EAX
+                MOV     EAX, SIGA_O_FLAGS
+                MOV     ES:[ESI].SA_FLAGS, EAX
+                ASSUME  ESI:NOTHING
+SIGACT_NO_OUTPUT:
+                XOR     EAX, EAX
+SIGACT_RET:     MOV     SP, BP
+                POP     BP
+                RET
+
+SIGACT_ERROR_STI:
+                STI
+SIGACT_ERROR:   MOV     EAX, EINVAL
+                JMP     SIGACT_RET
+                ASSUME  DI:NOTHING
+DO_SIGACTION    ENDP
+
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Hook BIOS interrupt: 1BH (Ctrl-Break)
+; Hook DOS interrupts: 23H (Ctrl-C) and 24H (critical error)
+;
+                ASSUME  DS:SV_DATA
+HOOK_INT        PROC    NEAR
+                MOV     AL, 1BH                 ; Hook interrupt 1BH
+                LEA     DX, CNTRL_BREAK         ; (Ctrl-Break)
+                CALL    SET_RM_INT
+                MOV     OLD_BREAK_OFF, DX       ; Save old Ctrl-Break
+                MOV     OLD_BREAK_SEG, AX       ; handler vector
+                MOV     AL, 23H                 ; Hook interrupt 23H
+                LEA     DX, CNTRL_C             ; (Ctrl-C)
+                CALL    SET_RM_INT
+                MOV     AL, 24H                 ; Hook interrupt 24H
+                LEA     DX, CRIT_ERROR          ; (critical error)
+                CALL    SET_RM_INT
+                MOV     CS:OLD_CRIT_OFF, DX     ; Save old critical error
+                MOV     CS:OLD_CRIT_SEG, AX     ; handler vector
+                RET
+HOOK_INT        ENDP
+
+;
+; Remove interrupt hooks
+;
+                ASSUME  DS:SV_DATA
+CLEANUP_SIGNAL  PROC    NEAR
+                MOV     DX, OLD_BREAK_OFF
+                MOV     BX, OLD_BREAK_SEG
+                OR      BX, BX
+                JZ      SHORT CS_1
+                MOV     AL, 1BH
+                CALL    RESTORE_RM_INT
+CS_1:           RET
+CLEANUP_SIGNAL  ENDP
+
+
+;
+; Ctrl-Break interrupt
+;
+; This interrupt is issued by BIOS when Ctrl-Break is pressed.
+;
+; Note: INT 23H also raises SIGINT.  To avoid SIGINT being raised twice,
+;       CNTRL_BREAK returns instead of jumping to the original vector.
+;       This way, DOS doesn't get informed about Ctrl-Break.
+;
+                ASSUME  DS:NOTHING
+CNTRL_BREAK     PROC    FAR
+                CALL    LOCAL_STACK
+                PUSHAD
+                PUSH    DS                      ; Save all registers
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+;
+; Check for emergency exit (Ctrl-Break five times in one second)
+;
+                CMP     EMERGENCY_TIMER, 0      ; Timer running?
+                JE      SHORT CB_EMGCY_START    ; No  -> start timer
+                INC     EMERGENCY_COUNTER       ; Increment counter
+                CMP     EMERGENCY_COUNTER, 4    ; 5 Ctrl-Break in one second?
+                JNE     SHORT CB_EMGCY_DONE     ; No  -> skip
+                MOV     EMERGENCY_FLAG, NOT FALSE ; Yes -> set flag
+                JMP     SHORT CB_EMGCY_DONE
+
+CB_EMGCY_START: MOV     EMERGENCY_COUNTER, 0    ; Initialize counter
+                MOV     EMERGENCY_TIMER, 18     ; Set timer to one second
+CB_EMGCY_DONE:
+;
+; Generate SIGINT if appropriate
+;
+                MOV     BX, PROCESS_SIG         ; Get current process
+                CMP     BX, NO_PROCESS          ; In supervisor?
+                JE      SHORT CB_DONE           ; Yes -> ignore
+                ASSUME  BX:PTR PROCESS
+                BTS     [BX].P_SIG_PENDING, SIGINT ; Generate SIGINT
+CB_DONE:        POP     DS                      ; Restore registers
+                ASSUME  DS:NOTHING
+                POPAD
+                ASSUME  BX:NOTHING
+                CALL    RESTORE_STACK           ; Switch back to original stack
+                IRET                            ; Return
+CNTRL_BREAK     ENDP
+
+;
+; Ctrl-C interrupt
+;
+                ASSUME  DS:NOTHING
+CNTRL_C         PROC    FAR
+                CALL    LOCAL_STACK             ; Switch to local stack
+                PUSHAD
+                PUSH    DS                      ; Save all registers
+                PUSH    ES
+                PUSH    FS
+                PUSH    GS
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                CMP     CRIT_ERR_FLAG, FALSE    ; Critical error?
+                JNE     SHORT CC_QUIT           ; Yes -> just quit
+                MOV     BX, PROCESS_SIG         ; Get current process
+                CMP     BX, NO_PROCESS          ; In supervisor?
+                JE      SHORT CC_QUIT           ; Yes -> just quit
+                ASSUME  BX:PTR PROCESS
+                BTS     [BX].P_SIG_PENDING, SIGINT      ; Generate SIGINT
+                ASSUME  BX:NOTHING
+                POP     GS
+                POP     FS
+                POP     ES
+                POP     DS                      ; Restore registers
+                POPAD
+                NOP                             ; Avoid 386 bug
+                CALL    RESTORE_STACK           ; Switch back to original stack
+                IRET
+
+CC_QUIT:        CALL    CLEANUP                 ; Cleanup for exit
+                POP     GS
+                POP     FS
+                POP     ES
+                POP     DS                      ; Restore registers
+                POPAD
+                NOP                             ; Avoid 386 bug
+                CALL    RESTORE_STACK           ; Switch back to original stack
+                MOV     AX, 4C03H               ; End program, errorlevel 3
+                INT     21H
+                JMP     SHORT $                 ; Never reached
+CNTRL_C         ENDP
+
+
+
+OLD_CRIT        LABEL   DWORD
+OLD_CRIT_OFF    DW      ?
+OLD_CRIT_SEG    DW      ?
+
+;
+; Critical error handler
+;
+                ASSUME  DS:NOTHING
+CRIT_ERROR      PROC    FAR
+                PUSHF                           ; Call original handler
+                CALL    OLD_CRIT                ; (it's an interrupt routine)
+                CMP     AL, 2                   ; Abort the program?
+                JNE     SHORT CRIT_RET          ; No -> skip
+                CALL    LOCAL_STACK             ; Switch to local stack
+                PUSHAD                          ; Save registers
+                PUSH    DS
+                PUSH    ES
+                MOV     AX, SV_DATA
+                MOV     DS, AX                  ; Setup DS
+                ASSUME  DS:SV_DATA
+                MOV     CRIT_ERR_FLAG, NOT FALSE ; Avoid some DOS calls
+                CALL    CLEANUP                 ; Cleanup before return to DOS
+                LEA     DX, $ABORTED
+                MOV     AH, 09H                 ; Display message
+                INT     21H
+                POP     ES                      ; Restore registers
+                POP     DS
+                ASSUME  DS:NOTHING
+                POPAD
+                CALL    RESTORE_STACK           ; Switch to original stack
+CRIT_RET:       IRET                            ; Return
+CRIT_ERROR      ENDP
+
+;
+; This variable is located in the code segment to avoid having to
+; load segment registers
+;
+                TALIGN  2
+LSTACK_NO       DW      0                       ; No local stacks in use
+
+;
+; Switch to local stack
+;
+; Only flags altered
+;
+                ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING
+LOCAL_STACK     PROC    NEAR
+                CMP     LSTACK_NO, LSTACKS      ; Any stacks left?
+                JB      SHORT LSTACK1           ; Yes -> continue
+                MOV     AX, SV_DATA
+                MOV     DS, AX
+                ASSUME  DS:SV_DATA
+                LEA     DX, $STACKS             ; We're out of stacks
+                MOV     AH, 09H                 ; Display message
+                INT     21H
+                JMP     SHORT $                 ; Stop
+                ASSUME  DS:NOTHING
+
+LSTACK1:        PUSH    BX                      ; Save registers on original
+                PUSH    AX                      ; stack (will be moved to
+                PUSH    DS                      ; new stack)
+                PUSH    DX                      ; Save DX
+                INC     LSTACK_NO               ; One more used stack
+                MOV     AX, LSTACK_NO           ; Get stack number
+                MOV     DX, LSTACK_SIZE         ; Size of one stack
+                MUL     DX                      ; DX:AX := top of stack
+                MOV     BX, AX                  ; BX := top of stack
+                MOV     AX, LSTACK
+                MOV     DS, AX                  ; DS:BX points to top of stack
+                ASSUME  DS:LSTACK
+                POP     DX                      ; Restore DX
+                SUB     BX, 12                  ; Build stack frame
+                POP     WORD PTR [BX+0]         ; Move DS to new stack
+                POP     WORD PTR [BX+2]         ; Move AX to new stack
+                POP     WORD PTR [BX+4]         ; Move BX to new stack
+                POP     WORD PTR [BX+6]         ; Move return address
+                MOV     [BX+8], SP              ; Copy original SS:SP
+                MOV     [BX+10], SS             ; to new stack
+                MOV     SS, AX                  ; (Disables interrupts for:)
+                MOV     SP, BX                  ; Switch to new stack
+                POP     DS                      ; Restore registers
+                ASSUME  DS:NOTHING              ; from new stack
+                POP     AX
+                POP     BX
+                RET                             ; Return address from new stack
+LOCAL_STACK     ENDP
+
+
+;
+; Switch back to original stack
+;
+; Only flags altered
+;
+
+                ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING
+RESTORE_STACK   PROC    NEAR
+                PUSH    BP                      ; Save registers on local
+                PUSH    DS                      ; stack (will be moved to
+                PUSH    BX                      ; original stack)
+                DEC     LSTACK_NO               ; Adjust number of used stacks
+                MOV     BP, SP                  ; SS:SP points to local stack
+                LDS     BX, [BP+8]              ; Original stack
+                SUB     BX, 8                   ; Build stack frame
+                POP     WORD PTR [BX+0]         ; Move BX to original stack
+                POP     WORD PTR [BX+2]         ; Move DS to original stack
+                POP     WORD PTR [BX+4]         ; Move BP to original stack
+                POP     WORD PTR [BX+6]         ; Move return address
+                MOV     BP, DS                  ; Copy DS to SS
+                MOV     SS, BP                  ; (Disables interrupts for:)
+                MOV     SP, BX                  ; Switch to original stack
+                POP     BX                      ; Restore registers from
+                POP     DS                      ; original stack
+                POP     BP
+                RET
+RESTORE_STACK   ENDP
+
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/signal.inc
===================================================================
--- trunk/src/emx/src/dos/signal.inc	(revision 18)
+++ trunk/src/emx/src/dos/signal.inc	(revision 18)
@@ -0,0 +1,127 @@
+;
+; SIGNAL.INC --  Signal processing
+;
+; Copyright (c) 1991-1998 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; Cf. /emx/include/signal.h
+;
+SIGHUP    =      1                      ; Hangup
+SIGINT    =      2                      ; Interrupt (Ctrl-C)
+SIGQUIT   =      3                      ; Quit
+SIGILL    =      4                      ; Illegal instruction
+SIGTRAP   =      5                      ; Single step (debugging)
+SIGABRT   =      6                      ; abort ()
+SIGEMT    =      7                      ; ???
+SIGFPE    =      8                      ; Floating point
+SIGKILL   =      9                      ; Kill process
+SIGBUS    =     10                      ; ???
+SIGSEGV   =     11                      ; Segmentation fault
+SIGSYS    =     12                      ; Invalid argument to system call
+SIGPIPE   =     13                      ; Broken pipe
+SIGALRM   =     14                      ; Alarm
+SIGTERM   =     15                      ; Termination, process killed
+SIGUSR1   =     16                      ; User-defined signal #1
+SIGUSR2   =     17                      ; User-defined signal #2
+SIGCLD    =     18                      ; Death of a child process
+SIGBREAK  =     21                      ; Break (Ctrl-Break)
+SIGWINCH  =     28                      ; Window size change
+
+SIGNALS   =     29                      ; Signals 0..28
+
+;
+; Cf. /emx/include/signal.h
+;
+SIG_DFL   =     0                       ; Default handler
+SIG_IGN   =     1                       ; Ignore signal
+SIG_ACK   =     4                       ; Acknowledges receipt of a signal
+
+SIG_ERR   =     -1                      ; Return value of signal()
+
+SA_NOCLDSTOP    =       0001H           ; See POSIX.1
+SA_SYSV         =       0002H           ; Reset to SIG_DFL
+SA_ACK          =       0004H           ; Don't unblock automatically
+SA_TRAP         =       8000H           ; Signal generated by an exception
+
+SIG_BLOCK       =       1
+SIG_UNBLOCK     =       2
+SIG_SETMASK     =       3
+
+;
+; struct sigaction
+;
+SIGACTION       STRUC
+SA_HANDLER      DD      ?
+SA_MASK         DD      ?
+SA_FLAGS        DD      ?
+SIGACTION       ENDS
+
+;
+; Stack frame for signal handlers
+;
+SIGFRAME        STRUC
+SF_EIP          DD      ?
+SF_ARG          DD      ?
+SF_SIGNATURE    DD      ?
+SF_SIGNO        DD      ?
+SF_FLAGS        DD      ?
+SF_MASK         DD      ?
+SIGFRAME        ENDS
+
+SIG_BLOCK_MASK  =       NOT (1 SHL SIGKILL)
+
+SIG_SIGNATURE   =       9A003CFFH       ; See PMINT.ASM & EXCEPT.ASM for details
+SIG_EIP         =       -42             ; Beyond CS limit
+
+              IFNDEF __SIGNAL
+
+SV_DATA         SEGMENT
+
+                EXTRN   CRIT_ERR_FLAG:BYTE
+                EXTRN   SIG_CORE:BYTE           ; Signals which dump core
+                EXTRN   SIG_VALID:BYTE          ; Valid signal numbers
+                EXTRN   EMERGENCY_TIMER:BYTE    ; Timer for emergency exit
+                EXTRN   EMERGENCY_FLAG:BYTE     ; Flag for emergency exit
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   SIG_DELIVER_PENDING:NEAR ; Deliver pending signals
+                EXTRN   SIG_USER_CALL:NEAR      ; Invoke user signal handler
+                EXTRN   SIG_RETURN:NEAR         ; Return from signal handler
+                EXTRN   SIG_MSG:NEAR            ; Display "Stopped by ..."
+                EXTRN   DO_SIGNAL:NEAR          ; Implement __signal()
+                EXTRN   DO_SIGACTION:NEAR       ; Implement __sigaction()
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   HOOK_INT:NEAR           ; Hook interrupts
+                EXTRN   CLEANUP_SIGNAL:NEAR     ; Remove interrupt hooks
+
+INIT_CODE       ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/stat.inc
===================================================================
--- trunk/src/emx/src/dos/stat.inc	(revision 18)
+++ trunk/src/emx/src/dos/stat.inc	(revision 18)
@@ -0,0 +1,50 @@
+;
+; STAT.INC -- Assembler version of sys/stat.h
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+S_IREAD         =       0400Q                   ; Owner: read
+S_IWRITE        =       0200Q                   ; Owner: write
+S_IEXEC         =       0100Q                   ; Owner: exec
+
+S_IFMT          =       0160000Q                ; Mask for file type
+S_IFCHR         =       0020000Q                ; Character device
+S_IFDIR         =       0040000Q                ; Directory
+S_IFREG         =       0100000Q                ; Regular file
+S_IFSOCK        =       0140000Q                ; Socket (or pipe)
+
+STAT            STRUCT
+ST_DEV          DD      ?
+ST_INO          DD      ?
+ST_MODE         DD      ?
+ST_NLINK        DD      ?
+ST_UID          DD      ?
+ST_GID          DD      ?
+ST_RDEV         DD      ?
+ST_SIZE         DD      ?
+ST_ATIME        DD      ?
+ST_MTIME        DD      ?
+ST_CTIME        DD      ?
+ST_ATTR         DD      ?
+ST_RESERVED     DD      ?
+STAT            ENDS
Index: trunk/src/emx/src/dos/swapper.asm
===================================================================
--- trunk/src/emx/src/dos/swapper.asm	(revision 18)
+++ trunk/src/emx/src/dos/swapper.asm	(revision 18)
@@ -0,0 +1,902 @@
+;
+; SWAPPER.ASM -- Swap memory pages in and out
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE OPRINT.INC
+                INCLUDE EXCEPT.INC
+                INCLUDE PMIO.INC
+                INCLUDE PAGING.INC
+                INCLUDE MEMORY.INC
+                INCLUDE PMINT.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE TABLES.INC
+                INCLUDE DEBUG.INC
+
+                PUBLIC  SWAP_HANDLE, SWAP_FLAG, SNATCH_COUNT
+                PUBLIC  SWAP_FAULTS, SWAP_READS, SWAP_WRITES, SWAP_SIZE
+                PUBLIC  PAGE_FAULT, SWAP_OUT, INIT_SWAP, ALLOC_SWAP
+                PUBLIC  CLEANUP_SWAP, SET_TMP_DIR
+
+SER_FLAG        =       FALSE                   ; Don't use serial interface
+
+;
+; The page directory has two parts.  The first 1024 entries contain
+; the page directory entries as required by the 386.  The next 1024
+; entries are called the swap directory.  Each entry is either zero
+; (no swap  table) or contains the physical address of the swap table
+; associated with the page table.
+;
+; A swap table entry has the following format:
+;
+;  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12
+;  |---------------Page number in swap/exec file-------------|
+;
+;  11 10  09 08 07 06 05 04 03 02 01 00
+;   0 |A| |SRC| |----Process index----|
+;
+; Bits   Description
+; 0-7    This identifies the owner of the page:
+;          00H       not owned, not accessible
+;          FFH       (PIDX_SV) owned by supervisor
+;          other     process index of owner (cf. P_PIDX)
+; 8-9    This field tells where to get the page from:
+;          SRC_NONE  no source, just allocate (stack, for example)
+;          SRC_ZERO  zero fill (bss, for example)
+;          SRC_EXEC  executable file (code, for example)
+;          SRC_SWAP  swap file (modified data, for example)
+; 10     This bit is set if swap space is allocated to this page (SWAP_ALLOC)
+; 11     Currently not used
+; 12-31  Page number in executable/swap file, 0=not assigned
+;
+
+SV_DATA         SEGMENT
+
+SWAP_ROVER      DD      ?               ; Roving pointer for swapping out
+SNATCH_ROVER    DD      ?               ; Roving pointer for getting swap pages
+
+SWAP_FAULTS     DD      0               ; Number of page faults
+SWAP_READS      DD      0               ; Number of swap file reads
+SWAP_WRITES     DD      0               ; Number of swap file writes
+SNATCH_COUNT    DD      0               ; Number of swap pages snatched
+SWAP_SIZE       DD      0               ; Size of swap file
+
+;
+; Variables for SWAP_OUT
+;
+SO_SWAP_TABLE   DD      ?               ; Address of swap table
+
+SWAP_HANDLE     DW      NO_FILE_HANDLE  ; Handle of swap file
+SWAP_FLAG       DB      FALSE           ; Swapping enabled (initially off)
+DISK_FULL       DB      FALSE           ; Disk full while expanding swap file
+
+
+              IF DEBUG_SWAP
+$PF1            DB      "Page fault, SRC=", 0
+$PF2            DB      CR, LF, "Address=", 0
+$PF3            DB      CR, LF, 0
+$SRC_NONE       DB      "NONE", 0
+$SRC_ZERO       DB      "ZERO", 0
+$SRC_EXEC       DB      "EXEC", 0
+$SRC_SWAP       DB      "SWAP", 0
+$SWAP_EXEC      DB      "File position=", 0
+              ENDIF
+
+$SWAP_OUT_OF_MEM        DB      "Out of memory or swap space", CR, LF, 0
+$SWAP_ERROR     DB      "Swap file I/O error", CR, LF, 0
+$SWAP_CREATE    DB      "Cannot create swap file", CR, LF, 0
+$SWAP_SPACE     DB      "Out of swap space", CR, LF, 0
+
+SWAP_FNAME      DB      64+1+13 DUP (?)
+
+ZERO_BYTE       DB      0
+
+SV_DATA         ENDS
+
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+                .386P
+
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+PAGE_FAULT      PROC    NEAR
+              IF SER_FLAG
+                SERIAL  "P"
+              ENDIF
+                MOV     EAX, CR2                ; Get linear address of fault
+                STI                             ; Be venturous
+;
+; Protected-mode interrupt routines must not cause a page fault!
+; Protected-mode interrupt routines must not issue INT 21H (buffer)!
+; Protected-mode interrupt routines must not access the page tables!
+;
+                MOV     FAULT_ADDR, EAX
+                TEST    I_ERRCD, PAGE_PRESENT   ; Caused by not-present page?
+                JNZ     DUMP                    ; No  -> dump
+                CMP     EAX, LIN_START          ; Address valid?
+                JB      DUMP                    ; No -> dump
+                MOV     BX, G_PAGEDIR_SEL
+                MOV     ES, BX
+                MOV     BX, G_PHYS_SEL
+                MOV     FS, BX                  ; Setup physical addressing
+                SHR     EAX, 22                 ; Compute page directory index
+                MOV     ESI, ES:[4*EAX+0]       ; Get page directory entry
+                MOV     EDI, ES:[4*EAX+4096]    ; Get swap directory entry
+                TEST    ESI, PAGE_PRESENT       ; Page table present?
+                JZ      DUMP                    ; No -> dump
+                OR      EDI, EDI                ; Is the swap table present?
+                JZ      DUMP                    ; No -> dump
+                AND     ESI, NOT 0FFFH          ; Page table address
+                MOV     EAX, FAULT_ADDR         ; Get linear address of fault
+                SHR     EAX, 12
+                AND     EAX, 03FFH              ; Page table index
+                LEA     ESI, [ESI+4*EAX]        ; Address of page table entry
+                LEA     EDI, [EDI+4*EAX]        ; Address of swap table entry
+                MOV     EAX, FS:[EDI]           ; Get swap table entry
+                MOV     SWAP_PIDX, AL           ; Save PIDX
+                CMP     AL, PIDX_SV             ; Supervisor page?
+                JE      SHORT PF_PIDX_OK        ; Yes -> ok
+                CMP     AL, 01H                 ; PIDX >= 1?
+                JB      DUMP
+                CMP     AL, MAX_PROCESSES       ; PIDX <= MAX_PROCESSES?
+                JA      DUMP
+PF_PIDX_OK:     MOV     AX, BUF_SEG             ; Current buffer segment
+                MOV     BX, BUF2_SEG            ; Segment of swapper buffer
+                CMP     AX, BX                  ; Already in swapper?
+                JE      DUMP                    ; Yes -> dump
+                MOV     BUF_SEG, BX             ; Switch to swapper buffer
+                MOV     BUF_SEL, G_BUF2_SEL
+;
+; Don't jump to DUMP from here on, BUF_SEG and BUF_SEL changed!
+;
+                CALL    GET_PROC                ; Get process table entry
+                MOV     FAULT_PROC, BX          ; Save process pointer
+                OR      BX, BX                  ; Supervisor?
+                JZ      SHORT PF_SV_1           ; Yes -> skip
+                INC     (PROCESS PTR [BX]).P_PAGE_FAULTS ; Process' counter
+PF_SV_1:        INC     SWAP_FAULTS             ; Totals counter
+              IF DEBUG_SWAP
+                CMP     DEBUG_FLAG, FALSE
+                JE      SHORT PF_02
+                LEA     EDX, $PF1
+                CALL    OTEXT
+                MOV     EAX, FS:[EDI]           ; Get swap table entry
+                AND     AX, SRC_MASK
+                LEA     EDX, $SRC_ZERO
+                CMP     AX, SRC_ZERO
+                JE      SHORT PF_01
+                LEA     EDX, $SRC_EXEC
+                CMP     AX, SRC_EXEC
+                JE      SHORT PF_01
+                LEA     EDX, $SRC_SWAP
+                CMP     AX, SRC_SWAP
+                JE      SHORT PF_01
+                LEA     EDX, $SRC_NONE
+PF_01:          CALL    OTEXT
+                LEA     EDX, $PF2
+                CALL    OTEXT
+                MOV     EAX, FAULT_ADDR
+                CALL    ODWORD
+                LEA     EDX, $PF3
+                CALL    OTEXT
+PF_02:
+              ENDIF
+                MOV     EAX, FS:[ESI]           ; Get page table entry
+                TEST    AX, PAGE_ALLOC          ; Memory allocated?
+                JZ      SHORT PF_ALLOC          ; No  -> allocate memory
+                AND     EAX, NOT 0FFFH          ; Extract address
+                JMP     SHORT PF_USE
+PF_ALLOC:       CALL    PM_ALLOC                ; Allocate a page (swap out)
+                CMP     EAX, NULL_PHYS          ; Failure?
+                JE      SWAP_OUT_OF_MEM         ; Yes -> error
+PF_USE:         MOV     EDX, EAX                ; Save physical address
+                MOV     EAX, FS:[ESI]           ; Page table entry
+                AND     EAX, PAGE_CLEAR         ; Clear address, P, D, A
+                OR      EAX, EDX                ; Insert phyiscal address
+                OR      AX, PAGE_PRESENT OR PAGE_ALLOC ; Page present
+                MOV     FS:[ESI], EAX           ; Store page table entry
+                CALL    CLEAR_TLB               ; Clear TLB
+                AND     EAX, NOT 0FFFH          ; Extract physical address
+                MOV     EDX, FS:[EDI]           ; Get swap table entry
+                CALL    LOAD_PAGE               ; Initialize the page
+                AND     WORD PTR FS:[ESI], NOT PAGE_DIRTY
+                CALL    CLEAR_TLB
+PF_DONE:
+              IF STOP_SWAP AND DEBUG_SWAP
+                MOV     AH, 01H
+                INT     21H
+              ENDIF
+                MOV     AX, BUF1_SEG            ; Switch back to main buffer
+                MOV     BUF_SEG, AX
+                MOV     BUF_SEL, G_BUF1_SEL
+              IF SER_FLAG
+                SERIAL  "p"
+              ENDIF
+                JMP     EXCEPT_RET
+
+;
+; Error while accessing swap file
+;
+SWAP_ERROR::    LEA     EDX, $SWAP_ERROR
+                CALL    OTEXT
+                MOV     AX, 4CFFH
+                INT     21H
+                JMP     $
+
+;
+; Cannot find a memory page for swapping in requested page
+;
+SWAP_OUT_OF_MEM:
+                LEA     EDX, $SWAP_OUT_OF_MEM
+                CALL    OTEXT
+                MOV     AX, 4CFFH
+                INT     21H
+                JMP     $
+
+DUMP:           CLI
+                RET
+
+                ASSUME  BP:NOTHING
+PAGE_FAULT      ENDP
+
+
+
+;
+; Initialize a page in physical memory.
+;
+; This procedure fills the page with zeros, loads the page from the
+; exec file, loads the page from the swap file or does nothing
+; (stack pages).
+;
+; In:  EAX      Physical address
+;      EDX      Swap table entry
+;
+LOAD_PAGE       PROC    NEAR
+                PUSH    ES                      ; Save registers
+                PUSH    EAX
+                PUSH    EBX
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    EDI
+                MOV     EDI, EAX                ; EDI := physical address
+                MOV     AX, DX
+                AND     AX, SRC_MASK            ; Get type of source
+                CMP     AX, SRC_NONE            ; No source (stack)?
+                JE      LP_NONE                 ; Yes -> done
+                CMP     AX, SRC_ZERO            ; Zero-filled (bss)?
+                JE      LP_ZERO                 ; Yes -> fill
+                CMP     AX, SRC_EXEC            ; From exec file?
+                JE      SHORT LP_EXEC           ; Yes -> read from exec file
+;
+; Read from swap file
+;
+LP_SWAP:        INC     SWAP_READS              ; Update statistics
+                AND     EDX, NOT 0FFFH          ; Extract address
+                MOV     BX, SWAP_HANDLE         ; Handle of swap file
+                MOV     ECX, 4096               ; Read one page
+                JMP     SHORT LP_READ           ; (EDX is address in file)
+
+;
+; Fill page with zeros
+;
+LP_ZERO:        MOV     BX, G_PHYS_SEL
+                MOV     ES, BX
+                MOV     ECX, 1024
+                XOR     EAX, EAX
+                CLD
+                REP     STOS DWORD PTR ES:[EDI]
+                JMP     LP_RET                  ; Done
+
+;
+; Read from exec file
+;
+LP_EXEC:
+              IF DEBUG_SWAP
+                CMP     DEBUG_FLAG, FALSE
+                JE      SHORT LP_EXEC_1
+                LEA     EDX, $SWAP_EXEC
+                CALL    OTEXT
+                MOV     EAX, FS:[EDI]
+                AND     EAX, NOT 0FFFH
+                CALL    ODWORD
+                CALL    OCRLF
+LP_EXEC_1:
+              ENDIF
+                MOV     BX, FAULT_PROC
+                OR      BX, BX                  ; Supervisor (cannot happen)?
+                JZ      SWAP_ERROR              ; Yes -> impossible (wrong msg)
+                ASSUME  BX:PTR PROCESS
+                TEST    [BX].P_FLAGS, PF_PRELOADING     ; Preloading?
+                JNZ     SHORT LP_ZERO           ; Yes -> zero page
+                AND     EDX, NOT 0FFFH          ; Extract address
+                MOV     ECX, 4096
+                MOV     EAX, [BX].P_LAST_PAGE
+                OR      EAX, EAX                ; Incomplete last page?
+                JZ      SHORT LP_EXEC_2         ; No -> skip
+                SHL     EAX, 12
+                CMP     EDX, EAX                ; On last page?
+                JNE     SHORT LP_EXEC_2         ; No  -> skip
+                MOVZX   ECX, [BX].P_LAST_BYTES  ; Adjust number of bytes
+LP_EXEC_2:      MOV     EAX, [BX].P_SYM_PAGE
+                SHL     EAX, 12
+                CMP     EDX, EAX                ; Symbol table page?
+                JB      SHORT LP_EXEC_3         ; No  -> skip
+                ADD     EDX, [BX].P_RELOC_SIZE  ; Adjust page address
+LP_EXEC_3:      ADD     EDX, [BX].P_EXEC_OFFSET ; Compute address in file
+                MOV     BX, [BX].P_EXEC_HANDLE  ; Get handle of exec file
+                ASSUME  BX:NOTHING
+;
+; Load page from a file (BX=handle, EDX=address)
+;
+LP_READ:        CALL    SEEK                    ; Move file pointer
+                JC      SWAP_ERROR              ; Error -> abort
+                MOV     EDX, EDI
+                MOV     AX, G_PHYS_SEL          ; Read page from file
+                CALL    READ                    ; into physical memory
+                JC      SWAP_ERROR              ; Error -> abort
+                JNZ     SWAP_ERROR              ; Error -> abort
+                ADD     EDI, ECX                ; Compute end address
+                SUB     ECX, 4096               ; Number of remaining bytes
+                JE      SHORT LP_RET            ; Complete page -> done
+                MOV     AX, G_PHYS_SEL
+                MOV     ES, AX                  ; Zero rest of page
+                NEG     ECX                     ; Number of remaining bytes
+                XOR     AL, AL
+                CLD
+                REP     STOS BYTE PTR ES:[EDI]
+LP_NONE:
+LP_RET:         POP     EDI                     ; Restore registers
+                POP     EDX
+                POP     ECX
+                POP     EBX
+                POP     EAX
+                POP     ES
+                RET
+LOAD_PAGE       ENDP
+
+;
+; Get process table entry for process index
+;
+; In:   SS:BP   Exception stack frame with
+;               SWAP_PIDX = process index
+;
+; Out:  BX      Pointer to process table entry or
+;               0000H supervisor page
+;
+GET_PROC        PROC    NEAR
+                MOVZX   BX, SWAP_PIDX           ; Get process index
+                CMP     BL, PIDX_SV             ; Supervisor?
+                JE      SHORT GET_PROC_SV       ; Yes -> return 0
+                DEC     BX                      ; Now zero based
+                IMUL    BX, SIZE PROCESS        ; Compute offset
+                LEA     BX, PROCESS_TABLE[BX]   ; Compute address
+                RET
+GET_PROC_SV:    XOR     BX, BX                  ; Return 0 (supervisor)
+                RET
+GET_PROC        ENDP
+
+;
+; Initialize the swap file bitmap. Attention: this causes page
+; faults!
+;
+INIT_SWAP       PROC    NEAR
+                MOV     ECX, 4096               ; Bitmap size: 4096 bytes
+                LEA     SI, G_SWAP_BMP_DESC     ; Bitmap segment descriptor
+                CALL    SV_SEGMENT              ; Create segment
+                JC      SHORT IS_RET            ; Out of memory -> don't swap
+                MOV     AX, G_SWAP_BMP_SEL
+                MOV     ES, AX
+                XOR     DI, DI
+                MOV     ECX, 4096 / 4
+                XOR     EAX, EAX
+                NOT     EAX                     ; All pages free
+                CLD
+                REP     STOS DWORD PTR ES:[DI]
+                MOV     SWAP_FLAG, NOT FALSE
+                MOV     EAX, LIN_START
+                MOV     SWAP_ROVER, EAX
+                MOV     SNATCH_ROVER, EAX
+IS_RET:         RET
+INIT_SWAP       ENDP
+
+
+;
+; Return (in EAX) the physical address of the swapped-out page
+; or NULL_PHYS if out of memory.
+;
+; (This code cannot handle swapping of page-tables (TLB!!!))
+;
+; Note: If SWAP_ROVER equals LIN_START and there are no pages present,
+;       this code makes one superfluous, benign pass.
+;
+
+                ASSUME  DS:SV_DATA
+SWAP_OUT        PROC    NEAR
+                CMP     SWAP_FLAG, FALSE        ; Swapping enabled?
+                JNE     SHORT SO_1              ; Yes -> throw out a page
+                MOV     EAX, NULL_PHYS          ; Out of memory
+                RET
+
+SO_1:           PUSH    ES                      ; Save registers
+                PUSH    FS
+                PUSH    EBX
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    ESI
+                PUSH    EDI
+                PUSH    EBP
+                MOV     AX, G_PAGEDIR_SEL
+                MOV     FS, AX
+                MOV     AX, G_PHYS_SEL
+                MOV     ES, AX
+                MOV     EDI, SWAP_ROVER
+                MOV     BP, 0                   ; Count number of rounds
+SO_LOOP1:       MOV     EAX, EDI                ; Rover
+                SHR     EAX, 22                 ; Compute page directory index
+                MOV     EBX, FS:[4*EAX]         ; Get page directory entry
+                TEST    EBX, PAGE_PRESENT       ; Page table present?
+                JZ      SHORT SO_NTBL0          ; No -> skip to next table
+                MOV     EAX, FS:[4*EAX+4096]    ; Address of swap table
+                OR      EAX, EAX                ; Does it exist?
+                JZ      SHORT SO_NTBL0          ; No -> skip to next table
+                MOV     SO_SWAP_TABLE, EAX      ; Save address
+                AND     EBX, NOT 0FFFH          ; Address of page table
+                MOV     EAX, EDI                ; Compute page table index
+                SHR     EAX, 12
+                AND     EAX, 03FFH              ; EAX := page table index
+                LEA     ESI, [EBX+4*EAX]        ; Address of page table entry
+                MOV     ECX, 1024
+                SUB     ECX, EAX                ; Number of remaining entries
+                TALIGN  4
+SO_LOOP2:       MOV     EAX, ES:[ESI]           ; Get page table entry
+                TEST    AX, PAGE_ALLOC          ; Memory allocated?
+                JZ      SHORT SO_NEXT           ; No -> skip
+;
+; We use only pages that are swappable and were not accessed since
+; the last round.
+;
+                TEST    AX, PAGE_ACCESSED OR PAGE_LOCKED    ; Both bits zero?
+                JZ      SHORT SO_USE            ; Yes -> use this page
+                TEST    AX, PAGE_LOCKED         ; Page locked?
+                JNZ     SHORT SO_NEXT           ; Yes -> skip
+                AND     AL, NOT PAGE_ACCESSED   ; Clear accessed bit
+                MOV     ES:[ESI], AL            ; Update page table entry
+                TALIGN  4
+SO_NEXT:        ADD     ESI, 4                  ; Next entry
+                ADD     EDI, 4096
+                LOOP    SO_LOOP2                ; All page table entries
+                JMP     SHORT SO_NTBL1          ; Next page table
+;
+; Skip to next page table
+;
+SO_NTBL0:       AND     EDI, NOT ((1 SHL 22) - 1)   ; First page table entry
+                ADD     EDI, 1 SHL 22           ; Next page table
+SO_NTBL1:       OR      EDI, EDI                ; End of virtual memory?
+                JNZ     SHORT SO_NTBL2          ; No -> continue
+                MOV     EDI, LIN_START          ; Restart from beginning
+                CMP     BP, 2                   ; Up to 2 rounds allowed
+                JAE     SHORT SO_LOOSE          ; More -> failure
+                INC     BP                      ; Increment counter
+SO_NTBL2:       JMP     SO_LOOP1
+
+SO_LOOSE:       MOV     EAX, NULL_PHYS          ; No pages found, sorry
+                JMP     SO_RET
+
+;
+; Recycle this page
+;
+; If the page is dirty and the SWAP_ALLOC bit is not set, allocate a
+; swap page.  If the page is dirty, write the page to the swap page.
+; Recycle the memory page by returning the address of the page.
+; 
+                TALIGN  2
+SO_USE:         MOV     SWAP_ROVER, EDI
+                SUB     EBX, ESI
+                NEG     EBX                     ; Offset
+                ADD     EBX, SO_SWAP_TABLE      ; Address of swap table entry
+                TEST    AL, PAGE_DIRTY          ; Dirty page?
+                JZ      SO_RECYCLE              ; No -> just discard
+;
+; The page is present and dirty.  Write it to the swap file.
+;
+                MOV     EAX, ES:[EBX]           ; Get swap table entry
+                TEST    AX, SWAP_ALLOC          ; Swap space allocated?
+                JZ      SHORT SO_ALLOC          ; No  -> allocate swap space
+                MOV     EDX, EAX                ; Copy it (address!)
+                AND     AX, NOT SRC_MASK        ; Clear SRC field
+                OR      AX, SRC_SWAP            ; Reload page from swap file
+                AND     EDX, NOT 0FFFH          ; Extract page address
+                JMP     SHORT SO_WRITE          ; Write the page
+
+SO_ALLOC:       CALL    ALLOC_SWAP              ; Allocate a page in swap file
+                JC      OUT_OF_SWAP_SPACE       ; Out of swap space
+                MOV     EDX, EAX                ; Address to EDX
+                MOV     EAX, ES:[EBX]           ; Get swap table entry
+                AND     EAX, 0FFFH AND NOT SRC_MASK ; Clear address & SRC field
+                OR      EAX, EDX                ; Insert address into entry
+                OR      AX, SRC_SWAP OR SWAP_ALLOC ; Reload page from swap file
+SO_WRITE:       MOV     ES:[EBX], EAX           ; Update swap table entry
+                PUSH    EBX
+                MOV     BX, SWAP_HANDLE         ; Handle of swap file
+                CALL    SEEK                    ; Set file pointer to page
+                POP     EBX                     ; (address in EDX)
+                JC      SWAP_ERROR              ; Error -> abort
+                INC     SWAP_WRITES             ; Update statistics
+                MOV     EDX, ES:[ESI]           ; Get physical address of
+                AND     EDX, NOT 0FFFH          ; the page
+                MOV     AX, G_PHYS_SEL          ; Write the page to the
+                MOV     ECX, 4096               ; swap file
+                PUSH    EBX
+                MOV     BX, SWAP_HANDLE         ; Handle of swap file
+                CALL    WRITE
+                POP     EBX
+                JC      SWAP_ERROR              ; Error -> abort
+                JNZ     SWAP_ERROR              ; disk full (cannot happen)
+;
+; Recycle the physical memory page.
+;
+SO_RECYCLE:     MOV     EAX, ES:[ESI]           ; Get page table entry
+                MOV     ECX, EAX                ; Copy it
+                AND     ECX, PAGE_CLEAR         ; Clear address, P, D, A
+                AND     CX, NOT PAGE_ALLOC      ; Clear PAGE_ALLOC
+SO_DONE:        MOV     ES:[ESI], ECX           ; Update the page table
+                AND     EAX, NOT 0FFFH          ; Extract address (ret value)
+                CALL    CLEAR_TLB               ; Clear the TLB
+SO_RET:         POP     EBP                     ; Restore registers
+                POP     EDI
+                POP     ESI
+                POP     EDX
+                POP     ECX
+                POP     EBX
+                POP     FS
+                POP     ES
+                RET
+
+;
+; Out of swap space.  Display message and abort.
+;
+OUT_OF_SWAP_SPACE:
+                LEA     EDX, $SWAP_SPACE
+                CALL    OTEXT
+                MOV     AX, 4CFFH
+                INT     21H
+                JMP     $
+SWAP_OUT        ENDP
+
+;
+; Try to get a swap page by snatching the swap page of a present page
+; which has swap space allocated.  This must not be done if PF_COMMIT
+; is set.  The swap page stays marked as used!
+;
+; As SWAP_OUT calls SWAP_ALLOC only if swap space is not allocated,
+; and PAGE_FAULT calls PM_ALLOC only if the page is not pressent,
+; there is no danger of snatching the swap space of the page currently
+; operated on.
+;
+; Out: EAX      External address of page (if NC), a multiple of 4096
+;      CY       Error (no page available)
+;
+
+                ASSUME  DS:SV_DATA
+SNATCH_SWAP     PROC    NEAR
+                PUSH    ES                      ; Save registers
+                PUSH    FS
+                PUSH    EBX
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    ESI
+                PUSH    EDI
+                PUSH    EBP
+                MOV     AX, G_PAGEDIR_SEL
+                MOV     FS, AX
+                MOV     AX, G_PHYS_SEL
+                MOV     ES, AX
+                MOV     EDI, SNATCH_ROVER
+                MOV     BP, 0
+SS_LOOP1:       MOV     EAX, EDI                ; Rover
+                SHR     EAX, 22                 ; Compute page directory index
+                MOV     EBX, FS:[4*EAX+0]       ; Get page directory entry
+                TEST    EBX, PAGE_PRESENT       ; Page table present?
+                JZ      SHORT SS_NTBL0          ; No -> skip to next table
+                MOV     ESI, FS:[4*EAX+4096]    ; Address of swap table
+                OR      ESI, ESI                ; Does it exist?
+                JZ      SHORT SS_NTBL0          ; No -> skip to next table
+                AND     EBX, NOT 0FFFH          ; Address of page table
+                MOV     EAX, EDI                ; Compute page table index
+                SHR     EAX, 12
+                AND     EAX, 03FFH              ; EAX := page table index
+                MOV     ECX, 1024
+                SUB     ECX, EAX                ; Number of remaining entries
+                TALIGN  4
+SS_LOOP2:       TEST    WORD PTR ES:[EBX+4*EAX], PAGE_ALLOC ; Memory allocated?
+                JZ      SHORT SS_NEXT           ; No  -> skip
+                TEST    WORD PTR ES:[ESI+4*EAX], SWAP_ALLOC ; Swap space?
+                JNZ     SHORT SS_USE            ; Yes -> use this page
+SS_NEXT:        INC     EAX                     ; Next entry
+                ADD     EDI, 4096
+                CMP     EDI, SNATCH_ROVER       ; All pages examined?
+                JE      SHORT SS_FAIL           ; Yes -> no page found
+                LOOP    SS_LOOP2                ; All page table entries
+                JMP     SHORT SS_NTBL1          ; Next page table
+;
+; Skip to next page table
+;
+SS_NTBL0:       AND     EDI, NOT ((1 SHL 22) - 1)   ; First page table entry
+                ADD     EDI, 1 SHL 22           ; Next page table
+SS_NTBL1:       OR      EDI, EDI                ; End of virtual memory?
+                JNZ     SHORT SS_NTBL2          ; No -> continue
+                MOV     EDI, LIN_START          ; Restart from beginning
+                INC     BP                      ; In case SNATCH_ROVER points
+                CMP     BP, 2                   ; into a not-present page table
+                JAE     SHORT SS_FAIL           ; stop after 2 loops
+SS_NTBL2:       JMP     SS_LOOP1
+
+SS_FAIL:        XOR     EAX, EAX
+                STC                             ; No pages found
+                JMP     SS_RET
+
+;
+; Use the swap space of this page.  This is done by marking the
+; page as dirty, clearing the SWAP_ALLOC bit and returning the
+; address of the swap page.
+;
+                TALIGN  2
+SS_USE:         MOV     SNATCH_ROVER, EDI
+                INC     SNATCH_COUNT            ; Update statistics
+                OR      BYTE PTR ES:[EBX+4*EAX], PAGE_DIRTY
+                LEA     EDI, [ESI+4*EAX]
+                MOV     EDX, ES:[EDI]           ; Get swap table entry
+                MOV     EAX, EDX
+                AND     EAX, 0FFFH AND NOT SWAP_ALLOC
+                MOV     ES:[EDI], EAX
+                MOV     EAX, EDX
+                AND     EAX, NOT 0FFFH          ; Also clears CY flag
+                CALL    CLEAR_TLB               ; Clear the TLB (dirty bit!)
+SS_RET:         POP     EBP                     ; Restore registers
+                POP     EDI
+                POP     ESI
+                POP     EDX
+                POP     ECX
+                POP     EBX
+                POP     FS
+                POP     ES
+                RET
+SNATCH_SWAP     ENDP
+
+
+;
+; Open swap file
+;
+SWAP_OPEN       PROC    NEAR
+                CMP     SWAP_HANDLE, NO_FILE_HANDLE
+                JNE     SHORT SOP_9             ; Already open -> skip
+                PUSH    EAX
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    ESI
+                PUSH    EDI
+                PUSH    ES
+                MOV     AX, DS
+                LEA     EDX, SWAP_FNAME
+                CALL    CREATE_TMP              ; Create temporary file
+                JC      SHORT SOP_ERROR         ; Error -> abort
+                MOV     SWAP_HANDLE, AX         ; Save file handle
+                POP     ES
+                POP     EDI
+                POP     ESI
+                POP     EDX
+                POP     ECX
+                POP     EAX
+SOP_9:          RET
+
+SOP_ERROR:      LEA     EDX, $SWAP_CREATE
+                CALL    OTEXT
+                MOV     AX, 4CFFH
+                INT     21H
+                JMP     $
+
+SWAP_OPEN       ENDP
+
+;
+; Allocate a page in the swap file.
+;
+; 1. Create the swap file if it hasn't been opened yet.
+;
+; 2. Use a bitmap to locate a free page.  If there is no page
+;    available, return with CY set (error; this happens if the size
+;    of the swap file exceeds 128 MB).
+;
+; 3. If the page is beyond the current end of the swap file
+;    (taken from the SWAP_SIZE variable) expand the swap file.
+;    If this succeeds, update the SWAP_SIZE variable.  If expanding
+;    the swap file fails, try to snatch a swap page.  If this fails,
+;    return with CY set (error).  Expanding the swap file is not tried
+;    if DISK_FULL is set (which is set if expanding the swap file
+;    fails).  If snatching a swap page fails, DISK_FULL is cleared
+;    and ALLOC_SWAP tries again to expand the swap file.
+; 
+; 4. Mark the page as used, clear CY (success) and return the page
+;    address.
+;
+; Out: EAX      External address of page (if NC), a multiple of 4096
+;      CY       Error
+;
+ALLOC_SWAP      PROC    NEAR
+                PUSH    ES                      ; Save registers
+                PUSH    EBX
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    EDI
+                CALL    SWAP_OPEN               ; Open swap file
+                MOV     AX, G_SWAP_BMP_SEL
+                MOV     ES, AX                  ; Access bitmap
+                XOR     EDI, EDI                ; Scan bitmap for a
+                MOV     ECX, 4096 / 4           ; DWORD with at least
+                XOR     EAX, EAX                ; one bit set
+                CLD
+                REPE    SCAS DWORD PTR ES:[EDI]
+                JE      SHORT AS_FAIL           ; All pages in use -> fail
+                SUB     EDI, 4                  ; Address of DWORD
+                BSF     EAX, DWORD PTR ES:[EDI] ; Find bit in DWORD
+                JZ      SHORT $                 ; Cannot happen
+                SHL     EDI, 3                  ; 8 bits per bytes
+                ADD     EDI, EAX                ; Compute page number
+                SHL     EDI, 12                 ; Convert to page address
+                LEA     EAX, [EDI+4096]         ; End of page
+                CMP     EAX, SWAP_SIZE          ; Grow swap file?
+                JBE     SHORT AS_OK             ; No  -> skip
+                CMP     DISK_FULL, FALSE        ; Disk full?
+                JNE     SHORT AS_SNATCH         ; Yes -> don't try to grow file
+                CALL    GROW_SWAP               ; Grow the swap file
+                JNC     SHORT AS_OK             ; Success -> done
+                CALL    SNATCH_SWAP             ; Try to snatch a swap page
+                JNC     SHORT AS_RET            ; Success -> done
+                JMP     SHORT AS_FAIL           ; Error
+
+AS_OK:          MOV     EAX, EDI                ; Return page address in EAX
+                SHR     EDI, 12                 ; Compute bit number
+                BTR     ES:[0], EDI             ; Mark page as used
+                JNC     SHORT $                 ; Must not happen
+                CLC
+AS_RET:         POP     EDI                     ; Restore registers
+                POP     EDX
+                POP     ECX
+                POP     EBX
+                POP     ES
+                RET
+
+AS_SNATCH:      CALL    SNATCH_SWAP             ; Try to snatch a swap page
+                JNC     AS_RET                  ; Success -> use this page
+                MOV     DISK_FULL, FALSE        ; Try again to grow swap file
+                LEA     EAX, [EDI+4096]         ; New file size
+                CALL    GROW_SWAP               ; Disk full?
+                JNC     SHORT AS_RET            ; No  -> success
+AS_FAIL:        XOR     EAX, EAX                ; Set constant return value
+                STC                             ; Error
+                JMP     SHORT AS_RET
+
+ALLOC_SWAP      ENDP
+
+
+;
+; Grow the swap file
+;
+; In:  EAX      New size
+;
+; Out: CY       Disk full
+;
+GROW_SWAP       PROC    NEAR
+                PUSH    EAX                     ; Save registers
+                PUSH    EBX
+                PUSH    ECX
+                PUSH    EDX
+                PUSH    EAX                     ; Save size
+                MOV     EDX, EAX                ; New size of swap file
+                DEC     EDX                     ; Address of (new) last byte
+                MOV     BX, SWAP_HANDLE         ; Handle of swap file
+                CALL    SEEK                    ; Set file pointer to last byte
+                JC      SWAP_ERROR              ; Error -> abort
+                MOV     AX, DS                  ; Write a byte just before the
+                LEA     EDX, ZERO_BYTE          ; (new) end of the file
+                MOV     ECX, 1                  ; (ECX=0 never fails!)
+                CALL    WRITE                   ; Call INT 21H, function 40H
+                JC      SWAP_ERROR              ; Error -> abort
+                POP     EAX                     ; Restore size
+                JNE     SHORT GS_FAIL
+                MOV     SWAP_SIZE, EAX          ; Update variable (file size)
+                CLC                             ; Success
+                JMP     SHORT GS_RET
+
+GS_FAIL:        MOV     DISK_FULL, NOT FALSE    ; Set flag
+                STC                             ; Failure
+GS_RET:         POP     EDX
+                POP     ECX
+                POP     EBX
+                POP     EAX
+                RET
+GROW_SWAP       ENDP
+
+SV_CODE         ENDS
+
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Set directory for temporary file
+;
+; In:   DI=0    EMXTMP and TMP not set
+;       ES:DI   Pointer to value of EMXTMP (or TMP)
+;
+                ASSUME  DS:SV_DATA
+SET_TMP_DIR     PROC    NEAR
+                OR      DI, DI                  ; EMXTMP or TMP set?
+                JZ      SHORT STD_DEFAULT       ; No -> use \
+                LEA     BX, SWAP_FNAME          ; Copy value to SWAP_FNAME
+                MOV     CX, 64                  ; Copy up to 64 bytes
+STD_1:          MOV     AL, ES:[DI]             ; Fetch byte from environment
+                MOV     [BX], AL                ; Store to SWAP_FNAME
+                INC     DI
+                INC     BX
+                OR      AL, AL                  ; End reached?
+                JZ      SHORT STD_RET           ; Yes -> ok
+                LOOP    STD_1                   ; Repeat
+STD_DEFAULT:    MOV     SWAP_FNAME[0], "\"      ; Use \ if EMXTMP/TMP not set
+                MOV     SWAP_FNAME[1], 0        ; or if the value is too long
+STD_RET:        RET
+SET_TMP_DIR     ENDP
+
+
+;
+; Close and delete the swap file if it has been created.
+; If called from critical error handler, this should not be done.
+;
+                ASSUME  DS:SV_DATA
+CLEANUP_SWAP    PROC    NEAR
+                MOV     BX, NO_FILE_HANDLE      ; Get handle of swap file
+                XCHG    BX, SWAP_HANDLE         ; and mark the file as closed
+                CMP     BX, NO_FILE_HANDLE      ; Swap file created?
+                JE      SHORT CUW_RET           ; No -> done
+                CMP     CRIT_ERR_FLAG, FALSE    ; Critical error?
+                JNE     SHORT CUW_RET           ; Yes -> skip
+                MOV     AH, 3EH
+                INT     21H                     ; Close swap file
+                JC      SHORT CUW_RET           ; Error -> do not delete
+                LEA     DX, SWAP_FNAME
+                MOV     AH, 41H
+                INT     21H                     ; Delete swap file
+CUW_RET:        RET
+CLEANUP_SWAP    ENDP
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/swapper.inc
===================================================================
--- trunk/src/emx/src/dos/swapper.inc	(revision 18)
+++ trunk/src/emx/src/dos/swapper.inc	(revision 18)
@@ -0,0 +1,54 @@
+;
+; SWAPPER.INC -- Swap memory pages in and out
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_DATA         SEGMENT
+
+                EXTRN   SWAP_HANDLE:WORD
+                EXTRN   SWAP_FLAG:BYTE
+                EXTRN   SWAP_FAULTS:DWORD
+                EXTRN   SWAP_READS:DWORD
+                EXTRN   SWAP_WRITES:DWORD
+                EXTRN   SWAP_SIZE:DWORD
+                EXTRN   SNATCH_COUNT:DWORD
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   PAGE_FAULT:NEAR         ; Page fault exception
+                EXTRN   SWAP_OUT:NEAR           ; Swap a page out
+                EXTRN   INIT_SWAP:NEAR          ; Initialize swapper
+                EXTRN   ALLOC_SWAP:NEAR         ; Allocate swap space
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   CLEANUP_SWAP:NEAR
+                EXTRN   SET_TMP_DIR:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/symbols.asm
===================================================================
--- trunk/src/emx/src/dos/symbols.asm	(revision 18)
+++ trunk/src/emx/src/dos/symbols.asm	(revision 18)
@@ -0,0 +1,330 @@
+;
+; SYMBOLS.ASM -- Manage symbol tables
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__SYMBOLS       =       1
+
+                INCLUDE EMX.INC
+                INCLUDE SYMBOLS.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+
+                PUBLIC  SYM_BY_NAME, SYM_BY_ADDR, SYM_MODULE, SYM_BEFORE
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; In:   DS:DI   Pointer to process table entry
+;       DS:BX   Name of symbol (0 terminated)
+;       LDTR    Set for process
+;
+; Out:  EDX     Address
+;       AL      Code/data
+;       CY      Not found
+;
+; Note: Assumes that symbols in the string table are unique
+; 
+                ASSUME  DI:PTR PROCESS
+SYM_BY_NAME     PROC    NEAR
+                PUSH    ES
+                PUSH    ECX
+                PUSH    ESI
+                PUSH    EBP
+                MOV     DX, BX
+                CMP     [DI].P_SYMBOLS, 0
+                JE      SBN_LOOSE
+                MOV     AX, L_SYM_SEL
+                .386P
+                VERR    AX
+                .386
+                JNZ     SBN_LOOSE
+                MOV     ES, AX
+                MOV     ESI, [DI].P_STR_OFF
+                MOV     ECX, ES:[ESI]
+                ADD     ECX, ESI
+                ADD     ESI, 4
+SBN1:           MOV     BX, DX
+                CMP     ESI, ECX
+                JAE     SHORT SBN_LOOSE
+                MOV     EBP, ESI
+SBN2:           MOV     AL, ES:[ESI]
+                CMP     AL, [BX]
+                JNE     SHORT SBN3
+                INC     BX
+                INC     ESI
+                OR      AL, AL
+                JNZ     SHORT SBN2
+                JMP     SHORT SBN4
+
+SBN3:           INC     ESI
+                CMP     BYTE PTR ES:[ESI-1], 0
+                JNE     SHORT SBN3
+                JMP     SHORT SBN1
+
+SBN4:           SUB     EBP, [DI].P_STR_OFF
+                MOV     ESI, 0
+                ASSUME  ESI:NEAR32 PTR NLIST
+                MOV     ECX, [DI].P_SYMBOLS
+SBN5:           CMP     ES:[ESI].N_STRING, EBP
+                JE      SHORT SBN7
+SBN6:           ADD     ESI, SIZE NLIST
+                LOOPD   SBN5
+                JMP     SHORT SBN_LOOSE
+
+SBN7:           MOV     AL, ES:[ESI].N_TYPE
+                AND     AL, NOT N_EXT
+                MOV     AH, SYM_TEXT
+                CMP     AL, N_TEXT
+                JE      SHORT SBN8
+                MOV     AH, SYM_DATA
+                CMP     AL, N_DATA
+                JE      SHORT SBN8
+                CMP     AL, N_BSS
+                JE      SHORT SBN8
+                JMP     SHORT SBN6
+
+SBN8:           MOV     AL, AH
+                MOV     BX, DX
+                MOV     EDX, ES:[ESI].N_VALUE
+                CLC
+                JMP     SHORT SBN_RET
+
+SBN_LOOSE:      STC
+                MOV     BX, DX
+SBN_RET:        POP     EBP
+                POP     ESI
+                POP     ECX
+                POP     ES
+                RET
+                ASSUME  ESI:NOTHING
+                ASSUME  DI:NOTHING
+SYM_BY_NAME     ENDP
+
+
+;
+; In:   DS:DI   Pointer to process table entry
+;       EDX     Address
+;       AL      Code/data
+;       LDTR    Set for process
+;
+; Out:  ES:EBX  Pointer to name
+;       DX      Descriptor (line number)
+;       CY      Not found
+;
+; This function searches the list backwards, to meet a `real' symbol
+; before a file name (eg, __time before time.o). Yes, it's a hack.
+;
+                ASSUME  DI:PTR PROCESS
+SYM_BY_ADDR     PROC    NEAR
+                PUSH    ECX
+                PUSH    ESI
+                PUSH    EBP
+                MOV     BL, AL
+                CMP     [DI].P_SYMBOLS, 0
+                JE      SBA_LOOSE
+                MOV     AX, L_SYM_SEL
+                .386P
+                VERR    AX
+                .386
+                JNZ     SBA_LOOSE
+                MOV     ES, AX
+                MOV     ECX, [DI].P_SYMBOLS
+                MOV     ESI, ECX
+                DEC     ESI
+                IMUL    ESI, SIZE NLIST
+                ASSUME  ESI:NEAR32 PTR NLIST
+SBA1:           CMP     ES:[ESI].N_VALUE, EDX
+                JE      SHORT SBA3
+SBA2:           SUB     ESI, SIZE NLIST
+                LOOPD   SBA1
+                JMP     SHORT SBA_LOOSE
+
+SBA3:           MOV     AL, ES:[ESI].N_TYPE
+                AND     AL, NOT N_EXT
+                MOV     AH, SYM_TEXT
+                CMP     AL, N_TEXT
+                JE      SHORT SBA4
+                MOV     AH, SYM_DATA
+                CMP     AL, N_DATA
+                JE      SHORT SBA4
+                CMP     AL, N_BSS
+                JE      SHORT SBA4
+                CMP     AL, N_SLINE
+                JNE     SHORT SBA2
+                CMP     BL, SYM_LINE
+                JNE     SHORT SBA2
+                JMP     SHORT SBA5
+
+SBA4:           CMP     BL, SYM_ANY
+                JE      SHORT SBA5
+                CMP     BL, AH
+                JNE     SHORT SBA2
+SBA5:           MOV     EBX, ES:[ESI].N_STRING
+                ADD     EBX, [DI].P_STR_OFF
+                MOV     DX, ES:[ESI].N_DESC
+                CLC
+                JMP     SHORT SBA_RET
+
+SBA_LOOSE:      STC
+SBA_RET:        POP     EBP
+                POP     ESI
+                POP     ECX
+                RET
+                ASSUME  ESI:NOTHING
+                ASSUME  DI:NOTHING
+SYM_BY_ADDR     ENDP
+
+
+;
+; In:   DS:DI   Pointer to process table entry
+;       EDX     Address
+;       LDTR    Set for process
+;
+; Out:  ES:EBX  Pointer to file name
+;       CY      Not found
+;
+; This functions assumes that the list is sorted by address.
+;
+                ASSUME  DI:PTR PROCESS
+SYM_MODULE      PROC    NEAR
+                PUSH    ECX
+                PUSH    ESI
+                PUSH    EBP
+                CMP     [DI].P_SYMBOLS, 0
+                JE      SBM_LOOSE
+                MOV     AX, L_SYM_SEL
+                .386P
+                VERR    AX
+                .386
+                JNZ     SBM_LOOSE
+                MOV     ES, AX
+                MOV     ECX, [DI].P_SYMBOLS
+                MOV     ESI, 0
+                ASSUME  ESI:NEAR32 PTR NLIST
+                MOV     EBP, -1                 ; Nothing found yet
+SBM1:           MOV     AL, ES:[ESI].N_TYPE
+                CMP     AL, 64H                 ; Main module
+                JE      SHORT SBM4
+                CMP     AL, 84H                 ; Submodule
+                JE      SHORT SBM4
+SBM2:           ADD     ESI, SIZE NLIST
+                LOOPD   SBM1
+SBM3:           CMP     EBP, -1
+                JE      SHORT SBM_LOOSE
+                MOV     ESI, EBP
+                MOV     EBX, ES:[ESI].N_STRING
+                ADD     EBX, [DI].P_STR_OFF
+                CLC
+                JMP     SHORT SBM_RET
+
+SBM4:           CMP     ES:[ESI].N_VALUE, EDX
+                JA      SHORT SBM3
+                MOV     EBP, ESI
+                JMP     SHORT SBM2
+
+SBM_LOOSE:      STC
+SBM_RET:        POP     EBP
+                POP     ESI
+                POP     ECX
+                RET
+                ASSUME  ESI:NOTHING
+                ASSUME  DI:NOTHING
+SYM_MODULE      ENDP
+
+
+;
+; In:   DS:DI   Pointer to process table entry
+;       EDX     Address
+;       LDTR    Set for process
+;
+; Out:  ES:EBX  Pointer to name
+;       EAX     Address
+;       CY      Not found
+;
+; This functions assumes that file names come after other symbols.
+;
+                ASSUME  DI:PTR PROCESS
+SYM_BEFORE      PROC    NEAR
+                PUSH    ECX
+                PUSH    ESI
+                PUSH    EBP
+                CMP     [DI].P_SYMBOLS, 0
+                JE      SBB_LOOSE
+                MOV     AX, L_SYM_SEL
+                .386P
+                VERR    AX
+                .386
+                JNZ     SBB_LOOSE
+                MOV     ES, AX
+                MOV     EBP, -1                 ; Nothing found yet
+                MOV     ECX, [DI].P_SYMBOLS
+                MOV     ESI, 0
+                ASSUME  ESI:NEAR32 PTR NLIST
+                MOV     EBP, -1
+                MOV     EBX, 0
+SBB1:           MOV     AL, ES:[ESI].N_TYPE
+                AND     AL, NOT N_EXT
+                CMP     AL, N_TEXT
+                JE      SHORT SBB3
+                CMP     AL, N_DATA
+                JE      SHORT SBB3
+                CMP     AL, N_BSS
+                JE      SHORT SBB3
+SBB2:           ADD     ESI, SIZE NLIST
+                LOOPD   SBB1
+                CMP     EBP, -1
+                JE      SHORT SBB_LOOSE
+                MOV     ESI, EBP
+                MOV     EBX, ES:[ESI].N_STRING
+                ADD     EBX, [DI].P_STR_OFF
+                MOV     EAX, ES:[ESI].N_VALUE
+                CLC
+                JMP     SHORT SBB_RET
+
+
+SBB3:           CMP     ES:[ESI].N_VALUE, EDX
+                JA      SHORT SBB2
+                CMP     ES:[ESI].N_VALUE, EBX
+                JB      SHORT SBB2
+                MOV     EBP, ESI
+                MOV     EBX, ES:[ESI].N_VALUE
+                JMP     SHORT SBB2
+
+SBB_LOOSE:      STC
+SBB_RET:        POP     EBP
+                POP     ESI
+                POP     ECX
+                RET
+                ASSUME  ESI:NOTHING
+                ASSUME  DI:NOTHING
+SYM_BEFORE      ENDP
+
+
+
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/symbols.inc
===================================================================
--- trunk/src/emx/src/dos/symbols.inc	(revision 18)
+++ trunk/src/emx/src/dos/symbols.inc	(revision 18)
@@ -0,0 +1,57 @@
+;
+; SYMBOLS.INC -- Manage symbol tables
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+NLIST           STRUCT
+N_STRING        DD      ?
+N_TYPE          DB      ?
+N_OTHER         DB      ?
+N_DESC          DW      ?
+N_VALUE         DD      ?
+NLIST           ENDS
+
+N_EXT           =       01H
+N_TEXT          =       04H
+N_DATA          =       06H
+N_BSS           =       08H
+N_SLINE         =       44H
+
+SYM_ANY         =       0               ; SYM_TEXT or SYM_DATA
+SYM_TEXT        =       1
+SYM_DATA        =       2
+SYM_LINE        =       3
+SYM_NONE        =       0FFH                    ; for disassembler
+
+              IFNDEF __SYMBOLS
+
+SV_CODE         SEGMENT
+
+                EXTRN   SYM_BY_ADDR:NEAR
+                EXTRN   SYM_BY_NAME:NEAR
+                EXTRN   SYM_MODULE:NEAR
+                EXTRN   SYM_BEFORE:NEAR
+
+SV_CODE         ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/syscall.asm
===================================================================
--- trunk/src/emx/src/dos/syscall.asm	(revision 18)
+++ trunk/src/emx/src/dos/syscall.asm	(revision 18)
@@ -0,0 +1,3551 @@
+;
+; SYSCALL.ASM -- System calls (without BIOS and DOS calls)
+;
+; Copyright (c) 1991-1998 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE PAGING.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE LOADER.INC
+                INCLUDE FILEIO.INC
+                INCLUDE TABLES.INC
+                INCLUDE PMINT.INC
+                INCLUDE SWAPPER.INC
+                INCLUDE MEMORY.INC
+                INCLUDE VCPI.INC
+                INCLUDE MISC.INC
+                INCLUDE XMS.INC
+                INCLUDE CORE.INC
+                INCLUDE PROFIL.INC
+                INCLUDE VPRINT.INC
+                INCLUDE UTILS.INC
+                INCLUDE VERSION.INC
+                INCLUDE TERMIO.INC
+                INCLUDE STAT.INC
+                INCLUDE TIMEB.INC
+                INCLUDE ULIMIT.INC
+                INCLUDE ERRORS.INC
+
+                PUBLIC  DO_SYSCALL
+
+FD_SETSIZE      =       256
+
+MY_DATETIME     STRUCT
+SECONDS         DD      ?
+MINUTES         DD      ?
+HOURS           DD      ?
+DAY             DD      ?
+MONTH           DD      ?
+YEAR            DD      ?
+MY_DATETIME     ENDS
+
+SELECT_ARGS     STRUCT
+SELA_NFDS       DD      ?
+SELA_READFDS    DD      ?
+SELA_WRITEFDS   DD      ?
+SELA_EXCEPTFDS  DD      ?
+SELA_TIMEOUT    DD      ?
+SELECT_ARGS     ENDS
+
+TIMEVAL         STRUCT
+TV_SEC          DD      ?
+TV_USEC         DD      ?
+TIMEVAL         ENDS
+
+SV_DATA         SEGMENT
+
+;
+; This structure is passed by spawnve() to NEW_PROCESS
+;
+                TALIGN  2
+NP2             NEW_PROC        <>
+
+;
+; Variables for __select()
+;
+SEL_COUNT       WORD    ?
+SEL_RBITS       BYTE    FD_SETSIZE/8 DUP (?)
+
+;
+;
+;
+INO_NUMBER      DWORD   100000H
+
+;
+; Number of days of a month
+;
+MONTH_LEN       DB      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+
+$FAT            DB      "FAT", 0
+$LAN            DB      "LAN", 0
+
+;
+; __open() maps "/dev/null" and "/dev/tty" to "nul" and "con",
+; respectively.
+;
+$DEVNULL        BYTE    "/dev/null", 0
+$DEVTTY         BYTE    "/dev/tty", 0
+$NUL            BYTE    "nul", 0
+$CON            BYTE    "con", 0
+
+;
+; Special program names
+;
+$COMMAND        BYTE    "COMMAND.COM", 0
+$4DOS           BYTE    "4DOS.COM", 0
+
+;
+; DOS_COMMAND sets this flag to non-FALSE if command.com or 4dos.com
+; is to be run.
+;
+IS_COMMAND      BYTE    FALSE
+
+;
+; Parameter block for DOS function 4BH
+;
+PAR_BLOCK       LABEL   BYTE
+PB_ENV          DW      0
+                DD      CMD_LINE                ; Command line
+                DD      FCB                     ; FCB1
+                DD      FCB                     ; FCB2
+
+;
+; He who uses FCBs loses
+;
+FCB             DB      0                       ; Drive name
+                DB      11 DUP (" ")            ; File name
+                DB      20 DUP (0)              ; Fill to 32 bytes
+
+;
+; Program name and command line for DOS programs
+;
+PGM_NAME_SIZE   =       65
+CMD_LINE_SIZE   =       128
+
+PGM_NAME        DB      PGM_NAME_SIZE DUP (0)
+CMD_LINE        DB      CMD_LINE_SIZE DUP (0)
+
+FIND_BUF        STRUC
+FIND_RESERVED   DB      15H DUP (?)
+FIND_ATTR       DB      ?
+FIND_TIME       DW      ?
+FIND_DATE       DW      ?
+FIND_SIZE       DD      ?
+FIND_NAME       DB      13 DUP (?)
+FIND_BUF        ENDS
+
+STAT_CWD        DB      "x:\"
+                DB      65 DUP (?)
+
+;
+; Error message
+;
+$SYSCALL        DB      "Invalid syscall function code: 7f", 0
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+TIME_2_UNIX     PROTO   PASCAL, MDT:PTR MY_DATETIME
+                EXTRN   PTRACE:NEAR
+
+;
+; Jump table for syscall functions
+;
+                TALIGN  2
+SYSCALL_JMP     DW      SYS00                   ; __sbrk
+                DW      SYS01                   ; __brk
+                DW      SYS02                   ; __ulimit
+                DW      SYS03                   ; __vmstat
+                DW      SYS04                   ; __umask1
+                DW      SYS05                   ; __getpid
+                DW      SYS06                   ; __spawnve
+                DW      SYSCALL_ERROR           ; (obsolete)
+                DW      PTRACE                  ; __ptrace
+                DW      SYS09                   ; __wait
+                DW      SYS0A                   ; __version
+                DW      SYS0B                   ; __memavail
+                DW      SYS0C                   ; __signal
+                DW      SYS0D                   ; __kill
+                DW      SYS0E                   ; __raise
+                DW      SYS0F                   ; __uflags
+                DW      SYS10                   ; __unwind
+                DW      SYS11                   ; __core
+                DW      SYS12                   ; __portaccess
+                DW      SYS13                   ; __memaccess
+                DW      SYS14                   ; __ioctl2
+                DW      SYS15                   ; __alarm
+                DW      SYS16                   ; Poll the keyboard
+                DW      SYS17                   ; __sleep
+                DW      SYS18                   ; __chsize
+                DW      SYS19                   ; __fcntl
+                DW      SYS1A                   ; __pipe
+                DW      SYS1B                   ; __fsync
+                DW      SYS1C                   ; __fork
+                DW      SYS1D                   ; __scrsize
+                DW      SYS1E                   ; __select
+                DW      SYS1F                   ; __syserrno
+                DW      SYS20                   ; __stat
+                DW      SYS21                   ; __fstat
+                DW      SYSCALL_ERROR           ; No longer used
+                DW      SYS23                   ; __filesys
+                DW      SYS24                   ; __utimes
+                DW      SYS25                   ; __ftruncate
+                DW      SYS26                   ; __clock
+                DW      SYS27                   ; __ftime
+                DW      SYS28                   ; __umask
+                DW      SYS29                   ; __getppid
+                DW      SYS2A                   ; __nls_memupr
+                DW      SYS2B                   ; __open
+                DW      SYS2C                   ; __newthread
+                DW      SYS2D                   ; __endthread
+                DW      SYS2E                   ; __waitpid
+                DW      SYS2F                   ; __read_kbd
+                DW      SYS30                   ; __sleep2
+                DW      SYS31                   ; __unwind2
+                DW      SYS32                   ; __pause
+                DW      SYS33                   ; __execname
+                DW      SYS34                   ; __initthread
+                DW      SYS35                   ; __sigaction
+                DW      SYS36                   ; __sigpending
+                DW      SYS37                   ; __sigprocmask
+                DW      SYS38                   ; __sigsuspend
+                DW      SYS39                   ; __imphandle
+                DW      SYS3A                   ; __fpuemu
+                DW      SYSCALL_ERROR           ; __getsockhandle
+                DW      SYSCALL_ERROR           ; __socket
+                DW      SYSCALL_ERROR           ; __bind
+                DW      SYSCALL_ERROR           ; __listen
+                DW      SYSCALL_ERROR           ; __recv
+                DW      SYSCALL_ERROR           ; __send
+                DW      SYSCALL_ERROR           ; __accept
+                DW      SYSCALL_ERROR           ; __connect
+                DW      SYSCALL_ERROR           ; __getsockopt
+                DW      SYSCALL_ERROR           ; __setsockopt
+                DW      SYSCALL_ERROR           ; __getsockname
+                DW      SYSCALL_ERROR           ; __getpeername
+                DW      SYSCALL_ERROR           ; __gethostbyname
+                DW      SYSCALL_ERROR           ; __gethostbyaddr
+                DW      SYSCALL_ERROR           ; __getservbyname
+                DW      SYSCALL_ERROR           ; __getservbyport
+                DW      SYSCALL_ERROR           ; __getprotobyname
+                DW      SYSCALL_ERROR           ; __getprotobynumber
+                DW      SYSCALL_ERROR           ; __getnetbyname
+                DW      SYSCALL_ERROR           ; __getnetbyaddr
+                DW      SYSCALL_ERROR           ; __gethostname
+                DW      SYSCALL_ERROR           ; __gethostid
+                DW      SYSCALL_ERROR           ; __shutdown
+                DW      SYSCALL_ERROR           ; __recvfrom
+                DW      SYSCALL_ERROR           ; __sendto
+                DW      SYSCALL_ERROR           ; __impsockhandle
+                DW      SYSCALL_ERROR           ; __recvmsg
+                DW      SYSCALL_ERROR           ; __sendmsg
+                DW      SYSCALL_ERROR           ; __ttyname
+                DW      SYS58                   ; __settime
+                DW      SYS59                   ; __profil
+                DW      SYS5A                   ; __nls_ctype
+                DW      SYSCALL_ENOSYS		; __setsyserrno
+SYSCALL_LAST    =       ($-SYSCALL_JMP)/2-1
+
+;
+; Syscall functions
+;
+; In:   AH      7FH
+;       AL      Function code
+;
+                ASSUME  DS:SV_DATA
+                ASSUME  BP:PTR ISTACKFRAME
+                TALIGN  4
+DO_SYSCALL:     CMP     AL, SYSCALL_LAST        ; Valid function code?
+                JA      SHORT SYSCALL_ENOSYS    ; Yes -> return ENOSYS
+                MOV     DI, PROCESS_PTR         ; Process table entry
+                MOVZX   EAX, AL                 ; Keep only lower 8 bits
+                JMP     SYSCALL_JMP[EAX*2]      ; Jump!
+
+SYSCALL_ERROR:  LEA     EDX, $SYSCALL           ; Display error message
+                MOV     BL, AL                  ; (function code = AL)
+                JMP     DOSF_ERROR              ; and abort
+
+SYSCALL_ENOSYS: MOV     I_EAX, -1
+                MOV     I_ECX, ENOSYS
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F00H: EAX:=sbrk(EDX)
+; AX=7F01H: EAX:=brk(EDX)
+;
+; Change data segment space allocation
+;
+; ----------------------------------------------------------------------------
+;
+; AX=7F00H: EAX:=sbrk(EDX)
+;
+; In:   EDX     Value to be added to current break value (address of
+;               first byte beyond the end of the data segment). Positive
+;               values grow the data segment, negative values shrink the
+;               data segment.
+;
+; Out:  EAX     Previous break value or -1 if error.
+;
+; ----------------------------------------------------------------------------
+;
+; AX=7F01H: EAX:=brk(EDX)
+;
+; In:   EDX     New break value.
+;
+; Out:  EAX     0 if successful or -1 if error.
+;
+; ----------------------------------------------------------------------------
+;
+; Bug: doesn't fail if there isn't enough swap space
+; Bug: Doesn't free pages with negative argument
+; Bug: Doesn't work with stack above data/bss!!!
+; Bug?: Doesn't zero-fill new memory
+;
+; ----------------------------------------------------------------------------
+                ASSUME  DI:PTR PROCESS
+SYS00:          MOV     EAX, [DI].P_BRK         ; Get current break value
+                PUSH    EAX                     ; Save it
+                MOV     EDX, I_EDX              ; Get argument
+                CMP     EDX, 0                  ; No change?
+                JE      SHORT SYS00_OK          ; Yes -> done
+                JS      SHORT SYS00_NEG
+                ADD     EAX, EDX
+                JMP     SHORT SYS00_1
+SYS00_NEG:      NEG     EDX
+                SUB     EAX, EDX
+SYS00_1:        JC      SHORT SYS00_ERR
+                CALL    BRK
+                JNC     SHORT SYS00_OK
+SYS00_ERR:      POP     EAX                     ; Throw away saved value
+                MOV     I_EAX, -1               ; Return -1
+                RET
+
+SYS00_OK:       POP     I_EAX                   ; Return previous break value
+                RET
+
+                ASSUME  DI:NOTHING
+
+SYS01:          MOV     EAX, I_EDX              ; Argument
+                CALL    BRK
+                SBB     EAX, EAX                ; ok -> 0, error -> -1
+                MOV     I_EAX, EAX
+                RET
+
+
+;
+; Common code for brk and sbrk
+;
+; In:   DS:DI   Pointer to process table entry
+;       EAX     New break value
+;
+; Out:  CY      Error
+;
+                ASSUME  DI:PTR PROCESS
+BRK             PROC    NEAR
+                CMP     EAX, [DI].P_INIT_BRK
+                JB      BRK_ERR
+                MOV     EBX, [DI].P_STACK_ADDR
+                CMP     EBX, [DI].P_BRK         ; Stack above data/bss ?
+                JB      SHORT BRK_1             ; No  -> don't check stack
+                SUB     EBX, 4096               ; Leave at least one page
+                CMP     EAX, EBX                ; of stack space (note 1)
+                JA      BRK_ERR                 ; Out of memory -> failure
+BRK_1:          MOV     ESI, EAX                ; ESI := new break value
+                CMP     EAX, [DI].P_BRK
+                JB      SHORT BRK_SEG           ; Set segment size
+                MOV     ECX, EAX
+                DEC     ECX                     ; New last byte
+                SHR     ECX, 12                 ; New last page number
+                MOV     EAX, [DI].P_BRK
+                DEC     EAX
+                JS      SHORT BRK_2
+                SHR     EAX, 12                 ; Old last page number
+BRK_2:          SUB     ECX, EAX                ; Number of new pages
+                JBE     SHORT BRK_SEG
+                INC     EAX                     ; First new page number
+                SHL     EAX, 12                 ; Byte address of new page
+                ADD     EAX, [DI].P_LINEAR      ; Linear address
+;
+; Note 1: We must not change the attributes of stack pages!
+;         This is assured by leaving at least 4096 bytes between data
+;         and stack.
+;
+                CALL    INIT_PAGES
+                JC      SHORT BRK_ERR           ; Out of memory
+                MOV     EBX, PAGE_WRITE OR PAGE_USER
+                MOV     EDX, SRC_NONE
+                TEST    [DI].P_FLAGS, PF_DONT_ZERO
+                JNZ     SHORT BRK_3
+                MOV     EDX, SRC_ZERO
+BRK_3:          MOV     DL, [DI].P_PIDX
+                CALL    SET_COMMIT              ; Set PAGE_ALLOC bit
+                CALL    SET_PAGES
+                JC      SHORT BRK_ERR           ; Committing failed
+;
+; Adjust data segment size
+;
+BRK_SEG:        MOV     EBX, [DI].P_STACK_ADDR
+                CMP     EBX, [DI].P_BRK         ; Stack above data/bss ?
+                JA      BRK_DONE                ; Yes -> skip
+                MOV     ECX, ESI
+                PUSH    ESI
+                MOV     SI, [DI].P_LDT_PTR
+                ADD     SI, L_DATA_SEL AND NOT 07H
+                CALL    SEG_SIZE
+                POP     ESI
+BRK_DONE:       MOV     [DI].P_BRK, ESI
+                CLC
+                RET
+
+BRK_ERR:        STC
+                RET
+
+                ASSUME  DI:NOTHING
+BRK             ENDP
+
+
+; ----------------------------------------------------------------------------
+; AX=7F02H: EAX:=ulimit
+;
+; Get greatest possible break value
+;
+; ----------------------------------------------------------------------------
+;
+; In:   ECX     Command code (must be UL_GMEMLIM or UL_OBJREST)
+;       EDX     New limit (currently ignored)
+;
+; Out:  EAX     Return value:   
+;                   greatest possible break value for UL_GMEMLIM
+;                   remaining bytes in current heap object for UL_OBJREST
+;       ECX     errno, if non-zero
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS02:          CMP     I_ECX, UL_GMEMLIM
+                JE      ULIMIT_GMEMLIM
+                CMP     I_ECX, UL_OBJREST
+                JE      ULIMIT_OBJREST
+ULIMIT_ERR:     MOV     I_EAX, -1
+                MOV     I_ECX, EINVAL
+                RET
+
+ULIMIT_OBJREST: CALL    HEAP_LIMIT
+                SUB     EAX, [DI].P_BRK
+                JMP     SHORT ULIMIT_RET
+
+ULIMIT_GMEMLIM: CALL    HEAP_LIMIT
+ULIMIT_RET:     MOV     I_EAX, EAX
+                MOV     I_ECX, 0
+                RET
+
+HEAP_LIMIT      PROC    NEAR
+                MOV     EAX, [DI].P_BRK         ; Return this on error
+                MOV     EDX, [DI].P_STACK_ADDR
+                CMP     EDX, [DI].P_BRK
+                MOV     EBX, 80000000H          ; ...bad estimate
+                JB      SHORT HEAP_LIMIT_1
+                MOV     EBX, I_ESP
+                SUB     EBX, 4096               ; Leave at least on page
+                JC      SHORT HEAP_LIMIT_RET    ; of stack space (note 1)
+HEAP_LIMIT_1:   CMP     EBX, [DI].P_BRK
+                JB      SHORT HEAP_LIMIT_RET
+                MOV     EAX, EBX
+HEAP_LIMIT_RET: RET
+HEAP_LIMIT      ENDP
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F03H: [EBX]:=statistics
+;
+; Virtual memory statistics
+;
+; In:   DS:EBX  Buffer
+;       ECX     Size (in bytes) of buffer pointed to by DS:EBX
+;
+; Out:  [EBX+0] Number of page faults caused by this process
+;       [EBX+4] Total number of page faults
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS03:          MOV     EBX, I_EBX
+                MOV     ES, I_DS
+                MOV     ECX, I_ECX
+                CMP     ECX, 1*4
+                JB      SHORT SYS03_RET
+                MOV     EAX, [DI].P_PAGE_FAULTS
+                MOV     ES:[EBX+0], EAX
+                CMP     ECX, 2*4
+                JB      SHORT SYS03_RET
+                MOV     EAX, SWAP_FAULTS
+                MOV     ES:[EBX+4], EAX
+SYS03_RET:      RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F04H: EAX:=__umask1(EDX)
+;
+; Set file-permission mask
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS04:          MOVZX   EAX, [DI].P_UMASK1
+                MOV     I_EAX, EAX
+                MOV     AX, WORD PTR I_EDX
+                NOT     AX
+                AND     [DI].P_UMASK1, AX
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F05H: EAX:=getpid()
+;
+; Get process ID
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS05:          MOV     EAX, [DI].P_PID
+                MOV     I_EAX, EAX
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F06H: spawnve()
+;
+; Spawn child process
+;
+; In:   DS:EDX  Pointer to parameter table (NEW_PROC, see PROCESS.INC)
+;               NP_PARENT will be filled in by this function.
+;
+; Out:  CY      Error
+;       NC      Success
+;       EAX     Error code (CY)
+;       EAX     Process id (NC, asynchronous process)
+;       EAX     Return code (NC, synchronous process)
+;
+; Note: Not reentrant (uses global variable NP2!).
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS06:          MOV     BX, DI
+                CALL    SAVE_PROCESS            ; Save registers
+                CALL    MAKE_NP2                ; Copy param. table to NP2
+                CALL    SPAWN_FNAME             ; Create program file name
+                MOV     NP2.NP_FNAME_SEL, DS
+                MOV     NP2.NP_FNAME_OFF, OFFSET PGM_NAME
+                MOV     DI, PROCESS_PTR         ; Current process
+                CMP     BYTE PTR NP2.NP_MODE1, NP_EXEC ; exec?
+                JNE     SHORT SPAWN_2           ; No -> process is parent
+                MOV     EAX, [DI].P_PPID        ; PID of parent process
+                CALL    FIND_PROCESS            ; Find parent process
+                CMP     BX, NO_PROCESS          ; Success?
+                JNE     SHORT SPAWN_2           ; Yes -> has real parent
+                LEA     BX, PROC0               ; No  -> use dummy parent
+SPAWN_2:        MOV     NP2.NP_PARENT, BX       ; Set NP_PARENT field
+                MOV     NP2.NP_FPROC, DI        ; Set source of file handles
+                LEA     SI, NP2                 ; Parameter table
+                CALL    NEW_PROCESS             ; Create new process
+                OR      AX, AX                  ; Failure?
+                JNZ     SHORT SPAWN_FAIL        ; Yes -> try DOS pgm or return
+                MOV     BX, PROCESS_PTR         ; Outgoing process
+                ASSUME  BX:PTR PROCESS
+                CMP     BYTE PTR NP2.NP_MODE1, NP_DEBUG ; Debugging?
+                JE      SHORT SPAWN_ASYNC       ; Yes -> return to parent
+                CMP     BYTE PTR NP2.NP_MODE1, NP_SPAWN_ASYNC ; Asynchronous?
+                JNE     SHORT SPAWN_3           ; No -> continue
+                MOV     EAX, [DI].P_PID         ; Process ID of child
+                MOV     [BX].P_SPAWN_RC, EAX    ; will be returned by spawn()
+                OR      [BX].P_FLAGS, PF_PSEUDO_ASYNC
+SPAWN_3:        MOV     [BX].P_STATUS, PS_WAIT_SPAWN
+;
+; Now run the new process synchronously
+;
+                MOV     PROCESS_PTR, DI         ; Switch to incoming process
+                MOV     PROCESS_SIG, DI
+                CMP     BYTE PTR NP2.NP_MODE1, NP_EXEC
+                JNE     SHORT SPAWN_4
+                CALL    REMOVE_PROCESS          ; TODO: FPUEMU_ENDPROC
+SPAWN_4:        MOV     BX, DI
+                CALL    REST_PROCESS            ; Start incoming process
+                CALL    BREAK_AFTER_IRET
+                MOV     EAX, [BX].P_NUMBER
+                CALL    FPUEMU_NEWPROC          ; Notify FPU emulator
+SPAWN_RET:      RET
+
+;
+; Return to the parent process after starting an asynchronous process.
+; This is currently used for NP_DEBUG only.
+;
+SPAWN_ASYNC:    MOV     EAX, [DI].P_PID         ; Process ID of child
+                MOV     I_EAX, EAX              ; Return process ID
+                MOV     EAX, [DI].P_NUMBER
+                CALL    FPUEMU_NEWPROC          ; Notify FPU emulator
+                JMP     SHORT SPAWN_RET
+
+SPAWN_FAIL:     CMP     AX, ENOEXEC             ; Not an emx program?
+                JE      SHORT SPAWN_DOS         ; Yes -> try to run a DOS pgm
+SPAWN_ERROR:    MOVZX   EAX, AX
+                MOV     I_EAX, EAX              ; Failure
+                OR      BYTE PTR I_EFLAGS, FLAG_C
+                RET
+
+                ASSUME  BX:NOTHING
+                ASSUME  DI:NOTHING
+;
+; Try to run the program as ordinary DOS program
+;
+SPAWN_DOS:      CMP     BYTE PTR NP2.NP_MODE1, NP_SPAWN_SYNC ; Synchronous?
+                JE      SHORT SPAWN_DOS_1       ; Yes -> continue
+                CMP     BYTE PTR NP2.NP_MODE1, NP_SPAWN_ASYNC ; Asynchronous?
+                JNE     SHORT SPAWN_ERROR       ; No -> error
+SPAWN_DOS_1:    CMP     DISABLE_LOW_MEM, FALSE  ; Low memory in use?
+                JNE     SHORT DOS_10            ; No  -> ok
+                MOV     AX, ENOMEM              ; Not enough memory
+                JMP     SHORT SPAWN_ERROR
+;
+; Build command line
+;
+DOS_10:         CALL    DOS_COMMAND             ; Look for COMMAND.COM
+                CALL    DOS_ARGS                ; Build command line
+                JC      SHORT DOS_TOO_BIG
+                CALL    DOS_ENV                 ; Build environment
+                OR      AX, AX
+                JNZ     SHORT SPAWN_ERROR       ; Error -> return errno
+                CALL    MAP_ALL_HANDLES         ; Remap file handles
+                JC      SHORT SPAWN_ERROR       ; Error -> return errno
+;
+; Try to run the program
+;
+                LEA     DX, PGM_NAME
+                LEA     BX, PAR_BLOCK
+                MOV     AX, 4B00H               ; Load and execute program
+                INT     21H
+                MOV     I_EAX, EAX
+                JNC     SHORT DOS_OK
+                OR      BYTE PTR I_EFLAGS, FLAG_C
+                JMP     SPAWN_RET
+
+DOS_OK:         MOV     AH, 4DH                 ; Get ret code of child process
+                INT     21H
+                MOVZX   EAX, AX                 ; Put it in EAX
+                MOV     BX, PROCESS_PTR         ; Parent process
+                ASSUME  BX:PTR PROCESS
+                CMP     BYTE PTR NP2.NP_MODE1, NP_SPAWN_ASYNC ; Pseudo async?
+                JNE     SHORT DOS_SPAWN_RC      ; No -> return return code
+                MOV     [BX].P_RC, AL           ; Save the return code
+                CALL    CREATE_PID              ; Return a process ID
+                OR      [BX].P_FLAGS, PF_PSEUDO_ASYNC
+                CMP     [BX].P_SIG_HANDLERS[4*SIGCLD], SIG_IGN
+                JE      SHORT DOS_SPAWN_RC
+                CMP     [BX].P_SIG_HANDLERS[4*SIGCLD], SIG_DFL
+                JE      SHORT DOS_SPAWN_RC
+                BTS     [BX].P_SIG_PENDING, SIGCLD      ; Generate SIGCLD
+DOS_SPAWN_RC:   MOV     [BX].P_SPAWN_RC, EAX
+                MOV     I_EAX, EAX
+                JMP     SPAWN_RET
+                ASSUME  BX:NOTHING
+
+;
+; Arguments or environment too big
+;
+DOS_TOO_BIG:    MOV     AX, E2BIG
+                JMP     SPAWN_ERROR
+
+;
+;
+;
+                TALIGN  4
+SPAWN_FNAME     PROC    NEAR
+                PUSH    ESI
+                PUSH    EDI
+                PUSH    DS
+                LEA     DI, PGM_NAME
+                MOV_ES_DS
+                MOV     ESI, NP2.NP_FNAME_OFF
+                MOV     DS, NP2.NP_FNAME_SEL
+                ASSUME  DS:NOTHING
+                MOV     CX, PGM_NAME_SIZE - 1
+SPAWN_FNAME_1:  LODS    BYTE PTR DS:[ESI]
+                OR      AL, AL
+                JZ      SHORT SPAWN_FNAME_2
+                STOS    BYTE PTR ES:[DI]
+                LOOP    SPAWN_FNAME_1
+SPAWN_FNAME_2:  XOR     AL, AL
+                STOS    BYTE PTR ES:[DI]
+                POP     DS
+                ASSUME  DS:SV_DATA
+                LEA     EDI, PGM_NAME
+                CALL    TRUNCATE
+                POP     EDI
+                POP     ESI
+                RET
+SPAWN_FNAME     ENDP
+
+;
+; Check for COMMAND.COM and 4DOS.COM
+;
+
+DOS_COMMAND     PROC    NEAR
+                MOV     IS_COMMAND, FALSE       ; Standard quoting by default
+                LEA     SI, PGM_NAME            ; Find base name
+                MOV     DI, SI
+DC_1:           LODSB
+                OR      AL, AL
+                JZ      SHORT DC_3
+                CMP     AL, "/"
+                JE      SHORT DC_2
+                CMP     AL, "\"
+                JE      SHORT DC_2
+                CMP     AL, ":"
+                JNE     SHORT DC_1
+DC_2:           MOV     DI, SI
+                JMP     SHORT DC_1
+
+DC_3:           MOV_ES_DS
+                LEA     SI, $COMMAND            ; command.com?
+                CALL    STRICMP
+                JE      SHORT DC_4              ; Yes ->
+                LEA     SI, $4DOS               ; 4dos.com?
+                CALL    STRICMP
+                JNE     SHORT DC_RET            ; No  -> skip
+DC_4:           MOV     IS_COMMAND, NOT FALSE   ; Don't quote arguments
+DC_RET:         RET
+DOS_COMMAND     ENDP
+
+;
+; Build command line for DOS programs
+;
+; In:  NP2      Parameter block
+;
+; Out: CY       Command line too big
+;
+DOS_ARGS        PROC    NEAR PASCAL
+                LOCAL   ARG_COUNTER:WORD
+                LOCAL   NO_QUOTE:BYTE
+                LOCAL   FORCE_QUOTE:BYTE
+
+                PUSH    DS                      ; Save DS
+                MOV     AL, IS_COMMAND          ; No quoting if command.com
+                MOV     NO_QUOTE, AL            ; Copy to stack segment
+                MOV     FORCE_QUOTE, FALSE
+                TEST    NP2.NP_MODE2, NP2_QUOTE
+                JNZ     SHORT DA_1
+                MOV     BX, PROCESS_PTR
+                CMP     BX, NO_PROCESS
+                JE      SHORT DA_2
+                TEST    (PROCESS PTR [BX]).P_FLAGS, PF_QUOTE
+                JZ      SHORT DA_2
+DA_1:           NOT     FORCE_QUOTE
+DA_2:           MOV     DX, 0                   ; Size of command line
+                MOV     AX, NP2.NP_ARG_COUNT    ; Number of arguments
+                MOV_ES_DS
+                LEA     DI, CMD_LINE + 1
+                MOV     ESI, NP2.NP_ARG_OFF
+                MOV     DS, NP2.NP_ARG_SEL
+                ASSUME  DS:NOTHING
+                CLD
+;
+; Skip argv[0]
+;
+                CMP     AX, 2
+                JB      DONE                    ; No arguments -> done
+                DEC     AX                      ; argv[0] skipped
+                MOV     ARG_COUNTER, AX
+                LODS    BYTE PTR DS:[ESI]       ; Get flags byte
+                OR      AL, AL                  ; End of arguments?
+                JZ      DONE                    ; Yes -> done
+SKIP_ARGV0:     LODS    BYTE PTR DS:[ESI]       ; Fetch character
+                OR      AL, AL                  ; End of argument?
+                JNZ     SKIP_ARGV0              ; No  -> repeat
+;
+; Next argument
+;
+NEXT:           LODS    BYTE PTR DS:[ESI]       ; Get flags byte
+                OR      DX, DX
+                JZ      SHORT ARG_SKIP_FLAG     ; First argument -> skip
+                INC     DX
+                CMP     DX, CMD_LINE_SIZE - 2   ; Too long?
+                JA      DONE                    ; Yes -> end
+                MOV     AL, " "                 ; Delimit arguments
+                STOS    BYTE PTR ES:[DI]
+;
+; Look for blanks and tabs. Quote the entire argument if there is
+; a blank or a tab.
+;
+ARG_SKIP_FLAG:  CMP     NO_QUOTE, FALSE         ; Quote?
+                JNE     SHORT ARG_CHECK_NO      ; No  -> skip
+                CMP     BYTE PTR DS:[ESI], 0    ; Empty argument?
+                JE      SHORT ARG_CHECK_YES     ; Yes -> needs quoting
+                PUSH    ESI
+                XOR     AH, AH                  ; No quoting required
+ARG_CHECK:      LODS    BYTE PTR DS:[ESI]       ; Fetch character
+                TEST    AL, AL                  ; End of argument?
+                JZ      SHORT ARG_CHECK_END     ; Yes -> no quoting required
+                CMP     AL, " "                 ; Blank?
+                JE      SHORT ARG_CHECK_END     ; Yes -> quote the argument
+                CMP     AL, TAB                 ; Tab?
+                JNE     SHORT ARG_CHECK         ; No  -> check next character
+ARG_CHECK_END:  POP     ESI
+                TEST    AL, AL
+                JNZ     SHORT ARG_CHECK_YES
+                CMP     FORCE_QUOTE, FALSE      ; P_QUOTE or -q?
+                JE      SHORT ARG_CHECK_NO      ; No  -> don't quote
+;
+; Check for @, ? or *
+;
+                PUSH    ESI
+                MOV     AL, 1
+                CMP     BYTE PTR DS:[ESI], "@"  ; Argument starting with "@"?
+                JNE     SHORT AC_200
+                CMP     BYTE PTR DS:[ESI+1], 0
+                JNE     SHORT AC_299            ; Yes -> quote (AL non-zero)
+AC_200:         LODS    BYTE PTR DS:[ESI]       ; Fetch character
+                TEST    AL, AL                  ; End of argument?
+                JZ      SHORT AC_299            ; Yes -> don't quote (AL=0)
+                CMP     AL, "?"                 ; Wildcard character?
+                JE      SHORT AC_299            ; Yes -> quote (AL non-zero)
+                CMP     AL, "*"                 ; Wildcard character?
+                JNE     SHORT AC_200            ; No  -> check next character
+AC_299:         POP     ESI
+                TEST    AL, AL
+                JZ      SHORT ARG_CHECK_NO
+ARG_CHECK_YES:  MOV     AH, 1                   ; Flag for closing quote
+                INC     DX
+                CMP     DX, CMD_LINE_SIZE - 2   ; Too long?
+                JA      SHORT DONE              ; Yes -> end
+                MOV     AL, '"'                 ; Store opening quote
+                STOS    BYTE PTR ES:[DI]
+ARG_CHECK_NO:   XOR     CX, CX                  ; Clear backslash counter
+;
+; Copy argument
+;
+ARG_COPY:       LODS    BYTE PTR DS:[ESI]       ; Fetch character
+                OR      AL, AL                  ; End of argument?
+                JZ      SHORT ARG_END           ; Yes -> next argument
+                CMP     NO_QUOTE, FALSE         ; Quoting disabled?
+                JNE     SHORT ARG_STORE         ; Yes -> simply store the char
+                CMP     AL, "\"                 ; Backslash?
+                JE      SHORT ARG_BACKSLASH     ; Yes  -> count
+                CMP     AL, '"'                 ; Quote?
+                JE      SHORT ARG_QUOTE         ; Yes -> handle backslashes
+                XOR     CX, CX                  ; Clear backslash counter
+ARG_STORE:      INC     DX
+                CMP     DX, CMD_LINE_SIZE - 2   ; Too long?
+                JA      SHORT DONE              ; Yes -> end
+                STOS    BYTE PTR ES:[DI]
+                JMP     SHORT ARG_COPY
+
+                TALIGN  4
+ARG_BACKSLASH:  INC     CX                      ; Increment backslash counter
+                JMP     SHORT ARG_STORE         ; Store character
+
+                TALIGN  4
+ARG_QUOTE:      INC     CX                      ; 2n+1 backslashes
+                ADD     DX, CX
+                CMP     DX, CMD_LINE_SIZE - 2   ; Too long?
+                JA      SHORT DONE              ; Yes -> end
+                MOV     AL, "\"                 ; Store backslashes
+ARG_QUOTE_1:    STOSB
+                LOOP    ARG_QUOTE_1
+                MOV     AL, '"'
+                JMP     SHORT ARG_STORE
+
+ARG_END:        OR      AH, AH                  ; Closing quote required?
+                JZ      SHORT MORE              ; No  -> skip
+                JCXZ    ARG_END_2
+                ADD     DX, CX
+                CMP     DX, CMD_LINE_SIZE - 2   ; Too long?
+                JA      SHORT DONE              ; Yes -> end
+                MOV     AL, "\"
+ARG_END_1:      STOSB
+                LOOP    ARG_END_1
+ARG_END_2:      MOV     AL, '"'
+                INC     DX
+                CMP     DX, CMD_LINE_SIZE - 2   ; Too long?
+                JA      SHORT DONE              ; Yes -> end
+                STOSB
+MORE:           DEC     ARG_COUNTER
+                JNZ     NEXT
+DONE:           POP     DS                      ; Restore DS
+                ASSUME  DS:SV_DATA
+                CMP     DX, CMD_LINE_SIZE - 2
+                JA      SHORT TOO_BIG
+                MOV     CMD_LINE[0], DL         ; Length = 0
+                MOV     AL, CR
+                STOS    BYTE PTR ES:[DI]        ; End of command line
+                CLC
+FIN:            RET
+
+TOO_BIG:        STC
+                JMP     SHORT FIN
+DOS_ARGS        ENDP
+
+
+; ----------------------------------------------------------------------------
+;
+; Build environment for DOS program
+;
+; Out:  AX      errno (0 if no error)
+;       PB_ENV  Segment of environment
+;
+; ----------------------------------------------------------------------------
+DOS_ENV         PROC    NEAR
+                CMP     NP2.NP_ENV_SIZE, 8000H  ; Fail with E2BIG if the
+                MOV     AX, E2BIG               ; environment is too big
+                JAE     SHORT ERR
+;
+; Copy the environment to the real-mode buffer (that buffer is not used
+; for INT 21H, AH=4BH).
+;
+                MOV     AX, NP2.NP_ENV_SEL
+                MOV     ESI, NP2.NP_ENV_OFF
+                MOV     EDI, 0                  ; OFFSET_1 is not zero!
+                MOVZX   ECX, NP2.NP_ENV_SIZE
+                CALL    MOVE_TO_RM
+                MOV     AX, BUF_SEG             ; Set the environment pointer
+                MOV     PB_ENV, AX              ; in the parameter block
+OK:             XOR     AX, AX                  ; No error
+ERR:            RET
+DOS_ENV         ENDP
+
+
+; ----------------------------------------------------------------------------
+; Copy NEW_PROC (_new_proc) structure from user process' data segment to
+; supervisor data segment
+;
+; In:   I_EDX   Pointer to structure in user process' data segment
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+MAKE_NP2        PROC    NEAR
+                PUSH    DS
+                XOR     EDI, EDI
+                LEA     DI, NP2
+                MOV_ES_DS
+                MOV     ESI, I_EDX
+                MOV     DS, I_DS
+                ASSUME  DS:NOTHING
+                MOV     ECX, NP_USER_SIZE
+                REP     MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
+                POP     DS
+                ASSUME  DS:SV_DATA
+                MOV     NP2.NP_MODE2, 0
+                TEST    NP2.NP_MODE1, 8000H
+                JZ      SHORT MNP2_1
+                MOV     ES, I_DS
+                MOV     ESI, I_EDX
+                ASSUME  ESI:NEAR32 PTR NEW_PROC
+                MOV     AX, ES:[ESI].NP_MODE2
+                MOV     NP2.NP_MODE2, AX
+                ASSUME  ESI:NOTHING
+MNP2_1:         RET
+MAKE_NP2        ENDP
+
+
+; ----------------------------------------------------------------------------
+; AX=7F09H: __wait()
+;
+; Wait for child process
+;
+; In:   --
+;
+; Out:  EAX     Process ID of child process (-1 if no children)
+;       ECX     errno
+;       EDX     Termination status
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS09:          TEST    [DI].P_FLAGS, PF_PSEUDO_ASYNC ; Pseudo async child?
+                JNZ     SHORT WAIT_PSEUDO       ; Yes -> return its status
+                MOV     EAX, [DI].P_PID         ; Get process ID
+                CALL    WAIT_PROCESS            ; Look for children
+                CMP     BX, NO_PROCESS          ; Children?
+                JE      SHORT SYS09_ERROR       ; No  -> error
+                CMP     BX, NO_WPROCESS         ; Stopped/terminated children?
+                JE      SHORT SYS09_WAIT        ; No  -> wait
+                ASSUME  BX:PTR PROCESS
+                AND     [BX].P_FLAGS, NOT PF_WAIT_WAIT  ; wait done
+                MOV     EAX, [BX].P_PID         ; Return process ID
+                MOV     I_EAX, EAX
+                XOR     EAX, EAX                ; Termination status := 0
+                CMP     [BX].P_STATUS, PS_STOP  ; Stopped process?
+                JE      SHORT SYS09_STOP        ; Yes ->
+                MOV     AH, [BX].P_RC           ; Return code -> bits 8..15
+                JMP     SHORT SYS09_OK
+SYS09_STOP:     MOV     AL, 177Q
+                MOV     AH, [BX].P_SIG_NO       ; Signal number
+SYS09_OK:       MOV     I_EDX, EAX              ; Return status in EDX
+                MOV     I_ECX, 0                ; No error
+                CMP     [BX].P_STATUS, PS_DEFUNCT ; Zombie process?
+                JNE     SHORT SYS09_RET         ; No  -> skip
+                CALL    KILL_PROCESS            ; Remove last vestiges
+                ASSUME  BX:NOTHING
+SYS09_RET:      RET
+
+
+;
+; There are children, but no one stopped/terminated. Wait.
+; Not implemented, return error.
+;
+SYS09_WAIT:
+SYS09_ERROR:    MOV     I_ECX, ECHILD
+                MOV     I_EAX, -1
+                RET
+
+;
+; We had a pseudo asynchronous child process.  Return its termination
+; status.
+;
+WAIT_PSEUDO:    AND     [DI].P_FLAGS, NOT PF_PSEUDO_ASYNC       ; Child is dead
+                XOR     EAX, EAX
+                MOV     AH, [DI].P_RC           ; Get the return code
+                MOV     I_EDX, EAX              ; Set termination status
+                MOV     EAX, [DI].P_SPAWN_RC    ; Process ID
+                MOV     I_EAX, EAX
+                MOV     I_ECX, 0                ; No error
+                RET
+
+                ASSUME  DI:NOTHING
+
+
+; ----------------------------------------------------------------------------
+; AX=7F0AH: version
+;
+; Return emx version
+;
+; In:   --
+;
+; Out:  EAX     Version number
+;                 Bits 0..7:    version letter ("a".."z")
+;                 Bits 8..15:   minor version number ("0".."9")
+;                 Bits 16..23:  2EH (".")
+;                 Bits 24..31:  major version number ("0".."9")
+;       EBX     Environment:
+;                 Bit 0:        VCPI
+;                 Bit 1:        XMS
+;                 Bit 2:        VDISK.SYS 3.3
+;                 Bit 3:        DESQview
+;                 Bit 4:        287
+;                 Bit 5:        387
+;                 Bit 6:        486      (not implemented)
+;                 Bit 7:        DPMI 0.9 (not implemented)
+;                 Bit 8:        DPMI 1.0 (not implemented)
+;                 Bit 9:        OS/2 2.0
+;                 Bit 10:       -t option given
+;                 Bits 6..31:   0 (reserved for future expansion)
+;       ECX     Revision index
+;       EDX     0 (reserved for future expansion)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS0A:          MOV     I_EAX, VERSION          ; Return version number in EAX
+                XOR     EAX, EAX                ; Clear all environment bits
+                CMP     VCPI_FLAG, FALSE
+                JE      SHORT SYS0A_1
+                OR      AL, 01H                 ; Set VCPI bit
+SYS0A_1:        CMP     XMS_FLAG, FALSE
+                JE      SHORT SYS0A_2
+                OR      AL, 02H                 ; Set XMS bit
+SYS0A_2:        CMP     VDISK_FLAG, FALSE
+                JE      SHORT SYS0A_3
+                OR      AL, 04H                 ; Set VDISK bit
+SYS0A_3:        CMP     DV_FLAG, FALSE
+                JE      SHORT SYS0A_4
+                OR      AL, 08H                 ; Set DESQview bit
+SYS0A_4:        CMP     FP_FLAG, FP_287
+                JNE     SHORT SYS0A_5
+                OR      AL, 10H                 ; Set 287 bit
+SYS0A_5:        CMP     FP_FLAG, FP_387
+                JNE     SHORT SYS0A_6
+                OR      AL, 20H                 ; Set 387 bit
+SYS0A_6:        CMP     [DI].P_TRUNC, 0
+                JE      SHORT SYS0A_7
+                OR      AX, 400H                ; Set -t bit
+SYS0A_7:        TEST    [DI].P_HW_ACCESS, HW_ACCESS_CODE
+                JZ      SHORT SYS0A_8
+                OR      AX, 800H                ; Set -ac bit
+SYS0A_8:        MOV     I_EBX, EAX
+                MOV     I_ECX, REV_INDEX_BIN    ; Revision index
+                MOV     I_EDX, 0                ; Reserved
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F0BH: memavail
+;
+; Return number of available pages of memory (w/o swapping)
+;
+; In:   --
+;
+; Out:  EAX     Number of available pages
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS0B:          CALL    PM_AVAIL                ; This call does all the work
+                MOV     I_EAX, EAX              ; Return the result in EAX
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F0CH: __signal()
+;
+; Set signal handler
+;
+; In:   ECX     Signal number
+;       EDX     Address of signal handler or SIG_ACK, SIG_DFL, SIG_IGN
+;
+; Out:  EAX     Previous value (success) or SIG_ERR (error)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS0C:          MOV     EAX, I_ECX              ; Signal number
+                MOV     EDX, I_EDX              ; Signal handler
+                CMP     EDX, SIG_ACK            ; Acknowledge?
+                JE      SHORT SIGNAL_ACK        ; Yes ->
+                CALL    DO_SIGNAL
+                MOV     I_EAX, EAX
+                RET
+
+;
+; Unblock the signal EAX.  If there is a pending signal, it will be
+; raised on return to the current process.
+;
+SIGNAL_ACK:     CMP     EAX, SIGNALS            ; Valid signal number?
+                JAE     SHORT SIGNAL_ERROR      ; No  -> failure
+                CMP     SIG_VALID[EAX], FALSE
+                JE      SHORT SIGNAL_ERROR      ; No  -> failure
+                MOV     BX, AX
+                SHL     BX, 2
+                TEST    [DI].P_SA_FLAGS[BX], SA_ACK ; SA_ACK set?
+                JZ      SHORT SIGNAL_ERROR      ; No  -> failure
+                BTR     [DI].P_SIG_BLOCKED, EAX ; Unblock the signal
+                MOV     EAX, [DI].P_SIG_HANDLERS[BX] ; Get previous value
+                MOV     I_EAX, EAX              ; Return previous value
+                RET
+
+SIGNAL_ERROR:   MOV     I_EAX, SIG_ERR          ; Return SIG_ERR
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F0DH: __kill()
+;
+; Send a signal to a process
+;
+; In:   ECX     Signal number
+;       EDX     Process ID
+;
+; Out:  EAX     0 if successful, -1 otherwise
+;       ECX     errno
+;
+; (As we don't have real multitasking, we should switch to the other
+; process.)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS0D:          MOV     EAX, I_EDX              ; Get process ID
+                CALL    FIND_PROCESS            ; Find process for given ID
+                CMP     BX, NO_PROCESS          ; Found?
+                JE      SHORT KILL_BAD_PID      ; No  -> error
+                CMP     I_ECX, 0                ; Signal 0 (check PID)?
+                JE      SHORT RAISE_OK          ; Yes -> ok
+                MOV     DI, BX                  ; Copy process pointer to DI
+;
+; Fall through to __raise() code
+;
+; ----------------------------------------------------------------------------
+; AX=7F0EH: __raise()
+;
+; Raise a signal (in current process)
+;
+; In:   ECX     Signal number
+;
+; Out:  EAX     0 if successful, a non-zero value otherwise
+;       ECX     errno
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS0E:          MOV     EAX, I_ECX              ; Get signal number
+                CMP     EAX, SIGNALS            ; Valid signal number?
+                JAE     SHORT RAISE_ERROR       ; No  -> failure
+                CMP     SIG_VALID[EAX], FALSE
+                JE      SHORT RAISE_ERROR       ; No  -> failure
+                BTS     [DI].P_SIG_PENDING, EAX ; Generate signal
+RAISE_OK:       MOV     I_ECX, 0                ; No error
+                MOV     I_EAX, 0                ; Success
+                RET
+
+RAISE_ERROR:    MOV     I_ECX, EINVAL
+                MOV     I_EAX, -1               ; Error
+                RET
+
+KILL_BAD_PID:   MOV     I_ECX, ESRCH
+                MOV     I_EAX, -1
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F0FH: EAX:=uflags(ECX,EDX)
+;
+; Set user flags
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS0F:          MOV     EAX, [DI].P_UFLAGS
+                MOV     I_EAX, EAX              ; Return previous value
+                MOV     ECX, I_ECX              ; Get mask
+                MOV     EDX, I_EDX              ; Get new bits
+                AND     EDX, ECX                ; Clear unwanted bits
+                NOT     ECX
+                AND     EAX, ECX                ; Clear bits to be changed
+                OR      EAX, EDX                ; Insert new bits
+                MOV     [DI].P_UFLAGS, EAX      ; Store new value
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F10H: __unwind()
+;
+; Unwind signal handlers for longjmp()
+;
+; Currently not used by the DOS version of emx.
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS10:          RET
+
+; ----------------------------------------------------------------------------
+; AX=7F11H: __core()
+;
+; Write core image file
+;
+; In:   EBX     File handle
+;
+; Out:  CY      Error
+;       EAX     errno (CY)
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS11:          MOV     BX, DI                  ; Process table entry
+                CALL    CORE_REGS_I
+                MOV     EAX, I_EBX              ; Get file handle
+                CALL    CORE_MAIN               ; Write core image file
+                JNC     SHORT SYS11_RET
+                OR      I_EFLAGS, FLAG_C
+                CALL    DOS_ERROR_TO_ERRNO
+                MOV     I_EAX, EAX
+SYS11_RET:      RET
+
+; ----------------------------------------------------------------------------
+; AX=7F12H: _portaccess()
+;
+; Enable access to I/O ports
+;
+; In:   ECX    First port number
+;       EDX    Last port number
+;
+; Out:  CY     Failed
+;       EAX    errno (0 if successful)
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS12:          MOV     EAX, I_ECX
+                CMP     EAX, 10000H
+                JAE     SHORT PORTACCESS_ERR
+                MOV     ECX, I_EDX
+                CMP     ECX, 10000H
+                JAE     SHORT PORTACCESS_ERR
+                SUB     ECX, EAX
+                JB      SHORT PORTACCESS_ERR
+                INC     ECX
+                TEST    [DI].P_HW_ACCESS, HW_ACCESS_IO
+                JZ      SHORT PORTACCESS_ERR
+                CMP     NEW_TSS, FALSE
+                JE      SHORT PORTACCESS_ERR
+                MOV     DX, G_TSS_MEM_SEL
+                MOV     FS, DX
+                MOVZX   EBX, (TSS_STRUC PTR FS:[0]).TSS_BIT_MAP_OFF
+PORTACCESS_1:   BTR     DWORD PTR FS:[EBX], EAX
+                INC     EAX
+                LOOPD   PORTACCESS_1
+                MOV     I_EAX, 0
+                RET
+
+PORTACCESS_ERR: MOV     I_EAX, EACCES
+                OR      I_EFLAGS, FLAG_C
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F13H: _memaccess()
+;
+; Enable access to memory
+;
+; In:   EBX    First address
+;       ECX    Last address
+;       EDX    0: read access, 1:write access
+;
+; Out:  CY     Failed
+;       EAX    errno if failed (CY)
+;       EAX    Pointer to start of mapped memory area (NC)
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS13:          CMP     I_EDX, 1
+                JA      MEMACCESS_INV
+                MOV     EAX, I_EBX
+                TEST    EAX, 0FFFH
+                JNZ     MEMACCESS_ACC
+                MOV     ECX, I_ECX
+                INC     ECX
+                JNZ     SHORT MEMACCESS_01
+                OR      EAX, EAX
+                JZ      MEMACCESS_MEM
+                SUB     ECX, EAX
+                JMP     SHORT MEMACCESS_02
+MEMACCESS_01:   TEST    ECX, 0FFFH
+                JNZ     MEMACCESS_ACC
+                SUB     ECX, EAX
+                JBE     MEMACCESS_ACC
+MEMACCESS_02:   TEST    [DI].P_HW_ACCESS, HW_ACCESS_MEM
+                JZ      MEMACCESS_ACC
+                MOV     EBX, I_EBX
+                OR      EBX, PAGE_PRESENT OR PAGE_USER OR PAGE_LOCKED
+                CMP     I_EDX, 0
+                JE      SHORT MEMACCESS_RD
+                CMP     I_EBX, 0A0000H
+                JB      SHORT MEMACCESS_DNG     ; Danger!
+                CMP     I_ECX, 0BFFFFH
+                JBE     SHORT MEMACCESS_WR
+MEMACCESS_DNG:  TEST    [DI].P_HW_ACCESS, HW_ACCESS_WRITE
+                JZ      SHORT MEMACCESS_ACC
+MEMACCESS_WR:   OR      EBX, PAGE_WRITE
+MEMACCESS_RD:   MOV     EDX, SRC_NONE
+                SHR     ECX, 12
+                CALL    MAP_PHYS
+                TEST    EAX, EAX
+                JZ      SHORT MEMACCESS_MEM
+                MOV     I_EAX, EAX
+                RET
+
+MEMACCESS_INV:  MOV     I_EAX, EINVAL
+                OR      I_EFLAGS, FLAG_C
+                RET
+
+MEMACCESS_ACC:  MOV     I_EAX, EACCES
+                OR      I_EFLAGS, FLAG_C
+                RET
+
+MEMACCESS_MEM:  MOV     I_EAX, ENOMEM
+                OR      I_EFLAGS, FLAG_C
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F14H: __ioctl2()
+;
+; UNIX-like termio ioctl()
+;
+; In:   EBX     Handle
+;       ECX     Request code
+;       EDX     Argument
+;
+; Out:  EAX     Return value
+;       ECX     errno
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS14:          CMP     I_ECX, TCGETA
+                JE      SHORT TC_GETA
+                CMP     I_ECX, TCSETA
+                JE      SHORT TC_SETA
+                CMP     I_ECX, TCSETAW
+                JE      SHORT TC_SETA
+                CMP     I_ECX, TCSETAF
+                JE      SHORT TC_SETAF
+                CMP     I_ECX, TCFLSH
+                JE      IOCTL_FLUSH
+                CMP     I_ECX, TCXONC
+                JE      IOCTL_XONC
+                CMP     I_ECX, TCSBRK
+                JE      IOCTL_SBRK
+                CMP     I_ECX, _TCGA
+                JE      SHORT TCS_GETA
+                CMP     I_ECX, _TCSANOW
+                JE      SHORT TCS_SETA
+                CMP     I_ECX, _TCSADRAIN
+                JE      SHORT TCS_SETA
+                CMP     I_ECX, _TCSAFLUSH
+                JE      SHORT TCS_SETAF
+                CMP     I_ECX, FIONREAD
+                JE      IOCTL_NREAD
+                CMP     I_ECX, FGETHTYPE
+                JE      IOCTL_HTYPE
+                JMP     EMX_EINVAL
+
+                TALIGN  4
+TC_GETA:        MOV     EAX, I_EBX
+                MOV     ES, I_DS
+                MOV     EBX, I_EDX
+                CALL    TERMIO_GET
+TC_RET:         MOV     I_EAX, EAX
+                MOV     I_ECX, ECX
+                RET
+
+                TALIGN  4
+TC_SETAF:       MOV     EAX, I_EBX
+                CALL    TERMIO_FLUSH
+                OR      EAX, EAX
+                JNZ     SHORT TC_RET
+TC_SETA:        MOV     EAX, I_EBX
+                MOV     ES, I_DS
+                MOV     EBX, I_EDX
+                CALL    TERMIO_SET
+                JMP     SHORT TC_RET
+
+                TALIGN  4
+TCS_GETA:       MOV     EAX, I_EBX
+                MOV     ES, I_DS
+                MOV     EBX, I_EDX
+                CALL    TERMIOS_GET
+                JMP     SHORT TC_RET
+
+                TALIGN  4
+TCS_SETAF:      MOV     EAX, I_EBX
+                CALL    TERMIOS_FLUSH
+                OR      EAX, EAX
+                JNZ     SHORT TC_RET
+TCS_SETA:       MOV     EAX, I_EBX
+                MOV     ES, I_DS
+                MOV     EBX, I_EDX
+                CALL    TERMIOS_SET
+                JMP     SHORT TC_RET
+
+;
+; TCFLSH
+;
+                TALIGN  4
+IOCTL_FLUSH:    CMP     I_EBX, 0                ; stdin?
+                JNE     EMX_EBADF
+                CMP     I_EDX, 0                ; Flush input queue
+                JE      SHORT IOCTL_FLUSH_1
+                CMP     I_EDX, 1                ; Flush output queue
+                JE      EMX_OK                  ; Not implemented -- ignore
+                CMP     I_EDX, 2                ; Flush input & output queues
+                JNE     EMX_EINVAL              ; No  -> error
+IOCTL_FLUSH_1:  CALL    KBD_FLUSH
+                JMP     EMX_OK
+
+;
+; TCSBRK (not implemented)
+;
+                TALIGN  4
+IOCTL_SBRK:     JMP     EMX_OK
+
+;
+; TCXCONC (not yet implemented)
+;
+                TALIGN  4
+IOCTL_XONC:     JMP     EMX_OK
+
+                TALIGN  4
+IOCTL_NREAD:    CMP     I_EBX, 0                ; stdin?
+                JNE     SHORT IOCTL_NREAD2      ; No  -> check input status
+                TEST    STDIN_TERMIO.C_LFLAG, IDEFAULT OR ICANON ; termio?
+                JNZ     SHORT IOCTL_NREAD2      ; No  -> check input status
+                CALL    STDIN_AVAIL
+IOCTL_NREAD1:   MOV     EBX, I_EDX
+                MOV     ES, I_DS
+                MOV     ES:[EBX], EAX
+                JMP     EMX_OK
+
+IOCTL_NREAD2:   MOV     EBX, I_EBX              ; Get file handle
+                MOV     AX, 4406H               ; IOCTL: Check input status
+                INT     21H
+                JC      SHORT IOCTL_ERR         ; Error -> done
+                OR      AL, AL                  ; 00H=not ready, 0FFH=ready
+                MOV     EAX, 0                  ; No characters ready
+                JZ      SHORT IOCTL_NREAD1      ; Not ready -> 0 characters
+                INC     EAX                     ; Ready     -> 1 character
+                JMP     SHORT IOCTL_NREAD1
+
+IOCTL_ERR:      MOV     I_ECX, EAX
+                MOV     I_EAX, -1
+                RET
+
+HT_FILE         =       0
+HT_UPIPE        =       1
+HT_NPIPE        =       2
+HT_DEV_OTHER    =       3
+HT_DEV_NUL      =       4
+HT_DEV_CON      =       5
+HT_DEV_CLK      =       7
+
+                TALIGN  4
+IOCTL_HTYPE:    MOV     AX, 4400H
+                MOV     EBX, I_EBX
+                INT     21H
+                JC      SHORT HTYPE_ERR
+                MOV     ECX, HT_FILE
+                TEST    EDX, 80H
+                JZ      SHORT HTYPE_RET
+                MOV     ECX, HT_DEV_CON
+                TEST    EDX, 03H
+                JNZ     SHORT HTYPE_RET
+                MOV     ECX, HT_DEV_NUL
+                TEST    EDX, 04H
+                JNZ     SHORT HTYPE_RET
+                MOV     ECX, HT_DEV_CLK
+                TEST    EDX, 08H
+                JNZ     SHORT HTYPE_RET
+                MOV     ECX, HT_DEV_OTHER
+HTYPE_RET:      MOV     EBX, I_EDX
+                MOV     ES, I_DS
+                MOV     ES:[EBX], ECX
+                JMP     EMX_OK
+
+HTYPE_ERR:      MOV     I_ECX, EAX
+                MOV     I_EAX, -1
+                RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F15H: __alarm()
+;
+; Set alarm clock
+;
+; In:   EDX     Seconds
+;
+; Out:  EAX     Time remaining
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS15:          MOV     EAX, I_EDX
+                MOV     ECX, 91
+                MUL     ECX                     ; Multiply by 18.2
+                ADD     EAX, 4
+                ADC     EDX, 0
+                MOV     ECX, 5
+                CMP     EDX, ECX                ; Overflow?
+                JAE     SHORT ALARM_OV          ; Yes -> use maximum value
+                DIV     ECX
+ALARM_SET:      MOV     BX, DI
+                MOV     DX, TT_ALARM
+                CALL    SET_TIMER
+                MOV     I_EAX, 0
+                JC      SHORT SYS15_RET
+                MOV     ECX, 5
+                MUL     ECX                     ; Divide by 18.2
+                MOV     ECX, 91
+                DIV     ECX
+                MOV     I_EAX, EAX
+SYS15_RET:      RET
+
+ALARM_OV:       MOV     EAX, MAX_32             ; Use maximum value
+                JMP     SHORT ALARM_SET
+
+; ----------------------------------------------------------------------------
+; AX=7F16H: Used internally for polling the keyboard
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS16:          TEST    I_CS, 3                 ; Called from user code?
+                JNZ     SYSCALL_ERROR           ; Yes -> error
+                MOV     RM_AX, 7F16H
+                CALL    INT_RM
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F17H: __sleep()
+;
+; Suspend process
+;
+; In:   EDX     Seconds
+;
+; Out:  EAX     Remaining seconds
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS17:          MOV     EAX, I_EDX
+                TEST    EAX, EAX
+                JZ      SHORT SYS17_RET
+                MOV     ECX, 91
+                MUL     ECX                     ; Multiply by 18.2 = 91/5
+                ADD     EAX, 4
+                ADC     EDX, 0
+                MOV     ECX, 5
+                CMP     EDX, ECX                ; Overflow?
+                JAE     SHORT SLEEP_OV
+                DIV     ECX
+SLEEP_DO:       MOV     BX, DI
+                CALL    SLEEP
+                MOV     ECX, 5
+                MUL     ECX                     ; Divide by 18.2
+                MOV     ECX, 91
+                DIV     ECX
+SYS17_RET:      MOV     I_EAX, EAX
+                RET
+
+SLEEP_OV:       MOV     EAX, MAX_32             ; Use maximum value
+                JMP     SHORT SLEEP_DO
+
+; ----------------------------------------------------------------------------
+; AX=7F18H: __chsize()
+;
+; Change file size
+;
+; In:   EBX     File handle
+;       EDX     File size
+;
+; Out:  CY      Error
+;       EAX     errno (CY)
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS18:          MOV     EBX, I_EBX              ; File handle
+                MOV     EDX, I_EDX              ; Distance
+                MOV     AL, 0                   ; SEEK_SET
+                MOV     AH, 42H                 ; Move file pointer
+                INT     21H
+                JC      SHORT SYS18_RET
+                MOV     EBX, I_EBX              ; File handle
+                MOV     ECX, 0                  ; Number of bytes
+                MOV     EDX, 0                  ; Buffer
+                MOV     AH, 40H                 ; Write handle
+                INT     21H
+                JC      SHORT SYS18_RET
+                XOR     EAX, EAX
+SYS18_RET:      MOV     I_EAX, EAX
+                RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F19H: __fcntl()
+;
+; Unix-like file control
+;
+; In:   EBX     File handle
+;       ECX     Request code
+;       EDX     Argument
+;
+; Out:  EAX     Return value
+;       ECX     errno
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS19:          CMP     I_ECX, F_SETFL
+                JE      SHORT FCNTL_SETFL
+                CMP     I_ECX, F_SETFD
+                JE      SHORT FCNTL_SETFD
+                CMP     I_ECX, F_GETFD
+                JE      SHORT FCNTL_GETFD
+                CMP     I_ECX, F_GETFL
+                JE      FCNTL_GETFL
+EMX_EINVAL:     MOV     I_ECX, EINVAL
+                MOV     I_EAX, -1
+                RET
+
+                TALIGN  4
+FCNTL_GETFD:    MOV     BX, WORD PTR I_EBX
+                CMP     BX, MAX_FILES
+                JAE     EMX_EBADF
+                XOR     EAX, EAX
+                SHL     BX, 1
+                TEST    [DI].P_HFLAGS[BX], HF_NOINHERIT
+                JZ      SHORT GETFD_1
+                OR      EAX, 1                  ; FD_CLOEXEC
+GETFD_1:        MOV     I_EAX, EAX
+                MOV     I_ECX, 0
+                RET
+
+                TALIGN  4
+FCNTL_SETFD:    MOV     BX, WORD PTR I_EBX
+                CMP     BX, MAX_FILES
+                JAE     EMX_EBADF
+                SHL     BX, 1
+                AND     [DI].P_HFLAGS[BX], NOT HF_NOINHERIT
+                TEST    I_EDX, 1                ; FD_CLOEXEC
+                JZ      SHORT SETFD_1
+                OR      [DI].P_HFLAGS[BX], HF_NOINHERIT
+SETFD_1:        JMP     SHORT EMX_OK
+
+                TALIGN  4
+FCNTL_SETFL:    MOV     BX, WORD PTR I_EBX
+                CMP     BX, MAX_FILES
+                JAE     SHORT EMX_EBADF
+                SHL     BX, 1
+                MOV     EAX, I_EDX
+                TEST    EAX, NOT (O_NDELAY OR O_APPEND)
+                JNZ     SHORT EMX_EINVAL
+                .ERRE   O_NDELAY EQ HF_NDELAY
+                .ERRE   O_APPEND EQ HF_APPEND
+                AND     [DI].P_HFLAGS[BX], NOT (HF_NDELAY OR HF_APPEND)
+                OR      [DI].P_HFLAGS[BX], AX
+                CMP     I_EBX, 0                ; stdin?
+                JNE     SHORT EMX_OK
+                MOV     STDIN_FL, EAX
+                TALIGN  4
+EMX_OK:         MOV     I_ECX, 0
+                MOV     I_EAX, 0
+                RET
+
+                TALIGN  4
+FCNTL_GETFL:    MOV     BX, WORD PTR I_EBX
+                CMP     BX, MAX_FILES
+                JAE     SHORT EMX_EBADF
+                SHL     BX, 1
+                XOR     EAX, EAX
+                MOV     AX, [DI].P_HFLAGS[BX]
+                .ERRE   O_NDELAY EQ HF_NDELAY
+                .ERRE   O_APPEND EQ HF_APPEND
+                AND     AX, HF_NDELAY OR HF_APPEND
+                MOV     I_EAX, EAX
+                MOV     I_ECX, 0
+                RET
+
+                TALIGN  4
+EMX_EBADF:      MOV     I_ECX, EBADF
+                MOV     I_EAX, -1
+                RET
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F1AH: __pipe()
+;
+; Create unnamed pipe
+;
+; In:   ECX     Size of pipe
+;       EDX     Pointer to storage for two handles (two DWORDs)
+;
+; Out:  EAX     0 (success) or -1 (failure)
+;       ECX     errno
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS1A:          MOV     I_ECX, ENOSYS
+                MOV     I_EAX, -1
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F1BH: __fsync()
+;
+; Update file system
+;
+; In:   EBX     File handle
+;
+; Out:  EAX     0 (success) or -1 (failure)
+;       ECX     errno
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS1B:          MOV     I_ECX, ENOSYS
+                MOV     I_EAX, -1
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F1CH: __fork()
+;
+; Duplicate process
+;
+;
+; Out: EAX      Process ID or 0 (in new process) or -1 (failure)
+;      ECX      errno (0 if successful)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS1C:          MOV     I_ECX, ENOSYS
+                MOV     I_EAX, -1
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F1DH: __scrsize()
+;
+; Get number of rows and columns
+;
+; In:   EDX     Pointer to structure
+;
+; Out:  --
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS1D:          MOV     EBX, I_EDX
+                MOV     ES, I_DS
+                MOVZX   EAX, VWIDTH
+                MOV     DWORD PTR ES:[EBX+0], EAX
+                MOVZX   EAX, VHEIGHT
+                MOV     DWORD PTR ES:[EBX+4], EAX
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F1EH: __select()
+;
+; Synchronous I/O multiplexing
+;
+; In:   EDX     pointer to structure
+;
+; Out:  EAX     0 (timeout), > 0 (ready) or -1 (failure)
+;       ECX     errno (0 if successful)
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS1E:          AND     [DI].P_FLAGS, NOT PF_SLEEP_FLAG ; Clear counter flag
+                MOV     SEL_COUNT, 0            ; No ready handles
+                MOV     ESI, I_EDX              ; Get pointer to structure
+                MOV     ES, I_DS                ; and segment register
+                ASSUME  ESI:NEAR32 PTR SELECT_ARGS
+                MOV     EBX, ES:[ESI].SELA_TIMEOUT ; Get timeout pointer
+                TEST    EBX, EBX                ; NULL pointer?
+                JZ      SHORT SELECT_LOOP       ; Yes -> indefinite wait
+                ASSUME  EBX:NEAR32 PTR TIMEVAL
+                MOV     EAX, ES:[EBX].TV_USEC   ; Get microseconds
+                XOR     EDX, EDX
+                MOV     ECX, 54945
+                DIV     ECX                     ; Convert to timer ticks
+                PUSH    EAX                     ; Save ticks for microseconds
+                MOV     EAX, ES:[EBX].TV_SEC    ; Get seconds
+                ASSUME  EBX:NOTHING
+                MOV     ECX, 91
+                MUL     ECX                     ; Multiply by 18.2 = 91/5
+                ADD     EAX, 4
+                ADC     EDX, 0
+                MOV     ECX, 5
+                CMP     EDX, ECX
+                JAE     SHORT SELECT_OV1
+                DIV     ECX
+                POP     ECX                     ; Ticks for microseconds
+                ADD     EAX, ECX                ; Total number of ticks
+                JC      EMX_EINVAL              ; Overflow -> error
+                JZ      SHORT SELECT_ONCE       ; Zero -> return after one loop
+                MOV     DX, TT_SLEEP            ; Set `sleep' timer
+                MOV     BX, DI                  ; Process table entry
+                CALL    SET_TIMER
+                JC      EMX_EINVAL              ; Table overflow -> error
+                JMP     SHORT SELECT_LOOP       ; Start loop
+
+SELECT_OV1:     POP     ECX                     ; Ticks for microseconds
+                JMP     EMX_EINVAL              ; Error
+
+SELECT_ONCE:    OR      [DI].P_FLAGS, PF_SLEEP_FLAG ; Return after first loop
+                ASSUME  DI:NOTHING
+                LEA     DI, SEL_RBITS           ; Clear all bits in the
+                MOV_ES_DS                       ; bitmap of ready handles
+                MOV     CX, FD_SETSIZE/8
+                XOR     AL, AL
+                REP     STOSB
+                MOV     ES, I_DS
+;
+; This is the main loop
+;
+SELECT_LOOP:    MOV     BX, PROCESS_PTR
+                ASSUME  BX:PTR PROCESS
+                MOV     EAX, [BX].P_SIG_BLOCKED ; Compute set of pending,
+                NOT     EAX                     ; unblocked signals
+                AND     EAX, [BX].P_SIG_PENDING
+                ASSUME  BX:NOTHING
+;
+; TODO: Deliver signals set to SIG_DFL now
+; TODO: Ignore signals set to SIG_IGN
+;
+                JNZ     SELECT_INTR             ; Signal -> return EINTR
+                MOV     EDI, ES:[ESI].SELA_READFDS ; Get readfds pointer
+                TEST    EDI, EDI                ; NULL pointer?
+                JZ      SELECT_TIME             ; Yes -> wait until timeout
+                XOR     EBX, EBX                ; Start with handle 0
+SELECT_POLL:    CMP     EBX, ES:[ESI].SELA_NFDS ; All handles checked?
+                JAE     SELECT_CHECK            ; Yes -> any ready handles?
+                BT      DWORD PTR ES:[EDI], EBX ; Handle in readfds bitmap?
+                JNC     SELECT_NEXT             ; No  -> next handle
+                CMP     EBX, 0                  ; stdin?
+                JNZ     SHORT SELECT_TEST       ; No  -> check input status
+                TEST    STDIN_TERMIO.C_LFLAG, IDEFAULT ; termio?
+                JNZ     SHORT SELECT_TEST       ; No  -> check input status
+                CALL    STDIN_AVAIL             ; Get number of available chars
+                TEST    EAX, EAX                ; Any characters available?
+                JNZ     SHORT SELECT_HIT        ; Yes -> handle ready
+                JMP     SHORT SELECT_NEXT       ; Next handle
+
+SELECT_TEST:    PUSH    EBX
+                PUSH    ESI
+                PUSH    EDI
+                MOV     AX, 4406H               ; IOCTL: Check input status
+                INT     21H
+                POP     EDI
+                POP     ESI
+                POP     EBX
+                JC      SELECT_ERR              ; Error -> done
+                TEST    AL, AL                  ; 00H=not ready, 0FFH=ready
+                JZ      SHORT SELECT_NEXT       ; Not ready -> next handle
+SELECT_HIT:     INC     SEL_COUNT               ; Increment # of ready handles
+                BTS     DWORD PTR SEL_RBITS, EBX ; Set bit in bitmap
+SELECT_NEXT:    INC     EBX                     ; Next handle
+                JMP     SELECT_POLL             ; Check next handle
+
+;
+; Having looped though the handles, check if a handle is ready
+;
+SELECT_CHECK:   CMP     SEL_COUNT, 0            ; Are there ready handles?
+                JNE     SHORT SELECT_READY      ; Yes -> success
+SELECT_TIME:    MOV     EBX, ES:[ESI].SELA_TIMEOUT ; Get pointer to timeout
+                TEST    EBX, EBX                ; NULL pointer?
+                JZ      SELECT_LOOP             ; Yes -> indefinite wait
+                MOV     BX, PROCESS_PTR         ; Process table entry
+                TEST    (PROCESS PTR [BX]).P_FLAGS, PF_SLEEP_FLAG ; Timer down?
+                JZ      SELECT_LOOP             ; No  -> check handles again
+;
+; Time out, clear all sets
+;
+                MOV     EDI, ES:[ESI].SELA_READFDS
+                CALL    CLEAR_FDSET
+                MOV     EDI, ES:[ESI].SELA_WRITEFDS
+                CALL    CLEAR_FDSET
+                MOV     EDI, ES:[ESI].SELA_EXCEPTFDS
+                CALL    CLEAR_FDSET
+                MOV     I_EAX, 0                ; Time out
+                MOV     I_ECX, 0                ; No error
+                JMP     SELECT_RET              ; Done
+
+;
+; At least one handle is ready
+;
+SELECT_READY:   MOVZX   EAX, SEL_COUNT          ; Return number of ready
+                MOV     I_EAX, EAX              ; handles
+                MOV     I_ECX, 0                ; No error
+                PUSH    ESI                     ; Save pointer to structure
+                LEA     ESI, SEL_RBITS          ; Copy bitmap of ready handles
+                MOV     ECX, FD_SETSIZE/8       ; to readfds
+                REP     MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
+                POP     ESI                     ; Restore pointer to structure
+                MOV     EDI, ES:[ESI].SELA_WRITEFDS ; Get writefds pointer
+                CALL    CLEAR_FDSET
+                MOV     EDI, ES:[ESI].SELA_EXCEPTFDS ; Get exceptfds pointer
+                CALL    CLEAR_FDSET
+SELECT_RET:     RET                             ; Done
+
+;
+; A signal occured while waiting in select().  Return EINTR and raise
+; the signal.
+;
+SELECT_INTR:    MOV     EAX, EINTR
+
+SELECT_ERR:     MOV     I_ECX, EAX              ; Return errno in ECX
+                MOV     I_EAX, -1               ; Error
+                JMP     SHORT SELECT_RET        ; Done
+
+;
+; Clear a fd_set object pointed to by ES:EDI if EDI is not NULL
+;
+                ALIGN   4
+CLEAR_FDSET     PROC    NEAR
+                TEST    EDI, EDI
+                JZ      SHORT FIN
+                MOV     ECX, FD_SETSIZE/8
+                XOR     AL, AL
+                MOV     ECX, FD_SETSIZE/8
+                REP     STOS BYTE PTR ES:[EDI]
+FIN:            RET
+CLEAR_FDSET     ENDP
+
+                ASSUME  ESI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F1FH: __syserrno()
+;
+; Return DOS error number for last syscall
+;
+; Out:  EAX     error number
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS1F:          MOV     I_EAX, 0
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F20H __stat()
+;
+; Get information about a path name
+;
+; In:  EDX      path name
+;      EDI      pointer to structure
+;
+; Out: EAX      0 (ok), -1 (error)
+;      ECX      errno (0 if successful)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  EDI:NEAR32 PTR STAT
+SYS20:          MOV     ESI, I_EDX              ; Pointer to path name
+                MOV     ES, I_DS
+;
+; Return ENOENT if the path name contains wildcard characters
+;
+                TALIGN  4
+NSTAT_WILD:     LODS    BYTE PTR ES:[ESI]
+                TEST    AL, AL
+                JZ      SHORT NSTAT_NOWILD
+                CMP     AL, "?"
+                JE      SHORT NSTAT_FAILURE1
+                CMP     AL, "*"
+                JNE     SHORT NSTAT_WILD
+NSTAT_FAILURE1: JMP     NSTAT_FAILURE
+
+NSTAT_NOWILD:   MOV     EDX, I_EDX              ; Pointer to path name
+                MOV     ESI, I_ESP              ; Allocate FIND_BUF in user
+                SUB     ESI, SIZE FIND_BUF      ; stack (same segment as path!)
+                ASSUME  ESI:NEAR32 PTR FIND_BUF
+                PUSH    DS
+                MOV     DS, I_DS
+                MOV     CX, 16H                 ; Dir & system & hidden
+                MOV     AH, 4EH                 ; Find first file
+                INT     21H
+                POP     DS
+                JC      NSTAT_10                ; Error -> root directory?
+                MOV     EDI, I_EDI              ; Pointer to structure
+                MOV     ES, I_DS                ; Use ES for user data segment
+                MOV     EAX, S_IFREG            ; File
+                TEST    ES:[ESI].FIND_ATTR, 10H ; Is it a directory?
+                JZ      SHORT NSTAT_1           ; No  -> it's a file
+                MOV     ES:[ESI].FIND_SIZE, 0   ; The size of a directory is 0
+                MOV     EAX, S_IFDIR OR ((S_IREAD+S_IWRITE+S_IEXEC) SHR 6) * 111Q
+                JMP     SHORT NSTAT_2
+                TALIGN  4
+NSTAT_1:        OR      EAX, (S_IREAD SHR 6) * 111Q ; Read-only access
+                TEST    ES:[ESI].FIND_ATTR, 01H ; Ready-only attribute set?
+                JNZ     SHORT NSTAT_2           ; Yes -> skip
+                OR      EAX, (S_IWRITE SHR 6) * 111Q ; Read-write access
+NSTAT_2:        MOV     ES:[EDI].ST_MODE, EAX   ; Set mode
+                MOVZX   EAX, ES:[ESI].FIND_ATTR ; Get attributes
+                MOV     ES:[EDI].ST_ATTR, EAX   ; and store them
+                MOV     EAX, ES:[ESI].FIND_SIZE ; Get size
+                MOV     ES:[EDI].ST_SIZE, EAX   ; and store it
+                MOV     CX, ES:[ESI].FIND_TIME  ; Get time
+                MOV     DX, ES:[ESI].FIND_DATE  ; and date
+                CALL    PACKED_2_UNIX           ; and convert them to time_t
+NSTAT_MORE:     MOV     ES:[EDI].ST_ATIME, EAX  ; Time of last access
+                MOV     ES:[EDI].ST_MTIME, EAX  ; Time of last modification
+                MOV     ES:[EDI].ST_CTIME, EAX  ; Time of creation
+                MOV     ES:[EDI].ST_NLINK, 1    ; One link
+                MOV     ES:[EDI].ST_UID, 0      ; root
+                MOV     ES:[EDI].ST_GID, 0      ; root
+                MOV     ES:[EDI].ST_DEV, 0      ; Device numbers not supported
+                MOV     ES:[EDI].ST_RDEV, 0     ; Device numbers not supported
+                MOV     ES:[EDI].ST_RESERVED, 0 ; Nomen est omen
+                MOV     EAX, INO_NUMBER         ; Mock inode number
+                MOV     ES:[EDI].ST_INO, EAX
+                INC     INO_NUMBER
+                JNZ     SHORT NSTAT_INO_1
+                INC     INO_NUMBER
+NSTAT_INO_1:    JMP     EMX_OK                  ; Done
+
+;
+; Not found -- check for root directory
+;
+; Get current working directory and save it. Then try to change to the
+; "directory" given as argument to __stat(). If successful, it's the
+; root directory: set the structure appropriately and restore the
+; previous working directory. Otherwise, the file/directory does not
+; exist (or it's a device -- which is not supported by this implementation
+; of stat).
+;
+                TALIGN  4
+NSTAT_10:       MOV     EBX, I_EDX
+                MOV     ES, I_DS
+                MOV     AL, ES:[EBX]
+                CALL    UPPER
+                CMP     AL, "A"
+                JB      SHORT NSTAT_11
+                CMP     AL, "Z"
+                JA      SHORT NSTAT_11
+                CMP     BYTE PTR ES:[EBX+1], ":"
+                JE      SHORT NSTAT_12
+NSTAT_11:       MOV     AH, 19H
+                INT     21H
+                ADD     AL, "A"
+NSTAT_12:       MOV     STAT_CWD, AL
+                SUB     AL, "A" - 1
+                MOV     DL, AL
+                LEA     ESI, STAT_CWD + 3
+                MOV     AH, 47H
+                INT     21H
+                JC      SHORT NSTAT_FAILURE
+                PUSH    DS
+                MOV     EDX, I_EDX
+                MOV     DS, I_DS
+                MOV     AH, 3BH
+                INT     21H
+                POP     DS
+                JC      SHORT NSTAT_FAILURE
+                LEA     EDX, STAT_CWD
+                MOV     AH, 3BH
+                INT     21H
+                MOV     EDI, I_EDI
+                MOV     ES, I_DS
+                MOV     ES:[EDI].ST_MODE, S_IFDIR+((S_IREAD+S_IWRITE+S_IEXEC) SHR 6)*111Q
+                MOV     ES:[EDI].ST_ATTR, 0     ; Look here to find out about
+                                                ; root directory (not 10H!)
+                MOV     ES:[EDI].ST_SIZE, 0
+                XOR     EAX, EAX
+                JMP     NSTAT_MORE
+
+                TALIGN  4
+NSTAT_FAILURE:  MOV     I_EAX, -1
+                MOV     I_ECX, ENOENT
+                RET
+
+                ASSUME  ESI:NOTHING
+                ASSUME  EDI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F21H __fstat()
+;
+; Get information about an open file
+;
+; In:  EBX      file handle
+;      EDI      pointer to structure
+;
+; Out: EAX      0 (ok), -1 (error)
+;      ECX      errno (0 if successful)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  EDI:NEAR32 PTR STAT
+SYS21:          MOV     EBX, I_EBX
+                MOV     AX, 4400H
+                INT     21H
+                JC      FSTAT_ERROR
+                MOV     EDI, I_EDI
+                MOV     ES, I_DS
+                TEST    DL, 80H                 ; Device?
+                JNZ     FSTAT_DEV
+                MOV     ES:[EDI].ST_MODE, S_IFREG
+                MOV     ES:[EDI].ST_ATTR, 0
+                MOV     ES:[EDI].ST_RESERVED, 0
+                MOV     AX, 5700H
+                INT     21H
+                JC      FSTAT_ERROR
+                CALL    PACKED_2_UNIX
+                MOV     ES:[EDI].ST_ATIME, EAX
+                MOV     ES:[EDI].ST_MTIME, EAX
+                MOV     ES:[EDI].ST_CTIME, EAX
+                MOV     AX, 4201H
+                MOV     EDX, 0
+                INT     21H
+                JC      FSTAT_ERROR
+                MOV     ESI, EAX
+                MOV     AX, 4202H
+                MOV     EDX, 0
+                INT     21H
+                JC      FSTAT_ERROR
+                MOV     ES:[EDI].ST_SIZE, EAX
+                MOV     AX, 4200H
+                MOV     EDX, ESI
+                INT     21H
+                JC      FSTAT_ERROR
+                JMP     SHORT FSTAT_MORE
+
+                TALIGN  4
+FSTAT_DEV:      MOV     ES:[EDI].ST_MODE, S_IFCHR
+                MOV     ES:[EDI].ST_SIZE, 0
+                MOV     ES:[EDI].ST_ATIME, 0
+                MOV     ES:[EDI].ST_MTIME, 0
+                MOV     ES:[EDI].ST_CTIME, 0
+FSTAT_MORE:     MOV     EAX, INO_NUMBER
+                MOV     ES:[EDI].ST_INO, EAX
+                INC     INO_NUMBER
+                JNZ     SHORT FSTAT_INO_1
+                INC     INO_NUMBER
+FSTAT_INO_1:    MOV     ES:[EDI].ST_UID, 0
+                MOV     ES:[EDI].ST_GID, 0
+                MOV     ES:[EDI].ST_NLINK, 1
+                MOV     ES:[EDI].ST_DEV, 0
+                MOV     ES:[EDI].ST_RDEV, 0
+                OR      ES:[EDI].ST_MODE, ((S_IREAD+S_IWRITE) SHR 6) * 111Q
+                JMP     EMX_OK
+
+FSTAT_ERROR:    MOV     I_EAX, -1
+                MOV     I_ECX, EAX
+                RET
+
+                ASSUME  EDI:NOTHING
+
+
+; ----------------------------------------------------------------------------
+; AX=7F23H __filesys()
+;
+; Get name of file-system driver
+;
+; In:  EDX      pointer to drive name
+;      EDI      pointer to output buffer
+;      ECX      size of output buffer
+;
+; Out: EAX      0 (ok) or -1 (error)
+;      ECX      errno (0 if successful)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS23:          MOV     EBX, I_EDX
+                MOV     ES, I_DS
+                MOV     AL, ES:[EBX+0]
+                CALL    UPPER
+                CMP     AL, "A"
+                JB      SHORT FILESYS_INVALID
+                CMP     AL, "Z"
+                JA      SHORT FILESYS_INVALID
+                CMP     BYTE PTR ES:[EBX+1], ":"
+                JNE     SHORT FILESYS_INVALID
+                CMP     BYTE PTR ES:[EBX+2], 0
+                JNE     SHORT FILESYS_INVALID
+                CMP     I_ECX, 4
+                JB      SHORT FILESYS_2BIG
+                SUB     AL, "A"-1
+                MOV     BL, AL
+                MOV     AX, 4409H
+                INT     21H
+                JC      SHORT FILESYS_ERROR
+                LEA     ESI, $FAT
+                TEST    DX, 1 SHL 12
+                JZ      SHORT FILESYS_1
+                LEA     ESI, $LAN
+FILESYS_1:      MOV     ECX, 4
+                MOV     EDI, I_EDI
+                REP     MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
+                JMP     EMX_OK
+
+FILESYS_2BIG:   MOV     EAX, E2BIG
+                JMP     SHORT FILESYS_ERROR
+
+FILESYS_INVALID:MOV     EAX, EINVAL
+FILESYS_ERROR:  MOV     I_EAX, -1
+                MOV     I_ECX, EAX
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F24H __utimes()
+;
+; Set access and modification time of a file
+;
+; In:  EDX      pointer to path name
+;      ESI      pointer to array of structures
+;
+; Out: EAX      0 (ok) or -1 (error)
+;      ECX      errno (0 if successful)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS24:          PUSH    PROCESS_PTR
+                MOV     PROCESS_PTR, NO_PROCESS
+                PUSH    DS
+                MOV     EDX, I_EDX
+                MOV     DS, I_DS
+                ASSUME  DS:NOTHING
+                MOV     AX, 3D11H
+                INT     21H
+                POP     DS
+                ASSUME  DS:SV_DATA
+                JC      SHORT UTIMES_ERROR
+                MOV     EBX, EAX
+                MOV     ESI, I_ESI
+                MOV     ES, I_DS
+                MOV     EAX, ES:[ESI+8]         ; Modification time
+                CALL    UNIX_2_PACKED
+                MOV     AX, 5701H
+                INT     21H
+                JC      SHORT UTIMES_1
+                MOV     AH, 3EH
+                INT     21H
+                JC      SHORT UTIMES_ERROR
+                MOV     I_EAX, 0
+                MOV     I_ECX, 0
+UTIMES_RET:     POP     PROCESS_PTR
+                RET
+
+UTIMES_1:       PUSH    EAX
+                MOV     AH, 3EH
+                INT     21H
+                POP     EAX
+UTIMES_ERROR:   MOV     I_EAX, -1
+                MOV     I_ECX, EAX
+                JMP     SHORT UTIMES_RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F25H: __ftruncate()
+;
+; Truncate a file
+;
+; In:   EBX     File handle
+;       EDX     File size
+;
+; Out:  EAX     0 (ok), -1 (error)
+;       ECX     errno
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS25:          MOV     EBX, I_EBX              ; File handle
+                MOV     EDX, 0                  ; Distance
+                MOV     AL, 2                   ; SEEK_END
+                MOV     AH, 42H                 ; Move file pointer
+                INT     21H
+                JC      SHORT SYS25_ERR         ; Error ->
+                CMP     I_EDX, EAX              ; Truncating?
+                JNB     EMX_OK                  ; No  -> ignore request, OK
+                MOV     EBX, I_EBX              ; File handle
+                MOV     EDX, I_EDX              ; Distance
+                MOV     AL, 0                   ; SEEK_SET
+                MOV     AH, 42H                 ; Move file pointer
+                INT     21H
+                JC      SHORT SYS25_ERR         ; Error ->
+                MOV     EBX, I_EBX              ; File handle
+                MOV     ECX, 0                  ; Number of bytes
+                MOV     EDX, 0                  ; Buffer
+                MOV     AH, 40H                 ; Write handle
+                INT     21H
+                JNC     EMX_OK
+SYS25_ERR:      MOV     I_ECX, EAX
+                MOV     I_EAX, -1
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F26H: __clock()
+;
+; Processor time
+;
+; Out:  EAX     timer ticks of processor time used, low-order 32 bits
+;       EDX     high-order 32 bits
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS26:          MOV     EAX, CLOCK_HI
+                MOV     EBX, CLOCK_LO
+                CMP     EAX, CLOCK_HI
+                JNE     SHORT SYS26
+                MOV     ECX, 500
+                MUL     ECX
+                XCHG    EAX, EBX
+                MUL     ECX                     ; Multiply by 100 / 18.2
+                ADD     EDX, EBX
+                PUSH    EAX
+                MOV     EAX, EDX
+                XOR     EDX, EDX
+                MOV     ECX, 91
+                DIV     ECX
+                MOV     I_EDX, EAX
+                POP     EAX
+                DIV     ECX
+                MOV     I_EAX, EAX
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F27H: __ftime()
+;
+; Get current time
+;
+; In:  EDX     pointer to structure
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS27:          MOV     EDI, I_EDX
+                MOV     ES, I_DS
+                CALL    DO_FTIME
+                RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F28H: __umask()
+;
+; Set file permission mask
+;
+; In:  EDX      file permission mask
+;
+; Out: EAX      previous file permission mask
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS28:          MOV     AX, WORD PTR I_EDX
+                XCHG    AX, [DI].P_UMASK
+                MOVZX   EAX, AX
+                MOV     I_EAX, EAX
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F29H: __getppid()
+;
+; Get parent process ID
+;
+; Out: EAX      parent process ID
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS29:          MOV     EAX, [DI].P_PPID
+                MOV     I_EAX, EAX
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F2AH: __nls_memupr()
+;
+; Convert buffer to upper case
+;
+; In:  EDX      pointer to buffer
+;      ECX      size of buffer
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS2A:          MOV     AX, I_DS
+                MOV     ESI, I_EDX
+                MOV     EDI, OFFSET_1
+                MOV     ECX, I_ECX
+                MOV     RM_DX, DI               ; Offset of buffer
+                MOV     RM_CX, CX
+                CALL    MOVE_TO_RM
+                MOV     RM_AX, 7F2AH
+                CALL    INT_RM
+                MOV     AX, I_DS
+                MOV     EDI, I_EDX
+                MOV     ECX, I_ECX
+                CALL    MOVE_FROM_RM
+                RET
+
+
+
+; ----------------------------------------------------------------------------
+; AX=7F2BH: __open
+;
+; Open file
+;
+; In:  EDX      pointer to file name
+;      ECX      flags
+;
+; Out: EAX      handle or -1
+;      ECX      errno (0 if successful)
+;
+; ----------------------------------------------------------------------------
+;
+; Replace "/dev/null" with "nul"
+;
+SYS2B_NUL:      MOV     I_EDX, OFFSET $NUL      ; Use "nul" instead
+                MOV     SI, DS
+                JMP     SHORT SYS2B_1
+
+;
+; Replace "/dev/tty" with "con"
+;
+SYS2B_CON:      MOV     I_EDX, OFFSET $CON      ; Use "con" instead
+                MOV     SI, DS
+                JMP     SHORT SYS2B_1
+
+;
+; __open()
+;
+                TALIGN  4
+SYS2B:          LEA     ESI, $DEVNULL
+                MOV     EDI, I_EDX
+                MOV     ES, I_DS
+                CALL    STRCMP                  ; "/dev/null"?
+                JE      SHORT SYS2B_NUL         ; Yes -> use "nul"
+                LEA     ESI, $DEVTTY
+                MOV     EDI, I_EDX
+                CALL    STRCMP                  ; "/dev/tty"?
+                JE      SHORT SYS2B_CON         ; Yes -> use "con"
+                MOV     SI, I_DS
+SYS2B_1:        MOV     EDX, I_EDX              ; File name
+                MOV     AL, BYTE PTR I_ECX[0]   ; Open mode
+                MOV     AH, 3DH
+                PUSH    DS
+                MOV     DS, SI
+                INT     21H
+                POP     DS
+                JC      SHORT SYS2B_FAILED
+;
+; File exists
+;
+                MOV     EDX, I_ECX
+                AND     EDX, 30000H             ; O_CREAT|O_EXCL
+                CMP     EDX, 30000H             ; O_CREAT and O_EXCL set?
+                JE      SYS2B_EXFAIL            ; Yes -> fail
+                MOV     I_EAX, EAX              ; Save the handle
+SYS2B_OK:       TEST    I_ECX, 40000H           ; O_TRUNC set?
+                JZ      SHORT SYS2B_SUCCESS     ; No  -> don't truncate file
+                MOV     EBX, EAX                ; File handle
+                XOR     EDX, EDX                ; Distance = 0
+                MOV     AL, 0                   ; SEEK_SET
+                MOV     AH, 42H                 ; Move file pointer
+                INT     21H
+                JC      SHORT SYS2B_SUCCESS     ; Ignore error (device!)
+                MOV     EBX, I_EAX              ; File handle
+                MOV     ECX, 0                  ; Number of bytes
+                MOV     EDX, 0                  ; Buffer
+                MOV     AH, 40H                 ; Write handle
+                INT     21H                     ; Ignore error (device!)
+;
+; Opening the file succeeded.  Set the handle flags.
+;
+SYS2B_SUCCESS:  TEST    I_ECX, 80000H           ; O_NOINHERIT?
+                JZ      SHORT SYS2B_RET
+                MOV     BX, PROCESS_PTR
+                CMP     BX, NO_PROCESS
+                JE      SHORT SYS2B_RET
+                ASSUME  BX:PTR PROCESS
+                MOV     SI, WORD PTR I_EAX
+                SHL     SI, 1
+                OR      [BX].P_HFLAGS[SI], HF_NOINHERIT
+                ASSUME  BX:NOTHING
+SYS2B_RET:      MOV     I_ECX, 0                ; Success
+                RET
+
+;
+; Opening an existing file failed.
+;
+SYS2B_FAILED:   CMP     EAX, ENOENT             ; No such file?
+                JNE     SHORT SYS2B_ERR         ; No  -> fail
+                TEST    I_ECX, 10000H           ; O_CREAT?
+                JZ      SHORT SYS2B_ERR         ; No  -> fail
+;
+; Try to create the file
+;
+                MOV     EDX, I_EDX              ; File name
+                MOVZX   CX, BYTE PTR I_ECX[1]
+                MOV     AH, 3CH                 ; umask is applied by
+                PUSH    DS                      ; function 3CH
+                MOV     DS, SI
+                INT     21H
+                POP     DS
+                JC      SHORT SYS2B_ERR
+                MOV     I_EAX, EAX              ; Save the handle
+                JMP     SHORT SYS2B_SUCCESS     ; Done
+
+SYS2B_ERR:      MOV     I_ECX, EAX
+                MOV     I_EAX, -1
+                RET
+
+SYS2B_EXFAIL:   MOV     EBX, EAX                ; File handle
+                MOV     AH, 3EH                 ; Close handle
+                INT     21H
+                MOV     EAX, EEXIST
+                JMP     SHORT SYS2B_ERR
+
+; ----------------------------------------------------------------------------
+; AX=7F2CH: __newthread
+;
+; Notify emx of new thread
+;
+; In:  EDX      Thread ID
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS2C:          MOV     I_ECX, ENOSYS
+                MOV     I_EAX, -1
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F2DH: __endthread
+;
+; Notify emx of end of thread
+;
+; In:  EDX      Thread ID
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS2D:          MOV     I_ECX, ENOSYS
+                MOV     I_EAX, -1
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F2EH: __waitpid()
+;
+; Wait for child process
+;
+; In:   EDX     Process ID
+;       ECX     Options
+;
+; Out:  EAX     Process ID of child process (-1 if no children)
+;       ECX     errno
+;       EDX     Termination status
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS2E:          MOV     I_ECX, ENOSYS
+                MOV     I_EDX, 0
+                MOV     I_EAX, -1
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F2FH: __read_kbd()
+;
+; Keyboard input
+;
+; In:   EDX     flags (bit 0: echo, bit 1: wait, bit 2:sig)
+;
+; Out:  EAX     Character (or -1)
+;
+; ----------------------------------------------------------------------------
+
+RK_ECHO         =       1
+RK_WAIT         =       2
+RK_SIG          =       4
+
+                TALIGN  4
+SYS2F:          TEST    I_EDX, RK_SIG
+                JNZ     SHORT RKBD_SIG
+                TEST    I_EDX, RK_WAIT
+                JNZ     SHORT RKBD_WAIT
+                MOV     DL, 0FFH
+                MOV     AH, 06H
+                INT     21H
+                JZ      SHORT RKBD_NOTHING
+                MOVZX   EAX, AL
+RKBD_ECHO:      TEST    I_EDX, RK_ECHO
+                JZ      RKBD_RET
+                PUSH    EAX
+                MOV     DL, AL
+                MOV     AH, 06H
+                INT     21H
+                POP     EAX
+RKBD_RET:       MOV     I_EAX, EAX
+                RET
+
+RKBD_WAIT:      MOV     AH, 07H
+                INT     21H
+                MOVZX   EAX, AL
+                JMP     SHORT RKBD_ECHO
+
+RKBD_SIG:       TEST    I_EDX, RK_WAIT
+                JNZ     SHORT RKBD_SIG_WAIT
+                MOV     AH, 0BH
+                INT     21H
+                OR      AL, AL
+                JZ      SHORT RKBD_NOTHING
+RKBD_SIG_WAIT:  TEST    I_EDX, RK_ECHO
+                JNZ     SHORT RKBD_SIG_ECHO
+                MOV     AH, 08H
+                INT     21H
+                MOVZX   EAX, AL
+                JMP     SHORT RKBD_RET
+
+RKBD_SIG_ECHO:  MOV     AH, 01H
+                INT     21H
+                MOVZX   EAX, AL
+                JMP     SHORT RKBD_RET
+
+RKBD_NOTHING:   MOV     EAX, -1
+                JMP     SHORT RKBD_RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F30H: __sleep2()
+;
+; Suspend process
+;
+; In:   EDX     Milliseconds
+;
+; Out:  EAX     0
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS30:          MOV     I_EAX, 0                ; Return value
+                MOV     EAX, I_EDX
+                OR      EAX, EAX
+                JZ      SHORT SYS30_RET
+                MOV     ECX, 91
+                MUL     ECX                     ; Multiply by 0.0182 = 91/5000
+                ADD     EAX, 4999
+                ADC     EDX, 0
+                MOV     ECX, 5000
+                DIV     ECX
+                MOV     BX, DI
+                CALL    SLEEP                   ; Suspend process
+SYS30_RET:      RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F31H: __unwind2()
+;
+; Unwind signal handlers for longjmp()
+;
+; Currently not used by the DOS version of emx.
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS31:          RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F32H: __pause()
+;
+; Wait for signal
+;
+; Currently not implemented
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS32:          RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F33H: __execname()
+;
+; Get the name of the executable file
+;
+; In:   EDX     Buffer
+;       ECX     Buffer size
+;
+; Out:  EAX     0 if successful, -1 otherwise
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS33:          MOV     I_EAX, -1
+                RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F34H: __initthread()
+;
+; Install exception handler in new thread
+;
+; In:   EDX     Pointer to EXCEPTIONREGISTRATIONRECORD
+;
+; Out:  EAX     0 if successful, -1 otherwise
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS34:          MOV     I_EAX, -1
+                RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F35H: __sigaction()
+;
+; Examine or specify action for a signal
+;
+; In:   ECX     Signal number
+;       EDX     Pointer to sigaction structure (input)
+;       EBX     Pointer to sigaction structure (output)
+;
+; Out:  EAX     0 if successful, -1 otherwise
+;       ECX     errno (0 if no error)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS35:          MOV     EAX, I_ECX
+                MOV     EDX, I_EDX
+                MOV     EBX, I_EBX
+                MOV     ES, I_DS
+                CALL    DO_SIGACTION
+                MOV     I_ECX, EAX
+                MOV     I_EAX, 0
+                TEST    EAX, EAX
+                JZ      SHORT SYS35_RET
+                MOV     I_EAX, -1
+SYS35_RET:      RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F36H: __sigpending()
+;
+; Query set of pending signals
+;
+; In:   EDX     Pointer to sigset_t (output)
+;
+; Out:  EAX     0 if successful, -1 otherwise
+;       ECX     errno (0 if no error)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS36:          MOV     EAX, [DI].P_SIG_BLOCKED
+                AND     EAX, [DI].P_SIG_PENDING
+                SHR     EAX, 1
+                MOV     EBX, I_EDX
+                MOV     ES, I_DS
+                MOV     ES:[EBX], EAX
+                MOV     I_EAX, 0
+                MOV     I_ECX, 0
+                RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F37H: __sigprocmask()
+;
+; Examine or change the signal mask
+;
+; In:   ECX     Manner in which to set the mask
+;       EDX     Pointer to sigset_t (input)
+;       EBX     Pointer to sigset_t (output)
+;
+; Out:  EAX     0 if successful, -1 otherwise
+;       ECX     errno (0 if no error)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS37:          PUSH    [DI].P_SIG_BLOCKED
+                MOV     EBX, I_EDX
+                TEST    EBX, EBX
+                JZ      SHORT SPM_NO_INPUT
+                MOV     ES, I_DS
+                MOV     EAX, ES:[EBX]
+                SHL     EAX, 1
+                CMP     I_ECX, SIG_BLOCK
+                JE      SHORT SPM_BLOCK
+                CMP     I_ECX, SIG_UNBLOCK
+                JE      SHORT SPM_UNBLOCK
+                CMP     I_ECX, SIG_SETMASK
+                JE      SHORT SPM_SETMASK
+                POP     EAX
+                MOV     I_EAX, -1
+                MOV     I_ECX, EINVAL
+                RET
+
+SPM_UNBLOCK:    NOT     EAX
+                AND     EAX, [DI].P_SIG_BLOCKED
+                JMP     SHORT SPM_SETMASK
+
+SPM_BLOCK:      OR      EAX, [DI].P_SIG_BLOCKED
+SPM_SETMASK:    AND     EAX, SIG_BLOCK_MASK
+                MOV     [DI].P_SIG_BLOCKED, EAX
+SPM_NO_INPUT:   POP     EAX
+                MOV     EBX, I_EBX
+                TEST    EBX, EBX
+                JZ      SHORT SPM_NO_OUTPUT
+                SHR     EAX, 1
+                MOV     ES:[EBX], EAX
+SPM_NO_OUTPUT:  MOV     I_EAX, 0
+                MOV     I_ECX, 0
+                RET
+
+
+; ----------------------------------------------------------------------------
+; AX=7F38H: __sigsuspend()
+;
+; Replace signal mask and wait for signal
+;
+; In:   EDX     Pointer to sigset_t (input)
+;
+; Out:  EAX     0 if successful, -1 otherwise
+;       ECX     errno (0 if no error)
+;
+; Currently not implemented
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS38:          MOV     I_EAX, -1
+                MOV     I_ECX, ENOSYS
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F39H: __imphandle()
+;
+; Import a file handle
+;
+; In:   EDX     File handle
+;
+; Out:  EAX     Relocated file handle (success) or -1 (failure)
+;       ECX     errno (0 if no error)
+;
+; ----------------------------------------------------------------------------
+
+                TALIGN  4
+SYS39:          MOV     I_ECX, ENOSYS
+                MOV     I_EAX, -1
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F3AH: __fpuemu()
+;
+; Interface for floating point emulator
+;
+; In:   ECX     Command code
+;       EDX     Pointer to communication area
+;
+; Out:  EAX     Relocated file handle (success) or -1 (failure)
+;       ECX     errno (0 if no error)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS3A:          CMP     I_ECX, FPUC_INIT
+                JE      SHORT FPUEMU_INIT
+                CMP     PROCESS_FPUEMU, DI      ; Correct process?
+                JNE     FPUEMU_FAIL             ; No  -> fail
+                CMP     I_ECX, FPUC_NEXT
+                JE      SHORT FPUEMU_NEXT       ; Yes -> wait for notification
+                CMP     I_ECX, FPUC_SIGNAL
+                JE      FPUEMU_SIGNAL
+
+;
+; The FP emulator waits for the next notification; switch back to the
+; interrupted process
+;
+FPUEMU_NEXT:    CMP     FPUEMU_STATE, FES_ON
+                JNE     SHORT FPUEMU_NEXT_1
+                MOV     AX, 0
+                MOV     FS, AX                          ; Avoid trap on POP FS
+                MOV     [DI].P_STATUS, PS_FPUEMU_NEXT
+                MOV     BX, DI
+                CALL    SAVE_PROCESS
+                MOV     DI, PROCESS_FPUCLIENT
+                ASSUME  DI:PTR PROCESS
+                MOV     PROCESS_PTR, DI
+                MOV     ES, I_DS
+                MOV     ESI, I_EDX
+                ASSUME  ESI:NEAR32 PTR FPUEMU_COM
+                MOV     CX, I_REG_DWORDS
+                XOR     EBX, EBX
+FEN_LOOP:       MOV     EAX, ES:[ESI].FEC_FRAME[EBX]
+                MOV     DWORD PTR [DI].P_GS[BX], EAX
+                ADD     BX, 4
+                LOOP    FEN_LOOP
+                MOV     BX, DI
+                CALL    REST_PROCESS
+;;;;            CALL    BREAK_AFTER_IRET
+                ASSUME  DI:NOTHING
+                RET
+
+FPUEMU_INIT:    CMP     PROCESS_FPUEMU, NO_PROCESS ; FPU emu already installed?
+                JNE     FPUEMU_FAIL
+                CMP     FPUEMU_STATE, FES_LOADING
+                JNE     FPUEMU_FAIL
+                MOV     PROCESS_FPUEMU, DI
+                MOV     FPUEMU_STATE, FES_INIT1
+                JMP     EMX_OK
+
+                ASSUME  DI:PTR PROCESS
+FPUEMU_NEXT_1:  CMP     FPUEMU_STATE, FES_ENDPROC
+                JE      FPUEMU_ENDPROC_1
+                CMP     FPUEMU_STATE, FES_NEWPROC
+                JE      SHORT FPUEMU_NEWPROC_1
+                CMP     FPUEMU_STATE, FES_INIT1
+                JNE     FPUEMU_EXIT               ; TODO
+;
+; Send FPUN_NEWPROC notifications for all processes
+;
+                LEA     BX, PROCESS_TABLE
+                ASSUME  BX:PTR PROCESS
+                MOV     CX, MAX_PROCESSES
+NEWPROC_LOOP:   TEST    [BX].P_FLAGS, PF_FPUEMU_INIT
+                JNZ     SHORT NEWPROC_NEXT
+                CMP     [BX].P_STATUS, PS_NONE
+                JE      SHORT NEWPROC_NEXT
+                CMP     [BX].P_STATUS, PS_DEFUNCT
+                JE      SHORT NEWPROC_NEXT
+                CMP     [BX].P_STATUS, PS_INIT
+                JE      SHORT NEWPROC_NEXT
+                CMP     BX, PROCESS_FPUEMU
+                JNE     SHORT NEWPROC_SEND
+NEWPROC_NEXT:   ADD     BX, SIZE PROCESS
+                LOOP    NEWPROC_LOOP
+                ASSUME  BX:NOTHING
+;
+; All processes have been processed, send FPUN_EMU notification
+;
+FPUEMU_NEXT_INIT2:
+                MOV     FPUEMU_STATE, FES_ON
+                MOV     BX, PROCESS_PTR
+                CALL    SAVE_PROCESS
+                MOV     BX, PROCESS_FPUCLIENT
+                MOV     PROCESS_PTR, BX
+                CALL    REST_PROCESS
+                CALL    FPUEMU_CALL
+                JMP     EMX_OK
+
+;
+; Send a FPUN_NEWPROC notification
+;
+                ASSUME  BX:PTR PROCESS
+NEWPROC_SEND:   OR      [BX].P_FLAGS, PF_FPUEMU_INIT
+                MOV     ES, I_DS
+                MOV     EDI, I_EDX
+                ASSUME  EDI:NEAR32 PTR FPUEMU_COM
+                MOV     ES:[EDI].FEC_NOTIFY, FPUN_NEWPROC
+                MOV     EAX, [BX].P_NUMBER
+                MOV     ES:[EDI].FEC_PNUM, EAX
+                JMP     EMX_OK
+
+                ASSUME  EDI:NOTHING
+                ASSUME  BX:NOTHING
+
+;
+; FPUN_ENDPROC and FPUN_NEWPROC handled
+;
+                ASSUME  DI:PTR PROCESS
+FPUEMU_ENDPROC_1:
+FPUEMU_NEWPROC_1:
+                MOV     FPUEMU_STATE, FES_ON
+                MOV     [DI].P_STATUS, PS_FPUEMU_NEXT
+                MOV     BX, DI
+                CALL    SAVE_PROCESS
+                MOV     BX, PROCESS_FPUCLIENT
+                MOV     PROCESS_PTR, BX
+                CALL    REST_PROCESS
+                RET
+
+;
+; Generate a signal.  Faking an exception would be better, but this
+; will do for now.
+;
+FPUEMU_SIGNAL:  MOV     ES, I_DS
+                MOV     ESI, I_EDX
+                ASSUME  ESI:NEAR32 PTR FPUEMU_COM
+                MOV     EAX, ES:[ESI].FEC_SIGNAL
+                MOV     BX, PROCESS_FPUCLIENT
+                BTS     (PROCESS PTR [BX]).P_SIG_PENDING, EAX ; Generate signal
+                JMP     EMX_OK
+                ASSUME  ESI:NOTHING
+
+;
+; TODO: Error message
+;
+FPUEMU_EXIT:    MOV     AX, 4CFFH
+                INT     21H
+
+FPUEMU_FAIL:    MOV     I_ECX, EINVAL
+                MOV     I_EAX, -1
+                RET
+
+                ASSUME  DI:NOTHING
+
+; ----------------------------------------------------------------------------
+; AX=7F58H: __settime()
+;
+; Set system time
+;
+; In:   EDX     Pointer to struct timeval
+;
+; Out:  EAX     0 (success) or -1 (failure)
+;       ECX     errno (0 if no error)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS58:          MOV     ESI, I_EDX
+                MOV     ES, I_DS
+                CALL    DO_SETTIME
+                MOV     I_ECX, EAX
+                MOV     I_EAX, 0
+                TEST    EAX, EAX
+                JZ      SHORT SYS58_RET
+                MOV     I_EAX, -1
+SYS58_RET:      RET
+
+; ----------------------------------------------------------------------------
+; AX=7F59H: __profil()
+;
+; Sampling profiler
+;
+; In:   EDX     Pointer to struct _profil
+;
+; Out:  EAX     0 (success) or -1 (failure)
+;       ECX     errno (0 if no error)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+                ASSUME  DI:PTR PROCESS
+SYS59:          MOV     ES, I_DS
+                MOV     ESI, I_EDX
+                CALL    DO_PROFIL
+                MOV     I_ECX, EAX
+                TEST    EAX, EAX
+                JZ      SHORT SYS59_1
+                MOV     EAX, -1
+SYS59_1:        MOV     I_EAX, EAX
+                RET
+
+; ----------------------------------------------------------------------------
+; AX=7F5AH: __nls_ctype()
+;
+; Mark DBCS lead bytes
+;
+; In:   EDX     pointer to buffer
+;
+; Out:  EAX     0 (success) or -1 (failure)
+;       ECX     errno (0 if no error)
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+SYS5A:          CALL    GET_DBCS_LEAD
+                TEST    AX, AX
+                JZ      SHORT NLS_CT_COPY
+                JMP     SYSCALL_ENOSYS
+
+;
+; Copy the DBCS lead byte bits of our table to the target buffer
+;
+NLS_CT_COPY:    CMP     I_DS, 0                 ; See INIT_DBCS
+                JE      SHORT NLS_CT_EFAULT
+                MOV     ES, I_DS
+                MOV     EDI, I_EDX
+                MOV     ECX, 0
+                TALIGN  4
+NLS_CT_COPY_BIT:BT      DBCS_LEAD_TAB, CX
+                JC      SHORT NLS_CT_COPY_SET
+                AND     BYTE PTR ES:[EDI], 0FEH ; Clear _NLS_DBCS_LEAD
+NLS_CT_COPY_NXT:INC     EDI
+                INC     CX
+                CMP     CX, 256
+                JB      SHORT NLS_CT_COPY_BIT
+                JMP     EMX_OK
+
+                TALIGN  4
+NLS_CT_COPY_SET:OR      BYTE PTR ES:[EDI], 01H  ; Set _NLS_DBCS_LEAD
+                JMP     SHORT NLS_CT_COPY_NXT
+
+NLS_CT_EFAULT:  MOV     I_EAX, -1
+                MOV     I_ECX, EFAULT
+                RET
+
+                ASSUME  BP:NOTHING
+
+; ----------------------------------------------------------------------------
+;
+; Convert a MY_DATETIME structure to Unix time format
+;
+; MDT must be in the stack!
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+TIME_2_UNIX     PROC    PASCAL USES EBX ESI, MDT:PTR MY_DATETIME
+                MOV     BX, MDT
+                ASSUME  BX:PTR MY_DATETIME
+                MOV     EAX, SS:[BX].YEAR
+                MOV     EDX, 365
+                MUL     EDX
+                MOV     ESI, EAX
+                MOV     EAX, SS:[BX].MONTH
+                DEC     EAX
+                MOV     EDX, 31
+                MUL     EDX
+                ADD     ESI, EAX
+                ADD     ESI, SS:[BX].DAY        ; 365*year + day + 31*(month-1)
+                DEC     SS:[BX].YEAR
+                CMP     SS:[BX].MONTH, 2        ; Jan or Feb?
+                JBE     SHORT T2U_1             ; Yes -> skip
+
+                INC     SS:[BX].YEAR
+                MOV     EAX, SS:[BX].MONTH
+                SHL     EAX, 2
+                ADD     EAX, 23
+                XOR     EDX, EDX
+                MOV     ECX, 10
+                DIV     ECX
+                SUB     ESI, EAX                ; - ((4*month)+23)/10
+
+                TALIGN  4
+T2U_1:          MOV     EAX, SS:[BX].YEAR
+                SHR     EAX, 2
+                ADD     ESI, EAX                ; + (year{-1})/4
+                MOV     EAX, SS:[BX].YEAR
+                XOR     EDX, EDX
+                MOV     ECX, 100
+                DIV     ECX
+                INC     EAX
+                MOV     EDX, EAX
+                ADD     EAX, EAX
+                ADD     EAX, EDX
+                SHR     EAX, 2
+                SUB     ESI, EAX                ; - (3*((year{-1})/100+1)) / 4
+                MOV     EAX, ESI
+                SUB     EAX, 719528             ; 01-Jan-1970
+                MOV     EDX, 24*60*60
+                MUL     EDX
+;
+; Add time of day
+;
+                ADD     EAX, SS:[BX].SECONDS
+                MOV     ESI, EAX
+                MOV     EAX, SS:[BX].MINUTES
+                MOV     EDX, 60
+                MUL     EDX
+                ADD     ESI, EAX
+                MOV     EAX, SS:[BX].HOURS
+                MOV     EDX, 60*60
+                MUL     EDX
+                ADD     EAX, ESI
+                RET
+                ASSUME  BX:NOTHING
+TIME_2_UNIX     ENDP
+
+; ----------------------------------------------------------------------------
+; Convert a packed time/date value to Unix time value (GMT)
+;
+; In:  CX       Time
+;      DX       Date
+;
+; Out: EAX      Unix time
+;
+; ----------------------------------------------------------------------------
+;
+                TALIGN  4
+PACKED_2_UNIX   PROC
+                LOCAL   MDT:MY_DATETIME
+                MOV     AX, DX                  ; Day of month
+                AND     EAX, 1FH
+                MOV     MDT.DAY, EAX
+                MOV     AX, DX                  ; Month
+                SHR     AX, 5
+                AND     EAX, 0FH
+                MOV     MDT.MONTH, EAX
+                MOV     AX, DX                  ; Year - 1980
+                SHR     AX, 9
+                AND     EAX, 7FH
+                ADD     EAX, 1980
+                MOV     MDT.YEAR, EAX
+                MOV     AX, CX                  ; Seconds / 2
+                AND     EAX, 1FH
+                SHL     EAX, 1
+                MOV     MDT.SECONDS, EAX
+                MOV     AX, CX                  ; Minutes
+                SHR     AX, 5
+                AND     EAX, 3FH
+                MOV     MDT.MINUTES, EAX
+                MOV     AX, CX                  ; Hours
+                SHR     AX, 11
+                AND     EAX, 1FH
+                MOV     MDT.HOURS, EAX
+                INVOKE  TIME_2_UNIX, ADDR MDT
+                RET
+PACKED_2_UNIX   ENDP
+
+
+;
+; In:  EAX      Year
+;
+; Out: EAX      1 if leap year, 0 otherwise
+;
+                TALIGN  4
+LEAP_YEAR       PROC    NEAR
+                PUSH    ECX
+                PUSH    EDX
+                TEST    EAX, 3                  ; year = 4n?
+                JNZ     SHORT LEAP_NO           ; No -> not a leap year
+                MOV     ECX, 100
+                XOR     EDX, EDX
+                DIV     ECX
+                OR      EDX, EDX                ; year = 100n?
+                JNZ     SHORT LEAP_YES          ; No  -> it's a leap year
+                TEST    EAX, 3                  ; year = 400n?
+                JNZ     SHORT LEAP_NO           ; No  -> not a leap year
+LEAP_YES:       XOR     EAX, EAX
+                INC     EAX
+                JMP     SHORT LEAP_RET
+
+                TALIGN  4
+LEAP_NO:        XOR     EAX, EAX
+LEAP_RET:       POP     EDX
+                POP     ECX
+                RET
+LEAP_YEAR       ENDP
+
+; ----------------------------------------------------------------------------
+;
+; Convert a Unix time value to a MY_DATETIME structure
+;
+; MDT must be in the stack!
+;
+; ----------------------------------------------------------------------------
+                TALIGN  4
+UNIX_2_TIME     PROC    PASCAL USES EBX ESI EDI,
+                        TIME:DWORD, MDT:PTR MY_DATETIME
+                MOV     BX, MDT
+                ASSUME  BX:PTR MY_DATETIME
+                MOV     EAX, TIME
+                MOV     ECX, 60
+                XOR     EDX, EDX
+                DIV     ECX
+                MOV     SS:[BX].SECONDS, EDX
+                XOR     EDX, EDX
+                DIV     ECX
+                MOV     SS:[BX].MINUTES, EDX
+                MOV     ECX, 24
+                XOR     EDX, EDX
+                DIV     ECX
+                MOV     SS:[BX].HOURS, EDX
+                MOV     ESI, 1970
+                MOV     EDI, EAX
+                TALIGN  4
+U2T_Y_LOOP:     MOV     EAX, ESI
+                CALL    LEAP_YEAR
+                ADD     EAX, 365
+                MOV     ECX, EAX
+                INC     ESI
+                SUB     EDI, ECX
+                JNC     SHORT U2T_Y_LOOP
+                ADD     EDI, ECX
+                DEC     ESI
+                MOV     SS:[BX].YEAR, ESI
+                MOV     ESI, 0
+                TALIGN  4
+U2T_M_LOOP:     CMP     ESI, 1                  ; February?
+                JE      SHORT U2T_M_FEB
+                MOVZX   ECX, MONTH_LEN[ESI]
+                JMP     SHORT U2T_M_CONT
+                TALIGN  4
+U2T_M_FEB:      MOV     EAX, SS:[BX].YEAR
+                CALL    LEAP_YEAR
+                ADD     EAX, 28
+                MOV     ECX, EAX
+                TALIGN  4
+U2T_M_CONT:     INC     ESI
+                SUB     EDI, ECX
+                JNC     SHORT U2T_M_LOOP
+                ADD     EDI, ECX
+                MOV     SS:[BX].MONTH, ESI
+                INC     EDI
+                MOV     SS:[BX].DAY, EDI
+                RET
+UNIX_2_TIME     ENDP
+
+
+;
+; Convert Unix time value (GMT) to a packed time/date value
+;
+; In:  EAX      Unix time
+;
+; Out: CX       Time
+;      DX       Date
+;
+UNIX_2_PACKED   PROC
+                LOCAL   MDT:MY_DATETIME
+                INVOKE  UNIX_2_TIME, EAX, ADDR MDT
+
+                MOV     ECX, MDT.SECONDS
+                SHR     ECX, 1
+                MOV     EAX, MDT.MINUTES
+                SHL     EAX, 5
+                OR      ECX, EAX
+                MOV     EAX, MDT.HOURS
+                SHL     EAX, 11
+                OR      ECX, EAX
+
+                MOV     EDX, MDT.DAY
+                MOV     EAX, MDT.MONTH
+                SHL     EAX, 5
+                OR      EDX, EAX
+                MOV     EAX, MDT.YEAR
+                SUB     EAX, 1980
+                SHL     EAX, 9
+                OR      EDX, EAX
+                RET
+UNIX_2_PACKED   ENDP
+
+
+;
+; In:  ES:EDI   destination
+;
+                TALIGN  4
+                ASSUME  EDI:NEAR32 PTR TIMEB
+DO_FTIME        PROC
+                LOCAL   DATE_CX:WORD, DATE_DX:WORD
+                LOCAL   TIME_CX:WORD, TIME_DX:WORD
+                LOCAL   MDT:MY_DATETIME
+
+RETRY:          MOV     AH, 2AH
+                INT     21H
+                MOV     DATE_CX, CX
+                MOV     DATE_DX, DX
+                MOV     AH, 2CH
+                INT     21H
+                MOV     TIME_CX, CX
+                MOV     TIME_DX, DX
+                MOV     AH, 2AH
+                INT     21H
+                CMP     CX, DATE_CX
+                JNE     SHORT RETRY
+                CMP     DX, DATE_DX
+                JNE     SHORT RETRY
+
+                MOVZX   EAX, BYTE PTR TIME_DX[1]
+                MOV     MDT.SECONDS, EAX
+                MOVZX   EAX, BYTE PTR TIME_CX[0]
+                MOV     MDT.MINUTES, EAX
+                MOVZX   EAX, BYTE PTR TIME_CX[1]
+                MOV     MDT.HOURS, EAX
+                MOVZX   EAX, BYTE PTR DATE_DX[0]
+                MOV     MDT.DAY, EAX
+                MOVZX   EAX, BYTE PTR DATE_DX[1]
+                MOV     MDT.MONTH, EAX
+                MOVZX   EAX, DATE_CX
+                MOV     MDT.YEAR, EAX
+
+                INVOKE  TIME_2_UNIX, ADDR MDT
+
+                MOV     ES:[EDI].DSTFLAG, 0
+                MOV     ES:[EDI].TIME, EAX
+                MOVZX   EAX, BYTE PTR TIME_DX[0]
+                MOV     ECX, 10
+                MUL     ECX
+                MOV     ES:[EDI].MILLITM, EAX
+                MOV     ES:[EDI].TIMEZONE, 0
+                ASSUME  EDI:NOTHING
+                RET
+DO_FTIME        ENDP
+
+
+;
+; In: ES:ESI    Source
+;
+                TALIGN  4
+                ASSUME  ESI:NEAR32 PTR TIMEVAL
+DO_SETTIME      PROC
+                LOCAL   MDT:MY_DATETIME
+                MOV     EAX, ES:[ESI].TV_USEC
+                XOR     EDX, EDX
+                MOV     ECX, 1000000
+                DIV     ECX
+                PUSH    EDX                     ; Save microseconds
+                ADD     EAX, ES:[ESI].TV_SEC
+                INVOKE  UNIX_2_TIME, EAX, ADDR MDT
+                POP     EAX                     ; Microseconds
+                XOR     EDX, EDX
+                MOV     ECX, 10000
+                DIV     ECX                     ; 1/100 seconds
+                MOV     DL, CL
+                MOV     DH, BYTE PTR MDT.SECONDS
+                MOV     CL, BYTE PTR MDT.MINUTES
+                MOV     CH, BYTE PTR MDT.HOURS
+                MOV     AH, 2DH                 ; Set system time
+                INT     21H
+                TEST    AL, AL
+                JNZ     SHORT ERROR
+; TODO: Time window
+                MOV     DL, BYTE PTR MDT.DAY
+                MOV     DH, BYTE PTR MDT.MONTH
+                MOV     CX, WORD PTR MDT.YEAR
+                MOV     AH, 2BH                 ; Set system date
+                INT     21H
+                TEST    AL, AL
+                JNZ     SHORT ERROR
+                XOR     EAX, EAX
+                RET
+
+ERROR:          MOV     EAX, EINVAL
+                RET
+DO_SETTIME      ENDP
+
+                ASSUME  ESI:NOTHING
+
+
+;
+; Compare two strings
+;
+; In:   DS:ESI  First string
+;       ES:EDI  Second string
+;
+; Out:  ZR      Strings are equal
+;       ESI     Modified
+;       EDI     Modified
+;
+                TALIGN  4
+STRCMP          PROC    NEAR
+SC_1:           LODS    BYTE PTR DS:[ESI]
+                SCAS    BYTE PTR ES:[EDI]
+                JNE     SHORT SC_RET
+                OR      AL, AL
+                JNZ     SHORT SC_1
+SC_RET:         RET
+STRCMP          ENDP
+       
+;
+; Compare two strings, disregarding letter case
+;
+; In:   DS:SI   First string
+;       ES:DI   Second string
+;
+; Out:  ZR      Strings are equal
+;       SI      Modified
+;
+                TALIGN  4
+STRICMP         PROC    NEAR
+                PUSH    DI
+SIC_1:          LODSB
+                CALL    UPPER
+                MOV     AH, AL
+                MOV     AL, ES:[DI]
+                INC     DI
+                CALL    UPPER
+                CMP     AL, AH
+                JNE     SHORT SIC_RET
+                OR      AL, AL
+                JNZ     SHORT SIC_1
+SIC_RET:        POP     DI
+                RET
+STRICMP         ENDP
+       
+
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/syscall.inc
===================================================================
--- trunk/src/emx/src/dos/syscall.inc	(revision 18)
+++ trunk/src/emx/src/dos/syscall.inc	(revision 18)
@@ -0,0 +1,30 @@
+;
+; SYSCALL.INC -- System calls (without BIOS and DOS calls)
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_CODE         SEGMENT
+
+                EXTRN   DO_SYSCALL:NEAR
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/tables.asm
===================================================================
--- trunk/src/emx/src/dos/tables.asm	(revision 18)
+++ trunk/src/emx/src/dos/tables.asm	(revision 18)
@@ -0,0 +1,468 @@
+;
+; TABLES.ASM -- Protected mode tables
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; Global descriptor table
+; Local descriptor tables
+; Task state segment
+;
+
+__TABLES        =       1
+                INCLUDE EMX.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE PMINT.INC
+                INCLUDE TABLES.INC
+                INCLUDE HEADERS.INC
+                INCLUDE EXCEPT.INC
+                INCLUDE MISC.INC
+
+
+                PUBLIC  GDT_PTR, GDT_LIN
+                PUBLIC  IDT_PTR, IDT_LIN
+                PUBLIC  REAL_IDT_PTR
+                PUBLIC  GDT, LDTS, IDT, BASE_TABLE
+                PUBLIC  G_VCPI_DESC, G_ENV_DESC, G_PHYS_DESC, G_LIN_MAP_DESC
+                PUBLIC  G_SWAP_BMP_DESC, G_PAGEDIR_DESC, G_VIDEO_DESC
+                PUBLIC  G_PAGE_BMP_DESC, G_TSS_DESC, G_TSS_MEM_DESC
+                PUBLIC  G_TMP1_DESC, G_TMP2_DESC
+                PUBLIC  G_BUF1_DESC, G_BUF2_DESC
+                PUBLIC  TSS_BUSY
+                PUBLIC  TSS_EX8_CR3, TSS_EX10_CR3
+
+SV_DATA         SEGMENT
+
+GDT_PTR         LABEL   FWORD
+                WORD    END_GDT - GDT - 1       ; Limit of GDT
+GDT_LIN         LABEL   DWORD
+                WORD    GDT, 0                  ; Linear address of GDT
+                
+IDT_PTR         LABEL   FWORD
+                WORD    END_IDT - IDT - 1       ; Limit of IDT
+IDT_LIN         LABEL   DWORD
+                WORD    IDT, 0                  ; Linear address of IDT
+
+REAL_IDT_PTR    LABEL   FWORD
+                WORD    03FFH                   ; limit of real-mode IDT
+                DWORD   0                       ; Linear address
+
+
+                DALIGN  8
+
+GDT             LABEL   QWORD
+;
+; The null selector (G_NULL_SEL)
+;
+                QWORD   0
+;
+; The GDT as memory segment (G_GDT_MEM_SEL)
+;
+BTD1            WORD    END_GDT-GDT-1   ; Limit (0..15)
+                WORD    GDT             ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; The IDT (G_IDT_SEL), not used, but convenient for debugging
+;
+                QWORD   0
+;
+; Accessing physical memory by physical addresses (G_PHYS_SEL, see note 1)
+;
+G_PHYS_DESC     WORD    0FFFFH          ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0CFH            ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Supervisor code (G_SV_CODE_SEL)
+;
+BTC1            WORD    0FFFFH          ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    9BH             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Used for switch to real mode (G_REAL_SEL)
+;
+                WORD    0FFFFH          ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Initialization/termination code (G_INIT_SEL)
+;
+BTI1            WORD    0FFFFH          ; Limit (0..15)  !!! (return to RM)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    9BH             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Supervisor data (G_SV_DATA_SEL)
+;
+BTD3            WORD    0FFFFH          ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Supervisor stack (G_SV_STACK_SEL)
+;
+BTS1            WORD    OFFSET SV_TOS-1 ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    40H             ; Granularity   (see note 2)
+                BYTE    0               ; Base (24..31)
+;
+; Video memory (G_VIDEO_SEL)
+;
+G_VIDEO_DESC    WORD    4000 - 1        ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0BH             ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; The TSS (G_TSS_SEL)
+;
+G_TSS_DESC      WORD    END_TSS-TSS-1   ; Limit (0..15)
+                WORD    TSS             ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+TSS_BUSY        BYTE    89H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Three segments for VCPI server (G_SERVER_SEL)
+;
+G_VCPI_DESC     QWORD   3 DUP (0)
+;
+; The DOS environment (G_ENV_SEL)
+;
+G_ENV_DESC      QWORD   0
+;
+; The HDR_SEG segment (G_HDR_SEL)
+;
+BTH1            WORD    SIZE BIND_HEADER - 1
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    91H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Two temporary entries (G_TMP1_SEL, G_TMP2_SEL)
+;
+G_TMP1_DESC     QWORD   0               ; G_TMP1_SEL
+G_TMP2_DESC     QWORD   0               ; G_TMP2_SEL
+;
+; Zero based segment (4G bytes) for returning from protected mode
+; to real mode under VCPI (G_ZERO_SEL)
+;
+                WORD    0FFFFH          ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0CFH            ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; 1st communication buffer (G_BUF1_SEL)
+;
+G_BUF1_DESC     WORD    0FFFFH          ; Limit 0..15
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; 2nd communication buffer (G_BUF2_SEL)
+;
+G_BUF2_DESC     WORD    0FFFH+OFFSET_1  ; Limit 0..15
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; The page directory (and swapper info directory, G_PAGEDIR_SEL)
+;
+G_PAGEDIR_DESC  WORD    2*4096-1        ; Limit 0..15
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; The swapper file bitmap (G_SWAP_BMP_SEL)
+;
+G_SWAP_BMP_DESC QWORD   0
+;
+; The linear address map (G_LIN_MAP_SEL)
+;
+G_LIN_MAP_DESC  WORD    4096-1          ; Limit 0..15
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; The free page bitmap (G_PAGE_BMP_SEL)
+;
+G_PAGE_BMP_DESC QWORD   0
+;
+; The TSS for exception 8 (double fault, G_TSS_EX8_SEL)
+;
+BTD5            WORD    END_TSS_EX8 - TSS_EX8 - 1       ; Limit (0..15)
+                WORD    TSS_EX8         ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    89H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; The TSS for exception 10 (invalid TSS, G_TSS_EX10_SEL)
+;
+BTD6            WORD    END_TSS_EX10 - TSS_EX10 - 1     ; Limit (0..15)
+                WORD    TSS_EX10        ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    89H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Stack for exception 8 task (G_EX8_STACK_SEL)
+;
+BTS8            WORD    OFFSET EX8_TOS-1        ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    40H             ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; Stack for exception 10 task (G_EX10_STACK_SEL)
+;
+BTS10           WORD    OFFSET EX10_TOS-1       ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    40H             ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; The TSS as memory segment (G_TSS_MEM_SEL)
+;
+G_TSS_MEM_DESC  WORD    END_TSS-TSS-1   ; Limit (0..15)
+                WORD    TSS             ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    93H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; The lower 1MB (+64KB)
+;
+                WORD    010FH           ; Limit (0..15)
+                WORD    0               ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    91H             ; Access (read only)
+                BYTE    0C0H            ; Granularity
+                BYTE    0               ; Base (24..31)
+;
+; One LDT per process (G_LDT_SEL, the first entry, is already initialized,
+; because it is used for protected mode startup -- only its existence is
+; required)
+;
+BTD8            WORD    8*LDT_ENTRIES-1 ; Limit (0..15)
+                WORD    LDTS            ; Base (0..15)
+                BYTE    0               ; Base (16..23)
+                BYTE    82H             ; Access
+                BYTE    0               ; Granularity
+                BYTE    0               ; Base (24..31)
+                
+                QWORD   (MAX_PROCESSES-1) DUP (0)
+
+END_GDT         LABEL   QWORD
+
+
+;
+; Note 1: When running under VCPI, the base address of the physical
+;         memory segment will be changed. See INIT_VCPI for details.
+;         The limit will be also changed if not running under VCPI,
+;         see INIT_PAGING.
+;
+; Note 2: Setting the B bit is required to make a stack-switch to
+;         an inner privilege level load ESP instead of SP from the
+;         TSS. With non-zero upper word of ESP the VCPI server doesn't
+;         work (tested with CEMM.SYS: crash!).
+;
+LDTS            QWORD   (MAX_PROCESSES * LDT_ENTRIES) DUP (0)
+
+;
+; The IDT will be filled in by this program. See RMINT module.
+;
+IDT             LABEL   QWORD
+                QWORD   256 DUP (?)
+END_IDT         LABEL   QWORD
+
+
+; This TSS is used only for holding the ring 0 SS:ESP.  After
+; switching to protected mode, it is replaced with a dynamically
+; allocated TSS which adds an I/O permission bitmap.
+;
+TSS             LABEL   BYTE
+                DWORD   0                       ; Back pointer
+                WORD    OFFSET SV_TOS, 0        ; STK0
+                WORD    G_SV_STACK_SEL, 0
+                QWORD   0                       ; STK1
+                QWORD   0                       ; STK2
+                DWORD   0                       ; CR3
+                DWORD   0                       ; EIP
+                DWORD   0                       ; EFLAGS
+                DWORD   0                       ; EAX
+                DWORD   0                       ; ECX
+                DWORD   0                       ; EDX
+                DWORD   0                       ; EBX
+                DWORD   0                       ; ESP
+                DWORD   0                       ; EBP
+                DWORD   0                       ; ESI
+                DWORD   0                       ; EDI
+                DWORD   0                       ; ES
+                DWORD   0                       ; CS
+                DWORD   0                       ; SS
+                DWORD   0                       ; DS
+                DWORD   0                       ; FS
+                DWORD   0                       ; GS
+                DWORD   0                       ; LDT
+                WORD    0                       ; DTB
+                WORD    $ + 2 - TSS             ; I/O bitmap
+                BYTE    0FFH                    ; End of bitmap
+END_TSS         LABEL   BYTE
+
+
+;
+; This TSS is used for exception 8 (double fault)
+;
+TSS_EX8         LABEL   BYTE
+                DWORD   0                       ; Back pointer
+                QWORD   0                       ; STK0 (no priv. level chg!)
+                QWORD   0                       ; STK1
+                QWORD   0                       ; STK2
+TSS_EX8_CR3     DWORD   0                       ; CR3
+                DWORD   OFFSET EXCEPT_TASK      ; EIP
+                DWORD   0                       ; EFLAGS
+                DWORD   8                       ; EAX (exception #)
+                DWORD   0                       ; ECX
+                DWORD   0                       ; EDX
+                DWORD   0                       ; EBX
+                DWORD   OFFSET EX8_TOS          ; ESP
+                DWORD   0                       ; EBP
+                DWORD   0                       ; ESI
+                DWORD   0                       ; EDI
+                DWORD   G_SV_DATA_SEL           ; ES
+                DWORD   G_SV_CODE_SEL           ; CS
+                DWORD   G_EX8_STACK_SEL         ; SS
+                DWORD   G_SV_DATA_SEL           ; DS
+                DWORD   G_SV_DATA_SEL           ; FS
+                DWORD   G_SV_DATA_SEL           ; GS
+                DWORD   0                       ; LDT
+                WORD    0                       ; DTB
+                WORD    $ + 2 - TSS_EX8         ; I/O bitmap
+                BYTE    0FFH                    ; End of bitmap
+END_TSS_EX8     LABEL   BYTE
+
+
+;
+; This TSS is used for exception 10 (invalid TSS)
+;
+TSS_EX10        LABEL   BYTE
+                DWORD   0                       ; Back pointer
+                QWORD   0                       ; STK0 (no priv. level chg!)
+                QWORD   0                       ; STK1
+                QWORD   0                       ; STK2
+TSS_EX10_CR3    DWORD   0                       ; CR3
+                DWORD   OFFSET EXCEPT_TASK      ; EIP
+                DWORD   0                       ; EFLAGS
+                DWORD   10                      ; EAX (exception #)
+                DWORD   0                       ; ECX
+                DWORD   0                       ; EDX
+                DWORD   0                       ; EBX
+                DWORD   OFFSET EX10_TOS         ; ESP
+                DWORD   0                       ; EBP
+                DWORD   0                       ; ESI
+                DWORD   0                       ; EDI
+                DWORD   G_SV_DATA_SEL           ; ES
+                DWORD   G_SV_CODE_SEL           ; CS
+                DWORD   G_EX10_STACK_SEL        ; SS
+                DWORD   G_SV_DATA_SEL           ; DS
+                DWORD   G_SV_DATA_SEL           ; FS
+                DWORD   G_SV_DATA_SEL           ; GS
+                DWORD   0                       ; LDT
+                WORD    0                       ; DTB
+                WORD    $ + 2 - TSS_EX10        ; I/O bitmap
+                BYTE    0FFH                    ; End of bitmap
+END_TSS_EX10    LABEL   BYTE
+
+
+;
+; This table is used for converting segment/offset pairs to linear addresses
+; in descriptor tables. The first word of a pair is the real-mode segment,
+; the second word points to the descriptor table entry (ASSUME DS:SV_DATA),
+; which already contains the offset in the base 0..15 field.
+;
+BASE_TABLE      LABEL   WORD
+                WORD    SV_DATA, BTD1
+                WORD    SV_DATA, BTD3
+                WORD    SV_DATA, G_TSS_DESC
+                WORD    SV_DATA, BTD5
+                WORD    SV_DATA, BTD6
+                WORD    SV_DATA, G_TSS_MEM_DESC
+                WORD    SV_DATA, BTD8
+                WORD    SV_STACK, BTS1
+                WORD    SV_CODE, BTC1
+                WORD    INIT_CODE, BTI1
+                WORD    HDR_SEG, BTH1
+                WORD    EX8_STACK, BTS8
+                WORD    EX10_STACK, BTS10
+                WORD    0, 0                    ; End of table
+
+
+SV_DATA         ENDS
+
+
+EX8_STACK       SEGMENT
+                WORD    256 DUP (?)
+EX8_TOS         LABEL   WORD
+EX8_STACK       ENDS
+
+
+EX10_STACK      SEGMENT
+                WORD    256 DUP (?)
+EX10_TOS        LABEL   WORD
+EX10_STACK      ENDS
+
+
+                END
Index: trunk/src/emx/src/dos/tables.inc
===================================================================
--- trunk/src/emx/src/dos/tables.inc	(revision 18)
+++ trunk/src/emx/src/dos/tables.inc	(revision 18)
@@ -0,0 +1,86 @@
+;
+; TABLES.INC -- Protected mode tables
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+LDT_ENTRIES     =       6
+
+
+;
+; Task State Segment
+;
+; Without I/O bitmap, at least one bytes (0FFH) required after TSS
+;
+TSS_STRUC       STRUC
+TSS_BACK        DD      ?                       ; Back pointer
+TSS_STK0_OFF    DD      ?                       ; STK0: offset
+TSS_STK0_SEL    DW      ?, 0                    ; STK0: selector
+TSS_STK1_OFF    DD      ?                       ; STK1: offset
+TSS_STK1_SEL    DW      ?, 0                    ; STK1: selector
+TSS_STK2_OFF    DD      ?                       ; STK2: offset
+TSS_STK2_SEL    DW      ?, 0                    ; STK2: selector
+TSS_CR3         DD      ?                       ; CR3
+TSS_EIP         DD      ?                       ; EIP
+TSS_EFLAGS      DD      ?                       ; EFLAGS
+TSS_EAX         DD      ?                       ; EAX
+TSS_ECX         DD      ?                       ; ECX
+TSS_EDX         DD      ?                       ; EDX
+TSS_EBX         DD      ?                       ; EBX
+TSS_ESP         DD      ?                       ; ESP
+TSS_EBP         DD      ?                       ; EBP
+TSS_ESI         DD      ?                       ; ESI
+TSS_EDI         DD      ?                       ; EDI
+TSS_ES          DW      ?, 0                    ; ES
+TSS_CS          DW      ?, 0                    ; CS
+TSS_SS          DW      ?, 0                    ; SS
+TSS_DS          DW      ?, 0                    ; DS
+TSS_FS          DW      ?, 0                    ; FS
+TSS_GS          DW      ?, 0                    ; GS
+TSS_LDT         DD      ?                       ; LDT
+TSS_TRAP        DW      ?                       ; Bit 0: trap flag
+TSS_BIT_MAP_OFF DW      ?                       ; I/O bitmap
+TSS_STRUC       ENDS
+
+
+
+              IFNDEF __TABLES
+
+SV_DATA         SEGMENT
+
+                EXTRN   IDT:QWORD, GDT:QWORD, LDTS:QWORD
+                EXTRN   BASE_TABLE:WORD
+                EXTRN   GDT_PTR:FWORD, IDT_PTR:FWORD, REAL_IDT_PTR:FWORD
+                EXTRN   GDT_LIN:DWORD, IDT_LIN:DWORD
+                EXTRN   G_VCPI_DESC:QWORD, G_ENV_DESC:QWORD
+                EXTRN   G_TMP1_DESC:QWORD, G_TMP2_DESC:QWORD
+                EXTRN   G_BUF1_DESC:QWORD, G_BUF2_DESC:QWORD
+                EXTRN   G_SWAP_BMP_DESC:QWORD, G_VIDEO_DESC:QWORD
+                EXTRN   G_LIN_MAP_DESC:QWORD, G_PAGE_BMP_DESC:QWORD
+                EXTRN   G_TSS_DESC:QWORD, G_TSS_MEM_DESC:QWORD
+                EXTRN   TSS_BUSY:BYTE
+                EXTRN   TSS_EX8_CR3:DWORD, TSS_EX10_CR3:DWORD
+                EXTRN   G_PHYS_DESC:DESCRIPTOR
+                EXTRN   G_PAGEDIR_DESC:DESCRIPTOR
+SV_DATA         ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/termio.asm
===================================================================
--- trunk/src/emx/src/dos/termio.asm	(revision 18)
+++ trunk/src/emx/src/dos/termio.asm	(revision 18)
@@ -0,0 +1,900 @@
+;
+; TERMIO.ASM -- General terminal interface
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+__TERMIO        =       1
+                INCLUDE EMX.INC
+                INCLUDE TERMIO.INC
+                INCLUDE SIGNAL.INC
+                INCLUDE PROCESS.INC
+                INCLUDE ERRORS.INC
+
+                PUBLIC  STDIN_TERMIO, STDIN_FL
+                PUBLIC  TERMIO_INIT, TERMIO_READ, STDIN_AVAIL, KBD_FLUSH
+                PUBLIC  POLL_KEYBOARD, INIT_TERMIO
+
+SV_DATA         SEGMENT
+
+CHAR_SIG        =       0100H
+CHAR_NO         =       0101H
+CHAR_TIME       =       0102H
+
+STDIN_TERMIO    TERMIO  <>
+STDIN_ESCAPE    DB      FALSE
+                DALIGN  4
+STDIN_FL        DD      0
+STDIN_BUFFERED  DD      0
+STDIN_BUF_PTR   DD      ?
+STDIN_BUFFER    DB      256 DUP (?)
+
+EXT_KBD         DB      00H                     ; Either 00H or 10H
+
+TR_OUT_TMP_CHAR DB      ?
+
+KBD_PTR_IN      DW      KBD_BUF
+KBD_PTR_OUT     DW      KBD_BUF
+KBD_BUF         DB      64 DUP (?)
+KBD_BUF_END     =       THIS BYTE
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+
+;
+; Set default values for a TERMIO structure
+;
+; In:   BX      Pointer to TERMIO structure
+;
+; The default values for c_iflag, c_lflag and c_cc differ from Unix
+;
+                TALIGN  2
+                ASSUME  BX:PTR TERMIO
+TERMIO_INIT     PROC    NEAR
+                MOV     [BX].C_IFLAG, BRKINT OR ICRNL OR IXON OR IXANY
+                MOV     [BX].C_OFLAG, 0
+                MOV     [BX].C_CFLAG, B9600 OR CS8 OR CREAD OR HUPCL
+                MOV     [BX].C_LFLAG, ISIG OR ICANON OR IECHO OR ECHOE OR ECHOK OR IDEFAULT
+                MOV     [BX].C_LINE, 0
+                MOV     [BX].C_CC[VINTR], 03H           ; Ctrl-C
+                MOV     [BX].C_CC[VQUIT], 1CH           ; Ctrl-\
+                MOV     [BX].C_CC[VERASE], 08H          ; Ctrl-H
+                MOV     [BX].C_CC[VKILL], 15H           ; Ctrl-U
+                MOV     [BX].C_CC[VEOF], 04H            ; Ctrl-D
+                MOV     [BX].C_CC[VEOL], 0              ; Disabled
+                MOV     [BX].C_CC[VMIN], 6
+                MOV     [BX].C_CC[VTIME], 1
+                RET
+                ASSUME  BX:NOTHING
+TERMIO_INIT     ENDP
+
+;
+; Query `struct termio'
+;
+; In:   EAX     File handle
+;       ES:EBX  Destination address, points to `struct termio'
+;
+; Out:  EAX     Return code (0 on success, -1 on error)
+;       ECX     errno (0 on success)
+
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  EBX:NEAR32 PTR TERMIO
+TERMIO_GET      PROC    NEAR
+                CMP     EAX, 0                  ; stdin
+                JNE     TG_EBADF
+                IRP     F, <C_IFLAG, C_OFLAG, C_CFLAG, C_LFLAG>
+                MOV     EAX, STDIN_TERMIO.F
+                MOV     ES:[EBX].F, EAX
+                ENDM
+                MOV     ES:[EBX].C_LINE, 0
+                MOV     ESI, 0
+TG_1:           MOV     AL, STDIN_TERMIO.C_CC[SI]
+                MOV     ES:[EBX].C_CC[ESI], AL
+                INC     SI
+                CMP     SI, NCC
+                JB      SHORT TG_1
+                XOR     EAX, EAX
+                XOR     ECX, ECX
+                RET
+
+TG_EBADF:       MOV     EAX, -1
+                MOV     ECX, EBADF
+                RET
+TERMIO_GET      ENDP
+
+
+;
+; Set terminal attributes from `struct termio'
+;
+; In:   EAX     File handle
+;       ES:EBX  Source address, points to `struct termio'
+;
+; Out:  EAX     Return code (0 on success, -1 on error)
+;       ECX     errno (0 on success)
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  EBX:NEAR32 PTR TERMIO
+TERMIO_SET      PROC    NEAR
+                CMP     EAX, 0                ; stdin?
+                JNE     SHORT TS_EBADF
+                IRP     F, <C_IFLAG, C_OFLAG, C_CFLAG, C_LFLAG>
+                MOV     EAX, ES:[EBX].F
+                MOV     STDIN_TERMIO.F, EAX
+                ENDM
+                MOV     ESI, 0
+TS_1:           MOV     AL, ES:[EBX].C_CC[ESI]
+                MOV     STDIN_TERMIO.C_CC[SI], AL
+                INC     SI
+                CMP     SI, NCC
+                JB      SHORT TS_1
+                MOV     STDIN_TERMIO.C_CC[VSUSP], 0     ; Disabled
+                MOV     STDIN_TERMIO.C_CC[VSTOP], 13H   ; Ctrl-S
+                MOV     STDIN_TERMIO.C_CC[VSTART], 11H  ; Ctrl-Q
+                XOR     EAX, EAX
+                XOR     ECX, ECX
+                RET
+
+TS_EBADF:       MOV     EAX, -1
+                MOV     ECX, EBADF
+                RET
+TERMIO_SET      ENDP
+
+
+;
+; Flush input queue for termio
+;
+; In:   EAX     File handle
+;
+; Out:  EAX     Return code (0 on success, -1 on error)
+;       ECX     errno (0 on success)
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+TERMIO_FLUSH    PROC    NEAR
+                CMP     EAX, 0                  ; stdin
+                JNE     SHORT TF_EBADF
+                CALL    KBD_FLUSH
+                XOR     EAX, EAX
+                XOR     ECX, ECX
+                RET
+
+TF_EBADF:       MOV     EAX, -1
+                MOV     ECX, EBADF
+                RET
+TERMIO_FLUSH    ENDP
+
+
+;
+; Query `struct termios'
+;
+; In:   EAX     File handle
+;       ES:EBX  Destination address, points to `struct termios'
+;
+; Out:  EAX     Return code (0 on success, -1 on error)
+;       ECX     errno (0 on success)
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  EBX:NEAR32 PTR TERMIOS
+TERMIOS_GET     PROC    NEAR
+                CMP     EAX, 0                  ; stdin
+                JNE     TSG_ENOTTY
+                IRP     F, <C_IFLAG, C_OFLAG, C_CFLAG>
+                MOV     EAX, STDIN_TERMIO.F
+                MOV     ES:[EBX].F, EAX
+                ENDM
+                MOV     EAX, STDIN_TERMIO.C_LFLAG
+                AND     EAX, NOT IDEFAULT
+                MOV     ES:[EBX].C_LFLAG, EAX
+                MOV     ESI, 0
+TSG_1:          MOV     AL, STDIN_TERMIO.C_CC[SI]
+                MOV     ES:[EBX].C_CC[ESI], AL
+                INC     SI
+                CMP     SI, NCCS
+                JB      SHORT TSG_1
+                XOR     EAX, EAX
+                XOR     ECX, ECX
+                RET
+
+TSG_ENOTTY:     MOV     EAX, -1
+                MOV     ECX, ENOTTY
+                RET
+TERMIOS_GET     ENDP
+
+;
+; Set terminal attributes from `struct termios'
+;
+; In:   EAX     File handle
+;       ES:EBX  Source address, points to `struct termios'
+;
+; Out:  EAX     Return code (0 on success, -1 on error)
+;       ECX     errno (0 on success)
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+                ASSUME  EBX:NEAR32 PTR TERMIOS
+TERMIOS_SET     PROC    NEAR
+                CMP     EAX, 0                ; stdin?
+                JNE     SHORT TCS_ENOTTY
+                IRP     F, <C_IFLAG, C_OFLAG, C_CFLAG>
+                MOV     EAX, ES:[EBX].F
+                MOV     STDIN_TERMIO.F, EAX
+                ENDM
+                MOV     EAX, ES:[EBX].C_LFLAG
+                AND     EAX, NOT IDEFAULT
+                MOV     STDIN_TERMIO.C_LFLAG, EAX
+                MOV     ESI, 0
+TCS_1:          MOV     AL, ES:[EBX].C_CC[ESI]
+                MOV     STDIN_TERMIO.C_CC[SI], AL
+                INC     SI
+                CMP     SI, NCCS
+                JB      SHORT TCS_1
+                XOR     EAX, EAX
+                XOR     ECX, ECX
+                RET
+
+TCS_ENOTTY:     MOV     EAX, -1
+                MOV     ECX, ENOTTY
+                RET
+TERMIOS_SET     ENDP
+
+
+;
+; Flush input queue for termios
+;
+; In:   EAX     File handle
+;
+; Out:  EAX     Return code (0 on success, -1 on error)
+;       ECX     errno (0 on success)
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+TERMIOS_FLUSH   PROC    NEAR
+                CMP     EAX, 0                  ; stdin
+                JNE     SHORT TF_ENOTTY
+                CALL    KBD_FLUSH
+                XOR     EAX, EAX
+                XOR     ECX, ECX
+                RET
+
+TF_ENOTTY:      MOV     EAX, -1
+                MOV     ECX, ENOTTY
+                RET
+TERMIOS_FLUSH   ENDP
+
+
+;
+; Get and preprocess a character for termio input
+;
+; In:   CX=FALSE        Return AX=CHAR_NO if no character available
+;       CX!=FALSE       Wait until signal or character available
+; Out:  AX=CHAR_SIG     Interrupted by signal
+;       AX=CHAR_NO      No character available (for CX!=FALSE)
+;       AX=CHAR_TIME    Time-out
+;       AL              Character (AH=0)
+;
+                TALIGN  2
+                ASSUME  DS:SV_DATA
+TR_GET          PROC    NEAR
+TR_GET_0:       PUSH    CX
+                CALL    READ_KEYBOARD
+                POP     CX
+                OR      AH, AH
+                JNZ     SHORT TR_GET_RET
+;
+; Strip bit 7 if ISTRIP is set
+;
+                TEST    STDIN_TERMIO.C_IFLAG, ISTRIP
+                JZ      SHORT TR_GET_1
+                AND     AL, 7FH
+TR_GET_1:
+;
+; Ignore CR characters if IGNCR is set
+;
+                TEST    STDIN_TERMIO.C_IFLAG, IGNCR
+                JZ      SHORT TR_GET_2
+                CMP     AL, CR
+                JE      SHORT TR_GET_0
+TR_GET_2:
+;
+; Translate LF to CR if INLCR is set (don't translate the CR back to LF if
+; ICRNL is also set; IGNCR is also ignored for a CR created by this
+; translation)
+;
+                TEST    STDIN_TERMIO.C_IFLAG, INLCR
+                JZ      SHORT TR_GET_3
+                CMP     AL, LF
+                JNE     SHORT TR_GET_3
+                MOV     AL, CR
+                JMP     SHORT TR_GET_4
+TR_GET_3:
+;
+; Translate CR to LF if ICRNL is set
+;
+                TEST    STDIN_TERMIO.C_IFLAG, ICRNL
+                JZ      SHORT TR_GET_4
+                CMP     AL, CR
+                JNE     SHORT TR_GET_4
+                MOV     AL, LF
+TR_GET_4:
+;
+; Translate upper-case letters to lower case if IUCLC is set
+;
+                TEST    STDIN_TERMIO.C_IFLAG, IUCLC
+                JZ      SHORT TR_GET_5
+                CMP     AL, "A"
+                JB      SHORT TR_GET_5
+                CMP     AL, "Z"
+                JA      SHORT TR_GET_5
+                ADD     AL, "a" - "A"
+TR_GET_5:
+;
+; No further input transformations are available
+;
+TR_GET_RET:     RET
+TR_GET          ENDP
+
+
+;
+; Read keyboard
+;
+; In:   CX=FALSE        Return AX=CHAR_NO if no character available
+;       CX!=FALSE       Wait until signal, time-out or character available 
+; Out:  AX=CHAR_SIG     Interrupted by signal
+;       AX=CHAR_NO      No character available (for CX!=FALSE)
+;       AX=CHAR_TIME    Time-out
+;       AL              Character (AH=0)
+;
+                TALIGN  4
+                ASSUME  DS:SV_DATA
+READ_KEYBOARD   PROC    NEAR
+RK_LOOP:        MOV     AX, 7F16H               ; Poll keyboard
+                INT     21H
+                MOV     BX, PROCESS_PTR
+                ASSUME  BX:PTR PROCESS
+                MOV     AX, CHAR_SIG
+                CMP     [BX].P_SIG_PENDING, 0
+                JNE     SHORT RK_RET
+                TEST    [BX].P_FLAGS, PF_TERMIO_TIME
+                MOV     AX, CHAR_TIME
+                JNZ     SHORT RK_RET
+                ASSUME  BX:NOTHING
+                CLI
+                MOV     BX, KBD_PTR_OUT
+                CMP     BX, KBD_PTR_IN
+                JE      SHORT RK_NONE
+                MOV     AL, [BX]
+                INC     BX
+                CMP     BX, OFFSET KBD_BUF_END
+                JNE     SHORT RK_OK
+                LEA     BX, KBD_BUF
+RK_OK:          MOV     KBD_PTR_OUT, BX
+                STI
+                MOV     AH, 0
+                JMP     SHORT RK_RET
+
+RK_NONE:        STI
+                CMP     CX, FALSE
+                JNE     SHORT RK_LOOP
+                MOV     AX, CHAR_NO
+RK_RET:         RET
+READ_KEYBOARD   ENDP
+
+;
+; Return the number of characters in the keyboard buffer
+;
+                TALIGN  4
+STDIN_AVAIL     PROC    NEAR
+                MOV     AX, 7F16H               ; Poll keyboard
+                INT     21H
+                CLI
+                MOV     AX, KBD_PTR_IN
+                SUB     AX, KBD_PTR_OUT
+                JAE     SHORT SA_1
+                ADD     AX, SIZE KBD_BUF
+SA_1:           STI
+                MOVZX   EAX, AX
+                RET
+STDIN_AVAIL     ENDP
+
+;
+; Unix-like read() for terminal
+;
+; In:   ES:EDI  Destination address
+;       ECX     Number of bytes
+;
+; Out:  CY      Error
+;       EAX     Number of bytes read (NC)
+;       EAX     errno (CY)
+;
+; Currently implemented for the keyboard only
+;
+TR_COUNT        EQU     (DWORD PTR [BP-1*4])
+TR_RESULT       EQU     (DWORD PTR [BP-2*4])
+TR_TIMER        EQU     (DWORD PTR [BP-3*4])
+TR_TIMER_FLAG   EQU     (DWORD PTR [BP-4*4])
+TR_MIN          EQU     (DWORD PTR [BP-5*4])
+TR_TMP          EQU     (DWORD PTR [BP-6*4])
+
+                TALIGN  2
+                ASSUME  DS:SV_DATA
+TERMIO_READ     PROC    NEAR
+                PUSH    BP
+                MOV     BP, SP
+                SUB     SP, 6*4
+                MOV     TR_COUNT, ECX
+                MOV     TR_RESULT, 0
+                MOV     TR_TIMER_FLAG, FALSE
+                MOV     BX, PROCESS_PTR
+                AND     (PROCESS PTR [BX]).P_FLAGS, NOT PF_TERMIO_TIME
+                TEST    STDIN_TERMIO.C_LFLAG, ICANON
+                JNZ     TR_CANON
+                MOVZX   EAX, STDIN_TERMIO.C_CC[VMIN]
+                MOV     TR_MIN, EAX
+;
+; Check for O_NDELAY mode
+;
+                TEST    STDIN_FL, O_NDELAY      ; O_NDELAY set?
+                JZ      SHORT TR_RAW_DELAY      ; No  -> skip
+;
+; Rule out all cases where we have to wait
+;
+                MOVZX   EAX, STDIN_TERMIO.C_CC[VMIN]
+                OR      EAX, EAX
+                JNZ     SHORT TR_RAW_COUNT      ; Check count
+                CMP     STDIN_TERMIO.C_CC[VTIME], 0
+                JE      SHORT TR_RAW_DELAY      ; Both zero -> won't wait
+                INC     EAX                     ; At least one character
+TR_RAW_COUNT:   PUSH    EAX
+                CALL    STDIN_AVAIL             ; Available characters
+                POP     ECX
+                CMP     EAX, ECX                ; Enough characters for VMIN?
+                JAE     TR_RAW_DELAY            ; Yes ->
+                CMP     EAX, TR_COUNT           ; Enough characters for COUNT?
+                JAE     TR_RAW_DELAY            ; Yes ->
+                MOV     EAX, EAGAIN
+                STC
+                JMP     TR_RET
+
+TR_RAW_DELAY:
+;
+; Start timer if VMIN = 0 and VTIME > 0
+;
+                CMP     STDIN_TERMIO.C_CC[VMIN], 0
+                JNE     SHORT TR_RAW_LOOP
+                CMP     STDIN_TERMIO.C_CC[VTIME], 0
+                JE      SHORT TR_RAW_LOOP
+                CALL    TR_START_TIMER
+                MOV     TR_MIN, 1
+TR_RAW_LOOP:    CMP     TR_COUNT, 0
+                JE      TR_OK
+                MOV     CX, NOT FALSE           ; Wait
+                MOV     EAX, TR_RESULT
+                CMP     EAX, TR_MIN
+                JB      SHORT TR_RAW_GET
+                MOV     CX, FALSE
+TR_RAW_GET:     CALL    TR_GET
+                CMP     AX, CHAR_NO
+                JE      TR_OK
+                CMP     AX, CHAR_TIME
+                JE      TR_OK
+                CMP     AX, CHAR_SIG
+                JE      SHORT TR_SIG
+                MOV     ES:[EDI], AL            ;...ext
+                INC     EDI
+                INC     TR_RESULT
+                DEC     TR_COUNT
+                CALL    TR_ECHO
+                CMP     TR_COUNT, 0
+                JE      TR_OK
+;
+; Restart timer for VMIN > 0 and VTIME > 0
+;
+                CMP     STDIN_TERMIO.C_CC[VMIN], 0
+                JE      SHORT TR_RAW_LOOP
+                CMP     STDIN_TERMIO.C_CC[VTIME], 0
+                JE      SHORT TR_RAW_LOOP
+;
+; Stop timer if TR_TIMER_FLAG
+;
+                CMP     TR_TIMER_FLAG, FALSE
+                JE      SHORT TR_RAW_INTER_1
+                CALL    TR_STOP_TIMER
+TR_RAW_INTER_1: MOV     BX, PROCESS_PTR
+                AND     (PROCESS PTR [BX]).P_FLAGS, NOT PF_TERMIO_TIME
+                CALL    TR_START_TIMER
+                JMP     TR_RAW_LOOP
+
+TR_SIG:         CMP     TR_TIMER_FLAG, FALSE
+                JE      SHORT TR_SIG_1
+                CALL    TR_STOP_TIMER
+TR_SIG_1:       MOV     EAX, EINTR
+                STC
+                JMP     TR_RET
+
+TR_CANON:       CMP     STDIN_BUFFERED, 0
+                JE      SHORT TR_CANON_10
+                MOV     ECX, TR_COUNT
+                CMP     ECX, STDIN_BUFFERED
+                JBE     SHORT TR_CANON_01
+                MOV     ECX, STDIN_BUFFERED
+TR_CANON_01:    SUB     TR_COUNT, ECX
+                SUB     STDIN_BUFFERED, ECX
+                ADD     TR_RESULT, ECX
+                MOV     ESI, STDIN_BUF_PTR
+                ADD     STDIN_BUF_PTR, ECX
+                CLD
+                REP     MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
+                JMP     TR_OK
+
+TR_CANON_10:    CMP     TR_COUNT, 0
+                JZ      TR_OK
+;
+; Read a line
+;
+                MOV     STDIN_BUFFERED, 0
+                LEA     ESI, STDIN_BUFFER
+                MOV     STDIN_BUF_PTR, ESI
+                MOV     STDIN_ESCAPE, FALSE
+TR_CANON_LOOP:  MOV     CX, NOT FALSE
+                CALL    TR_GET
+                CMP     AX, CHAR_SIG
+                JE      TR_SIG
+                OR      AL, AL
+                JZ      TR_CANON_EXT
+                CMP     AL, LF
+                JE      TR_CANON_LF
+                CMP     AL, STDIN_TERMIO.C_CC[VEOL]
+                JE      TR_CANON_LF
+                CMP     AL, STDIN_TERMIO.C_CC[VEOF]
+                JE      TR_CANON_EOF
+                CMP     AL, STDIN_TERMIO.C_CC[VERASE]
+                JE      SHORT TR_CANON_ERASE
+                CMP     AL, STDIN_TERMIO.C_CC[VKILL]
+                JE      SHORT TR_CANON_KILL
+                CMP     STDIN_ESCAPE, FALSE
+                JNE     TR_CANON_QUOTE
+                CMP     AL, "\"
+                JE      TR_CANON_ESC
+TR_CANON_PUT:   MOV     STDIN_ESCAPE, FALSE
+                CALL    TR_PUT
+                CALL    TR_ECHO
+                JMP     SHORT TR_CANON_LOOP
+
+TR_CANON_ERASE: CMP     STDIN_ESCAPE, FALSE
+                JNE     SHORT TR_CANON_ESC_PUT
+                CMP     STDIN_BUFFERED, 0
+                JE      TR_CANON_LOOP
+                CALL    TR_BACK
+                JMP     TR_CANON_LOOP
+
+TR_CANON_ESC_PUT:
+                PUSH    AX
+                MOV     AL, 08H
+                CALL    TR_OUT                  ; Delete the backslash
+                POP     AX
+                JMP     SHORT TR_CANON_PUT
+
+TR_CANON_KILL:  CMP     STDIN_ESCAPE, FALSE
+                JNE     SHORT TR_CANON_ESC_PUT
+                MOV     STDIN_BUFFERED, 0
+                LEA     ESI, STDIN_BUFFER
+                TEST    STDIN_TERMIO.C_LFLAG, ECHOK
+                JZ      TR_CANON_LOOP
+                MOV     AL, CR
+                CALL    TR_OUT
+                MOV     AL, LF
+                CALL    TR_OUT
+                JMP     TR_CANON_LOOP
+
+TR_CANON_EXT:   MOV     CX, NOT FALSE
+                CALL    TR_GET
+                CMP     AX, CHAR_SIG
+                JE      TR_SIG
+                JMP     TR_CANON_LOOP
+
+TR_CANON_EOF:   CMP     STDIN_ESCAPE, FALSE
+                JNE     SHORT TR_CANON_ESC_PUT
+                CMP     STDIN_BUFFERED, 0
+                JE      SHORT TR_OK
+                JMP     TR_CANON
+
+TR_CANON_LF:    CALL    TR_PUT
+                CALL    TR_ECHO
+                JMP     TR_CANON
+
+TR_CANON_ESC:   MOV     STDIN_ESCAPE, NOT FALSE
+                CALL    TR_ECHO
+                JMP     TR_CANON_LOOP
+
+TR_CANON_QUOTE: PUSH    EAX
+                MOV     AL, "\"
+                CALL    TR_PUT
+                POP     EAX
+                JMP     TR_CANON_PUT
+
+TR_OK:          CMP     TR_TIMER_FLAG, FALSE
+                JE      SHORT TR_OK_1
+                CALL    TR_STOP_TIMER
+TR_OK_1:        MOV     EAX, TR_RESULT
+                CLC
+TR_RET:         MOV     SP, BP
+                NOP                             ; Try to fix Cyrix 486DLC bug
+                POP     BP
+                RET
+TERMIO_READ     ENDP
+
+;
+;
+;
+                TALIGN  2
+                ASSUME  DS:SV_DATA
+TR_START_TIMER  PROC    NEAR
+                MOVZX   EAX, STDIN_TERMIO.C_CC[VTIME]
+                MOV     ECX, 91
+                MUL     ECX                     ; Multiply by 1.82
+                ADD     EAX, 49
+                MOV     ECX, 50
+                DIV     ECX
+                MOV     BX, PROCESS_PTR
+                MOV     DX, TT_TERMIO_TIME
+                CALL    SET_TIMER
+                MOV     TR_TIMER_FLAG, NOT FALSE
+                RET
+TR_START_TIMER  ENDP
+
+;
+;
+;
+                TALIGN  2
+                ASSUME  DS:SV_DATA
+TR_STOP_TIMER   PROC    NEAR
+                MOV     BX, PROCESS_PTR
+                MOV     DX, TT_TERMIO_TIME
+                XOR     EAX, EAX
+                CALL    SET_TIMER
+                MOV     TR_TIMER_FLAG, FALSE
+                RET
+TR_STOP_TIMER   ENDP
+
+;
+;
+;
+                TALIGN  2
+                ASSUME  DS:SV_DATA
+TR_PUT          PROC    NEAR
+                CMP     STDIN_BUFFERED, SIZE STDIN_BUFFER
+                JAE     SHORT TR_PUT_OV
+                MOV     [ESI], AL
+                INC     ESI
+                INC     STDIN_BUFFERED
+TR_PUT_OV:      RET
+TR_PUT          ENDP
+
+;
+;
+;
+                TALIGN  2
+                ASSUME  DS:SV_DATA
+TR_ECHO         PROC    NEAR
+                TEST    STDIN_TERMIO.C_LFLAG, IECHO
+                JZ      SHORT TR_ECHO_RET
+                CMP     AL, LF
+                JE      SHORT TR_ECHO_LF
+        if 1
+                JMP     SHORT TR_ECHO_1
+        else
+                CMP     AL, 20H
+                JAE     SHORT TR_ECHO_1
+                PUSH    EAX
+                MOV     AL, "^"
+                CALL    TR_OUT
+                POP     EAX
+                PUSH    EAX
+                ADD     AL, 40H
+                CALL    TR_OUT
+                POP     EAX
+                RET
+        endif
+
+TR_ECHO_LF:     MOV     AL, CR
+                CALL    TR_OUT
+                MOV     AL, LF
+TR_ECHO_1:      CALL    TR_OUT
+TR_ECHO_RET:    RET
+TR_ECHO         ENDP
+
+;
+;
+;
+                TALIGN  2
+                ASSUME  DS:SV_DATA
+TR_BACK         PROC    NEAR
+                DEC     STDIN_BUFFERED
+                DEC     ESI
+                MOV     AL, 08H
+                CALL    TR_OUT
+                MOV     AL, " "
+                CALL    TR_OUT
+                MOV     AL, 08H
+                CALL    TR_OUT
+                RET
+TR_BACK         ENDP
+
+;
+; Note: Ctrl-C!!!
+;
+; Don't use function 02H as that would require calling MAP_HANDLE.
+;
+                TALIGN  4
+TR_OUT          PROC    NEAR
+                PUSH    EAX
+                PUSH    EBX
+                PUSH    ECX
+                PUSH    EDX
+                MOV     TR_OUT_TMP_CHAR, AL
+                LEA     EDX, TR_OUT_TMP_CHAR
+                MOV     ECX, 1
+                MOV     EBX, 1                  ; Standard output
+                MOV     AH, 40H
+                INT     21H
+                POP     EDX
+                POP     ECX
+                POP     EBX
+                POP     EAX
+                RET
+TR_OUT          ENDP
+
+
+                TALIGN  4
+KBD_FLUSH       PROC    NEAR
+KF_1:           MOV     AH, 01H
+                ADD     AH, EXT_KBD
+                INT     16H
+                JZ      SHORT KF_2
+                MOV     AH, 00H
+                ADD     AH, EXT_KBD
+                INT     16H
+                JMP     SHORT KF_1
+                TALIGN  4
+KF_2:           CLI
+                LEA     AX, KBD_BUF
+                MOV     KBD_PTR_IN, AX
+                MOV     KBD_PTR_OUT, AX
+                STI
+                MOV     STDIN_BUFFERED, 0
+                RET
+KBD_FLUSH       ENDP
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Get keyboard type
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+INIT_TERMIO     PROC    NEAR
+                MOV     EXT_KBD, 00H
+                MOV     AX, 40H
+                MOV     ES, AX
+                TEST    BYTE PTR ES:[96H], 10H  ; Extended keyboard?
+                JZ      SHORT IT_1
+                MOV     EXT_KBD, 10H
+IT_1:           RET
+INIT_TERMIO     ENDP
+
+;
+; Read keyboard
+;
+; If the keyboard buffer is full, it will be cleared
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+POLL_KEYBOARD   PROC    NEAR
+PK_LOOP:        MOV     AH, 01H
+                ADD     AH, EXT_KBD
+                INT     16H
+                JZ      PK_RET
+                MOV     AH, 00H
+                ADD     AH, EXT_KBD
+                INT     16H
+                OR      AX, AX                  ; Ctrl-Break?
+                JZ      SHORT PK_LOOP           ; Yes -> repeat
+                OR      AH, AH                  ; Alt+numeric keypad?
+                JZ      SHORT PK_NORMAL         ; Yes -> no extended code
+                OR      AL, AL                  ; Extended code?
+                JZ      SHORT PK_EXT            ; Yes ->
+                CMP     AL, 0E0H                ; New extended code?
+                JE      SHORT PK_EXT            ; Yes ->
+PK_NORMAL:      TEST    STDIN_TERMIO.C_IFLAG, IDELETE
+                JZ      SHORT PK_1
+                CMP     AH, 0EH                 ; Backspace?
+                JNE     SHORT PK_1              ; No  -> skip
+                MOV     AH, AL                  ; Save character code
+                MOV     AL, 08H                 ; BS
+                CMP     AH, 7FH                 ; DEL?
+                JE      SHORT PK_1              ; Yes -> convert to BS
+                MOV     AL, 7FH                 ; DEL
+                CMP     AH, 08H                 ; BS?
+                JE      SHORT PK_1              ; Yes -> convert to DEL
+                MOV     AL, AH                  ; Restore character code
+PK_1:           TEST    STDIN_TERMIO.C_LFLAG, ISIG
+                JZ      SHORT PK_PUT
+                MOVZX   EBX, PROCESS_PTR
+                ASSUME  EBX:NEAR32 PTR PROCESS
+                CMP     BX, NO_PROCESS
+                JE      SHORT PK_PUT
+                CMP     AL, STDIN_TERMIO.C_CC[VINTR]
+                MOV     ECX, SIGINT
+                JE      SHORT PK_SIG
+                CMP     AL, STDIN_TERMIO.C_CC[VQUIT]
+                MOV     ECX, SIGQUIT
+                JE      SHORT PK_SIG
+PK_PUT:         CALL    KBD_PUT
+                JMP     SHORT PK_LOOP
+
+                TALIGN  4
+PK_EXT:         XOR     AL, AL                  ; Prefix
+                CALL    KBD_PUT
+                MOV     AL, AH                  ; Scan code
+                CALL    KBD_PUT
+                JMP     PK_LOOP
+
+                TALIGN  4
+PK_SIG:         CMP     [EBX].P_SIG_HANDLERS[4*ECX], SIG_IGN
+                JE      PK_LOOP
+                BTS     (PROCESS PTR [BX]).P_SIG_PENDING, ECX
+                JMP     PK_LOOP
+
+                TALIGN  4
+PK_RET:         RET
+                ASSUME  EBX:NOTHING
+POLL_KEYBOARD   ENDP
+
+
+                TALIGN  4
+KBD_PUT         PROC    NEAR
+                MOV     BX, KBD_PTR_IN
+                MOV     [BX], AL
+                INC     BX
+                CMP     BX, OFFSET KBD_BUF_END
+                JNE     SHORT KP_1
+                LEA     BX, KBD_BUF
+KP_1:           MOV     KBD_PTR_IN, BX
+                RET
+KBD_PUT         ENDP
+
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/termio.inc
===================================================================
--- trunk/src/emx/src/dos/termio.inc	(revision 18)
+++ trunk/src/emx/src/dos/termio.inc	(revision 18)
@@ -0,0 +1,219 @@
+;
+; TERMIO.INC -- General terminal interface
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+;
+; cf. /emx/include/sys/termio.h and /emx/include/sys/ioctl.h
+;
+
+TCGETA          =       1
+TCSETA          =       2
+TCSETAW         =       3
+TCSETAF         =       4
+TCFLSH          =       5
+TCSBRK          =       6
+TCXONC          =       7
+_TCGA           =       8               ; Used internally for tcgetattr()
+_TCSANOW        =       9               ; Used internally for tcsetattr()
+_TCSADRAIN      =       10              ; Used internally for tcsetattr()
+_TCSAFLUSH      =       11              ; Used internally for tcsetattr()
+FIONREAD        =       16
+FGETHTYPE       =       32
+
+VINTR           =       0
+VQUIT           =       1
+VERASE          =       2
+VKILL           =       3
+VEOF            =       4
+VEOL            =       5
+VMIN            =       6
+VTIME           =       7
+VSUSP           =       8                       ; termios
+VSTOP           =       9                       ; termios
+VSTART          =       10                      ; termios
+
+NCC             =       8                       ; termio
+NCCS            =       11                      ; termios
+
+IGNBRK          =       0001H
+BRKINT          =       0002H
+IGNPAR          =       0004H
+PARMRK          =       0008H
+INPCK           =       0010H
+ISTRIP          =       0020H
+INLCR           =       0040H
+IGNCR           =       0080H
+ICRNL           =       0100H
+IUCLC           =       0200H
+IXON            =       0400H
+IXANY           =       0800H
+IXOFF           =       1000H
+IDELETE         =       8000H
+
+OPOST           =       0001H
+OLCUC           =       0002H
+ONLCR           =       0004H
+OCRNL           =       0008H
+ONOCR           =       0010H
+ONLRET          =       0020H
+OFILL           =       0040H
+OFDEL           =       0080H
+NLDLY           =       0100H   ; Mask
+NL0             =       0000H
+NL1             =       0100H
+CRDLY           =       0600H   ; Mask
+_CR0            =       0000H
+_CR1            =       0200H
+_CR2            =       0400H
+_CR3            =       0600H
+TABDLY          =       1800H   ; Mask
+TAB0            =       0000H
+TAB1            =       0800H
+TAB2            =       1000H
+TAB3            =       1800H
+BSDLY           =       2000H   ; Mask
+BS0             =       0000H
+BS1             =       2000H
+VTDLY           =       4000H   ; Mask
+VT0             =       0000H
+VT1             =       4000H
+FFDLY           =       8000H   ; Mask
+FF0             =       0000H
+FF1             =       8000H
+
+CBAUD           =       000FH   ; Mask
+B0              =       0000H
+B50             =       0001H
+B75             =       0002H
+B110            =       0003H
+B134            =       0004H
+B150            =       0005H
+B200            =       0006H
+B300            =       0007H
+B600            =       0008H
+B1200           =       0009H
+B1800           =       000AH
+B2400           =       000BH
+B4800           =       000CH
+B9600           =       000DH
+B19200          =       000EH
+B38400          =       000FH
+CSIZE           =       0030H   ; Mask
+CS5             =       0000H
+CS6             =       0010H
+CS7             =       0020H
+CS8             =       0030H
+CSTOPB          =       0040H
+CREAD           =       0080H
+PARENB          =       0100H
+PARODD          =       0200H
+HUPCL           =       0400H
+CLOCAL          =       0800H
+LOBLK           =       1000H
+
+ISIG            =       0001H
+ICANON          =       0002H
+XCASE           =       0004H
+IECHO           =       0008H
+ECHOE           =       0010H
+ECHOK           =       0020H
+ECHONL          =       0040H
+NOFLSH          =       0080H
+IDEFAULT        =       8000H
+
+
+;
+; ioctl()
+;
+TERMIO          STRUCT
+C_IFLAG         DD      ?
+C_OFLAG         DD      ?
+C_CFLAG         DD      ?
+C_LFLAG         DD      ?
+C_LINE          DD      ?
+C_CC            DB      NCC DUP (?)
+TERMIO          ENDS
+
+TERMIOS         STRUCT
+C_IFLAG         DD      ?
+C_OFLAG         DD      ?
+C_CFLAG         DD      ?
+C_LFLAG         DD      ?
+C_CC            DB      NCCS DUP (?)
+                ALIGN   4
+C_RESERVED      DD      4 DUP (?)
+TERMIOS         ENDS
+
+MY_TERMIO       STRUCT
+C_IFLAG         DD      ?
+C_OFLAG         DD      ?
+C_CFLAG         DD      ?
+C_LFLAG         DD      ?
+C_CC            DB      NCCS DUP (?)
+MY_TERMIO       ENDS
+
+;
+; cf. /emx/include/sys/fcntl.h
+;
+F_GETFL         =       1
+F_SETFL         =       2
+F_GETFD         =       3
+F_SETFD         =       4
+
+O_NDELAY        =       04H
+O_APPEND        =       08H
+
+              IFNDEF __TERMIO
+
+SV_DATA         SEGMENT
+
+                EXTRN   STDIN_TERMIO:MY_TERMIO
+                EXTRN   STDIN_FL:DWORD
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   TERMIO_INIT:NEAR
+                EXTRN   TERMIO_READ:NEAR
+                EXTRN   STDIN_AVAIL:NEAR
+                EXTRN   KBD_FLUSH:NEAR
+                EXTRN   TERMIO_GET:NEAR
+                EXTRN   TERMIO_SET:NEAR
+                EXTRN   TERMIO_FLUSH:NEAR
+                EXTRN   TERMIOS_GET:NEAR
+                EXTRN   TERMIOS_SET:NEAR
+                EXTRN   TERMIOS_FLUSH:NEAR
+
+SV_CODE         ENDS
+
+INIT_CODE       SEGMENT
+
+                EXTRN   POLL_KEYBOARD:NEAR
+                EXTRN   INIT_TERMIO:NEAR
+
+INIT_CODE       ENDS
+
+              ENDIF
Index: trunk/src/emx/src/dos/timeb.inc
===================================================================
--- trunk/src/emx/src/dos/timeb.inc	(revision 18)
+++ trunk/src/emx/src/dos/timeb.inc	(revision 18)
@@ -0,0 +1,31 @@
+;
+; TIMEB.INC -- Assembler version of sys/timeb.h
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+TIMEB           STRUCT
+TIME            DWORD   ?
+MILLITM         DWORD   ?
+TIMEZONE        DWORD   ?
+DSTFLAG         DWORD   ?
+TIMEB           ENDS
Index: trunk/src/emx/src/dos/ulimit.inc
===================================================================
--- trunk/src/emx/src/dos/ulimit.inc	(revision 18)
+++ trunk/src/emx/src/dos/ulimit.inc	(revision 18)
@@ -0,0 +1,27 @@
+;
+; ULIMIT.INC -- Assembler version of sys/ulimit.h
+;
+; Copyright (c) 1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+UL_GMEMLIM      =       3
+UL_OBJREST      =       81
Index: trunk/src/emx/src/dos/utils.asm
===================================================================
--- trunk/src/emx/src/dos/utils.asm	(revision 18)
+++ trunk/src/emx/src/dos/utils.asm	(revision 18)
@@ -0,0 +1,76 @@
+;
+; UTILS.ASM -- Utility functions
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+
+                PUBLIC  NSTRCPY, UPPER
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Copy a null-terminated string
+;
+; In:  DS:SI    Pointer to source string
+;      DS:DI    Pointer to destination array
+;
+; Out: AX       Points to terminating null byte of the destination string
+;
+NSTRCPY         PROC    NEAR
+                PUSH    SI
+                PUSH    DI
+                TALIGN  4
+NSC_LOOP:       LODS    BYTE PTR DS:[SI]
+                MOV     [DI], AL
+                INC     DI
+                TEST    AL, AL
+                JNZ     SHORT NSC_LOOP
+                LEA     AX, [DI-1]
+                POP     DI
+                POP     SI
+                RET
+NSTRCPY         ENDP
+
+;
+; Convert a letter (a..z) to upper case
+;
+; In:   AL      Character
+;
+; Out:  AL      Character
+;
+                TALIGN  4
+UPPER           PROC    NEAR
+                CMP     AL, "a"
+                JB      SHORT UPPER_RET
+                CMP     AL, "z"
+                JA      SHORT UPPER_RET
+                SUB     AL, "a" - "A"
+UPPER_RET:      RET
+UPPER           ENDP
+
+SV_CODE         ENDS
+
+                END
Index: trunk/src/emx/src/dos/utils.inc
===================================================================
--- trunk/src/emx/src/dos/utils.inc	(revision 18)
+++ trunk/src/emx/src/dos/utils.inc	(revision 18)
@@ -0,0 +1,31 @@
+;
+; UTILS.INC -- Utility functions
+;
+; Copyright (c) 1991-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_CODE         SEGMENT
+
+                EXTRN   NSTRCPY:NEAR
+                EXTRN   UPPER:NEAR              ; Convert char to upper case
+
+SV_CODE         ENDS
Index: trunk/src/emx/src/dos/vcpi.asm
===================================================================
--- trunk/src/emx/src/dos/vcpi.asm	(revision 18)
+++ trunk/src/emx/src/dos/vcpi.asm	(revision 18)
@@ -0,0 +1,580 @@
+;
+; VCPI.ASM -- Virtual Control Program Interface
+;
+; Copyright (c) 1991-1999 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE TABLES.INC
+                INCLUDE PMINT.INC
+                INCLUDE PAGING.INC
+                INCLUDE SEGMENTS.INC
+                INCLUDE RPRINT.INC
+                INCLUDE MEMORY.INC
+                INCLUDE OPRINT.INC
+                INCLUDE MISC.INC
+
+                PUBLIC  VCPI_FLAG, DV_FLAG
+                PUBLIC  V2P_LIN, V2P_CR3, V2P_IDTR, V2P_GDTR
+                PUBLIC  START_VCPI, INT_BACK_VCPI, INT_VCPI
+                PUBLIC  VCPI_ALLOC, VCPI_AVAIL
+                PUBLIC  INIT_VCPI, CHECK_VCPI, GET_INT_MAP, SET_INT_MAP
+                PUBLIC  CHECK_VM, CLEANUP_VCPI, VCPI_LIN_TO_PHYS
+
+SV_DATA         SEGMENT
+
+                TALIGN  2
+V2P_LIN         LABEL   DWORD
+                DW      VCPI_TO_PROT, 0
+
+                TALIGN  2
+VCPI_TO_PROT    LABEL   DWORD
+V2P_CR3         DD      ?
+V2P_GDTR        LABEL   DWORD
+                DW      GDT_PTR, 0
+V2P_IDTR        LABEL   DWORD
+                DW      IDT_PTR, 0
+V2P_LDTR        DW      G_LDT_SEL
+V2P_TR          DW      G_TSS_SEL
+V2P_EIP         DD      ?
+V2P_CS          DW      G_SV_CODE_SEL
+
+;
+; We have to remember all VCPI pages we've allocated, as we have to
+; deallocate them when terminating. This is done by maintaining a
+; bitmap of pages allocated by calling the VCPI server. The first bit
+; refers to physical address 0. Currently, only one page is used for
+; the bitmap, therefore only 128 MB of memory are supported. This bitmap
+; must be in low memory, as deallocation is done in real mode.
+;
+VCPI_BITMAP_PHYS DD     ?               ; Points to the bitmap
+VCPI_BITMAP_SEG DW      0               ; Real-mode segment, zero: not alloc.
+
+
+EMM_PAGE        DW      0
+EMM_PAGE_FLAG   DB      FALSE           ; EMM_PAGE allocated
+
+VCPI_FLAG       DB      FALSE
+DV_FLAG         DB      FALSE
+
+;
+; Names of devices implemented by expanded memory managers
+;
+EMS_FNAME       DB      "EMMXXXX0", 0           ; EMS enabled
+NOEMS_FNAME1    DB      "EMMQXXX0", 0           ; EMS disabled
+NOEMS_FNAME2    DB      "$MMXXXX0",0            ; EMS disabled
+
+$NO_VCPI        DB      "Virtual mode not supported without VCPI", CR, LF, 0
+$DESQVIEW       DB      "DESQview without expanded memory emulator not supported", CR, LF, 0
+$VA_BUG         DB      "Page allocated more than once", CR, LF, 0
+$RTP_FAILURE    DB      "VCPI function 6 error", CR, LF, 0
+
+                DALIGN  4
+
+VCPI_ENTRY      LABEL   FWORD
+VCPI_OFF        DD      ?
+                DW      G_SERVER_SEL
+
+
+SV_DATA         ENDS
+
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+;
+; Switch from protected mode to virtual mode
+;
+                ASSUME  DS:NOTHING
+                TALIGN  4
+INT_VCPI:       MOV     AX, G_ZERO_SEL
+                MOV     DS, AX
+                ASSUME  DS:NOTHING
+                XOR     EAX, EAX
+                MOV     AX, SV_DATA
+                PUSH    EAX                     ; GS
+                PUSH    EAX                     ; FS
+                PUSH    EAX                     ; DS
+                PUSH    EAX                     ; ES
+                MOV     AX, RM_STACK
+                PUSH    EAX                     ; SS
+                LEA     AX, RM_TOS
+                PUSH    EAX                     ; ESP
+                XOR     EAX, EAX
+                PUSH    EAX                     ; EFLAGS
+                MOV     AX, INIT_CODE
+                PUSH    EAX                     ; CS
+                LEA     EAX, V2V_CONT
+                PUSH    EAX                     ; EIP
+                XOR     EAX, EAX
+                PUSH    EAX
+                PUSH    EAX
+                MOV     AX, G_SV_DATA_SEL
+                MOV     ES, AX
+                ASSUME  ES:SV_DATA
+                MOV     AX, 0DE0CH
+                CLI
+                JMP     VCPI_ENTRY
+
+                ASSUME  ES:NOTHING
+
+;
+; Allocate one page
+;
+; Out:  EAX     Physical address (or NULL_PHYS if failed)
+;
+                ASSUME  DS:SV_DATA
+VCPI_ALLOC      PROC    NEAR
+                PUSH    ES
+                PUSH    EDX
+                PUSH    EBX
+                MOV     AX, G_PHYS_SEL
+                MOV     ES, AX
+VA_RETRY:       MOV     AX, 0DE04H              ; Allocate a 4K page
+                CALL    VCPI_ENTRY
+                OR      AH, AH                  ; Failure?
+                JNZ     SHORT VA_ERROR          ; Yes -> return 0
+                MOV     EAX, EDX
+                SHR     EAX, 12                 ; Physical page number
+                CMP     EAX, 4096*8             ; Number of bits exceeded?
+                JAE     SHORT VA_RETRY          ; Yes -> retry, don't free
+                MOV     EBX, VCPI_BITMAP_PHYS
+                BTS     DWORD PTR ES:[EBX], EAX ; Test/set bit
+                JC      SHORT VA_BUG            ; Impossible
+                MOV     EAX, EDX
+                JMP     SHORT VA_RET
+
+VA_ERROR:       MOV     EAX, NULL_PHYS          ; Yes -> return NULL_PHYS
+VA_RET:         POP     EBX
+                POP     EDX
+                POP     ES
+                RET
+
+VA_BUG:         LEA     EDX, $VA_BUG
+                CALL    OTEXT                   ; Display error message
+                MOV     AX, 4CFFH               ; Quit
+                INT     21H
+                JMP     SHORT $                 ; Never reached
+VCPI_ALLOC      ENDP
+
+
+;
+; Available VCPI memory
+;
+; Amount of available memory will be added to TAVAIL.
+;
+                ASSUME  DS:SV_DATA
+VCPI_AVAIL      PROC    NEAR
+                PUSH    EAX
+                PUSH    EDX
+                MOV     AX, 0DE03H              ; Get number of free 4K pages
+                CALL    VCPI_ENTRY
+                OR      AH, AH                  ; Failure?
+                JNZ     SHORT VAV_RET           ; Yes -> no memory
+                ADD     TAVAIL, EDX             ; Add to sum
+VAV_RET:        POP     EDX
+                POP     EAX
+                RET
+VCPI_AVAIL      ENDP
+
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Check presence of VCPI server
+;
+                ASSUME  DS:SV_DATA
+CHECK_VCPI      PROC    NEAR
+                MOV     EMM_PAGE_FLAG, FALSE
+;
+; First, check the EMS interrupt vector
+;
+                MOV     AX, 3567H               ; Get interrupt vector 67H
+                INT     21H
+                MOV     AX, ES
+                OR      AX, BX                  ; Is the vector 0:0 ?
+                JZ      SHORT CV_END            ; Yes -> no VCPI
+;
+; Check for an EMM with EMS enabled
+;
+                LEA     DX, EMS_FNAME
+                CALL    CHECK_EMM               ; EMS present?
+                JC      SHORT EMM_DISABLED      ; No  -> try disabled EMS
+;
+; Check EMM status
+;
+                MOV     AH, 40H                 ; Get EMM status
+                INT     67H
+                CMP     AH, 0                   ; Successful?
+                JNE     SHORT CV_END            ; No  -> no VCPI
+;
+; Try to allocate a page.  Ignore failure
+;
+                MOV     BX, 1
+                MOV     AH, 43H                 ; Allocate an EMS page
+                INT     67H
+                CMP     AH, 0
+                JNE     SHORT EMS_1
+                MOV     EMM_PAGE, DX
+                MOV     EMM_PAGE_FLAG, NOT FALSE
+EMS_1:          JMP     SHORT EMM_OK
+
+;
+; Check for an EMM with EMS disabled (using undocumented "features")
+;
+EMM_DISABLED:   LEA     DX, NOEMS_FNAME1
+                CALL    CHECK_EMM
+                JNC     SHORT EMM_OK            ; EMM present
+                LEA     DX, NOEMS_FNAME2
+                CALL    CHECK_EMM
+                JC      SHORT CV_END            ; No EMM present -> no VCPI
+;
+; There is an EMM with EMS enabled or disabled.  Check for VCPI
+;
+EMM_OK:         MOV     AX, 0DE00H              ; VCPI presence detection
+                INT     67H
+                CMP     AH, 0                   ; VCPI present?
+                JNE     SHORT CV_END            ; No ->
+;
+; VCPI server present.  Don't deallocate the page to prevent the VCPI
+; server from switching back to real mode
+;
+                MOV     VCPI_FLAG, NOT FALSE
+                JMP     SHORT CV_RET
+
+;
+; Dellocate the EMS page if we have allocated one
+;
+CV_END:         CMP     EMM_PAGE_FLAG, FALSE
+                JE      SHORT CV_RET
+                MOV     EMM_PAGE_FLAG, FALSE
+                MOV     DX, EMM_PAGE
+                MOV     AH, 45H
+                INT     67H
+CV_RET:         RET
+CHECK_VCPI      ENDP
+
+
+;
+; Check for the presence of an expanded memory manager
+;
+; In:   DX      Pointer to device name
+;
+; Out:  NC      EMM present
+;
+                EVEN
+CHECK_EMM       PROC    NEAR
+                MOV     AX, 3D00H               ; Open
+                INT     21H
+                JC      SHORT CE_RET
+;
+; A file or device with that name exists.  Check for a device
+;
+                MOV     BX, AX                  ; Handle
+                MOV     AX, 4400H               ; IOCTL: get device data
+                INT     21H
+                JC      SHORT CE_FAIL           ; Failure -> no EMM
+                TEST    DL, 80H                 ; Device?
+                JZ      SHORT CE_FAIL           ; No -> no EMM
+                MOV     AX, 4407H               ; IOCTL: check output status
+                INT     21H
+                JC      SHORT CE_FAIL           ; Failure -> no EMM
+                CMP     AL, 0FFH                ; Ready?
+                JNE     SHORT CE_FAIL           ; No  -> no EMM
+                MOV     AH, 3EH                 ; Close
+                INT     21H
+                CLC
+CE_RET:         RET
+
+CE_FAIL:        MOV     AH, 3EH                 ; Close
+                INT     21H
+                STC
+                RET
+CHECK_EMM       ENDP
+
+
+;
+; Fatal exit for some cases not handled without VCPI (virtual mode, DESQview)
+;
+                EVEN
+CHECK_VM        PROC    NEAR
+                CMP     VCPI_FLAG, FALSE
+                JNE     SHORT CVM_RET
+                .386P
+                SMSW    AX                      ; Get machine status word
+                .386
+                TEST    AX, 0001H               ; Protected (virtual) mode?
+                JZ      SHORT NO_VCPI_1         ; No -> continue
+                LEA     DX, $NO_VCPI            ; We've a problem...
+VCPI_ERROR:     CALL    RTEXT
+                MOV     AL, 0FFH
+                JMP     EXIT
+
+;
+; No VCPI: DESQview not supported
+;
+NO_VCPI_1:      CMP     DV_FLAG, FALSE          ; Running under DESQview?
+                JE      SHORT CVM_RET           ; No -> ok
+                LEA     DX, $DESQVIEW           ; Not supported
+                JMP     SHORT VCPI_ERROR
+
+CVM_RET:        RET
+CHECK_VM        ENDP
+
+
+
+;
+; Free all pages allocated via VCPI
+;
+CLEANUP_VCPI    PROC    NEAR
+                CMP     VCPI_FLAG, FALSE        ; VCPI active?
+                JE      SHORT CUV_RET           ; No -> nothing to do
+                MOV     AX, VCPI_BITMAP_SEG     ; Get segment of bitmap
+                OR      AX, AX                  ; Bitmap allocated?
+                JZ      SHORT CUV_5             ; No -> nothing to do
+                MOV     ES, AX
+                XOR     DI, DI                  ; Bitmap pointer
+                XOR     EDX, EDX                ; Physical address
+CUV_1:          CMP     DI, 4096                ; End of bitmap?
+                JAE     SHORT CUV_5             ; Yes -> done
+                CMP     DWORD PTR ES:[DI], 0    ; Any bits in this DWORD?
+                JNZ     SHORT CUV_2             ; Yes -> deallocate pages
+                ADD     DI, 4                   ; Next DWORD
+                ADD     EDX, 32*4096            ; Adjust physical address
+                JMP     SHORT CUV_1             ; Repeat
+
+CUV_2:          MOV     CX, 32                  ; Examine 32 bits
+                XOR     ESI, ESI
+                XCHG    ESI, ES:[DI]            ; Fetch DWORD, set to zero
+CUV_3:          SHR     ESI, 1                  ; Bit set?
+                JNC     SHORT CUV_4             ; No  -> skip
+                MOV     AX, 0DE05H              ; Free a 4K page
+                INT     67H
+CUV_4:          ADD     EDX, 4096               ; Adjust physical address
+                LOOP    CUV_3                   ; Repeat for all 32 bits
+                ADD     DI, 4                   ; Next DWORD
+                JMP     SHORT CUV_1
+
+;
+; Deallocate the EMS page allocated by the VCPI presence check
+;
+CUV_5:          CMP     EMM_PAGE_FLAG, FALSE
+                JE      SHORT CUV_RET
+                MOV     EMM_PAGE_FLAG, FALSE
+                MOV     DX, EMM_PAGE
+                MOV     AH, 45H
+                INT     67H
+CUV_RET:        RET
+CLEANUP_VCPI    ENDP
+
+
+;
+; VCPI specific initializations, setup page tables, allocate bitmap.
+;
+                ASSUME  DS:SV_DATA
+INIT_VCPI       PROC    NEAR
+                MOV     AX, 1
+                CALL    RM_ALLOC                ; Allocate 0th page table
+                CMP     AX, NULL_RM             ; Out of memory?
+                JE      RM_OUT_OF_MEM           ; Yes -> abort
+                MOV     PAGE_TAB0_SEG, AX       ; Save address
+                MOV     ES, AX
+                XOR     DI, DI
+                MOV     ECX, 1024
+                XOR     EAX, EAX
+                CLD
+                REP     STOS DWORD PTR ES:[DI]
+                XOR     DI, DI                  ; ES:DI --> 0th page table
+                LEA     SI, G_VCPI_DESC         ; DS:SI --> GDT entries
+                MOV     AX, 0DE01H              ; Get protected mode interface
+                INT     67H
+;
+; RM_TO_PHYS works from now onwards.
+;
+                MOV     VCPI_OFF, EBX
+                MOV     LIN_START, 1 SHL 22     ; 1st page table
+;
+; Put page table 0 into page directory
+;
+                MOV     AX, PAGE_TAB0_SEG
+                XOR     DX, DX
+                CALL    RM_TO_PHYS
+                OR      EAX, 7
+                MOV     FS, PAGE_DIR_SEG
+                MOV     FS:[0], EAX
+;
+; Create linear address space for G_PHYS_SEL
+;
+; The VCPI server initializes parts of page table 0 (0..4M), at least the
+; first 1M. We must not change the page table entries initialized by the VCPI
+; server. But the `Allocate a 4K Page' call of the VCPI server may return a
+; page with a physical address in this range. Now we have a problem: How
+; shall we access those pages, as we cannot use identity mapping?
+; Solution: We remap the entire physical memory for use with G_PHYS_SEL.
+; The part of the 0th page table initialized by the VCPI server will be
+; copied.
+;
+; Important: LIN_START must point to an unused page table (or no
+;            swapper info will be created). This is done by making
+;            LIN_START point to the beginning of the next page table.
+;
+                MOV     AX, 0DE02H              ; Get maximum physical address
+                INT     67H
+                ADD     EDX, 1000H              ; First free physical address
+                ADD     EDX, (1 SHL 22)-1       ; Round to next page table
+                AND     EDX, NOT ((1 SHL 22)-1)
+                MOV     EBP, 0                  ; Physical address = 0
+                MOV     FS, PAGE_DIR_SEG        ; Page directory
+                MOV     SI, 4                   ; Page table 1
+                MOV     EAX, LIN_START          ; First free linear address
+                PUSH    EAX                     ; Save for G_PHYS_SEL base
+                ADD     LIN_START, EDX          ; First free linear address
+                MOV     ECX, EDX                ; Compute number of pages
+                SHR     ECX, 22                 ; of physical memory
+                PUSH    EDX
+                CALL    MAP_PAGES               ; Initialize page tables
+IVCPI_1:        POP     ECX
+                POP     EAX                     ; Base address of G_PHYS_SEL
+                MOV     G_PHYS_BASE, EAX
+                LEA     DI, G_PHYS_DESC
+                CALL    RM_SEG_BASE
+                CALL    RM_SEG_SIZE
+;
+; Allocate and zero the VCPI allocation bitmap
+;
+                MOV     AX, 1
+                CALL    RM_ALLOC                ; Allocate bitmap
+                CMP     AX, NULL_RM             ; Out of memory?
+                JE      RM_OUT_OF_MEM           ; Yes -> abort
+                MOV     VCPI_BITMAP_SEG, AX     ; Save segment
+                PUSH    AX
+                XOR     DX, DX                  ; Offset = 0
+                CALL    RM_TO_PHYS              ; Compute physical address
+                MOV     VCPI_BITMAP_PHYS, EAX   ; Save physical address
+                POP     ES                      ; Restore segment
+                XOR     DI, DI                  ; Zero the bitmap
+                XOR     AL, AL
+                MOV     CX, 4096
+                CLD
+                REP     STOS BYTE PTR ES:[DI]
+                RET
+INIT_VCPI       ENDP
+
+
+;
+; Start protected mode
+;
+                ASSUME  DS:SV_DATA
+START_VCPI      PROC    NEAR
+                MOV     V2P_EIP, OFFSET PROT1   ; Protected mode entry point
+                MOV     ESI, V2P_LIN            ; Table of registers
+                MOV     AX, 0DE0CH              ; Switch to protected mode
+                CLI                             ; Required by VCPI specs.
+                INT     67H                     ; Call VCPI server
+                JMP     SHORT $                 ; Hardly ever reached (note 1)
+;
+; Note 1: INT 67H doesn't work when single-stepping into the interrupt
+;         routine due to virtual mode and changed IDTR.
+;
+START_VCPI      ENDP
+
+
+;
+; Return from virtual mode to protected-mode interrupt handler
+;
+                ASSUME  DS:SV_DATA
+                TALIGN  4
+INT_BACK_VCPI   PROC    NEAR
+                MOV     V2P_EIP, OFFSET V2P_CONT
+                MOV     ESI, V2P_LIN
+                MOV     AX, 0DE0CH
+                CLI
+                INT     67H
+                JMP     SHORT $                 ; Hardly ever reached (note 1)
+INT_BACK_VCPI   ENDP
+
+
+;
+; Get interrupt vector mappings
+;
+                ASSUME  DS:NOTHING
+GET_INT_MAP     PROC    NEAR
+                MOV     AX, 0DE0AH
+                INT     67H                     ; Get interrupt vector mappings
+                RET
+GET_INT_MAP     ENDP
+
+
+;
+; Inform VCPI server about interrupt vector mappings
+;
+                ASSUME  DS:NOTHING
+SET_INT_MAP     PROC    NEAR
+                MOV     AX, 0DE0BH
+                INT     67H
+                RET
+SET_INT_MAP     ENDP
+
+
+;
+; Convert linear address in first Megabyte to physical address
+;
+; In:   EAX     Linear address (less than 1M)
+;
+; Out:  EAX     Physical address
+;
+                ASSUME  DS:SV_DATA
+VCPI_LIN_TO_PHYS PROC   NEAR
+                PUSH    CX                      ; Save CX
+                PUSH    EDX                     ; Save EDX
+                PUSH    EAX                     ; Save linear address
+                SHR     EAX, 12                 ; Compute page number
+                MOV     CX, AX
+                MOV     AX, 0DE06H              ; Get physical address of 4K
+                INT     67H                     ; page in first Megabyte
+                OR      AH, AH                  ; Success?
+                JNZ     SHORT RTP_FAILURE       ; No  -> stop (cannot happen)
+                POP     EAX                     ; Restore linear address
+                AND     EAX, 0FFFH              ; Keep offset into page
+                ADD     EAX, EDX                ; Add physical address
+                POP     EDX                     ; Restore EDX
+                POP     CX                      ; Restore CX
+                RET
+
+RTP_FAILURE:    LEA     DX, $RTP_FAILURE        ; Error message
+                CALL    RTEXT
+                MOV     AL, 0FFH                ; Return code = 255
+                JMP     EXIT                    ; Quit
+
+VCPI_LIN_TO_PHYS ENDP
+
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/vcpi.inc
===================================================================
--- trunk/src/emx/src/dos/vcpi.inc	(revision 18)
+++ trunk/src/emx/src/dos/vcpi.inc	(revision 18)
@@ -0,0 +1,51 @@
+;
+; VCPI.INC -- Virtual Control Program Interface
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_DATA         SEGMENT
+
+                EXTRN   VCPI_FLAG:BYTE, DV_FLAG:BYTE
+                EXTRN   V2P_LIN:DWORD, V2P_CR3:DWORD
+                EXTRN   V2P_GDTR:DWORD, V2P_IDTR:DWORD
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                EXTRN   INT_VCPI:NEAR
+                EXTRN   VCPI_ALLOC:NEAR
+                EXTRN   VCPI_AVAIL:NEAR
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                EXTRN   START_VCPI:NEAR, INT_BACK_VCPI:NEAR
+                EXTRN   INIT_VCPI:NEAR, CHECK_VCPI:NEAR, CLEANUP_VCPI:NEAR
+                EXTRN   GET_INT_MAP:NEAR, SET_INT_MAP:NEAR, CHECK_VM:NEAR
+                EXTRN   VCPI_LIN_TO_PHYS:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/version.inc
===================================================================
--- trunk/src/emx/src/dos/version.inc	(revision 18)
+++ trunk/src/emx/src/dos/version.inc	(revision 18)
@@ -0,0 +1,31 @@
+;
+; VERSION.INC -- Version number and revision index
+;
+; Copyright (c) 1991-2000 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+VERSION         EQU     <"0.9d">                ; No comment
+REV_INDEX_TXT   EQU     <"61">                  ; Revision index (as text)
+REV_INDEX_BIN   =       61                      ; Revision index (as number)
+
+HDR_EMX_LEN     =       4                       ; "emx "
+HDR_VERSION_LEN =       9                       ; "emx 0.9d" plus null char
Index: trunk/src/emx/src/dos/vprint.asm
===================================================================
--- trunk/src/emx/src/dos/vprint.asm	(revision 18)
+++ trunk/src/emx/src/dos/vprint.asm	(revision 18)
@@ -0,0 +1,271 @@
+;
+; VPRINT.ASM -- Text output directly to video memory
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE TABLES.INC
+                INCLUDE SEGMENTS.INC
+
+                PUBLIC  VWIDTH, VHEIGHT
+                PUBLIC  VDWORD, VWORD, VBYTE, VNIBBLE
+                PUBLIC  VTEXT, VCHAR, VCRLF, VCLS, VGETCOL, VWRAP
+                PUBLIC  VINIT
+
+SV_DATA         SEGMENT
+
+VWIDTH          DW      80                      ; Number of character columns
+VHEIGHT         DW      25                      ; Number of character rows
+VPTR            DW      0                       ; Destination pointer
+
+SV_DATA         ENDS
+
+
+SV_CODE         SEGMENT
+
+                ASSUME  CS:SV_CODE, DS:NOTHING
+
+
+                ASSUME  DS:SV_DATA
+VDWORD          PROC    NEAR
+                ROR     EAX, 16
+                CALL    VWORD
+                ROR     EAX, 16
+                CALL    VWORD
+                RET
+VDWORD          ENDP
+
+
+                ASSUME  DS:SV_DATA
+VWORD           PROC    NEAR
+                XCHG    AL, AH
+                CALL    VBYTE
+                XCHG    AL, AH
+                CALL    VBYTE
+                RET
+VWORD           ENDP
+
+
+                ASSUME  DS:SV_DATA
+VBYTE           PROC    NEAR
+                PUSH    AX
+                SHR     AL, 4
+                CALL    VNIBBLE
+                POP     AX
+                PUSH    AX
+                CALL    VNIBBLE
+                POP     AX
+                RET
+VBYTE           ENDP
+
+
+                ASSUME  DS:SV_DATA
+VNIBBLE         PROC    NEAR
+                AND     AL, 0FH
+                ADD     AL, 30H
+                CMP     AL, 3AH
+                JB      SHORT VNIB1
+                ADD     AL, 7
+VNIB1:          CALL    VCHAR
+                RET
+VNIBBLE         ENDP
+
+
+                ASSUME  DS:SV_DATA
+VTEXT           PROC    NEAR
+                PUSH    AX
+VTEXT1:         MOV     AL, DS:[EDX]
+                OR      AL, AL
+                JZ      SHORT VTEXT9
+                CALL    VCHAR
+                INC     EDX
+                JMP     SHORT VTEXT1
+VTEXT9:         POP     AX
+                RET
+VTEXT           ENDP
+
+
+                ASSUME  DS:SV_DATA
+VCHAR           PROC    NEAR
+                PUSH    BX
+                MOV     BX, VPTR
+                CMP     AL, CR
+                JE      SHORT VCHAR_CR
+                CMP     AL, LF
+                JE      SHORT VCHAR_LF
+                CMP     AL, TAB
+                JE      SHORT VCHAR_TAB
+                MOV     ES:[BX], AL
+                ADD     BX, 2
+VCHAR_RET:      MOV     VPTR, BX
+                POP     BX
+                RET
+
+VCHAR_CR:       PUSH    AX
+                PUSH    DX
+                MOV     AX, BX
+                XOR     DX, DX
+                MOV     BX, VWIDTH
+                SHL     BX, 1
+                DIV     BX
+                MUL     BX
+                MOV     BX, AX
+                POP     DX
+                POP     AX
+                JMP     VCHAR_RET
+
+VCHAR_LF:       ADD     BX, VWIDTH
+                ADD     BX, VWIDTH
+                JMP     VCHAR_RET
+
+VCHAR_TAB:      PUSH    AX
+                PUSH    DX
+                MOV     AX, BX
+                SHR     AX, 1                   ; Compute character number
+                XOR     DX, DX
+                DIV     VWIDTH                  ; Compute column number (DX)
+                MOV     AX, DX
+                OR      AX, 8-1
+                INC     AX                      ; Next tab position
+                SUB     AX, DX                  ; Distance to next tab position
+                SHL     AX, 1                   ; Number of bytes to skip
+                ADD     BX, AX                  ; Update pointer
+                POP     DX
+                POP     AX
+                JMP     VCHAR_RET
+VCHAR           ENDP
+
+
+                ASSUME  DS:SV_DATA
+VCRLF           PROC    NEAR
+                PUSH    AX
+                MOV     AL, CR
+                CALL    VCHAR
+                MOV     AL, LF
+                CALL    VCHAR
+                POP     AX
+                RET
+VCRLF           ENDP
+
+
+                ASSUME  DS:SV_DATA
+VCLS            PROC    NEAR
+                MOV     AX, VWIDTH
+                MUL     VHEIGHT
+                MOV     CX, AX
+                MOV     AX, 0720H
+                MOV     DI, 0
+                CLD
+                REP     STOSW
+                MOV     VPTR, 0                 ; Set destination pointer
+                RET
+VCLS            ENDP
+
+;
+; Return the current column number
+;
+; Out:  AX      Column number (0 through VWIDTH - 1)
+;
+                ASSUME  DS:SV_DATA
+VGETCOL         PROC    NEAR
+                PUSH    DX
+                MOV     AX, VPTR
+                SHR     AX, 1                   ; Compute character number
+                XOR     DX, DX
+                DIV     VWIDTH                  ; Compute column number (DX)
+                MOV     AX, DX
+                POP     DX
+                RET
+VGETCOL         ENDP
+
+;
+; Move to the beginning of the next line if there are less than AX
+; characters remaining on the line (don't print in the last column).
+;
+                ASSUME  DS:SV_DATA
+VWRAP           PROC    NEAR
+                PUSH    DX
+                PUSH    AX
+                CALL    VGETCOL
+                POP     DX
+                ADD     AX, DX
+                CMP     AX, VWIDTH
+                JB      SHORT VWRAP_1
+                CALL    VCRLF
+VWRAP_1:        POP     DX
+                RET
+VWRAP           ENDP
+
+SV_CODE         ENDS
+
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Set VWIDTH and VHEIGHT
+;
+                ASSUME  DS:SV_DATA
+VINIT           PROC    NEAR
+;
+; Get the width in character columns
+;
+                MOV     AH, 0FH                 ; Get current video mode
+                INT     10H
+                MOV     AL, AH                  ; Number of character columns
+                XOR     AH, AH
+                MOV     VWIDTH, AX
+;
+; Get the height in character rows
+;
+                MOV     AH, 11H                 ; Get font information
+                MOV     AL, 30H                 ; (Check for EGA or better)
+                MOV     BH, 0
+                MOV     CX, 1234H
+                PUSH    ES
+                PUSH    BP
+                INT     10H
+                POP     BP
+                POP     ES
+                MOV     AX, 25
+                CMP     CX, 1234H               ; Function implemented?
+                JE      SHORT VINIT_1           ; No  -> old adapter (25 rows)
+                PUSH    ES
+                MOV     AX, 40H
+                MOV     ES, AX
+                MOVZX   AX, BYTE PTR ES:[84H]
+                INC     AX
+                POP     ES
+VINIT_1:        MOV     VHEIGHT, AX
+                MUL     VWIDTH
+                MOVZX   ECX, AX
+                SHL     ECX, 1
+                LEA     DI, G_VIDEO_DESC
+                CALL    RM_SEG_SIZE
+                RET
+VINIT           ENDP
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/vprint.inc
===================================================================
--- trunk/src/emx/src/dos/vprint.inc	(revision 18)
+++ trunk/src/emx/src/dos/vprint.inc	(revision 18)
@@ -0,0 +1,45 @@
+;
+; VPRINT.INC -- Text output directly to video memory
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_DATA         SEGMENT
+
+                EXTRN   VWIDTH:WORD             ; Number of columns
+                EXTRN   VHEIGHT:WORD            ; Number of rows
+
+SV_DATA         ENDS
+
+SV_CODE         SEGMENT
+
+                EXTRN   VDWORD:NEAR, VWORD:NEAR, VBYTE:NEAR, VNIBBLE:NEAR
+                EXTRN   VTEXT:NEAR, VCHAR:NEAR, VCRLF:NEAR
+                EXTRN   VCLS:NEAR, VGETCOL:NEAR, VWRAP:NEAR
+
+SV_CODE         ENDS
+
+INIT_CODE       SEGMENT
+
+                EXTRN   VINIT:NEAR              ; Set VWIDTH and VHEIGHT
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/dos/xms.asm
===================================================================
--- trunk/src/emx/src/dos/xms.asm	(revision 18)
+++ trunk/src/emx/src/dos/xms.asm	(revision 18)
@@ -0,0 +1,182 @@
+;
+; XMS.ASM -- Manage extended memory
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+                INCLUDE EMX.INC
+                INCLUDE MEMORY.INC
+                INCLUDE RPRINT.INC
+                INCLUDE OPTIONS.INC
+                INCLUDE VCPI.INC
+
+                PUBLIC  XMS_FLAG, DISABLE_XMS_MEM
+                PUBLIC  CHECK_XMS, INIT_XMS, CLEANUP_XMS
+                PUBLIC  XMS_A20_ON, XMS_A20_OFF
+
+XMS_NULL_HANDLE =       0
+
+SV_DATA         SEGMENT
+
+XMS_ENTRY       LABEL   DWORD
+XMS_OFF         DW      ?
+XMS_SEG         DW      ?
+
+XMS_FLAG        DB      FALSE
+DISABLE_XMS_MEM DB      FALSE
+
+$XMS_A20_ON     DB      "Cannot enable A20 via XMS", CR, LF, 0
+$XMS_VER        DB      "Unsupported XMS version", CR, LF, 0
+
+SV_DATA         ENDS
+
+INIT_CODE       SEGMENT
+
+                ASSUME  CS:INIT_CODE, DS:NOTHING
+
+;
+; Check presence of XMS driver
+;
+                ASSUME  DS:SV_DATA
+CHECK_XMS       PROC    NEAR
+                CMP     DISABLE_EXT_MEM, FALSE  ; Extended memory disabled?
+                JNE     SHORT CX_RET            ; Yes -> don't use XMS
+                MOV     AX, 4300H               ; XMS installation check
+                INT     2FH
+                CMP     AL, 80H                 ; XMS available?
+                JNE     SHORT CX_RET            ; No  -> skip
+                MOV     AX, 4310H               ; Get entry point
+                INT     2FH
+                MOV     XMS_OFF, BX             ; Store entry point
+                MOV     XMS_SEG, ES
+                MOV     AH, 00H                 ; Get version
+                CALL    XMS_ENTRY
+                CMP     OVERRIDE_FLAG, FALSE    ; Override version check?
+                JNE     SHORT CX_OK             ; Yes -> skip (danger!)
+                CMP     AX, 0200H               ; Specification 2.0 or later?
+                JB      SHORT XMS_VER           ; No  -> abort
+                CMP     BX, 0206H               ; Driver revision >= 2.06?
+                JB      SHORT XMS_VER           ; No  -> abort (buggy driver!)
+CX_OK:          MOV     XMS_FLAG, NOT FALSE
+CX_RET:         RET
+
+XMS_VER:        LEA     DX, $XMS_VER            ; Unsupported XMS version
+                CALL    RTEXT                   ; Display message
+                MOV     AX, 4CFFH               ; Abort
+                INT     21H
+
+CHECK_XMS       ENDP
+
+;
+; Initialize high memory (XMS)
+;
+                ASSUME  DS:SV_DATA
+INIT_XMS        PROC    NEAR
+                CMP     DISABLE_XMS_MEM, FALSE  ; Usage of XMS memory disabled?
+                JNE     IX9                     ; Yes -> skip
+                LEA     SI, HIMEM_TAB[0]
+                ASSUME  SI:PTR HIMEM_ENTRY
+IX1:            CMP     HIMEM_COUNT, HIMEM_MAX  ; Table full?
+                JAE     SHORT IX9               ; Yes -> done
+                MOV     AH, 08H                 ; Query free extended memory
+                CALL    XMS_ENTRY
+                CMP     AX, 7                   ; Don't use less than 7KB
+                JB      SHORT IX9
+                MOV     DX, AX
+                MOVZX   EAX, AX
+                SHL     EAX, 10                 ; Multiply by 1K
+                MOV     [SI].HM_SIZE, EAX
+                MOV     AH, 09H                 ; Allocate extended memory blk
+                CALL    XMS_ENTRY
+                OR      AX, AX                  ; Ok?
+                JZ      SHORT IX9               ; No  -> quit loop
+                MOV     [SI].HM_HANDLE, DX      ; Save handle
+                MOV     AH, 0CH                 ; Lock extended memory block
+                CALL    XMS_ENTRY
+                OR      AX, AX                  ; Ok?
+                JZ      SHORT IX9               ; No  -> quit loop
+                MOV     WORD PTR [SI].HM_ADDR[0], BX
+                MOV     WORD PTR [SI].HM_ADDR[2], DX
+                ADD     SI, SIZE HIMEM_ENTRY
+                INC     HIMEM_COUNT
+                JMP     SHORT IX1
+                ASSUME  SI:NOTHING
+IX9:            RET
+INIT_XMS        ENDP
+
+
+                ASSUME  DS:SV_DATA
+CLEANUP_XMS     PROC    NEAR
+                CMP     XMS_FLAG, FALSE
+                JE      SHORT CUX_RET
+                LEA     SI, HIMEM_TAB
+                ASSUME  SI:PTR HIMEM_ENTRY
+                MOV     CX, HIMEM_COUNT
+                JCXZ    CUX_RET
+;
+; Note: If XMS_FLAG is non-zero, we have only extended memory blocks
+;       allocated via XMS!  There won't be a memory block allocated
+;       by hooking INT 15H.
+;
+CUX_1:          MOV     DX, [SI].HM_HANDLE
+                MOV     AH, 0DH                 ; Unlock extended memory block
+                CALL    XMS_ENTRY
+                MOV     AH, 0AH                 ; Free extended memory block
+                CALL    XMS_ENTRY
+                ADD     SI, SIZE HIMEM_ENTRY
+                LOOP    CUX_1
+                ASSUME  SI:NOTHING
+CUX_RET:        RET
+CLEANUP_XMS     ENDP
+
+
+;
+; Enable A20
+;
+                ASSUME  DS:SV_DATA
+XMS_A20_ON      PROC    NEAR
+                MOV     AH, 05H
+                CALL    XMS_ENTRY
+                OR      AX, AX
+                JNZ     SHORT XMS_A20_ON_RET
+                LEA     DX, $XMS_A20_ON
+                CALL    RTEXT
+                MOV     AX, 4CFFH
+                INT     21H
+XMS_A20_ON_RET: CLI
+                RET
+XMS_A20_ON      ENDP
+
+;
+; Disable A20
+;
+                ASSUME  DS:SV_DATA
+XMS_A20_OFF     PROC    NEAR
+                MOV     AH, 06H
+                CALL    XMS_ENTRY
+                CLI
+                RET
+XMS_A20_OFF     ENDP
+
+INIT_CODE       ENDS
+
+                END
Index: trunk/src/emx/src/dos/xms.inc
===================================================================
--- trunk/src/emx/src/dos/xms.inc	(revision 18)
+++ trunk/src/emx/src/dos/xms.inc	(revision 18)
@@ -0,0 +1,38 @@
+;
+; XMS.INC -- Manage extended memory
+;
+; Copyright (c) 1991-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; See emx.asm for a special exception.
+;
+
+SV_DATA         SEGMENT
+
+                EXTRN   XMS_FLAG:BYTE
+                EXTRN   DISABLE_XMS_MEM:BYTE
+
+SV_DATA         ENDS
+
+INIT_CODE       SEGMENT
+
+                EXTRN   CHECK_XMS:NEAR, INIT_XMS:NEAR, CLEANUP_XMS:NEAR
+                EXTRN   XMS_A20_ON:NEAR, XMS_A20_OFF:NEAR
+
+INIT_CODE       ENDS
Index: trunk/src/emx/src/emxbind/COPYING
===================================================================
--- trunk/src/emx/src/emxbind/COPYING	(revision 18)
+++ trunk/src/emx/src/emxbind/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxbind/cmd.c
===================================================================
--- trunk/src/emx/src/emxbind/cmd.c	(revision 18)
+++ trunk/src/emx/src/emxbind/cmd.c	(revision 18)
@@ -0,0 +1,243 @@
+/* cmd.c -- Handle commands
+   Copyright (c) 1991-1995 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "emxbind.h"
+
+
+/* Alter the emx options of a bound executable. */
+
+static void alter (void)
+{
+  set_options ();
+  my_seek (&inp_file, patch_pos);
+  my_write (&dos_bind_h, sizeof (dos_bind_h), &inp_file);
+  my_seek (&inp_file, a_in_pos + a_in_data);
+  my_write (&os2_bind_h, sizeof (os2_bind_h), &inp_file);
+}
+
+
+/* Perform initializations for the bind operation. */
+
+static void init_bind (void)
+{
+  if (dll_flag)
+    {
+      relocatable = TRUE;
+      stack_size = 0;
+    }
+}
+
+
+/* Change the application type. */
+
+static void exe_type (void)
+{
+  read_os2_header ();
+  exe_flags ();
+  my_change (&out_file, &inp_file);
+  my_seek (&out_file, inp_os2_pos);
+  my_write (&os2_h, sizeof (os2_h), &out_file);
+}
+
+
+/* Show the emx options of a bound executable. */
+
+static void show (void)
+{
+  if (dos_bind_h.options[0] != 0)
+    printf ("emx options for MS-DOS: %s\n", (char *)dos_bind_h.options);
+  if (os2_bind_h.options[0] != 0)
+    printf ("emx options for OS/2:   %s\n", (char *)os2_bind_h.options);
+}
+
+
+/* Strip the symbols from a bound executable. */
+
+static void strip_symbols (void)
+{
+  long size, pos, str_len;
+
+  pos = a_in_pos + a_in_sym;
+  size = my_size (&inp_file);
+  if (pos + sizeof (str_len) <= size)
+    {
+      my_seek (&inp_file, pos);
+      str_len = 4;
+      my_write (&str_len, sizeof (str_len), &inp_file);
+      my_trunc (&inp_file);
+      a_in_h.sym_size = 0;
+      my_seek (&inp_file, a_in_pos);
+      my_write (&a_in_h, sizeof (a_in_h), &inp_file);
+    }
+}
+
+
+/* Update emxl.exe or emx.exe in a bound executable. */
+
+static void update (void)
+{
+  long size, i;
+  byte *buf;
+
+  read_os2_header ();
+  set_exe_header ();
+  i = (inp_os2_pos & 0xfff) - (os2_hdr_pos & 0xfff);
+  if (i != 0)
+    {
+      if (i < 0)
+	i += 0x1000;
+      os2_hdr_pos += i; fill2 += i;
+    }
+  out_h2.new_lo = LOWORD (os2_hdr_pos);
+  out_h2.new_hi = HIWORD (os2_hdr_pos);
+  size = my_size (&inp_file) - inp_os2_pos - sizeof (os2_h);
+  a_out_pos = a_in_pos - inp_os2_pos + os2_hdr_pos;
+  os2_h.enum_offset += os2_hdr_pos - inp_os2_pos;
+  if (os2_h.nonresname_size != 0)
+    os2_h.nonresname_offset += os2_hdr_pos - inp_os2_pos;
+  dos_bind_h.hdr_loc_lo = LOWORD (a_out_pos);
+  dos_bind_h.hdr_loc_hi = HIWORD (a_out_pos);
+  os2_bind_h.heap_off += os2_hdr_pos - inp_os2_pos;
+  memmove (dos_bind_h.hdr, emx_bind_h.hdr, sizeof (dos_bind_h.hdr));
+  buf = xmalloc (size);
+  my_seek (&inp_file, inp_os2_pos + sizeof (os2_h));
+  my_read (buf, size, &inp_file);
+  my_change (&out_file, &inp_file);
+  write_header ();
+  my_write (&os2_h, sizeof (os2_h), &out_file);
+  my_write (buf, size, &out_file);
+  my_trunc (&out_file);
+  write_bind_header ();
+}
+
+
+/* Extract the a.out subfile of a bound executable. */
+
+static void extract (void)
+{
+  long hdr_loc, size;
+
+  hdr_loc = COMBINE (dos_bind_h.hdr_loc_lo, dos_bind_h.hdr_loc_hi);
+  size = my_size (&inp_file) - hdr_loc;
+  my_seek (&inp_file, hdr_loc);
+  copy (&inp_file, size);
+}
+
+
+void cmd (int mode)
+{
+  switch (mode)
+    {
+    case 'a':
+
+      /* Alter emxbind options. */
+
+      check_bound ();
+      alter ();
+      break;
+
+    case 'b':
+
+      /* Bind an a.out file into an .exe file. */
+
+      init_bind ();
+      init_os2_header ();
+      read_emx ();
+      read_a_out_header ();
+      if (opt_c != NULL)
+	read_core ();
+      read_res ();
+      os2_fixup ();
+      relocations ();
+      sort_fixup ();
+      set_exe_header ();
+      set_os2_header ();
+      set_dos_bind_header ();
+      write_header ();
+      write_res ();
+      copy_a_out ();
+      write_nonres ();
+      write_bind_header ();
+      if (opt_m != NULL)
+        write_map (opt_m);
+      break;
+
+    case 'e':
+
+      /* Set the OS/2 application type. */
+
+      check_bound ();
+      exe_type ();
+      break;
+
+#if LIST_OPT
+    case 'L':
+
+      /* List the headers. */
+
+      check_bound ();
+      list ();
+      break;
+#endif
+    case 'i':
+
+      /* Show the emxbind options. */
+
+      check_bound ();
+      show ();
+      break;
+
+    case 's':
+
+      /* Strip symbols. */
+
+      check_bound ();
+      strip_symbols ();
+      break;
+
+    case 'u':
+
+      /* Update emxl.exe or emx.exe in a bound executable. */
+
+      read_emx ();
+
+      /* Call check_bound() *after* read_emx() as it needs dos_bind_h! */
+
+      check_bound ();
+      update ();
+      break;
+
+    case 'x':
+
+      /* Extract the a.out file of a bound executable. */
+
+      check_bound ();
+      extract ();
+      break;
+
+    default:
+      abort ();
+    }
+}
Index: trunk/src/emx/src/emxbind/emxbind.c
===================================================================
--- trunk/src/emx/src/emxbind/emxbind.c	(revision 18)
+++ trunk/src/emx/src/emxbind/emxbind.c	(revision 18)
@@ -0,0 +1,741 @@
+/* emxbind.c -- Create an .exe executable from an a.out executable
+   Copyright (c) 1991-1997 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define EXTERN
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/moddef.h>
+#include "defs.h"
+#include "emxbind.h"
+
+
+/* The name of the module definition file (set by the -d option) or
+   NULL (if there is no module definition file).  If it's the empty
+   string, the input file name with .def extension will be used. */
+
+static char *opt_d = NULL;
+
+/* The banner line of emxbind. */
+
+static char *title = "emxbind " VERSION " -- "
+                     "Copyright (c) 1991-1997 by Eberhard Mattes";
+
+/* These strings contain the valid option letters of the DOS and OS/2
+   versions of emx, respectively.  Depending on the string in which an
+   option is found, the option is put into the DOS or OS/2 emxbind
+   header.  Option letters which don't appear in any of the strings
+   are invalid. */
+
+static char *valid_dos_options = "CLRZacdehopqst";
+static char *valid_os2_options = "EKchnqtx";
+
+/* File names of various files.  inp_fname holds the name of the input
+   executable, emx_fname the name of the emxl.exe or emx.exe file, and
+   def_fname the name of the module definition file (-d option). */
+
+static char inp_fname[FNAME_SIZE];
+static char emx_fname[FNAME_SIZE];
+static char def_fname[FNAME_SIZE];
+
+/* These global variables have the same values as the argc and argv
+   parameters, respectively, of main(). */
+
+static int gargc;
+static char **gargv;
+
+/* Automatically locate emxl.exe if this flag is true.  Otherwise, use
+   the path name given on the command line. */
+
+static int auto_emxl = FALSE;
+
+/* The file name given by the STUB statement. */
+
+static char *stub_fname = NULL;
+
+
+/* Give the user a short reminder about how to call this program. */
+
+static void usage (void)
+{
+  puts (title);
+  puts ("\nUsage:");
+  puts ("  emxbind [-b] [<options>] <emx>[.exe] <input> [<output>[.exe]] [<emx_opt>]");
+  puts ("  emxbind [-b] [<options>] [-o <output>[.exe]] <input> [<emx_opt>]");
+  puts ("  emxbind -u [<options>] <emx>[.exe] <input>[.exe]");
+  puts ("  emxbind -e [<options>] <input>[.exe]");
+  puts ("  emxbind -s [<options>] <input>[.exe]");
+  puts ("  emxbind -x [<options>] <input>[.exe] <output>");
+  puts ("  emxbind -i [<options>] <input>[.exe]");
+  puts ("  emxbind -a [<options>] <input>[.exe] [<emx_opt>]");
+#if LIST_OPT
+  puts ("  emxbind -L [<options>] <input>[.exe]");
+#endif
+  puts ("\nCommands:");
+  puts ("  -b          bind .exe (default)");
+  puts ("  -u          update emx in .exe");
+  puts ("  -e          set OS/2 .exe flags: -f, -p or -w");
+  puts ("  -s          strip symbols");
+  puts ("  -x          extract a.out");
+  puts ("  -i          show options");
+  puts ("  -a          alter options");
+#if LIST_OPT
+  puts ("  -L          list headers");
+#endif
+  puts ("\nOptions:");
+  puts ("  -f          application type: full screen (-b and -e)");
+  puts ("  -p          application type: Presentation Manager (-b and -e)");
+  puts ("  -w          application type: windowed (-b and -e)");
+  puts ("  -q          be quiet");
+  puts ("  -v          be verbose");
+  puts ("  -s          strip symbols (-b only)");
+  puts ("  -C          use old method for creating preloaded executables");
+  puts ("  -c[<core>]  add data from core dump file (-b only)");
+  puts ("  -d[<def>]   read module definition file (-b only)");
+  puts ("  -E<dll>     use <dll> instead of emx.dll (-b only)");
+  puts ("  -h<size>    set heap size for OS/2 (-b only)");
+  puts ("  -k<size>    set stack size for OS/2 (-b only)");
+  puts ("  -m<map>     write .map file (-b only)");
+  puts ("  -r<res>     add resources (-b only)");
+  exit (1);
+}
+
+
+/* A module statement is ignored: display a warning message if the
+   verbosity level is high enough. */
+
+static void def_ignored (const char *name)
+{
+  if (verbosity >= 2)
+    printf ("emxbind: %s statement not supported (warning)\n", name);
+}
+
+
+/* Callback function for reading the module definition file.  Display
+   a warning for ignored statements if the verbosity level is high
+   enough.  Save data from the other statements. */
+
+static int md_callback (struct _md *md, const _md_stmt *stmt, _md_token token,
+                        void *arg)
+{
+  struct export exp;
+
+  switch (token)
+    {
+    case _MD_BASE:
+      def_ignored ("BASE");
+      break;
+
+    case _MD_CODE:
+      def_ignored ("CODE");
+      break;
+
+    case _MD_DATA:
+      def_ignored ("DATA");
+      break;
+
+    case _MD_DESCRIPTION:
+
+      /* Save the description string for putting it into the
+         non-resident name table. */
+
+      description = xstrdup (stmt->descr.string);
+      break;
+
+    case _MD_EXETYPE:
+      def_ignored ("EXETYPE");
+      break;
+
+    case _MD_EXPORTS:
+
+      /* Add an export entry. */
+
+      exp.ord = stmt->export.ordinal;
+      exp.resident = (stmt->export.flags & _MDEP_RESIDENTNAME) ? TRUE : FALSE;
+      exp.entryname = xstrdup (stmt->export.entryname);
+      if (stmt->export.internalname[0] != 0)
+        exp.internalname = xstrdup (stmt->export.internalname);
+      else
+        exp.internalname = xstrdup (stmt->export.entryname);
+      exp.offset = 0;
+      exp.object = 0;
+      add_export (&exp);
+      break;
+
+    case _MD_HEAPSIZE:
+      def_ignored ("HEAPSIZE");
+      break;
+
+    case _MD_IMPORTS:
+      def_ignored ("IMPORTS");
+      break;
+
+    case _MD_LIBRARY:
+
+      /* Create a DLL.  Save the initialization and termination
+         policies after choosing default values for unspecified
+         values. */
+
+      dll_flag = TRUE;
+      switch (stmt->library.init)
+        {
+        case _MDIT_GLOBAL:
+          init_global = TRUE;
+          break;
+        case _MDIT_INSTANCE:
+          init_global = FALSE;
+          break;
+        default:
+          break;
+        }
+      switch (stmt->library.term)
+        {
+        case _MDIT_GLOBAL:
+          term_global = TRUE;
+          break;
+        case _MDIT_INSTANCE:
+          term_global = FALSE;
+          break;
+        default:
+          break;
+        }
+      if (stmt->library.init != _MDIT_DEFAULT
+          && stmt->library.term == _MDIT_DEFAULT)
+        term_global = init_global;
+      if (stmt->library.term != _MDIT_DEFAULT
+          && stmt->library.init == _MDIT_DEFAULT)
+        init_global = term_global;
+      break;
+
+    case _MD_NAME:
+
+      /* Create a program.  Save the module name and the application
+         type. */
+
+      if (stmt->name.name[0] != 0)
+        module_name = xstrdup (stmt->name.name);
+      app_type = stmt->name.pmtype;
+      break;
+
+    case _MD_OLD:
+      def_ignored ("OLD");
+      break;
+
+    case _MD_PROTMODE:
+      def_ignored ("PROTMODE");
+      break;
+
+    case _MD_REALMODE:
+      def_ignored ("REALMODE");
+      break;
+
+    case _MD_SEGMENTS:
+      def_ignored ("SEGMENTS");
+      break;
+
+    case _MD_STACKSIZE:
+
+      /* Check and save the stack size. */
+
+      if (stmt->stacksize.size < 20*1024
+          || stmt->stacksize.size > 512*1024*1024)
+        error ("Invalid stack size in module definition file");
+      stack_size = (stmt->stacksize.size + 0xfff) & ~0xfff;
+      break;
+
+    case _MD_STUB:
+
+      /* Save the name of the stub. */
+
+      if (!stmt->stub.none)
+        stub_fname = xstrdup (stmt->stub.name);
+      break;
+
+    case _MD_VIRTUAL:
+    case _MD_PHYSICAL:
+      error ("VIRTUAL DEVICE and PHYSICAL DEVICE statements not supported");
+
+    case _MD_parseerror:
+
+      /* Handle a syntax error. */
+
+      error ("%s (line %ld of %s)", _md_errmsg (stmt->error.code),
+             _md_get_linenumber (md), def_fname);
+      break;
+
+    default:
+      abort ();
+    }
+  return 0;
+}
+
+
+/* Read the module definition file. */
+
+static void read_def_file (void)
+{
+  struct _md *md;
+
+  md = _md_open (def_fname);
+  if (md == NULL)
+    error ("cannot open `%s'", def_fname);
+  _md_next_token (md);
+  _md_parse (md, md_callback, NULL);
+  _md_close (md);
+}
+
+
+/* Fetch a file name from the command line.  If there are no more
+   arguments or if the current argument looks like an option, don't
+   use an argument and use the default file name DEF instead.  If DEF
+   is NULL, a file name must be provided.  If EXT is non-NULL, it is
+   used as default extension.  This function will update optind if it
+   uses an argument. */
+
+static void file_name (char *dst, const char *ext, const char *def)
+{
+  if (optind < gargc && gargv[optind][0] != '-')
+    {
+      if (strlen (gargv[optind]) > FNAME_SIZE - 5)
+        error ("file name too long");
+      strcpy (dst, gargv[optind]);
+      ++optind;
+    }
+  else if (def == NULL)
+    error ("file name missing");
+  else
+    {
+      strcpy (dst, def);
+      if (ext != NULL)
+        _remext (dst);
+    }
+  if (ext != NULL)
+    _defext (dst, ext);
+}
+
+
+/* Scan the remaining command line arguments as emx options and store
+   them to options_for_dos and options_for_os2. */
+
+static void emx_options (void)
+{
+  char c;
+  int dos_flag, os2_flag;
+  int i, index_dos, index_os2;
+  char *array_dos[100];
+  char *array_os2[100];
+
+  /* Collect the options in array_dos and array_os2. */
+
+  index_dos = index_os2 = 0;
+  while (optind < gargc)
+    {
+      if (gargv[optind][0] != '-')
+        error ("emx option expected");
+      c = gargv[optind][1];
+      dos_flag = (strchr (valid_dos_options, c) != NULL);
+      os2_flag = (strchr (valid_os2_options, c) != NULL);
+      if (!dos_flag && !os2_flag)
+	{
+	  if (verbosity > 0) puts (title);
+	  error ("invalid emx option: %s", gargv[optind]);
+	}
+      if (dos_flag)
+	{
+	  for (i = 0; i < index_dos; ++i)
+	    if (memcmp (array_dos[i], gargv[optind],
+                        gargv[optind][1] == 'R' ? 3 : 2) == 0)
+	      break;
+	  if (i >= index_dos)
+	    i = index_dos++;
+	  array_dos[i] = gargv[optind];
+	}
+      if (os2_flag)
+	{
+	  for (i = 0; i < index_os2; ++i)
+	    if (memcmp (array_os2[i], gargv[optind], 2) == 0)
+	      break;
+	  if (i >= index_os2)
+	    i = index_os2++;
+	  array_os2[i] = gargv[optind];
+	}
+      ++optind;
+    }
+
+  /* Concatenate the options for DOS. */
+
+  options_for_dos[0] = 0;
+  for (i = 0; i < index_dos; ++i)
+    {
+      if (strlen (options_for_dos) + strlen (array_dos[i])
+	  > sizeof (options_for_dos) - 3)
+	{
+	  if (verbosity > 0) puts (title);
+	  error ("too many emx options for MS-DOS");
+	}
+      if (options_for_dos[0] != 0)
+	strcat (options_for_dos, " ");
+      strcat (options_for_dos, array_dos[i]);
+    }
+
+  /* Concatenate the options for OS/2. */
+
+  options_for_os2[0] = 0;
+  for (i = 0; i < index_os2; ++i)
+    {
+      if (strlen (options_for_os2) + strlen (array_os2[i])
+	  > sizeof (options_for_os2) - 3)
+	{
+	  if (verbosity > 0) puts (title);
+	  error ("too many emx options for OS/2");
+	}
+      if (options_for_os2[0] != 0)
+	strcat (options_for_os2, " ");
+      strcat (options_for_os2, array_os2[i]);
+    }
+}
+
+
+/* Parse the command line. */
+
+static void get_args (void)
+{
+  int c;
+  char *q;
+  const char *opt_o = NULL;
+
+  /* At least one argument, the command option, must be supplied. */
+
+  if (gargc <= 1)
+    usage ();
+
+  /* Don't let getopt() report errors, use `-' to introduce options. */
+
+  opterr = FALSE;
+  optswchar = "-";
+
+  /* No command option has been seen yet. */
+
+  mode = 0;
+
+  /* Examine the initial (emxbind) options, one by one. */
+
+  while ((c = getopt (gargc, gargv,
+                      "abc::Cd::eE:fh:ik:lLm:o:pqr:suvwx")) != -1)
+    {
+      switch (c)
+	{
+	case 's':
+	  if (mode == 'b')
+	    {
+	      opt_s = TRUE;
+	      break;
+	    }
+	  /*NOBREAK*/
+	case 'a':
+	case 'b':
+	case 'e':
+#if LIST_OPT
+	case 'L':
+#endif
+	case 'i':
+	case 'u':
+	case 'x':
+	  if (mode != 0)
+            error ("multiple commands specified");
+	  mode = c;
+	  break;
+	case 'c':
+	  if (opt_c != NULL)
+            error ("multiple core files");
+	  opt_c = (optarg != NULL ? optarg : "");
+	  break;
+        case 'C':
+          old_heap = TRUE;
+          break;
+	case 'd':
+	  if (opt_d != NULL)
+            error ("multiple module definition files");
+	  opt_d = (optarg != NULL ? optarg : "");
+	  break;
+        case 'E':
+          if (emx_dll != NULL)
+            error ("multiple -E options");
+          emx_dll = optarg;
+          break;
+	case 'f':
+	  opt_f = TRUE;
+	  break;
+	case 'h':
+          errno = 0;
+	  heap_size = strtol (optarg, &q, 0);
+          if (errno != 0 || heap_size < 0 || heap_size > 512 || *q != 0)
+            error ("invalid heap size");
+          heap_size *= 1024*1024;
+	  break;
+	case 'k':
+          errno = 0;
+	  stack_size = strtol (optarg, &q, 0);
+          if (errno != 0 || *q != 0 ||
+              (stack_size < 20 || stack_size > 512*1024))
+            error ("invalid stack size");
+          stack_size *= 1024;
+          stack_size = (stack_size + 0xfff) & ~0xfff;
+	  break;
+	case 'm':
+	  if (opt_m != NULL)
+            error ("multiple map files");
+	  opt_m = optarg;
+	  break;
+	case 'o':
+	  if (opt_o != NULL)
+            error ("multiple output files");
+	  opt_o = optarg;
+	  break;
+	case 'p':
+	  opt_p = TRUE;
+	  break;
+	case 'q':
+	  verbosity = 0;
+	  break;
+	case 'r':
+	  opt_r = optarg;
+	  break;
+	case 'v':
+	  verbosity = 2;
+	  break;
+	case 'w':
+	  opt_w = TRUE;
+	  break;
+	default:
+	  error ("invalid option");
+	}
+    }
+
+  /* The default command option is -b. */
+
+  if (mode == 0)
+    mode = 'b';
+
+  /* Complain if an illegal combination of options is used. */
+
+  if (opt_o != NULL && mode != 'b')
+    error ("-o option can be used only with -b command");
+  if (opt_c != NULL && mode != 'b')
+    error ("-c option can be used only with -b command");
+  if ((opt_f || opt_p || opt_w) && mode != 'b' && mode != 'e')
+    error ("-f, -p and -w options can be used only with -b and -e commands");
+  if (opt_f + opt_p + opt_w > TRUE)
+    error ("more than one of -f, -p and -w options given");
+  if (mode == 'e' && !(opt_p || opt_f || opt_w))
+    error ("-e command requires -f, -p or -w option");
+  if (opt_d != NULL && mode != 'b')
+    error ("-d option can be used only with -b command");
+
+  /* If the -c option is used without argument, "core" will be used as
+     core dump file. */
+
+  if (opt_c != NULL && *opt_c == 0)
+    opt_c = "core";
+
+  /* If the -E option is not given and the name is not given by the
+     EMXBIND_DLL environment variable, "emx.dll" will be used. */
+
+  if (emx_dll == NULL)
+    emx_dll = getenv ("EMXBIND_DLL");
+  if (emx_dll == NULL)
+    emx_dll = "emx";
+
+  /* Parse the rest of the command line, depending on the command
+     option. */
+
+  switch (mode)
+    {
+    case 'a':
+      file_name (inp_fname, "exe", NULL);
+      emx_options ();
+      break;
+
+    case 'b':
+      if (gargc - optind <= 1 || gargv[optind+1][0] == '-')
+        auto_emxl = TRUE;
+      else if (opt_o != NULL)
+        error ("Too many file names specified");
+      else
+	file_name (emx_fname, "exe", NULL);
+      file_name (inp_fname, NULL, NULL);
+      if (opt_d != NULL)
+	{
+	  if (opt_d[0] == 0)
+	    {
+	      _strncpy (def_fname, inp_fname, sizeof (def_fname) - 4);
+	      _remext (def_fname);
+	    }
+	  else
+	    _strncpy (def_fname, opt_d, sizeof (def_fname) - 4);
+	  _defext (def_fname, "def");
+          read_def_file ();
+	}
+      if (auto_emxl)
+	{
+          if (stub_fname != NULL)
+            {
+              if (_path (emx_fname, stub_fname) != 0)
+                _strncpy (emx_fname, stub_fname, sizeof (emx_fname));
+              auto_emxl = FALSE;
+            }
+          else
+            {
+              strcpy (emx_fname, "\\emx\\bin\\emxl.exe");
+              if (!my_readable (emx_fname))
+                if (_path (emx_fname, "emxl.exe") != 0)
+                  strcpy (emx_fname, "emxl.exe");
+              auto_emxl = TRUE;
+            }
+        }
+      file_name (out_fname, (dll_flag ? "dll" : "exe"),
+                 (opt_o != NULL ? opt_o : inp_fname));
+      if (_fncmp (inp_fname, out_fname) == 0)
+        error ("The input and output files have the same name");
+      emx_options ();
+      break;
+
+    case 'e':
+    case 'L':
+    case 'i':
+    case 's':
+      file_name (inp_fname, "exe", NULL);
+      break;
+
+    case 'u':
+      file_name (emx_fname, "exe", NULL);
+      file_name (inp_fname, "exe", NULL);
+      break;
+
+    case 'x':
+      file_name (inp_fname, "exe", NULL);
+      file_name (out_fname, NULL, NULL);
+      if (_fncmp (inp_fname, out_fname) == 0)
+        error ("The input and output files have the same name");
+      break;
+    }
+
+  /* Complain if there are any unprocessed arguments left. */
+
+  if (optind < gargc)
+    error ("too many arguments");
+}
+
+
+static void cleanup (void)
+{
+  my_remove (&out_file);
+}
+
+
+/* Open the files, depending on the command option.  The module
+   definition file (-d option) is not handled here. */
+
+static void open_files (void)
+{
+  atexit (cleanup);
+  switch (mode)
+    {
+    case 'a':
+    case 'e':
+    case 's':
+      my_open (&inp_file, inp_fname, open_read_write);
+      break;
+    case 'b':
+      my_open (&inp_file, inp_fname, open_read);
+      my_open (&emx_file, emx_fname, open_read);
+      if (opt_c != NULL)
+	my_open (&core_file, opt_c, open_read);
+      if (opt_r != NULL)
+	my_open (&res_file, opt_r, open_read);
+      my_open (&out_file, out_fname, create_write);
+      break;
+    case 'L':
+    case 'i':
+      my_open (&inp_file, inp_fname, open_read);
+      break;
+    case 'u':
+      my_open (&inp_file, inp_fname, open_read_write);
+      my_open (&emx_file, emx_fname, open_read);
+      break;
+    case 'x':
+      my_open (&inp_file, inp_fname, open_read);
+      my_open (&out_file, out_fname, create_write);
+      break;
+    }
+}
+
+
+/* Close all the open files. */
+
+static void close_files (void)
+{
+  my_close (&out_file);
+  my_close (&inp_file);
+  my_close (&emx_file);
+  my_close (&core_file);
+  my_close (&res_file);
+}
+
+
+/* This is the main function.  Parse the command line and perform the
+   action requested by the user. */
+
+int main (int argc, char *argv[])
+{
+  /* Setup global variables for referencing the command line arguments. */
+
+  gargc = argc; gargv = argv;
+
+  /* Parse the command line. */
+
+  get_args ();
+
+  /* Display the banner line unless suppressed. */
+
+  if (verbosity > 0) puts (title);
+
+  /* If emxl.exe was located automatically by emxbind, display the
+     path name of emxl.exe. */
+
+  if (verbosity >= 2 && auto_emxl)
+    printf ("Loader program for DOS: %s\n", emx_fname);
+
+  /* Open the files. */
+
+  open_files ();
+
+  /* Further processing depends on the command. */
+
+  cmd (mode);
+
+  /* Close the files. */
+
+  close_files ();
+  return 0;
+}
Index: trunk/src/emx/src/emxbind/emxbind.h
===================================================================
--- trunk/src/emx/src/emxbind/emxbind.h	(revision 18)
+++ trunk/src/emx/src/emxbind/emxbind.h	(revision 18)
@@ -0,0 +1,587 @@
+/* emxbind.h -- Global header file for emxbind
+   Copyright (c) 1991-1998 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#if defined (EXTERN)
+#define INIT(X) = X
+#define INIT_GROW = GROW_INIT
+#else
+#define INIT(X)
+#define INIT_GROW
+#define EXTERN extern
+#endif
+
+/* By default, don't implement the -L option (for listing the headers
+   of an EXE file). */
+
+#if !defined (LIST_OPT)
+#define LIST_OPT FALSE
+#endif
+
+/* This is the version number. */
+
+#define VERSION "0.9d"
+
+/* Put this at the end of a function declaration to tell the compiler
+   that the function never returns. */
+
+#define NORETURN2 __attribute__ ((noreturn))
+
+/* Number of characters in a file name. */
+
+#define FNAME_SIZE 512
+
+/* This is the default value for the -h option (heap size). */
+
+#define DEFAULT_HEAP_SIZE   0x02000000      /* 32 MB */
+
+/* This is the default value for the -k option (stack size). */
+
+#define DEFAULT_STACK_SIZE  (8*1024*1024)
+
+/* A_OUT_OFFSET is the offset from the start of the a.out file to the
+   text segment in the file. */
+
+#define A_OUT_OFFSET        0x0400
+
+/* This is the start address (in memory) of the text segment. */
+
+#define TEXT_BASE           0x00010000
+
+/* We use up to 4 memory objects in an LX executable file. */
+
+#define OBJECTS             4
+
+/* Source types for LX fixup records. */
+
+#define NRSTYP      0x0f        /* Mask */
+#define NRSBYT      0x00        /* 8-bit byte (8-bits) */
+#define NRSSEG      0x02        /* 16-bit selector (16-bits) */
+#define NRSPTR      0x03        /* 16:16 pointer (32-bits) */
+#define NRSOFF      0x05        /* 16-bit offset (16-bits) */
+#define NRPTR48     0x06        /* 16:32 pointer (48-bits) */
+#define NROFF32     0x07        /* 32-bit offset (32-bits) */
+#define NRSOFF32    0x08        /* 32-bit self-relative offset (32-bits) */
+
+#define NRALIAS     0x10        /* Fixup to 16:16 alias */
+#define NRCHAIN     0x20        /* List of source offsets follows */
+
+/* Reference types for LX fixup records. */
+
+#define NRRTYP      0x03        /* Mask */
+#define NRRINT      0x00        /* Internal reference */
+#define NRRORD      0x01        /* Import by ordinal */
+#define NRRNAM      0x02        /* Import by name */
+
+/* Flags for LX fixup records. */
+
+#define NRADD       0x04        /* Additive fixup */
+#define NR32BITOFF  0x10        /* 32-bit target offset */
+#define NR32BITADD  0x20        /* 32-bit additive fixup */
+#define NR16OBJMOD  0x40        /* 16-bit object/module ordinal */
+#define NR8BITORD   0x80        /* 8-bit import ordinal */
+
+
+/* How to open a file.  This type is used for my_open(). */
+
+enum open_mode
+{
+  open_read, create_write, open_read_write
+};
+
+/* A file.  OK is non-zero if the file is open.  DEL is not yet used.
+   F is the stream.  NAME is the name of the file. */
+
+struct file
+{
+  int ok, del;
+  FILE *f;
+  const char *name;
+};
+
+
+/* Internal representation of fixups. */
+
+#define FIXUP_ABS       0
+#define FIXUP_REL       1
+#define FIXUP_FAR16     2
+
+#define TARGET_ORD      0
+#define TARGET_NAME     1
+#define TARGET_ADDR     2
+
+struct fixup
+{
+  int type;                   /* fixup type, see constants above */
+  int target;                 /* fixup target, see constants above */
+  dword addr;                 /* address of patch */
+  int obj;                    /* object number (where to patch) */
+  int mod;                    /* module number or object (target) */
+  dword dst;                  /* name or ordinal or address */
+  dword add;                  /* additive fixup if non-zero */
+};
+
+/* Internal representation of an export definition. */
+
+struct export
+{
+  char *entryname;
+  char *internalname;
+  long ord;
+  int resident;
+  dword offset;
+  int object;
+};
+
+/* A growable buffer. */
+
+#define GROW_INIT {NULL, 0, 0}
+
+struct grow
+{
+  byte *data;
+  size_t size;
+  size_t len;
+};
+
+
+/* This variable holds the command code.  For instance, it is 'b' for
+   binding. */
+
+EXTERN int mode INIT (0);
+
+/* Verbosity level. */
+
+EXTERN int verbosity INIT (1);
+
+/* The name of an emx.dll replacement (set by the -E option) or NULL
+   (for emx.dll). */
+
+EXTERN char *emx_dll INIT (NULL);
+
+/* The OS/2 heap size, in bytes.  The default value is 32 MB.  The
+   heap size can be changed with the -h option. */
+
+EXTERN long heap_size INIT (DEFAULT_HEAP_SIZE);
+
+/* The OS/2 stack size, in bytes.  The default value is 8 MB.  The
+   stack size can be changed with the -k option and the STACKSIZE
+   module statement. */
+
+EXTERN long stack_size INIT (DEFAULT_STACK_SIZE);
+
+/* The name of the core dump file (set by the -c option) or NULL (if
+   there is no core dump file). */
+
+EXTERN char *opt_c INIT (NULL);
+
+/* Create a full-screen application.  This flag is set by the -f
+   option. */
+
+EXTERN int opt_f INIT (FALSE);
+
+/* Create a Presentation Manager application.  This flag is set by the
+   -p option. */
+
+EXTERN int opt_p INIT (FALSE);
+
+/* The name of the map file (set by the -m option) or NULL (if no .map
+   file should be written). */
+
+EXTERN char *opt_m INIT (NULL);
+
+/* The name of the binary resource file (set by the -r option) or NULL
+   (if there is no binary resource file). */
+
+EXTERN char *opt_r INIT (NULL);
+
+/* Strip symbols.  This flag is set by the -s option. */
+
+EXTERN int opt_s INIT (FALSE);
+
+/* Create a windowed application.  This flag is set by the -w
+   option. */
+
+EXTERN int opt_w INIT (FALSE);
+
+/* If this flag is set, create an `empty' heap object and let emx.dll
+   load the heap pages at run-time (that's what previous versions of
+   emxbind did for historical reasons; now that's used only for
+   creating EXE files for testing emx.dll or for saving memory if
+   MEMMAN=COMMIT is in effect).  Otherwise, create a heap object which
+   contains the data pages of the core dump file.  Of course, all this
+   applies only if the -c option is given.  This flag is set by the -C
+   option. */
+
+EXTERN int old_heap INIT (FALSE);
+
+/* The module name. */
+
+EXTERN char *module_name INIT (NULL);
+
+/* The application type. */
+
+EXTERN int app_type INIT (_MDT_DEFAULT);
+
+/* INITINSTANCE, INITGLOBAL, TERMINSTANCE and TERMGLOBAL. */
+
+EXTERN int init_global INIT (TRUE);
+EXTERN int term_global INIT (TRUE);
+
+/* The description string. */
+
+EXTERN char *description INIT (NULL);
+
+/* The emx options for DOS and OS/2, respectively, are stored in these
+   buffers, before being written to the emxbind headers. */
+
+EXTERN char options_for_dos[512];
+EXTERN char options_for_os2[512];
+
+/* The name of the output file. */
+
+EXTERN char out_fname[FNAME_SIZE];
+
+/* File structure for the input executable.  Note that the `ok' field
+   is initialized to FALSE to avoid closing an unopened file. */
+
+EXTERN struct file inp_file INIT ({FALSE});
+
+/* File structure for the binary resource file (-r option).  Note that
+   the `ok' field is initialized to FALSE to avoid closing an unopened
+   file. */
+
+EXTERN struct file res_file INIT ({FALSE});
+
+/* File structure for the destination executable file.  Note that the
+   `ok' field is initialized to FALSE to avoid closing an unopened
+   file. */
+
+EXTERN struct file out_file INIT ({FALSE});
+
+/* File structure for emxl.exe or emx.exe.  Note that the `ok' field
+   is initialized to FALSE to avoid closing an unopened file. */
+
+EXTERN struct file emx_file INIT ({FALSE});
+
+/* File structure for the core dump file (-c option).  Note that the
+   `ok' field is initialized to FALSE to avoid closing an unopened
+   file. */
+
+EXTERN struct file core_file INIT ({FALSE});
+
+/* The DOS EXE headers read from the input executable. */
+
+EXTERN struct exe1_header inp_h1;
+EXTERN struct exe2_header inp_h2;
+
+/* The a.out header read from the source a.out (sub)file. */
+
+EXTERN struct a_out_header a_in_h;
+
+/* The DOS and OS/2 emxbind headers, respectively. */
+
+EXTERN struct dos_bind_header dos_bind_h;
+EXTERN struct os2_bind_header os2_bind_h;
+
+/* The fixed part of the LX header. */
+
+EXTERN struct os2_header os2_h;
+
+/* This flag is set by check_bound() to indicate whether the input
+   file is a bound executable or not.  Only the -L option (for listing
+   the headers) can process executables which are not bound. */
+
+EXTERN int is_bound;
+
+/* The location of the a.out header in the source file. */
+
+EXTERN long a_in_pos;
+
+/* The size of the string table in the source a.out (sub)file. */
+
+EXTERN long a_in_str_size;
+
+/* The offsets of the data section and symbol table, respectively, of
+   the source a.out (sub)file. */
+
+EXTERN long a_in_data;
+EXTERN long a_in_sym;
+
+/* This table contains all the fixups of the module, in an internal
+   format.  fixup_size is the number of entries allocated, fixup_len
+   is the number of entries used. */
+
+EXTERN struct fixup *fixup_data INIT (NULL);
+EXTERN int fixup_size INIT (0);
+EXTERN int fixup_len INIT (0);
+
+/* procs holds the import procedure name table (table of import symbol
+   names) of the executable, in LX EXE format, while it is being
+   built. */
+
+EXTERN struct grow procs INIT_GROW;
+
+/* Create a relocatable executable if this flag is true.  This flag is
+   set when creating a DLL. */
+
+EXTERN int relocatable INIT (FALSE);
+
+/* The base address of the initialized data segment. */
+
+EXTERN dword data_base;
+
+/* Add one of these offsets to an text or data address, respectively,
+   to get the location in the input executable. */
+
+EXTERN long text_off;
+EXTERN long data_off;
+
+/* These arrays contain the text and data sections, respectively, of
+   the source a.out file. */
+
+EXTERN byte *text_image INIT (NULL);
+EXTERN byte *data_image INIT (NULL);
+
+/* These arrays contain the text and data relocation tables,
+   respectively, as read from the source a.out file. */
+
+EXTERN struct reloc *tr_image INIT (NULL);
+EXTERN struct reloc *dr_image INIT (NULL);
+
+/* This array contains the symbol table, as read from the source a.out
+   file. */
+
+EXTERN struct nlist *sym_image INIT (NULL);
+
+/* This array contains the string table, as read from the source a.out
+   file. */
+
+EXTERN byte *str_image INIT (NULL);
+
+/* This is the number of symbols of the source a.out file. */
+
+EXTERN int sym_count INIT (-1);
+
+/* This array holds the object table entries.  Usually, the entries
+   are accessed via aliases, such as obj_text. */
+
+EXTERN struct object obj_h[OBJECTS];
+
+/* These are indices for the obj_h array. */
+
+#define OBJ_TEXT 0
+#define OBJ_DATA 1
+#define OBJ_HEAP 2
+#define OBJ_STK0 3
+
+/* Define shortcuts for the elements of the obj_h array. */
+
+#define obj_text obj_h[OBJ_TEXT]
+#define obj_data obj_h[OBJ_DATA]
+#define obj_heap obj_h[OBJ_HEAP]
+#define obj_stk0 obj_h[OBJ_STK0]
+
+/* This is the number of resource objects. */
+
+EXTERN int res_obj_count;
+
+/* This is the number of resources. */
+
+EXTERN int res_count;
+
+/* This is the number of resource pages. */
+
+EXTERN int res_pages;
+
+/* This is the number of preload resource pages. */
+
+EXTERN int res_preload_pages;
+
+/* entry_tab holds the entry table (table of exports) of the
+   executable, in LX EXE format, while it is being built. */
+
+EXTERN struct grow entry_tab INIT_GROW;
+
+/* resnames holds the resident name table (table of export symbol
+   names) of the executable, in LX EXE format, while it is being
+   built. */
+
+EXTERN struct grow resnames INIT_GROW;
+
+/* nonresnames holds the non-resident name table (table of export
+   symbol names) of the executable, in LX EXE format, while it is
+   being built. */
+
+EXTERN struct grow nonresnames INIT_GROW;
+
+/* The DOS EXE headers to be written to the output executable. */
+
+EXTERN struct exe1_header out_h1;
+EXTERN struct exe2_header out_h2;
+
+/* The emxbind DOS header of emxl.exe or emx.exe. */
+
+EXTERN struct dos_bind_header emx_bind_h;
+
+/* The bytes address of the DOS patch area in the input executable. */
+
+EXTERN long patch_pos;
+
+/* The location of the LX header of the output executable. */
+
+EXTERN long os2_hdr_pos;
+
+/* The location of the LX header in the input executable. */
+
+EXTERN long inp_os2_pos;
+
+/* The location of the a.out header in the output executable. */
+
+EXTERN long a_out_pos;
+
+/* The number of zero bytes to insert between the emx.exe or emxl.exe
+   image and the LX header. */
+
+EXTERN long fill2;
+
+/* This flag is set if a LIBRARY statement is seen in the module
+   definition file. */
+
+EXTERN int dll_flag INIT (FALSE);
+
+
+/* Round up to the next multiple of 4. */
+
+#define round_4(X) ((((X)-1) & ~3) + 4)
+
+/* Round up to the next multiple of the page size (0x1000). */
+
+#define round_page(X) ((((X)-1) & ~0xfff) + 0x1000)
+
+/* Divide by the page size, rounding down. */
+
+#define div_page(X) ((X) >> 12)
+
+/* Compute the number of pages required for X bytes. */
+
+#define npages(X) div_page (round_page (X))
+
+/* Return the low 16-bit word of a 32-bit word. */
+
+#define LOWORD(X) ((X) & 0xffff)
+
+/* Return the high 16-bit word of a 32-bit word. */
+
+#define HIWORD(X) ((X) >> 16)
+
+/* Combine two 16-bit words (low word L and high word H) into a 32-bit
+   word. */
+
+#define COMBINE(L,H) ((L) | (long)((H) << 16))
+
+
+/* exec.c */
+
+void check_bound (void);
+void read_emx (void);
+void read_a_out_header (void);
+void read_core (void);
+void read_segs (void);
+void read_reloc (void);
+void read_sym (void);
+void read_os2_header (void);
+void exe_flags (void);
+void set_dos_bind_header (void);
+void set_options (void);
+void set_exe_header (void);
+void put_header_byte (byte x);
+void put_header_word (word x);
+void put_header_dword (dword x);
+void put_header_bytes (const void *src, size_t size);
+void init_os2_header (void);
+void set_os2_header (void);
+void write_header (void);
+void write_nonres (void);
+void write_bind_header (void);
+void copy_a_out (void);
+void fill (long count);
+void copy (struct file *src, long size);
+
+/* fixup.c */
+
+void build_sym_hash_table (void);
+void sort_fixup (void);
+void create_fixup (const struct fixup *fp, int neg);
+void relocations (void);
+void os2_fixup (void);
+void put_impmod (void);
+
+/* export.c */
+
+void add_export (const struct export *exp);
+void entry_name (struct grow *table, const char *name, int ord);
+void exports (void);
+const struct export *get_export (int i);
+
+/* resource.c */
+
+void read_res (void);
+void put_rsctab (void);
+void put_res_obj (int map);
+void write_res (void);
+
+/* cmd.c */
+
+void cmd (int mode);
+
+/* list.c */
+
+#if LIST_OPT
+void list (void);
+#endif
+
+/* map.c */
+
+void write_map (const char *fname);
+void map_import (const char *sym_name, const char *mod, const char *name,
+    int ord);
+
+/* utils.c */
+
+void error (const char *fmt, ...) NORETURN2;
+void my_read (void *dst, size_t size, struct file *f);
+void my_read_str (byte *dst, size_t size, struct file *f);
+void my_write (const void *src, size_t size, struct file *f);
+void my_seek (struct file *f, long pos);
+void my_skip (struct file *f, long pos);
+long my_size (struct file *f);
+long my_tell (struct file *f);
+void my_trunc (struct file *f);
+void my_change (struct file *dst, struct file *src);
+void my_open (struct file *f, const char *name, enum open_mode mode);
+void my_close (struct file *f);
+void my_remove (struct file *f);
+int my_readable (const char *name);
+void *xmalloc (size_t n);
+void *xrealloc (void *p, size_t n);
+char *xstrdup (const char *p);
+void put_grow (struct grow *dst, const void *src, size_t size);
+const char *plural_s (long n);
Index: trunk/src/emx/src/emxbind/exec.c
===================================================================
--- trunk/src/emx/src/emxbind/exec.c	(revision 18)
+++ trunk/src/emx/src/emxbind/exec.c	(revision 18)
@@ -0,0 +1,1021 @@
+/* exec.c -- Manage executable files
+   Copyright (c) 1991-1996 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/moddef.h>
+#include <sys/user.h>
+#include "defs.h"
+#include "emxbind.h"
+
+
+/* Magic number for a.out executable files as used by emx. */
+
+#define A_OUT_MAGIC         0x010b
+
+
+/* String for relaxed checking of emxl.exe or emx.exe. */
+
+static char *relaxed = "emx ";
+
+/* String for strict checking of emxl.exe or emx.exe, including the
+   version number. */
+
+static char *version = "emx " VERSION;
+
+/* The first DOS EXE header read from emxl.exe or emx.exe. */
+
+static struct exe1_header emx_h1;
+
+/* The a.out header to be written to the output executable. */
+
+static struct a_out_header a_out_h;
+
+/* The header of the core dump file. */
+
+static struct user core_h;
+
+/* The offsets of the text section, text relocation table, and data
+   relocation table, respectively, of the source a.out (sub)file. */
+
+static long a_in_text;
+static long a_in_tr;
+static long a_in_dr;
+
+/* The offset of the string table in the source a.out (sub)file. */
+
+static long a_in_str;
+
+/* The offset and size, respectively, of the string table in the
+   destination a.out (sub)file. */
+
+static long a_out_str;
+static long a_out_str_size;
+
+/* The size of the a.out file, including the symbol table and the
+   string table. */
+
+static long a_out_size;
+
+/* The location of the emxl.exe or emx.exe image in the source and
+   destination executable, respectively. */
+
+static long src_image;
+static long dst_image;
+
+/* The size of the emxl.exe or emx.exe image. */
+
+static long emx_size;
+
+/* The size of the LX EXE header of the output executable. */
+
+static long os2_hdr_size;
+
+/* The number of text, data, and heap pages, respectively, in the LX
+   executable being created. */
+
+static int text_pages;
+static int data_pages;
+static int heap_pages;
+
+/* The number of pages between the data pages and the heap pages.
+   These are required for moving the heap to the correct address of
+   the a.out subfile.  The LX header, however, does not map these
+   pages. */
+
+static int gap_pages;
+
+/* The number of zero bytes to insert between the relocation table of
+   the DOS header and the emx.exe or emxl.exe image. */
+
+static long fill1;
+
+/* The number of zero bytes to insert between the LX header (or the
+   end of the resources, if there are resources) and the a.out
+   header. */
+
+static long fill3;
+
+/* header holds the LX header while it is being built. */
+
+static struct grow header = GROW_INIT;
+
+
+/* Return the minimum of A and B. */
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+/* Compute the virtual end address of a memory object of an LX
+   file.  X is a struct object. */
+
+#define OBJ_END(x) ((x).virt_base + (x).virt_size)
+
+/* Round up to the next multiple of the segment alignment (0x10000). */
+
+#define round_segment(X) ((((X)-1) & ~0xffff) + 0x10000)
+
+
+/* Derive the main module name from the output file name, if not
+   defined by a NAME or LIBRARY statement.  Put the main module name
+   into the resident name table.  If there is a description
+   (DESCRIPTION statement), put it into the resident name table. */
+
+static void get_module_name (void)
+{
+  char *p, *q;
+
+  if (module_name == NULL)
+    {
+      module_name = xmalloc (FNAME_SIZE);
+      q = out_fname;
+      for (p = out_fname; *p != 0; ++p)
+	if (*p == ':' || *p == '/' || *p == '\\')
+	  q = p + 1;
+      p = module_name;
+      while (*q != 0 && *q != '.')
+        *p++ = *q++;
+      *p = 0;
+    }
+  entry_name (&resnames, module_name, 0);
+  if (description != NULL)
+    entry_name (&nonresnames, description, 0);
+}
+
+
+/* Check the OS/2 emxbind header (patch area).  See also crt0.s. */
+
+static int check_os2_bind_header (void)
+{
+  if (os2_bind_h.text_base != TEXT_BASE
+      || os2_bind_h.text_end != TEXT_BASE + a_in_h.text_size
+      || os2_bind_h.data_base != data_base)
+    return FALSE;
+  if (memchr (os2_bind_h.options, 0, sizeof (os2_bind_h.options)) == NULL)
+    return FALSE;
+  return TRUE;
+}
+
+
+/* Read EXE header and emxbind DOS header of emx.exe */
+
+void read_emx (void)
+{
+  my_read (&emx_h1, sizeof (emx_h1), &emx_file);
+  if (emx_h1.magic != 0x5a4d)
+    error ("invalid <emx>.exe");
+  src_image = (long)emx_h1.hdr_size << 4;
+  emx_size = ((long)emx_h1.pages << 9) - src_image;
+  if (emx_h1.last_page != 0)
+    emx_size += emx_h1.last_page - 512;
+
+  my_seek (&emx_file, src_image);
+  my_read (&emx_bind_h, sizeof (emx_bind_h), &emx_file);
+
+  if (memcmp (emx_bind_h.hdr, relaxed, strlen (relaxed)) != 0
+      || emx_bind_h.bind_flag != 0)
+    error ("invalid <emx>.exe");
+  if (memcmp (emx_bind_h.hdr, version, strlen (version)) != 0)
+    fputs ("emxbind: emx version mismatch (warning)\n", stderr);
+  dos_bind_h = emx_bind_h;
+}
+
+
+/* Read the a.out header of the input executable. */
+
+void read_a_out_header (void)
+{
+  byte buf[16];
+  int syms;
+
+  a_in_pos = my_tell (&inp_file);
+  my_read (&a_in_h, sizeof (a_in_h), &inp_file);
+  a_out_h = a_in_h;
+  if (a_in_h.magic != A_OUT_MAGIC || a_in_h.entry != TEXT_BASE)
+    error ("invalid a.out file (header)");
+  a_out_h.drsize = 0;
+  a_out_h.trsize = 0;
+  my_seek (&inp_file, A_OUT_OFFSET);
+  my_read (buf, sizeof (buf), &inp_file);
+  /*            PUSH              CALL               JMP                CALL */
+  if (buf[0] != 0x68 || buf[5] != 0xe8 || buf[10] != 0xeb || buf[12] != 0xe8)
+    error ("invalid a.out file (startup code)");
+  a_in_text = A_OUT_OFFSET;
+  a_in_data = a_in_text + round_page (a_in_h.text_size);
+  a_in_tr = a_in_data + round_page (a_in_h.data_size);
+  a_in_dr = a_in_tr + a_in_h.trsize;
+  a_in_sym = a_in_dr + a_in_h.drsize;
+  data_base = round_segment (TEXT_BASE + a_in_h.text_size);
+  my_seek (&inp_file, a_in_data);
+  my_read (&os2_bind_h, sizeof (os2_bind_h), &inp_file);
+  if (!check_os2_bind_header ())
+    error ("invalid a.out file (startup data)");
+  text_off = a_in_pos + a_in_text - TEXT_BASE;
+  data_off = a_in_pos + a_in_data - data_base;
+  syms = (a_in_h.sym_size != 0 &&
+	  a_in_sym + a_in_h.sym_size + sizeof (a_in_str_size) <=
+	  my_size (&inp_file));
+  if (syms)
+    {
+      a_in_str = a_in_sym + a_in_h.sym_size;
+      my_seek (&inp_file, a_in_str);
+      my_read (&a_in_str_size, sizeof (a_in_str_size), &inp_file);
+    }
+  else
+    {
+      a_in_str = a_in_sym;
+      a_in_str_size = 4;
+    }
+  if (syms && !opt_s)
+    {
+      a_out_str = a_in_str;
+      a_out_str_size = a_in_str_size;
+    }
+  else
+    {
+      a_out_str = a_in_sym;
+      a_out_str_size = 4;
+      a_out_h.sym_size = 0;
+    }
+  a_out_str -= a_in_h.drsize + a_in_h.trsize;
+  a_out_size = a_out_str + a_out_str_size;
+}
+
+
+/* Read the header of the core dump file. */
+
+void read_core (void)
+{
+  my_read (&core_h, sizeof (core_h), &core_file);
+  if (core_h.u_magic != UMAGIC)
+    error ("invalid core file (header)");
+  if (core_h.u_data_base != data_base
+      || core_h.u_data_end != data_base + a_in_h.data_size + a_in_h.bss_size)
+    error ("core file doesn't match a.out file");
+  a_out_h.data_size = round_page (core_h.u_data_end - core_h.u_data_base);
+  a_out_h.bss_size = 0;
+  if (core_h.u_heap_brk > core_h.u_heap_base)
+    {
+      if (core_h.u_heap_brk - core_h.u_heap_base > heap_size)
+        error ("the heap size is too small for the core file's heap");
+      a_out_h.data_size = round_page (core_h.u_heap_brk - core_h.u_data_base);
+    }
+  if (core_h.u_heapobjs_off != 0)
+    error ("%s: multiple heap objects are not supported", opt_c);
+}
+
+
+/* Read the LX header. */
+
+void read_os2_header (void)
+{
+  my_seek (&inp_file, sizeof (inp_h1));
+  my_read (&inp_h2, sizeof (inp_h2), &inp_file);
+  inp_os2_pos = COMBINE (inp_h2.new_lo, inp_h2.new_hi);
+  my_seek (&inp_file, inp_os2_pos);
+  my_read (&os2_h, sizeof (os2_h), &inp_file);
+}
+
+
+/* Read the text and data relocation tables of the input a.out
+   executable. */
+
+void read_reloc (void)
+{
+  if (tr_image == NULL)
+    {
+      my_seek (&inp_file, a_in_tr);
+      tr_image = xmalloc (a_in_h.trsize);
+      my_read (tr_image, a_in_h.trsize, &inp_file);
+    }
+  if (dr_image == NULL)
+    {
+      my_seek (&inp_file, a_in_dr);
+      dr_image = xmalloc (a_in_h.drsize);
+      my_read (dr_image, a_in_h.drsize, &inp_file);
+    }
+}
+
+
+/* Read the text and data sections from the input a.out file. */
+
+void read_segs (void)
+{
+  int d_size, t_size;
+
+  if (text_image == NULL)
+    {
+      t_size = round_page (a_in_h.text_size);
+      text_image = xmalloc (t_size);
+      my_seek (&inp_file, a_in_text);
+      my_read (text_image, t_size, &inp_file);
+    }
+  if (data_image == NULL)
+    {
+      d_size = round_page (a_in_h.data_size);
+      data_image = xmalloc (d_size);
+      my_seek (&inp_file, a_in_data);
+      my_read (data_image, d_size, &inp_file);
+    }
+}
+
+
+/* Read the symbol and string tables from the input a.out file. */
+
+void read_sym (void)
+{
+  if (sym_image == NULL)
+    {
+      sym_image = xmalloc (a_in_h.sym_size);
+      str_image = xmalloc (a_in_str_size);
+      my_seek (&inp_file, a_in_sym);
+      my_read (sym_image, a_in_h.sym_size, &inp_file);
+      my_seek (&inp_file, a_in_str);
+      my_read (str_image, a_in_str_size, &inp_file);
+      sym_count = a_in_h.sym_size / sizeof (struct nlist);
+      build_sym_hash_table ();
+    }
+}
+
+
+/* Read the DOS EXE header of the input executable.  Fail if isn't a
+   bound executable file (unless the -L command option is in effect). */
+
+void check_bound (void)
+{
+  my_read (&inp_h1, sizeof (inp_h1), &inp_file);
+  if (inp_h1.magic != 0x5a4d)
+    error ("not an .exe file");
+  patch_pos = (long)inp_h1.hdr_size << 4;
+  my_seek (&inp_file, patch_pos);
+  my_read (&dos_bind_h, sizeof (dos_bind_h), &inp_file);
+  if (memcmp (dos_bind_h.hdr, relaxed, strlen (relaxed)) != 0
+      || dos_bind_h.bind_flag == 0)
+    {
+      is_bound = FALSE;
+      if (mode != 'L')
+        error ("invalid .exe file");
+    }
+  else
+    {
+      is_bound = TRUE;
+      if (mode != 'u' && mode != 'L' &&
+	  memcmp (dos_bind_h.hdr, version, strlen (version)) != 0)
+	fputs ("emxbind: emx version mismatch in .exe file (warning)\n",
+               stderr);
+      a_in_pos = COMBINE (dos_bind_h.hdr_loc_lo, dos_bind_h.hdr_loc_hi);
+      my_seek (&inp_file, a_in_pos);
+      my_read (&a_in_h, sizeof (a_in_h), &inp_file);
+      a_out_h = a_in_h;
+      if (a_in_h.magic != A_OUT_MAGIC || a_in_h.entry != TEXT_BASE)
+        error ("invalid .exe file (a.out header)");
+      a_out_h.drsize = 0;
+      a_out_h.trsize = 0;
+      a_in_text = A_OUT_OFFSET;
+      a_in_data = a_in_text + round_page (a_in_h.text_size);
+      a_in_tr = a_in_data + round_page (a_in_h.data_size);
+      a_in_dr = a_in_tr + a_in_h.trsize;
+      a_in_sym = a_in_dr + a_in_h.drsize;
+      data_base = round_segment (TEXT_BASE + a_in_h.text_size);
+      my_seek (&inp_file, a_in_pos + a_in_data);
+      my_read (&os2_bind_h, sizeof (os2_bind_h), &inp_file);
+      if (!check_os2_bind_header ())
+        error ("invalid .exe file (startup data)");
+    }
+}
+
+
+/* Setup the DOS emxbind header, including emx options. */
+
+void set_dos_bind_header (void)
+{
+  dos_bind_h.bind_flag = 0xff;
+  dos_bind_h.hdr_loc_lo = LOWORD (a_out_pos);
+  dos_bind_h.hdr_loc_hi = HIWORD (a_out_pos);
+  set_options ();
+}
+
+
+/* Copy the emx options from options_for_dos and options_for_os2 to
+   dos_bind_h and os2_bind_h, respectively.  Fail if the strings are
+   too long. */
+
+void set_options (void)
+{
+  if (strlen (options_for_dos) > sizeof (dos_bind_h.options) - 1)
+    error ("too many emx options for MS-DOS");
+  memset (dos_bind_h.options, 0, sizeof (dos_bind_h.options));
+  strcpy ((char *)dos_bind_h.options, options_for_dos);
+  if (strlen (options_for_os2) > sizeof (os2_bind_h.options) - 1)
+    error ("too many emx options for OS/2");
+  memset (os2_bind_h.options, 0, sizeof (os2_bind_h.options));
+  strcpy ((char *)os2_bind_h.options, options_for_os2);
+}
+
+
+/* Setup the DOS EXE headers for the destination executable.  Compute
+   the location of the LX header. */
+ 
+void set_exe_header (void)
+{
+  long i;
+
+  i = (emx_h1.reloc_size << 2) + sizeof (out_h1) + sizeof (out_h2);
+#if 1
+  dst_image = (i + 0x0f) & ~0x0f;
+#else
+  dst_image = (i + 0x1ff) & ~0x1ff;
+#endif
+  fill1 = dst_image - i;
+  out_h1 = emx_h1;
+  out_h1.reloc_ptr = sizeof (out_h1) + sizeof (out_h2);
+  out_h1.hdr_size = dst_image >> 4;
+  out_h1.chksum = 0;
+  memset (out_h2.res1, 0, sizeof (out_h2.res1));
+  out_h2.new_lo = out_h2.new_hi = 0;
+  i = os2_hdr_pos = dst_image + emx_size;
+  if (os2_hdr_pos & 0x1ff)
+    os2_hdr_pos = (os2_hdr_pos + 0x1ff) & ~0x1ff;
+  fill2 = os2_hdr_pos - i;
+}
+
+
+/* Add the byte X to the LX header. */
+
+void put_header_byte (byte x)
+{
+  put_grow (&header, &x, sizeof (x));
+}
+
+
+/* Add the 16-bit word X to the LX header. */
+
+void put_header_word (word x)
+{
+  put_grow (&header, &x, sizeof (x));
+}
+
+
+/* Add the 32-bit word X to the LX header. */
+
+void put_header_dword (dword x)
+{
+  put_grow (&header, &x, sizeof (x));
+}
+
+
+/* Add SIZE bytes at SRC to the LX header. */
+
+void put_header_bytes (const void *src, size_t size)
+{
+  put_grow (&header, src, size);
+}
+
+
+/* Setup the OS/2 LX header. */
+
+void set_os2_header (void)
+{
+  dword i, first_heap_page;
+  int j, last_page, cur_page, obj;
+  struct object obj_res;
+
+  exe_flags ();
+  out_h2.new_lo = LOWORD (os2_hdr_pos);
+  out_h2.new_hi = HIWORD (os2_hdr_pos);
+  obj_text.virt_size = a_in_h.text_size;
+  obj_data.virt_size = a_in_h.data_size + a_in_h.bss_size;
+  obj_stk0.virt_size = stack_size;
+  obj_data.virt_base = round_segment (obj_text.virt_base + a_in_h.text_size);
+  obj_heap.virt_base = round_segment (OBJ_END (obj_data));
+  obj_stk0.virt_base = round_segment (OBJ_END (obj_heap));
+  os2_h.stack_esp = obj_stk0.virt_size;
+  text_pages = npages (a_in_h.text_size);
+  heap_pages = 0;  gap_pages = 0;
+  if (opt_c != NULL)
+    {
+      data_pages = npages (a_in_h.data_size + a_in_h.bss_size);
+      if (!old_heap)
+        {
+          heap_pages = npages (core_h.u_heap_brk - core_h.u_heap_base);
+
+          /* Compute the number of pages between the last data page
+             and the first heap page, for padding the a.out subfile.
+             These pages are not mapped to any object.  Round down! */
+
+	  gap_pages = (core_h.u_heap_base - core_h.u_data_end) / 0x1000;
+        }
+    }
+  else
+    data_pages = npages (a_in_h.data_size);
+
+  /* The object page table and the fixup page table don't include the
+     pages between the last data page and the first heap page
+     (gap_pages). */
+
+  os2_h.mod_pages = res_pages + text_pages + data_pages + heap_pages;
+  obj_text.map_first = 1;
+  obj_text.map_count = text_pages;
+  obj_data.map_first = obj_text.map_first + obj_text.map_count;
+  obj_data.map_count = data_pages;
+  obj_heap.map_first = obj_data.map_first + obj_data.map_count;
+  obj_heap.map_count = heap_pages;
+  obj_stk0.map_first = obj_heap.map_first + obj_heap.map_count;
+  obj_stk0.map_count = 0;
+
+  /* The object numbers for the text object (OBJ_TEXT+1) and for the
+     data object (OBJ_DATA+1) are fixed, the remaining object numbers
+     are computed here. */
+
+  os2_h.obj_count = 0;
+  os2_h.stack_obj = 0;
+  for (j = 0; j < OBJECTS; ++j)
+    if (obj_h[j].virt_size != 0)
+      {
+        os2_h.obj_count += 1;
+        if (j == OBJ_STK0 && obj_stk0.virt_size != 0)
+          os2_h.stack_obj = os2_h.obj_count;
+      }
+  os2_h.obj_count += res_obj_count;
+
+  get_module_name ();
+  exports ();
+
+  header.len = 0;
+  put_header_bytes (&os2_h, sizeof (os2_h));
+
+  os2_h.obj_offset = header.len;
+  for (j = 0; j < OBJECTS; ++j)
+    if (obj_h[j].virt_size != 0)
+      put_header_bytes (&obj_h[j], sizeof (obj_h[j]));
+  memset (&obj_res, 0, sizeof (obj_res));
+  for (j = 0; j < res_obj_count; ++j)
+    put_header_bytes (&obj_res, sizeof (obj_res));
+  os2_h.pagemap_offset = header.len;
+  for (j = 0; j < text_pages + data_pages; ++j)
+    {
+      put_header_dword (j + res_pages);
+      put_header_word (0x1000);
+      put_header_word (0);
+    }
+  first_heap_page = res_pages + text_pages + data_pages + gap_pages;
+  for (j = 0; j < heap_pages; ++j)
+    {
+      put_header_dword (j + first_heap_page);
+      put_header_word (0x1000);
+      put_header_word (0);
+    }
+  for (j = 0; j < res_pages; ++j)
+    {
+      put_header_dword (j);
+      put_header_word (0x1000);
+      put_header_word (0);
+    }
+
+  if (res_count > 0)
+    {
+      os2_h.rsctab_offset = header.len;
+      put_rsctab ();
+    }
+
+  os2_h.resname_offset = header.len;
+  put_header_bytes (resnames.data, resnames.len);
+  put_header_byte (0);
+
+  os2_h.entry_offset = header.len;
+  put_header_bytes (entry_tab.data, entry_tab.len);
+
+  /* Record the location of the fixup page table and write a dummy
+     fixup page table to be filled-in while creating the fixup record
+     table.  Note that there's one additional fixup page table entry
+     to hold the end address of the fixup section for the last
+     page. */
+
+  os2_h.fixpage_offset = header.len;
+  for (j = 0; j <= os2_h.mod_pages; ++j)
+    put_header_dword (0);           /* will be patched later */
+
+  /* Record the location of the fixup record table. */
+
+  os2_h.fixrecord_offset = header.len;
+
+  /* Write the fixup record table.  Fill-in the fixup page table
+     whenever changing to a new page.  Note that the header may move
+     while adding fixup records. */
+
+#define FIXPAGE(PAGE) (((dword *)(header.data + os2_h.fixpage_offset))[PAGE])
+
+  last_page = 0;
+  for (j = 0; j < fixup_len; ++j)
+    {
+      /* Get the object number of the fixup.  Note that fixups are
+         sorted by object, then by address. */
+
+      obj = fixup_data[j].obj;
+
+      /* Compute the page number for the fixup. */
+
+      cur_page = div_page (fixup_data[j].addr) + obj_h[obj].map_first - 1;
+
+      /* Abort if the page number is out of range. */
+
+      if (cur_page >= os2_h.mod_pages)
+        error ("internal error 1");
+      if (cur_page < last_page - 1)
+        error ("internal error 4");
+
+      /* Fill-in the fixup page table if we're on a new page. */
+
+      while (last_page <= cur_page)
+        {
+          FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
+          ++last_page;
+        }
+
+      /* Add the fixup record to the fixup record table.  This may
+         move the header in memory. */
+
+      create_fixup (&fixup_data[j], FALSE);
+
+      /* Treat fixups which cross page bounaries specially.  Two fixup
+         records are created for such a fixup, one in the first page,
+         one in the second page involved.  The offset for the second
+         page is negative.  The method used here doesn't work with
+         overlapping fixups as we move to the next page and can't go
+         back (see internal error 4 above). */
+
+      if ((fixup_data[j].addr & 0x0fff) > 0x0ffc)
+        {
+	  FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
+	  ++last_page;
+          create_fixup (&fixup_data[j], TRUE);
+        }
+    }
+
+  /* Fill-in the remaining entries of the fixup page table. */
+
+  while (last_page <= os2_h.mod_pages)
+    {
+      FIXPAGE (last_page) = header.len - os2_h.fixrecord_offset;
+      ++last_page;
+    }
+
+#undef FIXPAGE
+
+  os2_h.impmod_offset = header.len;
+  put_impmod ();
+
+  os2_h.impprocname_offset = header.len;
+  put_header_bytes (procs.data, procs.len);
+  os2_h.fixup_size = header.len - os2_h.fixpage_offset;
+  put_header_byte (0);
+  os2_hdr_size = header.len;
+
+  i = os2_hdr_pos + os2_hdr_size;
+  if (res_count > 0)
+    {
+      a_out_pos = round_page (i);
+      fill3 = a_out_pos - i;
+      a_out_pos += res_pages * 0x1000 - A_OUT_OFFSET;
+    }
+  else
+    {
+      a_out_pos = round_page (i + A_OUT_OFFSET) - A_OUT_OFFSET;
+      fill3 = a_out_pos - i;
+    }
+  os2_h.loader_size = os2_h.fixpage_offset - os2_h.obj_offset;
+  os2_h.enum_offset = a_out_pos + A_OUT_OFFSET - res_pages * 0x1000;
+  os2_h.instance_demand = data_pages + heap_pages;
+  os2_h.preload_count = res_preload_pages;
+
+  if (nonresnames.len != 0)
+    {
+      os2_h.nonresname_offset =  a_out_pos + a_out_size;
+      os2_h.nonresname_size = nonresnames.len;
+    }
+
+  header.len = 0;
+  put_header_bytes (&os2_h, sizeof (os2_h));
+  for (j = 0; j < OBJECTS; ++j)
+    if (obj_h[j].virt_size != 0)
+      put_header_bytes (&obj_h[j], sizeof (obj_h[j]));
+
+  put_res_obj (obj_stk0.map_first + obj_stk0.map_count);
+  header.len = os2_hdr_size;
+  if (opt_c != NULL)
+    {
+      os2_bind_h.data_end = os2_bind_h.data_base + a_in_h.data_size + a_in_h.bss_size;
+      os2_bind_h.bss_base = os2_bind_h.data_end;
+      os2_bind_h.bss_end  = os2_bind_h.bss_base;
+      os2_bind_h.heap_base = core_h.u_heap_base;
+      os2_bind_h.heap_end  = core_h.u_heap_end;
+      os2_bind_h.heap_brk = core_h.u_heap_brk;
+      os2_bind_h.heap_off = a_out_pos + A_OUT_OFFSET
+	+ round_page (a_in_h.text_size)
+	  + round_segment (a_in_h.data_size + a_in_h.bss_size);
+    }
+  else
+    {
+      os2_bind_h.heap_base = obj_heap.virt_base;
+      os2_bind_h.heap_end  = OBJ_END (obj_heap);
+      os2_bind_h.heap_brk  = 0;
+      os2_bind_h.heap_off  = 0;
+    }
+}
+
+
+/* Initialize the fixed part of the OS/2 LX header.  Fields which are
+   overwritten later are initialized to X. */
+
+void init_os2_header (void)
+{
+  byte b;
+
+  b = 0;
+  put_grow (&procs, &b, 1);
+#define X 0
+  memset (&os2_h, 0, sizeof (os2_h));
+  os2_h.magic = 0x584c;         /* LX */
+  os2_h.byte_order = 0;         /* Little Endian byte order */
+  os2_h.word_order = 0;         /* Little Endian word order */
+  os2_h.level = 0;              /* Format level */
+  os2_h.cpu = 2;                /* 386 */
+  os2_h.os = 1;                 /* Operating system type: OS/2 */
+  os2_h.ver = 0;                /* Module version */
+  os2_h.mod_flags = 0x200;      /* WINDOWCOMPAT */
+  if (!relocatable)
+    os2_h.mod_flags |= 0x10;  /* no internal fixups */
+  os2_h.mod_pages = X;          /* Number of pages in .exe file*/
+  os2_h.entry_obj = OBJ_TEXT+1; /* Object number for EIP */
+  os2_h.entry_eip = 0;          /* EIP */
+  os2_h.stack_obj = X;          /* Stack object */
+  os2_h.stack_esp = X;          /* ESP */
+  os2_h.pagesize = 0x1000;      /* System page size */
+  os2_h.pageshift = 12;         /* Page offset shift */
+  os2_h.fixup_size = X;         /* Fixup section size */
+  os2_h.fixup_checksum = 0;     /* Fixup section checksum */
+  os2_h.loader_size = X;        /* Loader section size */
+  os2_h.loader_checksum = 0;    /* Loader section checksum */
+  os2_h.obj_offset = X;         /* Object table offset */
+  os2_h.obj_count = X;          /* Number of objects */
+  os2_h.pagemap_offset = X;
+  os2_h.itermap_offset = 0;
+  os2_h.rsctab_offset = 0;
+  os2_h.rsctab_count = 0;
+  os2_h.resname_offset = X;
+  os2_h.entry_offset = X;
+  os2_h.moddir_offset = 0;
+  os2_h.moddir_count = 0;
+  os2_h.fixpage_offset = X;
+  os2_h.fixrecord_offset = X;
+  os2_h.impmod_offset = X;
+  os2_h.impmod_count = X;
+  os2_h.impprocname_offset = X;
+  os2_h.page_checksum_offset = 0;
+  os2_h.enum_offset = X;
+  os2_h.preload_count = X;
+  os2_h.nonresname_offset = 0;
+  os2_h.nonresname_size = 0;
+  os2_h.nonresname_checksum = 0;
+  os2_h.auto_obj = OBJ_DATA+1;
+  os2_h.debug_offset = 0;
+  os2_h.debug_size = 0;
+  os2_h.instance_preload = 0;
+  os2_h.instance_demand = X;
+  os2_h.heap_size = 0;
+  os2_h.stack_size = 0;
+  obj_text.virt_size  = 0;
+  obj_text.virt_base  = TEXT_BASE;
+  obj_text.attr_flags = 0x2005;       /* readable, executable, big */
+  obj_text.map_first  = X;
+  obj_text.map_count  = X;
+  obj_text.reserved   = 0;
+  obj_data.virt_size  = 0;
+  obj_data.virt_base  = 0;
+  obj_data.attr_flags = 0x2003;       /* readable, writable, big */
+  obj_data.map_first  = X;
+  obj_data.map_count  = X;
+  obj_data.reserved   = 0;
+  obj_heap.virt_size  = heap_size;
+  obj_heap.virt_base  = 0;
+  if (old_heap || opt_c == NULL)
+    obj_heap.attr_flags = 0x2083;     /* readable, writable, big, invalid */
+  else
+    obj_heap.attr_flags = 0x2003;     /* readable, writable, big */
+  obj_heap.map_first  = X;
+  obj_heap.map_count  = X;
+  obj_heap.reserved   = 0;
+  obj_stk0.virt_size  = 0;
+  obj_stk0.virt_base  = 0;
+  obj_stk0.attr_flags = 0x2003;       /* readable, writable, big */
+  obj_stk0.map_first  = X;
+  obj_stk0.map_count  = X;
+  obj_stk0.reserved   = 0;
+#undef X
+}
+
+
+/* Set the application type in the OS/2 LX header. */
+
+void exe_flags (void)
+{
+  if (opt_f)
+    {
+      os2_h.mod_flags &= ~0x700;
+      os2_h.mod_flags |= 0x100;
+    }
+  else if (opt_p)
+    {
+      os2_h.mod_flags &= ~0x700;
+      os2_h.mod_flags |= 0x300;
+    }
+  else if (opt_w)
+    {
+      os2_h.mod_flags &= ~0x700;
+      os2_h.mod_flags |= 0x200;
+    }
+  else
+    switch (app_type)
+      {
+      case _MDT_NOTWINDOWCOMPAT:
+        os2_h.mod_flags &= ~0x700;
+        os2_h.mod_flags |= 0x100;
+        break;
+      case _MDT_WINDOWAPI:
+        os2_h.mod_flags &= ~0x700;
+        os2_h.mod_flags |= 0x300;
+        break;
+      case _MDT_WINDOWCOMPAT:
+        os2_h.mod_flags &= ~0x700;
+        os2_h.mod_flags |= 0x200;
+        break;
+      }
+  if (dll_flag)
+    {
+      os2_h.mod_flags |= 0x8000;
+      if (!init_global)
+        os2_h.mod_flags |= 0x0004;
+      if (!term_global)
+        os2_h.mod_flags |= 0x40000000;
+    }
+}
+
+
+/* Write the DOS EXE headers, the emxl.exe or emx.exe image, and the
+   OS/2 LX header. */
+
+void write_header (void)
+{
+  my_write (&out_h1, sizeof (out_h1), &out_file);
+  my_write (&out_h2, sizeof (out_h2), &out_file);
+  my_seek (&emx_file, emx_h1.reloc_ptr);
+  copy (&emx_file, emx_h1.reloc_size * 4);
+  fill (fill1);
+  my_seek (&emx_file, src_image);
+  copy (&emx_file, emx_size);
+  fill (fill2);
+  if (mode != 'u')
+    {
+      my_write (header.data, os2_hdr_size, &out_file);
+      fill (fill3);
+    }
+}
+
+
+/* Write the emxbind headers (patch areas). */
+
+void write_bind_header (void)
+{
+  my_seek (&out_file, dst_image);
+  my_write (&dos_bind_h, sizeof (dos_bind_h), &out_file);
+  my_seek (&out_file, a_out_pos + A_OUT_OFFSET
+	   + round_page (a_out_h.text_size));
+  my_write (&os2_bind_h, sizeof (os2_bind_h), &out_file);
+}
+
+
+/* Write the non-resident name table. */
+
+void write_nonres (void)
+{
+  if (nonresnames.len != 0)
+    {
+      my_seek (&out_file, os2_h.nonresname_offset);
+      my_write (nonresnames.data, nonresnames.len, &out_file);
+    }
+}
+
+
+/* Copy the a.out subfile (a.out header, text and data sections,
+   symbol table, and string table) to the destination executable. */
+
+void copy_a_out (void)
+{
+  long n, str_len;
+
+  my_write (&a_out_h, sizeof (a_out_h), &out_file);
+  fill (A_OUT_OFFSET - sizeof (a_out_h));
+  my_seek (&inp_file, a_in_text);
+  if (text_image != NULL)
+    my_write (text_image, round_page (a_in_h.text_size), &out_file);
+  else
+    copy (&inp_file, round_page (a_in_h.text_size));
+  if (opt_c != NULL)
+    {
+      my_seek (&core_file, core_h.u_data_off);
+      n = core_h.u_data_end - core_h.u_data_base;
+      copy (&core_file, n);
+      fill (round_page (n) - n);
+      if (core_h.u_heap_brk > core_h.u_heap_base)
+	{
+	  fill (core_h.u_heap_base - round_page (core_h.u_data_end));
+	  my_seek (&core_file, core_h.u_heap_off);
+	  n = core_h.u_heap_brk - core_h.u_heap_base;
+	  copy (&core_file, n);
+	  fill (round_page (n) - n);
+	}
+    }
+  else if (data_image != NULL)
+    my_write (data_image, round_page (a_in_h.data_size), &out_file);
+  else
+    {
+      my_seek (&inp_file, a_in_data);
+      copy (&inp_file, round_page (a_in_h.data_size));
+    }
+  if (a_out_h.sym_size == 0)
+    {
+      str_len = 4;
+      my_write (&str_len, sizeof (str_len), &out_file);
+    }
+  else
+    {
+      if (sym_image != NULL)
+	my_write (sym_image, a_out_h.sym_size, &out_file);
+      else
+	{
+	  my_seek (&inp_file, a_in_sym);
+	  copy (&inp_file, a_out_h.sym_size);
+	}
+      if (str_image != NULL)
+	my_write (str_image, a_out_str_size, &out_file);
+      else
+	{
+	  my_seek (&inp_file, a_in_str);
+	  copy (&inp_file, a_out_str_size);
+	}
+    }
+}
+
+
+/* Copy SIZE bytes from the file SRC to the destination executable
+   file (out_file). */
+
+void copy (struct file *src, long size)
+{
+  char buf[BUFSIZ];
+  size_t n;
+
+  while (size > 0)
+    {
+      n = min (size, BUFSIZ);
+      my_read (buf, n, src);
+      my_write (buf, n, &out_file);
+      size -= n;
+    }
+}
+
+
+/* Write COUNT zero bytes to the destination executable file
+   (out_file). */
+
+void fill (long count)
+{
+  char buf[BUFSIZ];
+  size_t n;
+
+  memset (buf, 0, BUFSIZ);
+  while (count > 0)
+    {
+      n = min (count, BUFSIZ);
+      my_write (buf, n, &out_file);
+      count -= n;
+    }
+}
Index: trunk/src/emx/src/emxbind/export.c
===================================================================
--- trunk/src/emx/src/emxbind/export.c	(revision 18)
+++ trunk/src/emx/src/emxbind/export.c	(revision 18)
@@ -0,0 +1,282 @@
+/* export.c -- Export symbols
+   Copyright (c) 1991-1995 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "emxbind.h"
+
+
+/* Export definitions from EXPORTS statements. */
+
+static struct export *export_data = NULL;
+static int export_size = 0;
+static int export_len = 0;
+
+
+/* Add an export entry to the exports table.  Adding an export
+   (external name or ordinal) which already exists is a fatal error.
+   Exporting a symbol with different external names triggers a warning
+   message. */
+
+void add_export (const struct export *exp)
+{
+  int i;
+  
+  for (i = 0; i < export_len; ++i)
+    {
+      if (stricmp (exp->entryname, export_data[i].entryname) == 0)
+        error ("export multiply defined: %s", exp->entryname);
+      if (strcmp (exp->internalname, export_data[i].internalname) == 0)
+        printf ("emxbind: %s multiply exported (warning)\n",
+                exp->internalname);
+      if (exp->ord != 0 && export_data[i].ord == exp->ord)
+        error ("ordinal %u multiply defined", (unsigned)exp->ord);
+    }
+  if (export_len >= export_size)
+    {
+      export_size += 32;
+      export_data = xrealloc (export_data,
+                              export_size * sizeof (struct export));
+    }
+  export_data[export_len++] = *exp;
+}
+
+
+/* Add an entry name to the resident name table or non-resident name
+   table TABLE (resnames or nonresnames).  NAME is the name of the
+   entrypoint, ORD is the ordinal number. */
+
+void entry_name (struct grow *table, const char *name, int ord)
+{
+  int name_len;
+  byte blen;
+  word ord16;
+
+  name_len = strlen (name);
+  if (name_len >= 128)
+    name_len = 127;
+  else
+    blen = (byte)name_len;
+  ord16 = (word)ord;
+  put_grow (table, &blen, 1);
+  put_grow (table, name, name_len);
+  put_grow (table, &ord16, 2);
+}
+
+
+/* Find the symbol NAME in the a.out symbol table of the input
+   executable.  If UNDERSCORE is true, an underscore is prepended to
+   NAME.  If the symbol is found, find_symbol() returns a pointer to
+   the symbol table entry.  Otherwise, NULL is returned. */
+
+static struct nlist *find_symbol (const char *name, int underscore)
+{
+  int i, j, n, len, ok, t;
+  const byte *s;
+
+  i = 4; len = strlen (name);
+  while (i < a_in_str_size)
+    {
+      ok = TRUE; s = name;
+      if (underscore)
+	{
+	  if (str_image[i] == '_')
+	    ++i;
+	  else
+	    ok = FALSE;
+	}
+      if (ok && memcmp (name, str_image+i, len+1) == 0)
+	{
+	  n = a_in_h.sym_size / sizeof (struct nlist);
+	  if (underscore) --i;
+	  for (j = 0; j < n; ++j)
+	    if (sym_image[j].string == i)
+	      {
+		t = sym_image[j].type & ~N_EXT;
+		if (t == N_TEXT || t == N_DATA || t == N_BSS)
+		  return sym_image+j;
+	      }
+	}
+      i += strlen (str_image+i) + 1;
+    }
+  return NULL;
+}
+
+
+/* Compare two entries of an int array for qsort().  This function is
+   used for sorting the exported ordinal numbers. */
+
+static int int_compare (const void *x1, const void *x2)
+{
+  int a1, a2;
+
+  a1 = *(int *)x1;
+  a2 = *(int *)x2;
+  if (a1 < a2)
+    return -1;
+  else if (a1 > a2)
+    return 1;
+  else
+    return 0;
+}
+
+
+/* Compare two entries of the export table for qsort().  This function
+   is used for sorting the export table by ordinal number. */
+
+static int export_compare (const void *x1, const void *x2)
+{
+  int a1, a2;
+
+  a1 = ((struct export *)x1)->ord;
+  a2 = ((struct export *)x2)->ord;
+  if (a1 < a2)
+    return -1;
+  else if (a1 > a2)
+    return 1;
+  else
+    return 0;
+}
+
+
+/* Process the export definitions: build the entry table and update
+   the resident name table and the non-resident name table. */
+
+void exports (void)
+{
+  int i, j, n, ord, bundle;
+  struct export *exp;
+  struct nlist *nl;
+  int *used;
+  byte count;
+  byte flags;
+  byte type;
+  word object;
+  dword offset;
+
+  if (export_len != 0)
+    {
+      if (a_in_h.sym_size == 0 || a_in_str_size == 0)
+        error ("need symbol table for EXPORTS");
+      read_sym ();
+    }
+
+  /* Search symbol table */
+
+  for (i = 0; i < export_len; ++i)
+    {
+      nl = find_symbol (export_data[i].internalname, TRUE);
+      if (nl == NULL)
+        error ("symbol %s undefined (EXPORTS)", export_data[i].internalname);
+      switch (nl->type & ~N_EXT)
+	{
+	case N_TEXT:
+	  export_data[i].offset = nl->value - obj_text.virt_base;
+	  export_data[i].object = OBJ_TEXT;
+	  break;
+	case N_DATA:
+	  export_data[i].offset = nl->value - obj_data.virt_base;
+	  export_data[i].object = OBJ_DATA;
+	  break;
+	default:
+	  error ("cannot export symbol %s of type %d",
+                 export_data[i].internalname, nl->type);
+	}
+    }
+
+  /* Assign unused ordinal numbers to entries with ord == 0 */
+
+  used = xmalloc (export_len * sizeof (int));
+  n = 0;
+  for (i = 0; i < export_len; ++i)
+    {
+      ord = export_data[i].ord;
+      if (ord != 0)
+	used[n++] = ord;
+    }
+  qsort (used, n, sizeof (int), int_compare);
+  ord = 1; j = 0;
+  for (i = 0; i < export_len; ++i)
+    if (export_data[i].ord == 0)
+      {
+	while (j < n && used[j] == ord)
+	  {
+	    ++ord; ++j;
+	  }
+	export_data[i].ord = ord++;
+      }
+  qsort (export_data, export_len, sizeof (struct export), export_compare);
+  ord = 1; bundle = 0;
+  for (i = 0; i < export_len; ++i)
+    {
+      exp = &export_data[i];
+      entry_name ((exp->resident ? &resnames : &nonresnames),
+		  exp->entryname, exp->ord);
+      if (bundle == 0)
+	{
+	  while (ord < exp->ord)
+	    {
+	      if (exp->ord - ord > 255)
+		count = 255;
+	      else
+		count = exp->ord - ord;
+	      type = 0;       /* empty bundle */
+	      put_grow (&entry_tab, &count, 1);
+	      put_grow (&entry_tab, &type, 1);
+	      ord += count;
+	    }
+	  object = (word)exp->object;
+	  bundle = 1;
+	  while (i+bundle < export_len && bundle < 255 &&
+		 export_data[i+bundle].ord == ord + bundle &&
+		 export_data[i+bundle].object == object)
+	    ++bundle;
+	  count = (byte)bundle;
+	  type = 3;           /* entry point, 32-bit offset */
+	  ++object;
+	  put_grow (&entry_tab, &count, 1);
+	  put_grow (&entry_tab, &type, 1);
+	  put_grow (&entry_tab, &object, 2);
+	}
+      flags = 3;
+      offset = exp->offset;
+      put_grow (&entry_tab, &flags, 1);
+      put_grow (&entry_tab, &offset, 4);
+      ++ord; --bundle;
+    }
+  count = 0;
+  put_grow (&entry_tab, &count, 1);
+  if (nonresnames.len != 0)
+    put_grow (&nonresnames, &count, 1);
+}
+
+
+/* Retrieve an export entry for writing the .map file. */
+
+const struct export *get_export (int i)
+{
+  if (i < export_len)
+    return &export_data[i];
+  else
+    return NULL;
+}
Index: trunk/src/emx/src/emxbind/fixup.c
===================================================================
--- trunk/src/emx/src/emxbind/fixup.c	(revision 18)
+++ trunk/src/emx/src/emxbind/fixup.c	(revision 18)
@@ -0,0 +1,620 @@
+/* fixup.c -- Manage fixups
+   Copyright (c) 1991-1995 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "emxbind.h"
+
+/* This constant is used in the module_data array to indicate that no
+   address is assigned to a module. */
+
+#define NO_ADDR             0xffffffff
+
+
+/* A module referenced by an import definition. */
+
+struct module
+{
+  char *name;                   /* Name of the module */
+  dword addr;                   /* Address of the name in the executable */
+};
+
+
+/* The module number of EMX for importing emx_init and emx_syscall
+   from emx.dll. */
+
+static int mod_emx;
+
+/* This table holds the modules for method (I1).  module_size is the
+   number of entries allocated, module_len is the number of entries
+   used. */
+
+static struct module *module_data = NULL;
+static int module_size = 0;
+static int module_len = 0;
+
+/* This is the hash table for the symbol table. */
+
+#define SYM_HASH_SIZE 1009
+static int sym_hash_table[SYM_HASH_SIZE];
+
+/* This table contains the `next' pointer for every symbol table entry
+   to handle hash table overflow. */
+
+static int *sym_hash_next = NULL;
+
+
+/* Compute the hash code of a symbol.  Note that the computation ends
+   at an '=' character to be able to use hashing for finding import
+   symbols. */
+
+static unsigned sym_hash (const unsigned char *name)
+{
+  unsigned hash;
+
+  for (hash = 0; *name != 0 && *name != '='; ++name)
+    hash = (hash << 2) ^ *name;
+  return hash % SYM_HASH_SIZE;
+}
+
+
+/* Build the hash table for the symbol table. */
+
+void build_sym_hash_table (void)
+{
+  int i;
+  unsigned hash;
+  const char *name;
+
+  sym_hash_next = xmalloc (sym_count * sizeof (*sym_hash_next));
+  for (i = 0; i < SYM_HASH_SIZE; ++i)
+    sym_hash_table[i] = -1;
+  for (i = 0; i < sym_count; ++i)
+    sym_hash_next[i] = -1;
+  for (i = 0; i < sym_count; ++i)
+    {
+      name = sym_image[i].string + str_image;
+      hash = sym_hash (name);
+      sym_hash_next[i] = sym_hash_table[hash];
+      sym_hash_table[hash] = i;
+    }
+}
+
+
+/* This function compares two entries of the fixup table for qsort().
+   Entries are sorted by object number and address. */
+
+static int fixup_compare (const void *x1, const void *x2)
+{
+  int o1, o2;
+  dword a1, a2;
+
+  o1 = ((struct fixup *)x1)->obj;
+  o2 = ((struct fixup *)x2)->obj;
+  if (o1 < o2)
+    return -1;
+  else if (o1 > o2)
+    return 1;
+  else
+    {
+      a1 = ((struct fixup *)x1)->addr;
+      a2 = ((struct fixup *)x2)->addr;
+      if (a1 < a2)
+        return -1;
+      else if (a1 > a2)
+        return 1;
+      else
+        return 0;
+    }
+}
+
+
+/* Sort the fixup table by object and address. */
+
+void sort_fixup (void)
+{
+  qsort (fixup_data, fixup_len, sizeof (struct fixup), fixup_compare);
+}
+
+
+/* Expand the fixup table. */
+
+static void grow_fixup (void)
+{
+  if (fixup_len >= fixup_size)
+    {
+      fixup_size += 256;
+      fixup_data = xrealloc (fixup_data, fixup_size * sizeof (struct fixup));
+    }
+}
+
+
+/* Add a fixup record to the LX header.  FP points to a structure
+   containing information about the fixup.  If NEG is true, a negative
+   offset is generated.  This is used for creating the second part of
+   a fixup spanning a page boundary. */
+
+void create_fixup (const struct fixup *fp, int neg)
+{
+  byte flags, type;
+  word addr;
+
+  switch (fp->type)
+    {
+    case FIXUP_REL:
+      type = NRSOFF32; break;
+    case FIXUP_ABS:
+      type = NROFF32; break;
+    case FIXUP_FAR16:
+      type = NRSPTR | NRALIAS; break;
+    default:
+      error ("internal error 3");
+    }
+  addr = fp->addr & 0x0fff;
+  if (neg)
+    addr |= 0xf000;
+  switch (fp->target)
+    {
+    case TARGET_ORD:
+      flags = NRRORD;
+      if (fp->dst <= 255)
+        flags |= NR8BITORD;
+      if (fp->mod > 255)
+        flags |= NR16OBJMOD;
+      if (fp->add != 0)
+        {
+          flags |= NRADD;
+          if (fp->add > 0xffff)
+            flags |= NR32BITADD;
+        }
+      put_header_byte (type);
+      put_header_byte (flags);
+      put_header_word (addr);
+      if (flags & NR16OBJMOD)
+        put_header_word (fp->mod);
+      else
+        put_header_byte (fp->mod);
+      if (flags & NR8BITORD)
+        put_header_byte (fp->dst);
+      else
+        put_header_word (fp->dst);
+      if (flags & NRADD)
+        {
+          if (flags & NR32BITADD)
+            put_header_dword (fp->add);
+          else
+            put_header_word (fp->add);
+        }
+      break;
+    case TARGET_NAME:
+      flags = NRRNAM;
+      if (fp->mod > 255)
+        flags |= NR16OBJMOD;
+      if (fp->add != 0)
+        {
+          flags |= NRADD;
+          if (fp->add > 0xffff)
+            flags |= NR32BITADD;
+        }
+      put_header_byte (type);
+      put_header_byte (flags);
+      put_header_word (addr);
+      if (flags & NR16OBJMOD)
+        put_header_word (fp->mod);
+      else
+        put_header_byte (fp->mod);
+      put_header_word (fp->dst);
+      if (flags & NRADD)
+        {
+          if (flags & NR32BITADD)
+            put_header_dword (fp->add);
+          else
+            put_header_word (fp->add);
+        }
+      break;
+    case TARGET_ADDR:
+      flags = NRRINT;
+      if (fp->dst >= 0x10000)
+        flags |= NR32BITOFF;
+      put_header_byte (type);
+      put_header_byte (flags);
+      put_header_word (addr);
+      put_header_byte (fp->mod + 1);
+      if (flags & NR32BITOFF)
+        put_header_dword (fp->dst);
+      else
+        put_header_word (fp->dst);
+      break;
+    }
+}
+
+
+/* Find an entry in the table of imported procedures (symbols).  NAME
+   is the name of the procedure.  If the procedure is not found, it
+   will be added to the table.  find_proc() returns the offset of the
+   entry. */
+
+static int find_proc (const char *name)
+{
+  int i, len, name_len;
+  byte blen;
+
+  name_len = strlen (name);
+  if (name_len >= 128)
+    name_len = 127;
+  i = 0;
+  while (i < procs.len)
+    {
+      len = procs.data[i];
+      if (len == name_len && memcmp (procs.data + i + 1, name, len) == 0)
+	return i;
+      i += 1 + len;
+    }
+  i = procs.len;
+  blen = (byte)name_len;
+  put_grow (&procs, &blen, 1);
+  put_grow (&procs, name, name_len);
+  return i;
+}
+
+
+/* Add a reference to an imported procedure (symbol SYM_NAME) to the
+   fixup table.  The fixup is to be applied to address ADDR of object
+   OBJ, an index into the obj_h array.  If NAME is NULL, the procedure
+   is imported by ordinal number ORD.  Otherwise, the procedure is
+   imported by name NAME (ORD will be ignored).  FIXUP_TYPE is the
+   type of the fixup: FIXUP_ABS (absolute 0:32 fixup), FIXUP_REL
+   (relative 0:32 fixup) or FIXUP_FAR16 (absolute 16:16 fixup).  ADD
+   is a number to be added to the fixup target. */
+
+void ref_proc (const char *sym_name, int obj, dword addr, int mod,
+               const char *name, int ord, int fixup_type, dword add)
+{
+  grow_fixup ();
+  fixup_data[fixup_len].type = fixup_type;
+  if (name != NULL)
+    {
+      fixup_data[fixup_len].target = TARGET_NAME;
+      fixup_data[fixup_len].dst = find_proc (name);
+    }
+  else
+    {
+      fixup_data[fixup_len].target = TARGET_ORD;
+      fixup_data[fixup_len].dst = ord;
+    }
+  fixup_data[fixup_len].addr = addr;
+  fixup_data[fixup_len].obj = obj;
+  fixup_data[fixup_len].mod = mod;
+  fixup_data[fixup_len].add = add;
+  ++fixup_len;
+
+  /* Remember the import for the .map file. */
+
+  if (opt_m != NULL && sym_name != NULL)
+    map_import (sym_name, module_data[mod-1].name, name, ord);
+}
+
+
+/* Build fixups for the relocation table TABLE. */
+
+static void reloc_table (const struct reloc *table, long tab_size, int seg_obj,
+                         dword seg_base, const byte *image, dword image_size)
+{
+  int n, obj;
+  const struct reloc *r;
+  dword x, dst_base;
+
+  n = tab_size / sizeof (struct reloc);
+  for (r = table; n > 0; --n, ++r)
+    {
+      if (r->length != 2)
+        error ("relocation of size %d not implemented", 1 << r->length);
+      switch (r->symbolnum & ~N_EXT)
+	{
+	case N_TEXT:
+	  obj = OBJ_TEXT;
+	  dst_base = TEXT_BASE;
+	  break;
+	case N_DATA:
+	case N_BSS:
+	  obj = OBJ_DATA;
+	  dst_base = data_base;
+	  break;
+	default:
+	  obj = -1;
+	  dst_base = 0;
+	  break;
+	}
+      if (obj >= 0 && (!r->pcrel || obj != seg_obj))
+	{
+	  grow_fixup ();
+	  if (r->address+3 >= image_size)
+            error ("fixup outside image");
+	  x = *(dword *)(image + r->address);
+	  if (r->pcrel)
+	    x += dst_base  + r->address + 4;
+	  fixup_data[fixup_len].type = (r->pcrel ? FIXUP_REL : FIXUP_ABS);
+	  fixup_data[fixup_len].target = TARGET_ADDR;
+	  fixup_data[fixup_len].obj = seg_obj;
+	  fixup_data[fixup_len].mod = obj;
+	  fixup_data[fixup_len].addr = r->address;
+	  fixup_data[fixup_len].dst = x - dst_base;
+	  fixup_data[fixup_len].add = 0;
+	  ++fixup_len;
+	}
+    }
+}
+
+
+/* Find a module in the table of imported modules by name.  NAME is
+   the name of the module to find.  If the module is not found, it
+   will be added; ADDR is the address of the module name in the a.out
+   image for method (I1).  find_module() returns the module index.
+   The index of the first module is 1. */
+
+static int find_module (const char *name, dword addr)
+{
+  int i;
+  char *p;
+
+  for (i = 0; i < module_len; ++i)
+    if (strcmp (module_data[i].name, name) == 0)
+      return i+1;
+  if (module_len >= module_size)
+    {
+      module_size += 16;
+      module_data = xrealloc (module_data, module_size *
+			      sizeof (struct module));
+    }
+  i = module_len + 1;
+  p = xstrdup (name);
+  module_data[module_len].name = p;
+  module_data[module_len].addr = addr;
+  ++module_len;
+  return i;
+}
+
+
+/* Find a module in the table of imported modules by address.  ADDR is
+   the address of the module name in the a.out image for method (I1).
+   find_module_by_addr() returns the module index.  The index of the
+   first module is 1.  If the module is not found, -1 will be
+   returned. */
+
+static int find_module_by_addr (dword addr)
+{
+  int i;
+
+  if (addr != NO_ADDR)
+    for (i = 0; i < module_len; ++i)
+      if (module_data[i].addr == addr)
+	return i+1;
+  return -1;
+}
+
+
+/* Build fixups for relocations if the destination executable is to be
+   relocatable (DLL). */
+
+void relocations (void)
+{
+  if (relocatable && (a_in_h.trsize != 0 || a_in_h.drsize != 0))
+    {
+      read_segs ();
+      read_reloc ();
+      reloc_table (tr_image, a_in_h.trsize, OBJ_TEXT, TEXT_BASE,
+                   text_image, a_in_h.text_size);
+      reloc_table (dr_image, a_in_h.drsize, OBJ_DATA, data_base,
+                   data_image, a_in_h.data_size);
+    }
+}
+
+
+/* Process an import symbol for method (I2). */
+
+static void import_symbol (int seg_obj, const struct reloc *r,
+                           const char *name1, int len, dword x,
+                           const char *name2)
+{
+  int k, mod_idx, fixup_type;
+  long ord;
+  const char *imp, *proc;
+  char mod[256], *q, *end;
+
+  imp = name2 + len + 1;
+  q = strchr (imp, '.');
+  if (q == NULL)
+    error ("invalid import symbol %s", name2);
+  k = q - imp;
+  memcpy (mod, imp, k);
+  mod[k] = 0;
+  proc = NULL;
+  errno = 0;
+  ord = strtol (q+1, &end, 10);
+  if (end != q+1 && *end == 0 && errno == 0)
+    {
+      if (ord < 1 || ord > 65535)
+        error ("invalid import symbol %s", name2);
+      if (verbosity >= 2)
+        printf ("Importing %s.%d\n", mod, (int)ord);
+    }
+  else
+    {
+      proc = q + 1;
+      if (*proc == 0)
+        error ("invalid import symbol %s", name2);
+      if (verbosity >= 2)
+        printf ("Importing %s.%s\n", mod, proc);
+    }
+  mod_idx = find_module (mod, NO_ADDR);
+  if (memcmp ("__16_", name1, 5) == 0)
+    {
+      if (r->pcrel)
+        error ("pc-relative 16:16 fixup is invalid");
+      fixup_type = FIXUP_FAR16;
+    }
+  else
+    fixup_type = (r->pcrel ? FIXUP_REL : FIXUP_ABS);
+  ref_proc (name1, seg_obj, r->address, mod_idx, proc, (int)ord,
+            fixup_type, x);
+}
+
+
+/* Scan the relocation table TABLE and create appropriate import fixup
+   records. */
+
+void import_reloc (const struct reloc *table, long tab_size,
+                   int seg_obj, dword seg_base, const byte *image,
+                   dword image_size)
+{
+  int reloc_count, i, j, len, ok;
+  const struct reloc *r;
+  const char *name1, *name2;
+  dword x;
+
+  reloc_count = tab_size / sizeof (struct reloc);
+  for (i = 0, r = table; i < reloc_count; ++i, ++r)
+    if (r->ext && r->length == 2)
+      {
+        if (sym_image == NULL)
+          read_sym ();
+        if (r->symbolnum >= sym_count)
+          error ("invalid symbol number");
+        if (sym_image[r->symbolnum].type == (N_IMP1|N_EXT))
+          {
+            if (r->address+3 >= image_size)
+              error ("fixup outside image");
+            x = *(dword *)(image + r->address);
+            if (r->pcrel)
+              x += seg_base + r->address + 4;
+            name1 = sym_image[r->symbolnum].string + str_image;
+            len = strlen (name1);
+            ok = FALSE;
+            for (j = sym_hash_table[sym_hash (name1)]; j != -1;
+                 j = sym_hash_next[j])
+              if (sym_image[j].type == (N_IMP2|N_EXT))
+                {
+                  name2 = sym_image[j].string + str_image;
+                  if (memcmp (name1, name2, len) == 0 && name2[len] == '=')
+                    {
+                      import_symbol (seg_obj, r, name1, len, x, name2);
+                      ok = TRUE;
+                      break;
+                    }
+                }
+            if (!ok)
+              error ("import symbol %s undefined", name1);
+          }
+      }
+}
+
+
+/* Build the fixup table from the (I1) import definitions and the
+   a.out symbol table and relocation tables. */
+
+void os2_fixup (void)
+{
+  int mod_idx;
+  dword set_len, i, zero;
+  dword *set_vec;
+  size_t set_size;
+  struct
+    {
+      dword flag;
+      dword addr;
+      dword mod;
+      dword proc;
+    } fixup;
+  byte mod_name[256];
+  byte proc_name[256];
+
+  mod_emx = find_module (emx_dll, NO_ADDR);
+  ref_proc ("_emx_init", OBJ_TEXT, 6, mod_emx, NULL, 1, FIXUP_REL, 0);
+  ref_proc ("_emx_syscall", OBJ_TEXT, 13, mod_emx, NULL, 2, FIXUP_REL, 0);
+  my_seek (&inp_file, data_off + os2_bind_h.os2_dll);
+  my_read (&set_len, sizeof (set_len), &inp_file);
+  if (set_len == 0xffffffff)
+    {
+      /* I think this is a bug in GNU ld */
+      my_seek (&inp_file, data_off + os2_bind_h.os2_dll - 4);
+      my_read (&set_len, sizeof (set_len), &inp_file);
+    }
+  if (set_len > 1)
+    {
+      set_size = sizeof (dword) * set_len;
+      set_vec = xmalloc (set_size);
+      my_read (set_vec, set_size, &inp_file);
+      my_read (&zero, sizeof (zero), &inp_file);
+      if (set_vec[0] != 0xffffffff || zero != 0)
+	set_len = 0;                            /* Ignore invalid table */
+      for (i = 1; i < set_len; ++i)
+	{
+	  my_seek (&inp_file, text_off + set_vec[i]);
+	  my_read (&fixup, sizeof (fixup), &inp_file);
+	  if ((fixup.flag & ~1) != 0)
+            error ("invalid fixup");
+	  mod_idx = find_module_by_addr (text_off + fixup.mod);
+	  if (mod_idx < 0)
+	    {
+	      my_seek (&inp_file, text_off + fixup.mod);
+	      my_read_str (mod_name, sizeof (mod_name), &inp_file);
+	      mod_idx = find_module ((char *)mod_name, text_off + fixup.mod);
+	    }
+	  if (fixup.flag & 1)             /* ordinal */
+	    ref_proc (NULL, OBJ_TEXT, fixup.addr - TEXT_BASE, mod_idx,
+                      NULL, fixup.proc, FIXUP_REL, 0);
+	  else
+	    {
+	      my_seek (&inp_file, text_off + fixup.proc);
+	      my_read_str (proc_name, sizeof (proc_name), &inp_file);
+	      ref_proc (NULL, OBJ_TEXT, fixup.addr - TEXT_BASE, mod_idx,
+                        (char *)proc_name, 0, FIXUP_REL, 0);
+	    }
+	}
+      free (set_vec);
+    }
+  if (a_in_h.trsize != 0 || a_in_h.drsize != 0)
+    {
+      read_segs ();
+      read_reloc ();
+      import_reloc (tr_image, a_in_h.trsize, OBJ_TEXT, TEXT_BASE, text_image,
+                    a_in_h.text_size);
+      import_reloc (dr_image, a_in_h.drsize, OBJ_DATA, data_base, data_image,
+                    a_in_h.data_size);
+    }
+}
+
+
+/* Put the imported modules table into the LX header. */
+
+void put_impmod (void)
+{
+  int j;
+
+  os2_h.impmod_count = module_len;
+  for (j = 0; j < module_len; ++j)
+    {
+      put_header_byte ((byte)strlen (module_data[j].name));
+      put_header_bytes (module_data[j].name, strlen (module_data[j].name));
+    }
+}
Index: trunk/src/emx/src/emxbind/list.c
===================================================================
--- trunk/src/emx/src/emxbind/list.c	(revision 18)
+++ trunk/src/emx/src/emxbind/list.c	(revision 18)
@@ -0,0 +1,538 @@
+/* list.c -- List headers
+   Copyright (c) 1991-1998 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "emxbind.h"
+
+#if LIST_OPT
+
+/* A page map entry of the LX header. */
+
+#pragma pack(1)
+struct pagemap
+{
+  dword number;
+  word size;
+  word flags;
+};
+#pragma pack()
+
+
+/* Location of the new EXE header. */
+
+static long new_exe;
+
+/* Offset in fixup record table. */
+
+static long fixup_pos;
+
+/* Array of imported module names. */
+
+static char **mods;
+
+/* List of imported procedure names. */
+
+static unsigned char *proc_names;
+static long proc_names_size;
+
+/* Object page map. */
+
+static struct pagemap *pagemap;
+
+
+/* Show an offset into the LX header. */
+
+static char *offset (long x)
+{
+  static char buf[100];
+  int i;
+
+  i = sprintf (buf, "0x%.8lx", x);
+  if (x != 0)
+    sprintf (buf + i, " (at 0x%.8lx)", x + new_exe);
+  return buf;
+}    
+
+/* Show a module name. */
+
+static void print_mod (long mod)
+{
+  if (mod < 1 || mod > os2_h.impmod_count)
+    printf ("#%ld", mod);
+  else
+    printf ("%s", mods[mod-1]);
+}
+
+static void print_proc (long ord)
+{
+  if (ord < 0 || ord >= proc_names_size
+      || (int)proc_names[ord] + ord + 1 > proc_names_size)
+    printf ("#%ld", ord);
+  else
+    printf ("%.*s", (int)proc_names[ord], proc_names+ord+1);
+}
+
+
+/* Display a listing section heading. */
+
+static void section (const char *msg)
+{
+  char ul[100];
+  int i;
+
+  i = strlen (msg);
+  memset (ul, '-', i);
+  ul[i] = 0;
+  printf ("\n%s\n%s\n\n", msg, ul);
+}
+
+
+/* List object I. */
+
+static void list_obj (long i)
+{
+  struct object obj;
+  long j;
+
+  my_read (&obj, sizeof (obj), &inp_file);
+  printf ("Object %ld", i+1);
+  if (i+1 == os2_h.auto_obj) printf (" (DGROUP)");
+  if (i+1 == os2_h.entry_obj) printf (" (entry)");
+  if (i+1 == os2_h.stack_obj) printf (" (stack)");
+  printf (":\n");
+  printf ("Virtual base address: 0x%.8lx\n", obj.virt_base);
+  printf ("Virtual size:         0x%.8lx\n", obj.virt_size);
+  printf ("Attribute flags:      0x%.8lx", obj.attr_flags);
+  if (obj.attr_flags & 0x0001) printf (" read");
+  if (obj.attr_flags & 0x0002) printf (" write");
+  if (obj.attr_flags & 0x0004) printf (" exec");
+  if (obj.attr_flags & 0x0008) printf (" resource");
+  if (obj.attr_flags & 0x0010) printf (" disardable");
+  if (obj.attr_flags & 0x0020) printf (" shared");
+  if (obj.attr_flags & 0x0040) printf (" preload");
+  if (obj.attr_flags & 0x0080) printf (" invalid");
+  switch (obj.attr_flags & 0x0700)
+    {
+    case 0x0100: printf (" perm/swap"); break;
+    case 0x0200: printf (" perm/res"); break;
+    case 0x0300: printf (" res/cont"); break;
+    case 0x0400: printf (" perm/long"); break;
+    }
+  if (obj.attr_flags & 0x1000) printf (" alias");
+  if (obj.attr_flags & 0x2000) printf (" big");
+  if (obj.attr_flags & 0x4000) printf (" conforming");
+  if (obj.attr_flags & 0x8000) printf (" iopl");
+  fputchar ('\n');
+  printf ("Page map index:       %ld\n", obj.map_first);
+  printf ("Page map entries:     %ld\n", obj.map_count);
+  for (j = 0; j < obj.map_count; ++j)
+    printf ("  %4ld: %4ld 0x%.4x 0x%.4x\n",
+            obj.map_first + j,
+            (long)pagemap[obj.map_first+j-1].number,
+            (int)pagemap[obj.map_first+j-1].size,
+            (int)pagemap[obj.map_first+j-1].flags);
+  if (i+1 < os2_h.obj_count) fputchar ('\n');
+}
+
+
+/* List fixup I. */
+
+static void list_fixup (long i)
+{
+  long mod, ord;
+  byte b, type, flags, cnt;
+  word w, src;
+  dword d;
+  int j;
+
+  my_read (&type, sizeof (type), &inp_file);
+  my_read (&flags, sizeof (flags), &inp_file);
+  fixup_pos += sizeof (type) + sizeof (flags);
+  if (type & NRCHAIN)
+    {
+      my_read (&cnt, sizeof (cnt), &inp_file);
+      fixup_pos += sizeof (cnt);
+      printf ("Source=list(%3d), ", cnt);
+    }
+  else
+    {
+      my_read (&src, sizeof (src), &inp_file);
+      fixup_pos += sizeof (src);
+      printf ("Source=0x%.8lx, ", (i << 12) + src + TEXT_BASE);
+    }
+  switch (type & NRSTYP)
+    {
+    case NRSBYT:
+      printf ("8-bit byte");
+      break;
+    case NRSSEG:
+      printf ("16-bit selector");
+      break;
+    case NRSPTR:
+      printf ("16:16 pointer");
+      break;
+    case NRSOFF:
+      printf ("16-bit offset");
+      break;
+    case NRPTR48:
+      printf ("16:32 pointer");
+      break;
+    case NROFF32:
+      printf ("32-bit offset");
+      break;
+    case NRSOFF32:
+      printf ("32-bit self-relative");
+      break;
+    default:
+      printf ("unknown (0x%x)", type & NRSTYP);
+      break;
+    }
+  if (type & NRALIAS)
+    printf (", 16:16 alias");
+  printf (", ");
+  switch (flags & NRRTYP)
+    {
+    case NRRINT:
+      if (flags & NR16OBJMOD)
+        {
+          my_read (&w, sizeof (w), &inp_file);
+          fixup_pos += sizeof (w);
+        }
+      else
+        {
+          my_read (&b, sizeof (b), &inp_file);
+          fixup_pos += sizeof (b);
+          w = b;
+        }
+      printf ("internal, object %u", w);
+      if ((type & NRSTYP) != NRSSEG)
+        {
+          if (flags & NR32BITOFF)
+            {
+              my_read (&d, sizeof (d), &inp_file);
+              fixup_pos += sizeof (d);
+              printf (", offset 0x%.8lx", d);
+            }
+          else
+            {
+              my_read (&w, sizeof (w), &inp_file);
+              fixup_pos += sizeof (w);
+              printf (", offset 0x%.4x", w);
+            }
+        }
+      break;
+    case NRRORD:
+      if (flags & NR16OBJMOD)
+        {
+          my_read (&w, sizeof (w), &inp_file);
+          fixup_pos += sizeof (w);
+          mod = w;
+        }
+      else
+        {
+          my_read (&b, sizeof (b), &inp_file);
+          fixup_pos += sizeof (b);
+          mod = b;
+        }
+      if (flags & NR8BITORD)
+        {
+          my_read (&b, sizeof (b), &inp_file);
+          fixup_pos += sizeof (b);
+          ord = b;
+        }
+      else
+        {
+          my_read (&w, sizeof (w), &inp_file);
+          fixup_pos += sizeof (w);
+          ord = w;
+        }
+      print_mod (mod);
+      printf (".%ld", ord);
+      break;
+    case NRRNAM:
+      if (flags & NR16OBJMOD)
+        {
+          my_read (&w, sizeof (w), &inp_file);
+          fixup_pos += sizeof (w);
+          mod = w;
+        }
+      else
+        {
+          my_read (&b, sizeof (b), &inp_file);
+          fixup_pos += sizeof (b);
+          mod = b;
+        }
+      my_read (&w, sizeof (w), &inp_file);
+      fixup_pos += sizeof (w);
+      ord = w;
+      print_mod (mod);
+      printf (".");
+      print_proc (ord);
+      break;
+    default:
+      printf ("unknown (0x%x)", flags & NRRTYP);
+      break;
+    }
+  if (flags & NRADD)
+    {
+      if (flags & NR32BITADD)
+        {
+          my_read (&d, sizeof (d), &inp_file);
+          fixup_pos += sizeof (d);
+          printf (" +0x%.8lx", d);
+        }
+      else
+        {
+          my_read (&w, sizeof (w), &inp_file);
+          fixup_pos += sizeof (w);
+          printf (" +0x%.4x", w);
+        }
+    }
+  printf ("\n");
+  if (type & NRCHAIN)
+    {
+      for (j = 0; j < (int)cnt; ++j)
+        {
+          if (j % 6 == 0)
+            printf (" ");
+          my_read (&src, sizeof (src), &inp_file);
+          fixup_pos += sizeof (src);
+          printf (" 0x%.8lx", (i << 12) + src + TEXT_BASE);
+          if (j % 6 == 5)
+            printf ("\n");
+        }
+      if (j % 6 != 0)
+        printf ("\n");
+    }
+}
+
+
+/* List the LX header. */
+
+static void list_lx (void)
+{
+  long i, j;
+  byte buf[257];
+  dword *fixpage;
+#pragma pack(1)
+  struct
+    {
+      word type;
+      word id;
+      dword length;
+      word obj;
+      dword offset;
+    } exeres;
+#pragma pack(4)
+  byte b;
+
+  section ("LX header:");
+  my_seek (&inp_file, new_exe);
+  my_read (&os2_h, sizeof (os2_h), &inp_file);
+  printf ("Module flags:                       0x%.8lx\n", os2_h.mod_flags);
+  printf ("Module pages:                       %ld\n", os2_h.mod_pages);
+  printf ("Entry point:                        %ld#0x%.8lx\n", os2_h.entry_obj, os2_h.entry_eip);
+  printf ("Initial stack pointer:              %ld#0x%.8lx\n", os2_h.stack_obj, os2_h.stack_esp);
+  printf ("Page size in EXE file:              0x%.8lx\n", os2_h.pagesize);
+  printf ("Fixup section size:                 0x%.8lx\n", os2_h.fixup_size);
+  printf ("Fixup section checksum:             0x%.8lx\n", os2_h.fixup_checksum);
+  printf ("Loader section size:                0x%.8lx\n", os2_h.loader_size);
+  printf ("Loader section checksum:            0x%.8lx\n", os2_h.loader_checksum);
+  printf ("Object table offset:                %s\n", offset (os2_h.obj_offset));
+  printf ("Number of objects:                  %ld\n", os2_h.obj_count);
+  printf ("Object page map offset:             %s\n", offset (os2_h.pagemap_offset));
+  printf ("Iterated data map offset:           %s\n", offset (os2_h.itermap_offset));
+  printf ("Resource table offset:              %s\n", offset (os2_h.rsctab_offset));
+  printf ("Resource table entries:             %ld\n", os2_h.rsctab_count);
+  printf ("Resident name table offset:         %s\n", offset (os2_h.resname_offset));
+  printf ("Entry table offset:                 %s\n", offset (os2_h.entry_offset));
+  printf ("Module directives table offset:     %s\n", offset (os2_h.moddir_offset));
+  printf ("Module directives table entries:    %ld\n", os2_h.moddir_count);
+  printf ("Fixup page table offset:            %s\n", offset (os2_h.fixpage_offset));
+  printf ("Fixup record table offset:          %s\n", offset (os2_h.fixrecord_offset));
+  printf ("Import module name table offset:    %s\n", offset (os2_h.impmod_offset));
+  printf ("Import module name table entries:   %ld\n", os2_h.impmod_count);
+  printf ("Import procedure name table offset: %s\n", offset (os2_h.impprocname_offset));
+  printf ("Per-page checksum table offset:     %s\n", offset (os2_h.page_checksum_offset));
+  printf ("Enumerated data pages offset:       %s\n", offset (os2_h.enum_offset));
+  printf ("Preload pages:                      %ld\n", os2_h.preload_count);
+  printf ("Non-resident names table offset:    %s (0x%.8lx bytes)\n", offset (os2_h.nonresname_offset), os2_h.nonresname_size);
+  printf ("Non-resident names table checksum:  0x%.8lx\n", os2_h.nonresname_checksum);
+  printf ("Automatic data object:              %ld\n", os2_h.auto_obj);
+  printf ("Debugging information offset:       %s (0x%.8lx bytes)\n", offset (os2_h.debug_offset), os2_h.debug_size);
+  printf ("Instance pages in preload section:  %ld\n", os2_h.instance_preload);
+  printf ("Instance pages in demand section:   %ld\n", os2_h.instance_demand);
+  printf ("Heap size:                          0x%.8lx\n", os2_h.heap_size);
+
+  j = sizeof (struct pagemap) * os2_h.mod_pages;
+  pagemap = xmalloc (j);
+  my_seek (&inp_file, new_exe + os2_h.pagemap_offset);
+  my_read (pagemap, j, &inp_file);
+
+  section ("Objects:");
+  my_seek (&inp_file, new_exe + os2_h.obj_offset);
+  for (i = 0; i < os2_h.obj_count; ++i)
+    list_obj (i);
+
+  fixpage = xmalloc (sizeof (dword) * (os2_h.mod_pages + 1));
+  mods = xmalloc (sizeof (char *) * os2_h.impmod_count);
+  my_seek (&inp_file, new_exe + os2_h.fixpage_offset);
+  my_read (fixpage, sizeof (dword) * (os2_h.mod_pages + 1), &inp_file);
+  my_seek (&inp_file, new_exe + os2_h.impmod_offset);
+  for (i = 0; i < os2_h.impmod_count; ++i)
+    {
+      my_read (&b, 1, &inp_file);
+      my_read (buf, b, &inp_file);
+      buf[b] = 0;
+      mods[i] = xstrdup ((char *)buf);
+    }
+  proc_names_size = os2_h.fixup_size - (os2_h.impprocname_offset
+                                        - os2_h.fixpage_offset);
+  proc_names = xmalloc (proc_names_size);
+  my_seek (&inp_file, new_exe + os2_h.impprocname_offset);
+  my_read (proc_names, proc_names_size, &inp_file);
+  if (os2_h.rsctab_count != 0)
+    {
+      section ("Resources:");
+      my_seek (&inp_file, new_exe + os2_h.rsctab_offset);
+      for (i = 0; i < os2_h.rsctab_count; ++i)
+	{
+	  my_read (&exeres, sizeof (exeres), &inp_file);
+	  printf ("id:%5d, type:%3d, size:%5ld, object:%2d, offset: 0x%.8lx\n",
+                  exeres.id, exeres.type, exeres.length, exeres.obj,
+                  exeres.offset);
+	}
+    }
+  if (os2_h.impmod_count != 0)
+    {
+      section ("Imported modules:");
+      for (i = 0; i < os2_h.impmod_count; ++i)
+        printf ("%2ld: %s\n", i + 1, mods[i]);
+    }
+
+  if (proc_names_size != 0)
+    {
+      section ("Imported procedures:");
+      i = 0;
+      while (i < proc_names_size && proc_names[i] + i + 1 <= proc_names_size)
+        {
+          printf ("%6ld: %.*s\n", i, (int)proc_names[i], proc_names + i + 1);
+          i += proc_names[i] + 1;
+        }
+    }
+
+  section ("Fixup page table:");
+
+  for (i = 0; i < os2_h.mod_pages; ++i)
+    printf ("Page %4ld: 0x%.8lx - 0x%.8lx\n",
+            i, fixpage[i], fixpage[i+1]);
+
+  section ("Fixup record table:");
+  fixup_pos = 0;
+  for (i = 0; i < os2_h.mod_pages; ++i)
+    if (fixpage[i+1] > fixpage[i])
+      {
+	fixup_pos = fixpage[i];
+	my_seek (&inp_file, new_exe + os2_h.fixrecord_offset + fixup_pos);
+	while (fixup_pos < fixpage[i+1])
+          list_fixup (i);
+      }
+
+  section ("OS/2 emxbind header:");
+  printf ("Text base:   0x%.8lx\n", os2_bind_h.text_base);
+  printf ("Text end:    0x%.8lx\n", os2_bind_h.text_end);
+  printf ("Data base:   0x%.8lx\n", os2_bind_h.data_base);
+  printf ("Data end:    0x%.8lx\n", os2_bind_h.data_end);
+  printf ("Bss base:    0x%.8lx\n", os2_bind_h.bss_base);
+  printf ("Bss end:     0x%.8lx\n", os2_bind_h.bss_end);
+  printf ("Heap base:   0x%.8lx\n", os2_bind_h.heap_base);
+  printf ("Heap end:    0x%.8lx\n", os2_bind_h.heap_end);
+  printf ("Heap brk:    0x%.8lx\n", os2_bind_h.heap_brk);
+  printf ("Heap offset: 0x%.8lx\n", os2_bind_h.heap_off);
+  printf ("Stack base:  0x%.8lx\n", os2_bind_h.stack_base);
+  printf ("Stack end:   0x%.8lx\n", os2_bind_h.stack_end);
+  printf ("OS/2 DLL:    0x%.8lx\n", os2_bind_h.os2_dll);
+  printf ("Flags:       0x%.8lx\n", os2_bind_h.flags);
+  printf ("Options:     %s\n", (char *)os2_bind_h.options);
+}
+
+
+/* List the headers. */
+
+void list (void)
+{
+  long dos_image, dos_size;
+  byte buf[2];
+
+  section ("MS-DOS exe header:");
+  dos_image = (long)inp_h1.hdr_size << 4;
+  dos_size = ((long)inp_h1.pages << 9) - dos_image;
+  if (inp_h1.last_page != 0)
+    dos_size += inp_h1.last_page - 512;
+  printf ("Real-mode image at:       0x%.4lx (0x%.4lx bytes)\n", dos_image, dos_size);
+  printf ("Relocation table at:      0x%.4x\n", (int)inp_h1.reloc_ptr);
+  printf ("Relocation table entries: %d\n", (int)inp_h1.reloc_size);
+  printf ("Minimum allocation:       0x%.4x paragraphs\n", (int)inp_h1.min_alloc);
+  printf ("Maximum allocation:       0x%.4x paragraphs\n", (int)inp_h1.max_alloc);
+  printf ("Initial stack pointer:    0x%.4x:0x%.4x\n", (int)inp_h1.ss, (int)inp_h1.sp);
+  printf ("Entry point:              0x%.4x:0x%.4x\n", (int)inp_h1.cs, (int)inp_h1.ip);
+  printf ("Checksum:                 0x%.4x\n", (int)inp_h1.chksum);
+  if (inp_h1.reloc_ptr < sizeof (inp_h1) + sizeof (inp_h2))
+    {
+      puts ("Old executable");
+      return;
+    }
+  my_seek (&inp_file, sizeof (inp_h1));
+  my_read (&inp_h2, sizeof (inp_h2), &inp_file);
+  new_exe = COMBINE (inp_h2.new_lo, inp_h2.new_hi);
+  printf ("New EXE header at:        0x%lx\n", new_exe);
+  my_seek (&inp_file, new_exe);
+  my_read (buf, 2, &inp_file);
+  if (buf[0] >= 'A' && buf[0] <= 'Z' && buf[1] >= 'A' && buf[1] <= 'Z')
+    printf ("New executable type:      %c%c\n", buf[0], buf[1]);
+  if (is_bound)
+    {
+      section ("MS-DOS emxbind header:");
+      printf ("Version:                  %s\n", (char *)dos_bind_h.hdr);
+      printf ("Bound:                    %s\n", (dos_bind_h.bind_flag != 0 ? "Yes" : "No"));
+      printf ("a.out header offset:      0x%.8lx\n", (long)a_in_pos);
+      printf ("Options:                  %s\n",
+		    (char *)dos_bind_h.options);
+      section ("a.out header:");
+      printf ("Magic word:               0x%.4x\n", (int)a_in_h.magic);
+      printf ("Machine type:             0x%.2x\n", (int)a_in_h.machtype);
+      printf ("Flags:                    0x%.2x\n", (int)a_in_h.flags);
+      printf ("Text size:                0x%.8lx\n", a_in_h.text_size);
+      printf ("Data size:                0x%.8lx\n", a_in_h.data_size);
+      printf ("Bss size:                 0x%.8lx\n", a_in_h.bss_size);
+      printf ("Symbols size:             0x%.8lx\n", a_in_h.sym_size);
+      printf ("Entry point:              0x%.8lx\n", a_in_h.entry);
+      printf ("Text relocation size:     0x%.8lx\n", a_in_h.trsize);
+      printf ("Data relocation size:     0x%.8lx\n", a_in_h.drsize);
+    }
+  if (buf[0] == 'L' && buf[1] == 'X')
+    list_lx ();
+}
+
+#endif /* LIST_OPT */
Index: trunk/src/emx/src/emxbind/makefile
===================================================================
--- trunk/src/emx/src/emxbind/makefile	(revision 18)
+++ trunk/src/emx/src/emxbind/makefile	(revision 18)
@@ -0,0 +1,68 @@
+#
+# /emx/src/emxbind/makefile
+#
+# Copyright (c) 1991-1998 by Eberhard Mattes
+#
+# This file is part of emxbind.
+#
+# emxbind is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emxbind is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emxbind; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+.SUFFIXES: .c .o
+
+BIN=d:\emx\bin\ #
+LIB=\emx\lib\ #
+INC=..\include\ #
+L=d:/emx/lib/
+I=d:/emx/include/
+S=$(I)sys/
+
+MODDEF=$(L)moddef.a
+
+H=$(INC)defs.h emxbind.h
+
+CC=gcc
+CFLAGS=-O -Wall -I../include -DLIST_OPT=1
+LFLAGS=-s -Zsmall-conv
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+default:	all
+all:		emxbind
+emxbind:	$(BIN)emxbind.exe
+
+OBJS = emxbind.o exec.o fixup.o export.o resource.o cmd.o list.o map.o utils.o
+
+emxbind.o:  emxbind.c $(H) $(S)moddef.h
+exec.o:     exec.c $(H) $(S)moddef.h $(S)user.h
+fixup.o:    fixup.c $(H)
+export.o:   export.c $(H)
+resource.o: resource.c $(H)
+cmd.o:      cmd.c $(H)
+list.o:     list.c $(H)
+map.o:      map.c $(H)
+utils.o:    utils.c $(H)
+
+$(BIN)emxbind.exe: $(OBJS) $(MODDEF)
+	gcc $(LFLAGS) -o $(BIN)emxbindn.exe $(OBJS) -lmoddef
+	del $(BIN)emxbind.exe
+	ren $(BIN)emxbindn.exe emxbind.exe
+
+clean:
+	-del *.o
+
+# End of /emx/src/emxbind/makefile
Index: trunk/src/emx/src/emxbind/map.c
===================================================================
--- trunk/src/emx/src/emxbind/map.c	(revision 18)
+++ trunk/src/emx/src/emxbind/map.c	(revision 18)
@@ -0,0 +1,310 @@
+/* map.c -- Write .map file
+   Copyright (c) 1994-1996 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "emxbind.h"
+
+struct map_sym
+{
+  dword addr;
+  char *name;
+  char *imp_name;
+  const char *imp_mod;
+  int imp_ord;
+  byte seg;
+};
+
+static FILE *map_file;
+static int first_dgroup_seg;
+static int text_seg;
+static int data_seg;
+static int map_sym_count = 0;
+static int map_sym_alloc = 0;
+static struct map_sym *map_sym_table = NULL;
+
+
+/* Write the header of the .map file.  It includes the module name. */
+
+static void map_header (void)
+{
+  fprintf (map_file, "\n %s\n\n", module_name);
+}
+
+
+/* Write the segment list to the .map file. */
+
+static void map_segments (void)
+{
+  int seg;
+  char *fmt = " %.4X:%.8X 0%.8XH %-22s %s 32-bit\n";
+
+  fputs (" Start         Length     Name                   Class\n", map_file);
+  seg = 0;
+  text_seg = ++seg;
+  fprintf (map_file, fmt, seg, 0, a_in_h.text_size, "TEXT32", "CODE");
+  first_dgroup_seg = data_seg = ++seg;
+  fprintf (map_file, fmt, seg, 0, a_in_h.data_size, "DATA32", "DATA");
+  fprintf (map_file, fmt, seg, a_in_h.data_size, a_in_h.bss_size, "BSS32", "BSS");
+
+  if (obj_heap.virt_size != 0)
+    fprintf (map_file, fmt, ++seg, 0, obj_heap.virt_size, "HEAP", "HEAP");
+  if (obj_stk0.virt_size != 0)
+    fprintf (map_file, fmt, ++seg, 0, obj_stk0.virt_size, "STACK", "STACK");
+}
+
+
+/* Write the group list to the .map file. */
+
+static void map_groups (void)
+{
+  char *fmt = " %.4X:0   %s\n";
+
+  fputs ("\n Origin   Group\n", map_file);
+  fprintf (map_file, fmt, 0, "FLAT");
+  fprintf (map_file, fmt, first_dgroup_seg, "DGROUP");
+}
+
+
+/* Compare two `struct map_sym' by name for qsort(). */
+
+static int cmp_by_name (const void *p1, const void *p2)
+{
+  return strcmp (((const struct map_sym *)p1)->name,
+                 ((const struct map_sym *)p2)->name);
+}
+
+
+/* Compare two `struct map_sym' by value for qsort(). */
+
+static int cmp_by_value (const void *p1, const void *p2)
+{
+  const struct map_sym *s1, *s2;
+
+  s1 = (const struct map_sym *)p1;
+  s2 = (const struct map_sym *)p2;
+  if (s1->seg < s2->seg)
+    return -1;
+  else if (s1->seg > s2->seg)
+    return 1;
+  else if (s1->addr < s2->addr)
+    return -1;
+  else if (s1->addr > s2->addr)
+    return 1;
+  else
+    return strcmp (s1->name, s2->name);
+}
+
+
+/* Write a list of public symbols to the .map file. */
+
+static void map_publics (const char *title,
+                         int (*compare)(const void *p1, const void *p2))
+{
+  int i;
+  
+  fprintf (map_file, "\n  Address         Publics by %s\n\n", title);
+  qsort (map_sym_table, map_sym_count, sizeof (*map_sym_table), compare);
+  for (i = 0; i < map_sym_count; ++i)
+    if (map_sym_table[i].imp_mod == NULL)
+      fprintf (map_file, " %.4X:%.8lX       %s\n", map_sym_table[i].seg,
+               map_sym_table[i].addr, map_sym_table[i].name);
+    else if (map_sym_table[i].imp_name != NULL)
+      fprintf (map_file, " %.4X:%.8lX  Imp  %-20s (%s.%s)\n", 0, 0L,
+               map_sym_table[i].name, map_sym_table[i].imp_mod,
+               map_sym_table[i].imp_name);
+    else
+      fprintf (map_file, " %.4X:%.8lX  Imp  %-20s (%s.%d)\n", 0, 0L,
+               map_sym_table[i].name, map_sym_table[i].imp_mod,
+               map_sym_table[i].imp_ord);
+}
+
+
+static void grow_map_sym_table (void)
+{
+  if (map_sym_count >= map_sym_alloc)
+    {
+      map_sym_alloc += 256;
+      map_sym_table = xrealloc (map_sym_table,
+                                map_sym_alloc * sizeof (*map_sym_table));
+    }
+}
+
+
+/* Remember an import symbol for the .map file.  Note: MAP points to a
+   module_data[].name string. */
+
+void map_import (const char *sym_name, const char *mod, const char *name,
+                 int ord)
+{
+  int i;
+
+  if (*sym_name == '_') ++sym_name;
+
+  /* TODO: Use hashing. */
+
+  for (i = 0; i < map_sym_count; ++i)
+    if (strcmp (map_sym_table[i].name, sym_name) == 0)
+      return;
+
+  grow_map_sym_table ();
+  map_sym_table[map_sym_count].name = xstrdup (sym_name);
+  if (name == NULL)
+    {
+      map_sym_table[map_sym_count].imp_name = NULL;
+      map_sym_table[map_sym_count].imp_ord = ord;
+    }
+  else
+    {
+      map_sym_table[map_sym_count].imp_name = xstrdup (name);
+      map_sym_table[map_sym_count].imp_ord = -1;
+    }
+
+  map_sym_table[map_sym_count].imp_mod = mod;
+  map_sym_table[map_sym_count].seg = 0;
+  map_sym_table[map_sym_count].addr = 0;
+  ++map_sym_count;
+}
+
+
+/* Read and prepare the symbol table, write lists of public symbols. */
+
+static void map_symbols (void)
+{
+  int i, seg;
+  dword addr;
+  char *name;
+
+  read_sym ();
+  if (sym_count != 0)
+    {
+      for (i = 0; i < sym_count; ++i)
+        {
+          switch (sym_image[i].type)
+            {
+            case N_TEXT|N_EXT:
+              seg  = text_seg; addr = sym_image[i].value - obj_text.virt_base;
+              break;
+            case N_DATA|N_EXT:
+            case N_BSS|N_EXT:
+              seg = data_seg; addr = sym_image[i].value - obj_data.virt_base;
+              break;
+            default:
+              seg = 0; addr = 0; break;
+            }
+          if (seg != 0)
+            {
+              grow_map_sym_table ();
+              name = sym_image[i].string + str_image;
+              if (*name == '_') ++name;
+              map_sym_table[map_sym_count].seg = seg;
+              map_sym_table[map_sym_count].addr = addr;
+              map_sym_table[map_sym_count].name = name;
+              map_sym_table[map_sym_count].imp_name = NULL;
+              map_sym_table[map_sym_count].imp_mod = NULL;
+              map_sym_table[map_sym_count].imp_ord = -1;
+              ++map_sym_count;
+            }
+        }
+      if (map_sym_count != 0)
+        {
+          map_publics ("Name", cmp_by_name);
+          map_publics ("Value", cmp_by_value);
+        }
+    }
+}
+
+
+/* Write the list of exported symbols to the .map file. */
+
+static void map_exports (void)
+{
+  int i, seg;
+  const struct export *p;
+
+  if (!dll_flag || get_export (0) == NULL)
+    return;
+
+  fputs ("\n Address       Export                  Alias\n\n", map_file);
+  for (i = 0; (p = get_export (i)) != NULL; ++i)
+    {
+      switch (p->object)
+        {
+        case OBJ_TEXT:
+          seg = text_seg; break;
+        case OBJ_DATA:
+          seg = data_seg; break;
+        default:
+          seg = 0; break;
+        }
+      if (seg != 0)
+        fprintf (map_file, " %.4X:%.8lX %-23s %s\n",
+                 seg, p->offset, p->entryname, p->internalname);
+    }
+}
+
+
+/* Write the entry point to the .map file. */
+
+static void map_entrypoint (void)
+{
+  if (!dll_flag)
+    fprintf (map_file, "\nProgram entry point at 0001:00000000\n");
+}
+
+
+/* Write the .map file. */
+
+void write_map (const char *fname)
+{
+  char *tmp;
+
+  /* Add an `.map' suffix if there's no file name extension. */
+
+  tmp = alloca (strlen (fname) + 5);
+  strcpy (tmp, fname);
+  _defext (tmp, "map");
+  fname = tmp;
+
+  /* Don't use my_open() etc., those functions are for binary files. */
+
+  map_file = fopen (fname, "w");
+  if (map_file == NULL)
+    error ("cannot open `%s'", fname);
+
+  /* Write the sections of the .map file. */
+
+  map_header ();
+  map_segments ();
+  map_groups ();
+  map_exports ();
+  map_symbols ();
+  map_entrypoint ();
+
+  /* Close the .map file. */
+
+  if (fflush (map_file) != 0)
+    error ("Cannot write `%s'", fname);
+  if (fclose (map_file) != 0)
+    error ("Cannot close `%s'", fname);
+}
Index: trunk/src/emx/src/emxbind/resource.c
===================================================================
--- trunk/src/emx/src/emxbind/resource.c	(revision 18)
+++ trunk/src/emx/src/emxbind/resource.c	(revision 18)
@@ -0,0 +1,326 @@
+/* resource.c -- Manage resources
+   Copyright (c) 1991-1998 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "emxbind.h"
+
+
+/* Flags for resources. */
+
+#define RES_MOVEABLE    0x0010
+#define RES_PRELOAD     0x0040
+#define RES_DISCARDABLE 0x1000
+
+
+/* This is the layout of the header of a binary resource (in a .res
+   or .exe file). */
+
+#pragma pack(1)
+
+struct bin_res
+{
+  byte type_flag;               /* Always 0xff (type is an integer)*/
+  word type_value;              /* Type of the resource */
+  byte id_flag;                 /* Always 0xff (ID is an integer)*/
+  word id_value;                /* Resources identifier */
+  word options;                 /* Load and memory options */
+  dword length;                 /* Size of the resource in bytes */
+};
+
+#pragma pack(4)
+
+/* Internal representation of a resource. */
+
+struct resource
+{
+  word type;
+  word id;
+  dword file_pos;
+  dword length;
+  dword offset;
+};
+
+/* Internal respresentation of a resource object. */
+
+struct res_obj
+{
+  struct resource *res;
+  size_t res_size;
+  size_t res_len;
+  word res_options;
+  word obj_number;
+  dword obj_size;
+};
+
+
+/* This table describes all the resource objects.  There are
+   res_obj_count entries. */
+
+static struct res_obj *res_objs = NULL;
+
+/* This is the number of preload resource objects. */
+
+static int res_preload_obj_count;
+
+/* emxbind tries to use the last resource page for the a.out header.
+   If there isn't enough space left in the last resource page, this
+   flag is set to indicate that an extra page is to be allocated for
+   the a.out header.  That page won't be referenced by the LX
+   header. */
+
+static int extra_aout_page;
+
+
+/* This function compares two resource table entries for qsort().  It
+   is used for sorting the resource table by resource attributes
+   (preload resources come first) and object number. */
+
+static int res_obj_compare (const void *x1, const void *x2)
+{
+  word opt1, opt2;
+
+  opt1 = ((struct res_obj *)x1)->res_options;
+  opt2 = ((struct res_obj *)x2)->res_options;
+  if ((opt1 & RES_PRELOAD) != (opt2 & RES_PRELOAD))
+    {
+      if (opt1 & RES_PRELOAD)
+        return -1;
+      else
+        return 1;
+    }
+  return ((int)((struct res_obj *)x1)->obj_number -
+	  (int)((struct res_obj *)x2)->obj_number);
+}
+
+
+/* This function compares two resource table entries for qsort().  It
+   is used for sorting the resource table by type and ID. */
+
+static int res_compare (const void *x1, const void *x2)
+{
+  int a1, a2;
+
+  a1 = ((struct resource *)x1)->type;
+  a2 = ((struct resource *)x2)->type;
+  if (a1 != a2)
+    return a1 - a2;
+  a1 = ((struct resource *)x1)->id;
+  a2 = ((struct resource *)x2)->id;
+  return a1 - a2;
+}
+
+
+/* Read a binary resource file. */
+
+void read_res (void)
+{
+  struct bin_res br;
+  struct res_obj *rop;
+  struct resource *rp;
+  size_t i, j;
+  int obj_no;
+  long file_size;
+
+  res_count = 0; res_obj_count = 0; res_preload_pages = 0; res_pages = 0;
+  res_preload_obj_count = 0; extra_aout_page = FALSE;
+  if (opt_r == NULL)
+    return;
+  file_size = my_size (&res_file);
+  my_seek (&res_file, 0);
+  while (my_tell (&res_file) != file_size)
+    {
+      my_read (&br, sizeof (br), &res_file);
+      if (br.type_flag != 0xff || br.id_flag != 0xff)
+        error ("invalid binary resource file");
+
+      /* Resource types 22 and 23 are ignored for unknown reasons. */
+
+      if (br.type_value != 22 && br.type_value != 23)
+	{
+	  ++res_count;
+	  for (i = 0; i < res_obj_count; ++i)
+	    if (res_objs[i].res_options == br.options)
+	      break;
+	  if (i < res_obj_count)
+	    rop = &res_objs[i];
+	  else
+	    {
+	      ++res_obj_count;
+	      res_objs = xrealloc (res_objs, res_obj_count
+				   * sizeof (struct res_obj));
+	      rop = &res_objs[res_obj_count-1];
+	      rop->res = NULL;
+	      rop->res_size = 0;
+	      rop->res_len = 0;
+	      rop->res_options = br.options;
+	      rop->obj_size = 0;
+	      rop->obj_number = res_obj_count;    /* for sorting */
+	      if (br.options & RES_PRELOAD)
+		++res_preload_obj_count;
+	    }
+	  if (rop->res_len >= rop->res_size)
+	    {
+	      rop->res_size += 16;
+	      rop->res = xrealloc (rop->res, rop->res_size * sizeof (*rop->res));
+	    }
+	  rp = &rop->res[rop->res_len++];
+	  rp->type = br.type_value;
+	  rp->id = br.id_value;
+	  rp->file_pos = my_tell (&res_file);
+	  rp->length = br.length;
+	  rp->offset = 0;
+	}
+      my_skip (&res_file, br.length);
+    }
+  if (verbosity > 0)
+    printf ("%d resource%s in %d object%s\n",
+            res_count, plural_s (res_count),
+            res_obj_count, plural_s (res_obj_count));
+  qsort (res_objs, res_obj_count, sizeof (struct res_obj), res_obj_compare);
+  obj_no = OBJECTS + 1;
+  for (i = 0, rop = res_objs; i < res_obj_count; ++i, ++rop)
+    {
+      qsort (rop->res, rop->res_len, sizeof (struct resource), res_compare);
+      rop->obj_number = obj_no++;
+      for (j = 0; j < rop->res_len; ++j)
+	{
+	  rop->obj_size = round_4 (rop->obj_size);
+	  rop->res[j].offset = rop->obj_size;
+	  rop->obj_size += rop->res[j].length;
+	}
+      j = npages (rop->obj_size);
+      if (rop->res_options & RES_PRELOAD)
+	res_preload_pages += j;
+      res_pages += j;
+    }
+  extra_aout_page = (res_pages != 0
+		     && ((res_objs[res_obj_count-1].obj_size & 0xfff)
+                         > 0x1000 - A_OUT_OFFSET));
+  if (extra_aout_page)
+    ++res_pages;            /* This one is for the a.out header */
+}
+
+
+/* Write resources to the destination executable file. */
+
+void write_res (void)
+{
+  struct res_obj *rop;
+  int i, j;
+  long pos;
+  enum {ro_unknown, ro_preload, ro_demand} ro_last, ro_this;
+
+  if (res_count == 0)
+    return;
+  ro_last = ro_unknown;
+  if (verbosity >= 2)
+    puts ("Writing resources");
+  for (i = 0, rop = res_objs; i < res_obj_count; ++i, ++rop)
+    {
+      if (verbosity >= 2)
+	{
+	  if (rop->res_options & RES_PRELOAD)
+	    ro_this = ro_preload;
+	  else
+	    ro_this = ro_demand;
+	  if (ro_this != ro_last)
+	    {
+	      ro_last = ro_this;
+	      if (ro_this == ro_preload)
+		printf ("Writing %d PRELOAD resource object%s\n",
+                        res_preload_obj_count,
+                        plural_s (res_preload_obj_count));
+	      else
+		printf ("Writing %d DEMAND resource object%s\n",
+                        res_obj_count - res_preload_obj_count,
+                        plural_s (res_obj_count - res_preload_obj_count));
+	    }
+	  printf ("  Writing:  %ld bytes in %lu page%s\n",
+                  round_4 (rop->obj_size),
+                  npages (rop->obj_size), plural_s (npages (rop->obj_size)));
+	}
+      pos = 0;
+      for (j = 0; j < rop->res_len; ++j)
+	{
+	  if (verbosity >= 2)
+	    printf ("    %d.%d (%lu byte%s)\n",
+                    rop->res[j].id, rop->res[j].type,
+                    rop->res[j].length, plural_s (rop->res[j].length));
+	  fill (rop->res[j].offset - pos);
+	  my_seek (&res_file, rop->res[j].file_pos);
+	  copy (&res_file, rop->res[j].length);
+	  pos = rop->res[j].offset + rop->res[j].length;
+	}
+      if (pos != rop->obj_size)
+        error ("internal error 2");
+      if (i < res_obj_count - 1)
+	fill (round_page (pos) - pos);
+      else if (extra_aout_page)
+	fill (round_page (pos) - pos + 0x1000 - A_OUT_OFFSET);
+      else
+	fill (round_page (pos) - pos - A_OUT_OFFSET);
+    }
+}
+
+
+void put_rsctab (void)
+{
+  int j, k;
+  const struct res_obj *rop;
+
+  os2_h.rsctab_count = res_count;
+  for (j = 0, rop = res_objs; j < res_obj_count; ++j, ++rop)
+    for (k = 0; k < rop->res_len; ++k)
+      {
+        put_header_word (rop->res[k].type);
+        put_header_word (rop->res[k].id);
+        put_header_dword (rop->res[k].length);
+        put_header_word (rop->obj_number);
+        put_header_dword (rop->res[k].offset);
+      }
+}
+
+
+void put_res_obj (int map)
+{
+  int j;
+  const struct res_obj *rop;
+  struct object obj_res;
+
+  for (j = 0, rop = res_objs; j < res_obj_count; ++j, ++rop)
+    {
+      obj_res.virt_size = rop->obj_size;
+      obj_res.virt_base = 0;
+      obj_res.attr_flags = 0x2029;
+      if (rop->res_options & RES_PRELOAD)
+	obj_res.attr_flags |= 0x0040;
+      if (rop->res_options & RES_DISCARDABLE)
+	obj_res.attr_flags |= 0x0010;
+      obj_res.map_first = map;
+      obj_res.map_count = npages (rop->obj_size);
+      obj_res.reserved = 0;
+      put_header_bytes (&obj_res, sizeof (obj_res));
+      map += obj_res.map_count;
+    }
+}
Index: trunk/src/emx/src/emxbind/utils.c
===================================================================
--- trunk/src/emx/src/emxbind/utils.c	(revision 18)
+++ trunk/src/emx/src/emxbind/utils.c	(revision 18)
@@ -0,0 +1,307 @@
+/* utils.c -- Utility functions
+   Copyright (c) 1991-1996 Eberhard Mattes
+
+This file is part of emxbind.
+
+emxbind is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxbind is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxbind; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <io.h>
+#include "defs.h"
+#include "emxbind.h"
+
+
+static void out_of_mem (void) NORETURN2;
+
+
+/* Print an error message and abort.  This function is called like
+   printf() but never returns.  The message will be prefixed with
+   "emxbind: " and a newline will be added at the end. */
+
+void error (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emxbind: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+  exit (2);
+}
+
+/* Print an out of memory message and abort. */
+
+static void out_of_mem (void)
+{
+  error ("out of memory");
+}
+
+
+/* Read SIZE bytes from the file F to the buffer DST.  If there aren't
+   SIZE bytes at the current location of the read/write pointer, an
+   error message will be displayed and the program will be
+   terminated. */
+
+void my_read (void *dst, size_t size, struct file *f)
+{
+  if (fread (dst, 1, size, f->f) != size)
+    error ("cannot read `%s'", f->name);
+}
+
+
+/* Write SIZE bytes from SRC to the file F. */
+
+void my_write (const void *src, size_t size, struct file *f)
+{
+  if (fwrite (src, 1, size, f->f) != size)
+    error ("cannot write `%s'", f->name);
+}
+
+
+/* Open the file named NAME and let F reference that file.  OMODE is
+   the open mode.  The file is always opened in binary mode. */
+
+void my_open (struct file *f, const char *name, enum open_mode omode)
+{
+  const char *ms;
+
+  f->del = FALSE;
+  switch (omode)
+    {
+    case open_read:
+      ms = "rb";
+      break;
+    case open_read_write:
+      ms = "r+b";
+      break;
+    case create_write:
+      ms = "wb";
+      f->del = TRUE;
+      break;
+    default:
+      ms = NULL;
+      break;
+    }
+  f->name = name;
+  f->f = fopen (name, ms);
+  if (f->f == NULL)
+    error ("cannot open `%s'", name);
+  f->ok = TRUE;
+}
+
+
+/* Close the file F if it is open. */
+
+void my_close (struct file *f)
+{
+  if (f->ok)
+    {
+      f->ok = FALSE;
+      if (fflush (f->f) != 0)
+        error ("cannot write `%s'", f->name);
+      if (fclose (f->f) != 0)
+        error ("cannot close `%s'", f->name);
+    }
+}
+
+
+/* Close and remove the file F if it is open. */
+
+void my_remove (struct file *f)
+{
+  if (f->ok)
+    {
+      f->ok = FALSE;
+      fclose (f->f);
+      remove (f->name);
+    }
+}
+
+
+/* Set the read/write pointer of the file F to location POS. */
+
+void my_seek (struct file *f, long pos)
+{
+  if (fseek (f->f, pos, SEEK_SET) != 0)
+    error ("seek failed (`%s')", f->name);
+}
+
+
+/* Skip POS bytes of the file F.  The read/write pointer is moved by
+   POS. */
+
+void my_skip (struct file *f, long pos)
+{
+  if (fseek (f->f, pos, SEEK_CUR) != 0)
+    error ("seek failed (`%s')", f->name);
+}
+
+
+/* Return the length of the file F.  Note that this function moves the
+   read/write pointer to the end of the file. */
+
+long my_size (struct file *f)
+{
+  long n;
+
+  if (fseek (f->f, 0L, SEEK_END) != 0 || (n = ftell (f->f)) < 0)
+    error ("seek failed (`%s')", f->name);
+  return n;
+}
+
+
+/* Return the current location of the read/write pointer of the file
+   F. */
+
+long my_tell (struct file *f)
+{
+  long n;
+
+  n = ftell (f->f);
+  if (n < 0)
+    error ("ftell() failed (`%s')", f->name);
+  return n;
+}
+
+
+/* Truncate the file F.  All data beyond the current read/write
+   pointer are discarded. */
+
+void my_trunc (struct file *f)
+{
+  fflush (f->f);
+  if (ftruncate (fileno (f->f), ftell (f->f)) != 0)
+    error ("ftruncate failed (`%s')", f->name);
+}
+
+
+/* Read a null-terminated string from the file F to the buffer DST.
+   There are SIZE bytes available at DST. */
+
+void my_read_str (byte *dst, size_t size, struct file *f)
+{
+  int c;
+
+  for (;;)
+    {
+      c = getc (f->f);
+      if (c == EOF)
+        error ("cannot read `%s'", f->name);
+      if (size <= 0)
+        error ("invalid string in `%s'", f->name);
+      *dst++ = (byte)c;
+      --size;
+      if (c == 0)
+	break;
+    }
+}
+
+
+/* Let DST reference the file referenced by SRC.  If DST refers to a
+   open file, it will be closed before doing this.  SRC will be
+   closed. */
+
+void my_change (struct file *dst, struct file *src)
+{
+  my_close (dst);
+  *dst = *src;
+  src->ok = src->del = FALSE;
+  my_seek (dst, 0);
+}
+
+
+/* Return true iff the file NAME is readable. */
+
+int my_readable (const char *name)
+{
+  return (access (name, 4) == 0);
+}
+
+
+/* Allocate N bytes of memory.  This function never returns NULL.
+   When running out of memory, a message is displayed and the program
+   is terminated. */
+
+void *xmalloc (size_t n)
+{
+  void *q;
+
+  q = malloc (n);
+  if (q == NULL)
+    out_of_mem ();
+  return q;
+}
+
+
+/* Create a duplicate of the string P on the heap.  This function
+   never returns NULL.  When running out of memory, a message is
+   displayed and the program is terminated. */
+
+char *xstrdup (const char *p)
+{
+  char *q;
+
+  q = strdup (p);
+  if (q == NULL)
+    out_of_mem ();
+  return q;
+}
+
+
+/* Reallocate the block of memory P to N bytes.  This function never
+   returns NULL.  When running out of memory, a message is displayed
+   and the program is terminated. */
+
+void *xrealloc (void *p, size_t n)
+{
+  void *q;
+
+  q = realloc (p, n);
+  if (q == NULL)
+    out_of_mem ();
+  return q;
+}
+
+
+/* Return the string "s" if plural should be used for the number N.
+   If N is 1, return the empty string. */
+
+const char *plural_s (long n)
+{
+  return (n == 1 ? "" : "s");
+}
+
+
+/* Add SIZE bytes at SRC to the end of the growable buffer DST.
+   Expand DST as required. */
+
+void put_grow (struct grow *dst, const void *src, size_t size)
+{
+  if (dst->len + size > dst->size)
+    {
+      dst->size += 1024 * ((size + 1023) / 1024);
+      dst->data = xrealloc (dst->data, dst->size);
+    }
+  memmove (dst->data + dst->len, src, size);
+  dst->len += size;
+}
Index: trunk/src/emx/src/emxcat/COPYING
===================================================================
--- trunk/src/emx/src/emxcat/COPYING	(revision 18)
+++ trunk/src/emx/src/emxcat/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxcat/emxcat.c
===================================================================
--- trunk/src/emx/src/emxcat/emxcat.c	(revision 18)
+++ trunk/src/emx/src/emxcat/emxcat.c	(revision 18)
@@ -0,0 +1,630 @@
+/* emxcat.c -- Concatenate source files
+   Copyright (c) 1992-1998 Eberhard Mattes
+
+This file is part of emxcat.
+
+emxcat is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxcat is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxcat; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define VERSION "0.9d"
+
+#define NORETURN volatile
+
+#define FALSE 0
+#define TRUE  1
+
+typedef struct list
+{
+  struct list *next;
+  char *name;
+} list;
+
+typedef struct edge
+{
+  struct edge *next;
+  struct vertex *v;
+} edge;
+
+typedef struct vertex
+{
+  struct vertex *next;
+  edge *desc;
+  char *name;
+  int mark;
+  int number;
+  int descs;
+} vertex;
+
+static vertex *includes = NULL;
+static vertex **includes_add = &includes;
+static vertex *prev_include = NULL;
+static list *selects = NULL;
+static list **selects_add = &selects;
+static list *consts = NULL;
+static list **consts_add = &consts;
+static list *defines;
+static list **defines_add;
+static list *predefs = NULL;
+static list **predefs_add = &predefs;
+static char *output_fname;
+static FILE *output_file;
+static int rc = 0;
+static int define_warning;
+static int sys_emx_h = FALSE;
+
+
+/* Prototypes. */
+
+static void NORETURN usage (void);
+static void *xmalloc (size_t n);
+static char *xstrdup (const char *s);
+int main (int argc, char *argv[]);
+
+
+/* Tell the user how to invoke this program. */
+
+static void NORETURN usage (void)
+{
+  fprintf (stderr, "emxcat " VERSION " -- "
+           "Copyright (c) 1992-1995 by Eberhard Mattes\n\n");
+  fprintf (stderr, "Usage: emxcat [-D<symbol>]... -o <output_file> <input_file>...\n");
+  exit (1);
+}
+
+
+/* Allocate a block of memory.  Abort if out of memory. */
+
+static void *xmalloc (size_t n)
+{
+  void *p;
+  
+  p = malloc (n);
+  if (p == NULL)
+    {
+      fprintf (stderr, "emxcat: out of memory\n");
+      exit (2);
+    }
+  return p;
+}
+
+
+/* Create on the heap a duplicate of the string S.  Abort if out of
+   memory. */
+
+static char *xstrdup (const char *s)
+{
+  char *p;
+  
+  p = xmalloc (strlen (s) + 1);
+  strcpy (p, s);
+  return p;
+}
+
+
+/* Add a string to a linked to list of strings. */
+
+static void add_list (list ***dst, const char *src)
+{
+  list *p;
+
+  p = xmalloc (sizeof (*p));
+  p->next = NULL;
+  p->name = (char *)src;
+  **dst = p;
+  *dst = &p->next;
+}
+
+
+/* Handle an #include directive. */
+
+static int do_include (const char *str, int pass, const char *fname)
+{
+  char delim;
+  char *name;
+  int len;
+  const char *start, *s;
+  vertex *p, *v;
+  edge *e;
+
+  if (pass == 1 && defines != NULL && !define_warning)
+    {
+      fprintf (stderr, "emxcat: #define used before #include in %s\n",
+               fname);
+      define_warning = TRUE;
+      rc = 1;
+    }
+  s = str;
+  if (!isspace ((unsigned char)*s))
+    return TRUE;
+  while (isspace ((unsigned char)*s))
+    ++s;
+  if (*s == '"')
+    delim = '"';
+  else if (*s == '<')
+    delim = '>';
+  else
+    return TRUE;
+  start = s;
+  ++s;
+  while (*s != 0 && *s != delim)
+    ++s;
+  if (*s != delim)
+    return TRUE;
+  if (pass == 1)
+    return FALSE;
+  ++s;
+  len = s - start;
+  name = alloca (len+1);
+  memcpy (name, start, len);
+  name[len] = 0;
+  if (strcmp (name, "<sys/emx.h>") == 0)
+    {
+      sys_emx_h = TRUE;
+      return FALSE;
+    }
+  v = NULL;
+  for (p = includes; p != NULL; p = p->next)
+    if (strcmp (name, p->name) == 0)
+      {
+        v = p;
+        break;
+      }
+  if (v == NULL)
+    {
+      v = xmalloc (sizeof (*v));
+      v->next = NULL;
+      v->name = xstrdup (name);
+      v->desc = NULL;
+      v->mark = 0;
+      v->descs = 0;
+      *includes_add = v;
+      includes_add = &v->next;
+    }
+  if (prev_include != NULL)
+    {
+      for (e = v->desc; e != NULL; e = e->next)
+        if (e->v == prev_include)
+          break;
+      if (e == NULL)
+        {
+          e = xmalloc (sizeof (*e));
+          e->next = v->desc;
+          v->desc = e;
+          e->v = prev_include;
+        }
+    }
+  prev_include = v;
+  return FALSE;
+}
+
+
+/* Handle a #define directive. */
+
+static int do_define (const char *str, int pass)
+{
+  char *name;
+  int len;
+  const char *start, *s;
+  list *p;
+
+  s = str;
+  if (!isspace ((unsigned char)*s))
+    return TRUE;
+  while (isspace ((unsigned char)*s))
+    ++s;
+  start = s;
+  while (*s == '_' || isalnum ((unsigned char)*s))
+    ++s;
+  len = s - start;
+  name = alloca (len+1);
+  memcpy (name, start, len);
+  name[len] = 0;
+  while (isspace ((unsigned char)*s))
+    ++s;
+  if (strncmp (s, "/*", 2) == 0)
+    s = strchr (s, 0);
+  if (strncmp (name, "INCL_", 5) == 0 && *s == 0)
+    {
+      if (pass == 1)
+        return FALSE;
+      for (p = selects; p != NULL; p = p->next)
+        if (strcmp (p->name, name) == 0)
+          return FALSE;
+      add_list (&selects_add, xstrdup (name));
+      return FALSE;
+    }
+  else if (pass == 0)
+    return FALSE;
+  else
+    {
+      add_list (&defines_add, xstrdup (name));
+      return TRUE;
+    }
+}
+
+
+/* Handle a CONST_ definition encountered in an .s file. */
+
+static int do_const (const char *str, int pass)
+{
+  const char *s;
+  char *name;
+  int len;
+  list *p;
+
+  if (pass == 0)
+    return FALSE;
+  for (s = str; *s == '_' || isalnum ((unsigned char)*s); ++s)
+    ;
+  len = s - str;
+  name = alloca (len+1);
+  memcpy (name, str, len);
+  name[len] = 0;
+  for (p = consts; p != NULL; p = p->next)
+    if (strcmp (name, p->name) == 0)
+      return FALSE;
+  add_list (&consts_add, xstrdup (name));
+  return TRUE;
+}
+
+
+/* Clear all marks of the dag of header files. */
+
+static void unmark (void)
+{
+  vertex *p;
+
+  for (p = includes; p != NULL; p = p->next)
+    p->mark = 0;
+}
+
+
+/* Number the vertices of the dag of header files. */
+
+static int vn;
+
+static void number_2 (vertex *v)
+{
+  edge *e;
+  
+  v->mark = 1;
+  v->number = vn++;
+  v->descs = 0;
+  for (e = v->desc; e != NULL; e = e->next)
+    if (!e->v->mark)
+      {
+        number_2 (e->v);
+        v->descs += 1 + e->v->descs;
+      }
+}
+
+/* Helper function for checking for cycles the dag of header files. */
+
+static void cycles_2 (vertex *v, const char *fname)
+{
+  edge *e;
+  vertex *w;
+
+  v->mark = 1;
+  for (e = v->desc; e != NULL; e = e->next)
+    {
+      w = e->v;
+      if (w->mark)
+        {
+          if (v->number >= w->number && v->number <= w->number + w->descs)
+            {
+              fprintf (stderr, "emxcat: %s: inconsistent order of %s and %s\n",
+                       fname, v->name, w->name);
+              rc = 1;
+            }
+        }
+      else
+        cycles_2 (w, fname);
+    }
+}
+
+/* Check for cycles the dag of header files. */
+
+static void cycles (const char *fname)
+{
+  vertex *p;
+
+  unmark ();
+  vn = 1;
+  for (p = includes; p != NULL; p = p->next)
+    if (!p->mark)
+      number_2 (p);
+  unmark ();
+  for (p = includes; p != NULL; p = p->next)
+    if (!p->mark)
+      cycles_2 (p, fname);
+}
+
+
+/* Read the input file named FNAME.  If PASS is zero, collect
+   information.  If PASS is one, copy the file contents to the output
+   file. */
+
+static void read_file (const char *fname, int pass)
+{
+  FILE *f;
+  char *s;
+  list *p, *q;
+  enum {TYPE_UNKNOWN, TYPE_C, TYPE_S} type;
+  char line[1024];
+  int copy;
+
+  /* Determine the type of the file (C or assembler) from the file
+     name suffix. */
+
+  type = TYPE_UNKNOWN;
+  s = _getext (fname);
+  if (s != NULL)
+    {
+      ++s;
+      if (stricmp (s, "c") == 0 || stricmp (s, "cc") == 0
+          || stricmp (s, "cpp") == 0 || stricmp (s, "cxx") == 0)
+        type = TYPE_C;
+      else if (stricmp (s, "s") == 0)
+        type = TYPE_S;
+    }
+
+  /* Abort if the file type is not known. */
+
+  if (type == TYPE_UNKNOWN)
+    {
+      fprintf (stderr, "emxcat: unknown file type (%s)\n", fname);
+      exit (1);
+    }
+
+  /* Open the file. */
+
+  f = fopen (fname, "rt");
+  if (f == NULL)
+    {
+      perror (fname);
+      exit (2);
+    }
+
+  /* Initialize file-local variables. */
+
+  defines = NULL; defines_add = &defines; prev_include = NULL;
+  define_warning = FALSE;
+
+  /* Read lines until hitting the end of the file. */
+
+  while (fgets (line, sizeof (line), f) != NULL)
+    {
+      /* Lines starting with #include and #define are handled
+         specially.  In assembler files, lines starting with CONST_
+         are handled specially.  In the second pass, all other lines
+         are copied verbatim to the output file. */
+
+      if (memcmp (line, "#include", 8) == 0)
+        copy = do_include (line+8, pass, fname);
+      else if (type == TYPE_S && memcmp (line, "CONST_", 6) == 0)
+        copy = do_const (line, pass);
+      else if (memcmp (line, "#define", 7) == 0)
+        copy = do_define (line+7, pass);
+      else
+        copy = TRUE;
+
+      /* Write the line to the output file if we are in the second
+         pass and the line is to be copied. */
+
+      if (copy && pass == 1)
+        {
+          if (fputs (line, output_file) == EOF)
+            break;
+        }
+    }
+
+  /* Check the input stream for I/O errors, then close it. */
+
+  if (ferror (f))
+    {
+      perror (fname);
+      exit (2);
+    }
+  fclose (f);
+
+  /* Undefine all symbols #defined in this file. */
+
+  if (defines != NULL)
+    {
+      fputc ('\n', output_file);
+      for (p = defines; p != NULL; p = q)
+        {
+          q = p->next;
+          fprintf (output_file, "#undef %s\n", p->name);
+          free (p->name);
+          free (p);
+        }
+    }
+
+  /* Check for cycles the dag of header files. */
+
+  if (pass == 0)
+    cycles (fname);
+
+  /* In the second pass, write an empty line to the output file, and
+     check for I/O errors. */
+
+  if (pass == 1)
+    {
+      fputc ('\n', output_file);
+      if (ferror (output_file))
+        {
+          perror ("emxcat output file");
+          exit (2);
+        }
+    }
+}
+
+
+/* Write #define directives for predefined symbols. */
+
+static void insert_predefs (void)
+{
+  list *p;
+
+  for (p = predefs; p != NULL; p = p->next)
+    fprintf (output_file, "#define %s\n", p->name);
+}
+
+
+/* Insert #define directives which have been used before #include
+   directives. */
+
+static void insert_selects (void)
+{
+  list *p;
+
+  for (p = selects; p != NULL; p = p->next)
+    fprintf (output_file, "#define %s\n", p->name);
+}
+
+
+/* Topological sort on the dag of #include directives, writing them to
+   the output file. */
+
+static void insert_includes_2 (vertex *v)
+{
+  edge *e;
+
+  v->mark = 1;
+  for (e = v->desc; e != NULL; e = e->next)
+    if (!e->v->mark)
+      insert_includes_2 (e->v);
+  fprintf (output_file, "#include %s\n", v->name);
+}
+
+
+/* Compare two argv[] entries by name.  This function is passed to
+   qsort() for sorting the input files by name. */
+
+int cmp_fname (const void *p1, const void *p2)
+{
+  /* Disregard case when comparing file names, to get same result on
+     case-preserving file systems (HPFS) and upper-casing file systems
+     (FAT). */
+
+  return _fncmp (*(const char * const *)p1,
+                 *(const char * const *)p2);
+}
+
+
+/* Topologically sort #include directives and write them to the output
+   file.  <sys/emx.h> always comes first. */
+
+static void insert_includes (void)
+{
+  vertex *p;
+
+  if (sys_emx_h)
+    fputs ("#include <sys/emx.h>\n", output_file);
+  unmark ();
+  for (p = includes; p != NULL; p = p->next)
+    if (!p->mark)
+      insert_includes_2 (p);
+}
+
+
+/* The main code of emxcat. */
+
+int main (int argc, char *argv[])
+{
+  int i, j, pass;
+
+  /* Expand response files and wildcards. */
+
+  _response (&argc, &argv);
+  _wildcard (&argc, &argv);
+
+  /* Handle -D options. */
+
+  i = 1;
+  while (i < argc && strncmp (argv[i], "-D", 2) == 0 && strlen (argv[i]) > 2)
+    {
+      add_list (&predefs_add, xstrdup (argv[i] + 2));
+      ++i;
+    }
+
+  /* 3 or more arguments must be left: -o <output_file> <input_file> */
+
+  if (argc - i < 3)
+    usage ();
+  if (strcmp (argv[i], "-o") != 0)
+    usage ();
+  ++i;
+  output_fname = argv[i++];
+
+  /* Open the output file. */
+
+  output_file = fopen (output_fname, "wt");
+  if (output_file == NULL)
+    {
+      perror (output_fname);
+      exit (2);
+    }
+
+  /* Sort the input files by name.  This is for getting predictable
+     results when using wildcards.  Note that _wildcard() yields files
+     sorted by name on HPFS partitions.  On FAT partitions, however,
+     the files are not in a particular order. */
+
+  qsort (argv + i, argc - i, sizeof (*argv), cmp_fname);
+
+  /* Make two passes over all the files.  The first pass collects
+     information, the second pass writes the output file. */
+
+  for (pass = 0; pass < 2; ++pass)
+    {
+      if (pass == 1)
+        {
+          /* At the beginning of the second pass, write #define and
+             #include directives. */
+
+          insert_predefs ();
+          insert_selects ();
+          insert_includes ();
+        }
+
+      /* Read each input file given on the command line, provided its
+         name is not identical to the name of the output file. */
+
+      for (j = i; j < argc; ++j)
+        if (_fncmp (output_fname, argv[j]) != 0)
+          read_file (argv[j], pass);
+    }
+
+  /* Close the output file. */
+
+  if (fflush (output_file) != 0 || fclose (output_file) != 0)
+    {
+      perror (output_fname);
+      exit (2);
+    }
+
+  /* Done. */
+
+  return rc;
+}
Index: trunk/src/emx/src/emxcat/makefile
===================================================================
--- trunk/src/emx/src/emxcat/makefile	(revision 18)
+++ trunk/src/emx/src/emxcat/makefile	(revision 18)
@@ -0,0 +1,50 @@
+#
+# /emx/src/emxcat/makefile
+#
+# Copyright (c) 1992-1998 by Eberhard Mattes
+#
+# This file is part of emxcat.
+#
+# emxcat is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emxcat is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emxcat; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+.SUFFIXES: .c .o
+
+BIN=d:\emx\bin\ #
+
+CC=gcc
+CFLAGS=-O -Wall
+LFLAGS=-s -Zsmall-conv
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+default:	all
+all:		emxcat
+emxcat:		$(BIN)emxcat.exe
+
+emxcat.o: emxcat.c
+
+$(BIN)emxcat.exe: emxcat.o
+	gcc $(LFLAGS) -o $(BIN)emxcat.exe emxcat.o
+
+clean:
+	-del *.o
+
+realclean: clean
+	-del $(BIN)emxcat.exe
+
+# End of /emx/src/emxcat/makefile
Index: trunk/src/emx/src/emxdoc/COPYING
===================================================================
--- trunk/src/emx/src/emxdoc/COPYING	(revision 18)
+++ trunk/src/emx/src/emxdoc/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxdoc/cond.c
===================================================================
--- trunk/src/emx/src/emxdoc/cond.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/cond.c	(revision 18)
@@ -0,0 +1,264 @@
+/* cond.c -- Conditional expressions
+   Copyright (c) 1993-1999 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "emxdoc.h"
+#include "cond.h"
+
+enum ctok
+{
+  CTOK_END,
+  CTOK_LPAR,
+  CTOK_RPAR,
+  CTOK_OR,
+  CTOK_AND,
+  CTOK_NOT,
+  CTOK_CONST
+};
+
+struct cond_var
+{
+  struct cond_var *next;
+  uchar *name;
+  int value;
+};
+
+static const uchar *cond_ptr;
+static enum ctok ct_token;
+static int ct_value;
+static struct cond_var *cond_vars = NULL;
+
+
+static int cond_or (void);
+static void cond_fetch (void);
+static struct cond_var *cond_find (const uchar *name);
+
+
+int condition (const uchar *p)
+{
+  int result;
+
+  cond_ptr = p;
+  cond_fetch ();
+  result = cond_or ();
+  if (ct_token != CTOK_END)
+    fatal ("%s:%d: End of line expected after condition expression",
+           input_fname, line_no);
+  return result;
+}
+
+
+void cond_set (const uchar *name, int value)
+{
+  struct cond_var *v;
+
+  v = cond_find (name);
+  if (v == NULL)
+    {
+      v = xmalloc (sizeof (*v));
+      v->name = xstrdup (name);
+      v->next = cond_vars;
+      cond_vars = v;
+    }
+  v->value = value;
+}
+
+
+static struct cond_var *cond_find (const uchar *name)
+{
+  struct cond_var *v;
+
+  for (v = cond_vars; v != NULL; v = v->next)
+    if (strcmp (v->name, name) == 0)
+      return v;
+  return NULL;
+}
+
+
+static void cond_fetch (void)
+{
+  static uchar name[512];
+  int len;
+  struct cond_var *v;
+
+  while (isspace (*cond_ptr))
+    ++cond_ptr;
+  switch (*cond_ptr)
+    {
+    case 0:
+      ct_token = CTOK_END;
+      return;
+    case '!':
+      ct_token = CTOK_NOT; ++cond_ptr;
+      return;
+    case '&':
+      ct_token = CTOK_AND; ++cond_ptr;
+      return;
+    case '|':
+      ct_token = CTOK_OR; ++cond_ptr;
+      return;
+    case '(':
+      ct_token = CTOK_LPAR; ++cond_ptr;
+      return;
+    case ')':
+      ct_token = CTOK_RPAR; ++cond_ptr;
+      return;
+    case 'f':
+      if (strncmp (cond_ptr, "false", 5) == 0)
+        {
+          ct_token = CTOK_CONST; ct_value = FALSE;
+          cond_ptr += 5;
+          return;
+        }
+      break;
+    case 'h':
+      if (strncmp (cond_ptr, "html", 4) == 0)
+        {
+          ct_token = CTOK_CONST; ct_value = (mode == 'H');
+          cond_ptr += 4;
+          return;
+        }
+      break;
+    case 'i':
+      if (strncmp (cond_ptr, "ipf", 3) == 0)
+        {
+          ct_token = CTOK_CONST; ct_value = (mode == 'I');
+          cond_ptr += 3;
+          return;
+        }
+      break;
+    case 'l':
+      if (strncmp (cond_ptr, "latex", 5) == 0)
+        {
+          ct_token = CTOK_CONST; ct_value = (mode == 'L');
+          cond_ptr += 5;
+          return;
+        }
+      break;
+    case 't':
+      if (strncmp (cond_ptr, "text", 4) == 0)
+        {
+          ct_token = CTOK_CONST; ct_value = (mode == 'T');
+          cond_ptr += 4;
+          return;
+        }
+      else if (strncmp (cond_ptr, "true", 4) == 0)
+        {
+          ct_token = CTOK_CONST; ct_value = TRUE;
+          cond_ptr += 4;
+          return;
+        }
+      break;
+    }
+  if (isalpha (*cond_ptr))
+    {
+      len = 0;
+      name[len] = cond_ptr[len]; ++len;
+      while (isalnum (cond_ptr[len]) || cond_ptr[len] == '_')
+        name[len] = cond_ptr[len], ++len;
+      name[len] = 0;
+      v = cond_find (name);
+      if (v != NULL)
+        {
+          ct_token = CTOK_CONST; ct_value = v->value;
+          cond_ptr += len;
+          return;
+        }
+    }
+  fatal ("%s:%d: Invalid token in condition expression",
+         input_fname, line_no);
+}
+
+
+static int cond_factor (void)
+{
+  int result;
+
+  switch (ct_token)
+    {
+    case CTOK_LPAR:
+      cond_fetch ();
+      result = cond_or ();
+      if (ct_token != CTOK_RPAR)
+        fatal ("%s:%d: Missing right parenthesis in condition expression",
+               input_fname, line_no);
+      break;
+
+    case CTOK_END:
+      fatal ("%s:%d: Operand expected in condition expression",
+             input_fname, line_no);
+
+    case CTOK_CONST:
+      result = ct_value;
+      cond_fetch ();
+      break;
+
+    default:
+      fatal ("%s:%d: Invalid operand in condition expression",
+             input_fname, line_no);
+    }
+  return result;
+}
+
+
+static int cond_not (void)
+{
+  if (ct_token == CTOK_NOT)
+    {
+      cond_fetch ();
+      return !cond_not ();
+    }
+  else
+    return cond_factor ();
+}
+
+
+static int cond_and (void)
+{
+  int result;
+
+  result = cond_not ();
+  while (ct_token == CTOK_AND)
+    {
+      cond_fetch ();
+      if (!cond_not ())
+        result = FALSE;
+    }
+  return result;
+}
+
+
+static int cond_or (void)
+{
+  int result;
+
+  result = cond_and ();
+  while (ct_token == CTOK_OR)
+    {
+      cond_fetch ();
+      if (cond_and ())
+        result = TRUE;
+    }
+  return result;
+}
Index: trunk/src/emx/src/emxdoc/cond.h
===================================================================
--- trunk/src/emx/src/emxdoc/cond.h	(revision 18)
+++ trunk/src/emx/src/emxdoc/cond.h	(revision 18)
@@ -0,0 +1,23 @@
+/* cond.h -- Conditional expressions
+   Copyright (c) 1993-1995 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+int condition (const uchar *p);
+void cond_set (const uchar *name, int value);
Index: trunk/src/emx/src/emxdoc/emxdoc.c
===================================================================
--- trunk/src/emx/src/emxdoc/emxdoc.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/emxdoc.c	(revision 18)
@@ -0,0 +1,2817 @@
+/* emxdoc.c -- Main module of emxdoc
+   Copyright (c) 1993-2001 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#define EXTERN
+#define INIT(X) = X
+#include "emxdoc.h"
+#include "html.h"
+#include "ipf.h"
+#include "latex.h"
+#include "text.h"
+#include "xref.h"
+#include "cond.h"
+
+#define VERSION "0.9d"
+
+struct word_table
+{
+  unsigned hash_size;           /* hash size */
+  struct word **hash_table;     /* hash table */
+  int count;                    /* number of elements */
+};
+
+struct local
+{
+  struct word *wp;
+  enum style style;
+};
+
+/* This is the return code of the program.  It is initially 0.
+   nonfatal() sets it to 1. */
+static int history = 0;
+
+static int opt_r = FALSE;       /* Make output file read-only */
+
+static const char *xref_fname = NULL;
+
+static const char *output_fname = NULL;
+static int output_flag = FALSE;
+
+static const char *hyphenation_fname = NULL;
+
+static uchar *line;
+static size_t line_size = 0;
+static size_t line_len = 0;
+
+/* Temporary output buffer. */
+static uchar output[512];
+
+/* Syntax style. */
+static enum syntax syntax_style;
+
+static size_t elements_size = 0;
+static size_t elements_count = 0;
+
+static int max_width;
+
+static struct local *local_stack = NULL;
+static int local_size = 0;
+static int local_sp;
+
+static int section_numbers[SECTION_LEVELS];
+
+static struct toc *toc_head = NULL;
+static struct toc *toc_ptr = NULL;
+static struct toc **toc_add = &toc_head;
+static int toc_indent = 0;
+
+static uchar compat[128];
+
+static int copy_flag;
+
+static void usage (void) NORETURN2;
+
+
+/* Display an error message and stop. */
+
+void fatal (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  vfprintf (stderr, fmt, arg_ptr);
+  putc ('\n', stderr);
+  exit (1);
+}
+
+
+/* Display an error message and set history to 1.  Don't stop. */
+
+void nonfatal (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  vfprintf (stderr, fmt, arg_ptr);
+  putc ('\n', stderr);
+  history = 1;
+}
+
+
+/* Display a warning message if opt_w is equal to or greater than
+   LEVEL.  Don't change history and don't stop. */
+
+void warning (int level, const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  if (opt_w >= level)
+    {
+      va_start (arg_ptr, fmt);
+      vfprintf (stderr, fmt, arg_ptr);
+      putc ('\n', stderr);
+    }
+}
+
+
+/* Allocate N bytes of memory.  Quit on failure.  This function is
+   used like malloc(), but we don't have to check the return value. */
+
+void *xmalloc (size_t n)
+{
+  void *p;
+
+  p = malloc (n);
+  if (p == NULL)
+    fatal ("Out of memory");
+  return p;
+}
+
+
+/* Change the allocation of PTR to N bytes.  Quit on failure.  This
+   function is used like realloc(), but we don't have to check the
+   return value. */
+
+static void *xrealloc (void *ptr, size_t n)
+{
+  void *p;
+
+  p = realloc (ptr, n);
+  if (p == NULL)
+    fatal ("Out of memory");
+  return p;
+}
+
+
+/* Create a duplicate of the string S on the heap.  Quit on failure.
+   This function is used like strdup(), but we don't have to check the
+   return value. */
+
+uchar *xstrdup (const uchar *s)
+{
+  char *p;
+
+  p = xmalloc (strlen (s) + 1);
+  strcpy (p, s);
+  return p;
+}
+
+
+static void usage (void)
+{
+  fputs ("emxdoc " VERSION " -- "
+         "Copyright (c) 1993-1999 by Eberhard Mattes\n\n", stderr);
+  fputs ("Usage:\n", stderr);
+  fputs ("  emxdoc -H [-o <output>] [-x <xref>] <input>\n", stderr);
+  fputs ("  emxdoc -T [-fr] [-o <output>] <input>\n", stderr);
+  fputs ("  emxdoc -L [-fr] [-o <output>] <input>\n", stderr);
+  fputs ("  emxdoc -I [-acfgr] [-n <start>] [-o <output>] [-x <xref>] <input>\n", stderr);
+  fputs ("  emxdoc -K [-o <output>] <input>\n", stderr);
+  fputs ("  emxdoc -M [-o <output>] <input>...\n", stderr);
+  fputs ("\nModes:\n\n", stderr);
+  fputs ("  -H         Generate HTML file\n", stderr);
+  fputs ("  -I         Generate IPF file\n", stderr);
+  fputs ("  -K         Generate index file\n", stderr);
+  fputs ("  -L         Generate LaTeX file\n", stderr);
+  fputs ("  -M         Merge directory files\n", stderr);
+  fputs ("  -T         Generate text file\n", stderr);
+  fputs ("\nOptions:\n\n", stderr);
+  fputs ("  -a         Concatenate instead of call .INF files\n", stderr);
+  fputs ("  -b<number> Select line breaking algorithm for -t\n", stderr);
+  fputs ("  -c         Use color instead of slanted font\n", stderr);
+  fputs ("  -e<char>   Set escape character\n", stderr);
+  fputs ("  -f         Enable French spacing\n", stderr);
+  fputs ("  -g         Gather global directory data\n", stderr);
+  fputs ("  -h<file>   Use hyphenation table\n", stderr);
+  fputs ("  -i<enc>    Select input encoding\n", stderr);
+  fputs ("  -n<start>  Set first ID number\n", stderr);
+  fputs ("  -o<output> Set output file name\n", stderr);
+  fputs ("  -r         Make output file read-only\n", stderr);
+  fputs ("  -w<level>  Set warning level\n", stderr);
+  fputs ("  -x<xref>   Use cross reference file\n", stderr);
+  exit (1);
+}
+
+
+static void upcase (uchar *s)
+{
+  while (*s != 0)
+    {
+      *s = (uchar)toupper (*s);
+      ++s;
+    }
+}
+
+
+static void downcase (uchar *s)
+{
+  while (*s != 0)
+    {
+      *s = (uchar)tolower (*s);
+      ++s;
+    }
+}
+
+
+void write_nl (void)
+{
+  if (output_flag)
+    {
+      putc ('\n', output_file);
+      if (ferror (output_file))
+        {
+          perror (output_fname);
+          exit (1);
+        }
+      if (output_x > max_width)
+        nonfatal ("%s:%d: Output line %d too long",
+                  input_fname, line_no, output_line_no);
+      output_x = 0;
+      ++output_line_no;
+    }
+}
+
+
+void write_break (void)
+{
+  if (output_x != 0)
+    write_nl ();
+}
+
+
+/* P must not contain \n! */
+
+void write_nstring (const uchar *p, size_t n)
+{
+  if (output_flag)
+    {
+      fwrite (p, n, 1, output_file);
+      output_x += n;
+    }
+}
+
+
+/* P must not contain \n! */
+
+void write_string (const uchar *p)
+{
+  write_nstring (p, strlen (p));
+}
+
+
+/* P must not contain \n! */
+
+void write_line (const uchar *p)
+{
+  write_string (p);
+  write_nl ();
+}
+
+/* Output must not contain \n! */
+
+void write_fmt (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  if (output_flag)
+    {
+      va_start (arg_ptr, fmt);
+      output_x += vfprintf (output_file, fmt, arg_ptr);
+    }
+}
+
+
+void write_space (void)
+{
+  if (output_x >= 60)
+    write_nl ();
+  else
+    write_string (" ");
+}
+
+struct word_table *wt_new (unsigned hash_size)
+{
+  unsigned i;
+  struct word_table *wt = xmalloc (sizeof (*wt));
+
+  wt->hash_size = hash_size;
+  wt->count = 0;
+  wt->hash_table = xmalloc (hash_size * sizeof (wt->hash_table[0]));
+  for (i = 0; i < hash_size; ++i)
+    wt->hash_table[i] = NULL;
+  return wt;
+}
+
+unsigned wt_hash (struct word_table *wt, const uchar *str)
+{
+  unsigned h;
+
+  h = 0;
+  while (*str != 0)
+    {
+      h = (h << 2) ^ *str;
+      ++str;
+    }
+  return h % wt->hash_size;
+}
+
+
+struct word *wt_find (struct word_table *wt, const uchar *str, unsigned hash)
+{
+  struct word *wp;
+
+  for (wp = wt->hash_table[hash]; wp != NULL; wp = wp->next)
+    if (strcmp (wp->str, str) == 0)
+      return wp;
+  return NULL;
+}
+
+
+struct word *wt_add (struct word_table *wt, const uchar *str)
+{
+  struct word *wp;
+  unsigned hash;
+
+  hash = wt_hash (wt, str);
+  wp = wt_find (wt, str, hash);
+  if (wp == NULL)
+    {
+      wp = xmalloc (sizeof (*wp));
+      wp->style = STYLE_NORMAL;
+      wp->str = xstrdup (str);
+      wp->ref = 0; wp->idx = 0;
+      wp->database = NULL;
+      wp->special = NULL;
+      wp->subidx = NULL;
+      wp->repl = NULL;
+      wp->flags = 0;
+      wp->next = wt->hash_table[hash];
+      wt->hash_table[hash] = wp;
+      wt->count += 1;
+    }
+  return wp;
+}
+
+int wt_walk (struct word_table *wt, int (*callback)(struct word *))
+{
+  int x = 0;
+  unsigned i;
+  struct word *wp;
+
+  for (i = 0; i < wt->hash_size; ++i)
+    for (wp = wt->hash_table[i]; wp != NULL; wp = wp->next)
+      {
+        x = callback (wp);
+        if (x != 0)
+          return x;
+      }
+  return x;
+}
+
+int wt_count (const struct word_table *wt)
+{
+  return wt->count;
+}
+
+unsigned word_hash (const uchar *str)
+{
+  return wt_hash (word_top, str);
+}
+
+struct word *word_find (const uchar *str, unsigned hash)
+{
+  return wt_find (word_top, str, hash);
+}
+
+struct word *word_add (const uchar *str)
+{
+  return wt_add (word_top, str);
+}
+
+int word_walk (int (*callback)(struct word *))
+{
+  return wt_walk (word_top, callback);
+}
+
+/* We do not really nest local blocks */
+
+static void local_begin (void)
+{
+}
+
+
+static void local_end (void)
+{
+  while (local_sp > 0)
+    {
+      --local_sp;
+      local_stack[local_sp].wp->style = local_stack[local_sp].style;
+    }
+}
+
+
+static void local_add (struct word *wp)
+{
+  if (local_sp >= local_size)
+    {
+      local_size += 256;
+      local_stack = xrealloc (local_stack, local_size * sizeof (*local_stack));
+    }
+  local_stack[local_sp].wp = wp;
+  local_stack[local_sp].style = wp->style;
+  ++local_sp;
+}
+
+
+void format_output (const uchar *p, int may_break)
+{
+  switch (mode)
+    {
+    case 'H':
+      html_output (p, may_break);
+      break;
+    case 'I':
+      ipf_output (p, may_break);
+      break;
+    case 'L':
+      latex_output (p, may_break);
+      break;
+    case 'T':
+      text_output (p, may_break);
+      break;
+    }
+}
+
+
+void start_hilite (int hilite)
+{
+  if (hl_sp >= HL_STACK_SIZE - 1)
+    fatal ("%s:%d: Highlighting stack overflow", input_fname, line_no);
+  ++hl_sp;
+  hl_stack[hl_sp] = hl_stack[hl_sp-1] | hilite;
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_start_hilite ();
+        break;
+      case 'L':
+        latex_start_hilite ();
+        break;
+      }
+}
+
+
+void end_hilite (void)
+{
+  if (hl_sp == 0)
+    fatal ("%s:%d: Highlighting stack underflow", input_fname, line_no);
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_end_hilite ();
+        break;
+      case 'L':
+        latex_end_hilite ();
+        break;
+      }
+  --hl_sp;
+}
+
+
+static void line_add (const uchar *src, size_t len)
+{
+  if (line_len + len + 1 > line_size)
+    {
+      line_size += 4096;
+      line = xrealloc (line, line_size);
+    }
+  memcpy (line + line_len, src, len);
+  line_len += len;
+  line[line_len] = 0;
+}
+
+
+static struct element *add_element (void)
+{
+  if (elements_count >= elements_size)
+    {
+      elements_size += 512;
+      elements = xrealloc (elements, elements_size * sizeof (*elements));
+    }
+  return &elements[elements_count++];
+}
+
+
+static struct element *add_word (const uchar *word, enum el el)
+{
+  struct element *ep;
+
+  ep = add_element ();
+  ep->el = el;
+  ep->wp = word_add (word);
+  ep->n = 0;                    /* ref */
+  return ep;
+}
+
+
+static void make_elements_internal (const uchar *p)
+{
+  uchar word[512], *d, start, end, *h1;
+  struct element *ep;
+  struct word *wp;
+  struct toc *tp;
+  int n, level, paren;
+  enum {other, other_dot, abbrev, abbrev_dot} state;
+
+  state = other;
+  while (*p != 0)
+    {
+      if (*p == escape)
+        {
+          state = other;
+          parse_tag (&p);
+          switch (tg_tag)
+            {
+            case TAG_STYLE:
+            case TAG_REF:
+            case TAG_HPT:
+              start = *p;
+              if (start == '{')
+                end = '}';
+              else if (start == '[')
+                end = ']';
+              else
+                fatal ("%s:%d: Missing {", input_fname, line_no);
+              ++p; n = 0; level = 0;
+              while (*p != 0 && !(level == 0 && *p == end))
+                {
+                  if (n >= sizeof (word) - 1)
+                    fatal ("%s%d: Argument too long", input_fname, line_no);
+                  word[n++] = *p;
+                  if (*p == start)
+                    ++level;
+                  else if (*p == end)
+                    --level;
+                  ++p;
+                }
+              if (*p != end)
+                fatal ("%s:%d: Missing %c", input_fname, line_no, end);
+              ++p;
+              word[n] = 0;
+              break;
+            case TAG_BREAK:
+              ep = add_element ();
+              ep->el = EL_BREAK;
+              ep->n = 0;
+              break;
+            case TAG_FULLSTOP:
+              add_word (".", EL_PUNCT);
+              state = other_dot;
+              break;
+            default:
+              fatal ("%s:%d: Unexpected tag", input_fname, line_no);
+            }
+          switch (tg_tag)
+            {
+            case TAG_STYLE:
+              ep = add_element ();
+              ep->el = EL_STYLE;
+              ep->n = tg_style;
+              add_word (word, EL_WORD);
+              ep = add_element ();
+              ep->el = EL_ENDSTYLE;
+              break;
+            case TAG_REF:
+              wp = word_find (word, word_hash (word));
+              if (wp == NULL)
+                fatal ("%s:%d: Undefined label: %s",
+                       input_fname, line_no, word);
+              for (tp = toc_head; tp != NULL; tp = tp->next)
+                if (tp->ref == wp->ref)
+                  break;
+              if (tp == NULL)
+                fatal ("%s:%d: Undefined label: %s",
+                       input_fname, line_no, word);
+              ep = add_word (tp->number, EL_WORD);
+              if (ep->wp->ref == 0)
+                ep->wp->ref = wp->ref;
+              else if (ep->wp->ref != wp->ref)
+                fatal ("%s:%d: Label redefined: %s",
+                       input_fname, line_no, tp->number);
+              ep->n = 1;
+              break;
+            case TAG_HPT:
+              wp = use_reference (word);
+              switch (mode)
+                {
+                case 'H':
+                case 'I':
+                  if (wp != NULL)
+                    {
+                      ep = add_word (word, EL_WORD);
+                      ep->n = 1;
+                    }
+                  break;
+                case 'T':
+                case 'L':
+                  make_elements_internal (word); /* Recursive! */
+                  break;
+                }
+              break;
+            case TAG_BREAK:
+            case TAG_FULLSTOP:
+              break;
+            default:
+              abort ();
+            }
+        }
+
+      n = 0;
+      while (isspace (*p))
+        ++n, ++p;
+      if (n != 0)
+        {
+          if (state == other_dot && n == 1)
+            n = (opt_f ? 1 : 2);
+          else if (state == abbrev_dot && n == 2)
+            n = 1;
+          state = other;
+          ep = add_element ();
+          ep->el = EL_SPACE;
+          ep->n = n;
+          continue;
+        }
+
+      d = word;
+      while (*p == '(' || *p == '*' || *p == '`')
+        *d++ = *p++;
+      if (d != word)
+        {
+          *d = 0;
+          add_word (word, EL_PUNCT);
+          state = other;
+          continue;
+        }
+
+      d = word; paren = 0;
+      while (*p != 0 && *p != escape
+             && !(isspace (*p) || *p == ',' || *p == ';'
+                  || *p == '!' || *p == '?' || *p == '\''
+                  || (*p == ')' && paren == 0)
+                  || (*p == '[' && prototype_flag)
+                  || (*p == '&' && prototype_flag)
+                  || ((*p == '.' || *p == ':')
+                      && (p[1] == 0 || isspace (p[1])))))
+        {
+          if (*p == '(')
+            ++paren;
+          else if (*p == ')')
+            --paren;
+          *d++ = *p++;
+        }
+      if (d != word)
+        {
+          *d = 0;
+          wp = word_find (word, word_hash (word));
+          state = (wp != NULL && (wp->flags & WF_ABBREV)) ? abbrev : other;
+          if (language == LANG_GERMAN
+              && wp == NULL
+              && (h1 = strchr (word, '-')) != NULL)
+            {
+              *h1 = 0;
+              if (word_find (word, word_hash (word)) != NULL)
+                {
+                  add_word (word, EL_WORD);
+                  add_word ("-", EL_PUNCT);
+                  add_word (h1 + 1, EL_WORD);
+                }
+              else
+                {
+                  *h1 = '-';
+                  add_word (word, EL_WORD);
+                }
+            }
+          else if (wp != NULL && wp->repl != NULL)
+            make_elements_internal (wp->repl);
+          else
+            add_word (word, EL_WORD);
+        }
+
+      d = word;
+      while (*p == '.' || *p == ',' || *p == ';' || *p == '\''
+             || *p == ':' || *p == '!' || *p == '?' || *p == ')'
+             || (*p == '[' && prototype_flag)
+             || (*p == '&' && prototype_flag))
+        *d++ = *p++;
+      if (d != word)
+        {
+          *d = 0;
+          add_word (word, EL_PUNCT);
+          if (d[-1] == '.')
+            state = ((state == abbrev && d == word + 1)
+                     ? abbrev_dot : other_dot);
+          else
+            state = other;
+        }
+    }
+}
+
+
+static void make_elements_start (void)
+{
+  elements_count = 0;
+}
+
+
+static void make_elements_end (void)
+{
+  struct element *ep;
+
+  ep = add_element ();
+  ep->el = EL_END;
+}
+
+
+void make_elements (const uchar *p)
+{
+  make_elements_start ();
+  make_elements_internal (p);
+  make_elements_end ();
+}
+
+
+#define ISSYNTAXARG(C) ((C) == '*' || (C) == '#' \
+                        || (syntax_style == SYNTAX_DVIDRV && (C) == '+'))
+
+void format_string (const uchar *p, int sty, int may_break)
+{
+  uchar syntax[512], *d;
+  const uchar *s;
+
+  switch (sty)
+    {
+    case STYLE_NORMAL:
+      format_output (p, may_break);
+      break;
+    case STYLE_BOLD:
+      start_hilite (HL_BF);
+      format_output (p, may_break);
+      end_hilite ();
+      break;
+    case STYLE_SLANTED:
+      start_hilite (HL_SL);
+      format_output (p, may_break);
+      end_hilite ();
+      break;
+    case STYLE_UNDERLINE:
+      start_hilite (HL_UL);
+      format_output (p, may_break);
+      end_hilite ();
+      break;
+    case STYLE_TTY:
+      start_hilite (HL_TT);
+      format_output (p, may_break);
+      end_hilite ();
+      break;
+    case STYLE_EMPHASIZE:
+      strcpy (syntax, p);
+      if (mode == 'T')
+        upcase (syntax);
+      start_hilite (HL_EM);
+      format_output (syntax, may_break);
+      end_hilite ();
+      break;
+    case STYLE_PARAM:
+      strcpy (syntax, p);
+      if (mode != 'T' || prototype_flag)
+        downcase (syntax);
+      start_hilite (HL_SL);
+      format_output (syntax, may_break);
+      end_hilite ();
+      break;
+    case STYLE_SYNTAX:
+      s = p;
+      while (*s != 0)
+        {
+          if (isspace (*s) && output_x >= 60)
+            {
+              ++s;
+              write_nl ();
+            }
+          d = syntax;
+          while (*s != 0 && *s != '<' && *s != '|' && *s != '[' && *s != ']'
+                 && !(ISSYNTAXARG (s[0]) && s[1] == 0))
+            *d++ = *s++;
+          if (d != syntax)
+            {
+              *d = 0;
+              start_hilite (HL_TT);
+              format_output (syntax, may_break);
+              end_hilite ();
+            }
+
+          if (ISSYNTAXARG (s[0]) && s[1] == 0)
+            {
+              start_hilite (HL_SL);
+              format_output (s, may_break);
+              end_hilite ();
+              ++s;
+            }
+
+          if (*s == '[' || *s == ']' || *s == '|')
+            {
+              syntax[0] = *s++;
+              syntax[1] = 0;
+              start_hilite (HL_BF);
+              format_output (syntax, may_break);
+              end_hilite ();
+            }
+
+          if (*s == '<')
+            {
+              if (mode != 'T')
+                ++s;
+              d = syntax;
+              while (*s != 0 && *s != '>')
+                *d++ = *s++;
+              if (*s == '>')
+                {
+                  if (mode == 'T')
+                    *d++ = *s;
+                  ++s;
+                }
+              *d = 0;
+              start_hilite (HL_SL);
+              format_output (syntax, may_break);
+              end_hilite ();
+            }
+        }
+      break;
+    default:
+      abort ();
+    }
+}
+
+
+void format_spaces (int n, enum style style, int may_break)
+{
+  uchar *p;
+
+  p = alloca (n + 1);
+  memset (p, ' ', n);
+  p[n] = 0;
+  format_string (p, style, may_break);
+}
+
+
+static void start_env (int env, int tindent, int iindent)
+{
+  if (env_sp >= ENV_STACK_SIZE - 1)
+    fatal ("%s:%d: Environment stack overflow", input_fname, line_no);
+  ++env_sp;
+  env_stack[env_sp].env = env;
+  env_stack[env_sp].tmargin = env_stack[env_sp-1].tmargin + tindent;
+  env_stack[env_sp].imargin = env_stack[env_sp-1].imargin + iindent;
+  env_stack[env_sp].start_line = line_no;
+  env_stack[env_sp].counter = 0;
+}
+
+
+static void end_env (int env)
+{
+  const char *name;
+
+  if (env_stack[env_sp].env != env)
+    {
+      switch (env_stack[env_sp].env)
+        {
+        case ENV_DESCRIPTION:
+          name = "description";
+          break;
+        case ENV_ENUMERATE:
+          name = "enumerate";
+          break;
+        case ENV_ITEMIZE:
+          name = "itemize";
+          break;
+        case ENV_LIST:
+          name = "list";
+          break;
+        case ENV_INDENT:
+          name = "indent";
+          break;
+        case ENV_TYPEWRITER:
+          name = "typewriter";
+          break;
+        default:
+          fatal ("%s:%d: No environment to end", input_fname, line_no);
+          break;
+        }
+      fatal ("%s:%d: %cend%s expected", input_fname, line_no, escape, name);
+    }
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_end_env ();
+        break;
+      case 'I':
+        ipf_end_env ();
+        break;
+      case 'L':
+        latex_end_env ();
+        break;
+      }
+  --env_sp;
+}
+
+
+static void check_copy (void)
+{
+  if (out && !copy_flag)
+    warning (2, "%s:%d: Text should be inserted here", input_fname, line_no);
+  copy_flag = FALSE;
+}
+
+
+static void do_end_env (int env)
+{
+  end_env (env);
+  para_flag = TRUE; copy_flag = FALSE;
+  read_line ();
+}
+
+
+static void do_format (const uchar *p)
+{
+  const uchar *q;
+  enum style sty;
+  struct word *wp;
+  int len;
+  uchar word[512];
+  uchar flg;
+
+  if (!out)
+    {
+      flg = 0;
+      if (strncmp (p, "bold", 4) == 0 && isspace (p[4]))
+        {
+          sty = STYLE_BOLD;
+          p += 4;
+        }
+      else if (strncmp (p, "tty", 3) == 0 && isspace (p[3]))
+        {
+          sty = STYLE_TTY;
+          p += 3;
+        }
+      else if (strncmp (p, "slanted", 7) == 0 && isspace (p[7]))
+        {
+          sty = STYLE_SLANTED;
+          p += 7;
+        }
+      else if (strncmp (p, "syntax", 6) == 0 && isspace (p[6]))
+        {
+          sty = STYLE_SYNTAX;
+          p += 6;
+        }
+      else if (strncmp (p, "param", 5) == 0 && isspace (p[5]))
+        {
+          sty = STYLE_PARAM;
+          p += 5;
+        }
+      else if (strncmp (p, "underline", 9) == 0 && isspace (p[9]))
+        {
+          sty = STYLE_UNDERLINE;
+          p += 9;
+        }
+      else if (strncmp (p, "emphasize", 9) == 0 && isspace (p[9]))
+        {
+          sty = STYLE_EMPHASIZE;
+          p += 9;
+        }
+      else if (strncmp (p, "abbrev", 6) == 0 && isspace (p[6]))
+        {
+          sty = STYLE_NORMAL; flg = WF_ABBREV;
+          p += 6;
+        }
+      else
+        fatal ("%s:%d: Invalid style", input_fname, line_no);
+      for (;;)
+        {
+          while (isspace (*p))
+            ++p;
+          if (*p == 0)
+            break;
+          len = 0; q = p;
+          while (*p != 0 && !isspace (*p))
+            word[len++] = *p++;
+          word[len] = 0;
+          if (sty == STYLE_NORMAL && flg == WF_ABBREV)
+            {
+              if (len < 2 || word[len-1] != '.')
+                fatal ("%s:%d: Abbreviation must end with a period",
+                       input_fname, line_no);
+              word[len-1] = 0;
+            }
+          wp = word_add (word);
+          if (sty != STYLE_NORMAL)
+            wp->style = sty;
+          else
+            wp->flags |= flg;
+        }
+    }
+  read_line ();
+}
+
+
+static void do_special (const uchar *p)
+{
+  const uchar *q;
+  char m;
+  struct word *wp;
+  int len;
+  uchar word[512], *repl;
+
+  if (!out)
+    {
+      if (strncmp (p, "text", 4) == 0 && isspace (p[4]))
+        {
+          m = 'T'; p += 4;
+        }
+      else if (strncmp (p, "ipf", 3) == 0 && isspace (p[3]))
+        {
+          m = 'I'; p += 3;
+        }
+      else if (strncmp (p, "latex", 5) == 0 && isspace (p[5]))
+        {
+          m = 'L'; p += 5;
+        }
+      else if (strncmp (p, "html", 4) == 0 && isspace (p[4]))
+        {
+          m = 'H'; p += 4;
+        }
+      else
+        fatal ("%s:%d: Invalid special mode", input_fname, line_no);
+      while (isspace (*p))
+        ++p;
+      if (*p == 0)
+        fatal ("%s:%d: Missing word", input_fname, line_no);
+      len = 0; q = p;
+      while (*p != 0 && !isspace (*p))
+        word[len++] = *p++;
+      word[len] = 0;
+      while (isspace (*p))
+        ++p;
+      if (*p == 0)
+        fatal ("%s:%d: Missing replacement", input_fname, line_no);
+      repl = xstrdup (p);
+      wp = word_add (word);
+      if (wp->special == NULL)
+        {
+          wp->special = xmalloc (sizeof (struct special));
+          wp->special->text = NULL;
+          wp->special->ipf = NULL;
+          wp->special->latex = NULL;
+          wp->special->html = NULL;
+        }
+      switch (m)
+        {
+        case 'H':
+          wp->special->html = repl; break;
+        case 'T':
+          wp->special->text = repl; break;
+        case 'I':
+          wp->special->ipf = repl; break;
+        case 'L':
+          wp->special->latex = repl; break;
+        default:
+          abort ();
+        }
+    }
+  read_line ();
+}
+
+
+static void do_replace (const uchar *p)
+{
+  const uchar *q;
+  struct word *wp;
+  int len;
+  uchar word[512], *repl;
+
+  if (!out)
+    {
+      len = 0; q = p;
+      while (*p != 0 && !isspace (*p))
+        word[len++] = *p++;
+      word[len] = 0;
+      while (isspace (*p))
+        ++p;
+      if (*p == 0)
+        fatal ("%s:%d: Missing replacement", input_fname, line_no);
+      repl = xstrdup (p);
+      wp = word_add (word);
+      wp->repl = repl;
+    }
+  read_line ();
+}
+
+
+static void do_set (const uchar *p)
+{
+  int len, value;
+  uchar word[512];
+
+  len = 0;
+  if (!isalpha (*p))
+    fatal ("%s:%d: Invalid variable name", input_fname, line_no);
+  word[len++] = *p++;
+  while (isalnum (*p) || *p == '_')
+    word[len++] = *p++;
+  word[len] = 0;
+  if (!isspace (*p))
+    fatal ("%s:%d: Invalid variable name ", input_fname, line_no);
+  while (isspace (*p))
+    ++p;
+  if (strcmp (p, "false") == 0)
+    value = FALSE;
+  else if (strcmp (p, "true") == 0)
+    value = TRUE;
+  else
+    fatal ("%s:%d: Invalid value ", input_fname, line_no);
+  cond_set (word, value);
+  read_line ();
+}
+
+
+static void do_language (const uchar *p)
+{
+  if (!out)
+    {
+      if (strcmp (p, "english") == 0)
+        language = LANG_ENGLISH;
+      else if (strcmp (p, "german") == 0)
+        language = LANG_GERMAN;
+      else
+        fatal ("%s:%d: Invalid language", input_fname, line_no);
+    }
+  read_line ();
+}
+
+
+static void do_syntax (const uchar *p)
+{
+  if (strcmp (p, "emx") == 0)
+    language = SYNTAX_EMX;
+  else if (strcmp (p, "dvidrv") == 0)
+    language = SYNTAX_DVIDRV;
+  else
+    fatal ("%s:%d: Invalid syntax style", input_fname, line_no);
+  read_line ();
+}
+
+
+static void new_section (int level, unsigned flags)
+{
+  struct toc *tp;
+  int i;
+  uchar *d;
+
+  tp = xmalloc (sizeof (*tp));
+  tp->next = NULL;
+  tp->level = level;
+  tp->ref = ref_no++;
+  tp->print = FALSE;
+  tp->global = FALSE;
+  if (flags & HF_UNNUMBERED)
+    tp->number = NULL;
+  else
+    {
+      ++section_numbers[level-1];
+      for (i = level; i < SECTION_LEVELS; ++i)
+        section_numbers[i] = 0;
+      d = output;
+      for (i = 0; i < level; ++i)
+        {
+          if (i != 0)
+            *d++ = '.';
+          d += sprintf (d, "%d", section_numbers[i]);
+        }
+      i = strlen (output);
+      if (i > toc_indent)
+        toc_indent = i;
+      tp->number = xstrdup (output);
+    }
+  tp->title = NULL;
+  tp->flags = flags;
+  *toc_add = tp;
+  toc_add = &tp->next;
+  toc_ptr = tp;
+}
+
+
+static void do_heading_def (const uchar *p)
+{
+  if (tg_level > 0)
+    {
+      new_section (tg_level, tg_flags);
+      toc_ptr->print = TRUE;
+      toc_ptr->title = xstrdup (p);
+    }
+}
+
+static void do_heading_out (const uchar *p)
+{
+  check_copy ();
+  if (tg_level > 0)
+    {
+      toc_ptr = (toc_ptr == NULL ? toc_head : toc_ptr->next);
+      assert (toc_ptr != NULL);
+      assert (strcmp (p, toc_ptr->title) == 0);
+      if (toc_ptr->number == NULL)
+        output[0] = 0;
+      else
+        {
+          strcpy (output, toc_ptr->number);
+          strcat (output, " ");
+        }
+      switch (mode)
+        {
+        case 'H':
+          html_heading1 (toc_ptr->ref);
+          break;
+        case 'I':
+          ipf_heading1 (toc_ptr->level, toc_ptr->ref, toc_ptr->global,
+                        tg_flags);
+          break;
+        case 'L':
+          latex_heading1 ();
+          break;
+        case 'T':
+          text_heading1 ();
+          break;
+        }
+      strcat (output, p);
+    }
+  else
+    strcpy (output, p);
+  switch (mode)
+    {
+    case 'H':
+      html_heading2 (output);
+      break;
+    case 'I':
+      ipf_heading2 (output);
+      break;
+    case 'L':
+      latex_heading2 (p);
+      break;
+    case 'T':
+      text_heading2 (output);
+      break;
+    }
+  para_flag = TRUE;
+}
+
+
+static void do_toc_out (const uchar *p)
+{
+  struct toc *tp;
+  int i, len;
+
+  if (out && para_flag)
+    switch (mode)
+      {
+      case 'T':
+        write_nl ();
+        break;
+      }
+  para_flag = FALSE;
+  if (toc_head != NULL)
+    switch (mode)
+      {
+      case 'H':
+        html_toc_start ();
+        break;
+      case 'I':
+        ipf_toc_start ();
+        break;
+      }
+  for (tp = toc_head; tp != NULL; tp = tp->next)
+    if (tp->print)
+      {
+        if (tp->number == NULL)
+          len = 0;
+        else
+          {
+            len = strlen (tp->number);
+            memcpy (output, tp->number, len);
+          }
+        i = toc_indent + 2 * tp->level - len;
+        memset (output + len, ' ', i);
+        output[len+i] = 0;
+        switch (mode)
+          {
+          case 'H':
+            html_toc_line (output, tp);
+            break;
+          case 'I':
+            ipf_toc_line (output, tp);
+            break;
+          case 'T':
+            if (!(tp->flags & HF_UNNUMBERED))
+              text_toc_line (output, tp);
+            break;
+          }
+      }
+  if (mode == 'I' && toc_head != NULL)
+    ipf_toc_end ();
+  copy_flag = TRUE;
+}
+
+
+static void do_description (void)
+{
+  check_copy ();
+  para_flag = FALSE;
+  start_env (ENV_DESCRIPTION, 8, IPF_DESCRIPTION_INDENT);
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_description ();
+        break;
+      case 'I':
+        ipf_description ();
+        break;
+      case 'L':
+        latex_description ();
+        break;
+      }
+  read_line ();
+}
+
+
+static void do_enumerate (void)
+{
+  check_copy ();
+  para_flag = FALSE;
+  start_env (ENV_ENUMERATE, 4, 3);
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_enumerate ();
+        break;
+      case 'I':
+        ipf_enumerate ();
+        break;
+      case 'L':
+        latex_enumerate ();
+        break;
+      }
+  read_line ();
+}
+
+
+static void do_itemize (void)
+{
+  check_copy ();
+  para_flag = FALSE;
+  start_env (ENV_ITEMIZE, 2, 2);
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_itemize ();
+        break;
+      case 'I':
+        ipf_itemize ();
+        break;
+      case 'L':
+        latex_itemize ();
+        break;
+      }
+  read_line ();
+}
+
+
+static void do_indent (int env)
+{
+  check_copy ();
+  start_env (env, 4, 4);
+  ipf_env_margin (env_sp);
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_indent ();
+        break;
+      case 'L':
+        latex_indent ();
+        break;
+      }
+  read_line ();
+}
+
+
+static void do_list (void)
+{
+  check_copy ();
+  start_env (ENV_LIST, 4, 4);
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_list ();
+        break;
+      case 'L':
+        latex_description ();
+        break;
+      }
+  read_line ();
+}
+
+
+static void do_verbatim (enum tag tag_end)
+{
+  int start_line, tmargin;
+  const uchar *p;
+
+  check_copy ();
+  para_flag = FALSE;
+  start_line = line_no;
+  tmargin = env_stack[env_sp].tmargin;
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_verbatim_start (tag_end);
+        break;
+      case 'I':
+        ipf_verbatim_start (tag_end);
+        break;
+      case 'L':
+        latex_verbatim_start (tag_end);
+        break;
+      case 'T':
+        text_verbatim_start (tag_end, &tmargin);
+        break;
+      }
+  for (;;)
+    {
+      read_line ();
+      if (end_of_file)
+        switch (tag_end)
+          {
+          case TAG_ENDEXAMPLE:
+            fatal ("%s:%d: Missing %cendexample",
+                   input_fname, start_line, escape);
+            break;
+          case TAG_ENDHEADERS:
+            fatal ("%s:%d: Missing %cendheaders",
+                   input_fname, start_line, escape);
+            break;
+          case TAG_ENDSAMPLECODE:
+            fatal ("%s:%d: Missing %cendsamplecode",
+                   input_fname, start_line, escape);
+            break;
+          case TAG_ENDVERBATIM:
+            fatal ("%s:%d: Missing %cendverbatim",
+                   input_fname, start_line, escape);
+            break;
+          default:
+            abort ();
+          }
+      p = input;
+      if (parse_tag (&p) && tg_tag == tag_end)
+        break;
+      if (out)
+        {
+          switch (mode)
+            {
+            case 'H':
+              html_verbatim_line ();
+              break;
+            case 'I':
+              ipf_verbatim_line ();
+              break;
+            case 'L':
+            case 'T':
+              text_verbatim_line (tag_end, tmargin, compat);
+              break;
+            }
+        }
+    }
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_verbatim_end (tag_end);
+        break;
+      case 'I':
+        ipf_verbatim_end (tag_end);
+        break;
+      case 'L':
+        latex_verbatim_end (tag_end);
+        break;
+      case 'T':
+        para_flag = TRUE;
+        break;
+      }
+  read_line ();
+}
+
+
+static void do_table (const uchar *p)
+{
+  int start_line, tmargin, wn;
+  int do_indent;
+  uchar word[512], *d;
+  int widths[20];
+  char *tmp;
+  long n;
+
+  check_copy ();
+  para_flag = FALSE;
+  start_line = line_no;
+  tmargin = env_stack[env_sp].tmargin;
+  do_indent = FALSE; wn = 0;
+  while (*p != 0)
+    {
+      d = word;
+      while (*p != 0 && !isspace (*p))
+        *d++ = *p++;
+      *d = 0;
+      if (strcmp (word, "indent") == 0)
+        do_indent = TRUE;
+      else if (isdigit (word[0]))
+        {
+          errno = 0;
+          n = strtol (word, &tmp, 10);
+          if (errno != 0 || *tmp != 0)
+            fatal ("%s:%d: Invalid %ctable width",
+                   input_fname, line_no, escape);
+          widths[wn++] = (int)n;
+        }
+      else
+        fatal ("%s:%d: Invalid %ctable attribute",
+               input_fname, line_no, escape);
+      while (isspace (*p))
+        ++p;
+    }
+
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        fatal ("%ctable not yet implemented for HTML", escape);
+      case 'I':
+        ipf_table_start (do_indent, widths, wn);
+        break;
+      case 'L':
+        fatal ("%ctable not yet implemented for LaTeX", escape);
+      case 'T':
+        text_table_start (do_indent, &tmargin);
+        break;
+      }
+  for (;;)
+    {
+      read_line ();
+      if (end_of_file)
+        fatal ("%s:%d: Missing %cendtable", input_fname, start_line, escape);
+      p = input;
+      if (parse_tag (&p))
+        {
+          if (tg_tag == TAG_ENDTABLE)
+            break;
+          fatal ("%s%d: %cendtable expected", input_fname, line_no, escape);
+        }
+      if (out)
+        {
+          p = input;
+          while (isspace (*p))
+            ++p;
+          switch (mode)
+            {
+            case 'I':
+              ipf_table_line (p, wn);
+              break;
+            case 'T':
+              text_table_line (p, tmargin);
+              break;
+            }
+        }
+    }
+  if (out)
+    switch (mode)
+      {
+      case 'I':
+        ipf_table_end (do_indent);
+        break;
+      case 'T':
+        para_flag = TRUE;
+        break;
+      }
+  read_line ();
+}
+
+
+static void do_ipf (void)
+{
+  int start_line;
+  const uchar *p;
+
+  start_line = line_no;
+  for (;;)
+    {
+      read_line ();
+      if (end_of_file)
+        fatal ("%s:%d: Missing %cendipf", input_fname, start_line, escape);
+      p = input;
+      if (parse_tag (&p) && tg_tag == TAG_ENDIPF)
+        break;
+      if (out && mode == 'I' && output_flag)
+        {
+          fprintf (output_file, "%s\n", input);
+          output_x = 0; ++output_line_no;
+        }
+    }
+  read_line ();
+}
+
+
+static void do_text (void)
+{
+  int start_line;
+  const uchar *p;
+
+  start_line = line_no;
+  for (;;)
+    {
+      read_line ();
+      if (end_of_file)
+        fatal ("%s:%d: Missing %cendtext", input_fname, start_line, escape);
+      p = input;
+      if (parse_tag (&p) && tg_tag == TAG_ENDTEXT)
+        break;
+      if (out && mode == 'T' && output_flag)
+        {
+          fprintf (output_file, "%s\n", input);
+          output_x = 0; ++output_line_no;
+        }
+    }
+  read_line ();
+}
+
+
+static void do_latex (void)
+{
+  int start_line;
+  const uchar *p;
+
+  start_line = line_no;
+  for (;;)
+    {
+      read_line ();
+      if (end_of_file)
+        fatal ("%s:%d: Missing %cendlatex", input_fname, start_line, escape);
+      p = input;
+      if (parse_tag (&p) && tg_tag == TAG_ENDLATEX)
+        break;
+      if (out && mode == 'L' && output_flag)
+        {
+          fprintf (output_file, "%s\n", input);
+          output_x = 0; ++output_line_no;
+        }
+    }
+  read_line ();
+}
+
+
+static void do_html (void)
+{
+  int start_line;
+  const uchar *p;
+
+  start_line = line_no;
+  for (;;)
+    {
+      read_line ();
+      if (end_of_file)
+        fatal ("%s:%d: Missing %cendhtml", input_fname, start_line, escape);
+      p = input;
+      if (parse_tag (&p) && tg_tag == TAG_ENDHTML)
+        break;
+      if (out && mode == 'H' && output_flag)
+        {
+          fprintf (output_file, "%s\n", input);
+          output_x = 0; ++output_line_no;
+        }
+    }
+  read_line ();
+}
+
+
+static void do_label (const uchar *p)
+{
+  if (!out)
+    {
+      if (toc_ptr == NULL)
+        fatal ("%s:%d: Cannot use %clabel before %ch1",
+               input_fname, line_no, escape, escape);
+      define_label (p, toc_ptr->ref, "Label");
+    }
+  read_line ();
+}
+
+
+static void do_index (const uchar *p)
+{
+  if (toc_ptr == NULL)
+    fatal ("%s:%d: Cannot use %cindex before %ch1",
+           input_fname, line_no, escape, escape);
+  switch (mode)
+    {
+    case 'H':
+      html_index (toc_ptr, p, tg_level);
+      break;
+    case 'I':
+      ipf_index (p);
+      break;
+    case 'L':
+      latex_index (p, tg_level);
+      break;
+    }
+  read_line ();
+}
+
+
+static void do_keyword (const uchar *p)
+{
+  switch (mode)
+    {
+    case 'K':
+      keywords_keyword (p);
+      break;
+    }
+  read_line ();
+}
+
+
+static void do_item (const uchar *p)
+{
+  switch (env_stack[env_sp].env)
+    {
+    case ENV_DESCRIPTION:
+      para_flag = FALSE;
+      if (out)
+        switch (mode)
+          {
+          case 'H':
+            html_description_item (p);
+            break;
+          case 'I':
+            ipf_description_item (p);
+            break;
+          case 'L':
+            latex_description_item (p);
+            break;
+          case 'T':
+            text_description_item (p);
+            break;
+          }
+      break;
+    case ENV_ENUMERATE:
+      para_flag = FALSE;
+      if (*p != 0)
+        fatal ("%s:%d: %citem of %cenumerate doesn't take an argument",
+               input_fname, line_no, escape, escape);
+      if (out)
+        switch (mode)
+          {
+          case 'H':
+            html_enumerate_item ();
+            break;
+          case 'I':
+            ipf_enumerate_item ();
+            break;
+          case 'L':
+            latex_enumerate_item ();
+            break;
+          case 'T':
+            text_enumerate_item ();
+            break;
+          }
+      break;
+    case ENV_ITEMIZE:
+      para_flag = FALSE;
+      if (*p != 0)
+        fatal ("%s:%d: %citem of %citemize doesn't take an argument",
+               input_fname, line_no, escape, escape);
+      if (out)
+        switch (mode)
+          {
+          case 'H':
+            html_itemize_item ();
+            break;
+          case 'I':
+            ipf_itemize_item ();
+            break;
+          case 'L':
+            latex_itemize_item ();
+            break;
+          case 'T':
+            text_itemize_item ();
+            break;
+          }
+      break;
+    case ENV_LIST:
+      para_flag = FALSE;
+      if (out)
+        switch (mode)
+          {
+          case 'H':
+            html_list_item (p);
+            break;
+          case 'I':
+            ipf_list_item (p);
+            break;
+          case 'L':
+            latex_list_item (p);
+            break;
+          case 'T':
+            text_list_item (p);
+            break;
+          }
+      break;
+    default:
+      fatal ("%s:%d: %citem outside environment",
+             input_fname, line_no, escape);
+    }
+  read_line ();
+}
+
+
+static void do_prototype (void)
+{
+  int start_line, tmargin;
+  const uchar *p;
+  struct element *ep;
+
+  start_line = line_no;
+  tmargin = env_stack[env_sp].tmargin;
+  prototype_flag = TRUE;
+  if (out)
+    {
+      make_elements_start ();
+      switch (mode)
+        {
+        case 'H':
+          html_prototype_start ();
+          break;
+        case 'I':
+          ipf_prototype_start ();
+          break;
+        case 'L':
+          latex_prototype_start ();
+          break;
+        case 'T':
+          text_prototype_start (compat);
+          break;
+        }
+    }
+  for (;;)
+    {
+      read_line ();
+      if (end_of_file)
+        fatal ("%s:%d: Missing %cendprototype",
+               input_fname, start_line, escape);
+      p = input;
+      if (parse_tag (&p))
+        {
+          if (tg_tag == TAG_ENDPROTOTYPE)
+            break;
+          else
+            fatal ("%s:%d: %cendprototype expected",
+                   input_fname, line_no, escape);
+        }
+      if (out)
+        {
+          make_elements_internal (input);
+          ep = add_element ();
+          ep->el = EL_BREAK;
+          ep->n = 1;
+        }
+    }
+  if (out)
+    {
+      make_elements_end ();
+      switch (mode)
+        {
+        case 'H':
+          html_prototype_end (compat);
+          break;
+        case 'I':
+          ipf_prototype_end (compat);
+          break;
+        case 'L':
+          latex_prototype_end (compat);
+          break;
+        case 'T':
+          text_prototype_end ();
+          break;
+        }
+    }
+  prototype_flag = FALSE;
+  para_flag = TRUE;
+  read_line ();
+}
+
+
+static void do_see_also (const uchar *p)
+{
+  uchar word[512], *d, *o;
+
+  if (out)
+    {
+      while (isspace (*p))
+        ++p;
+      o = output; *o = 0;
+      switch (mode)
+        {
+        case 'H':
+          html_see_also_start ();
+          break;
+        case 'I':
+          ipf_see_also_start ();
+          break;
+        case 'L':
+          latex_see_also_start ();
+          break;
+        case 'T':
+          text_see_also_start ();
+          break;
+        }
+      while (*p != 0)
+        {
+          d = word;
+          while (*p != 0 && !isspace (*p))
+            *d++ = *p++;
+          *d = 0;
+          while (isspace (*p))
+            ++p;
+          switch (mode)
+            {
+            case 'H':
+              html_see_also_word (word, p);
+              break;
+            case 'I':
+              ipf_see_also_word (word, p);
+              break;
+            case 'L':
+              latex_see_also_word (word, p);
+              break;
+            case 'T':
+              strcpy (o, word);
+              if (*p != 0)
+                strcat (o, ", ");
+              o = strchr (o, 0);
+              break;
+            }
+        }
+      switch (mode)
+        {
+        case 'T':
+          text_see_also_end (output);
+          break;
+        }
+      para_flag = TRUE;
+    }
+  read_line ();
+}
+
+
+static void do_param (const uchar *p)
+{
+  uchar word[512], *d;
+  struct word *wp;
+
+  if (out)
+    {
+      while (*p != 0)
+        {
+          d = word;
+          while (*p != 0 && !isspace (*p))
+            *d++ = *p++;
+          *d = 0;
+          while (isspace (*p))
+            ++p;
+          wp = word_add (word);
+          local_add (wp);
+          wp->style = STYLE_PARAM;
+        }
+    }
+  read_line ();
+}
+
+
+static void do_sample_file (const uchar *p)
+{
+  if (out)
+    {
+      while (isspace (*p))
+        ++p;
+      switch (mode)
+        {
+        case 'H':
+          html_sample_file (p);
+          break;
+        case 'I':
+          ipf_sample_file (p);
+          break;
+        case 'L':
+          latex_sample_file (p);
+          break;
+        case 'T':
+          text_sample_file (p);
+          break;
+        }
+    }
+  read_line ();
+}
+
+
+static void do_libref_section (const uchar *text)
+{
+  if (out)
+    {
+      switch (mode)
+        {
+        case 'H':
+          html_libref_section (text);
+          break;
+        case 'I':
+          ipf_libref_section (text);
+          break;
+        case 'L':
+          latex_libref_section (text);
+          break;
+        case 'T':
+          text_libref_section (text);
+          break;
+        }
+    }
+  read_line ();
+}
+
+
+static void do_function (const uchar *p)
+{
+  uchar word[512], *d, *o;
+  struct word *wp;
+
+  local_end ();
+  local_begin ();
+  if (out)
+    {
+      toc_ptr = (toc_ptr == NULL ? toc_head : toc_ptr->next);
+      assert (toc_ptr != NULL);
+      switch (mode)
+        {
+        case 'H':
+          html_function_start (toc_ptr);
+          break;
+        case 'I':
+          ipf_function_start (toc_ptr);
+          break;
+        case 'L':
+          latex_function_start (toc_ptr);
+          break;
+        case 'T':
+          text_function ();
+          break;
+        }
+      para_flag = FALSE;
+    }
+  else
+    new_section (2, 0);
+
+  o = output; *o = 0; function_count = 0;
+  while (isspace (*p))
+    ++p;
+  while (*p != 0)
+    {
+      ++function_count;
+      d = word;
+      while (*p != 0 && !isspace (*p))
+        *d++ = *p++;
+      *d = 0;
+      while (isspace (*p))
+        ++p;
+      switch (mode)
+        {
+        case 'H':
+          html_function_function (toc_ptr, word);
+          break;
+        case 'I':
+          ipf_function_function (word);
+          break;
+        case 'L':
+          latex_function_function (word);
+          break;
+        }
+      if (!out)
+        {
+          wp = define_label (word, toc_ptr->ref, "Function");
+          /* Don't set format of variables, timezone! */
+          if (strstr (word, "()") != NULL)
+            wp->style = STYLE_TTY;
+          if (o != output)
+            {
+              if (*p == 0)
+                strcpy (o, " and ");
+              else
+                strcpy (o, ", ");
+            }
+          strcat (o, word);
+          o = strchr (o, 0);
+          switch (mode)
+            {
+            case 'K':
+              write_keyword (word);
+              break;
+            }
+        }
+    }
+  if (!out)
+    toc_ptr->title = xstrdup (output);
+  read_line ();
+}
+
+
+static void do_compat (const uchar *p)
+{
+  while (isspace (*p))
+    ++p;
+  strcpy (compat, p);
+  read_line ();
+}
+
+
+static void do_tag (const uchar *p)
+{
+  switch (tg_tag)
+    {
+    case TAG_HEADING:
+      local_end ();
+      if (out)
+        do_heading_out (p);
+      else
+        {
+          if (env_sp != 0)
+            nonfatal ("%s:%d: Heading within environment",
+                      input_fname, line_no);
+          do_heading_def (p);
+        }
+      read_line ();
+      break;
+
+    case TAG_TOC:
+      if (out)
+        do_toc_out (p);
+      read_line ();
+      break;
+
+    case TAG_HTMLFRAGMENT:
+      if (out && mode == 'H')
+        html_fragment (p);
+      read_line ();
+      break;
+
+    case TAG_IPFMINITOC:
+      if (out && mode == 'I')
+        ipf_minitoc (toc_ptr);
+      read_line ();
+      break;
+
+    case TAG_HTMLMINITOC:
+      if (out && mode == 'H')
+        html_minitoc (toc_ptr);
+      read_line ();
+      break;
+
+    case TAG_MINITOC:
+      if (out)
+        switch (mode)
+          {
+          case 'H':
+            html_minitoc (toc_ptr);
+            break;
+          case 'I':
+            ipf_minitoc (toc_ptr);
+            break;
+          }
+      read_line ();
+      break;
+
+    case TAG_TITLE:
+      if (!out)
+        title = xstrdup (p);
+      read_line ();
+      break;
+
+    case TAG_LANGUAGE:
+      do_language (p);
+      break;
+
+    case TAG_SYNTAX:
+      do_syntax (p);
+      break;
+
+    case TAG_ITEM:
+      do_item (p);
+      break;
+
+    case TAG_IPF:
+      do_ipf ();
+      break;
+
+    case TAG_TEXT:
+      do_text ();
+      break;
+
+    case TAG_LATEX:
+      do_latex ();
+      break;
+
+    case TAG_HTML:
+      do_html ();
+      break;
+
+    case TAG_LABEL:
+      do_label (p);
+      break;
+
+    case TAG_INDEX:
+      do_index (p);
+      break;
+
+    case TAG_KEYWORD:
+      do_keyword (p);
+      break;
+
+    case TAG_FORMAT:
+      do_format (p);
+      break;
+
+    case TAG_SPECIAL:
+      do_special (p);
+      break;
+
+    case TAG_REPLACE:
+      do_replace (p);
+      break;
+
+    case TAG_SET:
+      do_set (p);
+      break;
+
+    case TAG_DESCRIPTION:
+      do_description ();
+      break;
+
+    case TAG_ENDDESCRIPTION:
+      do_end_env (ENV_DESCRIPTION);
+      break;
+
+    case TAG_ENUMERATE:
+      do_enumerate ();
+      break;
+
+    case TAG_ENDENUMERATE:
+      do_end_env (ENV_ENUMERATE);
+      break;
+
+    case TAG_ITEMIZE:
+      do_itemize ();
+      break;
+
+    case TAG_ENDITEMIZE:
+      do_end_env (ENV_ITEMIZE);
+      break;
+
+    case TAG_LIST:
+      do_list ();
+      break;
+
+    case TAG_ENDLIST:
+      do_end_env (ENV_LIST);
+      break;
+
+    case TAG_INDENT:
+      do_indent (ENV_INDENT);
+      break;
+
+    case TAG_ENDINDENT:
+      do_end_env (ENV_INDENT);
+      break;
+
+    case TAG_TYPEWRITER:
+      do_indent (ENV_TYPEWRITER);
+      break;
+
+    case TAG_ENDTYPEWRITER:
+      do_end_env (ENV_TYPEWRITER);
+      break;
+
+    case TAG_EXAMPLE:
+      do_verbatim (TAG_ENDEXAMPLE);
+      break;
+
+    case TAG_SAMPLECODE:
+      do_verbatim (TAG_ENDSAMPLECODE);
+      break;
+
+    case TAG_HEADERS:
+      do_verbatim (TAG_ENDHEADERS);
+      break;
+
+    case TAG_PROTOTYPE:
+      do_prototype ();
+      break;
+
+    case TAG_VERBATIM:
+      do_verbatim (TAG_ENDVERBATIM);
+      break;
+
+    case TAG_TABLE:
+      do_table (p);
+      break;
+
+    case TAG_SEEALSO:
+      do_see_also (p);
+      break;
+
+    case TAG_FUNCTION:
+      do_function (p);
+      break;
+
+    case TAG_PARAM:
+      do_param (p);
+      break;
+
+    case TAG_COMPAT:
+      do_compat (p);
+      break;
+
+    case TAG_SAMPLEFILE:
+      do_sample_file (p);
+      break;
+
+    case TAG_RESTRICTIONS:
+      do_libref_section ("Restrictions");
+      break;
+
+    case TAG_IMPLEMENTATION:
+      do_libref_section ("Implementation-defined behavior");
+      break;
+
+    case TAG_BUGS:
+      do_libref_section ("Bugs");
+      break;
+
+    case TAG_ERRORS:
+      do_libref_section ("Errors");
+      break;
+
+    case TAG_HINTS:
+      do_libref_section ("Hints");
+      break;
+
+    case TAG_RETURNVALUE:
+      do_libref_section ("Return value");
+      break;
+
+    default:
+      fatal ("%s:%d: Unexpected tag", input_fname, line_no);
+    }
+}
+
+
+static void do_copy (void)
+{
+  size_t len;
+  const uchar *p;
+  int space, col1_warn;
+
+  line_len = 0; space = FALSE; col1_warn = FALSE;
+  do
+    {
+      if (out)
+        {
+          p = input;
+          while (isspace (*p))
+            ++p;
+          if (p == input && !col1_warn)
+            {
+              col1_warn = TRUE;
+              warning (1, "%s:%d: Text starting in first column",
+                       input_fname, line_no);
+            }
+          len = strlen (p);
+          while (len > 0 && isspace (p[len-1]))
+            --len;
+          if (len > 0)
+            {
+              if (space)
+                line_add (" ", 1);
+              line_add (p, len);
+            }
+          space = TRUE;
+        }
+      read_line ();
+      p = input;
+    } while (!end_of_file && input[0] != 0 && !parse_tag (&p));
+  if (out)
+    {
+      make_elements (line);
+      switch (mode)
+        {
+        case 'H':
+          html_copy ();
+          break;
+        case 'I':
+          ipf_copy ();
+          break;
+        case 'L':
+          latex_copy ();
+          break;
+        case 'T':
+          text_copy ();
+          break;
+        }
+    }
+  para_flag = TRUE; copy_flag = TRUE;
+}
+
+
+static void do_empty_line (void)
+{
+  read_line ();
+}
+
+
+void start_index (void)
+{
+  const char *text = "Index";
+  local_end ();
+  tg_level = 1; tg_flags = 0;
+  if (out)
+    do_heading_out (text);
+  else
+    do_heading_def (text);
+}
+
+
+static void init (void)
+{
+  word_top = wt_new (997);
+}
+
+
+void init_file (void)
+{
+  int i;
+
+  for (i = 0; i < SECTION_LEVELS; ++i)
+    section_numbers[i] = 0;
+  toc_ptr = NULL;
+
+  if (out)
+    switch (mode)
+      {
+      case 'H':
+        html_start ();
+        break;
+      case 'I':
+        ipf_start ();
+        break;
+      case 'L':
+        latex_start ();
+        break;
+      }
+
+  para_flag = FALSE;
+  env_sp = 0;
+  env_stack[env_sp].env = ENV_NONE;
+  env_stack[env_sp].tmargin = 0;
+  env_stack[env_sp].imargin = 1;
+  env_stack[env_sp].start_line = 0;
+  local_sp = 0;
+  hl_ipf = 0;
+  hl_ipf_no = 0;
+  hl_sp = 0;
+  hl_stack[hl_sp] = 0;
+  output_x = 0; output_line_no = 1;
+  compat[0] = 0;
+  syntax_style = SYNTAX_EMX;
+  copy_flag = TRUE;
+}
+
+
+static void end_file (void)
+{
+  switch (mode)
+    {
+    case 'H':
+      html_end ();
+      break;
+    case 'I':
+      ipf_end ();
+      break;
+    case 'L':
+      latex_end ();
+      break;
+    }
+  if (env_sp != 0)
+    fatal ("%s:%d: Environment not terminated",
+           input_fname, env_stack[env_sp].start_line);
+}
+
+
+static void read_file (const char *name)
+{
+  const uchar *p;
+
+  if (xref_fname != NULL)
+    read_xref (xref_fname, toc_head);
+  open_input (name);
+  init_file ();
+  read_line ();
+  while (!end_of_file)
+    {
+      p = input;
+      if (input[0] == 0)
+        do_empty_line ();
+      else if (parse_tag (&p))
+        do_tag (p);
+      else
+        do_copy ();
+    }
+  end_file ();
+  fclose (input_file);
+}
+
+
+static void cleanup (void)
+{
+  if (output_fname != NULL && output_file != stdout && output_file != NULL)
+    {
+      fclose (output_file);
+      output_file = NULL;
+      remove (output_fname);
+      output_fname = NULL;
+    }
+}
+
+
+static int opt_number (void)
+{
+  int result;
+  char *tmp;
+
+  errno = 0;
+  result = (int)strtol (optarg, &tmp, 0);
+  if (errno != 0 || *tmp != 0)
+    usage ();
+  return result;
+}
+
+static enum enc opt_encoding (void)
+{
+  if (strcmp (optarg, "cp850") == 0)
+    return ENC_CP850;
+  else if (strcmp (optarg, "iso8859-1") == 0)
+    return ENC_ISO8859_1;
+  else
+    fatal ("Invalid encoding: %s", optarg);
+}
+
+int main (int argc, char *argv[])
+{
+  int c, i;
+
+  init ();
+
+  while ((c = getopt (argc, argv, ":?HIKLMTab:ce:fgh:i:j:n:o:rw:x:")) != EOF)
+    switch (c)
+      {
+      case '?':
+        usage ();
+      case 'H':
+      case 'I':
+      case 'K':
+      case 'L':
+      case 'M':
+      case 'T':
+        mode = (char)c;
+        break;
+      case 'a':
+        opt_a = TRUE;
+        break;
+      case 'b':
+        opt_b = opt_number ();
+        if (opt_b < 0 || opt_b > 1)
+          fatal ("Invalid argument for -b (line breaking algorithm)");
+        break;
+      case 'c':
+        opt_c = TRUE;
+        break;
+      case 'e':
+        if (strlen (optarg) == 1 && !isdigit ((uchar)*optarg))
+          escape = *optarg;
+        else
+          {
+            i = opt_number ();
+            if (i < 1 || i > 255)
+              fatal ("Invalid argument for -e (escape character)");
+            escape = (uchar)i;
+          }
+        break;
+      case 'f':
+        opt_f = TRUE;
+        break;
+      case 'g':
+        opt_g = TRUE;
+        break;
+      case 'h':
+        hyphenation_fname = optarg;
+        break;
+      case 'i':
+        input_encoding = opt_encoding ();
+        break;
+      case 'j':
+        output_encoding = opt_encoding ();
+        break;
+      case 'n':
+        ref_no = opt_number ();
+        break;
+      case 'o':
+        output_fname = optarg;
+        break;
+      case 'r':
+        opt_r = TRUE;
+        break;
+      case 'w':
+        opt_w = opt_number ();
+        break;
+      case 'x':
+        xref_fname = optarg;
+        break;
+      case ':':
+        fatal ("Missing argument for option -%c", optopt);
+      default:
+        fatal ("Invalid option: -%c", optopt);
+      }
+
+  if (mode == 0)
+    usage ();
+  if (mode != 'I' && (opt_c || opt_g))
+    usage ();
+  if (mode != 'I' && mode != 'H' && xref_fname != NULL)
+    usage ();
+  if ((mode == 'H' || mode == 'I') && output_encoding != ENC_DEFAULT)
+    warning (0, "Output encoding ignored for -H and -I");
+
+  argv += optind;
+  argc -= optind;
+
+  if (argc != 1 && mode != 'M')
+    usage ();
+
+  atexit (cleanup);
+
+  switch (mode)
+    {
+    case 'T':
+      max_width = 79;
+      output_flag = TRUE;
+      if (hyphenation_fname != NULL)
+        text_hyphenation (hyphenation_fname);
+      if (output_encoding == ENC_DEFAULT)
+        output_encoding = input_encoding;
+      break;
+    case 'I':
+      max_width = 250;
+      output_flag = !opt_g;
+      output_encoding = ENC_CP850;
+      break;
+    case 'H':
+      max_width = 4096;
+      output_flag = TRUE;
+      output_encoding = ENC_ISO8859_1;
+      break;
+    case 'L':
+      max_width = 4096;
+      output_flag = TRUE;
+      if (output_encoding == ENC_DEFAULT)
+        output_encoding = input_encoding;
+      break;
+    case 'K':
+    case 'M':
+      output_flag = FALSE;
+      if (output_encoding == ENC_DEFAULT)
+        output_encoding = input_encoding;
+      break;
+    default:
+      abort ();
+    }
+
+  if (output_fname == NULL)
+    {
+      output_fname = "<stdout>";
+      output_file = stdout;
+    }
+  else
+    {
+      if (opt_r)
+        {
+          chmod (output_fname, 0666);
+          remove (output_fname);
+        }
+      output_file = fopen (output_fname, "wt");
+      if (output_file == NULL)
+        {
+          perror (output_fname);
+          return 1;
+        }
+    }
+
+  switch (mode)
+    {
+    case 'H':
+    case 'I':
+    case 'T':
+    case 'L':
+      out = FALSE;
+      read_file (argv[0]);
+      out = TRUE;
+      read_file (argv[0]);
+      break;
+    case 'K':
+      keywords_start (argv[0]);
+      out = FALSE;
+      read_file (argv[0]);
+      break;
+    case 'M':
+      out = FALSE;
+      for (i = 0; i < argc; ++i)
+        make_global (argv[i]);
+      out = TRUE;
+      for (i = 0; i < argc; ++i)
+        make_global (argv[i]);
+      break;
+    }
+
+  if (fflush (output_file) != 0 || fclose (output_file) != 0)
+    {
+      perror (output_fname);
+      return 1;
+    }
+  output_file = NULL;
+
+  if (opt_r)
+    chmod (output_fname, 0444);
+
+  return history;
+}
Index: trunk/src/emx/src/emxdoc/emxdoc.h
===================================================================
--- trunk/src/emx/src/emxdoc/emxdoc.h	(revision 18)
+++ trunk/src/emx/src/emxdoc/emxdoc.h	(revision 18)
@@ -0,0 +1,372 @@
+/* emxdoc.h -- Global header file
+   Copyright (c) 1993-1999 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#if !defined (EXTERN)
+#define EXTERN extern
+#define INIT(X)
+#endif
+
+#define FALSE 0
+#define TRUE  1
+
+#define ENV_STACK_SIZE          8
+#define HL_STACK_SIZE           8
+#define STYLE_STACK_SIZE        8
+#define SECTION_LEVELS          3
+
+#define HL_BF                   0x01
+#define HL_SL                   0x02
+#define HL_TT                   0x04
+#define HL_UL                   0x08
+#define HL_EM                   0x10
+
+#define HF_UNNUMBERED           0x01
+#define HF_HIDE                 0x02
+
+/* Flag bits for the `flags' field of struct word. */
+
+#define WF_ABBREV               0x01
+
+#ifdef __GNUC__
+#define PRINTF(x,y) __attribute__ ((format (printf, x, y)))
+#define NORETURN2 __attribute__ ((noreturn))
+#else
+#define PRINTF(x,y)
+#define NORETURN2
+#endif
+
+typedef unsigned char uchar;
+
+enum tag
+{
+  TAG_HEADING,
+  TAG_TOC,
+  TAG_TITLE,
+  TAG_IPF,
+  TAG_ENDIPF,
+  TAG_ITEM,
+  TAG_SAMPLECODE,
+  TAG_ENDSAMPLECODE,
+  TAG_VERBATIM,
+  TAG_ENDVERBATIM,
+  TAG_EXAMPLE,
+  TAG_ENDEXAMPLE,
+  TAG_HEADERS,
+  TAG_ENDHEADERS,
+  TAG_PROTOTYPE,
+  TAG_ENDPROTOTYPE,
+  TAG_DESCRIPTION,
+  TAG_ENDDESCRIPTION,
+  TAG_ENUMERATE,
+  TAG_ENDENUMERATE,
+  TAG_ITEMIZE,
+  TAG_ENDITEMIZE,
+  TAG_LIST,
+  TAG_ENDLIST,
+  TAG_INDENT,
+  TAG_ENDINDENT,
+  TAG_TYPEWRITER,
+  TAG_ENDTYPEWRITER,
+  TAG_TABLE,
+  TAG_ENDTABLE,
+  TAG_LABEL,
+  TAG_TEXT,
+  TAG_ENDTEXT,
+  TAG_LATEX,
+  TAG_ENDLATEX,
+  TAG_HTML,
+  TAG_ENDHTML,
+  TAG_FORMAT,
+  TAG_STYLE,
+  TAG_REF,
+  TAG_HPT,
+  TAG_BREAK,
+  TAG_INDEX,
+  TAG_KEYWORD,
+  TAG_FUNCTION,
+  TAG_SEEALSO,
+  TAG_COMPAT,
+  TAG_SAMPLEFILE,
+  TAG_RESTRICTIONS,
+  TAG_IMPLEMENTATION,
+  TAG_BUGS,
+  TAG_RETURNVALUE,
+  TAG_PARAM,
+  TAG_LANGUAGE,
+  TAG_SYNTAX,
+  TAG_IPFMINITOC,
+  TAG_HTMLMINITOC,
+  TAG_MINITOC,
+  TAG_HTMLFRAGMENT,
+  TAG_SPECIAL,
+  TAG_FULLSTOP,
+  TAG_SET,
+  TAG_REPLACE,
+  TAG_ERRORS,
+  TAG_HINTS
+};
+
+enum style
+{
+  STYLE_NORMAL,
+  STYLE_BOLD,
+  STYLE_TTY,
+  STYLE_UNDERLINE,
+  STYLE_SLANTED,
+  STYLE_SYNTAX,
+  STYLE_PARAM,
+  STYLE_EMPHASIZE
+};
+
+enum el
+{
+  EL_END,
+  EL_WORD,
+  EL_PUNCT,
+  EL_SPACE,
+  EL_STYLE,
+  EL_ENDSTYLE,
+  EL_REF,
+  EL_BREAK
+};
+
+enum env
+{
+  ENV_NONE,
+  ENV_ENUMERATE,
+  ENV_ITEMIZE,
+  ENV_DESCRIPTION,
+  ENV_LIST,
+  ENV_INDENT,
+  ENV_TYPEWRITER
+};
+
+enum lang
+{
+  LANG_ENGLISH,
+  LANG_GERMAN
+};
+
+enum syntax
+{
+  SYNTAX_EMX,
+  SYNTAX_DVIDRV
+};
+
+struct special
+{
+  uchar *text;
+  uchar *ipf;
+  uchar *latex;
+  uchar *html;
+};
+
+struct word
+{
+  struct word *next;
+  struct word *database;
+  enum style style;
+  uchar *str;
+  uchar *repl;
+  struct special *special;
+  struct word_table *subidx;
+  int ref, idx;
+  uchar flags;
+};
+
+struct word_table;
+
+struct element
+{
+  enum el el;
+  int n;
+  struct word *wp;
+};
+
+struct environment
+{
+  enum env env;
+  int tmargin;
+  int imargin;
+  int start_line;
+  int counter;
+};
+
+struct toc
+{
+  struct toc *next;
+  int level;
+  int ref;
+  int print;
+  int global;
+  unsigned flags;
+  uchar *number;
+  uchar *title;
+};
+
+enum enc { ENC_DEFAULT = -3, ENC_AMBIGUOUS = -2, ENC_UNSUPPORTED = -1,
+           ENC_CP850 = 0, ENC_ISO8859_1, ENCODINGS };
+
+/* This is the escape character. */
+EXTERN uchar escape INIT (0xfe);
+
+/* The current input line number. */
+EXTERN int line_no INIT (0);
+
+/* The current input line. */
+EXTERN uchar input[256];
+
+/* The input encoding. */
+EXTERN enum enc input_encoding INIT (ENC_DEFAULT);
+
+/* The output encoding. */
+EXTERN enum enc output_encoding INIT (ENC_DEFAULT);
+
+/* This is the processing mode. */
+EXTERN char mode INIT (0);
+
+/* Concatenate instead of call .inf files */
+EXTERN int opt_a INIT (FALSE);
+
+/* Select line break algorithm for text output. */
+EXTERN int opt_b INIT (0);
+
+/* Use color instead of slanted type. */
+EXTERN int opt_c INIT (FALSE);
+
+/* French spacing. */
+EXTERN int opt_f INIT (FALSE);
+
+/* Gather global information. */
+EXTERN int opt_g INIT (FALSE);
+
+/* Display warning messages. */
+EXTERN int opt_w INIT (0);
+
+EXTERN const char *input_fname INIT (NULL);
+
+/* The input stream. */
+EXTERN FILE *input_file INIT (NULL);
+
+/* Non-zero if the end of the input file has been reached. */
+EXTERN int end_of_file INIT (FALSE);
+
+/* The output stream. */
+EXTERN FILE *output_file INIT (NULL);
+
+/* The global table of words. */
+EXTERN struct word_table *word_top INIT (NULL);
+
+EXTERN int hl_stack[HL_STACK_SIZE];
+EXTERN int hl_sp;
+
+/* Current line number of the output file. */
+EXTERN int output_line_no;
+
+/* Current column number of the output file. */
+EXTERN int output_x;
+
+/* Non-zero when writing output file (second pass). */
+EXTERN int out;
+
+/* Non-zero while formatting a prototype. */
+EXTERN int prototype_flag INIT (FALSE);
+
+/* The stack of nested environments. */
+EXTERN struct environment env_stack[ENV_STACK_SIZE];
+
+/* Stack pointer for stack of nested environments. */
+EXTERN int env_sp;
+
+/* Current list of formatting elements. */
+EXTERN struct element *elements INIT (NULL);
+
+/* Non-zero if a new paragraph should be started. */
+EXTERN int para_flag;
+
+/* Number of functions. */
+EXTERN int function_count;
+
+/* ... */
+EXTERN int ref_no INIT (1);
+
+/* ... */
+EXTERN int idx_no INIT (0);
+
+/* The title of the document. */
+EXTERN uchar *title INIT (NULL);
+
+/* The language of the document. */
+EXTERN enum lang language INIT (LANG_ENGLISH);
+
+/* Current tag: the tag. */
+EXTERN enum tag tg_tag;
+
+/* Current tag: style. */
+EXTERN enum style tg_style;
+
+/* Current tag: level (for h-, h=, h1 through h3, i1, i2 and index). */
+EXTERN int tg_level;
+
+/* Current tag: character for underlining (for h-, h= and h1 through h3). */
+EXTERN int tg_underline;
+
+/* Current tag: flags (such as HF_UNNUMBERED). */
+EXTERN unsigned tg_flags;
+
+
+void fatal (const char *fmt, ...) NORETURN2 PRINTF (1, 2);
+void nonfatal (const char *fmt, ...) PRINTF (1, 2);
+void warning (int level, const char *fmt, ...) PRINTF (2, 3);
+void *xmalloc (size_t n);
+uchar *xstrdup (const uchar *s);
+
+struct word_table *wt_new (unsigned hash_size);
+struct word *wt_find (struct word_table *wt, const uchar *str, unsigned hash);
+unsigned wt_hash (struct word_table *wt, const uchar *str);
+struct word *wt_add (struct word_table *wt, const uchar *str);
+int wt_walk (struct word_table *wt, int (*callback)(struct word *));
+int wt_count (const struct word_table *wt);
+
+struct word *word_find (const uchar *str, unsigned hash);
+unsigned word_hash (const uchar *str);
+struct word *word_add (const uchar *str);
+int word_walk (int (*callback)(struct word *));
+
+void write_nl (void);
+void write_break (void);
+void write_nstring (const uchar *p, size_t n);
+void write_string (const uchar *p);
+void write_line (const uchar *p);
+void write_fmt (const char *fmt, ...) PRINTF (1, 2);
+void write_space (void);
+void format_output (const uchar *p, int may_break);
+void format_string (const uchar *p, int sty, int may_break);
+void format_spaces (int n, enum style style, int may_break);
+void make_elements (const uchar *p);
+void start_hilite (int hilite);
+void end_hilite (void);
+struct word *use_reference (const uchar *p);
+void open_input (const char *name);
+void read_line (void);
+void init_file (void);
+int parse_tag (const uchar **ptr);
+void start_index (void);
Index: trunk/src/emx/src/emxdoc/html.c
===================================================================
--- trunk/src/emx/src/emxdoc/html.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/html.c	(revision 18)
@@ -0,0 +1,755 @@
+/* html.c -- HTML output
+   Copyright (c) 1999 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "emxdoc.h"
+#include "html.h"
+#include "xref.h"
+
+static int index_count;
+static struct word **index_v;
+static int index_n;
+static struct word *index_wp1;
+static const uchar *index_map;
+
+static void html_write_index (void);
+
+void html_output (const uchar *p, int may_break)
+{
+  const uchar *q;
+
+  if (*p == ' ' && output_x >= 60 && may_break)
+    {
+      write_nl ();
+      ++p;
+    }
+  while ((q = strpbrk (p, "<>& ")) != NULL)
+    {
+      write_nstring (p, q - p);
+      p = q;
+      if (p[0] == ' ' && p[1] == ' ')
+        while (*p == ' ')
+          {
+            write_string ("&nbsp;");
+            ++p;
+          }
+      else
+        switch (*p++)
+          {
+          case '<':
+            write_string ("&lt;");
+            break;
+          case '>':
+            write_string ("&gt;");
+            break;
+          case '&':
+            write_string ("&amp;");
+            break;
+          case ' ':
+            write_string (" ");
+            break;
+          default:
+            abort ();
+            }
+    }
+  write_string (p);
+}
+
+static void html_para (void)
+{
+  write_break ();
+  write_string ("<P>");
+}
+
+static void html_begin_link (const uchar *database, int ref)
+{
+  write_fmt ("<A HREF=\"%s%s#%d\">",
+             database != NULL ? (const char *)database : "",
+             database != NULL ? ".html" : "", ref);
+}
+
+
+static void html_end_link (void)
+{
+  write_string ("</A>");
+}
+
+
+void html_elements (enum style style)
+{
+  const struct element *ep;
+  enum style style_stack[STYLE_STACK_SIZE];
+  int style_sp, ignore_spaces;
+  uchar *p;
+
+  style_sp = 0;
+  style_stack[style_sp] = style;
+  ignore_spaces = FALSE;
+  for (ep = elements; ep->el != EL_END; ++ep)
+    switch (ep->el)
+      {
+      case EL_WORD:
+      case EL_PUNCT:
+        if (ep->n != 0)
+          {
+            if (ep->wp->database == NULL)
+              html_begin_link (NULL, ep->wp->ref);
+            else
+              html_begin_link (ep->wp->database->str, ep->wp->ref);
+          }
+        p = ep->wp->str;
+        if (ep->wp->special != NULL && ep->wp->special->html != NULL)
+          write_string (ep->wp->special->html);
+        else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
+          format_string (p, (ep->wp->style != STYLE_NORMAL
+                             ? ep->wp->style : style), FALSE);
+        else
+          format_string (p, style_stack[style_sp], FALSE);
+        if (ep->n != 0)
+          html_end_link ();
+        break;
+      case EL_SPACE:
+        if (ignore_spaces)
+          ignore_spaces = FALSE;
+        else
+          format_spaces (ep->n, style_stack[style_sp], TRUE);
+        break;
+      case EL_BREAK:
+        write_line ("<BR>");
+        break;
+      case EL_STYLE:
+        if (style_sp + 1 >= STYLE_STACK_SIZE)
+          fatal ("%s:%d: Style stack overflow", input_fname, line_no);
+        style_stack[++style_sp] = ep->n;
+        break;
+      case EL_ENDSTYLE:
+        if (style_sp == 0)
+          fatal ("%s:%d: Style stack underflow", input_fname, line_no);
+        --style_sp;
+        break;
+      default:
+        abort ();
+      }
+}
+
+void html_start_hilite (void)
+{
+  if (hl_stack[hl_sp] & HL_TT)
+    write_string ("<TT>");
+  else if (hl_stack[hl_sp] & HL_BF)
+    write_string ("<B>");
+  else if (hl_stack[hl_sp] & (HL_SL | HL_EM))
+    write_string ("<I>");
+}
+
+
+void html_end_hilite (void)
+{
+  if (hl_stack[hl_sp] & HL_TT)
+    write_string ("</TT>");
+  else if (hl_stack[hl_sp] & HL_BF)
+    write_string ("</B>");
+  else if (hl_stack[hl_sp] & (HL_SL | HL_EM))
+    write_string ("</I>");
+}
+
+
+void html_end_env (void)
+{
+  switch (env_stack[env_sp].env)
+    {
+    case ENV_DESCRIPTION:
+    case ENV_LIST:
+      write_break ();
+      write_line ("</DL>");
+      break;
+    case ENV_ENUMERATE:
+      write_break ();
+      write_line ("</OL>");
+      break;
+    case ENV_ITEMIZE:
+      write_break ();
+      write_line ("</UL>");
+      break;
+    case ENV_TYPEWRITER:
+      write_break ();
+      write_line ("</PRE></BLOCKQUOTE>");
+      break;
+    case ENV_INDENT:
+      write_break ();
+      write_line ("</BLOCKQUOTE>");
+      break;
+    default:
+      abort ();
+    }
+}
+
+
+void html_toc_start (void)
+{
+}
+
+
+void html_toc_line (const uchar *s, const struct toc *tp)
+{
+  format_string (s, STYLE_NORMAL, FALSE);
+  html_begin_link (NULL, tp->ref);
+  html_output (tp->title, FALSE);
+  html_end_link ();
+  write_line ("<BR>");
+}
+
+
+void html_toc_end (void)
+{
+  write_line ("<HR>");
+}
+
+void html_heading1 (int ref)
+{
+  write_break ();
+  write_fmt ("<A NAME=\"%d\"></A>", ref);
+  write_nl ();
+}
+
+
+void html_heading2 (const uchar *s)
+{
+  if (para_flag)
+    html_para ();
+  switch (tg_level)
+    {
+    case 0:
+      write_string (s);
+      write_line ("<BR>");
+      break;
+    case 1: case 2: case 3: case 4: case 5: case 6:
+      write_fmt ("<H%d>", tg_level);
+      html_output (s, FALSE);
+      write_fmt ("</H%d>", tg_level);
+      write_nl ();
+      break;
+    default:
+      fatal ("Sorry, HTML supports only 6 levels of headings");
+    }
+  write_nl ();
+}
+
+
+void html_description (void)
+{
+  write_break ();
+  write_line ("<DL COMPACT>");
+  write_nl ();
+}
+
+
+void html_enumerate (void)
+{
+  write_break ();
+  write_line ("<OL>");
+  write_nl ();
+}
+
+
+void html_itemize (void)
+{
+  write_break ();
+  write_line ("<UL>");
+  write_nl ();
+}
+
+
+void html_indent (void)
+{
+  write_break ();
+  write_line ("<BLOCKQUOTE>");
+}
+
+
+void html_list (void)
+{
+  write_break ();
+  write_line ("<DL COMPACT>");
+}
+
+
+void html_verbatim_start (enum tag tag_end)
+{
+  write_break ();
+  switch (tag_end)
+    {
+    case TAG_ENDHEADERS:
+      html_para ();
+      format_string ("Headers:", STYLE_BOLD, FALSE);
+      break;
+    case TAG_ENDSAMPLECODE:
+      html_para ();
+      format_string ("Example:", STYLE_BOLD, FALSE);
+      write_line ("<BLOCKQUOTE>");
+      break;
+    case TAG_ENDEXAMPLE:
+      html_para ();
+      write_line ("<BLOCKQUOTE>");
+      break;
+    default:
+      break;
+    }
+  write_break ();
+  write_line ("<PRE>");
+}
+
+void html_verbatim_line (void)
+{
+  html_output (input, FALSE);
+  write_nl ();
+}
+
+void html_verbatim_end (enum tag tag_end)
+{
+  write_line ("</PRE>");
+  switch (tag_end)
+    {
+    case TAG_ENDEXAMPLE:
+    case TAG_ENDSAMPLECODE:
+      write_line ("</BLOCKQUOTE>");
+      break;
+    default:
+      break;
+    }
+}
+
+
+void html_description_item (const uchar *s)
+{
+  write_break ();
+  write_string ("<DT>");
+  make_elements (s);
+  html_elements (STYLE_NORMAL);
+  write_string ("<DD>");
+}
+
+
+void html_enumerate_item (void)
+{
+  write_break ();
+  write_line ("<LI>");
+}
+
+
+void html_itemize_item (void)
+{
+  write_break ();
+  write_line ("<LI>");
+}
+
+
+void html_list_item (const uchar *s)
+{
+  write_break ();
+  write_string ("<DT>");
+  make_elements (s);
+  html_elements (STYLE_NORMAL);
+  write_string ("<DD>");
+}
+
+
+void html_copy (void)
+{
+  if (para_flag)
+    html_para ();
+  switch (env_stack[env_sp].env)
+    {
+    case ENV_TYPEWRITER:
+      html_elements (STYLE_TTY);
+      break;
+    default:
+      html_elements (STYLE_NORMAL);
+      break;
+    }
+}
+
+
+void html_start (void)
+{
+  write_line ("<HTML><HEAD>");
+  if (title != NULL)
+    {
+      write_string ("<TITLE>");
+      format_string (title, STYLE_NORMAL, FALSE);
+      write_line ("</TITLE>");
+    }
+  write_line ("</HEAD><BODY>");
+}
+
+
+void html_end (void)
+{
+  if (index_count != 0)
+    start_index ();
+  if (out)
+    {
+      write_nl ();
+      html_write_index ();
+      write_line ("</BODY></HTML>");
+    }
+}
+
+void html_prototype_start (void)
+{
+  if (para_flag)
+    html_para ();
+  format_string (function_count == 1 ? "Prototype:" : "Prototypes:",
+                 STYLE_BOLD, FALSE);
+  write_break ();
+  html_para ();
+}
+
+void html_prototype_end (uchar *compat)
+{
+  html_elements (STYLE_TTY);
+  html_para ();
+  if (compat[0] != 0)
+    {
+      format_string ("Compatibility:", STYLE_BOLD, FALSE);
+      html_para ();
+      format_string (compat, STYLE_NORMAL, FALSE);
+      html_para ();
+      compat[0] = 0;
+    }
+  format_string ("Description:", STYLE_BOLD, FALSE);
+}
+
+void html_see_also_start (void)
+{
+  if (para_flag)
+    html_para ();
+  format_string ("See also: ", STYLE_BOLD, FALSE);
+}
+
+void html_see_also_word (const uchar *word, const uchar *s)
+{
+  struct word *wp;
+
+  wp = use_reference (word);
+  if (wp != NULL)
+    {
+      if (wp->database == NULL)
+        html_begin_link (NULL, wp->ref);
+      else
+        html_begin_link (wp->database->str, wp->ref);
+      html_output (word, FALSE);
+      html_end_link ();
+    }
+  if (*s != 0)
+    {
+      write_string (",");
+      if (output_x >= 60)
+        write_nl ();
+      else
+        write_string (" ");
+    }
+}
+
+void html_sample_file (const uchar *s)
+{
+  html_libref_section ("Example");
+  format_string (" See ", STYLE_NORMAL, FALSE);
+  format_string (s, STYLE_TTY, FALSE);
+  para_flag = TRUE;
+}
+
+void html_libref_section (const uchar *s)
+{
+  if (para_flag)
+    html_para ();
+  format_string (s, STYLE_BOLD, FALSE);
+  write_string (":");
+  para_flag = TRUE;
+}
+
+void html_function_start (const struct toc *tp)
+{
+  write_line ("<HR>");
+  html_heading1 (tp->ref);
+  write_string ("<H2>");
+  html_output (tp->title, FALSE);
+  write_line ("</H2>");
+}
+
+void html_function_function (const struct toc *tp, const uchar *s)
+{
+  if (index_wp1 != NULL)
+    html_index (tp, s, 2);
+}
+
+void html_minitoc (const struct toc *tp)
+{
+  int level;
+
+  if (tp == NULL)
+    fatal ("%s:%d: Cannot build minitoc before the first heading",
+           input_fname, line_no);
+  if (para_flag)
+    html_para ();
+  level = tp->level;
+  tp = tp->next;
+  while (tp != NULL && tp->level >= level + 1)
+    {
+      if (tp->level == level + 1)
+        {
+          html_begin_link (NULL, tp->ref);
+          format_output (tp->title, FALSE);
+          html_end_link ();
+          write_line ("<BR>");
+        }
+      tp = tp->next;
+    }
+}
+
+
+void html_index (const struct toc *tp, const uchar *s, int level)
+{
+  struct word *wp;
+
+  switch (level)
+    {
+    case 0:
+      wp = word_add (s);
+      assert (tp != NULL);
+      if (wp->idx == 0)
+        {
+          wp->idx = tp->ref;
+          if (wp->subidx == NULL)
+            ++index_count;
+        }
+      else if (wp->idx != tp->ref)
+        warning (1, "%s:%d: Index entry multiply defined",
+                 input_fname, line_no);
+      break;
+    case 1:
+      if (*s == 0)
+        index_wp1 = NULL;
+      else
+        {
+          wp = word_add (s);
+          index_wp1 = wp;
+        }
+      break;
+    case 2:
+      if (index_wp1 == NULL)
+        fatal ("%s:%d: %ci2 without %ci1", input_fname, line_no,
+               escape, escape);
+      if (index_wp1->subidx == NULL)
+        {
+          index_wp1->subidx = wt_new (37);
+          if (index_wp1->idx == 0)
+            ++index_count;
+        }
+      wp = wt_add (index_wp1->subidx, s);
+      assert (tp != NULL);
+      if (wp->idx == 0)
+        wp->idx = tp->ref;
+      else if (wp->idx != tp->ref)
+        warning (1, "%s:%d: Index entry multiply defined",
+                 input_fname, line_no);
+      break;
+    default:
+      abort ();
+    }
+}
+
+
+static int index_add (struct word *wp)
+{
+  if (wp->idx != 0 || wp->subidx != NULL)
+    {
+      assert (index_n < index_count);
+      index_v[index_n++] = wp;
+    }
+  return 0;
+}
+
+static const uchar map_ascii[256] =
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+  "\x40\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x5a\x5b\x5c\x5d\x5e\x5f"
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
+
+static const uchar map_cp850[256] =
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+  "\x40\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x5a\x5b\x5c\x5d\x5e\x5f"
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\xff"
+  "\x63\x75\x65\x61\x61\x61\x61\x63\x65\x65\x65\x69\x69\x69\x61\x61"
+  "\x65\x61\x61\x6f\x6f\x6f\x75\x75\x79\x6f\x75\x6f\xff\x6f\xff\xff"
+  "\x61\x69\x6f\x75\x6e\x6e\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\x61\x61\x61\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\x61\x61\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\x65\x65\x65\xff\x69\x69\x69\xff\xff\xff\xff\xff\x69\xff"
+  "\x6f\x80\x6f\x6f\x6f\x6f\xff\xff\xff\x75\x75\x75\x79\x79\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
+
+static const uchar map_iso8859_1[256] =
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+  "\x40\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x5a\x5b\x5c\x5d\x5e\x5f"
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\x20\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+  "\x61\x61\x61\x61\x61\x61\x61\x63\x65\x65\x65\x65\x69\x69\x69\x69"
+  "\xff\x6e\x6f\x6f\x6f\x6f\x6f\xff\x6f\x75\x75\x75\x75\x79\xff\x80"
+  "\x61\x61\x61\x61\x61\x61\x61\x63\x65\x65\x65\x65\x69\x69\x69\x69"
+  "\xff\x6e\x6f\x6f\x6f\x6f\x6f\xff\x6f\x75\x75\x75\x75\x79\xff\x79";
+
+static int compare1 (const uchar *s1, size_t n1,
+                     const uchar *s2, size_t n2,
+                     const uchar *map)
+{
+  uchar c1, c2;
+  int cmp;
+
+  while (n1 != 0 && n2 != 0)
+    {
+      c1 = map[*s1];
+      c2 = map[*s2];
+      if (c1 != c2)
+        {
+          /* Special cases for \ss */
+          if (c1 == 0x80)
+            {
+              cmp = compare1 ("ss", 2, s2, n2 < 2 ? n2 : 2, map_ascii);
+              if (cmp != 0)
+                return cmp;
+              ++s2; --n2;
+            }
+          else if (c2 == 0x80)
+            {
+              cmp = compare1 (s1, n1 < 2 ? n1 : 2, "ss", 2, map_ascii);
+              if (cmp != 0)
+                return cmp;
+              ++s1; --n1;
+            }
+          else if (c1 < c2)
+            return -1;
+          else
+            return 1;
+        }
+      ++s1; ++s2; --n1; --n2;
+    }
+  if (n1 != 0)
+    return 1;
+  if (n2 != 0)
+    return -1;
+  return 0;
+}
+
+static int index_compare (const void *p1, const void *p2)
+{
+  const struct word *wp1 = *(const struct word **)p1;
+  const struct word *wp2 = *(const struct word **)p2;
+  int cmp = compare1 (wp1->str, strlen (wp1->str),
+                      wp2->str, strlen (wp2->str), index_map);
+  if (cmp != 0)
+    return cmp;
+  return strcmp (wp1->str, wp2->str);
+}
+
+static void index_recurse (struct word_table *wt, int level)
+{
+  int i, j, n;
+  struct word **v;
+
+  if (level != 0)
+    index_count = wt_count (wt);
+  n = index_count;
+  index_v = xmalloc (n * sizeof (*index_v));
+  index_n = 0;
+  wt_walk (wt, index_add);
+  assert (index_n == n);
+  v = index_v;
+  index_count = 0; index_v = NULL;
+
+  qsort (v, n, sizeof (*v), index_compare);
+  for (i = 0; i < n; ++i)
+    {
+      struct word *wp = v[i];
+      assert (wp->idx != 0 || wp->subidx != NULL);
+      for (j = 0; j < level; ++j)
+        write_string ("&nbsp;&nbsp;");
+      if (wp->idx != 0)
+        html_begin_link (NULL, wp->idx);
+      html_output ((const char *)wp->str, FALSE);
+      if (wp->idx != 0)
+        html_end_link ();
+      write_line ("<BR>");
+      if (wp->subidx != NULL)
+        index_recurse (wp->subidx, level + 1);
+    }
+  free (v);
+}
+
+static void html_write_index (void)
+{
+  if (index_count != 0)
+    {
+      int n = index_count;
+      if (output_encoding == ENC_ISO8859_1)
+        index_map = map_iso8859_1;
+      else
+        index_map = map_cp850;
+      index_recurse (word_top, 0);
+      index_count = n;
+    }
+}
+
+void html_fragment (const uchar *s)
+{
+  write_break ();
+  write_fmt ("<A NAME=\"%s\"></A>", (const char *)s);
+  write_nl ();
+}
Index: trunk/src/emx/src/emxdoc/html.h
===================================================================
--- trunk/src/emx/src/emxdoc/html.h	(revision 18)
+++ trunk/src/emx/src/emxdoc/html.h	(revision 18)
@@ -0,0 +1,58 @@
+/* html.h -- HTML output
+   Copyright (c) 1999 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+void html_output (const uchar *p, int may_break);
+void html_elements (enum style style);
+void html_start_hilite (void);
+void html_end_hilite (void);
+void html_end_env (void);
+void html_toc_start (void);
+void html_toc_line (const uchar *s, const struct toc *tp);
+void html_toc_end (void);
+void html_heading1 (int ref);
+void html_heading2 (const uchar *s);
+void html_description (void);
+void html_enumerate (void);
+void html_itemize (void);
+void html_indent (void);
+void html_list (void);
+void html_verbatim_start (enum tag tag_end);
+void html_verbatim_line (void);
+void html_verbatim_end (enum tag tag_end);
+void html_description_item (const uchar *s);
+void html_enumerate_item (void);
+void html_itemize_item (void);
+void html_list (void);
+void html_list_item (const uchar *s);
+void html_copy (void);
+void html_start (void);
+void html_end (void);
+void html_minitoc (const struct toc *tp);
+void html_prototype_start (void);
+void html_prototype_end (uchar *compat);
+void html_index (const struct toc *tp, const uchar *s, int level);
+void html_see_also_start (void);
+void html_see_also_word (const uchar *word, const uchar *s);
+void html_sample_file (const uchar *s);
+void html_libref_section (const uchar *s);
+void html_function_start (const struct toc *tp);
+void html_function_function (const struct toc *tp, const uchar *s);
+void html_fragment (const uchar *s);
Index: trunk/src/emx/src/emxdoc/input.c
===================================================================
--- trunk/src/emx/src/emxdoc/input.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/input.c	(revision 18)
@@ -0,0 +1,656 @@
+/* input.c -- Read and tokenize the input file
+   Copyright (c) 1993-1999 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "emxdoc.h"
+#include "cond.h"
+
+#define COND_STACK_SIZE         8
+
+struct cond
+{
+  int start_line;
+  int true;
+  int else_seen;
+};
+
+struct recode_table
+{
+  enum enc inp;
+  enum enc out;
+  uchar tab[256];
+};
+
+static struct cond cond_stack[COND_STACK_SIZE];
+static int cond_sp;
+
+static const uchar *char_table[ENCODINGS] =
+{
+  /* ENC_CP850 */
+  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\xa0"
+  "\xa1\xa2\xa3\xa4\xa5\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb5\xb6\xb7"
+  "\xb8\xbd\xbe\xc6\xc7\xcf\xd0\xd1\xd2\xd3\xd4\xd6\xd7\xd8\xdd\xde"
+  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xf1\xf3"
+  "\xf4\xf5\xf6\xfa\xfb\xfc\xfd",
+
+  /* ENC_ISO8859_1 */
+  "\xc7\xfc\xe9\xe2\xe4\xe0\xe5\xe7\xea\xeb\xe8\xef\xee\xec\xc4\xc5"
+  "\xc9\xe6\xc6\xf4\xf6\xf2\xfb\xf9\xff\xd6\xdc\xf8\xa3\xd8\xd7\xe1"
+  "\xed\xf3\xfa\xf1\xd1\xbf\xae\xac\xbd\xbc\xa1\xab\xbb\xc1\xc2\xc0"
+  "\xa9\xa2\xa5\xe3\xc3\xa4\xf0\xd0\xca\xcb\xc8\xcd\xce\xcf\xa6\xcc"
+  "\xd3\xdf\xd4\xd2\xf5\xd5\xb5\xfe\xde\xda\xdb\xd9\xfd\xdd\xb1\xbe"
+  "\xb6\xa7\xf7\xb7\xb9\xb3\xb2"
+};
+
+static const uchar chars_iso8859_1[] = "";
+
+static const struct recode_table *build_recode_table (enum enc inp,
+                                                      enum enc out)
+{
+  struct recode_table *p;
+  const uchar *pi, *po;
+  int i;
+
+  if (inp < 0 || inp >= ENCODINGS || out < 0 || out >= ENCODINGS)
+    abort ();
+  p = xmalloc (sizeof (*p));
+  p->inp = inp;
+  p->out = out;
+  memset (p->tab, 0, 256);
+  for (i = 0; i < 128; ++i)
+    p->tab[i] = (uchar)i;
+
+  pi = char_table[inp];
+  po = char_table[out];
+  for (i = 0; pi[i] != 0 && po[i] != 0; ++i)
+    if (pi[i] != ' ' && po[i] != ' ')
+      {
+        if (p->tab[pi[i]] != 0)
+          abort ();
+        p->tab[pi[i]] = po[i];
+      }
+  if (pi[i] != 0 || po[i] != 0)
+    abort ();
+  p->tab[escape] = escape;
+  return p;
+}
+
+static int recode (uchar *s, enum enc inp, enum enc out)
+{
+  static const struct recode_table *rt;
+  const uchar *t;
+
+  if (rt == NULL)
+    rt = build_recode_table (inp, out);
+  else if (inp != rt->inp || out != rt->out)
+    fatal ("recode(): encoding changed");
+  t = rt->tab;
+  while (*s != 0)
+    {
+      if (t[*s] == 0)
+        return *s;
+      *s = t[*s];
+      ++s;
+    }
+  return 0;
+}
+
+static enum enc find_encoding (const uchar *s)
+{
+  char pos[ENCODINGS];
+  char neg[ENCODINGS];
+  uchar c;
+  int i, j;
+
+  memset (pos, 0, ENCODINGS);
+  memset (neg, 0, ENCODINGS);
+  while (*s != 0)
+    {
+      c = *s++;
+      if (c >= 0x80 && c != escape)
+        for (i = 0; i < ENCODINGS; ++i)
+          {
+            if (strchr (char_table[i], c) == NULL)
+              neg[i] = 1;
+            else
+              pos[i] = 1;
+          }
+    }
+
+  i = 0;
+  while (i < ENCODINGS && !pos[i] && !neg[i])
+    ++i;
+  if (i >= ENCODINGS)
+    return ENC_DEFAULT;         /* No character codes >= 0x80 */
+
+  j = -1;
+  for (i = 0; i < ENCODINGS; ++i)
+    if (pos[i] && !neg[i])
+      {
+        if (j != -1)
+          return ENC_AMBIGUOUS;
+        j = i;
+      }
+  if (j == -1)
+    return ENC_UNSUPPORTED;
+  return (enum enc)j;
+}
+
+static void choose_encoding (const uchar *s)
+{
+  enum enc e = find_encoding (s);
+  if (e != ENC_DEFAULT)
+    {
+      if (e == ENC_AMBIGUOUS)
+        fatal ("Input encoding ambiguous, please use -i");
+      if (e == ENC_UNSUPPORTED)
+        fatal ("Input encoding unsupported, please use -i");
+      input_encoding = e;
+      if (output_encoding == ENC_DEFAULT)
+        output_encoding = e;
+    }
+}
+
+#define ISARG(C) ((C) == '{' || (C) == '[')
+#define ISARGW(C) (isspace (C) || ISARG (C))
+#define ISENDW(C) (isspace (C) || (C) == 0)
+
+#define SKIP1W(P,AT) do { (P) += (AT); if (isspace (*(P))) ++(P); } while (0)
+#define SKIPW(P,AT) do { (P) += (AT); while (isspace (*(P))) ++(P); } while (0)
+
+void read_line (void)
+{
+  uchar *p;
+  int c1;
+
+redo:
+  ++line_no;
+  if (fgets (input, sizeof (input), input_file) == NULL)
+    {
+      if (ferror (input_file))
+        {
+          perror (input_fname);
+          exit (1);
+        }
+      end_of_file = TRUE;
+      if (cond_sp >= 0)
+        fatal ("%s:%d: Unterminated %cif",
+               input_fname, cond_stack[cond_sp].start_line, escape);
+      return;
+    }
+  p = strchr (input, '\n');
+  if (p == NULL)
+    fatal ("%s:%d: Line too long", input_fname, line_no);
+  *p = 0;
+  if (input_encoding == ENC_DEFAULT && output_encoding != ENC_DEFAULT)
+    choose_encoding (input);
+  if (input_encoding != output_encoding && input_encoding != ENC_DEFAULT)
+    {
+      int c = recode (input, input_encoding, output_encoding);
+      if (c != 0)
+        fatal ("%s:%d: unsupported character 0x%.2x",
+               input_fname, line_no, c);
+    }
+  if (input[0] == escape)
+    {
+      p = input + 1;
+      if (strncmp (p, "c", 1) == 0 && ISENDW (p[1]))
+        goto redo;
+      if (strncmp (p, "if", 2) == 0 && isspace (p[2]))
+        {
+          SKIPW (p, 2);
+          c1 = condition (p);
+          if (cond_sp + 1 >= COND_STACK_SIZE)
+            fatal ("%s:%d: Conditional stack overflow", input_fname, line_no);
+          ++cond_sp;
+          cond_stack[cond_sp].true = c1;
+          cond_stack[cond_sp].start_line = line_no;
+          cond_stack[cond_sp].else_seen = FALSE;
+          goto redo;
+        }
+      else if (strcmp (p, "else") == 0)
+        {
+          if (cond_sp < 0)
+            fatal ("%s:%d: %celse without %cif",
+                   input_fname, line_no, escape, escape);
+          if (cond_stack[cond_sp].else_seen)
+            fatal ("%s:%d: Multiple %celse for %cif in line %d",
+                   input_fname, line_no, escape, escape,
+                   cond_stack[cond_sp].start_line);
+          cond_stack[cond_sp].else_seen = TRUE;
+          cond_stack[cond_sp].true = !cond_stack[cond_sp].true;
+          goto redo;
+        }
+      else if (strcmp (p, "endif") == 0)
+        {
+          if (cond_sp < 0)
+            fatal ("%s:%d: %cendif without %cif",
+                   input_fname, line_no, escape, escape);
+          --cond_sp;
+          goto redo;
+        }
+      else if (p[0] == 'h' && p[1] >= '1' && p[1] <= '0' + SECTION_LEVELS)
+        {
+          /* Support h1 inside if */
+          if (cond_sp >= 0 && !cond_stack[cond_sp].true)
+            ++ref_no;
+        }
+    }
+
+  if (cond_sp >= 0 && !cond_stack[cond_sp].true)
+    goto redo;
+
+  p = input;
+  while (isspace (*p))
+    ++p;
+  if (*p == 0)
+    input[0] = 0;
+}
+
+
+void open_input (const char *name)
+{
+
+  line_no = 0; end_of_file = FALSE; cond_sp = -1;
+  input_fname = name;
+  input_file = fopen (input_fname, "rt");
+  if (input_file == NULL)
+    {
+      perror (input_fname);
+      exit (1);
+    }
+}
+
+
+static void invalid_tag (void)
+{
+  fatal ("%s:%d: Invalid tag", input_fname, line_no);
+}
+
+
+int parse_tag (const uchar **ptr)
+{
+  const uchar *p;
+
+  p = *ptr;
+  if (*p != escape)
+    return FALSE;
+  ++p;                          /* Skip escape character */
+  tg_flags = 0;
+  switch (*p)
+    {
+    case '.':
+      tg_tag = TAG_FULLSTOP;
+      ++p;
+      break;
+
+    case 'b':
+      if (strncmp (p, "bf", 2) == 0 && ISARGW (p[2]))
+        {
+          tg_tag = TAG_STYLE;
+          tg_style = STYLE_BOLD;
+          p += 2;
+        }
+      else if (strncmp (p, "break", 5) == 0 && ISENDW (p[5]))
+        {
+          tg_tag = TAG_BREAK;
+          SKIP1W (p, 5);        /* Skip one space */
+        }
+      else if (strcmp (p, "bugs") == 0)
+        tg_tag = TAG_BUGS;
+      else
+        invalid_tag ();
+      break;
+
+    case 'c':
+      if (strncmp (p, "compat", 6) == 0 && isspace (p[6]))
+        {
+          tg_tag = TAG_COMPAT;
+          p += 6;
+        }
+      else
+        invalid_tag ();
+      break;
+
+    case 'd':
+      if (strcmp (p, "description") == 0)
+        tg_tag = TAG_DESCRIPTION;
+      else
+        invalid_tag ();
+      break;
+
+    case 'e':
+      if (strncmp (p, "em", 2) == 0 && ISARGW (p[2]))
+        {
+          tg_tag = TAG_STYLE;
+          tg_style = STYLE_EMPHASIZE;
+          p += 2;
+        }
+      else if (strcmp (p, "enddescription") == 0)
+        tg_tag = TAG_ENDDESCRIPTION;
+      else if (strcmp (p, "endenumerate") == 0)
+        tg_tag = TAG_ENDENUMERATE;
+      else if (strcmp (p, "endexample") == 0)
+        tg_tag = TAG_ENDEXAMPLE;
+      else if (strcmp (p, "endheaders") == 0)
+        tg_tag = TAG_ENDHEADERS;
+      else if (strcmp (p, "endhtml") == 0)
+        tg_tag = TAG_ENDHTML;
+      else if (strcmp (p, "endindent") == 0)
+        tg_tag = TAG_ENDINDENT;
+      else if (strcmp (p, "enditemize") == 0)
+        tg_tag = TAG_ENDITEMIZE;
+      else if (strcmp (p, "endlist") == 0)
+        tg_tag = TAG_ENDLIST;
+      else if (strcmp (p, "endprototype") == 0)
+        tg_tag = TAG_ENDPROTOTYPE;
+      else if (strcmp (p, "endsamplecode") == 0)
+        tg_tag = TAG_ENDSAMPLECODE;
+      else if (strcmp (p, "endverbatim") == 0)
+        tg_tag = TAG_ENDVERBATIM;
+      else if (strcmp (p, "endtypewriter") == 0)
+        tg_tag = TAG_ENDTYPEWRITER;
+      else if (strcmp (p, "endipf") == 0)
+        tg_tag = TAG_ENDIPF;
+      else if (strcmp (p, "endlatex") == 0)
+        tg_tag = TAG_ENDLATEX;
+      else if (strcmp (p, "endtext") == 0)
+        tg_tag = TAG_ENDTEXT;
+      else if (strcmp (p, "endtable") == 0)
+        tg_tag = TAG_ENDTABLE;
+      else if (strcmp (p, "enumerate") == 0)
+        tg_tag = TAG_ENUMERATE;
+      else if (strcmp (p, "errors") == 0)
+        tg_tag = TAG_ERRORS;
+      else if (strcmp (p, "example") == 0)
+        tg_tag = TAG_EXAMPLE;
+      else
+        invalid_tag ();
+      break;
+
+    case 'f':
+      if (strncmp (p, "format", 6) == 0 && isspace (p[6]))
+        {
+          tg_tag = TAG_FORMAT;
+          SKIPW (p, 6);
+        }
+      else if (strncmp (p, "function", 8) == 0 && isspace (p[8]))
+        {
+          tg_tag = TAG_FUNCTION;
+          SKIPW (p, 8);
+        }
+      else
+        invalid_tag ();
+      break;
+
+    case 'h':
+      if (p[1] >= '1' && p[1] <= '0' + SECTION_LEVELS)
+        {
+          tg_tag = TAG_HEADING;
+          tg_level = p[1] - '0';
+          tg_underline = (tg_level == 1 ? '=' : '-');
+          p += 2;
+          while (*p != 0 && !isspace (*p))
+            switch (*p++)
+              {
+              case 'h':
+                tg_flags |= HF_HIDE;
+                break;
+              case 'u':
+                tg_flags |= HF_UNNUMBERED;
+                break;
+              default:
+                invalid_tag ();
+              }
+          SKIPW (p, 0);
+        }
+      else if (p[1] == '-' || p[1] == '=')
+        {
+          tg_tag = TAG_HEADING;
+          tg_level = 0;
+          tg_underline = p[1];
+          SKIPW (p, 2);
+        }
+      else if (strncmp (p, "hpt", 3) == 0 && ISARGW (p[3]))
+        {
+          tg_tag = TAG_HPT;
+          p += 3;
+        }
+      else if (strcmp (p, "headers") == 0)
+        tg_tag = TAG_HEADERS;
+      else if (strcmp (p, "hints") == 0)
+        tg_tag = TAG_HINTS;
+      else if (strcmp (p, "html") == 0)
+        tg_tag = TAG_HTML;
+      else if (strncmp (p, "htmlfragment", 12) == 0 && isspace (p[12]))
+        {
+          tg_tag = TAG_HTMLFRAGMENT;
+          SKIPW (p, 12);
+        }
+      else if (strcmp (p, "htmlminitoc") == 0)
+        tg_tag = TAG_HTMLMINITOC;
+      else
+        invalid_tag ();
+      break;
+
+    case 'i':
+      if (p[1] >= '1' && p[1] <= '2')
+        {
+          tg_tag = TAG_INDEX;
+          tg_level = p[1] - '0';
+          SKIPW (p, 2);
+        }
+      else if (strcmp (p, "implementation") == 0)
+        tg_tag = TAG_IMPLEMENTATION;
+      else if (strcmp (p, "ipf") == 0)
+        tg_tag = TAG_IPF;
+      else if (strcmp (p, "ipfminitoc") == 0)
+        tg_tag = TAG_IPFMINITOC;
+      else if (strncmp (p, "item", 4) == 0 && ISENDW (p[4]))
+        {
+          tg_tag = TAG_ITEM;
+          SKIPW (p, 4);
+        }
+      else if (strncmp (p, "index", 5) == 0 && isspace (p[5]))
+        {
+          tg_tag = TAG_INDEX;
+          tg_level = 0;
+          SKIPW (p, 5);
+        }
+      else if (strcmp (p, "indent") == 0)
+        tg_tag = TAG_INDENT;
+      else if (strcmp (p, "itemize") == 0)
+        tg_tag = TAG_ITEMIZE;
+      else
+        invalid_tag ();
+      break;
+
+    case 'k':
+      if (strncmp (p, "keyword ", 8) == 0)
+        {
+          tg_tag = TAG_KEYWORD;
+          SKIPW (p, 8);
+        }
+      else
+        invalid_tag ();
+      break;
+
+    case 'l':
+      if (strncmp (p, "label ", 6) == 0)
+        {
+          tg_tag = TAG_LABEL;
+          SKIPW (p, 6);
+        }
+      else if (strncmp (p, "language", 8) == 0 && isspace (p[8]))
+        {
+          tg_tag = TAG_LANGUAGE;
+          SKIPW (p, 8);
+        }
+      else if (strcmp (p, "latex") == 0)
+        tg_tag = TAG_LATEX;
+      else if (strcmp (p, "list") == 0)
+        tg_tag = TAG_LIST;
+      else
+        invalid_tag ();
+      break;
+
+    case 'm':
+      if (strcmp (p, "minitoc") == 0)
+        tg_tag = TAG_MINITOC;
+      else
+        invalid_tag ();
+      break;
+    case 'p':
+      if (strcmp (p, "prototype") == 0)
+        tg_tag = TAG_PROTOTYPE;
+      else if (strncmp (p, "param", 5) == 0 && isspace (p[5]))
+        {
+          tg_tag = TAG_PARAM;
+          SKIPW (p, 5);
+        }
+      else if (strncmp (p, "pa", 2) == 0 && ISARGW (p[2]))
+        {
+          tg_tag = TAG_STYLE;
+          tg_style = STYLE_PARAM;
+          p += 2;
+        }
+      else
+        invalid_tag ();
+      break;
+
+    case 'r':
+      if (strncmp (p, "ref", 3) == 0 && ISARGW (p[3]))
+        {
+          tg_tag = TAG_REF;
+          p += 3;
+        }
+      else if (strncmp (p, "replace", 7) == 0 && isspace (p[7]))
+        {
+          tg_tag = TAG_REPLACE;
+          SKIPW (p, 7);
+        }
+      else if (strcmp (p, "restrictions") == 0)
+        tg_tag = TAG_RESTRICTIONS;
+      else if (strcmp (p, "returnvalue") == 0)
+        tg_tag = TAG_RETURNVALUE;
+      else
+        invalid_tag ();
+      break;
+
+    case 's':
+      if (strncmp (p, "seealso", 7) == 0 && isspace (p[7]))
+        {
+          tg_tag = TAG_SEEALSO;
+          p += 7;
+        }
+      else if (strcmp (p, "samplecode") == 0)
+        tg_tag = TAG_SAMPLECODE;
+      else if (strncmp (p, "samplefile", 10) == 0 && isspace (p[10]))
+        {
+          tg_tag = TAG_SAMPLEFILE;
+          SKIPW (p, 10);
+        }
+      else if (strncmp (p, "set", 3) == 0 && isspace (p[3]))
+        {
+          tg_tag = TAG_SET;
+          SKIPW (p, 3);
+        }
+      else if (strncmp (p, "sl", 2) == 0 && ISARGW (p[2]))
+        {
+          tg_tag = TAG_STYLE;
+          tg_style = STYLE_SLANTED;
+          p += 2;
+        }
+      else if (strncmp (p, "special", 7) == 0 && isspace (p[7]))
+        {
+          tg_tag = TAG_SPECIAL;
+          SKIPW (p, 7);
+        }
+      else if (strncmp (p, "sy", 2) == 0 && ISARGW (p[2]))
+        {
+          tg_tag = TAG_STYLE;
+          tg_style = STYLE_SYNTAX;
+          p += 2;
+        }
+      else if (strncmp (p, "syntax", 6) == 0 && isspace (p[6]))
+        {
+          tg_tag = TAG_SYNTAX;
+          SKIPW (p, 6);
+        }
+      else
+        invalid_tag ();
+      break;
+
+    case 't':
+      if (strncmp (p, "tt", 2) == 0 && ISARGW (p[2]))
+        {
+          tg_tag = TAG_STYLE;
+          tg_style = STYLE_TTY;
+          p += 2;
+        }
+      else if (strcmp (p, "toc") == 0)
+        tg_tag = TAG_TOC;
+      else if (strcmp (p, "text") == 0)
+        tg_tag = TAG_TEXT;
+      else if (strncmp (p, "table ", 6) == 0)
+        {
+          tg_tag = TAG_TABLE;
+          SKIPW (p, 6);
+        }
+      else if (strncmp (p, "title ", 6) == 0)
+        {
+          tg_tag = TAG_TITLE;
+          SKIPW (p, 6);
+        }
+      else if (strcmp (p, "typewriter") == 0)
+        tg_tag = TAG_TYPEWRITER;
+      else
+        invalid_tag ();
+      break;
+
+    case 'u':
+      if (strncmp (p, "ul", 2) == 0 && ISARGW (p[2]))
+        {
+          tg_tag = TAG_STYLE;
+          tg_style = STYLE_UNDERLINE;
+          p += 2;
+        }
+      else
+        invalid_tag ();
+      break;
+
+    case 'v':
+      if (strcmp (p, "verbatim") == 0)
+        tg_tag = TAG_VERBATIM;
+      else
+        invalid_tag ();
+      break;
+
+    default:
+      invalid_tag ();
+    }
+  *ptr = p;
+  return TRUE;
+}
Index: trunk/src/emx/src/emxdoc/ipf.c
===================================================================
--- trunk/src/emx/src/emxdoc/ipf.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/ipf.c	(revision 18)
@@ -0,0 +1,735 @@
+/* ipf.c -- IPF output
+   Copyright (c) 1993-2000 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "emxdoc.h"
+#include "ipf.h"
+#include "xref.h"
+
+#define HBAR   0xc4
+#define VBAR   0xb3
+
+static int idx_refid;
+
+
+void ipf_hilite (int new)
+{
+  int diff, font_changed;
+
+  if (new & HL_EM)
+    new = (new & ~HL_EM) | HL_SL;
+  if (hl_ipf == new)
+    return;
+  font_changed = FALSE;
+  diff = new & ~hl_ipf;
+  if (diff & HL_TT)
+    {
+      write_string (":font");
+      write_space ();
+      write_string ("facename=Courier");
+      write_space ();
+      write_string ("size=16x9.");
+      font_changed = TRUE;
+    }
+  diff = hl_ipf & ~new;
+  if (diff & HL_TT)
+    {
+      write_string (":font");
+      write_space ();
+      write_string ("facename=default");
+      write_space ();
+      write_string ("size=0x0.");
+      font_changed = TRUE;
+    }
+
+  if ((hl_ipf & (HL_BF|HL_SL|HL_UL))
+      != (new & (HL_BF|HL_SL|HL_UL)) || font_changed)
+    {
+      if (hl_ipf_no != 0)
+        write_fmt (":ehp%d.", hl_ipf_no);
+      if (opt_c && (new & HL_SL))
+        hl_ipf_no = 4;
+      else
+        switch (new & (HL_BF|HL_SL|HL_UL))
+          {
+          case 0:
+            hl_ipf_no = 0;
+            break;
+          case HL_SL:
+            hl_ipf_no = 1;
+            break;
+          case HL_SL|HL_BF:
+            hl_ipf_no = 3;
+            break;
+          case HL_SL|HL_UL:
+          case HL_SL|HL_BF|HL_UL:
+            hl_ipf_no = 6;
+            break;
+          case HL_BF:
+            hl_ipf_no = 2;
+            break;
+          case HL_BF|HL_UL:
+            hl_ipf_no = 7;
+            break;
+          case HL_UL:
+            hl_ipf_no = 5;
+            break;
+          default:
+            abort ();
+          }
+      if (hl_ipf_no != 0)
+        write_fmt (":hp%d.", hl_ipf_no);
+    }
+
+  hl_ipf = new;
+}
+
+
+static void ipf_string (const uchar *p, int may_break)
+{
+  const uchar *q;
+
+  while ((q = strpbrk (p, ":&. ")) != NULL)
+    {
+      write_nstring (p, q - p);
+      switch (*q)
+        {
+        case ':':
+          write_string ("&colon.");
+          break;
+        case '&':
+          write_string ("&amp.");
+          break;
+        case ' ':
+          if (output_x >= 60 && may_break)
+            write_nl ();
+          else
+            write_string (" ");
+          break;
+        case '.':
+          if (output_x == 0)
+            write_string ("&per.");
+          else
+            write_string (".");
+          break;
+        default:
+          abort ();
+        }
+      p = q + 1;
+    }
+  write_string (p);
+}
+
+
+void ipf_output (const uchar *p, int may_break)
+{
+  ipf_hilite (hl_stack[hl_sp]);
+  ipf_string (p, may_break);
+}
+
+
+void ipf_para (void)
+{
+  write_break ();
+  write_line (":p.");
+}
+
+
+void ipf_margin (int margin)
+{
+  if (out && mode == 'I')
+    {
+      write_fmt (":lm margin=%d.", margin);
+      write_nl ();
+    }
+}
+
+
+void ipf_env_margin (int sp)
+{
+  ipf_margin (env_stack[sp].imargin);
+}
+
+
+void ipf_elements (enum style style)
+{
+  const struct element *ep;
+  enum style style_stack[STYLE_STACK_SIZE];
+  int style_sp;
+
+  style_sp = 0;
+  style_stack[style_sp] = style;
+  for (ep = elements; ep->el != EL_END; ++ep)
+    switch (ep->el)
+      {
+      case EL_WORD:
+      case EL_PUNCT:
+        if (ep->n != 0)
+          {
+            if (ep->wp->database == NULL)
+              ipf_begin_link (NULL, ep->wp->ref);
+            else
+              ipf_begin_link (ep->wp->database->str, ep->wp->ref);
+            format_output (ep->wp->str, FALSE);
+            ipf_end_link ();
+          }
+        else if (ep->wp->special != NULL && ep->wp->special->ipf != NULL)
+          write_string (ep->wp->special->ipf);
+        else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
+          format_string (ep->wp->str, (ep->wp->style != STYLE_NORMAL
+                                       ? ep->wp->style : style), FALSE);
+        else
+          format_string (ep->wp->str, style_stack[style_sp], FALSE);
+        break;
+      case EL_SPACE:
+        format_spaces (ep->n, style_stack[style_sp], TRUE);
+        break;
+      case EL_BREAK:
+        write_break ();
+        write_line (".br");
+        break;
+      case EL_STYLE:
+        if (style_sp + 1 >= STYLE_STACK_SIZE)
+          fatal ("%s:%d: Style stack overflow", input_fname, line_no);
+        style_stack[++style_sp] = ep->n;
+        break;
+      case EL_ENDSTYLE:
+        if (style_sp == 0)
+          fatal ("%s:%d: Style stack underflow", input_fname, line_no);
+        --style_sp;
+        break;
+      default:
+        abort ();
+      }
+}
+
+
+void ipf_begin_link (const uchar *database, int ref)
+{
+  ipf_hilite (hl_stack[hl_sp]);
+  write_string (":link");
+  write_space ();
+  write_string ("reftype=hd");
+  write_space ();
+  if (database != NULL && !opt_a)
+    {
+      write_space ();
+      write_fmt ("refid=%d database='%s'", ref, database);
+    }
+  else
+    write_fmt ("res=%d", ref);
+  write_string (".");
+}
+
+
+void ipf_end_link (void)
+{
+  write_string (":elink.");
+}
+
+
+void ipf_end_env (void)
+{
+  switch (env_stack[env_sp].env)
+    {
+    case ENV_DESCRIPTION:
+      write_break ();
+      write_line (":edl.");
+      break;
+    case ENV_ENUMERATE:
+      write_break ();
+      write_line (":eol.");
+      break;
+    case ENV_ITEMIZE:
+      write_break ();
+      write_line (":eul.");
+      break;
+    case ENV_LIST:
+    case ENV_INDENT:
+    case ENV_TYPEWRITER:
+      write_break ();
+      ipf_env_margin (env_sp-1);
+      break;
+    default:
+      abort ();
+    }
+}
+
+
+void ipf_toc_start (void)
+{
+  write_line (":lines align=left.");
+}
+
+
+void ipf_toc_line (const uchar *s, const struct toc *tp)
+{
+  format_string (s, STYLE_NORMAL, FALSE);
+  ipf_begin_link (NULL, tp->ref);
+  format_output (tp->title, FALSE);
+  ipf_end_link ();
+  write_nl ();
+}
+
+
+void ipf_toc_end (void)
+{
+  write_line (":elines.");
+}
+
+
+void ipf_heading1 (int level, int ref, int global, unsigned flags)
+{
+  if (hl_sp != 0)
+    fatal ("%s:%d: Hilighting must be off at section heading",
+           input_fname, line_no);
+  ipf_hilite (hl_stack[hl_sp]);
+  write_break ();
+  write_fmt (":h%d res=%d", level, ref);
+  if (global && !opt_a)
+    write_fmt (" id=%d global", ref);
+  if (flags & HF_HIDE)
+    write_string (" hide");
+  write_string (".");
+}
+
+
+void ipf_heading2 (const uchar *s)
+{
+  if (tg_level == 0)
+    {
+      if (para_flag)
+        ipf_para ();
+      ipf_para ();
+      start_hilite (HL_BF);
+      format_output (s, FALSE);
+      end_hilite ();
+    }
+  else
+    format_output (s, FALSE);
+  write_nl ();
+  ipf_env_margin (0);
+}
+
+
+void ipf_description (void)
+{
+  write_fmt (":dl break=fit tsize=%d.", IPF_DESCRIPTION_INDENT);
+  write_nl ();
+}
+
+
+void ipf_enumerate (void)
+{
+  write_line (":ol.");
+}
+
+
+void ipf_itemize (void)
+{
+  write_line (":ul.");
+}
+
+
+void ipf_verbatim_start (enum tag tag_end)
+{
+  switch (tag_end)
+    {
+    case TAG_ENDHEADERS:
+      format_string ("Headers:", STYLE_BOLD, FALSE);
+      break;
+    case TAG_ENDSAMPLECODE:
+      ipf_para ();
+      format_string ("Example:", STYLE_BOLD, FALSE);
+      break;
+    case TAG_ENDEXAMPLE:
+      ipf_margin (env_stack[env_sp].imargin + 4);
+      break;
+    default:
+      break;
+    }
+  write_break ();
+  ipf_hilite (hl_stack[hl_sp]); /* Don't switch font after :cgraphic */
+  write_line (":cgraphic.");
+}
+
+
+void ipf_verbatim_line (void)
+{
+  format_output (input, FALSE);
+  write_nl ();
+}
+
+
+void ipf_verbatim_end (enum tag tag_end)
+{
+  write_line (":ecgraphic.");
+  switch (tag_end)
+    {
+    case TAG_ENDEXAMPLE:
+      ipf_env_margin (env_sp);
+      write_line (".br");
+      para_flag = FALSE;
+      break;
+    default:
+      para_flag = TRUE;
+      break;
+    }
+}
+
+
+void ipf_description_item (const uchar *s)
+{
+  write_break ();
+  write_string (":dt.");
+  make_elements (s);
+  ipf_elements (STYLE_NORMAL);
+  write_break ();
+  write_string (":dd.");
+}
+
+
+void ipf_enumerate_item (void)
+{
+  write_break ();
+  ipf_hilite (hl_stack[hl_sp]); /* Use correct font for number */
+  write_string (":li.");
+}
+
+
+void ipf_itemize_item (void)
+{
+  write_break ();
+  ipf_hilite (hl_stack[hl_sp]); /* Use correct font for mark */
+  write_string (":li.");
+}
+
+
+void ipf_list_item (const uchar *s)
+{
+  ipf_env_margin (env_sp-1);
+  ipf_para ();
+  make_elements (s);
+  ipf_elements (STYLE_NORMAL);
+  ipf_para ();
+  ipf_env_margin (env_sp);
+}
+
+
+void ipf_prototype_start (void)
+{
+  if (para_flag)
+    ipf_para ();
+  format_string (function_count == 1 ? "Prototype:" : "Prototypes:",
+                 STYLE_BOLD, FALSE);
+  write_break ();
+  ipf_para ();
+}
+
+
+void ipf_prototype_end (uchar *compat)
+{
+  ipf_elements (STYLE_TTY);
+  ipf_para ();
+  if (compat[0] != 0)
+    {
+      format_string ("Compatibility:", STYLE_BOLD, FALSE);
+      ipf_para ();
+      format_string (compat, STYLE_NORMAL, FALSE);
+      ipf_para ();
+      compat[0] = 0;
+    }
+  format_string ("Description:", STYLE_BOLD, FALSE);
+}
+
+
+void ipf_start (void)
+{
+  write_line (":userdoc.");
+  write_line (":prolog.");
+  write_line (":docprof toc=123.");
+  if (title != NULL)
+    {
+      write_string (":title.");
+      format_string (title, STYLE_NORMAL, FALSE);
+      write_nl ();
+    }
+  write_line (":eprolog.");
+  write_line (":body.");
+}
+
+
+void ipf_table_start (int do_indent, int *widths, int wn)
+{
+  int wi;
+
+  if (do_indent)
+    ipf_margin (env_stack[env_sp].imargin + 4);
+  write_break ();
+  write_string (":table");
+  if (wn != 0)
+    {
+      write_string (" cols='");
+      for (wi = 0; wi < wn; ++wi)
+        {
+          if (wi != 0)
+            write_string (" ");
+          write_fmt ("%d", widths[wi]);
+        }
+      write_string ("'");
+    }
+  write_line (".");
+}
+
+
+void ipf_table_line (const uchar *s, int wn)
+{
+  int wi;
+  uchar word[512], *d;
+
+  if (*s != HBAR)
+    {
+      write_line (":row.");
+      wi = 0;
+      while (*s != 0)
+        {
+          ++wi;
+          write_string (":c.");
+          d = word;
+          while (*s != VBAR && *s != 0)
+            *d++ = *s++;
+          while (d != word && isspace (d[-1]))
+            --d;
+          *d = 0;
+          make_elements (word);
+          ipf_elements (STYLE_NORMAL);
+          write_break ();
+          if (*s != 0)
+            {
+              ++s;
+              while (isspace (*s))
+                ++s;
+            }
+        }
+      if (wi != wn)
+        fatal ("%s:%d: Wrong number of columns", input_fname, line_no);
+    }
+}
+
+
+void ipf_table_end (int do_indent)
+{
+  write_line (":etable.");
+  if (do_indent)
+    {
+      ipf_env_margin (env_sp);
+      write_line (".br");
+      para_flag = FALSE;
+    }
+  else
+    para_flag = TRUE;
+}
+
+
+void ipf_index (const uchar *s)
+{
+  struct word *wp;
+
+  if (!out)
+    return;
+  switch (tg_level)
+    {
+    case 0:
+      write_string (":i1.");
+      ipf_string (s, FALSE);
+      write_nl ();
+      break;
+    case 1:
+      if (*s == 0)
+        idx_refid = 0;
+      else
+        {
+          wp = word_add (s);
+          if (wp->idx == 0)
+            {
+              idx_refid = wp->idx = ++idx_no;
+              write_fmt (":i1 id=%d.", idx_refid);
+              ipf_string (s, FALSE);
+              write_nl ();
+            }
+          else
+            idx_refid = wp->idx;
+        }
+      break;
+    case 2:
+      if (idx_refid == 0)
+        fatal ("%s:%d: %ci2 without %ci1", input_fname, line_no,
+               escape, escape);
+      write_fmt (":i2 refid=%d.", idx_refid);
+      ipf_string (s, FALSE);
+      write_nl ();
+      break;
+    default:
+      abort ();
+    }
+}
+
+
+void ipf_see_also_start (void)
+{
+  if (para_flag)
+    ipf_para ();
+  format_string ("See also: ", STYLE_BOLD, FALSE);
+}
+
+
+void ipf_see_also_word (const uchar *word, const uchar *s)
+{
+  struct word *wp;
+
+  wp = use_reference (word);
+  if (wp != NULL)
+    {
+      if (wp->database == NULL)
+        ipf_begin_link (NULL, wp->ref);
+      else
+        ipf_begin_link (wp->database->str, wp->ref);
+      ipf_string (word, FALSE);
+      ipf_end_link ();
+    }
+  if (*s != 0)
+    {
+      write_string (",");
+      if (output_x >= 60)
+        write_nl ();
+      else
+        write_string (" ");
+    }
+}
+
+
+void ipf_sample_file (const uchar *s)
+{
+  if (para_flag)
+    ipf_para ();
+  format_string ("Example: ", STYLE_BOLD, FALSE);
+  format_string ("See ", STYLE_NORMAL, FALSE);
+  format_string (s, STYLE_TTY, FALSE);
+  para_flag = TRUE;
+}
+
+
+void ipf_libref_section (const uchar *s)
+{
+  if (para_flag)
+    ipf_para ();
+  format_string (s, STYLE_BOLD, FALSE);
+  write_string ("&colon.");
+  para_flag = TRUE;
+}
+
+
+void ipf_function_start (const struct toc *tp)
+{
+  ipf_heading1 (2, tp->ref, tp->global, 0);
+  ipf_string (tp->title, TRUE);
+  if (idx_refid == 0)
+    fatal ("%s:%d: %cfunction without %ci1",
+           input_fname, line_no, escape, escape);
+  ipf_margin (1);
+}
+
+
+void ipf_function_function (const uchar *s)
+{
+  if (out)
+    {
+      write_break ();
+      write_fmt (":i2 refid=%d.", idx_refid);
+      ipf_string (s, FALSE);
+      write_nl ();
+    }
+}
+
+
+void ipf_copy (void)
+{
+  if (para_flag)
+    ipf_para ();
+  switch (env_stack[env_sp].env)
+    {
+    case ENV_TYPEWRITER:
+      ipf_elements (STYLE_TTY);
+      break;
+    default:
+      ipf_elements (STYLE_NORMAL);
+      break;
+    }
+}
+
+
+void ipf_minitoc (const struct toc *tp)
+{
+  int level, any;
+
+  if (tp == NULL)
+    fatal ("%s:%d: Cannot build minitoc before the first heading",
+           input_fname, line_no);
+  if (para_flag)
+    ipf_para ();
+  level = tp->level;
+  tp = tp->next;
+  any = FALSE;
+  while (tp != NULL && tp->level >= level + 1)
+    {
+      if (tp->level == level + 1)
+        {
+          if (!any)
+            {
+              write_line (":lines align=left.");
+              any = TRUE;
+            }
+          ipf_begin_link (NULL, tp->ref);
+          format_output (tp->title, TRUE);
+          ipf_end_link ();
+          write_nl ();
+        }
+      tp = tp->next;
+    }
+  if (any)
+    {
+      write_line (":elines.");
+      para_flag = TRUE;
+    }
+}
+
+
+void ipf_end (void)
+{
+  if (out)
+    {
+      ipf_hilite (0);
+      write_line (":euserdoc.");
+    }
+}
Index: trunk/src/emx/src/emxdoc/ipf.h
===================================================================
--- trunk/src/emx/src/emxdoc/ipf.h	(revision 18)
+++ trunk/src/emx/src/emxdoc/ipf.h	(revision 18)
@@ -0,0 +1,66 @@
+/* ipf.h -- IPF output
+   Copyright (c) 1993-1998 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define IPF_DESCRIPTION_INDENT  8
+
+EXTERN int hl_ipf;
+EXTERN int hl_ipf_no;
+
+void ipf_begin_link (const uchar *database, int ref);
+void ipf_end_link (void);
+void ipf_para (void);
+void ipf_env_margin (int sp);
+void ipf_elements (enum style style);
+void ipf_end_env (void);
+void ipf_toc_start (void);
+void ipf_toc_line (const uchar *s, const struct toc *tp);
+void ipf_toc_end (void);
+void ipf_heading1 (int level, int ref, int global, unsigned flags);
+void ipf_heading2 (const uchar *s);
+void ipf_output (const uchar *p, int may_break);
+void ipf_margin (int margin);
+void ipf_hilite (int new);
+void ipf_description (void);
+void ipf_enumerate (void);
+void ipf_itemize (void);
+void ipf_verbatim_start (enum tag tag_end);
+void ipf_verbatim_line (void);
+void ipf_verbatim_end (enum tag tag_end);
+void ipf_description_item (const uchar *s);
+void ipf_enumerate_item (void);
+void ipf_itemize_item (void);
+void ipf_list_item (const uchar *s);
+void ipf_prototype_start (void);
+void ipf_prototype_end (uchar *compat);
+void ipf_start (void);
+void ipf_table_start (int do_indent, int *widths, int wn);
+void ipf_table_line (const uchar *s, int wn);
+void ipf_table_end (int do_indent);
+void ipf_index (const uchar *s);
+void ipf_see_also_start (void);
+void ipf_see_also_word (const uchar *word, const uchar *s);
+void ipf_sample_file (const uchar *s);
+void ipf_libref_section (const uchar *s);
+void ipf_function_start (const struct toc *tp);
+void ipf_function_function (const uchar *s);
+void ipf_copy (void);
+void ipf_minitoc (const struct toc *tp);
+void ipf_end (void);
Index: trunk/src/emx/src/emxdoc/latex.c
===================================================================
--- trunk/src/emx/src/emxdoc/latex.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/latex.c	(revision 18)
@@ -0,0 +1,522 @@
+/* latex.c -- LaTeX output
+   Copyright (c) 1993-2000 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+/* TODO: LaTeX output is work in progress */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "emxdoc.h"
+#include "latex.h"
+
+static const uchar *index_word1;
+static int index_flag;
+
+void latex_output (const uchar *p, int may_break)
+{
+  const uchar *q;
+
+  if (*p == ' ' && output_x >= 60 && may_break)
+    {
+      write_nl ();
+      ++p;
+    }
+  while ((q = strpbrk (p, "\\&#$%_^")) != NULL)
+    {
+      write_nstring (p, q - p);
+      switch (*q)
+        {
+        case '\\':
+          /* TODO: Warning if no such character in current font! */
+          write_string ("\\bs/");
+          break;
+        case '&':
+          write_string ("\\&");
+          break;
+        case '#':
+          write_string ("\\#");
+          break;
+        case '$':
+          write_string ("\\$");
+          break;
+        case '%':
+          write_string ("\\%");
+          break;
+        case '_':
+          /* TODO: Warning if no such character in current font! */
+          write_string ("\\_");
+          break;
+        case '^':
+          /* TODO: Warning if no such character in current font! */
+          write_string ("\\^");
+          break;
+        default:
+          abort ();
+        }
+      p = q + 1;
+    }
+  write_string (p);
+}
+
+
+static void latex_elements (enum style style, int alltt)
+{
+  const struct element *ep, *ep2;
+  enum style style_stack[STYLE_STACK_SIZE];
+  int style_sp, ignore_spaces;
+  size_t len;
+  uchar *p, last;
+
+  if (alltt)
+    write_line ("\\begin{alltt}");
+  style_sp = 0;
+  style_stack[style_sp] = style;
+  ignore_spaces = FALSE;
+  for (ep = elements; ep->el != EL_END; ++ep)
+    switch (ep->el)
+      {
+      case EL_WORD:
+      case EL_PUNCT:
+        p = ep->wp->str;
+        if (strcmp (p, ".") == 0 && ep != elements && ep[-1].el == EL_WORD)
+          {
+            ep2 = ep + 1;
+            while (ep2->el == EL_STYLE || ep2->el == EL_ENDSTYLE)
+              ++ep2;
+            if (ep2->el == EL_SPACE)
+              {
+                len = strlen (ep[-1].wp->str);
+                if (len != 0)
+                  {
+                    last = ep[-1].wp->str[len-1];
+                    if (isupper (last) && ep2->n == 2)
+                      {
+                        ignore_spaces = TRUE;
+                        write_string ("\\@. ");
+                      }
+                    else if (!isupper (last) && ep2->n == 1)
+                      {
+                        ignore_spaces = TRUE;
+                        write_string (".\\ ");
+                      }
+                    else
+                      write_string (".");
+                    break;
+                  }
+              }
+          }
+        if (strcmp (p, "--") == 0)
+          p = "---";
+        if (ep->wp->special != NULL && ep->wp->special->latex != NULL)
+          write_string (ep->wp->special->latex);
+        else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
+          format_string (p, (ep->wp->style != STYLE_NORMAL
+                             ? ep->wp->style : style), FALSE);
+        else
+          format_string (p, style_stack[style_sp], FALSE);
+        break;
+      case EL_SPACE:
+        if (ignore_spaces)
+          ignore_spaces = FALSE;
+        else
+          format_spaces (ep->n, style_stack[style_sp], FALSE);
+        break;
+      case EL_BREAK:
+        if (alltt)
+          write_nl ();
+        else
+          write_line ("\\break");
+        break;
+      case EL_STYLE:
+        if (style_sp + 1 >= STYLE_STACK_SIZE)
+          fatal ("%s:%d: Style stack overflow", input_fname, line_no);
+        style_stack[++style_sp] = ep->n;
+        break;
+      case EL_ENDSTYLE:
+        if (style_sp == 0)
+          fatal ("%s:%d: Style stack underflow", input_fname, line_no);
+        --style_sp;
+        break;
+      default:
+        abort ();
+      }
+  if (alltt)
+    write_line ("\\end{alltt}");
+}
+
+
+void latex_start_hilite (void)
+{
+  if (hl_stack[hl_sp] & HL_TT)
+    write_string ("\\texttt{");
+  else if (hl_stack[hl_sp] & HL_BF)
+    write_string ("\\textbf{");
+  else if (hl_stack[hl_sp] & HL_SL)
+    write_string ("\\textsl{");
+  else if (hl_stack[hl_sp] & HL_EM)
+    write_string ("\\emph{");
+}
+
+
+void latex_end_hilite (void)
+{
+  write_string ("}");
+}
+
+
+void latex_end_env (void)
+{
+  switch (env_stack[env_sp].env)
+    {
+    case ENV_DESCRIPTION:
+    case ENV_LIST:
+      write_break ();
+      write_line ("\\end{description}");
+      break;
+    case ENV_ENUMERATE:
+      write_break ();
+      write_line ("\\end{enumerate}");
+      break;
+    case ENV_ITEMIZE:
+      write_break ();
+      write_line ("\\end{itemize}");
+      break;
+    case ENV_TYPEWRITER:
+    case ENV_INDENT:
+      write_break ();
+      write_line ("\\end{quote}");
+      break;
+    default:
+      abort ();
+    }
+}
+
+
+void latex_heading1 (void)
+{
+  write_nl ();
+}
+
+
+void latex_heading2 (const uchar *s)
+{
+  if (para_flag)
+    write_nl ();
+  switch (tg_level)
+    {
+    case 0:
+      latex_output (s, FALSE);
+      write_line ("\\break");
+      break;
+    case 1:
+      write_string ("\\section{");
+      latex_output (s, FALSE);
+      write_line ("}");
+      break;
+    case 2:
+      write_string ("\\subsection{");
+      latex_output (s, FALSE);
+      write_line ("}");
+      break;
+    case 3:
+      write_string ("\\subsubsection{");
+      latex_output (s, FALSE);
+      write_line ("}");
+      break;
+    default:
+      fatal ("Sorry, LaTeX supports only 3 levels of headings");
+    }
+  write_nl ();
+}
+
+
+void latex_description (void)
+{
+  write_break ();
+  write_line ("\\begin{description}");
+  write_nl ();
+}
+
+
+void latex_enumerate (void)
+{
+  write_break ();
+  write_line ("\\begin{enumerate}");
+  write_nl ();
+}
+
+
+void latex_itemize (void)
+{
+  write_break ();
+  write_line ("\\begin{itemize}");
+  write_nl ();
+}
+
+
+void latex_indent (void)
+{
+  write_break ();
+  write_line ("\\begin{quote}");
+}
+
+
+void latex_list (void)
+{
+  write_break ();
+  write_line ("\\begin{description}");
+}
+
+
+void latex_verbatim_start (enum tag tag_end)
+{
+  write_break ();
+  switch (tag_end)
+    {
+    case TAG_ENDHEADERS:
+      write_nl ();
+      write_line ("\\subsubsection*{Headers}");
+      break;
+    case TAG_ENDSAMPLECODE:
+      write_nl ();
+      write_line ("\\subsubsection*{Example}");
+      break;
+    case TAG_ENDEXAMPLE:
+      write_line ("\\begin{quote}");
+      break;
+    default:
+      break;
+    }
+  write_break ();
+  write_line ("\\begin{verbatim}");
+}
+
+
+void latex_verbatim_end (enum tag tag_end)
+{
+  write_line ("\\end{verbatim}");
+  switch (tag_end)
+    {
+    case TAG_ENDEXAMPLE:
+      write_line ("\\end{quote}");
+      break;
+    default:
+      break;
+    }
+}
+
+
+void latex_description_item (const uchar *s)
+{
+  write_break ();
+  write_string ("\\item[");
+  make_elements (s);
+  latex_elements (STYLE_NORMAL, FALSE);
+  write_line ("]");
+}
+
+
+void latex_enumerate_item (void)
+{
+  write_break ();
+  write_line ("\\item");
+}
+
+
+void latex_itemize_item (void)
+{
+  write_break ();
+  write_line ("\\item");
+}
+
+
+void latex_list_item (const uchar *s)
+{
+  write_break ();
+  write_string ("\\item[");
+  make_elements (s);
+  latex_elements (STYLE_NORMAL, FALSE);
+  write_line ("]");
+}
+
+
+void latex_copy (void)
+{
+  if (para_flag)
+    {
+      write_break ();
+      write_nl ();
+    }
+  switch (env_stack[env_sp].env)
+    {
+    case ENV_TYPEWRITER:
+      latex_elements (STYLE_NORMAL, TRUE);
+      break;
+    default:
+      latex_elements (STYLE_NORMAL, FALSE);
+      break;
+    }
+}
+
+void latex_prototype_start (void)
+{
+  write_break ();
+  write_fmt ("\\subsubsection*{Prototype%s}", function_count == 1 ? "" : "s");
+  write_nl ();
+}
+
+void latex_prototype_end (uchar *compat)
+{
+  latex_elements (STYLE_NORMAL, TRUE);
+  if (compat[0] != 0)
+    {
+      write_break ();
+      write_line ("\\subsubsection*{Compatibility}");
+      format_string (compat, STYLE_NORMAL, TRUE);
+      compat[0] = 0;
+    }
+  write_line ("\\subsubsection*{Description}");
+
+}
+
+void latex_see_also_start (void)
+{
+  write_break ();
+  write_line ("\\subsubsection*{See also}");
+}
+
+void latex_see_also_word (const uchar *word, const uchar *s)
+{
+  latex_output (word, FALSE);
+  if (*s != 0)
+    write_string (", ");
+}
+
+void latex_libref_section (const uchar *s)
+{
+  write_break ();
+  write_fmt ("\\subsubsection*{%s}", s);
+  write_nl ();
+}
+
+void latex_sample_file (const uchar *s)
+{
+  latex_libref_section ("Example");
+  format_string ("See ", STYLE_NORMAL, FALSE);
+  format_string (s, STYLE_TTY, FALSE);
+  para_flag = TRUE;
+}
+
+void latex_function_start (const struct toc *tp)
+{
+  write_break ();
+  write_string ("\\subsection{");
+  latex_output (tp->title, TRUE);
+  write_line ("}");
+}
+
+void latex_function_function (const uchar *s)
+{
+  if (index_word1 != NULL)
+    latex_index (s, 2);
+}
+
+void latex_start (void)
+{
+  write_line ("\\documentclass{article}");
+  write_line ("\\usepackage{emxdoc}");
+  write_line ("\\usepackage{alltt}");
+  if (output_encoding == ENC_CP850)
+    write_line ("\\usepackage[cp850]{inputenc}");
+  else if (output_encoding == ENC_ISO8859_1)
+    write_line ("\\usepackage[latin1]{inputenc}");
+  write_line ("\\usepackage[T1]{fontenc}");
+  if (index_flag)
+    write_line ("\\usepackage{makeidx}");
+  if (title != NULL)
+    {
+      write_string ("\\title{");
+      format_string (title, STYLE_NORMAL, FALSE);
+      write_line ("}");
+      write_line ("\\author{}");
+    }
+  if (index_flag)
+    write_line ("\\makeindex");
+  write_line ("\\begin{document}");
+  if (title != NULL)
+    write_line ("\\maketitle");
+  write_line ("\\tableofcontents");
+  write_line ("\\newpage");
+}
+
+
+void latex_end (void)
+{
+  if (out)
+    {
+      write_nl ();
+      if (index_flag)
+        write_line ("\\printindex");
+      write_line ("\\end{document}");
+    }
+}
+
+void latex_index (const uchar *s, int level)
+{
+  switch (level)
+    {
+    case 0:
+      index_flag = TRUE;
+      if (out)
+        {
+          write_string ("\\index{");
+          latex_output (s, FALSE);
+          write_string ("}");
+        }
+      break;
+    case 1:
+      if (*s == 0)
+        index_word1 = NULL;
+      else
+        {
+          struct word *wp = word_add (s);
+          index_word1 = wp->str;
+        }
+      break;
+    case 2:
+      if (index_word1 == NULL)
+        fatal ("%s:%d: %ci2 without %ci1", input_fname, line_no,
+               escape, escape);
+      index_flag = TRUE;
+      if (out)
+        {
+          write_string ("\\index{");
+          latex_output (index_word1, FALSE);
+          write_string ("!");
+          latex_output (s, FALSE);
+          write_string ("}");
+        }
+      break;
+    default:
+      abort ();
+    }
+}
Index: trunk/src/emx/src/emxdoc/latex.h
===================================================================
--- trunk/src/emx/src/emxdoc/latex.h	(revision 18)
+++ trunk/src/emx/src/emxdoc/latex.h	(revision 18)
@@ -0,0 +1,50 @@
+/* latex.h -- LaTeX output
+   Copyright (c) 1993-1999 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+void latex_output (const uchar *p, int may_break);
+void latex_start_hilite (void);
+void latex_end_hilite (void);
+void latex_end_env (void);
+void latex_heading1 (void);
+void latex_heading2 (const uchar *s);
+void latex_description (void);
+void latex_enumerate (void);
+void latex_itemize (void);
+void latex_indent (void);
+void latex_list (void);
+void latex_verbatim_start (enum tag tag_end);
+void latex_verbatim_end (enum tag tag_end);
+void latex_description_item (const uchar *s);
+void latex_enumerate_item (void);
+void latex_itemize_item (void);
+void latex_list_item (const uchar *s);
+void latex_prototype_start (void);
+void latex_prototype_end (uchar *compat);
+void latex_index (const uchar *s, int level);
+void latex_see_also_start (void);
+void latex_see_also_word (const uchar *word, const uchar *s);
+void latex_sample_file (const uchar *s);
+void latex_libref_section (const uchar *s);
+void latex_function_start (const struct toc *tp);
+void latex_function_function (const uchar *s);
+void latex_copy (void);
+void latex_start (void);
+void latex_end (void);
Index: trunk/src/emx/src/emxdoc/lb.c
===================================================================
--- trunk/src/emx/src/emxdoc/lb.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/lb.c	(revision 18)
@@ -0,0 +1,786 @@
+/* lb.c -- Line breaking
+   Copyright (c) 1993-1996 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lb.h"
+
+#define FALSE   0
+#define TRUE    1
+
+#define NODE_WORD       1
+#define NODE_GLUE       2
+#define NODE_PENALTY    3
+#define NODE_DISCR      4
+#define NODE_PRE        5
+#define NODE_POST       6
+#define NODE_NEWLINE    7
+
+#define HASH_SIZE       997
+
+#define HYPHEN_PENALTY  18
+
+struct node
+{
+  struct node *next;
+  char *word, *pre, *post;
+  const void *info;
+  int value, value_pre, value_post;
+  char type;
+};
+
+struct brkp
+{
+  struct node *node;
+  int chain;
+  int cost;
+  char special;
+};
+
+struct hword
+{
+  struct hword *next;
+  char *str;
+};
+
+struct lbh
+{
+  struct hword *hash_table[HASH_SIZE];
+};
+
+struct lb
+{
+  int lmargin;
+  int rmargin;
+  int lmargin_1;
+  int rmargin_1;
+  int brkp_count;
+  const struct lbh *hyphenation;
+  const struct node *cur_node;
+  struct node *node_list;
+  struct node **node_add;
+  struct brkp *brkps;
+  int *distance;
+};
+
+
+static const struct hword *lbh_find (const struct lbh *p, const char *s);
+
+
+int lb_init (struct lb **pp, int lmargin, int rmargin)
+{
+  struct lb *p;
+
+  *pp = NULL;
+  if (lmargin < 0 || lmargin >= rmargin)
+    return LB_INVAL;
+  p = malloc (sizeof (struct lb));
+  if (p == NULL) return LB_NOMEM;
+  p->lmargin = p->lmargin_1 = lmargin;
+  p->rmargin = p->rmargin_1 = rmargin;
+  p->brkp_count = 0;
+  p->cur_node = NULL;
+  p->node_list = NULL;
+  p->node_add = &p->node_list;
+  p->brkps = NULL;
+  p->distance = NULL;
+  p->hyphenation = NULL;
+  *pp = p;
+  return 0;
+}
+
+
+static void lb_free_node (struct node *n1)
+{
+  if (n1->word != NULL) free (n1->word);
+  if (n1->pre != NULL) free (n1->pre);
+  if (n1->post != NULL) free (n1->post);
+  free (n1);
+}
+
+
+int lb_exit (struct lb **pp)
+{
+  struct lb *p;
+  struct node *n1, *n2;
+
+  p = *pp; *pp = NULL;
+  if (p != NULL)
+    {
+      for (n1 = p->node_list; n1 != NULL; n1 = n2)
+        {
+          n2 = n1->next;
+          lb_free_node (n1);
+        }
+      if (p->brkps != NULL) free (p->brkps);
+      if (p->distance != NULL) free (p->distance);
+      free (p);
+    }
+  return 0;
+}
+
+
+static struct node * lb_new (struct lb *p, char type, int value,
+                             const char *word, const void *info)
+{
+  struct node *n1;
+
+  n1 = malloc (sizeof (struct node));
+  if (n1 == NULL) return NULL;
+  if (word == NULL)
+    n1->word = NULL;
+  else
+    {
+      n1->word = strdup (word);
+      if (n1->word == NULL)
+        {
+          free (n1);
+          return NULL;
+        }
+    }
+  n1->next       = NULL;
+  n1->type       = type;
+  n1->value      = value;
+  n1->value_pre  = 0;
+  n1->value_post = 0;
+  n1->pre        = NULL;
+  n1->post       = NULL;
+  n1->info       = info;
+  return n1;
+}
+
+
+static int lb_add (struct lb *p, char type, int value, const char *word,
+                   int value_pre, char *pre, int value_post, char *post,
+                   const void *info)
+{
+  struct node *n1;
+
+  n1 = lb_new (p, type, value, word, info);
+  if (n1 == NULL) return LB_NOMEM;
+  n1->pre        = pre;
+  n1->post       = post;
+  n1->value_pre  = value_pre;
+  n1->value_post = value_post;
+  *(p->node_add) = n1;
+  p->node_add = &n1->next;
+  return 0;
+}
+
+
+int lb_penalty (struct lb *p, int penalty)
+{
+  return lb_add (p, NODE_PENALTY, penalty, NULL, 0, NULL, 0, NULL, NULL);
+}
+
+
+int lb_word (struct lb *p, int width, const char *word, const void *info)
+{
+  return lb_add (p, NODE_WORD, width, word, 0, NULL, 0, NULL, info);
+}
+
+
+int lb_discr (struct lb *p, int width_word, const char *word,
+              int width_pre, const char *pre, int width_post, const char *post,
+              const void *info)
+{
+  char *p1, *p2;
+  int rc;
+
+  if (pre == NULL)
+    p1 = NULL;
+  else
+    {
+      p1 = strdup (pre);
+      if (p1 == NULL)
+        return LB_NOMEM;
+    }
+  if (post == NULL)
+    p2 = NULL;
+  else
+    {
+      p2 = strdup (post);
+      if (p2 == NULL)
+        {
+          if (p1 != NULL) free (p1);
+          return LB_NOMEM;
+        }
+    }
+  rc = lb_add (p, NODE_DISCR, width_word, word, width_pre, p1, width_post, p2,
+               info);
+  if (rc != 0)
+    {
+      if (p1 != NULL) free (p1);
+      if (p2 != NULL) free (p2);
+    }
+  return rc;
+}
+
+
+int lb_hyphen (struct lb *p, int width, const void *info)
+{
+  return lb_discr (p, 0, "", width, "-", 0, "", info);
+}
+
+
+int lb_glue (struct lb *p, int width, const void *info)
+{
+  return lb_add (p, NODE_GLUE, width, NULL, 0, NULL, 0, NULL, info);
+}
+
+
+int lb_first_rmargin (struct lb *p, int margin)
+{
+  if (margin < 1)
+    return LB_INVAL;
+  p->rmargin_1 = margin;
+  return 0;
+}
+
+
+int lb_first_lmargin (struct lb *p, int margin)
+{
+  if (margin < 0)
+    return LB_INVAL;
+  p->lmargin_1 = margin;
+  return 0;
+}
+
+
+int lb_use_hyphenation (struct lb *p, const struct lbh *h)
+{
+  p->hyphenation = h;
+  return 0;
+}
+
+
+static int lb_hyphenation (struct lb *p)
+{
+  struct node *n1, *n2, *n3;
+  const struct hword *hw;
+  const char *start, *hyph;
+  char *pre;
+  int len;
+
+  for (n1 = p->node_list; n1 != NULL; n1 = n1->next)
+    if (n1->type == NODE_WORD && strchr (n1->word, LB_HYPHEN) == NULL
+        && (hw = lbh_find (p->hyphenation, n1->word)) != NULL)
+      {
+        start = hw->str;
+        free (n1->word); n1->word = NULL;
+        while ((hyph = strchr (start, LB_HYPHEN)) != NULL)
+          {
+            if (hyph != start && hyph[-1] == '-')
+              pre = NULL;
+            else
+              {
+                pre = strdup ("-");
+                if (pre == NULL) return LB_NOMEM;
+              }
+
+            n2 = lb_new (p, NODE_DISCR, 0, NULL, n1->info);
+            if (n2 == NULL) return LB_NOMEM;
+            n2->pre = pre;
+            n2->value_pre = (pre != NULL ? (int)strlen (pre) : 0);
+            n2->next = n1->next; n1->next = n2;
+
+            n3 = lb_new (p, NODE_WORD, 0, NULL, n1->info);
+            if (n3 == NULL) return LB_NOMEM;
+            n3->next = n2->next; n2->next = n3;
+
+            len = hyph - start;
+            n1->value = len;
+            n1->word = malloc ((size_t)(len + 1));
+            if (n1->word == NULL) return LB_NOMEM;
+            memcpy (n1->word, start, (size_t)len);
+            n1->word[len] = 0;
+
+            n1 = n3;
+            start = hyph + 1;
+          }
+        n1->value = (int)strlen (start);
+        n1->word = strdup (start);
+        if (n1->word == NULL) return LB_NOMEM;
+      }
+  return 0;
+}
+
+
+static void lb_add_brkp (struct lb *p, struct node *n1, int store)
+{
+  if (store)
+    p->brkps[p->brkp_count].node = n1;
+  ++p->brkp_count;
+}
+
+
+static int lb_find_brkps (struct lb *p, int store)
+{
+  struct node *n1;
+
+  p->brkp_count = 0;
+  n1 = p->node_list;
+  lb_add_brkp (p, n1, store);
+  while (n1 != NULL)
+    switch (n1->type)
+      {
+      case NODE_WORD:
+        n1 = n1->next;
+        break;
+      case NODE_PENALTY:
+        if (n1->value != LB_INFINITY)
+          lb_add_brkp (p, n1, store);
+        while (n1 != NULL && n1->type != NODE_WORD)
+          n1 = n1->next;
+        break;
+      case NODE_GLUE:
+        lb_add_brkp (p, n1, store);
+        while (n1 != NULL && n1->type == NODE_GLUE)
+          n1 = n1->next;
+        break;
+      case NODE_DISCR:
+        lb_add_brkp (p, n1, store);
+        n1 = n1->next;
+        break;
+      default:
+        return LB_INTERN;
+      }
+  return 0;
+}
+
+
+static int cost_add (int c1, int c2)
+{
+  if (c1 >= LB_INFINITY || c2 >= LB_INFINITY || c1 + c2 >= LB_INFINITY)
+    return LB_INFINITY;
+  else
+    return c1 + c2;
+}
+
+
+#define DISTANCE(P,B1,B2) ((P)->distance[(B1) * (P)->brkp_count + (B2)])
+
+static int lb_compute_distance (struct lb *p)
+{
+  int i, j, c, w, w0, hc;
+  struct node *n0, *n1, *n2;
+
+  p->distance = malloc ((size_t)(p->brkp_count * p->brkp_count
+                                 * sizeof (int)));
+  if (p->distance == NULL) return LB_NOMEM;
+
+  for (i = 0; i < p->brkp_count; ++i)
+    {
+      DISTANCE (p, i, i) = 0;
+      for (j = i + 1; j < p->brkp_count; ++j)
+        {
+          n0 = p->brkps[i].node;
+          n2 = p->brkps[j].node;
+          w = 0; hc = 0;
+          /* Discard glue at the beginning of a line unless preceded
+             by a penalty. */
+          n1 = n0;
+          while (n1 != NULL && n1->type == NODE_GLUE)
+            n1 = n1->next;
+          for (; n1 != NULL; n1 = n1->next)
+            {
+              switch (n1->type)
+                {
+                case NODE_WORD:
+                  w += n1->value;
+                  break;
+                case NODE_GLUE:
+                  w += n1->value; /* Rigid glue */
+                  break;
+                case NODE_PENALTY:
+                  break;
+                case NODE_DISCR:
+                  if (n1 == n0)
+                    w += n1->value_post;
+                  else if (n1 == n2)
+                    {
+                      w += n1->value_pre;
+                      hc = HYPHEN_PENALTY;
+                    }
+                  else
+                    w += n1->value;
+                  break;
+                default:
+                  return LB_INTERN;
+                }
+              if (n1 == n2)
+                break;
+            }
+
+          if (i == 0)
+            w0 = p->rmargin_1 - p->lmargin_1;
+          else
+            w0 = p->rmargin - p->lmargin;
+
+          if (w > w0)
+            c = LB_INFINITY;
+          else if (j == p->brkp_count - 1)
+            {
+              /* The length of the last line of a paragraph does not
+                 matter.  Note that n2 is a penalty node with a value
+                 of 0. */
+              c = 0;
+            }
+          else if (w0 - w > LB_SQRT_INFINITY)
+            c = LB_INFINITY;
+          else
+            c = (w0 - w) * (w0 - w);
+          if (n2->type == NODE_PENALTY)
+            c = cost_add (c, n2->value);
+          c = cost_add (c, hc);
+
+          DISTANCE (p, i, j) = c;
+          DISTANCE (p, j, i) = c;
+        }
+    }
+
+#if 0
+  fprintf (stderr, "@@DISTANCE:\n");
+  for (i = 0; i < p->brkp_count; ++i)
+    {
+      for (j = 0; j < p->brkp_count; ++j)
+        fprintf (stderr, "%6d", DISTANCE (p, i, j));
+      fprintf (stderr, "\n");
+    }
+  fprintf (stderr, "@@END\n");
+#endif
+  return 0;
+}
+
+
+static int lb_dijkstra (struct lb *p)
+{
+  int i, j, n, best, bcost, c;
+
+  n = p->brkp_count;
+
+  for (i = 0; i < n; ++i)
+    {
+      p->brkps[i].cost = DISTANCE (p, 0, i);
+      p->brkps[i].chain = 0;
+      p->brkps[i].special = FALSE;
+    }
+  p->brkps[0].special = TRUE;
+
+  for (i = 1; i < n; ++i)
+    {
+      best = 0; bcost = LB_INFINITY + 1;
+      for (j = 0; j < n; ++j)
+        if (!p->brkps[j].special && p->brkps[j].cost < bcost)
+          {
+            best = j; bcost = p->brkps[j].cost;
+          }
+      if (best == n - 1)
+        break;
+      p->brkps[best].special = TRUE;
+      for (j = best + 1; j < n; ++j)
+        if (!p->brkps[j].special)
+          {
+            c = bcost + DISTANCE (p, best, j);
+            if (c < p->brkps[j].cost)
+              {
+                p->brkps[j].cost = c;
+                p->brkps[j].chain = best;
+              }
+          }
+    }
+  return 0;
+}
+
+
+static int lb_reverse (struct lb *p)
+{
+  int i, j, k;
+
+  i = p->brkp_count - 1;
+  j = -1;
+  while (i != 0)
+    {
+      if (p->brkps[i].chain >= i)
+        return LB_INTERN;
+      k = p->brkps[i].chain; p->brkps[i].chain = j; j = i; i = k;
+    }
+  p->brkps[0].chain = j;
+
+#if 0
+  fprintf (stderr, "[");
+  for (i = 0; i != -1; i = p->brkps[i].chain)
+    fprintf (stderr, " %d", i);
+  fprintf (stderr, "]\n");
+#endif
+
+  return 0;
+}
+
+
+static int lb_break (struct lb *p)
+{
+  int i;
+  struct node **nn, *n2, *n3, *nb;
+
+  i = p->brkps[0].chain;
+  nb = (i >= p->brkp_count - 1 ? NULL : p->brkps[i].node);
+  for (nn = &p->node_list; *nn != NULL; nn = &(*nn)->next)
+    {
+      if ((*nn) == nb)
+        {
+          switch (nb->type)
+            {
+            case NODE_DISCR:
+              n2 = lb_new (p, NODE_NEWLINE, 0, NULL, NULL);
+              n2->next = (*nn)->next; (*nn) = n2;
+
+              if (nb->pre != NULL && nb->pre[0] != 0)
+                {
+                  n2 = lb_new (p, NODE_PRE, nb->value_pre, nb->pre, NULL);
+                  n2->next = (*nn); (*nn) = n2;
+                  nn = &n2->next;
+                }
+
+              if (nb->post != NULL && nb->post[0] != 0)
+                {
+                  n2 = lb_new (p, NODE_POST, nb->value_post, nb->post, NULL);
+                  n2->next = (*nn)->next; (*nn)->next = n2;
+                  nn = &n2->next;
+                }
+
+              lb_free_node (nb);
+              break;
+
+            case NODE_GLUE:
+              (*nn)->type = NODE_NEWLINE;
+              for (n2 = (*nn)->next; n2 != NULL && n2->type == NODE_GLUE;
+                   n2 = n3)
+                {
+                  n3 = n2->next;
+                  lb_free_node (n2);
+                }
+              (*nn)->next = n2;
+              break;
+
+            case NODE_PENALTY:
+              n2 = lb_new (p, NODE_NEWLINE, 0, NULL, NULL);
+              n2->next = (*nn); (*nn) = n2;
+              break;
+
+            default:
+              return LB_INTERN;
+            }
+          i = p->brkps[i].chain;
+          nb = (i >= p->brkp_count - 1 ? NULL : p->brkps[i].node);
+        }
+    }
+  return 0;
+}
+
+
+int lb_format (struct lb *p)
+{
+  int rc;
+
+  rc = lb_penalty (p, 0);
+  if (rc != 0) return rc;
+
+  if (p->hyphenation != NULL)
+    {
+      rc = lb_hyphenation (p);
+      if (rc != 0) return rc;
+    }
+
+  rc = lb_find_brkps (p, FALSE);
+  if (rc != 0) return rc;
+  p->brkps = malloc ((size_t)(p->brkp_count * sizeof (struct brkp)));
+  if (p->brkps == NULL) return LB_NOMEM;
+  rc = lb_find_brkps (p, TRUE);
+  if (rc != 0) return rc;
+
+  rc = lb_compute_distance (p);
+  if (rc != 0) return rc;
+
+  rc = lb_dijkstra (p);
+  if (rc != 0) return rc;
+
+  rc = lb_reverse (p);
+  if (rc != 0) return rc;
+
+  rc = lb_break (p);
+  if (rc != 0) return rc;
+
+  p->cur_node = p->node_list;
+  return 0;
+}
+
+
+int lb_next (struct lb *p, struct lb_node *dst)
+{
+  const struct node *n1;
+
+redo:
+  n1 = p->cur_node;
+  if (n1 == NULL)
+    {
+      dst->type  = LBN_END;
+      dst->value = 0;
+      dst->word  = NULL;
+      dst->info  = NULL;
+      return 0;
+    }
+  p->cur_node = p->cur_node->next;
+
+  switch (n1->type)
+    {
+    case NODE_WORD:
+    case NODE_DISCR:
+      if (n1->word == NULL || n1->word[0] == 0)
+        goto redo;
+      dst->type = LBN_WORD;
+      break;
+    case NODE_PRE:
+      dst->type = LBN_PRE;
+      break;
+    case NODE_POST:
+      dst->type = LBN_POST;
+      break;
+    case NODE_GLUE:
+      dst->type = LBN_GLUE;
+      break;
+    case NODE_PENALTY:
+      goto redo;
+    case NODE_NEWLINE:
+      dst->type = LBN_NEWLINE;
+      break;
+    default:
+      return LB_INTERN;
+    }
+  dst->value = n1->value;
+  dst->word  = n1->word;
+  dst->info  = n1->info;
+  return 0;
+}
+
+
+int lbh_init (struct lbh **pp)
+{
+  struct lbh *p;
+  int i;
+
+  *pp = NULL;
+  p = malloc (sizeof (struct lbh));
+  if (p == NULL) return LB_NOMEM;
+  for (i = 0; i < HASH_SIZE; ++i)
+    p->hash_table[i] = NULL;
+  *pp = p;
+  return 0;
+}
+
+
+int lbh_exit (struct lbh **pp)
+{
+  struct lbh *p;
+  struct hword *w1, *w2;
+  int i;
+
+  p = *pp; *pp = NULL;
+  if (p != NULL)
+    {
+      for (i = 0; i < HASH_SIZE; ++i)
+        for (w1 = p->hash_table[i]; w1 != NULL; w1 = w2)
+          {
+            w2 = w1->next;
+            free (w1->str);
+            free (w1);
+          }
+      free (p);
+    }
+  return 0;
+}
+
+
+static unsigned lbh_hash (const char *s)
+{
+  const unsigned char *u;
+  unsigned h;
+
+  h = 0;
+  for (u = s; *u != 0; ++u)
+    if (*u != LB_HYPHEN)
+      h = (h << 2) ^ *u;
+  return h % HASH_SIZE;
+}
+
+
+static int lbh_equal (const char *s1, const char *s2)
+{
+  while (*s1 != 0 || *s2 != 0)
+    {
+      if (*s1 == LB_HYPHEN)
+        ++s1;
+      else if (*s2 == LB_HYPHEN)
+        ++s2;
+      else if (*s1 == *s2)
+        ++s1, ++s2;
+      else
+        return FALSE;
+    }
+  return TRUE;
+}
+
+
+int lbh_word (struct lbh *p, const char *s)
+{
+  unsigned h;
+  struct hword *w;
+
+  h = lbh_hash (s);
+  for (w = p->hash_table[h]; w != NULL; w = w->next)
+    if (lbh_equal (w->str, s))
+      return (strcmp (w->str, s) == 0 ? 0 : LB_INVAL);
+  w = malloc (sizeof (struct hword));
+  if (w == NULL) return LB_NOMEM;
+  w->str = strdup (s);
+  if (w->str == NULL)
+    {
+      free (w);
+      return LB_NOMEM;
+    }
+  w->next = p->hash_table[h];
+  p->hash_table[h] = w;
+  return 0;
+}
+
+
+static const struct hword *lbh_find (const struct lbh *p, const char *s)
+{
+  unsigned h;
+  struct hword *w;
+
+  h = lbh_hash (s);
+  for (w = p->hash_table[h]; w != NULL; w = w->next)
+    if (lbh_equal (w->str, s))
+      return w;
+  return NULL;
+}
Index: trunk/src/emx/src/emxdoc/lb.h
===================================================================
--- trunk/src/emx/src/emxdoc/lb.h	(revision 18)
+++ trunk/src/emx/src/emxdoc/lb.h	(revision 18)
@@ -0,0 +1,67 @@
+/* lb.h -- Line breaking
+   Copyright (c) 1993-1995 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define LB_NOMEM        1
+#define LB_INVAL        2
+#define LB_INTERN       3
+
+#define LBN_WORD        1
+#define LBN_PRE         2
+#define LBN_POST        3
+#define LBN_GLUE        4
+#define LBN_NEWLINE     5
+#define LBN_END         6
+
+#define LB_INFINITY             10000
+#define LB_SQRT_INFINITY        100
+
+#define LB_HYPHEN       '*'
+
+struct lb;
+struct lbh;
+
+struct lb_node
+{
+  int type;
+  int value;
+  const char *word;
+  const void *info;
+};
+
+int lb_init (struct lb **pp, int lmargin, int rmargin);
+int lb_exit (struct lb **p);
+int lb_first_lmargin (struct lb *p, int margin);
+int lb_first_rmargin (struct lb *p, int margin);
+int lb_penalty (struct lb *p, int penalty);
+int lb_word (struct lb *p, int width, const char *word, const void *info);
+int lb_discr (struct lb *p, int width_word, const char *word,
+    int width_pre, const char *pre, int width_post, const char *post,
+    const void *info);
+int lb_hyphen (struct lb *p, int width, const void *info);
+int lb_glue (struct lb *p, int width, const void *info);
+int lb_format (struct lb *p);
+int lb_next (struct lb *p, struct lb_node *dst);
+
+int lb_use_hyphenation (struct lb *p, const struct lbh *h);
+
+int lbh_init (struct lbh **pp);
+int lbh_word (struct lbh *p, const char *s);
+int lbh_exit (struct lbh **pp);
Index: trunk/src/emx/src/emxdoc/makefile
===================================================================
--- trunk/src/emx/src/emxdoc/makefile	(revision 18)
+++ trunk/src/emx/src/emxdoc/makefile	(revision 18)
@@ -0,0 +1,63 @@
+#
+# /emx/src/emxdoc/makefile
+#
+# Copyright (c) 1993-1999 by Eberhard Mattes
+#
+# This file is part of emxdoc.
+#
+# emxdoc is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emxdoc is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emxdoc; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+.SUFFIXES: .c .o
+
+BIN=d:\emx\bin\ #
+
+CC=gcc
+CFLAGS=-O -Wall
+LFLAGS=-s -Zsmall-conv
+#CFLAGS=-g -Wall
+#LFLAGS=-g
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+default:	all
+all:		emxdoc
+emxdoc:		$(BIN)emxdoc.exe
+
+emxdoc.o: emxdoc.c emxdoc.h html.h ipf.h latex.h text.h xref.h cond.h
+input.o:  input.c emxdoc.h cond.h
+cond.o:   cond.c emxdoc.h cond.h
+html.o:   html.c emxdoc.h html.h xref.h
+ipf.o:    ipf.c emxdoc.h ipf.h xref.h
+latex.o:  latex.c emxdoc.h latex.h
+text.o:   text.c emxdoc.h lb.h text.h
+xref.o:   xref.c emxdoc.h xref.h
+lb.o:    lb.c lb.h
+
+$(BIN)emxdoc.exe: emxdoc.o input.o cond.o html.o ipf.o latex.o text.o \
+		xref.o lb.o
+	gcc $(LFLAGS) -o $(BIN)emxdoc.exe emxdoc.o input.o cond.o \
+		html.o ipf.o latex.o text.o xref.o lb.o
+
+
+clean:
+	-del *.o
+
+realclean: clean
+	-del $(BIN)emxdoc.exe
+
+# End of /emx/src/emxdoc/makefile
Index: trunk/src/emx/src/emxdoc/text.c
===================================================================
--- trunk/src/emx/src/emxdoc/text.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/text.c	(revision 18)
@@ -0,0 +1,465 @@
+/* text.c -- Text output
+   Copyright (c) 1993-1999 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "emxdoc.h"
+#include "text.h"
+#include "lb.h"
+
+static int text_width = 70;
+static int format_width;
+static int format_margin;
+static struct lb *lb;
+static struct lbh *lbh = NULL;
+
+static void text_indent (int margin)
+{
+  uchar *s;
+  int i;
+
+  i = margin - output_x;
+  if (i > 0)
+    {
+      s = alloca (i);
+      memset (s, ' ', i);
+      write_nstring (s, i);
+    }
+}
+
+
+static void text_para (void)
+{
+  if (para_flag)
+    {
+      para_flag = FALSE;
+      write_nl ();
+    }
+}
+
+
+static int isblank (const uchar *p)
+{
+  while (*p != 0)
+    if (*p++ != ' ')
+      return FALSE;
+  return TRUE;
+}
+
+
+void text_output (const uchar *p, int may_break)
+{
+  if (opt_b == 0)
+    {
+      if (may_break && output_x + strlen (p) > format_width)
+        write_nl ();
+      text_indent (format_margin);
+      write_string (p);
+    }
+  else
+    {
+      int rc;
+
+      if (may_break && isblank (p))
+        rc = lb_glue (lb, strlen (p), NULL);
+      else
+        rc = lb_word (lb, strlen (p), p, NULL);
+      if (rc != 0)
+        fatal ("lb_glue or lb_word failed, rc=%d", rc);
+    }
+}
+
+
+static int text_elements (int margin, int width, int newline)
+{
+  const struct element *ep, *ep2;
+  int i, spaces, line, rc;
+  enum style style_stack[STYLE_STACK_SIZE];
+  int style_sp;
+  enum style style = STYLE_NORMAL;
+
+  style_sp = 0;
+  style_stack[style_sp] = style;
+  line = output_line_no; spaces = 0;
+  format_width = width; format_margin = margin;
+  if (opt_b != 0)
+    {
+      rc = lb_init (&lb, margin, width);
+      if (rc != 0)
+        fatal ("lb_init failed, rc=%d", rc);
+      if (output_x > margin)
+        lb_first_lmargin (lb, output_x);
+    }
+
+  for (ep = elements; ep->el != EL_END; ++ep)
+    switch (ep->el)
+      {
+      case EL_WORD:
+      case EL_PUNCT:
+        if (spaces != 0)
+          {
+            format_spaces (spaces, STYLE_NORMAL, TRUE); spaces = 0;
+          }
+        if (ep->wp->special != NULL && ep->wp->special->text != NULL)
+          format_output (ep->wp->special->text, FALSE);
+        else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
+          format_string (ep->wp->str, (ep->wp->style != STYLE_NORMAL
+                                       ? ep->wp->style : style), FALSE);
+        else
+          format_string (ep->wp->str, style_stack[style_sp], FALSE);
+        break;
+      case EL_SPACE:
+        if (opt_b == 0)
+          {
+            spaces += ep->n;
+            i = 0;
+            ep2 = ep + 1;
+            while (ep2->el != EL_END && ep2->el != EL_SPACE)
+              {
+                if (ep2->el == EL_WORD || ep2->el == EL_PUNCT)
+                  i += strlen (ep2->wp->str);
+                ++ep2;
+              }
+            if (output_x + spaces + i > format_width)
+              {
+                write_nl ();
+                spaces = 0;
+              }
+          }
+        else
+          format_spaces (ep->n, STYLE_NORMAL, TRUE);
+        break;
+      case EL_BREAK:
+        if (opt_b == 0)
+          {
+            if (output_x != 0 || ep->n)
+              {
+                write_nl (); spaces = 0;
+              }
+          }
+        else
+          lb_penalty (lb, -10000);
+        break;
+      case EL_STYLE:
+        if (style_sp + 1 >= STYLE_STACK_SIZE)
+          fatal ("%s:%d: Style stack overflow", input_fname, line_no);
+        style_stack[++style_sp] = ep->n;
+        break;
+      case EL_ENDSTYLE:
+        if (style_sp == 0)
+          fatal ("%s:%d: Style stack underflow", input_fname, line_no);
+        --style_sp;
+        break;
+      default:
+        abort ();
+      }
+
+  if (opt_b != 0)
+    {
+      struct lb_node lbn;
+
+      if (lbh != NULL)
+        lb_use_hyphenation (lb, lbh);
+      rc = lb_format (lb);
+      if (rc != 0)
+        fatal ("lb_format failed, rc=%d", rc);
+      for (;;)
+        {
+          rc = lb_next (lb, &lbn);
+          if (rc != 0)
+            fatal ("lb_next failed, rc=%d", rc);
+          if (lbn.type == LBN_END)
+            break;
+          switch (lbn.type)
+            {
+            case LBN_WORD:
+            case LBN_PRE:
+            case LBN_POST:
+              text_indent (margin);
+              write_string (lbn.word);
+              break;
+            case LBN_GLUE:
+              text_indent (margin);
+              write_fmt ("%*s", lbn.value, "");
+              break;
+            case LBN_NEWLINE:
+              write_nl ();
+              break;
+            default:
+              abort ();
+            }
+        }
+      lb_exit (&lb);
+    }
+
+  if (newline && output_x > margin)
+    write_nl ();
+  return output_line_no - line;
+}
+
+
+void text_heading1 (void)
+{
+  env_stack[0].tmargin = 0;
+  write_nl ();
+  write_nl ();
+}
+
+
+void text_heading2 (uchar *s)
+{
+  if (tg_level == 0)
+    {
+      if (para_flag)
+        write_nl ();
+      write_nl ();
+    }
+  write_line (s);
+  memset (s, tg_underline, strlen (s));
+  write_line (s);
+}
+
+
+void text_see_also_start (void)
+{
+  if (para_flag)
+    write_nl ();
+}
+
+
+void text_see_also_end (const uchar *s)
+{
+  write_string ("  See also: ");
+  make_elements (s);
+  text_elements (output_x, text_width, TRUE);
+}
+
+
+void text_description_item (const uchar *s)
+{
+  write_nl ();
+  text_para ();
+  make_elements (s);
+  text_elements (env_stack[env_sp-1].tmargin, text_width, FALSE);
+  if (output_x + 2 <= env_stack[env_sp].tmargin)
+    write_string ("  ");
+  else
+    write_nl ();
+}
+
+
+void text_enumerate_item (void)
+{
+  write_nl ();
+  text_para ();
+  text_indent (env_stack[env_sp-1].tmargin);
+  write_fmt ("%d.", ++env_stack[env_sp].counter);
+}
+
+
+void text_itemize_item (void)
+{
+  write_nl ();
+  text_para ();
+  text_indent (env_stack[env_sp-1].tmargin);
+  write_string ("- ");
+}
+
+
+void text_list_item (const uchar *s)
+{
+  write_nl ();
+  text_para ();
+  make_elements (s);
+  text_elements (env_stack[env_sp-1].tmargin, text_width, TRUE);
+  write_nl ();
+}
+
+
+void text_copy (void)
+{
+  if (para_flag)
+    write_nl ();
+  text_elements (env_stack[env_sp].tmargin, text_width, TRUE);
+}
+
+
+void text_verbatim_start (enum tag tag_end, int *ptmargin)
+{
+  switch (tag_end)
+    {
+    case TAG_ENDHEADERS:
+      break;
+    case TAG_ENDSAMPLECODE:
+      write_nl ();
+      write_line ("  Example:");
+      write_nl ();
+      break;
+    case TAG_ENDEXAMPLE:
+      *ptmargin += 4;
+      write_nl ();
+      break;
+    default:
+      write_nl ();
+      break;
+    }
+}
+
+
+static void add_compat (uchar *dst, uchar *compat)
+{
+  int i, len;
+
+  len = strlen (dst);
+  i = 78 - len - strlen (compat) - 2;
+  if (i > 0)
+    {
+      memset (dst + len, ' ', i);
+      len += i;
+    }
+  dst[len++] = '[';
+  strcpy (dst+len, compat);
+  strcat (dst+len, "]");
+  compat[0] = 0;
+}
+
+
+void text_verbatim_line (enum tag tag_end, int tmargin, uchar *compat)
+{
+  uchar buf[512];
+
+  memset (buf, ' ', tmargin);
+  strcpy (buf + tmargin, input);
+  if (tag_end == TAG_ENDHEADERS && compat[0] != 0)
+    add_compat (buf, compat);
+  write_line (buf);
+}
+
+
+void text_function (void)
+{
+  env_stack[0].tmargin = 0;
+  write_nl ();
+  write_line("---------------------------------------"
+             "---------------------------------------");
+}
+
+
+void text_prototype_start (uchar *compat)
+{
+  uchar buf[512];
+
+  if (compat[0] != 0)
+    {
+      buf[0] = 0;
+      add_compat (buf, compat);
+      write_string (buf);
+    }
+  write_nl ();
+}
+
+
+void text_prototype_end (void)
+{
+  text_elements (0, 78, TRUE);
+  env_stack[0].tmargin = 4;
+}
+
+
+void text_toc_line (const uchar *s, const struct toc *tp)
+{
+  write_string (s);
+  write_line (tp->title);
+}
+
+
+void text_table_start (int do_indent, int *ptmargin)
+{
+  if (do_indent)
+    *ptmargin += 4;
+  write_nl ();
+}
+
+
+void text_table_line (const uchar *s, int tmargin)
+{
+  make_elements (s);
+  if (text_elements (tmargin, 78, TRUE) > 1)
+    fatal ("%s:%d: Table entry too long", input_fname, line_no);
+}
+
+
+void text_sample_file (const uchar *s)
+{
+  if (para_flag)
+    write_nl ();
+  write_string ("  Example: See ");
+  write_line (s);
+}
+
+
+void text_libref_section (const uchar *s)
+{
+  if (para_flag)
+    write_nl ();
+  write_fmt ("  %s:", s);
+  write_nl ();
+  para_flag = TRUE;
+}
+
+
+void text_hyphenation (const char *name)
+{
+  FILE *f;
+  char line[128], *p;
+  int line_no, rc;
+
+  if (opt_b == 0)
+    return;
+  rc = lbh_init (&lbh);
+  if (rc != 0)
+    fatal ("lb_init failed, rc=%d", rc);
+  f = fopen (name, "rt");
+  if (f == NULL)
+    {
+      perror (name);
+      exit (1);
+    }
+  line_no = 0;
+  while (fgets (line, sizeof (line), f) != NULL)
+    {
+      ++line_no;
+      p = strchr (line, '\n');
+      if (p == NULL)
+        fatal ("%s:%d: Line too long", name, line_no);
+      *p = 0;
+      rc = lbh_word (lbh, line);
+      if (rc != 0)
+        fatal ("lbh_word failed, rc=%d", rc);
+    }
+  if (ferror (f))
+    {
+      perror (name);
+      exit (1);
+    }
+  fclose (f);
+}
Index: trunk/src/emx/src/emxdoc/text.h
===================================================================
--- trunk/src/emx/src/emxdoc/text.h	(revision 18)
+++ trunk/src/emx/src/emxdoc/text.h	(revision 18)
@@ -0,0 +1,42 @@
+/* text.h -- Text output
+   Copyright (c) 1993-1995 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+void text_output (const uchar *p, int may_break);
+void text_heading1 (void);
+void text_heading2 (uchar *s);
+void text_see_also_start (void);
+void text_see_also_end (const uchar *s);
+void text_description_item (const uchar *s);
+void text_enumerate_item (void);
+void text_itemize_item (void);
+void text_list_item (const uchar *s);
+void text_copy (void);
+void text_verbatim_start (enum tag tag_end, int *ptmargin);
+void text_verbatim_line (enum tag tag_end, int tmargin, uchar *compat);
+void text_function (void);
+void text_prototype_start (uchar *compat);
+void text_prototype_end (void);
+void text_toc_line (const uchar *s, const struct toc *tp);
+void text_table_start (int do_indent, int *ptmargin);
+void text_table_line (const uchar *s, int tmargin);
+void text_sample_file (const uchar *s);
+void text_libref_section (const uchar *s);
+void text_hyphenation (const char *name);
Index: trunk/src/emx/src/emxdoc/xref.c
===================================================================
--- trunk/src/emx/src/emxdoc/xref.c	(revision 18)
+++ trunk/src/emx/src/emxdoc/xref.c	(revision 18)
@@ -0,0 +1,284 @@
+/* xref.c -- Manage cross references
+   Copyright (c) 1993-1999 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "emxdoc.h"
+#include "xref.h"
+
+#ifndef _MAX_FNAME
+
+/* Quick and dirty implementation of a subset of _splitpath() for
+   systems which don't have _splitpath(). */
+
+#include <sys/param.h>
+#include <assert.h>
+#define _MAX_FNAME MAXPATHLEN
+
+static void _splitpath (const char *src, char *drv, char *dir,
+			char *base, char *ext)
+{
+  const char *p, *q;
+  size_t n;
+
+  assert (drv == NULL); assert (dir == NULL); assert (ext == NULL);
+  assert (src != NULL); assert (base != NULL);
+
+  p = strrchr (src, '/');
+  if (p == NULL)
+    p = src;
+  q = strchr (p, '.');
+  if (q == NULL)
+    n = strlen (p);
+  else
+    n = q - p;
+  assert (n < _MAX_FNAME);
+  memcpy (base, p, n);
+  base[n] = 0;
+}
+
+#endif
+
+static int first_keyword_flag = TRUE;
+static char inf_name[_MAX_FNAME] = "";
+
+
+void write_keyword (const uchar *p)
+{
+  int len;
+
+  if (*p != 0 && strpbrk (p, " ,") == NULL)
+    {
+      if (first_keyword_flag)
+        {
+          if (title != NULL)
+            fprintf (output_file, "DESCRIPTION: %s\n", title);
+          else
+            fprintf (output_file, "DESCRIPTION: %s.inf\n", inf_name);
+          first_keyword_flag = FALSE;
+        }
+      len = strlen (p);
+      if (len > 2 && p[len-2] == '(' && p[len-1] == ')')
+        len -= 2;
+      fprintf (output_file, "(%.*s, view %s ~)\n", len, p, inf_name);
+    }
+}
+
+
+static void gather_define (struct word *wp)
+{
+  fprintf (output_file, "d %d %s\n", wp->ref, wp->str);
+}
+
+
+static void gather_reference (const uchar *p)
+{
+  struct word *wp;
+
+  fprintf (output_file, "r %s\n", p);
+  wp = word_add (p);
+  wp->ref = -1;
+}
+
+
+struct word *define_label (const uchar *p, int ref, const char *msg)
+{
+  struct word *wp;
+
+  wp = word_add (p);
+  if (wp->ref != 0)
+    {
+      if (wp->database == NULL || wp->ref != ref)
+        fatal ("%s:%d: %s %s multiply defined", input_fname, line_no, msg, p);
+    }
+  else
+    {
+      wp->ref = ref;
+      if (opt_g)
+        gather_define (wp);
+    }
+  return wp;
+}
+
+
+struct word *use_reference (const uchar *p)
+{
+  struct word *wp;
+
+  wp = word_find (p, word_hash (p));
+  if ((wp == NULL || wp->ref == 0) && mode != 'T' && mode != 'L')
+    {
+      if (!opt_g)
+        fatal ("%s:%d: Undefined label: %s", input_fname, line_no, p);
+      gather_reference (p);
+      return NULL;
+    }
+  else
+    return wp;
+}
+
+
+/* Misuse the style field of struct word */
+
+#define STYLE_UNUSED STYLE_NORMAL
+#define STYLE_USED   STYLE_BOLD
+
+void make_global (const uchar *name)
+{
+  struct word *wdb, *wp;
+  const uchar *p;
+  char *tmp;
+  long n;
+  char database[_MAX_FNAME];
+
+  open_input (name);
+  init_file ();
+  wdb = NULL;
+  if (!out)
+    {
+      _splitpath (input_fname, NULL, NULL, database, NULL);
+      wdb = word_add (database);
+    }
+  read_line ();
+  while (!end_of_file)
+    {
+      p = input + 1;
+      while (isspace (*p))
+        ++p;
+      switch (input[0])
+        {
+        case 'd':
+          if (!out)
+            {
+              errno = 0;
+              n = strtol (p, &tmp, 10);
+              if (errno != 0 || *tmp != ' ')
+                fatal ("%s:%d: Invalid reference number",
+                       input_fname, line_no);
+              p = tmp;
+              while (isspace (*p))
+                ++p;
+              wp = word_add (p);
+              if (wp->ref != 0)
+                fatal ("%s:%d: Label %s already defined",
+                       input_fname, line_no, p);
+              wp->ref = (int)n;
+              wp->style = STYLE_UNUSED;
+              wp->database = wdb;
+            }
+          break;
+        case 'r':
+          if (out)
+            {
+              wp = word_find (p, word_hash (p));
+              if (wp == NULL || wp->ref == 0)
+                fatal ("%s:%d: Label %s not defined",
+                       input_fname, line_no, p);
+              if (wp->style == STYLE_UNUSED)
+                {
+                  fprintf (output_file, "x %d %s %s\n",
+                           wp->ref, wp->database->str, p);
+                  wp->style = STYLE_USED;
+                }
+            }
+          break;
+        }
+      read_line ();
+    }
+  fclose (input_file);
+}
+
+
+void keywords_keyword (const uchar *s)
+{
+  uchar word[512], *d;
+
+  while (*s != 0)
+    {
+      d = word;
+      while (*s != 0 && !isspace (*s))
+        *d++ = *s++;
+      *d = 0;
+      write_keyword (word);
+      while (isspace (*s))
+        ++s;
+    }
+}
+
+
+void keywords_start (const char *fname)
+{
+  _splitpath (fname, NULL, NULL, inf_name, NULL);
+  fprintf (output_file, "EXTENSIONS: *\n");
+}
+
+
+void read_xref (const char *fname, struct toc *th)
+{
+  struct word *wp;
+  uchar database[512], *d;
+  const uchar *p;
+  char *tmp;
+  long n;
+  struct toc *tp;
+
+  open_input (fname);
+  read_line ();
+  while (!end_of_file)
+    {
+      if (input[0] != 'x')
+        fatal ("%s:%d: Syntax error", fname, line_no);
+      p = input + 1;
+      while (isspace (*p))
+        ++p;
+      errno = 0;
+      n = strtol (p, &tmp, 10);
+      if (errno != 0 || *tmp != ' ')
+        fatal ("%s:%d: Syntax error", fname, line_no);
+      p = tmp;
+      while (isspace (*p))
+        ++p;
+      d = database;
+      while (*p != 0 && !isspace (*p))
+        *d++ = *p++;
+      *d = 0;
+      while (isspace (*p))
+        ++p;
+      if (d == database || *p == 0)
+        fatal ("%s:%d: Syntax error", fname, line_no);
+      if (out)
+        {
+          for (tp = th; tp != NULL; tp = tp->next)
+            if (tp->ref == (int)n)
+              tp->global = TRUE;
+        }
+      else
+        {
+          wp = word_add (p);
+          wp->database = word_add (database);
+          wp->ref = (int)n;
+        }
+      read_line ();
+    }
+  fclose (input_file);
+}
Index: trunk/src/emx/src/emxdoc/xref.h
===================================================================
--- trunk/src/emx/src/emxdoc/xref.h	(revision 18)
+++ trunk/src/emx/src/emxdoc/xref.h	(revision 18)
@@ -0,0 +1,28 @@
+/* xref.h -- Manage cross references
+   Copyright (c) 1993-1995 Eberhard Mattes
+
+This file is part of emxdoc.
+
+emxdoc is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxdoc is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxdoc; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+void write_keyword (const uchar *p);
+struct word *define_label (const uchar *p, int ref, const char *msg);
+struct word *use_reference (const uchar *p);
+void make_global (const uchar *name);
+void keywords_keyword (const uchar *s);
+void keywords_start (const char *fname);
+void read_xref (const char *fname, struct toc *th);
Index: trunk/src/emx/src/emxexp/COPYING
===================================================================
--- trunk/src/emx/src/emxexp/COPYING	(revision 18)
+++ trunk/src/emx/src/emxexp/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxexp/ansidecl.h
===================================================================
--- trunk/src/emx/src/emxexp/ansidecl.h	(revision 18)
+++ trunk/src/emx/src/emxexp/ansidecl.h	(revision 18)
@@ -0,0 +1,139 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro	ANSI C definition	Traditional C definition
+   -----	---- - ----------	----------- - ----------
+   PTR		`void *'		`char *'
+   LONG_DOUBLE	`long double'		`double'
+   VOLATILE	`volatile'		`'
+   SIGNED	`signed'		`'
+   PTRCONST	`void *const'		`char *'
+
+   CONST is also defined, but is obsolete.  Just use const.
+
+   DEFUN (name, arglist, args)
+
+	Defines function NAME.
+
+	ARGLIST lists the arguments, separated by commas and enclosed in
+	parentheses.  ARGLIST becomes the argument list in traditional C.
+
+	ARGS list the arguments with their types.  It becomes a prototype in
+	ANSI C, and the type declarations in traditional C.  Arguments should
+	be separated with `AND'.  For functions with a variable number of
+	arguments, the last thing listed should be `DOTS'.
+
+   DEFUN_VOID (name)
+
+	Defines a function NAME, which takes no arguments.
+
+   obsolete --     EXFUN (name, (prototype))	-- obsolete.
+
+	Replaced by PARAMS.  Do not use; will disappear someday soon.
+	Was used in external function declarations.
+	In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+	parentheses).  In traditional C it is `NAME()'.
+	For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+    PARAMS ((args))
+
+	We could use the EXFUN macro to handle prototype declarations, but
+	the name is misleading and the result is ugly.  So we just define a
+	simple macro to handle the parameter lists, as in:
+
+	      static int foo PARAMS ((int, char));
+
+	This produces:  `static int foo();' or `static int foo (int, char);'
+
+	EXFUN would have done it like this:
+
+	      static int EXFUN (foo, (int, char));
+
+	but the function is not external...and it's hard to visually parse
+	the function name out of the mess.   EXFUN should be considered
+	obsolete; new code should be written to use PARAMS.
+
+    For example:
+	extern int printf PARAMS ((CONST char *format DOTS));
+	int DEFUN(fprintf, (stream, format),
+		  FILE *stream AND CONST char *format DOTS) { ... }
+	void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef	_ANSIDECL_H
+
+#define	_ANSIDECL_H	1
+
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4))
+/* All known AIX compilers implement these things (but don't always
+   define __STDC__).  The RISC/OS MIPS compiler defines these things
+   in SVR4 mode, but does not define __STDC__.  */
+
+#define	PTR		void *
+#define	PTRCONST	void *CONST
+#define	LONG_DOUBLE	long double
+
+#define	AND		,
+#define	NOARGS		void
+#define	CONST		const
+#define	VOLATILE	volatile
+#define	SIGNED		signed
+#define	DOTS		, ...
+
+#define	EXFUN(name, proto)		name proto
+#define	DEFUN(name, arglist, args)	name(args)
+#define	DEFUN_VOID(name)		name(void)
+
+#define PROTO(type, name, arglist)	type name arglist
+#define PARAMS(paramlist)		paramlist
+
+#else	/* Not ANSI C.  */
+
+#define	PTR		char *
+#define	PTRCONST	PTR
+#define	LONG_DOUBLE	double
+
+#define	AND		;
+#define	NOARGS
+#define	CONST
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define	const
+#endif
+#define	VOLATILE
+#define	SIGNED
+#define	DOTS
+
+#define	EXFUN(name, proto)		name()
+#define	DEFUN(name, arglist, args)	name arglist args;
+#define	DEFUN_VOID(name)		name()
+#define PROTO(type, name, arglist) type name ()
+#define PARAMS(paramlist)		()
+
+#endif	/* ANSI C.  */
+
+#endif	/* ansidecl.h	*/
Index: trunk/src/emx/src/emxexp/cplus-de.c
===================================================================
--- trunk/src/emx/src/emxexp/cplus-de.c	(revision 18)
+++ trunk/src/emx/src/emxexp/cplus-de.c	(revision 18)
@@ -0,0 +1,3290 @@
+/* cplus-de.c -- changed for emx by Eberhard Mattes -- Mar 1998 */
+/* Demangler for GNU C++ 
+   Copyright 1989, 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+   Written by James Clark (jjc@jclark.uucp)
+   Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
+   
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
+
+   This file imports xmalloc and xrealloc, which are like malloc and
+   realloc except that they generate a fatal error if there is no
+   available memory.  */
+
+/* This file lives in both GCC and libiberty.  When making changes, please
+   try not to break either.  */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <demangle.h>
+#undef CURRENT_DEMANGLING_STYLE
+#define CURRENT_DEMANGLING_STYLE work->options
+
+extern char *xmalloc PARAMS((unsigned));
+extern char *xrealloc PARAMS((char *, unsigned));
+
+static const char *mystrstr PARAMS ((const char *, const char *));
+
+static const char *
+mystrstr (s1, s2)
+     const char *s1, *s2;
+{
+  register const char *p = s1;
+  register int len = strlen (s2);
+
+  for (; (p = strchr (p, *s2)) != 0; p++)
+    {
+      if (strncmp (p, s2, len) == 0)
+	{
+	  return (p);
+	}
+    }
+  return (0);
+}
+
+/* In order to allow a single demangler executable to demangle strings
+   using various common values of CPLUS_MARKER, as well as any specific
+   one set at compile time, we maintain a string containing all the
+   commonly used ones, and check to see if the marker we are looking for
+   is in that string.  CPLUS_MARKER is usually '$' on systems where the
+   assembler can deal with that.  Where the assembler can't, it's usually
+   '.' (but on many systems '.' is used for other things).  We put the
+   current defined CPLUS_MARKER first (which defaults to '$'), followed
+   by the next most common value, followed by an explicit '$' in case
+   the value of CPLUS_MARKER is not '$'.
+
+   We could avoid this if we could just get g++ to tell us what the actual
+   cplus marker character is as part of the debug information, perhaps by
+   ensuring that it is the character that terminates the gcc<n>_compiled
+   marker symbol (FIXME).  */
+
+#if !defined (CPLUS_MARKER)
+#define CPLUS_MARKER '$'
+#endif
+
+enum demangling_styles current_demangling_style = gnu_demangling;
+
+static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
+
+void
+set_cplus_marker_for_demangling (ch)
+     int ch;
+{
+  cplus_markers[0] = ch;
+}
+
+/* Stuff that is shared between sub-routines.
+   Using a shared structure allows cplus_demangle to be reentrant.  */
+
+struct work_stuff
+{
+  int options;
+  char **typevec;
+  int ntypes;
+  int typevec_size;
+  int constructor;
+  int destructor;
+  int static_type;	/* A static member function */
+  int const_type;	/* A const member function */
+  char **tmpl_argvec;   /* Template function arguments. */
+  int ntmpl_args;       /* The number of template function arguments. */
+};
+
+#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
+#define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
+
+static const struct optable
+{
+  const char *in;
+  const char *out;
+  int flags;
+} optable[] = {
+  {"nw",	  " new",	DMGL_ANSI},	/* new (1.92,	 ansi) */
+  {"dl",	  " delete",	DMGL_ANSI},	/* new (1.92,	 ansi) */
+  {"new",	  " new",	0},		/* old (1.91,	 and 1.x) */
+  {"delete",	  " delete",	0},		/* old (1.91,	 and 1.x) */
+  {"vn",	  " new []",	DMGL_ANSI},	/* GNU, pending ansi */
+  {"vd",	  " delete []",	DMGL_ANSI},	/* GNU, pending ansi */
+  {"as",	  "=",		DMGL_ANSI},	/* ansi */
+  {"ne",	  "!=",		DMGL_ANSI},	/* old, ansi */
+  {"eq",	  "==",		DMGL_ANSI},	/* old,	ansi */
+  {"ge",	  ">=",		DMGL_ANSI},	/* old,	ansi */
+  {"gt",	  ">",		DMGL_ANSI},	/* old,	ansi */
+  {"le",	  "<=",		DMGL_ANSI},	/* old,	ansi */
+  {"lt",	  "<",		DMGL_ANSI},	/* old,	ansi */
+  {"plus",	  "+",		0},		/* old */
+  {"pl",	  "+",		DMGL_ANSI},	/* ansi */
+  {"apl",	  "+=",		DMGL_ANSI},	/* ansi */
+  {"minus",	  "-",		0},		/* old */
+  {"mi",	  "-",		DMGL_ANSI},	/* ansi */
+  {"ami",	  "-=",		DMGL_ANSI},	/* ansi */
+  {"mult",	  "*",		0},		/* old */
+  {"ml",	  "*",		DMGL_ANSI},	/* ansi */
+  {"amu",	  "*=",		DMGL_ANSI},	/* ansi (ARM/Lucid) */
+  {"aml",	  "*=",		DMGL_ANSI},	/* ansi (GNU/g++) */
+  {"convert",	  "+",		0},		/* old (unary +) */
+  {"negate",	  "-",		0},		/* old (unary -) */
+  {"trunc_mod",	  "%",		0},		/* old */
+  {"md",	  "%",		DMGL_ANSI},	/* ansi */
+  {"amd",	  "%=",		DMGL_ANSI},	/* ansi */
+  {"trunc_div",	  "/",		0},		/* old */
+  {"dv",	  "/",		DMGL_ANSI},	/* ansi */
+  {"adv",	  "/=",		DMGL_ANSI},	/* ansi */
+  {"truth_andif", "&&",		0},		/* old */
+  {"aa",	  "&&",		DMGL_ANSI},	/* ansi */
+  {"truth_orif",  "||",		0},		/* old */
+  {"oo",	  "||",		DMGL_ANSI},	/* ansi */
+  {"truth_not",	  "!",		0},		/* old */
+  {"nt",	  "!",		DMGL_ANSI},	/* ansi */
+  {"postincrement","++",	0},		/* old */
+  {"pp",	  "++",		DMGL_ANSI},	/* ansi */
+  {"postdecrement","--",	0},		/* old */
+  {"mm",	  "--",		DMGL_ANSI},	/* ansi */
+  {"bit_ior",	  "|",		0},		/* old */
+  {"or",	  "|",		DMGL_ANSI},	/* ansi */
+  {"aor",	  "|=",		DMGL_ANSI},	/* ansi */
+  {"bit_xor",	  "^",		0},		/* old */
+  {"er",	  "^",		DMGL_ANSI},	/* ansi */
+  {"aer",	  "^=",		DMGL_ANSI},	/* ansi */
+  {"bit_and",	  "&",		0},		/* old */
+  {"ad",	  "&",		DMGL_ANSI},	/* ansi */
+  {"aad",	  "&=",		DMGL_ANSI},	/* ansi */
+  {"bit_not",	  "~",		0},		/* old */
+  {"co",	  "~",		DMGL_ANSI},	/* ansi */
+  {"call",	  "()",		0},		/* old */
+  {"cl",	  "()",		DMGL_ANSI},	/* ansi */
+  {"alshift",	  "<<",		0},		/* old */
+  {"ls",	  "<<",		DMGL_ANSI},	/* ansi */
+  {"als",	  "<<=",	DMGL_ANSI},	/* ansi */
+  {"arshift",	  ">>",		0},		/* old */
+  {"rs",	  ">>",		DMGL_ANSI},	/* ansi */
+  {"ars",	  ">>=",	DMGL_ANSI},	/* ansi */
+  {"component",	  "->",		0},		/* old */
+  {"pt",	  "->",		DMGL_ANSI},	/* ansi; Lucid C++ form */
+  {"rf",	  "->",		DMGL_ANSI},	/* ansi; ARM/GNU form */
+  {"indirect",	  "*",		0},		/* old */
+  {"method_call",  "->()",	0},		/* old */
+  {"addr",	  "&",		0},		/* old (unary &) */
+  {"array",	  "[]",		0},		/* old */
+  {"vc",	  "[]",		DMGL_ANSI},	/* ansi */
+  {"compound",	  ", ",		0},		/* old */
+  {"cm",	  ", ",		DMGL_ANSI},	/* ansi */
+  {"cond",	  "?:",		0},		/* old */
+  {"cn",	  "?:",		DMGL_ANSI},	/* pseudo-ansi */
+  {"max",	  ">?",		0},		/* old */
+  {"mx",	  ">?",		DMGL_ANSI},	/* pseudo-ansi */
+  {"min",	  "<?",		0},		/* old */
+  {"mn",	  "<?",		DMGL_ANSI},	/* pseudo-ansi */
+  {"nop",	  "",		0},		/* old (for operator=) */
+  {"rm",	  "->*",	DMGL_ANSI}	/* ansi */
+};
+
+
+typedef struct string		/* Beware: these aren't required to be */
+{				/*  '\0' terminated.  */
+  char *b;			/* pointer to start of string */
+  char *p;			/* pointer after last character */
+  char *e;			/* pointer after end of allocated space */
+} string;
+
+#define STRING_EMPTY(str)	((str) -> b == (str) -> p)
+#define PREPEND_BLANK(str)	{if (!STRING_EMPTY(str)) \
+    string_prepend(str, " ");}
+#define APPEND_BLANK(str)	{if (!STRING_EMPTY(str)) \
+    string_append(str, " ");}
+
+#define ARM_VTABLE_STRING "__vtbl__"	/* Lucid/ARM virtual table prefix */
+#define ARM_VTABLE_STRLEN 8		/* strlen (ARM_VTABLE_STRING) */
+
+/* Prototypes for local functions */
+
+static char *
+mop_up PARAMS ((struct work_stuff *, string *, int));
+
+#if 0
+static int
+demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *));
+#endif
+
+static int
+demangle_template PARAMS ((struct work_stuff *, const char **, string *,
+			   string *, int));
+
+static int
+arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
+		const char **));
+
+static void
+demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
+
+static int
+demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
+			    int, int));
+
+static int
+demangle_class PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+gnu_special PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+arm_special PARAMS ((struct work_stuff *, const char **, string *));
+
+static void
+string_need PARAMS ((string *, int));
+
+static void
+string_delete PARAMS ((string *));
+
+static void
+string_init PARAMS ((string *));
+
+static void
+string_clear PARAMS ((string *));
+
+#if 0
+static int
+string_empty PARAMS ((string *));
+#endif
+
+static void
+string_append PARAMS ((string *, const char *));
+
+static void
+string_appends PARAMS ((string *, string *));
+
+static void
+string_appendn PARAMS ((string *, const char *, int));
+
+static void
+string_prepend PARAMS ((string *, const char *));
+
+static void
+string_prependn PARAMS ((string *, const char *, int));
+
+static int
+get_count PARAMS ((const char **, int *));
+
+static int
+consume_count PARAMS ((const char **));
+
+static int 
+consume_count_with_underscores PARAMS ((const char**));
+
+static int
+demangle_args PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+do_type PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+do_arg PARAMS ((struct work_stuff *, const char **, string *));
+
+static void
+demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
+				const char *));
+
+static void
+remember_type PARAMS ((struct work_stuff *, const char *, int));
+
+static void
+forget_types PARAMS ((struct work_stuff *));
+
+static void
+string_prepends PARAMS ((string *, string *));
+
+/*  Translate count to integer, consuming tokens in the process.
+    Conversion terminates on the first non-digit character.
+    Trying to consume something that isn't a count results in
+    no consumption of input and a return of 0.  */
+
+static int
+consume_count (type)
+     const char **type;
+{
+  int count = 0;
+
+  while (isdigit (**type))
+    {
+      count *= 10;
+      count += **type - '0';
+      (*type)++;
+    }
+  return (count);
+}
+
+
+/* Like consume_count, but for counts that are preceded and followed
+   by '_' if they are greater than 10.  Also, -1 is returned for
+   failure, since 0 can be a valid value.  */
+
+static int
+consume_count_with_underscores (mangled)
+     const char **mangled;
+{
+  int idx;
+
+  if (**mangled == '_')
+    {
+      (*mangled)++;
+      if (!isdigit (**mangled))
+	return -1;
+
+      idx = consume_count (mangled);
+      if (**mangled != '_')
+	/* The trailing underscore was missing. */
+	return -1;
+	    
+      (*mangled)++;
+    }
+  else
+    {
+      if (**mangled < '0' || **mangled > '9')
+	return -1;
+	    
+      idx = **mangled - '0';
+      (*mangled)++;
+    }
+
+  return idx;
+}
+
+int
+cplus_demangle_opname (opname, result, options)
+     const char *opname;
+     char *result;
+     int options;
+{
+  int len, i, len1, ret;
+  string type;
+  struct work_stuff work[1];
+  const char *tem;
+
+  len = strlen(opname);
+  result[0] = '\0';
+  ret = 0;
+  work->options = options;
+  
+  if (opname[0] == '_' && opname[1] == '_'
+      && opname[2] == 'o' && opname[3] == 'p')
+    {
+      /* ANSI.  */
+      /* type conversion operator.  */
+      tem = opname + 4;
+      if (do_type (work, &tem, &type))
+	{
+	  strcat (result, "operator ");
+	  strncat (result, type.b, type.p - type.b);
+	  string_delete (&type);
+	  ret = 1;
+	}
+    }
+  else if (opname[0] == '_' && opname[1] == '_'
+	   && opname[2] >= 'a' && opname[2] <= 'z'
+	   && opname[3] >= 'a' && opname[3] <= 'z')
+    {
+      if (opname[4] == '\0')
+	{
+	  /* Operator.  */
+	  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+	    {
+	      if (strlen (optable[i].in) == 2
+		  && memcmp (optable[i].in, opname + 2, 2) == 0)
+		{
+		  strcat (result, "operator");
+		  strcat (result, optable[i].out);
+		  ret = 1;
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  if (opname[2] == 'a' && opname[5] == '\0')
+	    {
+	      /* Assignment.  */
+	      for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+		{
+		  if (strlen (optable[i].in) == 3
+		      && memcmp (optable[i].in, opname + 2, 3) == 0)
+		    {
+		      strcat (result, "operator");
+		      strcat (result, optable[i].out);
+		      ret = 1;
+		      break;
+		    }		      
+		}
+	    }
+	}
+    }
+  else if (len >= 3 
+	   && opname[0] == 'o'
+	   && opname[1] == 'p'
+	   && strchr (cplus_markers, opname[2]) != NULL)
+    {
+      /* see if it's an assignment expression */
+      if (len >= 10 /* op$assign_ */
+	  && memcmp (opname + 3, "assign_", 7) == 0)
+	{
+	  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+	    {
+	      len1 = len - 10;
+	      if (strlen (optable[i].in) == len1
+		  && memcmp (optable[i].in, opname + 10, len1) == 0)
+		{
+		  strcat (result, "operator");
+		  strcat (result, optable[i].out);
+		  strcat (result, "=");
+		  ret = 1;
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+	    {
+	      len1 = len - 3;
+	      if (strlen (optable[i].in) == len1 
+		  && memcmp (optable[i].in, opname + 3, len1) == 0)
+		{
+		  strcat (result, "operator");
+		  strcat (result, optable[i].out);
+		  ret = 1;
+		  break;
+		}
+	    }
+	}
+    }
+  else if (len >= 5 && memcmp (opname, "type", 4) == 0
+	   && strchr (cplus_markers, opname[4]) != NULL)
+    {
+      /* type conversion operator */
+      tem = opname + 5;
+      if (do_type (work, &tem, &type))
+	{
+	  strcat (result, "operator ");
+	  strncat (result, type.b, type.p - type.b);
+	  string_delete (&type);
+	  ret = 1;
+	}
+    }
+  return ret;
+
+}
+/* Takes operator name as e.g. "++" and returns mangled
+   operator name (e.g. "postincrement_expr"), or NULL if not found.
+
+   If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
+   if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
+
+const char *
+cplus_mangle_opname (opname, options)
+     const char *opname;
+     int options;
+{
+  int i;
+  int len;
+
+  len = strlen (opname);
+  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+    {
+      if (strlen (optable[i].out) == len
+	  && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
+	  && memcmp (optable[i].out, opname, len) == 0)
+	return optable[i].in;
+    }
+  return (0);
+}
+
+/* char *cplus_demangle (const char *mangled, int options)
+
+   If MANGLED is a mangled function name produced by GNU C++, then
+   a pointer to a malloced string giving a C++ representation
+   of the name will be returned; otherwise NULL will be returned.
+   It is the caller's responsibility to free the string which
+   is returned.
+
+   The OPTIONS arg may contain one or more of the following bits:
+
+   	DMGL_ANSI	ANSI qualifiers such as `const' and `void' are
+			included.
+	DMGL_PARAMS	Function parameters are included.
+
+   For example,
+   
+   cplus_demangle ("foo__1Ai", DMGL_PARAMS)		=> "A::foo(int)"
+   cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI)	=> "A::foo(int)"
+   cplus_demangle ("foo__1Ai", 0)			=> "A::foo"
+
+   cplus_demangle ("foo__1Afe", DMGL_PARAMS)		=> "A::foo(float,...)"
+   cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
+   cplus_demangle ("foo__1Afe", 0)			=> "A::foo"
+
+   Note that any leading underscores, or other such characters prepended by
+   the compilation system, are presumed to have already been stripped from
+   MANGLED.  */
+
+char *
+cplus_demangle (mangled, options)
+     const char *mangled;
+     int options;
+{
+  string decl;
+  int success = 0;
+  struct work_stuff work[1];
+  char *demangled = NULL;
+
+  if ((mangled != NULL) && (*mangled != '\0'))
+    {
+      memset ((char *) work, 0, sizeof (work));
+      work -> options = options;
+      if ((work->options & DMGL_STYLE_MASK) == 0)
+	work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
+      
+      string_init (&decl);
+
+      /* First check to see if gnu style demangling is active and if the
+	 string to be demangled contains a CPLUS_MARKER.  If so, attempt to
+	 recognize one of the gnu special forms rather than looking for a
+	 standard prefix.  In particular, don't worry about whether there
+	 is a "__" string in the mangled string.  Consider "_$_5__foo" for
+	 example.  */
+
+      if ((AUTO_DEMANGLING || GNU_DEMANGLING))
+	{
+	  success = gnu_special (work, &mangled, &decl);
+	}
+      if (!success)
+	{
+	  success = demangle_prefix (work, &mangled, &decl);
+	}
+      if (success && (*mangled != '\0'))
+	{
+	  success = demangle_signature (work, &mangled, &decl);
+	}
+      if (work->constructor == 2)
+        {
+          string_prepend(&decl, "global constructors keyed to ");
+          work->constructor = 0;
+        }
+      else if (work->destructor == 2)
+        {
+          string_prepend(&decl, "global destructors keyed to ");
+          work->destructor = 0;
+        }
+      demangled = mop_up (work, &decl, success);
+    }
+  return (demangled);
+}
+
+static char *
+mop_up (work, declp, success)
+     struct work_stuff *work;
+     string *declp;
+     int success;
+{
+  char *demangled = NULL;
+
+  /* Discard the remembered types, if any.  */
+  
+  forget_types (work);
+  if (work -> typevec != NULL)
+    {
+      free ((char *) work -> typevec);
+    }
+  if (work->tmpl_argvec)
+    {
+      int i;
+
+      for (i = 0; i < work->ntmpl_args; i++)
+	if (work->tmpl_argvec[i])
+	  free ((char*) work->tmpl_argvec[i]);
+      
+      free ((char*) work->tmpl_argvec);
+    }
+
+  /* If demangling was successful, ensure that the demangled string is null
+     terminated and return it.  Otherwise, free the demangling decl.  */
+  
+  if (!success)
+    {
+      string_delete (declp);
+    }
+  else
+    {
+      string_appendn (declp, "", 1);
+      demangled = declp -> b;
+    }
+  return (demangled);
+}
+
+/*
+
+LOCAL FUNCTION
+
+	demangle_signature -- demangle the signature part of a mangled name
+
+SYNOPSIS
+
+	static int
+	demangle_signature (struct work_stuff *work, const char **mangled,
+			    string *declp);
+
+DESCRIPTION
+
+	Consume and demangle the signature portion of the mangled name.
+
+	DECLP is the string where demangled output is being built.  At
+	entry it contains the demangled root name from the mangled name
+	prefix.  I.E. either a demangled operator name or the root function
+	name.  In some special cases, it may contain nothing.
+
+	*MANGLED points to the current unconsumed location in the mangled
+	name.  As tokens are consumed and demangling is performed, the
+	pointer is updated to continuously point at the next token to
+	be consumed.
+
+	Demangling GNU style mangled names is nasty because there is no
+	explicit token that marks the start of the outermost function
+	argument list.  */
+
+static int
+demangle_signature (work, mangled, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+{
+  int success = 1;
+  int func_done = 0;
+  int expect_func = 0;
+  int expect_return_type = 0;
+  const char *oldmangled = NULL;
+  string trawname;
+  string tname;
+
+  while (success && (**mangled != '\0'))
+    {
+      switch (**mangled)
+	{
+	case 'Q':
+	  oldmangled = *mangled;
+	  success = demangle_qualified (work, mangled, declp, 1, 0);
+	  if (success)
+	    {
+	      remember_type (work, oldmangled, *mangled - oldmangled);
+	    }
+	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
+	    {
+	      expect_func = 1;
+	    }
+	  oldmangled = NULL;
+	  break;
+	  
+	case 'S':
+	  /* Static member function */
+	  if (oldmangled == NULL)
+	    {
+	      oldmangled = *mangled;
+	    }
+	  (*mangled)++;
+	  work -> static_type = 1;
+	  break;
+
+	case 'C':
+	  /* a const member function */
+	  if (oldmangled == NULL)
+	    {
+	      oldmangled = *mangled;
+	    }
+	  (*mangled)++;
+	  work -> const_type = 1;
+	  break;
+	  
+	case '0': case '1': case '2': case '3': case '4':
+	case '5': case '6': case '7': case '8': case '9':
+	  if (oldmangled == NULL)
+	    {
+	      oldmangled = *mangled;
+	    }
+	  success = demangle_class (work, mangled, declp);
+	  if (success)
+	    {
+	      remember_type (work, oldmangled, *mangled - oldmangled);
+	    }
+	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
+	    {
+	      expect_func = 1;
+	    }
+	  oldmangled = NULL;
+	  break;
+	  
+	case 'F':
+	  /* Function */
+	  /* ARM style demangling includes a specific 'F' character after
+	     the class name.  For GNU style, it is just implied.  So we can
+	     safely just consume any 'F' at this point and be compatible
+	     with either style.  */
+
+	  oldmangled = NULL;
+	  func_done = 1;
+	  (*mangled)++;
+
+	  /* For lucid/ARM style we have to forget any types we might
+	     have remembered up to this point, since they were not argument
+	     types.  GNU style considers all types seen as available for
+	     back references.  See comment in demangle_args() */
+
+	  if (LUCID_DEMANGLING || ARM_DEMANGLING)
+	    {
+	      forget_types (work);
+	    }
+	  success = demangle_args (work, mangled, declp);
+	  break;
+	  
+	case 't':
+	  /* G++ Template */
+	  string_init(&trawname); 
+	  string_init(&tname);
+	  if (oldmangled == NULL)
+	    {
+	      oldmangled = *mangled;
+	    }
+	  success = demangle_template (work, mangled, &tname, &trawname, 1);
+	  if (success)
+	    {
+	      remember_type (work, oldmangled, *mangled - oldmangled);
+	    }
+	  string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::");
+	  string_prepends(declp, &tname);
+	  if (work -> destructor & 1)
+	    {
+	      string_prepend (&trawname, "~");
+	      string_appends (declp, &trawname);
+	      work->destructor -= 1;
+	    }
+	  if ((work->constructor & 1) || (work->destructor & 1))
+	    {
+	      string_appends (declp, &trawname);
+	      work->constructor -= 1;
+	    }
+	  string_delete(&trawname);
+	  string_delete(&tname);
+	  oldmangled = NULL;
+	  expect_func = 1;
+	  break;
+
+	case '_':
+	  if (GNU_DEMANGLING && expect_return_type) 
+	    {
+	      /* Read the return type. */
+	      string return_type;
+	      string_init (&return_type);
+
+	      (*mangled)++;
+	      success = do_type (work, mangled, &return_type);
+	      APPEND_BLANK (&return_type);
+
+	      string_prepends (declp, &return_type);
+	      string_delete (&return_type);
+	      break;
+	    }
+	  else
+	    /* At the outermost level, we cannot have a return type specified,
+	       so if we run into another '_' at this point we are dealing with
+	       a mangled name that is either bogus, or has been mangled by
+	       some algorithm we don't know how to deal with.  So just
+	       reject the entire demangling.  */
+	    success = 0;
+	  break;
+
+	case 'H':
+	  if (GNU_DEMANGLING) 
+	    {
+	      /* A G++ template function.  Read the template arguments. */
+	      success = demangle_template (work, mangled, declp, 0, 0);
+	      expect_return_type = 1;
+	      (*mangled)++;
+	      break;
+	    }
+	  else
+	    /* fall through */
+	    ;
+
+	default:
+	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
+	    {
+	      /* Assume we have stumbled onto the first outermost function
+		 argument token, and start processing args.  */
+	      func_done = 1;
+	      success = demangle_args (work, mangled, declp);
+	    }
+	  else
+	    {
+	      /* Non-GNU demanglers use a specific token to mark the start
+		 of the outermost function argument tokens.  Typically 'F',
+		 for ARM-demangling, for example.  So if we find something
+		 we are not prepared for, it must be an error.  */
+	      success = 0;
+	    }
+	  break;
+	}
+      /*
+	if (AUTO_DEMANGLING || GNU_DEMANGLING)
+	*/
+      {
+	if (success && expect_func)
+	  {
+	    func_done = 1;
+	    success = demangle_args (work, mangled, declp);
+	    /* Since template include the mangling of their return types,
+	       we must set expect_func to 0 so that we don't try do
+	       demangle more arguments the next time we get here.  */
+	    expect_func = 0;
+	  }
+      }
+    }
+  if (success && !func_done)
+    {
+      if (AUTO_DEMANGLING || GNU_DEMANGLING)
+	{
+	  /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+	     bar__3fooi is 'foo::bar(int)'.  We get here when we find the
+	     first case, and need to ensure that the '(void)' gets added to
+	     the current declp.  Note that with ARM, the first case
+	     represents the name of a static data member 'foo::bar',
+	     which is in the current declp, so we leave it alone.  */
+	  success = demangle_args (work, mangled, declp);
+	}
+    }
+  if (success && work -> static_type && PRINT_ARG_TYPES)
+    {
+      string_append (declp, " static");
+    }
+  if (success && work -> const_type && PRINT_ARG_TYPES)
+    {
+      string_append (declp, " const");
+    }
+  return (success);
+}
+
+#if 0
+
+static int
+demangle_method_args (work, mangled, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+{
+  int success = 0;
+
+  if (work -> static_type)
+    {
+      string_append (declp, *mangled + 1);
+      *mangled += strlen (*mangled);
+      success = 1;
+    }
+  else
+    {
+      success = demangle_args (work, mangled, declp);
+    }
+  return (success);
+}
+
+#endif
+
+static int
+demangle_template (work, mangled, tname, trawname, is_type)
+     struct work_stuff *work;
+     const char **mangled;
+     string *tname;
+     string *trawname;
+     int is_type;
+{
+  int i;
+  int is_pointer;
+  int is_real;
+  int is_integral;
+  int is_char;
+  int is_bool;
+  int r;
+  int need_comma = 0;
+  int success = 0;
+  int done;
+  const char *old_p;
+  const char *start;
+  int symbol_len;
+  int is_java_array = 0;
+  string temp;
+
+  (*mangled)++;
+  if (is_type)
+    {
+      start = *mangled;
+      /* get template name */
+      if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
+	{
+	  return (0);
+	}
+      if (trawname)
+	string_appendn (trawname, *mangled, r);
+      is_java_array = (work -> options & DMGL_JAVA)
+	&& strncmp (*mangled, "JArray1Z", 8) == 0;
+      if (! is_java_array)
+	{
+	  string_appendn (tname, *mangled, r);
+	}
+      *mangled += r;
+    }
+  if (!is_java_array)
+    string_append (tname, "<");
+  /* get size of template parameter list */
+  if (!get_count (mangled, &r))
+    {
+      return (0);
+    }
+  if (!is_type)
+    {
+      /* Create an array for saving the template argument values. */
+      work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
+      work->ntmpl_args = r;
+      for (i = 0; i < r; i++)
+	work->tmpl_argvec[i] = 0;
+    }
+  for (i = 0; i < r; i++)
+    {
+      if (need_comma)
+	{
+	  string_append (tname, ", ");
+	}
+      /* Z for type parameters */
+      if (**mangled == 'Z')
+	{
+	  (*mangled)++;
+	  /* temp is initialized in do_type */
+	  success = do_type (work, mangled, &temp);
+	  if (success)
+	    {
+	      string_appends (tname, &temp);
+
+	      if (!is_type)
+		{
+		  /* Save the template argument. */
+		  int len = temp.p - temp.b;
+		  work->tmpl_argvec[i] = xmalloc (len + 1);
+		  memcpy (work->tmpl_argvec[i], temp.b, len);
+		  work->tmpl_argvec[i][len] = '\0';
+		}
+	    }
+	  string_delete(&temp);
+	  if (!success)
+	    {
+	      break;
+	    }
+	}
+      else
+	{
+	  string  param;
+	  string* s;
+
+	  /* otherwise, value parameter */
+	  old_p  = *mangled;
+	  is_pointer = 0;
+	  is_real = 0;
+	  is_integral = 0;
+          is_char = 0;
+	  is_bool = 0;
+	  done = 0;
+	  /* temp is initialized in do_type */
+	  success = do_type (work, mangled, &temp);
+	  /*
+	    if (success)
+	    {
+	    string_appends (s, &temp);
+	    }
+	    */
+	  string_delete(&temp);
+	  if (!success)
+	    {
+	      break;
+	    }
+	  /*
+	    string_append (s, "=");
+	    */
+
+	  if (!is_type)
+	    {
+	      s = &param;
+	      string_init (s);
+	    }
+	  else
+	    s = tname;
+
+	  while (*old_p && !done)
+	    {	
+	      switch (*old_p)
+		{
+		case 'P':
+		case 'p':
+		case 'R':
+		  done = is_pointer = 1;
+		  break;
+		case 'C':	/* const */
+		case 'S':	/* explicitly signed [char] */
+		case 'U':	/* unsigned */
+		case 'V':	/* volatile */
+		case 'F':	/* function */
+		case 'M':	/* member function */
+		case 'O':	/* ??? */
+		case 'J':	/* complex */
+		  old_p++;
+		  continue;
+		case 'Q':	/* qualified name */
+		  done = is_integral = 1;
+		  break;
+		case 'T':	/* remembered type */
+		  abort ();
+		  break;
+		case 'v':	/* void */
+		  abort ();
+		  break;
+		case 'x':	/* long long */
+		case 'l':	/* long */
+		case 'i':	/* int */
+		case 's':	/* short */
+		case 'w':	/* wchar_t */
+		  done = is_integral = 1;
+		  break;
+		case 'b':	/* bool */
+		  done = is_bool = 1;
+		  break;
+		case 'c':	/* char */
+		  done = is_char = 1;
+		  break;
+		case 'r':	/* long double */
+		case 'd':	/* double */
+		case 'f':	/* float */
+		  done = is_real = 1;
+		  break;
+		default:
+		  /* it's probably user defined type, let's assume
+		     it's integral, it seems hard to figure out
+		     what it really is */
+		  done = is_integral = 1;
+		}
+	    }
+	  if (**mangled == 'Y')
+	    {
+	      /* The next argument is a template parameter. */
+	      int idx;
+
+	      (*mangled)++;
+	      idx = consume_count_with_underscores (mangled);
+	      if (idx == -1 
+		  || (work->tmpl_argvec && idx >= work->ntmpl_args)
+		  || consume_count_with_underscores (mangled) == -1)
+		{
+		  success = 0;
+		  if (!is_type)
+		    string_delete (s);
+		  break;
+		}
+	      if (work->tmpl_argvec)
+		string_append (s, work->tmpl_argvec[idx]);
+	      else
+		{
+		  char buf[10];
+		  sprintf(buf, "T%d", idx);
+		  string_append (s, buf);
+		}
+	    }
+	  else if (is_integral)
+	    {
+	      if (**mangled == 'm')
+		{
+		  string_appendn (s, "-", 1);
+		  (*mangled)++;
+		}
+	      while (isdigit (**mangled))	
+		{
+		  string_appendn (s, *mangled, 1);
+		  (*mangled)++;
+		}
+	    }
+	  else if (is_char)
+	    {
+	      char tmp[2];
+	      int val;
+              if (**mangled == 'm')
+                {
+                  string_appendn (s, "-", 1);
+                  (*mangled)++;
+                }
+	      string_appendn (s, "'", 1);
+              val = consume_count(mangled);
+	      if (val == 0)
+		{
+		  success = 0;
+		  if (!is_type)
+		    string_delete (s);
+		  break;
+                }
+              tmp[0] = (char)val;
+              tmp[1] = '\0';
+              string_appendn (s, &tmp[0], 1);
+	      string_appendn (s, "'", 1);
+	    }
+	  else if (is_bool)
+	    {
+	      int val = consume_count (mangled);
+	      if (val == 0)
+		string_appendn (s, "false", 5);
+	      else if (val == 1)
+		string_appendn (s, "true", 4);
+	      else
+		success = 0;
+	    }
+	  else if (is_real)
+	    {
+	      if (**mangled == 'm')
+		{
+		  string_appendn (s, "-", 1);
+		  (*mangled)++;
+		}
+	      while (isdigit (**mangled))	
+		{
+		  string_appendn (s, *mangled, 1);
+		  (*mangled)++;
+		}
+	      if (**mangled == '.') /* fraction */
+		{
+		  string_appendn (s, ".", 1);
+		  (*mangled)++;
+		  while (isdigit (**mangled))	
+		    {
+		      string_appendn (s, *mangled, 1);
+		      (*mangled)++;
+		    }
+		}
+	      if (**mangled == 'e') /* exponent */
+		{
+		  string_appendn (s, "e", 1);
+		  (*mangled)++;
+		  while (isdigit (**mangled))	
+		    {
+		      string_appendn (s, *mangled, 1);
+		      (*mangled)++;
+		    }
+		}
+	    }
+	  else if (is_pointer)
+	    {
+	      symbol_len = consume_count (mangled);
+	      if (symbol_len == 0)
+		{
+		  success = 0;
+		  if (!is_type)
+		    string_delete (s);
+		  break;
+		}
+	      if (symbol_len == 0)
+		string_appendn (s, "0", 1);
+	      else
+		{
+		  char *p = xmalloc (symbol_len + 1), *q;
+		  strncpy (p, *mangled, symbol_len);
+		  p [symbol_len] = '\0';
+		  q = cplus_demangle (p, work->options);
+		  string_appendn (s, "&", 1);
+		  if (q)
+		    {
+		      string_append (s, q);
+		      free (q);
+		    }
+		  else
+		    string_append (s, p);
+		  free (p);
+		}
+	      *mangled += symbol_len;
+	    }
+	  if (!is_type)
+	    {
+	      int len = s->p - s->b;
+	      work->tmpl_argvec[i] = xmalloc (len + 1);
+	      memcpy (work->tmpl_argvec[i], s->b, len);
+	      work->tmpl_argvec[i][len] = '\0';
+	      
+	      string_appends (tname, s);
+	      string_delete (s);
+	    }
+	}
+      need_comma = 1;
+    }
+  if (is_java_array)
+    {
+      string_append (tname, "[]");
+    }
+  else
+    {
+      if (tname->p[-1] == '>')
+	string_append (tname, " ");
+      string_append (tname, ">");
+    }
+  
+  /*
+    if (work -> static_type)
+    {
+    string_append (declp, *mangled + 1);
+    *mangled += strlen (*mangled);
+    success = 1;
+    }
+    else
+    {
+    success = demangle_args (work, mangled, declp);
+    }
+    }
+    */
+  return (success);
+}
+
+static int
+arm_pt (work, mangled, n, anchor, args)
+     struct work_stuff *work;
+     const char *mangled;
+     int n;
+     const char **anchor, **args;
+{
+  /* ARM template? */
+  if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
+    {
+      int len;
+      *args = *anchor + 6;
+      len = consume_count (args);
+      if (*args + len == mangled + n && **args == '_')
+	{
+	  ++*args;
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+static void
+demangle_arm_pt (work, mangled, n, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     int n;
+     string *declp;
+{
+  const char *p;
+  const char *args;
+  const char *e = *mangled + n;
+
+  /* ARM template? */
+  if (arm_pt (work, *mangled, n, &p, &args))
+    {
+      string arg;
+      string_init (&arg);
+      string_appendn (declp, *mangled, p - *mangled);
+      string_append (declp, "<");
+      /* should do error checking here */
+      while (args < e) {
+	string_clear (&arg);
+	do_type (work, &args, &arg);
+	string_appends (declp, &arg);
+	string_append (declp, ",");
+      }
+      string_delete (&arg);
+      --declp->p;
+      string_append (declp, ">");
+    }
+  else
+    {
+      string_appendn (declp, *mangled, n);
+    }
+  *mangled += n;
+}
+
+static int
+demangle_class_name (work, mangled, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+{
+  int n;
+  int success = 0;
+
+  n = consume_count (mangled);
+  if (strlen (*mangled) >= n)
+    {
+      demangle_arm_pt (work, mangled, n, declp);
+      success = 1;
+    }
+
+  return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+	demangle_class -- demangle a mangled class sequence
+
+SYNOPSIS
+
+	static int
+	demangle_class (struct work_stuff *work, const char **mangled,
+			strint *declp)
+
+DESCRIPTION
+
+	DECLP points to the buffer into which demangling is being done.
+
+	*MANGLED points to the current token to be demangled.  On input,
+	it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
+	On exit, it points to the next token after the mangled class on
+	success, or the first unconsumed token on failure.
+
+	If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
+	we are demangling a constructor or destructor.  In this case
+	we prepend "class::class" or "class::~class" to DECLP.
+
+	Otherwise, we prepend "class::" to the current DECLP.
+
+	Reset the constructor/destructor flags once they have been
+	"consumed".  This allows demangle_class to be called later during
+	the same demangling, to do normal class demangling.
+
+	Returns 1 if demangling is successful, 0 otherwise.
+
+*/
+
+static int
+demangle_class (work, mangled, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+{
+  int success = 0;
+  string class_name;
+
+  string_init (&class_name);
+  if (demangle_class_name (work, mangled, &class_name))
+    {
+      if ((work->constructor & 1) || (work->destructor & 1))
+	{
+	  string_prepends (declp, &class_name);
+	  if (work -> destructor & 1)
+	    {
+	      string_prepend (declp, "~");
+              work -> destructor -= 1;
+	    }
+	  else
+	    {
+	      work -> constructor -= 1; 
+	    }
+	}
+      string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::");
+      string_prepends (declp, &class_name);
+      success = 1;
+    }
+  string_delete (&class_name);
+  return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+	demangle_prefix -- consume the mangled name prefix and find signature
+
+SYNOPSIS
+
+	static int
+	demangle_prefix (struct work_stuff *work, const char **mangled,
+			 string *declp);
+
+DESCRIPTION
+
+	Consume and demangle the prefix of the mangled name.
+
+	DECLP points to the string buffer into which demangled output is
+	placed.  On entry, the buffer is empty.  On exit it contains
+	the root function name, the demangled operator name, or in some
+	special cases either nothing or the completely demangled result.
+
+	MANGLED points to the current pointer into the mangled name.  As each
+	token of the mangled name is consumed, it is updated.  Upon entry
+	the current mangled name pointer points to the first character of
+	the mangled name.  Upon exit, it should point to the first character
+	of the signature if demangling was successful, or to the first
+	unconsumed character if demangling of the prefix was unsuccessful.
+	
+	Returns 1 on success, 0 otherwise.
+ */
+
+static int
+demangle_prefix (work, mangled, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+{
+  int success = 1;
+  const char *scan;
+  int i;
+
+  if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
+    {
+      char *marker = strchr (cplus_markers, (*mangled)[8]);
+      if (marker != NULL && *marker == (*mangled)[10])
+	{
+	  if ((*mangled)[9] == 'D')
+	    {
+	      /* it's a GNU global destructor to be executed at program exit */
+	      (*mangled) += 11;
+	      work->destructor = 2;
+	      if (gnu_special (work, mangled, declp))
+		return success;
+	    }
+	  else if ((*mangled)[9] == 'I')
+	    {
+	      /* it's a GNU global constructor to be executed at program init */
+	      (*mangled) += 11;
+	      work->constructor = 2;
+	      if (gnu_special (work, mangled, declp))
+		return success;
+	    }
+	}
+    }
+  else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
+    {
+      /* it's a ARM global destructor to be executed at program exit */
+      (*mangled) += 7;
+      work->destructor = 2;
+    }
+  else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
+    {
+      /* it's a ARM global constructor to be executed at program initial */
+      (*mangled) += 7;
+      work->constructor = 2;
+    }
+
+  /*  This block of code is a reduction in strength time optimization
+      of:
+      scan = mystrstr (*mangled, "__"); */
+
+  {
+    scan = *mangled;
+
+    do {
+      scan = strchr (scan, '_');
+    } while (scan != NULL && *++scan != '_');
+
+    if (scan != NULL) --scan;
+  }
+
+  if (scan != NULL)
+    {
+      /* We found a sequence of two or more '_', ensure that we start at
+	 the last pair in the sequence.  */
+      i = strspn (scan, "_");
+      if (i > 2)
+	{
+	  scan += (i - 2); 
+	}
+    }
+ 
+  if (scan == NULL)
+    {
+      success = 0;
+    }
+  else if (work -> static_type)
+    {
+      if (!isdigit (scan[0]) && (scan[0] != 't'))
+	{
+	  success = 0;
+	}
+    }
+  else if ((scan == *mangled)
+	   && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
+    {
+      /* The ARM says nothing about the mangling of local variables.
+	 But cfront mangles local variables by prepending __<nesting_level>
+	 to them. As an extension to ARM demangling we handle this case.  */
+      if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
+	{
+	  *mangled = scan + 2;
+	  consume_count (mangled);
+	  string_append (declp, *mangled);
+	  *mangled += strlen (*mangled);
+	  success = 1; 
+	}
+      else
+	{
+	  /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
+	     names like __Q2_3foo3bar for nested type names.  So don't accept
+	     this style of constructor for cfront demangling.  */
+	  if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
+	    work -> constructor += 1;
+	  *mangled = scan + 2;
+	}
+    }
+  else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
+    {
+      /* Mangled name starts with "__".  Skip over any leading '_' characters,
+	 then find the next "__" that separates the prefix from the signature.
+	 */
+      if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
+	  || (arm_special (work, mangled, declp) == 0))
+	{
+	  while (*scan == '_')
+	    {
+	      scan++;
+	    }
+	  if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
+	    {
+	      /* No separator (I.E. "__not_mangled"), or empty signature
+		 (I.E. "__not_mangled_either__") */
+	      success = 0;
+	    }
+	  else
+	    {
+	      demangle_function_name (work, mangled, declp, scan);
+	    }
+	}
+    }
+  else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
+    {
+      /* Cfront-style parameterized type.  Handled later as a signature.  */
+      success = 1;
+
+      /* ARM template? */
+      demangle_arm_pt (work, mangled, strlen (*mangled), declp);
+    }
+  else if (*(scan + 2) != '\0')
+    {
+      /* Mangled name does not start with "__" but does have one somewhere
+	 in there with non empty stuff after it.  Looks like a global
+	 function name.  */
+      demangle_function_name (work, mangled, declp, scan);
+    }
+  else
+    {
+      /* Doesn't look like a mangled name */
+      success = 0;
+    }
+
+  if (!success && (work->constructor == 2 || work->destructor == 2))
+    {
+      string_append (declp, *mangled);
+      *mangled += strlen (*mangled);
+      success = 1;
+    } 
+  return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+	gnu_special -- special handling of gnu mangled strings
+
+SYNOPSIS
+
+	static int
+	gnu_special (struct work_stuff *work, const char **mangled,
+		     string *declp);
+
+
+DESCRIPTION
+
+	Process some special GNU style mangling forms that don't fit
+	the normal pattern.  For example:
+
+		_$_3foo		(destructor for class foo)
+		_vt$foo		(foo virtual table)
+		_vt$foo$bar	(foo::bar virtual table)
+		__vt_foo	(foo virtual table, new style with thunks)
+		_3foo$varname	(static data member)
+		_Q22rs2tu$vw	(static data member)
+		__t6vector1Zii	(constructor with template)
+		__thunk_4__$_7ostream (virtual function thunk)
+ */
+
+static int
+gnu_special (work, mangled, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+{
+  int n;
+  int success = 1;
+  const char *p;
+
+  if ((*mangled)[0] == '_'
+      && strchr (cplus_markers, (*mangled)[1]) != NULL
+      && (*mangled)[2] == '_')
+    {
+      /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
+      (*mangled) += 3;
+      work -> destructor += 1;
+    }
+  else if ((*mangled)[0] == '_'
+	   && (((*mangled)[1] == '_'
+		&& (*mangled)[2] == 'v'
+		&& (*mangled)[3] == 't'
+		&& (*mangled)[4] == '_')
+	       || ((*mangled)[1] == 'v'
+		   && (*mangled)[2] == 't'
+		   && strchr (cplus_markers, (*mangled)[3]) != NULL)))
+    {
+      /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
+         and create the decl.  Note that we consume the entire mangled
+	 input string, which means that demangle_signature has no work
+	 to do.  */
+      if ((*mangled)[2] == 'v')
+	(*mangled) += 5; /* New style, with thunks: "__vt_" */
+      else
+	(*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
+      while (**mangled != '\0')
+	{
+	  p = strpbrk (*mangled, cplus_markers);
+	  switch (**mangled)
+	    {
+	    case 'Q':
+	      success = demangle_qualified (work, mangled, declp, 0, 1);
+	      break;
+	    case 't':
+	      success = demangle_template (work, mangled, declp, 0, 1);
+	      break;
+	    default:
+	      if (isdigit(*mangled[0]))
+		{
+		  n = consume_count(mangled);
+		}
+	      else
+		{
+		  n = strcspn (*mangled, cplus_markers);
+		}
+	      string_appendn (declp, *mangled, n);
+	      (*mangled) += n;
+	    }
+
+	  if (success && ((p == NULL) || (p == *mangled)))
+	    {
+	      if (p != NULL)
+		{
+		  string_append (declp,
+				 (work -> options & DMGL_JAVA) ? "." : "::");
+		  (*mangled)++;
+		}
+	    }
+	  else
+	    {
+	      success = 0;
+	      break;
+	    }
+	}
+      if (success)
+	string_append (declp, " virtual table");
+    }
+  else if ((*mangled)[0] == '_'
+	   && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
+	   && (p = strpbrk (*mangled, cplus_markers)) != NULL)
+    {
+      /* static data member, "_3foo$varname" for example */
+      (*mangled)++;
+      switch (**mangled)
+	{
+	case 'Q':
+	  success = demangle_qualified (work, mangled, declp, 0, 1);
+	  break;
+	case 't':
+	  success = demangle_template (work, mangled, declp, 0, 1);
+	  break;
+	default:
+	  n = consume_count (mangled);
+	  string_appendn (declp, *mangled, n);
+	  (*mangled) += n;
+	}
+      if (success && (p == *mangled))
+	{
+	  /* Consumed everything up to the cplus_marker, append the
+	     variable name.  */
+	  (*mangled)++;
+	  string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::");
+	  n = strlen (*mangled);
+	  string_appendn (declp, *mangled, n);
+	  (*mangled) += n;
+	}
+      else
+	{
+	  success = 0;
+	}
+    }
+  else if (strncmp (*mangled, "__thunk_", 8) == 0)
+    {
+      int delta = ((*mangled) += 8, consume_count (mangled));
+      char *method = cplus_demangle (++*mangled, work->options);
+      if (method)
+	{
+	  char buf[50];
+	  sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
+	  string_append (declp, buf);
+	  string_append (declp, method);
+	  free (method);
+	  n = strlen (*mangled);
+	  (*mangled) += n;
+	}
+      else
+	{
+	  success = 0;
+	}
+    }
+  else if (strncmp (*mangled, "__t", 3) == 0
+	   && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
+    {
+      p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
+      (*mangled) += 4;
+      switch (**mangled)
+	{
+	case 'Q':
+	  success = demangle_qualified (work, mangled, declp, 0, 1);
+	  break;
+	case 't':
+	  success = demangle_template (work, mangled, declp, 0, 1);
+	  break;
+	default:
+	  success = demangle_fund_type (work, mangled, declp);
+	  break;
+	}
+      if (success && **mangled != '\0')
+	success = 0;
+      if (success)
+	string_append (declp, p);
+    }
+  else
+    {
+      success = 0;
+    }
+  return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+	arm_special -- special handling of ARM/lucid mangled strings
+
+SYNOPSIS
+
+	static int
+	arm_special (struct work_stuff *work, const char **mangled,
+			string *declp);
+
+
+DESCRIPTION
+
+	Process some special ARM style mangling forms that don't fit
+	the normal pattern.  For example:
+
+		__vtbl__3foo		(foo virtual table)
+		__vtbl__3foo__3bar	(bar::foo virtual table)
+
+ */
+
+static int
+arm_special (work, mangled, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+{
+  int n;
+  int success = 1;
+  const char *scan;
+
+  if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
+    {
+      /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
+         and create the decl.  Note that we consume the entire mangled
+	 input string, which means that demangle_signature has no work
+	 to do.  */
+      scan = *mangled + ARM_VTABLE_STRLEN;
+      while (*scan != '\0')        /* first check it can be demangled */
+        {
+          n = consume_count (&scan);
+          if (n==0)
+	    {
+	      return (0);           /* no good */
+	    }
+          scan += n;
+          if (scan[0] == '_' && scan[1] == '_')
+	    {
+	      scan += 2;
+	    }
+        }
+      (*mangled) += ARM_VTABLE_STRLEN;
+      while (**mangled != '\0')
+	{
+	  n = consume_count (mangled);
+	  string_prependn (declp, *mangled, n);
+	  (*mangled) += n;
+	  if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
+	    {
+	      string_prepend (declp, "::");
+	      (*mangled) += 2;
+	    }
+	}
+      string_append (declp, " virtual table");
+    }
+  else
+    {
+      success = 0;
+    }
+  return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+	demangle_qualified -- demangle 'Q' qualified name strings
+
+SYNOPSIS
+
+	static int
+	demangle_qualified (struct work_stuff *, const char *mangled,
+			    string *result, int isfuncname, int append);
+
+DESCRIPTION
+
+	Demangle a qualified name, such as "Q25Outer5Inner" which is
+	the mangled form of "Outer::Inner".  The demangled output is
+	prepended or appended to the result string according to the
+	state of the append flag.
+
+	If isfuncname is nonzero, then the qualified name we are building
+	is going to be used as a member function name, so if it is a
+	constructor or destructor function, append an appropriate
+	constructor or destructor name.  I.E. for the above example,
+	the result for use as a constructor is "Outer::Inner::Inner"
+	and the result for use as a destructor is "Outer::Inner::~Inner".
+
+BUGS
+
+	Numeric conversion is ASCII dependent (FIXME).
+
+ */
+
+static int
+demangle_qualified (work, mangled, result, isfuncname, append)
+     struct work_stuff *work;
+     const char **mangled;
+     string *result;
+     int isfuncname;
+     int append;
+{
+  int qualifiers;
+  int namelength;
+  int success = 1;
+  const char *p;
+  char num[2];
+  string temp;
+
+  string_init (&temp);
+  switch ((*mangled)[1])
+    {
+    case '_':
+      /* GNU mangled name with more than 9 classes.  The count is preceded
+	 by an underscore (to distinguish it from the <= 9 case) and followed
+	 by an underscore.  */
+      p = *mangled + 2;
+      qualifiers = atoi (p);
+      if (!isdigit (*p) || *p == '0')
+	success = 0;
+
+      /* Skip the digits.  */
+      while (isdigit (*p))
+	++p;
+
+      if (*p != '_')
+	success = 0;
+
+      *mangled = p + 1;
+      break;
+
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      /* The count is in a single digit.  */
+      num[0] = (*mangled)[1];
+      num[1] = '\0';
+      qualifiers = atoi (num);
+
+      /* If there is an underscore after the digit, skip it.  This is
+	 said to be for ARM-qualified names, but the ARM makes no
+	 mention of such an underscore.  Perhaps cfront uses one.  */
+      if ((*mangled)[2] == '_')
+	{
+	  (*mangled)++;
+	}
+      (*mangled) += 2;
+      break;
+
+    case '0':
+    default:
+      success = 0;
+    }
+
+  if (!success)
+    return success;
+
+  /* Pick off the names and collect them in the temp buffer in the order
+     in which they are found, separated by '::'.  */
+
+  while (qualifiers-- > 0)
+    {
+      if (*mangled[0] == '_') 
+	*mangled = *mangled + 1;
+      if (*mangled[0] == 't')
+	{
+	  success = demangle_template(work, mangled, &temp, 0, 1);
+	  if (!success) break;
+	}
+      else if (*mangled[0] == 'X')
+	{
+	  success = do_type (work, mangled, &temp);
+	  if (!success) break;
+	}
+      else
+        {	
+	  namelength = consume_count (mangled);
+      	  if (strlen (*mangled) < namelength)
+	    {
+	      /* Simple sanity check failed */
+	      success = 0;
+	      break;
+	    }
+      	  string_appendn (&temp, *mangled, namelength);
+      	  *mangled += namelength;
+	}
+      if (qualifiers > 0)
+        {
+          string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
+        }
+    }
+
+  /* If we are using the result as a function name, we need to append
+     the appropriate '::' separated constructor or destructor name.
+     We do this here because this is the most convenient place, where
+     we already have a pointer to the name and the length of the name.  */
+
+  if (isfuncname && (work->constructor & 1 || work->destructor & 1))
+    {
+      string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
+      if (work -> destructor & 1)
+	{
+	  string_append (&temp, "~");
+	}
+      string_appendn (&temp, (*mangled) - namelength, namelength);
+    }
+
+  /* Now either prepend the temp buffer to the result, or append it, 
+     depending upon the state of the append flag.  */
+
+  if (append)
+    {
+      string_appends (result, &temp);
+    }
+  else
+    {
+      if (!STRING_EMPTY (result))
+	{
+	  string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
+	}
+      string_prepends (result, &temp);
+    }
+
+  string_delete (&temp);
+  return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+	get_count -- convert an ascii count to integer, consuming tokens
+
+SYNOPSIS
+
+	static int
+	get_count (const char **type, int *count)
+
+DESCRIPTION
+
+	Return 0 if no conversion is performed, 1 if a string is converted.
+*/
+
+static int
+get_count (type, count)
+     const char **type;
+     int *count;
+{
+  const char *p;
+  int n;
+
+  if (!isdigit (**type))
+    {
+      return (0);
+    }
+  else
+    {
+      *count = **type - '0';
+      (*type)++;
+      if (isdigit (**type))
+	{
+	  p = *type;
+	  n = *count;
+	  do 
+	    {
+	      n *= 10;
+	      n += *p - '0';
+	      p++;
+	    } 
+	  while (isdigit (*p));
+	  if (*p == '_')
+	    {
+	      *type = p + 1;
+	      *count = n;
+	    }
+	}
+    }
+  return (1);
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (work, mangled, result)
+     struct work_stuff *work;
+     const char **mangled;
+     string *result;
+{
+  int n;
+  int done;
+  int success;
+  string decl;
+  const char *remembered_type;
+  int constp;
+  int volatilep;
+
+  string_init (&decl);
+  string_init (result);
+
+  done = 0;
+  success = 1;
+  while (success && !done)
+    {
+      int member;
+      switch (**mangled)
+	{
+
+	  /* A pointer type */
+	case 'P':
+	case 'p':
+	  (*mangled)++;
+	  if (! (work -> options & DMGL_JAVA))
+	    string_prepend (&decl, "*");
+	  break;
+
+	  /* A reference type */
+	case 'R':
+	  (*mangled)++;
+	  string_prepend (&decl, "&");
+	  break;
+
+	  /* An array */
+	case 'A':
+	  {
+	    const char *p = ++(*mangled);
+
+	    string_prepend (&decl, "(");
+	    string_append (&decl, ")[");
+	    /* Copy anything up until the next underscore (the size of the
+	       array).  */
+	    while (**mangled && **mangled != '_')
+	      ++(*mangled);
+	    if (**mangled == '_')
+	      {
+		string_appendn (&decl, p, *mangled - p);
+		string_append (&decl, "]");             
+		*mangled += 1;
+	      }
+	    else
+	      success = 0;
+	    break;
+	  }
+
+	/* A back reference to a previously seen type */
+	case 'T':
+	  (*mangled)++;
+	  if (!get_count (mangled, &n) || n >= work -> ntypes)
+	    {
+	      success = 0;
+	    }
+	  else
+	    {
+	      remembered_type = work -> typevec[n];
+	      mangled = &remembered_type;
+	    }
+	  break;
+
+	  /* A function */
+	case 'F':
+	  (*mangled)++;
+	  if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
+	    {
+	      string_prepend (&decl, "(");
+	      string_append (&decl, ")");
+	    }
+	  /* After picking off the function args, we expect to either find the
+	     function return type (preceded by an '_') or the end of the
+	     string.  */
+	  if (!demangle_args (work, mangled, &decl)
+	      || (**mangled != '_' && **mangled != '\0'))
+	    {
+	      success = 0;
+	    }
+	  if (success && (**mangled == '_'))
+	    {
+	      (*mangled)++;
+	    }
+	  break;
+
+	case 'M':
+	case 'O':
+	  {
+	    constp = 0;
+	    volatilep = 0;
+
+	    member = **mangled == 'M';
+	    (*mangled)++;
+	    if (!isdigit (**mangled) && **mangled != 't')
+	      {
+		success = 0;
+		break;
+	      }
+
+	    string_append (&decl, ")");
+	    string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::");
+	    if (isdigit (**mangled)) 
+	      {
+		n = consume_count (mangled);
+		if (strlen (*mangled) < n)
+		  {
+		    success = 0;
+		    break;
+		  }
+		string_prependn (&decl, *mangled, n);
+		*mangled += n;
+	      }
+	    else
+	      {
+		string temp;
+		string_init (&temp);
+		success = demangle_template (work, mangled, &temp, NULL, 1);
+		if (success)
+		  {
+		    string_prependn (&decl, temp.b, temp.p - temp.b);
+		    string_clear (&temp);
+		  }
+		else
+		  break;
+	      }
+	    string_prepend (&decl, "(");
+	    if (member)
+	      {
+		if (**mangled == 'C')
+		  {
+		    (*mangled)++;
+		    constp = 1;
+		  }
+		if (**mangled == 'V')
+		  {
+		    (*mangled)++;
+		    volatilep = 1;
+		  }
+		if (*(*mangled)++ != 'F')
+		  {
+		    success = 0;
+		    break;
+		  }
+	      }
+	    if ((member && !demangle_args (work, mangled, &decl))
+		|| **mangled != '_')
+	      {
+		success = 0;
+		break;
+	      }
+	    (*mangled)++;
+	    if (! PRINT_ANSI_QUALIFIERS)
+	      {
+		break;
+	      }
+	    if (constp)
+	      {
+		APPEND_BLANK (&decl);
+		string_append (&decl, "const");
+	      }
+	    if (volatilep)
+	      {
+		APPEND_BLANK (&decl);
+		string_append (&decl, "volatile");
+	      }
+	    break;
+	  }
+        case 'G':
+	  (*mangled)++;
+	  break;
+
+	case 'C':
+	  (*mangled)++;
+	  /*
+	    if ((*mangled)[1] == 'P')
+	    {
+	    */
+	  if (PRINT_ANSI_QUALIFIERS)
+	    {
+	      if (!STRING_EMPTY (&decl))
+		{
+		  string_prepend (&decl, " ");
+		}
+	      string_prepend (&decl, "const");
+	    }
+	  break;
+	  /*
+	    }
+	    */
+
+	  /* fall through */
+	default:
+	  done = 1;
+	  break;
+	}
+    }
+
+  switch (**mangled)
+    {
+      /* A qualified name, such as "Outer::Inner".  */
+    case 'Q':
+      success = demangle_qualified (work, mangled, result, 0, 1);
+      break;
+
+    case 'X':
+    case 'Y':
+      /* A template parm.  We substitute the corresponding argument. */
+      {
+	int idx;
+	int lvl;
+
+	(*mangled)++;
+	idx = consume_count_with_underscores (mangled);
+
+	if (idx == -1 
+	    || (work->tmpl_argvec && idx >= work->ntmpl_args)
+	    || consume_count_with_underscores (mangled) == -1)
+	  {
+	    success = 0;
+	    break;
+	  }
+
+	if (work->tmpl_argvec)
+	  string_append (result, work->tmpl_argvec[idx]);
+	else
+	  {
+	    char buf[10];
+	    sprintf(buf, "T%d", idx);
+	    string_append (result, buf);
+	  }
+
+	success = 1;
+      }
+    break;
+
+    default:
+      success = demangle_fund_type (work, mangled, result);
+      break;
+    }
+
+  if (success)
+    {
+      if (!STRING_EMPTY (&decl))
+	{
+	  string_append (result, " ");
+	  string_appends (result, &decl);
+	}
+    }
+  else
+    {
+      string_delete (result);
+    }
+  string_delete (&decl);
+  return (success);
+}
+
+/* Given a pointer to a type string that represents a fundamental type
+   argument (int, long, unsigned int, etc) in TYPE, a pointer to the
+   string in which the demangled output is being built in RESULT, and
+   the WORK structure, decode the types and add them to the result.
+
+   For example:
+
+   	"Ci"	=>	"const int"
+	"Sl"	=>	"signed long"
+	"CUs"	=>	"const unsigned short"
+
+   */
+
+static int
+demangle_fund_type (work, mangled, result)
+     struct work_stuff *work;
+     const char **mangled;
+     string *result;
+{
+  int done = 0;
+  int success = 1;
+
+  /* First pick off any type qualifiers.  There can be more than one.  */
+
+  while (!done)
+    {
+      switch (**mangled)
+	{
+	case 'C':
+	  (*mangled)++;
+	  if (PRINT_ANSI_QUALIFIERS)
+	    {
+	      APPEND_BLANK (result);
+	      string_append (result, "const");
+	    }
+	  break;
+	case 'U':
+	  (*mangled)++;
+	  APPEND_BLANK (result);
+	  string_append (result, "unsigned");
+	  break;
+	case 'S': /* signed char only */
+	  (*mangled)++;
+	  APPEND_BLANK (result);
+	  string_append (result, "signed");
+	  break;
+	case 'V':
+	  (*mangled)++;
+	  if (PRINT_ANSI_QUALIFIERS)
+	    {
+	      APPEND_BLANK (result);
+	      string_append (result, "volatile");
+	    }
+	  break;
+	case 'J':
+	  (*mangled)++;
+	  APPEND_BLANK (result);
+	  string_append (result, "__complex");
+	  break;
+	default:
+	  done = 1;
+	  break;
+	}
+    }
+
+  /* Now pick off the fundamental type.  There can be only one.  */
+
+  switch (**mangled)
+    {
+    case '\0':
+    case '_':
+      break;
+    case 'v':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "void");
+      break;
+    case 'x':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "long long");
+      break;
+    case 'l':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "long");
+      break;
+    case 'i':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "int");
+      break;
+    case 's':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "short");
+      break;
+    case 'b':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "bool");
+      break;
+    case 'c':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "char");
+      break;
+    case 'w':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "wchar_t");
+      break;
+    case 'r':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "long double");
+      break;
+    case 'd':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "double");
+      break;
+    case 'f':
+      (*mangled)++;
+      APPEND_BLANK (result);
+      string_append (result, "float");
+      break;
+    case 'G':
+      (*mangled)++;
+      if (!isdigit (**mangled))
+	{
+	  success = 0;
+	  break;
+	}
+      /* fall through */
+      /* An explicit type, such as "6mytype" or "7integer" */
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      APPEND_BLANK (result);
+      if (!demangle_class_name (work, mangled, result)) {
+	--result->p;
+	success = 0;
+      }
+      break;
+    case 't':
+      success = demangle_template(work,mangled, result, 0, 1);
+      break;
+    default:
+      success = 0;
+      break;
+    }
+
+  return (success);
+}
+
+/* `result' will be initialized in do_type; it will be freed on failure */
+
+static int
+do_arg (work, mangled, result)
+     struct work_stuff *work;
+     const char **mangled;
+     string *result;
+{
+  const char *start = *mangled;
+
+  if (!do_type (work, mangled, result))
+    {
+      return (0);
+    }
+  else
+    {
+      remember_type (work, start, *mangled - start);
+      return (1);
+    }
+}
+
+static void
+remember_type (work, start, len)
+     struct work_stuff *work;
+     const char *start;
+     int len;
+{
+  char *tem;
+
+  if (work -> ntypes >= work -> typevec_size)
+    {
+      if (work -> typevec_size == 0)
+	{
+	  work -> typevec_size = 3;
+	  work -> typevec
+	    = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
+	}
+      else
+	{
+	  work -> typevec_size *= 2;
+	  work -> typevec
+	    = (char **) xrealloc ((char *)work -> typevec,
+				  sizeof (char *) * work -> typevec_size);
+	}
+    }
+  tem = xmalloc (len + 1);
+  memcpy (tem, start, len);
+  tem[len] = '\0';
+  work -> typevec[work -> ntypes++] = tem;
+}
+
+/* Forget the remembered types, but not the type vector itself.  */
+
+static void
+forget_types (work)
+     struct work_stuff *work;
+{
+  int i;
+
+  while (work -> ntypes > 0)
+    {
+      i = --(work -> ntypes);
+      if (work -> typevec[i] != NULL)
+	{
+	  free (work -> typevec[i]);
+	  work -> typevec[i] = NULL;
+	}
+    }
+}
+
+/* Process the argument list part of the signature, after any class spec
+   has been consumed, as well as the first 'F' character (if any).  For
+   example:
+
+   "__als__3fooRT0"		=>	process "RT0"
+   "complexfunc5__FPFPc_PFl_i"	=>	process "PFPc_PFl_i"
+
+   DECLP must be already initialised, usually non-empty.  It won't be freed
+   on failure.
+
+   Note that g++ differs significantly from ARM and lucid style mangling
+   with regards to references to previously seen types.  For example, given
+   the source fragment:
+
+     class foo {
+       public:
+       foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
+     };
+
+     foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+     void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+
+   g++ produces the names:
+
+     __3fooiRT0iT2iT2
+     foo__FiR3fooiT1iT1
+
+   while lcc (and presumably other ARM style compilers as well) produces:
+
+     foo__FiR3fooT1T2T1T2
+     __ct__3fooFiR3fooT1T2T1T2
+
+   Note that g++ bases it's type numbers starting at zero and counts all
+   previously seen types, while lucid/ARM bases it's type numbers starting
+   at one and only considers types after it has seen the 'F' character
+   indicating the start of the function args.  For lucid/ARM style, we
+   account for this difference by discarding any previously seen types when
+   we see the 'F' character, and subtracting one from the type number
+   reference.
+
+ */
+
+static int
+demangle_args (work, mangled, declp)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+{
+  string arg;
+  int need_comma = 0;
+  int r;
+  int t;
+  const char *tem;
+  char temptype;
+
+  if (PRINT_ARG_TYPES)
+    {
+      string_append (declp, "(");
+      if (**mangled == '\0')
+	{
+	  string_append (declp, "void");
+	}
+    }
+
+  while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
+    {
+      if ((**mangled == 'N') || (**mangled == 'T'))
+	{
+	  temptype = *(*mangled)++;
+	  
+	  if (temptype == 'N')
+	    {
+	      if (!get_count (mangled, &r))
+		{
+		  return (0);
+		}
+	    }
+	  else
+	    {
+	      r = 1;
+	    }
+          if (ARM_DEMANGLING && work -> ntypes >= 10)
+            {
+              /* If we have 10 or more types we might have more than a 1 digit
+                 index so we'll have to consume the whole count here. This
+                 will lose if the next thing is a type name preceded by a
+                 count but it's impossible to demangle that case properly
+                 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
+                 Pc, ...)"  or "(..., type12, char *, ...)" */
+              if ((t = consume_count(mangled)) == 0)
+                {
+                  return (0);
+                }
+            }
+          else
+	    {
+	      if (!get_count (mangled, &t))
+	    	{
+	          return (0);
+	    	}
+	    }
+	  if (LUCID_DEMANGLING || ARM_DEMANGLING)
+	    {
+	      t--;
+	    }
+	  /* Validate the type index.  Protect against illegal indices from
+	     malformed type strings.  */
+	  if ((t < 0) || (t >= work -> ntypes))
+	    {
+	      return (0);
+	    }
+	  while (--r >= 0)
+	    {
+	      tem = work -> typevec[t];
+	      if (need_comma && PRINT_ARG_TYPES)
+		{
+		  string_append (declp, ", ");
+		}
+	      if (!do_arg (work, &tem, &arg))
+		{
+		  return (0);
+		}
+	      if (PRINT_ARG_TYPES)
+		{
+		  string_appends (declp, &arg);
+		}
+	      string_delete (&arg);
+	      need_comma = 1;
+	    }
+	}
+      else
+	{
+	  if (need_comma & PRINT_ARG_TYPES)
+	    {
+	      string_append (declp, ", ");
+	    }
+	  if (!do_arg (work, mangled, &arg))
+	    {
+	      return (0);
+	    }
+	  if (PRINT_ARG_TYPES)
+	    {
+	      string_appends (declp, &arg);
+	    }
+	  string_delete (&arg);
+	  need_comma = 1;
+	}
+    }
+
+  if (**mangled == 'e')
+    {
+      (*mangled)++;
+      if (PRINT_ARG_TYPES)
+	{
+	  if (need_comma)
+	    {
+	      string_append (declp, ",");
+	    }
+	  string_append (declp, "...");
+	}
+    }
+
+  if (PRINT_ARG_TYPES)
+    {
+      string_append (declp, ")");
+    }
+  return (1);
+}
+
+static void
+demangle_function_name (work, mangled, declp, scan)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+     const char *scan;
+{
+  int i;
+  int len;
+  string type;
+  const char *tem;
+
+  string_appendn (declp, (*mangled), scan - (*mangled));
+  string_need (declp, 1);
+  *(declp -> p) = '\0';
+
+  /* Consume the function name, including the "__" separating the name
+     from the signature.  We are guaranteed that SCAN points to the
+     separator.  */
+
+  (*mangled) = scan + 2;
+
+  if (LUCID_DEMANGLING || ARM_DEMANGLING)
+    {
+
+      /* See if we have an ARM style constructor or destructor operator.
+	 If so, then just record it, clear the decl, and return.
+	 We can't build the actual constructor/destructor decl until later,
+	 when we recover the class name from the signature.  */
+
+      if (strcmp (declp -> b, "__ct") == 0)
+	{
+	  work -> constructor += 1;
+	  string_clear (declp);
+	  return;
+	}
+      else if (strcmp (declp -> b, "__dt") == 0)
+	{
+	  work -> destructor += 1;
+	  string_clear (declp);
+	  return;
+	}
+    }
+
+  if (declp->p - declp->b >= 3 
+      && declp->b[0] == 'o'
+      && declp->b[1] == 'p'
+      && strchr (cplus_markers, declp->b[2]) != NULL)
+    {
+      /* see if it's an assignment expression */
+      if (declp->p - declp->b >= 10 /* op$assign_ */
+	  && memcmp (declp->b + 3, "assign_", 7) == 0)
+	{
+	  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+	    {
+	      len = declp->p - declp->b - 10;
+	      if (strlen (optable[i].in) == len
+		  && memcmp (optable[i].in, declp->b + 10, len) == 0)
+		{
+		  string_clear (declp);
+		  string_append (declp, "operator");
+		  string_append (declp, optable[i].out);
+		  string_append (declp, "=");
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+	    {
+	      int len = declp->p - declp->b - 3;
+	      if (strlen (optable[i].in) == len 
+		  && memcmp (optable[i].in, declp->b + 3, len) == 0)
+		{
+		  string_clear (declp);
+		  string_append (declp, "operator");
+		  string_append (declp, optable[i].out);
+		  break;
+		}
+	    }
+	}
+    }
+  else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
+	   && strchr (cplus_markers, declp->b[4]) != NULL)
+    {
+      /* type conversion operator */
+      tem = declp->b + 5;
+      if (do_type (work, &tem, &type))
+	{
+	  string_clear (declp);
+	  string_append (declp, "operator ");
+	  string_appends (declp, &type);
+	  string_delete (&type);
+	}
+    }
+  else if (declp->b[0] == '_' && declp->b[1] == '_'
+	   && declp->b[2] == 'o' && declp->b[3] == 'p')
+    {
+      /* ANSI.  */
+      /* type conversion operator.  */
+      tem = declp->b + 4;
+      if (do_type (work, &tem, &type))
+	{
+	  string_clear (declp);
+	  string_append (declp, "operator ");
+	  string_appends (declp, &type);
+	  string_delete (&type);
+	}
+    }
+  else if (declp->b[0] == '_' && declp->b[1] == '_'
+	   && declp->b[2] >= 'a' && declp->b[2] <= 'z'
+	   && declp->b[3] >= 'a' && declp->b[3] <= 'z')
+    {
+      if (declp->b[4] == '\0')
+	{
+	  /* Operator.  */
+	  for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+	    {
+	      if (strlen (optable[i].in) == 2
+		  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
+		{
+		  string_clear (declp);
+		  string_append (declp, "operator");
+		  string_append (declp, optable[i].out);
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  if (declp->b[2] == 'a' && declp->b[5] == '\0')
+	    {
+	      /* Assignment.  */
+	      for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+		{
+		  if (strlen (optable[i].in) == 3
+		      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
+		    {
+		      string_clear (declp);
+		      string_append (declp, "operator");
+		      string_append (declp, optable[i].out);
+		      break;
+		    }		      
+		}
+	    }
+	}
+    }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+     string *s;
+     int n;
+{
+  int tem;
+
+  if (s->b == NULL)
+    {
+      if (n < 32)
+	{
+	  n = 32;
+	}
+      s->p = s->b = xmalloc (n);
+      s->e = s->b + n;
+    }
+  else if (s->e - s->p < n)
+    {
+      tem = s->p - s->b;
+      n += tem;
+      n *= 2;
+      s->b = xrealloc (s->b, n);
+      s->p = s->b + tem;
+      s->e = s->b + n;
+    }
+}
+
+static void
+string_delete (s)
+     string *s;
+{
+  if (s->b != NULL)
+    {
+      free (s->b);
+      s->b = s->e = s->p = NULL;
+    }
+}
+
+static void
+string_init (s)
+     string *s;
+{
+  s->b = s->p = s->e = NULL;
+}
+
+static void 
+string_clear (s)
+     string *s;
+{
+  s->p = s->b;
+}
+
+#if 0
+
+static int
+string_empty (s)
+     string *s;
+{
+  return (s->b == s->p);
+}
+
+#endif
+
+static void
+string_append (p, s)
+     string *p;
+     const char *s;
+{
+  int n;
+  if (s == NULL || *s == '\0')
+    return;
+  n = strlen (s);
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_appends (p, s)
+     string *p, *s;
+{
+  int n;
+
+  if (s->b != s->p)
+    {
+      n = s->p - s->b;
+      string_need (p, n);
+      memcpy (p->p, s->b, n);
+      p->p += n;
+    }
+}
+
+static void
+string_appendn (p, s, n)
+     string *p;
+     const char *s;
+     int n;
+{
+  if (n != 0)
+    {
+      string_need (p, n);
+      memcpy (p->p, s, n);
+      p->p += n;
+    }
+}
+
+static void
+string_prepend (p, s)
+     string *p;
+     const char *s;
+{
+  if (s != NULL && *s != '\0')
+    {
+      string_prependn (p, s, strlen (s));
+    }
+}
+
+static void
+string_prepends (p, s)
+     string *p, *s;
+{
+  if (s->b != s->p)
+    {
+      string_prependn (p, s->b, s->p - s->b);
+    }
+}
+
+static void
+string_prependn (p, s, n)
+     string *p;
+     const char *s;
+     int n;
+{
+  char *q;
+
+  if (n != 0)
+    {
+      string_need (p, n);
+      for (q = p->p - 1; q >= p->b; q--)
+	{
+	  q[n] = q[0];
+	}
+      memcpy (p->b, s, n);
+      p->p += n;
+    }
+}
+
+/* To generate a standalone demangler program for testing purposes,
+   just compile and link this file with -DMAIN and libiberty.a.  When
+   run, it demangles each command line arg, or each stdin string, and
+   prints the result on stdout.  */
+
+#ifdef MAIN
+
+#include "getopt.h"
+
+static char *program_name;
+static char *program_version = VERSION;
+static int flags = DMGL_PARAMS | DMGL_ANSI;
+
+static void demangle_it PARAMS ((char *));
+static void usage PARAMS ((FILE *, int));
+static void fatal PARAMS ((char *));
+
+static void
+demangle_it (mangled_name)
+     char *mangled_name;
+{
+  char *result;
+
+  result = cplus_demangle (mangled_name, flags);
+  if (result == NULL)
+    {
+      printf ("%s\n", mangled_name);
+    }
+  else
+    {
+      printf ("%s\n", result);
+      free (result);
+    }
+}
+
+static void
+usage (stream, status)
+     FILE *stream;
+     int status;
+{    
+  fprintf (stream, "\
+Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
+      [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
+      [--help] [--version] [arg...]\n",
+	   program_name);
+  exit (status);
+}
+
+#define MBUF_SIZE 512
+char mbuffer[MBUF_SIZE];
+
+/* Defined in the automatically-generated underscore.c.  */
+extern int prepends_underscore;
+
+int strip_underscore = 0;
+
+static struct option long_options[] = {
+  {"strip-underscores", no_argument, 0, '_'},
+  {"format", required_argument, 0, 's'},
+  {"help", no_argument, 0, 'h'},
+  {"java", no_argument, 0, 'j'},
+  {"no-strip-underscores", no_argument, 0, 'n'},
+  {"version", no_argument, 0, 'v'},
+  {0, no_argument, 0, 0}
+};
+
+/* More 'friendly' abort that prints the line and file.
+   config.h can #define abort fancy_abort if you like that sort of thing.  */
+
+void
+fancy_abort ()
+{
+  fatal ("Internal gcc abort.");
+}
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *result;
+  int c;
+
+  program_name = argv[0];
+
+  strip_underscore = prepends_underscore;
+
+  while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
+    {
+      switch (c)
+	{
+	case '?':
+	  usage (stderr, 1);
+	  break;
+	case 'h':
+	  usage (stdout, 0);
+	case 'n':
+	  strip_underscore = 0;
+	  break;
+	case 'v':
+	  printf ("GNU %s version %s\n", program_name, program_version);
+	  exit (0);
+	case '_':
+	  strip_underscore = 1;
+	  break;
+	case 'j':
+	  flags |= DMGL_JAVA;
+	  break;
+	case 's':
+	  if (strcmp (optarg, "gnu") == 0)
+	    {
+	      current_demangling_style = gnu_demangling;
+	    }
+	  else if (strcmp (optarg, "lucid") == 0)
+	    {
+	      current_demangling_style = lucid_demangling;
+	    }
+	  else if (strcmp (optarg, "arm") == 0)
+	    {
+	      current_demangling_style = arm_demangling;
+	    }
+	  else
+	    {
+	      fprintf (stderr, "%s: unknown demangling style `%s'\n",
+		       program_name, optarg);
+	      exit (1);
+	    }
+	  break;
+	}
+    }
+
+  if (optind < argc)
+    {
+      for ( ; optind < argc; optind++)
+	{
+	  demangle_it (argv[optind]);
+	}
+    }
+  else
+    {
+      for (;;)
+	{
+	  int i = 0;
+	  c = getchar ();
+	  /* Try to read a label.  */
+	  while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
+	    {
+	      if (i >= MBUF_SIZE-1)
+		break;
+	      mbuffer[i++] = c;
+	      c = getchar ();
+	    }
+	  if (i > 0)
+	    {
+	      int skip_first = 0;
+
+	      if (mbuffer[0] == '.')
+		++skip_first;
+	      if (strip_underscore && mbuffer[skip_first] == '_')
+		++skip_first;
+
+	      if (skip_first > i)
+		skip_first = i;
+
+	      mbuffer[i] = 0;
+	      
+	      result = cplus_demangle (mbuffer + skip_first, flags);
+	      if (result)
+		{
+		  if (mbuffer[0] == '.')
+		    putc ('.', stdout);
+		  fputs (result, stdout);
+		  free (result);
+		}
+	      else
+		fputs (mbuffer, stdout);
+
+	      fflush (stdout);
+	    }
+	  if (c == EOF)
+	    break;
+	  putchar (c);
+	}
+    }
+
+  exit (0);
+}
+
+static void
+fatal (str)
+     char *str;
+{
+  fprintf (stderr, "%s: %s\n", program_name, str);
+  exit (1);
+}
+
+char * malloc ();
+char * realloc ();
+
+char *
+xmalloc (size)
+     unsigned size;
+{
+  register char *value = (char *) malloc (size);
+  if (value == 0)
+    fatal ("virtual memory exhausted");
+  return value;
+}
+
+char *
+xrealloc (ptr, size)
+     char *ptr;
+     unsigned size;
+{
+  register char *value = (char *) realloc (ptr, size);
+  if (value == 0)
+    fatal ("virtual memory exhausted");
+  return value;
+}
+#endif	/* main */
Index: trunk/src/emx/src/emxexp/demangle.h
===================================================================
--- trunk/src/emx/src/emxexp/demangle.h	(revision 18)
+++ trunk/src/emx/src/emxexp/demangle.h	(revision 18)
@@ -0,0 +1,90 @@
+/* Defs for interface to demanglers.
+   Copyright 1992, 1995, 1996 Free Software Foundation, Inc.
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+
+#if !defined (DEMANGLE_H)
+#define DEMANGLE_H
+
+#ifdef IN_GCC
+#include "gansidecl.h"
+#define PARAMS(ARGS) PROTO(ARGS)
+#else /* ! IN_GCC */
+#include <ansidecl.h>
+#endif /* IN_GCC */
+
+/* Options passed to cplus_demangle (in 2nd parameter). */
+
+#define DMGL_NO_OPTS	0		/* For readability... */
+#define DMGL_PARAMS	(1 << 0)	/* Include function args */
+#define DMGL_ANSI	(1 << 1)	/* Include const, volatile, etc */
+#define DMGL_JAVA	(1 << 2)	/* Demangle as Java rather than C++. */
+
+#define DMGL_AUTO	(1 << 8)
+#define DMGL_GNU	(1 << 9)
+#define DMGL_LUCID	(1 << 10)
+#define DMGL_ARM	(1 << 11)
+/* If none of these are set, use 'current_demangling_style' as the default. */
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM)
+
+/* Enumeration of possible demangling styles.
+
+   Lucid and ARM styles are still kept logically distinct, even though
+   they now both behave identically.  The resulting style is actual the
+   union of both.  I.E. either style recognizes both "__pt__" and "__rf__"
+   for operator "->", even though the first is lucid style and the second
+   is ARM style. (FIXME?) */
+
+extern enum demangling_styles
+{
+  unknown_demangling = 0,
+  auto_demangling = DMGL_AUTO,
+  gnu_demangling = DMGL_GNU,
+  lucid_demangling = DMGL_LUCID,
+  arm_demangling = DMGL_ARM
+} current_demangling_style;
+
+/* Define string names for the various demangling styles. */
+
+#define AUTO_DEMANGLING_STYLE_STRING	"auto"
+#define GNU_DEMANGLING_STYLE_STRING	"gnu"
+#define LUCID_DEMANGLING_STYLE_STRING	"lucid"
+#define ARM_DEMANGLING_STYLE_STRING	"arm"
+
+/* Some macros to test what demangling style is active. */
+
+#define CURRENT_DEMANGLING_STYLE current_demangling_style
+#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO)
+#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU)
+#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID)
+#define ARM_DEMANGLING (CURRENT_DEMANGLING_STYLE & DMGL_ARM)
+
+extern char *
+cplus_demangle PARAMS ((const char *mangled, int options));
+
+extern int
+cplus_demangle_opname PARAMS ((const char *opname, char *result, int options));
+
+extern const char *
+cplus_mangle_opname PARAMS ((const char *opname, int options));
+
+/* Note: This sets global state.  FIXME if you care about multi-threading. */
+
+extern void
+set_cplus_marker_for_demangling PARAMS ((int ch));
+
+#endif	/* DEMANGLE_H */
Index: trunk/src/emx/src/emxexp/emxexp.c
===================================================================
--- trunk/src/emx/src/emxexp/emxexp.c	(revision 18)
+++ trunk/src/emx/src/emxexp/emxexp.c	(revision 18)
@@ -0,0 +1,623 @@
+/* emxexp.c -- Create export definitions from .o and .obj files
+   Copyright (c) 1993-1998 Eberhard Mattes
+
+This file is part of emxexp.
+
+emxexp is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxexp is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxexp; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ar.h>
+#include "defs.h"
+#include <sys/omflib.h>
+#include "demangle.h"
+
+#define VERSION "0.9d"
+
+struct bss_list
+{
+  char *name;
+  struct bss_list *next;
+};
+
+static int ordinal = 0;
+static int noname_flag = FALSE;
+static int bss_flag = FALSE;
+
+static FILE *out_file;
+static const char *inp_fname;
+static const char *mod_name;
+static int new_mod = FALSE;
+static int last_dem = FALSE;
+static struct bss_list *bss_list = NULL;
+
+static void error (const char *fmt, ...) NORETURN2;
+static void usage (void) NORETURN2;
+static void bad_omf (void) NORETURN2;
+
+
+static void error (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emxexp: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+  exit (2);
+}
+
+
+/* Allocate N bytes of memory.  Quit on failure.  This function is
+   used like malloc(), but we don't have to check the return value. */
+
+void *xmalloc (size_t n)
+{
+  void *p;
+  
+  p = malloc (n);
+  if (p == NULL)
+    error ("Out of memory");
+  return p;
+}
+
+
+/* Change the allocation of PTR to N bytes.  Quit on failure.  This
+   function is used like realloc(), but we don't have to check the
+   return value. */
+
+void *xrealloc (void *ptr, size_t n)
+{
+  void *p;
+  
+  p = realloc (ptr, n);
+  if (p == NULL)
+    error ("Out of memory");
+  return p;
+}
+
+
+/* How to call this program. */
+
+static void usage (void)
+{
+  fputs ("emxexp " VERSION " -- Copyright (c) 1993-1995 by Eberhard Mattes\n\n"
+         "Usage: emxexp [-n] [-u] [-o[<ordinal>] <input_file>...\n\n"
+         "Options:\n"
+         "  -n          Output NONAME keyword for each exported symbol\n"
+         "  -o          Output ordinal numbers, starting at 1\n"
+         "  -o<ordinal> Output ordinal numbers, starting at <ordinal>\n"
+         "  -u          Also export uninitialized variables\n",
+         stderr);
+  exit (1);
+}
+
+
+static void export (const char *name)
+{
+  char *dem;
+
+  if (new_mod)
+    {
+      fprintf (out_file, "\n; From %s", inp_fname);
+      if (mod_name != NULL)
+        fprintf (out_file, "(%s)", mod_name);
+      fputc ('\n', out_file);
+      new_mod = FALSE;
+    }
+  dem = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+  if (dem != NULL)
+    {
+      fprintf (out_file, "\n  ; %s\n", dem);
+      free (dem);
+      last_dem = TRUE;
+    }
+  else if (last_dem)
+    {
+      fputc ('\n', out_file);
+      last_dem = FALSE;
+    }
+  fprintf (out_file, "  \"%s\"", name);
+  if (ordinal != 0)
+    fprintf (out_file, " @%d", ordinal++);
+  if (noname_flag)
+    fprintf (out_file, " NONAME");
+  fputc ('\n', out_file);
+}
+
+
+static void export_bss (const char *name)
+{
+  struct bss_list *p;
+
+  if (bss_flag)
+    {
+      for (p = bss_list; p != NULL; p = p->next)
+        if (strcmp (p->name, name) == 0)
+          return;
+      p = xmalloc (sizeof (*p));
+      p->name = xmalloc (strlen (name) + 1);
+      strcpy (p->name, name);
+      p->next = bss_list;
+      bss_list = p;
+      export (name);
+    }
+}
+
+
+static void process_aout (FILE *inp_file, long size)
+{
+  byte *inp_buf;
+  const struct a_out_header *a_out_h;
+  const byte *sym;
+  const struct nlist *sym_ptr;
+  const byte *str_ptr;
+  long str_size;
+  int sym_count, i;
+  const char *name;
+
+  new_mod = TRUE;
+
+  inp_buf = xmalloc (size);
+  size = fread (inp_buf, 1, size, inp_file);
+
+  a_out_h = (struct a_out_header *)inp_buf;
+  if (size < sizeof (struct a_out_header) || a_out_h->magic != 0407)
+    error ("Malformed input file `%s'", inp_fname);
+  sym = (inp_buf + sizeof (struct a_out_header) + a_out_h->text_size
+         + a_out_h->data_size + a_out_h->trsize + a_out_h->drsize);
+  str_ptr = sym + a_out_h->sym_size;
+  if (str_ptr + 4 - inp_buf > size)
+    error ("Malformed input file `%s'", inp_fname);
+  str_size = *(long *)str_ptr;
+  sym_ptr = (const struct nlist *)sym;
+  sym_count = a_out_h->sym_size / sizeof (struct nlist);
+  if (str_ptr + str_size - inp_buf > size)
+    error ("Malformed input file `%s'", inp_fname);
+
+  for (i = 0; i < sym_count; ++i)
+    if (sym_ptr[i].type == (N_TEXT|N_EXT) || sym_ptr[i].type == (N_DATA|N_EXT))
+      {
+        name = str_ptr + sym_ptr[i].string;
+        if (*name == '_')
+          ++name;
+        export (name);
+      }
+    else if (sym_ptr[i].type == N_EXT && sym_ptr[i].value != 0)
+      {
+        name = str_ptr + sym_ptr[i].string;
+        if (*name == '_')
+          ++name;
+        export_bss (name);
+      }
+
+  free (inp_buf);
+}
+
+
+static byte rec_buf[MAX_REC_SIZE+8];
+static int rec_type;
+static int rec_len;
+static int rec_idx;
+
+
+static void bad_omf (void)
+{
+  error ("Malformed OMF file `%s'", inp_fname);
+}
+
+
+static void get_mem (void *dst, int len)
+{
+  if (rec_idx + len > rec_len)
+    bad_omf ();
+  memcpy (dst, rec_buf + rec_idx, len);
+  rec_idx += len;
+}
+
+
+static int get_byte (void)
+{
+  if (rec_idx >= rec_len)
+    bad_omf ();
+  return rec_buf[rec_idx++];
+}
+
+
+static void get_string (byte *dst)
+{
+  int len;
+
+  len = get_byte ();
+  get_mem (dst, len);
+  dst[len] = 0;
+}
+
+
+static int get_index (void)
+{
+  int result;
+
+  result = get_byte ();
+  if (result & 0x80)
+    {
+      if (rec_idx >= rec_len)
+        bad_omf ();
+      result = ((result & 0x7f) << 8) | rec_buf[rec_idx++];
+    }
+  return result;
+}
+
+
+static word get_dword (void)
+{
+  dword result;
+
+  if (rec_idx + 4 > rec_len)
+    bad_omf ();
+  result = rec_buf[rec_idx++];
+  result |= rec_buf[rec_idx++] << 8;
+  result |= rec_buf[rec_idx++] << 16;
+  result |= rec_buf[rec_idx++] << 24;
+  return result;
+}
+
+
+static word get_word (void)
+{
+  word result;
+
+  if (rec_idx + 2 > rec_len)
+    bad_omf ();
+  result = rec_buf[rec_idx++];
+  result |= rec_buf[rec_idx++] << 8;
+  return result;
+}
+
+
+static dword get_word_or_dword (void)
+{
+  return rec_type & REC32 ? get_dword () : get_word ();
+}
+
+
+static dword get_commlen (void)
+{
+  dword result;
+
+  result = get_byte ();
+  if (result <= 0x80)
+    return result;
+  switch (result)
+    {
+    case 0x81:
+      return get_word ();
+    case 0x84:
+      result = get_byte ();
+      result |= get_byte () << 8;
+      result |= get_byte () << 16;
+      return result;
+    case 0x88:
+      return get_dword ();
+    default:
+      bad_omf ();
+    }
+}
+
+
+static void omf_pubdef (void)
+{
+  int type, group, seg;
+  word frame;
+  dword offset;
+  byte name[256];
+
+  group = get_index ();
+  seg = get_index ();
+  if (seg == 0)
+    frame = get_word ();
+
+  while (rec_idx < rec_len)
+    {
+      get_string (name);
+      offset = get_word_or_dword ();
+      type = get_index ();
+      export (name);
+    }
+}
+
+
+static void omf_comdef (void)
+{
+  int type_index, data_type;
+  byte name[256];
+
+  while (rec_idx < rec_len)
+    {
+      get_string (name);
+      type_index = get_index ();
+      data_type = get_byte ();
+      switch (data_type)
+        {
+        case 0x61:
+          get_commlen ();
+          get_commlen ();
+          break;
+        case 0x62:
+          get_commlen ();
+          break;
+        default:
+          bad_omf ();
+        }
+      export_bss (name);
+    }
+}
+
+
+static void process_omf (FILE *inp_file)
+{
+  struct omf_rec rec;
+
+  new_mod = TRUE;
+  do
+    {
+      if (fread (&rec, sizeof (rec), 1, inp_file) != 1)
+        error ("Unexpected end of file on input file `%s'", inp_fname);
+      rec_type = rec.rec_type;
+      rec_len = rec.rec_len;
+      rec_idx = 0;
+      if (rec_len > sizeof (rec_buf))
+        error ("OMF record too long in `%s'", inp_fname);
+      if (fread (rec_buf, rec_len, 1, inp_file) != 1)
+        error ("Unexpected end of file on input file `%s'", inp_fname);
+      --rec_len;                /* Remove checksum */
+      switch (rec_type)
+        {
+        case PUBDEF:
+        case PUBDEF|REC32:
+          omf_pubdef ();
+          break;
+        case COMDEF:
+          if (bss_flag)
+            omf_comdef ();
+          break;
+        }
+    } while (rec.rec_type != MODEND && rec_type != (MODEND|REC32));
+}
+
+
+/* Process one input file. */
+
+static void process (void)
+{
+  static char ar_magic[SARMAG+1] = ARMAG;
+  char ar_test[SARMAG], *p, *end;
+  struct ar_hdr ar;
+  long size, ar_pos, index;
+  int i, n;
+  FILE *inp_file;
+  char *long_names = NULL;
+  size_t long_names_size = 0;
+
+  mod_name = NULL;
+  inp_file = fopen (inp_fname, "rb");
+  if (inp_file == NULL)
+    error ("Cannot open input file `%s'", inp_fname);
+
+  /* Read some bytes from the start of the file to find out whether
+     this is an archive (.a) file or not. */
+
+  if (fread (ar_test, sizeof (ar_test), 1, inp_file) != 1)
+    error ("Cannot read input file `%s'", inp_fname);
+
+  if (memcmp (ar_test, ar_magic, SARMAG) == 0)
+    {
+
+      /* The input file is an archive. Loop over all the members of
+         the archive. */
+
+      ar_pos = SARMAG;
+      for (;;)
+        {
+
+          /* Read the header of the member. */
+
+          fseek (inp_file, ar_pos, SEEK_SET);
+          size = fread  (&ar, 1, sizeof (ar), inp_file);
+          if (size == 0)
+            break;
+          else if (size != sizeof (ar))
+            error ("Malformed archive `%s'", inp_fname);
+
+          /* Decode the header. */
+
+          errno = 0;
+          size = strtol (ar.ar_size, &p, 10);
+          if (p == ar.ar_size || errno != 0 || size <= 0 || *p != ' ')
+            error ("Malformed archive header in `%s'", inp_fname);
+          ar_pos += (sizeof (ar) + size + 1) & -2;
+
+          /* Remove trailing blanks from the member name. */
+
+          i = sizeof (ar.ar_name) - 1;
+          while (i > 0 && ar.ar_name[i-1] == ' ')
+            --i;
+          ar.ar_name[i] = 0;
+
+          if (strcmp (ar.ar_name, "ARFILENAMES/") == 0)
+            {
+              size_t i;
+
+              /* The "ARFILENAMES/" member contains the long file
+                 names, each one is terminated with a newline
+                 character.  Member names starting with a space are
+                 also considered long file names because a leading
+                 space is used for names pointing into the
+                 "ARFILENAMES/" table.  Read the "ARFILENAMES/" member
+                 to LONG_NAMES. */
+
+              if (size != 0)
+                {
+                  long_names_size = (size_t)size;
+                  long_names = xmalloc (long_names_size);
+                  size = fread (long_names, 1, long_names_size, inp_file);
+                  if (ferror (inp_file))
+                    error ("Cannot read `%s'", inp_fname);
+                  if (size != long_names_size)
+                    error ("%s: ARFILENAMES/ member is truncated", inp_fname);
+
+                  /* Replace the newlines with nulls to make
+                     processing a bit more convenient. */
+
+                  for (i = 0; i < long_names_size; ++i)
+                    if (long_names[i] == '\n')
+                      long_names[i] = 0;
+                  if (long_names[long_names_size-1] != 0)
+                    error ("%s: ARFILENAMES/ member corrupt", inp_fname);
+                }
+            }
+
+          /* Ignore the __.SYMDEF and __.IMPORT members. */
+
+          else if (strcmp (ar.ar_name, "__.SYMDEF") != 0
+              && strcmp (ar.ar_name, "__.IMPORT") != 0)
+            {
+              /* Process the current member.  First, fetch the name of
+                 the member.  If the ar_name starts with a space, the
+                 decimal number following that space is an offset into
+                 the "ARFILENAMES/" member.  The number may be
+                 followed by a space and a substring of the long file
+                 name. */
+
+              mod_name = ar.ar_name;
+              if (mod_name[0] == ' ' && long_names != NULL
+                  && (index = strtol (mod_name + 1, &end, 10)) >= 0
+                  && index < long_names_size - 1
+                  && (*end == 0 || *end == ' ')
+                  && (index == 0 || long_names[index-1] == 0))
+                mod_name = long_names + index;
+
+              process_aout (inp_file, size);
+            }
+        }
+    }
+  else
+    {
+      if (*(word *)ar_test == 0407)
+        {
+          if (fseek (inp_file, 0L, SEEK_END) != 0)
+            error ("Input file `%s' is not seekable", inp_fname);
+          size = ftell (inp_file);
+          fseek (inp_file, 0L, SEEK_SET);
+          process_aout (inp_file, size);
+        }
+      else if (*(byte *)ar_test == LIBHDR)
+        {
+          struct omflib *lib;
+          char errmsg[512], name[257];
+          int page;
+
+          lib = omflib_open (inp_fname, errmsg);
+          if (lib == NULL)
+            error ("%s: %s", inp_fname, errmsg);
+
+          n = omflib_module_count (lib, errmsg);
+          if (n == -1)
+            error ("%s: %s", inp_fname, errmsg);
+          for (i = 0; i < n; ++i)
+            {
+              if (omflib_module_info (lib, i, name, &page, errmsg) != 0)
+                error ("%s: %s", inp_fname, errmsg);
+              else
+                {
+                  fseek (inp_file, omflib_page_pos (lib, page), SEEK_SET);
+                  mod_name = name;
+                  process_omf (inp_file);
+                }
+            }
+          if (omflib_close (lib, errmsg) != 0)
+            error ("%s: %s", inp_fname, errmsg);
+        }
+      else
+        {
+          fseek (inp_file, 0L, SEEK_SET);
+          process_omf (inp_file);
+        }
+    }
+  fclose (inp_file);
+}
+
+
+/* Main line. */
+
+int main (int argc, char **argv)
+{
+  int c, i;
+  char *p;
+
+  _response (&argc, &argv);
+  _wildcard (&argc, &argv);
+  opterr = 0;
+  optswchar = "-";
+  optind = 0;
+  while ((c = getopt (argc, argv, "no::u")) != EOF)
+    {
+      switch (c)
+        {
+        case 'n':
+          noname_flag = TRUE;
+          break;
+        case 'o':
+          if (optarg == NULL)
+            ordinal = 1;
+          else
+            {
+              errno = 0;
+              ordinal = (int)strtol (optarg, &p, 0);
+              if (p == optarg || errno != 0 || *p != 0
+                  || ordinal < 1 || ordinal > 65535)
+                usage ();
+            }
+          break;
+        case 'u':
+          bss_flag = TRUE;
+          break;
+        default:
+          error ("Invalid option");
+        }
+    }
+
+  out_file = stdout;
+
+  if (optind >= argc)
+    usage ();
+
+  for (i = optind; i < argc; ++i)
+    {
+      inp_fname = argv[i];
+      process ();
+    }
+
+  if (fflush (out_file) != 0 || (out_file != stdout && fclose (out_file) != 0))
+    error ("Write error");
+
+  return 0;
+}
Index: trunk/src/emx/src/emxexp/libibert.h
===================================================================
--- trunk/src/emx/src/emxexp/libibert.h	(revision 18)
+++ trunk/src/emx/src/emxexp/libibert.h	(revision 18)
@@ -0,0 +1,4 @@
+/* libibert.h */
+
+char *xmalloc (size_t n);
+char *xrealloc (void *p, size_t n);
Index: trunk/src/emx/src/emxexp/makefile
===================================================================
--- trunk/src/emx/src/emxexp/makefile	(revision 18)
+++ trunk/src/emx/src/emxexp/makefile	(revision 18)
@@ -0,0 +1,54 @@
+#
+# /emx/src/emxexp/makefile
+#
+# Copyright (c) 1993-1998 by Eberhard Mattes
+#
+# This file is part of emxexp.
+#
+# emxexp is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emxexp is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emxexp; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+BIN=/emx/bin/
+
+DEFS_H=../include/defs.h
+OMFLIB_H=d:/emx/include/sys/omflib.h
+
+OMFLIB=d:/emx/lib/omflib.a
+
+CC=gcc
+CFLAGS=-O -Wall -I../include -I.
+LFLAGS=-s -Zsmall-conv
+
+default:	all
+all:		emxexp
+emxexp:	$(BIN)emxexp.exe
+
+emxexp.o: emxexp.c $(DEFS_H) $(OMFLIB_H)
+	$(CC) $(CFLAGS) -c emxexp.c
+
+cplus-de.o: cplus-de.c demangle.h ansidecl.h libibert.h
+	$(CC) $(CFLAGS) -c cplus-de.c
+
+$(BIN)emxexp.exe: emxexp.o cplus-de.o $(OMFLIB)
+	$(CC) $(LFLAGS) -o $(BIN)emxexp.exe emxexp.o cplus-de.o $(OMFLIB)
+
+clean:
+	-rm *.o
+
+realclean: clean
+	-rm $(BIN)emxexp.exe
+
+# End of /emx/src/emxexp/makefile
Index: trunk/src/emx/src/emximp/COPYING
===================================================================
--- trunk/src/emx/src/emximp/COPYING	(revision 18)
+++ trunk/src/emx/src/emximp/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emximp/emximp.c
===================================================================
--- trunk/src/emx/src/emximp/emximp.c	(revision 18)
+++ trunk/src/emx/src/emximp/emximp.c	(revision 18)
@@ -0,0 +1,1254 @@
+/* emximp.c  -- Manage import libraries
+   Copyright (c) 1992-1998 Eberhard Mattes
+
+This file is part of emximp.
+
+emximp is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emximp is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emximp; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <process.h>
+#include <ar.h>
+#include <time.h>
+#include <sys/moddef.h>
+#include "defs.h"
+#include <sys/omflib.h>
+
+#define VERSION "0.9d"
+
+#define NORETURN2 __attribute__ ((noreturn))
+
+#define MOD_PREDEF   0
+#define MOD_DEF      1
+#define MOD_REF      2
+
+#define N_EXT  0x01
+#define N_ABS  0x02
+#define N_IMP1 0x68
+#define N_IMP2 0x6a
+
+#define PARMS_REG     (-1)
+#define PARMS_FAR16   (-2)
+
+struct lib
+{
+  struct lib *next;
+  char *name;
+  int lbl;
+};
+
+struct predef
+{
+  struct predef *next;
+  char *name;
+};
+
+enum modes
+{
+  M_NONE,                       /* No mode selected */
+  M_LIB_TO_IMP,                 /* .lib -> .imp */
+  M_IMP_TO_S,                   /* .imp -> .s or .o */
+  M_IMP_TO_DEF,                 /* .imp -> .def */
+  M_LIB_TO_A,                   /* .lib -> .a */
+  M_IMP_TO_A,                   /* .imp -> .a */
+  M_IMP_TO_LIB,                 /* .imp -> .lib */
+  M_DEF_TO_IMP,                 /* .def -> .imp */
+  M_DEF_TO_A,                   /* .def -> .a */
+  M_DEF_TO_LIB                  /* .def -> .lib */
+};
+
+static FILE *out_file = NULL;
+static char out_fname[128];
+static struct lib *libs;
+static struct predef *predefs;
+static char *out_base;
+static int base_len;
+static char *as_name;
+static int pipe_flag;
+static int profile_flag;
+static int opt_b;
+static int opt_q;
+static int opt_s;
+static enum modes mode = M_NONE;
+static long mod_lbl;
+static long seq_no = 1;
+static char *first_module = NULL;
+static int warnings = 0;
+static struct omflib *out_lib;
+static char lib_errmsg[512];
+static char *module_name = NULL;
+
+
+static void error (const char *fmt, ...) NORETURN2;
+static void write_error (const char *fname) NORETURN2;
+static void lib_error (void) NORETURN2;
+static void write_a_import (const char *func_name, const char *mod_name,
+    int ordinal, const char *proc_name);
+
+
+static void usage (void)
+{
+  puts ("emximp " VERSION " -- Copyright (c) 1992-1996 by Eberhard Mattes\n");
+  puts ("Usage:");
+  puts ("  emximp [-a[<assembler>]] [-b <base_name>|<prefix_length>] "
+        "[-p <module>] ...");
+  puts ("         [-s] <input_file>.imp");
+  puts ("  emximp [-m] -o <output_file>.a <input_file>.def ...");
+  puts ("  emximp [-m] -o <output_file>.a <input_file>.imp ...");
+  puts ("  emximp [-m] -o <output_file>.a <input_file>.lib ...");
+  puts ("  emximp -o <output_file>.def <input_file>.imp ...");
+  puts ("  emximp -o <output_file>.imp <input_file>.def ...");
+  puts ("  emximp -o <output_file>.imp <input_file>.lib ...");
+  puts ("  emximp [-p#] -o <output_file>.lib <input_file>.def ...");
+  puts ("  emximp [-p#] -o <output_file>.lib <input_file>.imp...");
+  puts ("Options:");
+  puts ("  -p#  Set page size");
+  puts ("  -q   Be quiet");
+  puts ("  -m   Call _mcount for profiling");
+  exit (1);
+}
+
+
+static void error (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emximp: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+  exit (2);
+}
+
+
+static void warning (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emximp: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+  ++warnings;
+}
+
+
+/* Like warning(), but don't increment `warnings'. */
+
+static void information (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emximp: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+}
+
+
+void *xmalloc (size_t n)
+{
+  void *p;
+  
+  p = malloc (n);
+  if (p == NULL)
+    error ("Out of memory");
+  return p;
+}
+
+
+void *xrealloc (void *p, size_t n)
+{
+  void *q;
+  
+  q = realloc (p, n);
+  if (q == NULL)
+    error ("Out of memory");
+  return q;
+}
+
+
+char *xstrdup (const char *s)
+{
+  char *p;
+  
+  p = xmalloc (strlen (s) + 1);
+  strcpy (p, s);
+  return p;
+}
+
+
+static void write_error (const char *fname)
+{
+  error ("Write error on output file `%s'", fname);
+}
+
+
+static void lib_error (void)
+{
+  error ("%s", lib_errmsg);
+}
+
+
+static void out_flush (void)
+{
+  char name[512];
+  char *nargv[5];
+  int rc;
+  
+  if (out_file != NULL)
+    {
+      if (fflush (out_file) != 0)
+        write_error (out_fname);
+      if (pipe_flag)
+        {
+          rc = pclose (out_file);
+          if (rc == -1)
+            error ("Error while closing pipe");
+          if (rc > 0)
+            error ("Assembly failed, return code = %d", rc);
+        }
+      else
+        {
+          if (fclose (out_file) != 0)
+            error ("Cannot close output file `%s'", out_fname);
+          if (as_name != NULL)
+            {
+              _splitpath (out_fname, NULL, NULL, name, NULL);
+              strcat (name, ".o");
+              nargv[0] = as_name;
+              nargv[1] = "-o";
+              nargv[2] = name;
+              nargv[3] = out_fname;
+              nargv[4] = NULL;
+              rc = spawnvp (P_WAIT, as_name, nargv);
+              if (rc < 0)
+                error ("Cannot run `%s'", as_name);
+              if (rc > 0)
+                error ("Assembly of `%s' failed, return code = %d",
+                       out_fname, rc);
+              remove (out_fname);
+            }
+        }
+      out_file = NULL;
+    }
+}
+
+
+static void out_start (void)
+{
+  struct lib *lp1, *lp2;
+  char name[512], cmd[512];
+  
+  if (pipe_flag)
+    {
+      _splitpath (out_fname, NULL, NULL, name, NULL);
+      strcat (name, ".o");
+      sprintf (cmd, "%s -o %s", as_name, name);
+      out_file = popen (cmd, "wt");
+      if (out_file == NULL)
+        error ("Cannot open pipe to `%s'", as_name);
+    }
+  else
+    {
+      out_file = fopen (out_fname, "wt");
+      if (out_file == NULL)
+        error ("Cannot open output file `%s'", out_fname);
+    }
+  fprintf (out_file, "/ %s (emx+gcc)\n\n", out_fname);
+  fprintf (out_file, "\t.text\n");
+  for (lp1 = libs; lp1 != NULL; lp1 = lp2)
+    {
+      lp2 = lp1->next;
+      free (lp1->name);
+      free (lp1);
+    }
+  libs = NULL; mod_lbl = 1;
+}
+
+
+static void write_lib_import (const char *func, const char *module, long ord,
+                              const char *name)
+{
+  byte omfbuf[1024];
+  int i, len;
+  word page;
+
+  if (omflib_write_module (out_lib, func, &page, lib_errmsg) != 0)
+    lib_error ();
+  if (omflib_add_pub (out_lib, func, page, lib_errmsg) != 0)
+    lib_error ();
+  i = 0;
+  omfbuf[i++] = 0x00;
+  omfbuf[i++] = IMPDEF_CLASS;
+  omfbuf[i++] = IMPDEF_SUBTYPE;
+  omfbuf[i++] = (ord < 1 ? 0x00 : 0x01);
+  len = strlen (func);
+  omfbuf[i++] = (byte)len;
+  memcpy (omfbuf+i, func, len); i += len;
+  len = strlen (module);
+  omfbuf[i++] = (byte)len;
+  memcpy (omfbuf+i, module, len); i += len;
+  if (ord < 1)
+    {
+      if (strcmp (func, name) == 0)
+        len = 0;
+      else
+        len = strlen (name);
+      omfbuf[i++] = (byte)len;
+      memcpy (omfbuf+i, name, len); i += len;
+    }
+  else
+    {
+      omfbuf[i++] = (byte)ord;
+      omfbuf[i++] = (byte)(ord >> 8);
+    }
+  if (omflib_write_record (out_lib, COMENT, i, omfbuf, TRUE,
+                           lib_errmsg) != 0)
+    lib_error ();
+  omfbuf[0] = 0x00;
+  if (omflib_write_record (out_lib, MODEND, 1, omfbuf, TRUE,
+                           lib_errmsg) != 0)
+    lib_error ();
+}
+
+
+#define DELIM(c) ((c) == 0 || isspace ((unsigned char)c))
+
+
+static void read_imp (const char *fname)
+{
+  FILE *inp_file;
+  char buf[512], func[256], name[256], module[256], mod_ref[256], *p, *q;
+  char tmp[512];
+  long line_no, ord, parms, file_no;
+  int mod_type;
+  struct lib *lp1;
+  struct predef *pp1;
+
+  libs = NULL; mod_lbl = 1;
+  inp_file = fopen (fname, "rt");
+  if (inp_file == NULL)
+    error ("Cannot open input file `%s'", fname);
+  line_no = 0;
+  while (fgets (buf, sizeof (buf), inp_file) != NULL)
+    {
+      ++line_no;
+      p = strchr (buf, '\n');
+      if (p != NULL) *p = 0;
+      p = buf;
+      while (isspace ((unsigned char)*p)) ++p;
+      if (*p == '+')
+        {
+          if (mode == M_IMP_TO_S)
+            {
+              if (opt_b)
+                error ("Output file name in line %ld of %s not allowed "
+                       "as -b is used", line_no, fname);
+              ++p;
+              while (isspace ((unsigned char)*p)) ++p;
+              out_flush ();
+              q = out_fname;
+              while (!DELIM (*p))
+                *q++ = *p++;
+              *q = 0;
+              while (isspace ((unsigned char)*p)) ++p;
+              if (*p != 0 && *p != ';')
+                error ("Invalid file name in line %ld of %s", line_no, fname);
+              out_start ();
+            }
+        }
+      else if (*p == 0 || *p == ';')
+        ;           /* empty line */
+      else
+        {
+          if (!opt_b && out_file == NULL && mode != M_IMP_TO_LIB)
+            error ("No output file selected in line %ld of %s",
+                   line_no, fname);
+          if (DELIM (*p))
+            error ("Function name expected in line %ld of %s", line_no, fname);
+          q = func;
+          while (!DELIM (*p))
+            *q++ = *p++;
+          *q = 0;
+          while (isspace ((unsigned char)*p)) ++p;
+          if (DELIM (*p))
+            error ("Module name expected in line %ld of %s", line_no, fname);
+          q = module;
+          while (!DELIM (*p))
+            *q++ = *p++;
+          *q = 0;
+          while (isspace ((unsigned char)*p)) ++p;
+          if (DELIM (*p))
+            error ("External name or ordinal expected in line %ld of %s",
+                   line_no, fname);
+          if (isdigit ((unsigned char)*p))
+            {
+              name[0] = 0;
+              ord = strtol (p, &p, 10);
+              if (ord < 1 || ord > 65535 || !DELIM (*p))
+                error ("Invalid ordinal in line %ld of %s", line_no, fname);
+            }
+          else
+            {
+              if (opt_b && !opt_s)
+                error ("External name in line %ld of %s cannot be used "
+                       "as -b is given", line_no, fname);
+              ord = -1;
+              q = name;
+              while (!DELIM (*p))
+                *q++ = *p++;
+              *q = 0;
+            }
+          while (isspace ((unsigned char)*p)) ++p;
+          if (DELIM (*p))
+            error ("Number of arguments expected in line %ld of %s",
+                   line_no, fname);
+          if (*p == '?')
+            {
+              ++p;
+              parms = 0;
+              if (mode == M_IMP_TO_S)
+                warning ("Unknown number of arguments in line %ld of %s",
+                         line_no, fname);
+            }
+          else if (*p == 'R')
+            {
+              ++p;
+              parms = PARMS_REG;
+            }
+          else if (*p == 'F')
+            {
+              ++p;
+              parms = PARMS_FAR16;
+              if (mode == M_IMP_TO_S)
+                warning ("16-bit function not supported (line %ld of %s)",
+                         line_no, fname);
+              if (strlen (func) + 4 >= sizeof (func))
+                error ("Function name too long in line %ld of %s",
+                       line_no, fname);
+              strcpy (tmp, func);
+              strcpy (func, "_16_");
+              strcat (func, tmp);
+            }
+          else
+            {
+              parms = strtol (p, &p, 10);
+              if (parms < 0 || parms > 255 || !DELIM (*p))
+                error ("Invalid number of parameters in line %ld of %s",
+                       line_no, fname);
+            }
+          while (isspace ((unsigned char)*p)) ++p;
+          if (*p != 0 && *p != ';')
+            error ("Unexpected characters at end of line %ld of %s",
+                   line_no, fname);
+          switch (mode)
+            {
+            case M_IMP_TO_DEF:
+              if (first_module == NULL)
+                {
+                  first_module = xstrdup (module);
+                  fprintf (out_file, "LIBRARY %s\n", module);
+                  fprintf (out_file, "EXPORTS\n");
+                }
+              else if (strcmp (first_module, module) != 0)
+                error ("All functions must be in the same module "
+                       "(input file %s)", fname);
+              if (ord >= 0)
+                fprintf (out_file, "  %-32s @%ld\n", func, ord);
+              else if (strcmp (func, name) == 0)
+                fprintf (out_file, "  %-32s\n", func);
+              else
+                fprintf (out_file, "  %-32s = %s\n", name, func);
+              break;
+            case M_IMP_TO_A:
+              if (ord < 1)
+                write_a_import (func, module, ord, name);
+              else
+                write_a_import (func, module, ord, NULL);
+              break;
+            case M_IMP_TO_LIB:
+              write_lib_import (func, module, ord, name);
+              break;
+            case M_IMP_TO_S:
+              if (opt_b)
+                {
+                  out_flush ();
+                  if (opt_s)
+                    file_no = seq_no++;
+                  else
+                    file_no = ord;
+                  if (out_base != NULL)
+                    sprintf (out_fname, "%s%ld.s", out_base, file_no);
+                  else
+                    sprintf (out_fname, "%.*s%ld.s",
+                             base_len, module, file_no);
+                  out_start ();
+                }
+              for (pp1 = predefs; pp1 != NULL; pp1 = pp1->next)
+                if (stricmp (module, pp1->name) == 0)
+                  break;
+              if (pp1 != NULL)
+                {
+                  mod_type = MOD_PREDEF;
+                  sprintf (mod_ref, "__os2_%s", pp1->name);
+                }
+              else
+                {
+                  for (lp1 = libs; lp1 != NULL; lp1 = lp1->next)
+                    if (stricmp (module, lp1->name) == 0)
+                      break;
+                  if (lp1 == NULL)
+                    {
+                      mod_type = MOD_DEF;
+                      lp1 = xmalloc (sizeof (struct lib));
+                      lp1->name = xstrdup (module);
+                      lp1->lbl = mod_lbl++;
+                      lp1->next = libs;
+                      libs = lp1;
+                    }
+                  else
+                    mod_type = MOD_REF;
+                  sprintf (mod_ref, "L%d", lp1->lbl);
+                }
+              fprintf (out_file, "\n\t.globl\t_%s\n", func);
+              fprintf (out_file, "\t.align\t2, %d\n", 0x90);
+              fprintf (out_file, "_%s:\n", func);
+              if (parms >= 0)
+                fprintf (out_file, "\tmovb\t$%d, %%al\n", (int)parms);
+              fprintf (out_file, "1:\tjmp\t__os2_bad\n");
+              if (ord >= 0)
+                fprintf (out_file, "2:\t.long\t1, 1b+1, %s, %d\n",
+                         mod_ref, (int)ord);
+              else
+                fprintf (out_file, "2:\t.long\t0, 1b+1, %s, 4f\n", mod_ref);
+              if (mod_type == MOD_DEF)
+                fprintf (out_file, "%s:\t.asciz\t\"%s\"\n", mod_ref, module);
+              if (ord < 0)
+                fprintf (out_file, "4:\t.asciz\t\"%s\"\n", name);
+              fprintf (out_file, "\t.stabs  \"__os2dll\", 23, 0, 0, 2b\n");
+              break;
+            default:
+              abort ();
+            }
+        }
+    }
+  if (mode == M_IMP_TO_S)
+    out_flush ();
+  if (ferror (inp_file))
+    error ("Read error on input file `%s'", fname);
+  fclose (inp_file);
+}
+
+
+static void set_ar (char *dst, const char *src, int size)
+{
+  while (*src != 0 && size > 0)
+    {
+      *dst++ = *src++;
+      --size;
+    }
+  while (size > 0)
+    {
+      *dst++ = ' ';
+      --size;
+    }
+}
+
+
+static long ar_member_size;
+
+static void write_ar (const char *name, long size)
+{
+  struct ar_hdr ar;
+  char tmp[20];
+
+  ar_member_size = size;
+  set_ar (ar.ar_name, name, sizeof (ar.ar_name));
+  sprintf (tmp, "%ld", (long)time (NULL));
+  set_ar (ar.ar_date, tmp, sizeof (ar.ar_date));
+  set_ar (ar.ar_uid, "0", sizeof (ar.ar_uid));
+  set_ar (ar.ar_gid, "0", sizeof (ar.ar_gid));
+  set_ar (ar.ar_mode, "100666", sizeof (ar.ar_gid));
+  sprintf (tmp, "%ld", size);
+  set_ar (ar.ar_size, tmp, sizeof (ar.ar_size));
+  set_ar (ar.ar_fmag, ARFMAG, sizeof (ar.ar_fmag));
+  fwrite (&ar, 1, sizeof (ar), out_file);
+}
+
+
+static void finish_ar (void)
+{
+  if (ar_member_size & 1)
+    fputc (0, out_file);
+}
+
+
+static dword aout_str_size;
+static char aout_str_tab[2048];
+static int aout_sym_count;
+static struct nlist aout_sym_tab[6];
+
+static byte aout_text[64];
+static int aout_text_size;
+
+static struct reloc aout_treloc_tab[2];
+static int aout_treloc_count;
+
+static int aout_size;
+
+
+static void aout_init (void)
+{
+  aout_str_size = sizeof (dword);
+  aout_sym_count = 0;
+  aout_text_size = 0;
+  aout_treloc_count = 0;
+}
+
+static int aout_sym (const char *name, byte type, byte other,
+                     word desc, dword value)
+{
+  int len;
+
+  len = strlen (name);
+  if (aout_str_size + len + 1 > sizeof (aout_str_tab))
+    error ("a.out string table overflow");
+  if (aout_sym_count >= sizeof (aout_sym_tab) / sizeof (aout_sym_tab[0]))
+    error ("a.out symbol table overflow");
+  aout_sym_tab[aout_sym_count].string = aout_str_size;
+  aout_sym_tab[aout_sym_count].type = type;
+  aout_sym_tab[aout_sym_count].other = other;
+  aout_sym_tab[aout_sym_count].desc = desc;
+  aout_sym_tab[aout_sym_count].value = value;
+  strcpy (aout_str_tab + aout_str_size, name);
+  aout_str_size += len + 1;
+  return aout_sym_count++;
+}
+
+
+static void aout_text_byte (byte b)
+{
+  if (aout_text_size >= sizeof (aout_text))
+    error ("a.out text segment overflow");
+  aout_text[aout_text_size++] = b;
+}
+
+
+static void aout_text_dword (dword d)
+{
+  aout_text_byte ((d >> 0) & 0xff);
+  aout_text_byte ((d >> 8) & 0xff);
+  aout_text_byte ((d >> 16) & 0xff);
+  aout_text_byte ((d >> 24) & 0xff);
+}
+
+
+static void aout_treloc (dword address, int symbolnum, int pcrel, int length,
+                         int ext)
+{
+  if (aout_treloc_count >= sizeof (aout_treloc_tab) / sizeof (struct reloc))
+    error ("a.out text relocation buffer overflow");
+  aout_treloc_tab[aout_treloc_count].address = address;
+  aout_treloc_tab[aout_treloc_count].symbolnum = symbolnum;
+  aout_treloc_tab[aout_treloc_count].pcrel = pcrel;
+  aout_treloc_tab[aout_treloc_count].length = length;
+  aout_treloc_tab[aout_treloc_count].ext = ext;
+  aout_treloc_tab[aout_treloc_count].unused = 0;
+  ++aout_treloc_count;
+}
+
+
+static void aout_finish (void)
+{
+  while (aout_text_size & 3)
+    aout_text_byte (0x90);
+  aout_size = (sizeof (struct a_out_header) + aout_text_size
+               + aout_treloc_count * sizeof (struct reloc)
+               + aout_sym_count * sizeof (aout_sym_tab[0])
+               + aout_str_size);
+}
+
+
+static void aout_write (void)
+{
+  struct a_out_header ao;
+
+  ao.magic = 0407;
+  ao.machtype = 0;
+  ao.flags = 0;
+  ao.text_size = aout_text_size;
+  ao.data_size = 0;
+  ao.bss_size = 0;
+  ao.sym_size = aout_sym_count * sizeof (aout_sym_tab[0]);
+  ao.entry = 0;
+  ao.trsize = aout_treloc_count * sizeof (struct reloc);
+  ao.drsize = 0;
+  fwrite (&ao, 1, sizeof (ao), out_file);
+  fwrite (aout_text, 1, aout_text_size, out_file);
+  fwrite (aout_treloc_tab, aout_treloc_count, sizeof (struct reloc), out_file);
+  fwrite (aout_sym_tab, aout_sym_count, sizeof (aout_sym_tab[0]), out_file);
+  *(dword *)aout_str_tab = aout_str_size;
+  fwrite (aout_str_tab, 1, aout_str_size, out_file);
+}
+
+
+static void write_a_import (const char *func_name, const char *mod_name,
+                            int ordinal, const char *proc_name)
+{
+  char tmp1[256], tmp2[257], tmp3[1024];
+  int sym_mcount, sym_entry, sym_import;
+  dword fixup_mcount, fixup_import;
+
+  aout_init ();
+  sprintf (tmp2, "_%s", func_name);
+  if (profile_flag && strncmp (func_name, "_16_", 4) != 0)
+    {
+      sym_entry = aout_sym (tmp2, N_TEXT|N_EXT, 0, 0, aout_text_size);
+      sym_mcount = aout_sym ("__mcount", N_EXT, 0, 0, 0);
+
+      /* Use, say, "_$U_DosRead" for "DosRead" to import the
+         non-profiled function. */
+      sprintf (tmp2, "__$U_%s", func_name);
+      sym_import = aout_sym (tmp2, N_EXT, 0, 0, 0);
+
+      aout_text_byte (0x55);    /* push ebp */
+      aout_text_byte (0x89);    /* mov ebp, esp */
+      aout_text_byte (0xe5);
+      aout_text_byte (0xe8);    /* call _mcount*/
+      fixup_mcount = aout_text_size;
+      aout_text_dword (0 - (aout_text_size + 4));
+      aout_text_byte (0x5d);    /* pop ebp */
+      aout_text_byte (0xe9);    /* jmp _$U_DosRead*/
+      fixup_import = aout_text_size;
+      aout_text_dword (0 - (aout_text_size + 4));
+
+      aout_treloc (fixup_mcount, sym_mcount, 1, 2, 1);
+      aout_treloc (fixup_import, sym_import, 1, 2, 1);
+    }
+  sprintf (tmp1, "IMPORT#%ld", seq_no);
+  if (proc_name == NULL)
+    sprintf (tmp3, "%s=%s.%d", tmp2, mod_name, ordinal);
+  else
+    sprintf (tmp3, "%s=%s.%s", tmp2, mod_name, proc_name);
+  aout_sym (tmp2, N_IMP1|N_EXT, 0, 0, 0);
+  aout_sym (tmp3, N_IMP2|N_EXT, 0, 0, 0);
+  aout_finish ();
+  write_ar (tmp1, aout_size);
+  aout_write ();
+  finish_ar ();
+  seq_no++;
+  if (ferror (out_file))
+    write_error (out_fname);
+}
+
+
+static void read_lib (const char *fname)
+{
+  FILE *inp_file;
+  int n, i, next, more, impure_warned, ord_flag;
+  unsigned char *buf;
+#pragma pack(1)
+  struct record
+    {
+      unsigned char type;
+      unsigned short length;
+    } record, *rec_ptr;
+#pragma pack()
+  unsigned char func_name[256];
+  unsigned char mod_name[256];
+  unsigned char proc_name[256];
+  unsigned char theadr_name[256];
+  int ordinal;
+  long pos, size;
+  int page_size;
+
+  if (mode == M_LIB_TO_IMP)
+    fprintf (out_file, "; -------- %s --------\n", fname);
+  if (ferror (out_file))
+    write_error (out_fname);
+  inp_file = fopen (fname, "rb");
+  if (inp_file == NULL)
+    error ("Cannot open input file `%s'", fname);
+  if (fread (&record, sizeof (record), 1, inp_file) != 1)
+    goto read_error;
+  if (record.type != LIBHDR || record.length < 5)
+    error ("`%s' is not a library file", fname);
+  page_size = record.length + 3;
+  if (fread (&pos, sizeof (pos), 1, inp_file) != 1)
+    goto read_error;
+  if (fseek (inp_file, 0L, SEEK_END) != 0)
+    goto read_error;
+  size = ftell (inp_file);
+  if (pos < size)
+    size = pos;
+  buf = xmalloc (size);
+  if (fseek (inp_file, 0L, SEEK_SET) != 0)
+    goto read_error;
+  size = fread (buf, 1, size, inp_file);
+  if (size == 0 || ferror (inp_file))
+    goto read_error;
+  i = 0; more = TRUE; impure_warned = FALSE; theadr_name[0] = 0;
+  while (more)
+    {
+      rec_ptr = (struct record *)(buf + i);
+      i += sizeof (struct record);
+      if (i > size) goto bad;
+      next = i + rec_ptr->length;
+      if (next > size) goto bad;
+      switch (rec_ptr->type)
+        {
+        case MODEND:
+        case MODEND|REC32:
+          if ((next & (page_size-1)) != 0)
+            next = (next | (page_size-1)) + 1;
+          break;
+
+        case THEADR:
+          n = buf[i++];
+          if (i + n > next) goto bad;
+          memcpy (theadr_name, buf+i, n);
+          theadr_name[n] = 0;
+          impure_warned = FALSE;
+          break;
+
+        case COMENT:
+          if (record.length >= 11 && buf[i+0] == 0x00 && buf[i+1] == 0xa0 &&
+              buf[i+2] == 0x01)
+            {
+              ord_flag = buf[i+3];
+              i += 4;
+              if (i + 1 > next) goto bad;
+              n = buf[i++];
+              if (i + n > next) goto bad;
+              memcpy (func_name, buf+i, n);
+              func_name[n] = 0;
+              i += n;
+              if (i + 1 > next) goto bad;
+              n = buf[i++];
+              if (i + n > next) goto bad;
+              memcpy (mod_name, buf+i, n);
+              mod_name[n] = 0;
+              i += n;
+
+              if (ord_flag == 0)
+                {
+                  ordinal = -1;
+                  if (i + 1 > next) goto bad;
+                  n = buf[i++];
+                  if (i + n > next) goto bad;
+                  if (n == 0)
+                    strcpy (proc_name, func_name);
+                  else
+                    {
+                      memcpy (proc_name, buf+i, n);
+                      proc_name[n] = 0;
+                      i += n;
+                    }
+                }
+              else
+                {
+                  if (i + 2 > next) goto bad;
+                  ordinal = *(unsigned short *)(buf + i);
+                  i += 2;
+                  proc_name[0] = 0;
+                }
+              ++i;              /* Skip checksum */
+              if (i != next) goto bad;
+              switch (mode)
+                {
+                case M_LIB_TO_IMP:
+                  if (ordinal != -1)
+                    sprintf (proc_name, "%3d", ordinal);
+                  if (strncmp (func_name, "_16_", 4) != 0)
+                    fprintf (out_file, "%-23s %-8s %s ?\n",
+                             func_name, mod_name, proc_name);
+                  else
+                    fprintf (out_file, "%-23s %-8s %s F\n",
+                             func_name+4, mod_name, proc_name);
+                  if (ferror (out_file))
+                    write_error (out_fname);
+                  break;
+                case M_LIB_TO_A:
+                  if (ordinal == -1)
+                    write_a_import (func_name, mod_name, ordinal, proc_name);
+                  else
+                    write_a_import (func_name, mod_name, ordinal, NULL);
+                  break;
+                default:
+                  abort ();
+                }
+            }
+          break;
+
+        case EXTDEF:
+        case PUBDEF:
+        case PUBDEF|REC32:
+        case SEGDEF:
+        case SEGDEF|REC32:
+        case COMDEF:
+        case COMDAT:
+        case COMDAT|REC32:
+          if (!opt_q && !impure_warned)
+            {
+              impure_warned = TRUE;
+              information ("%s (%s) is not a pure import library",
+                           fname, theadr_name);
+            }
+          break;
+
+        case LIBEND:
+          more = FALSE;
+          break;
+        }
+      i = next;
+    }
+  free (buf);
+  fclose (inp_file);
+  return;
+
+read_error:
+  error ("Read error on file `%s'", fname);
+
+bad:
+  error ("Malformed import library file `%s'", fname);
+}
+
+
+static void create_output_file (int bin)
+{
+  out_file = fopen (out_fname, (bin ? "wb" : "wt"));
+  if (out_file == NULL)
+    error ("Cannot open output file `%s'", out_fname);
+  if (!bin)
+    fprintf (out_file, ";\n; %s (created by emximp)\n;\n", out_fname);
+}
+
+
+static void close_output_file (void)
+{
+  if (fflush (out_file) != 0)
+    error ("Write error on output file `%s'", out_fname);
+  if (fclose (out_file) != 0)
+      error ("Cannot close output file `%s'", out_fname);
+}
+
+
+static void init_archive (void)
+{
+  static char ar_magic[SARMAG+1] = ARMAG;
+
+  fwrite (ar_magic, 1, SARMAG, out_file);
+}
+
+
+static int md_export (struct _md *md, const _md_stmt *stmt, _md_token token,
+                      void *arg)
+{
+  const char *internal;
+
+  switch (token)
+    {
+    case _MD_LIBRARY:
+      module_name = xstrdup (stmt->library.name);
+      break;
+    case _MD_EXPORTS:
+      if (module_name == NULL)
+        error ("No module name given in module definition file");
+      if (stmt->export.internalname[0] != 0)
+        internal = stmt->export.internalname;
+      else
+        internal = stmt->export.entryname;
+      switch (mode)
+        {
+        case M_DEF_TO_IMP:
+          if (stmt->export.flags & _MDEP_ORDINAL)
+            fprintf (out_file, "%-23s %-8s %3u ?\n",
+                     stmt->export.entryname, module_name,
+                     (unsigned)stmt->export.ordinal);
+          else
+            fprintf (out_file, "%-23s %-8s %-23s ?\n",
+                     stmt->export.entryname, module_name, internal);
+          if (ferror (out_file))
+            write_error (out_fname);
+          break;
+        case M_DEF_TO_A:
+          if (stmt->export.flags & _MDEP_ORDINAL)
+            write_a_import (stmt->export.entryname, module_name,
+                            stmt->export.ordinal, NULL);
+          else
+            write_a_import (stmt->export.entryname, module_name,
+                            0, internal);
+          break;
+        case M_DEF_TO_LIB:
+          write_lib_import (stmt->export.entryname, module_name,
+                            stmt->export.ordinal, internal);
+          break;
+        default:
+          abort ();
+        }
+      break;
+    case _MD_parseerror:
+      error ("%s (line %ld of %s)", _md_errmsg (stmt->error.code),
+             _md_get_linenumber (md), (const char *)arg);
+      break;
+    default:
+      break;
+    }
+  return 0;
+}
+
+
+static void read_def (const char *fname)
+{
+  struct _md *md;
+
+  module_name = NULL;
+  md = _md_open (fname);
+  if (md == NULL)
+    error ("Cannot open input file `%s'", fname);
+  if (mode == M_DEF_TO_IMP)
+    {
+      fprintf (out_file, "; -------- %s --------\n", fname);
+      if (ferror (out_file))
+        write_error (out_fname);
+    }
+  _md_next_token (md);
+  _md_parse (md, md_export, (void *)fname);
+  _md_close (md);
+}
+
+
+int main (int argc, char *argv[])
+{
+  int i, c;
+  int imp_count, lib_count, def_count, page_size;
+  struct predef *pp1;
+  char *q, *ext, *opt_o;
+  
+  _response (&argc, &argv);
+  predefs = NULL; out_base = NULL; as_name = NULL; pipe_flag = FALSE;
+  profile_flag = FALSE; page_size = 16;
+  opt_b = FALSE; opt_q = FALSE; opt_s = FALSE; base_len = 0; opt_o = NULL;
+  opterr = 0;
+  optswchar = "-";
+  optind = 0;
+  while ((c = getopt (argc, argv, "a::b:mo:p:qsP:")) != EOF)
+    {
+      switch (c)
+        {
+        case 'a':
+          as_name = (optarg != NULL ? optarg : "as");
+          pipe_flag = (_osmode != DOS_MODE);
+          break;
+        case 'b':
+          opt_b = TRUE;
+          base_len = strtol (optarg, &q, 10);
+          if (base_len > 1 && *q == 0)
+            out_base = NULL;
+          else
+            {
+              out_base = optarg;
+              base_len = 0;
+            }
+          break;
+        case 'm':
+          profile_flag = TRUE;
+          break;
+        case 'o':
+          if (opt_o != NULL)
+            usage ();
+          opt_o = optarg;
+          break;
+        case 'p':
+          pp1 = xmalloc (sizeof (struct predef));
+          pp1->name = xstrdup (optarg);
+          pp1->next = predefs;
+          predefs = pp1;
+          break;
+        case 'q':
+          opt_q = TRUE;
+          break;
+        case 's':
+          opt_s = TRUE;
+          break;
+        default:
+          error ("Invalid option");
+        }
+    }
+  imp_count = 0; lib_count = 0; def_count = 0;
+  for (i = optind; i < argc; ++i)
+    {
+      ext = _getext (argv[i]);
+      if (ext != NULL && stricmp (ext, ".lib") == 0)
+        ++lib_count;
+      else if (ext != NULL && stricmp (ext, ".imp") == 0)
+        ++imp_count;
+      else if (ext != NULL && stricmp (ext, ".def") == 0)
+        ++def_count;
+      else
+        error ("Input file `%s' has unknown file name extension", argv[i]);
+    }
+  if (imp_count == 0 && lib_count == 0 && def_count == 0)
+    usage ();
+  if ((imp_count != 0) + (lib_count != 0) + (def_count != 0) > 1)
+    error ("More than one type of input files");
+  if (opt_o == NULL)
+    {
+      if (lib_count != 0)
+        error ("Cannot convert .lib files to %s files",
+               (as_name == NULL ? ".s" : ".o"));
+      if (def_count != 0)
+        error ("Cannot convert .def files to %s files",
+               (as_name == NULL ? ".s" : ".o"));
+      mode = M_IMP_TO_S;
+    }
+  else
+    {
+      ext = _getext (opt_o);
+      if (ext != NULL && stricmp (ext, ".imp") == 0)
+        {
+          if (imp_count != 0)
+            error ("Cannot convert .imp files to .imp file");
+          if (lib_count != 0)
+            mode = M_LIB_TO_IMP;
+          else
+            mode = M_DEF_TO_IMP;
+        }
+      else if (ext != NULL && stricmp (ext, ".a") == 0)
+        {
+          if (def_count != 0)
+            mode = M_DEF_TO_A;
+          else if (imp_count != 0)
+            mode = M_IMP_TO_A;
+          else
+            mode = M_LIB_TO_A;
+        }
+      else if (ext != NULL && stricmp (ext, ".def") == 0)
+        {
+          if (def_count != 0)
+            error ("Cannot convert .def files to .def file");
+          if (lib_count != 0)
+            error ("Cannot convert .lib files to .def file");
+          mode = M_IMP_TO_DEF;
+        }
+      else if (ext != NULL && stricmp (ext, ".lib") == 0)
+        {
+          if (lib_count != 0)
+            error ("Cannot convert .lib files to .lib file");
+          if (def_count != 0)
+            mode = M_DEF_TO_LIB;
+          else
+            mode = M_IMP_TO_LIB;
+          if (predefs != NULL)
+            {
+              if (predefs->next != NULL)
+                usage ();
+              page_size = strtol (predefs->name, &q, 10);
+              if (page_size < 1 || *q != 0)
+                usage ();
+              predefs = NULL;   /* See below */
+            }
+        }
+      else
+        error ("File name extension of output file not supported");
+      _strncpy (out_fname, opt_o, sizeof (out_fname));
+    }
+  if (mode != M_IMP_TO_S)
+    if (as_name != NULL || opt_b || opt_s || predefs != NULL)
+      usage ();
+  if (profile_flag && mode != M_DEF_TO_A && mode != M_IMP_TO_A
+      && mode != M_LIB_TO_A)
+    usage ();
+  switch (mode)
+    {
+    case M_LIB_TO_IMP:
+      create_output_file (FALSE);
+      for (i = optind; i < argc; ++i)
+        read_lib (argv[i]);
+      close_output_file ();
+      break;
+    case M_LIB_TO_A:
+      create_output_file (TRUE);
+      init_archive ();
+      for (i = optind; i < argc; ++i)
+        read_lib (argv[i]);
+      close_output_file ();
+      break;
+    case M_IMP_TO_S:
+      for (i = optind; i < argc; ++i)
+        read_imp (argv[i]);
+      break;
+    case M_IMP_TO_DEF:
+      create_output_file (FALSE);
+      for (i = optind; i < argc; ++i)
+        read_imp (argv[i]);
+      close_output_file ();
+      break;
+    case M_IMP_TO_LIB:
+      out_lib = omflib_create (out_fname, page_size, lib_errmsg);
+      if (out_lib == NULL)
+        lib_error ();
+      if (omflib_header (out_lib, lib_errmsg) != 0)
+        lib_error ();
+      for (i = optind; i < argc; ++i)
+        read_imp (argv[i]);
+      if (omflib_finish (out_lib, lib_errmsg) != 0
+          || omflib_close (out_lib, lib_errmsg) != 0)
+        lib_error ();
+      break;
+    case M_IMP_TO_A:
+      create_output_file (TRUE);
+      init_archive ();
+      for (i = optind; i < argc; ++i)
+        read_imp (argv[i]);
+      close_output_file ();
+      break;
+    case M_DEF_TO_A:
+      create_output_file (TRUE);
+      init_archive ();
+      for (i = optind; i < argc; ++i)
+        read_def (argv[i]);
+      close_output_file ();
+      break;
+    case M_DEF_TO_IMP:
+      create_output_file (FALSE);
+      for (i = optind; i < argc; ++i)
+        read_def (argv[i]);
+      close_output_file ();
+      break;
+    case M_DEF_TO_LIB:
+      out_lib = omflib_create (out_fname, page_size, lib_errmsg);
+      if (out_lib == NULL)
+        lib_error ();
+      if (omflib_header (out_lib, lib_errmsg) != 0)
+        lib_error ();
+      for (i = optind; i < argc; ++i)
+        read_def (argv[i]);
+      if (omflib_finish (out_lib, lib_errmsg) != 0
+          || omflib_close (out_lib, lib_errmsg) != 0)
+        lib_error ();
+      break;
+    default:
+      usage ();
+    }
+  return (warnings == 0 ? 0 : 1);
+}
Index: trunk/src/emx/src/emximp/makefile
===================================================================
--- trunk/src/emx/src/emximp/makefile	(revision 18)
+++ trunk/src/emx/src/emximp/makefile	(revision 18)
@@ -0,0 +1,57 @@
+#
+# /emx/src/emximp/makefile
+#
+# Copyright (c) 1992-1998 by Eberhard Mattes
+#
+# This file is part of emximp.
+#
+# emximp is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emximp is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emximp; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+.SUFFIXES: .c .o
+
+BIN=d:\emx\bin\ #
+INC=..\include\ #
+L=d:/emx/lib/
+I=d:/emx/include/
+S=$(I)sys/
+
+OMFLIB=$(L)omflib.a
+MODDEF=$(L)moddef.a
+
+CC=gcc
+CFLAGS=-O -Wall -I../include
+LFLAGS=-s -Zsmall-conv
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+default:	all
+all:		emximp
+emximp:		$(BIN)emximp.exe
+
+emximp.o: emximp.c $(INC)defs.h $(S)omflib.h $(S)moddef.h
+
+$(BIN)emximp.exe: emximp.o $(OMFLIB) $(MODDEF)
+	gcc $(LFLAGS) -o $(BIN)emximp.exe emximp.o -lomflib -lmoddef
+
+clean:
+	-del *.o
+
+realclean: clean
+	-del $(BIN)emximp.exe
+
+# End of /emx/src/emximp/makefile
Index: trunk/src/emx/src/emxload/COPYING
===================================================================
--- trunk/src/emx/src/emxload/COPYING	(revision 18)
+++ trunk/src/emx/src/emxload/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxload/emxload.c
===================================================================
--- trunk/src/emx/src/emxload/emxload.c	(revision 18)
+++ trunk/src/emx/src/emxload/emxload.c	(revision 18)
@@ -0,0 +1,801 @@
+/* emxload.c -- Keep OS/2 programs in memory
+  Copyright (c) 1993-1998 Eberhard Mattes
+
+This file is part of emxload.
+
+emxload is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxload is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxload; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/emxload.h>
+#include <emx/emxload.h>
+#define INCL_DOSPROCESS
+#define INCL_DOSNMPIPES
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSDEVICES
+#define INCL_DOSMISC
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#define VERSION "0.9d"
+
+/* ------------------------------ SERVER ------------------------------ */
+
+/* This is the maximum number of processes that can be managed by the
+   emxload server. */
+
+#define MAX_PROCS 256
+
+/* A process table entry.  PID is the process ID, STOP is the time at
+   which the program will be unloaded (0 means never unload), NAME is
+   the path name of the executable.  If NAME is NULL, the slot is
+   empty. */
+
+typedef struct
+{
+  int pid;
+  time_t stop;
+  char *name;
+} proc;
+
+/* The name of the pipe. */
+static char const pipe_name[] = _EMXLOAD_PIPENAME;
+
+/* The table of the processes. */
+static proc table[MAX_PROCS];
+
+/* This many entries of the process table are initialized. */
+static int procs = 0;
+
+/* Mutex semaphore for protecting the process table. */
+static HMTX hmtxTable;
+
+/* This event semaphore is posted when the process table has been
+   changed. */
+static HEV hevReady;
+
+/* The server pipe handle. */
+static HPIPE hp;
+
+/* These variables are used for debugging.  Use `-debug FNAME' instead
+   of `-server' on the command line to start the server manually in
+   debug mode.  You can also use the `EMXLOAD_DEBUG_FILE' environment
+   variable to set the file name.  In that case, debugging output will
+   also be enabled for `-server'.  If `debug_file' is non-NULL, the
+   server will print informational messages and error message to
+   FNAME.  Usually, the server is started detached and doesn't display
+   anything. */
+static char *debug_fname = NULL;
+static FILE *debug_file = NULL;
+
+/* Prototypes. */
+
+static void s_unload_all (void);
+static void debug (const char *fmt, ...)
+#ifdef __GNUC__
+    __attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+  ;
+
+/* Debugging output.  This function is called like printf(). */
+
+static void debug (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  if (debug_file == NULL)
+    return;
+  va_start (arg_ptr, fmt);
+  vfprintf (debug_file, fmt, arg_ptr);
+  va_end (arg_ptr);
+  fflush (debug_file);
+}
+
+
+/* Load the program NAME into memory and create a process table entry.
+   The program will be unloaded at the time indicated by STOP.  If
+   STOP is 0, the program won't be unloaded automatically.  This
+   function is called only while the process table is locked. */
+
+static void s_load (const char *name, time_t stop)
+{
+  int i;
+  RESULTCODES result;
+  uDB_t dbgbuf;
+  CHAR objbuf[16];
+  PCHAR args;
+  size_t len;
+  APIRET rc;
+
+  /* Find an unused slot in the process table. */
+
+  for (i = 0; i < procs; ++i)
+    if (table[i].name == NULL)
+      break;
+  if (i >= procs)
+    {
+      if (procs >= MAX_PROCS)
+        {
+          debug ("Too many programs\n");
+          return;
+        }
+      i = procs++;
+      table[i].pid = -1;
+      table[i].name = NULL;
+      table[i].stop = 0;
+    }
+
+  /* Build the command line. */
+
+  len = strlen (name);
+  args = alloca (len + 3);
+  memcpy (args, name, len);
+  args[len+0] = 0;
+  args[len+1] = 0;
+  args[len+2] = 0;
+
+  /* Load the program without running it.  Originally, we used
+     EXEC_LOAD, but emxload lost its children under certain
+     circumstances, perhaps due to a bug in the OS/2 kernel. */
+
+  rc = DosExecPgm (objbuf, sizeof (objbuf), EXEC_TRACE, args, NULL,
+                   &result, name);
+  if (rc == 0)
+    {
+      /* Now connect to the debuggee.  If we didn't do this, the child
+         process would be killed by OS/2 after 10 minutes. */
+
+      memset (&dbgbuf, 0, sizeof (dbgbuf));
+      dbgbuf.Addr = 0;          /* Sever connection to avoid deadlock */
+      dbgbuf.Pid = result.codeTerminate;
+      dbgbuf.Tid = 0;           /* Reserved */
+      dbgbuf.Cmd = DBG_C_Connect; /* Connect */
+      dbgbuf.Value = DBG_L_386; /* Level */
+      rc = DosDebug (&dbgbuf);
+      if (rc == 0 && dbgbuf.Cmd == DBG_N_Success)
+        {
+          /* Fill-in the process table entry. */
+
+          table[i].stop = stop;
+          table[i].name = strdup (name);
+          if (table[i].name == NULL)
+            {
+              debug ("Out of memory\n");
+              s_unload_all ();
+              exit (2);
+            }
+          table[i].pid = result.codeTerminate;
+
+          /* Notify the other thread. */
+
+          DosPostEventSem (hevReady);
+        }
+      else
+        debug ("Cannot connect to %s, rc=%lu\n", name, rc);
+    }
+  else
+    debug ("Cannot load %s, rc=%lu\n", name, rc);
+}
+
+
+/* Unload the program in process table entry I.  The process table
+   entry may be unused, see unload_all().  After calling unload(), the
+   process table entry will be marked unused. */
+
+static void s_unload (int i)
+{
+  uDB_t dbgbuf;
+
+  if (table[i].name != NULL)
+    {
+      memset (&dbgbuf, 0, sizeof (dbgbuf));
+      dbgbuf.Pid = table[i].pid;
+      dbgbuf.Cmd = DBG_C_Term;
+      if (DosDebug (&dbgbuf) != 0)
+        debug ("Cannot unload %s\n", table[i].name);
+      free (table[i].name);
+      table[i].name = NULL;
+      table[i].pid = -1;
+    }
+}
+
+
+/* Unload all programs. */
+
+static void s_unload_all (void)
+{
+  int i;
+
+  for (i = 0; i < procs; ++i)
+    s_unload (i);
+}
+
+
+/* Automatically unload programs.  This function never returns. */
+
+static void auto_unload (void)
+{
+  int i, next_set, more;
+  ULONG timeout, post_count, rc;
+  time_t now, next;
+
+  for (;;)
+    {
+
+      /* Request exclusive access to the process table. */
+
+      DosRequestMutexSem (hmtxTable, SEM_INDEFINITE_WAIT);
+      do
+        {
+
+          /* Scan the table, unloading programs which have expired.
+             Compute the time to sleep until the next program will
+             expire.  To improve accuracy of the timing, we repeat
+             this loop until no program has been unloaded. */
+
+          time (&now);
+          next = 0; next_set = FALSE; more = FALSE;
+          for (i = 0; i < procs; ++i)
+            if (table[i].name != NULL && table[i].stop != 0)
+              {
+                if (now >= table[i].stop)
+                  {
+                    debug ("Unloading %s\n", table[i].name);
+                    s_unload (i);
+                    more = TRUE;
+                  }
+                else if (!next_set)
+                  {
+                    next = table[i].stop;
+                    next_set = TRUE;
+                  }
+                else if (table[i].stop < next)
+                  next = table[i].stop;
+              }
+        } while (more);
+      DosReleaseMutexSem (hmtxTable);
+
+      if (next_set)
+        debug ("Waiting for %u seconds\n", (unsigned)(next - now));
+      else
+        debug ("Waiting forever\n");
+
+      /* Wait until next program expires or until a thread changes the
+         process table. */
+
+      timeout = (next_set ? (next - now) * 1000 : SEM_INDEFINITE_WAIT);
+      rc = DosWaitEventSem (hevReady, timeout);
+      rc = DosResetEventSem (hevReady, &post_count);
+    }
+}
+
+
+/* Send answer to client.  Return 0 on success, -1 on failure. */
+
+static int s_answer (const answer *ans)
+{
+  ULONG rc, cb;
+
+  rc = DosWrite (hp, ans, sizeof (answer), &cb);
+  return (rc == 0 ? 0 : -1);
+}
+
+
+/* Send acknowledge to client. */
+
+static void s_ack (void)
+{
+  answer ans;
+
+  ans.ans_code = 0;
+  s_answer (&ans);
+}
+
+
+/* Load or unload a program.  This function is called by the thread
+   which reads the pipe. */
+
+static void s_load_unload (const request *req)
+{
+  int i;
+  time_t now, stop;
+  
+  stop = 0;
+
+  /* Compute the time when the program will be unloaded. */
+
+  if (req->req_code == _EMXLOAD_LOAD && req->seconds != _EMXLOAD_INDEFINITE)
+    {
+      time (&now);
+      stop = now + req->seconds;
+    }
+
+  /* Request exclusive access to the process table. */
+
+  DosRequestMutexSem (hmtxTable, SEM_INDEFINITE_WAIT);
+
+  /* Scan table for a matching entry.  If the program is already in
+     the table, update the time-out or unload the program. */
+
+  for (i = 0; i < procs; ++i)
+    if (table[i].name != NULL && _fncmp (table[i].name, req->name) == 0)
+      {
+        if (req->req_code != _EMXLOAD_LOAD)
+          s_unload (i);
+        else
+          {
+            table[i].stop = stop;
+            DosPostEventSem (hevReady);
+          }
+        break;
+      }
+
+  /* Load the program if the program is not in the table. */
+
+  if (req->req_code == _EMXLOAD_LOAD && i >= procs)
+    s_load (req->name, stop);
+  if (req->req_code == _EMXLOAD_UNLOAD_WAIT)
+    s_ack ();
+  DosReleaseMutexSem (hmtxTable);
+}
+
+
+/* Send a list of preloaded programs to the client. */
+
+static void s_list (void)
+{
+  int i;
+  time_t now;
+  answer ans;
+
+  /* Request exclusive access to the process table. */
+
+  DosRequestMutexSem (hmtxTable, SEM_INDEFINITE_WAIT);
+
+  /* Get the current time. */
+
+  time (&now);
+
+  /* List all the process table entries. */
+
+  for (i = 0; i < procs; ++i)
+    if (table[i].name != NULL)
+      {
+        if (table[i].stop == 0)
+          ans.seconds = _EMXLOAD_INDEFINITE;
+        else
+          {
+            ans.seconds = table[i].stop - now;
+            if (ans.seconds < 0)
+              ans.seconds = 0;
+          }
+        _strncpy (ans.name, table[i].name, sizeof (ans.name));
+        ans.ans_code = 0;
+        if (s_answer (&ans) != 0)
+          break;
+      }
+
+  ans.ans_code = 1;
+  s_answer (&ans);
+  DosReleaseMutexSem (hmtxTable);
+}
+
+
+static void read_pipe (void)
+{
+  ULONG rc, len;
+  request req;
+
+  for (;;)
+    {
+      rc = DosRead (hp, &req, sizeof (req), &len);
+      if (rc == ERROR_BROKEN_PIPE)
+        break;
+      if (rc != 0)
+        {
+          debug ("Error code %lu\n", rc);
+          s_unload_all ();
+          exit (2);
+        }
+      if (len == 0)
+        break;
+      if (len != sizeof (request))
+        debug ("Invalid record length: %lu\n", len);
+      else
+        switch (req.req_code)
+          {
+          case _EMXLOAD_LOAD:
+          case _EMXLOAD_UNLOAD:
+          case _EMXLOAD_UNLOAD_WAIT:
+            s_load_unload (&req);
+            break;
+          case _EMXLOAD_STOP:
+          case _EMXLOAD_STOP_WAIT:
+            s_unload_all ();
+            exit (0);
+          case _EMXLOAD_LIST:
+            s_list ();
+            break;
+          default:
+            debug ("Unknown request code: %d\n", req.req_code);
+            break;
+          }
+    }
+}
+
+
+/* Handle connections to the pipe.  This function never returns. */
+
+static void connections (void)
+{
+  ULONG rc;
+
+  for (;;)
+    {
+      rc = DosConnectNPipe (hp);
+      debug ("Connected\n");
+      read_pipe ();
+      rc = DosDisConnectNPipe (hp);
+      debug ("Disconnected\n");
+    }
+}
+
+
+/* This is an additional thread.  It handles connections to the named
+   pipe. */
+
+static void thread (void *arg)
+{
+  connections ();
+}
+
+
+/* This is the main thread of the server. */
+
+static void server (void)
+{
+  ULONG rc;
+
+  /* Set our priority to foreground server.  This decreases the time
+     clients have to wait on a heavily loaded system.  Moreover, we
+     may have inherited idle-time priority from our parent... */
+
+  DosSetPriority (PRTYS_PROCESS, PRTYC_FOREGROUNDSERVER, 0, 0);
+
+  /* Open the debug output file if the `-debug FNAME' option is used
+     or the EMXLOAD_DEBUG_FILE environment variable is set. */
+
+  if (debug_fname == NULL)
+    debug_fname = getenv ("EMXLOAD_DEBUG_FILE");
+  if (debug_fname != NULL)
+    debug_file = fopen (debug_fname, "w");
+
+  /* Close all the file handles as we inherit the file handles of the
+     parent process.  If we didn't close the file handles, the parent
+     couldn't delete, rename etc. the files.  This should be done
+     before creating the pipe to avoid a timing window. */
+
+  {
+    LONG req;
+    ULONG i, cur;
+
+    req = 0; cur = 0;
+    if (DosSetRelMaxFH (&req, &cur) == 0)
+      for (i = 0; i < cur; ++i)
+        if (!(debug_file != NULL && i == fileno (debug_file)))
+          DosClose ((HFILE)i);
+  }
+
+  /* Change to the root directory of all non-removable drivers and of
+     the current drive (in case it's removable).  This is for allowing
+     the user to rename or delete the directories which were the
+     current directories when emxload was started. */
+
+  {
+    ULONG drive, drive_map, parmlen, datalen, rc;
+    CHAR parm[2], data[1];
+    static CHAR dir[] = "A:\\";
+
+    DosError (FERR_DISABLEHARDERR | FERR_ENABLEEXCEPTION);
+    if (DosQueryCurrentDisk (&drive, &drive_map) == 0)
+      {
+        for (drive = 0; drive < 26; ++drive)
+          if (drive_map & (1 << drive))
+            {
+              parm[0] = 0; parm[1] = drive; data[0] = 0;
+              parmlen = 2; datalen = 0;
+              if (DosDevIOCtl ((HFILE)-1, 8, 0x20, parm, 2, &parmlen,
+                               data, 1, &datalen) == 0
+                  && datalen == 1 && data[0] == 1)
+                {
+                  dir[0] = (CHAR)('A' + drive);
+                  rc = DosSetCurrentDir (dir);
+                  debug ("DosSetCurrentDir(%s) -> %lu\n", dir, rc);
+                }
+            }
+      }
+    DosSetCurrentDir ("\\");
+    DosError (FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
+  }
+
+  /* Create the named pipe. */
+
+  rc = DosCreateNPipe (pipe_name, &hp, NP_NOINHERIT|NP_ACCESS_DUPLEX,
+                       NP_WAIT|NP_TYPE_MESSAGE|NP_READMODE_MESSAGE|1,
+                       0x1000, 0x1000, 0);
+  if (rc == ERROR_PIPE_BUSY)
+    {
+      debug ("An emxload server is already running\n");
+      exit (1);
+    }
+  if (rc != 0)
+    {
+      debug ("Error code %lu\n", rc);
+      exit (2);
+    }
+
+  /* Create the semaphores. */
+
+  rc = DosCreateMutexSem (NULL, &hmtxTable, 0, FALSE);
+  rc = DosCreateEventSem (NULL, &hevReady, 0, FALSE);
+
+  /* Start the second thread. */
+
+  if (_beginthread (thread, NULL, 0x8000, NULL) == -1)
+    {
+      debug ("Cannot start thread\n");
+      exit (2);
+    }
+
+  auto_unload ();
+}
+
+
+/* ------------------------------ CLIENT ------------------------------ */
+
+/* This flag is set by the -u and -uw command line options.  All
+   programs given on the command line will be unloaded instead of
+   loaded. */
+static int unload_flag = FALSE;
+
+/* This flag is set by the -uw command line option.  Wait for
+   completion. */
+static int unload_wait = FALSE;
+
+/* The number of seconds to keep the programs in memory.  May be
+   _EMXLOAD_INDEFINITE. */
+static int seconds;
+
+/* Prototypes. */
+
+static void usage (void);
+
+
+/* Handle one request for loading or unloading (client side). */
+
+static void c_load_unload (const char *name)
+{
+  if (unload_flag)
+    {
+      if (_emxload_unload (name, unload_wait) != 0)
+        fprintf (stderr, "emxload: cannot unload %s\n", name);
+    }
+  else
+    {
+      if (_emxload_prog (name, seconds) != 0)
+        fprintf (stderr, "emxload: cannot load %s\n", name);
+    }
+}
+
+
+/* Parse the command line for the client. */
+
+static void client (int argc, char **argv)
+{
+  int i, mul;
+  int load_gcc, load_gpp, load_gobjc, load_gnat, load_omf;
+  char *p, *q;
+
+  /* Set the default values. */
+
+  seconds = 10 * 60;
+  load_gcc = FALSE; load_gpp = FALSE; load_gobjc = FALSE; load_gnat = FALSE;
+  load_omf = FALSE;
+  i = 1;
+
+  /* Parse the options. */
+
+  while (i < argc && argv[i][0] == '-')
+    {
+      p = argv[i++];
+      if (strcmp (p, "-e") == 0)
+        seconds = _EMXLOAD_INDEFINITE;
+      else if (strcmp (p, "-u") == 0)
+        unload_flag = TRUE;
+      else if (strcmp (p, "-uw") == 0)
+        {
+          unload_flag = TRUE;
+          unload_wait = TRUE;
+        }
+      else if (strncmp (p, "-m", 2) == 0 || strncmp (p, "-s", 2) == 0)
+        {
+          mul = (p[1] == 'm' ? 60 : 1);
+          p += 2;
+          if (*p == 0)
+            {
+              if (i >= argc)
+                usage ();
+              p = argv[i++];
+            }
+          errno = 0;
+          seconds = (int)strtol (p, &q, 10);
+          if (seconds < 1 || errno != 0 || q == p || *q != 0)
+            usage ();
+          seconds *= mul;
+        }
+      else if (strcmp (p, "-g++") == 0)
+        load_gpp = TRUE;
+      else if (strcmp (p, "-gcc") == 0)
+        load_gcc = TRUE;
+      else if (strcmp (p, "-gobjc") == 0)
+        load_gobjc = TRUE;
+      else if (strcmp (p, "-gnat") == 0)
+        load_gnat = TRUE;
+      else if (strcmp (p, "-omf") == 0)
+        load_omf = TRUE;
+      else
+        usage ();
+    }
+
+  /* At least program must be given. */
+
+  if (i >= argc && !(load_gcc || load_gpp || load_gobjc || load_gnat
+                     || load_omf))
+    usage ();
+
+  /* Connect to the server and keep the connection open. */
+
+  if (!unload_flag && _emxload_connect () != 0)
+    {
+      fputs ("emxload: cannot start emxload server\n", stderr);
+      exit (2);
+    }
+
+  /* Load or unload the programs. */
+
+  if (load_gcc || load_gpp || load_gobjc || load_gnat)
+    {
+      c_load_unload ("gcc");
+      c_load_unload ("as");
+      c_load_unload ("ld");
+      c_load_unload ("emxbind");
+    }
+  if (load_gcc || load_gpp || load_gobjc)
+    c_load_unload ("cpp");
+  if (load_gcc)
+    c_load_unload ("cc1");
+  if (load_gpp)
+    c_load_unload ("cc1plus");
+  if (load_gobjc)
+    c_load_unload ("cc1obj");
+  if (load_gnat)
+    {
+      c_load_unload ("gnat1");
+      c_load_unload ("gnatbind");
+    }
+  if (load_omf)
+    {
+      c_load_unload ("emxomf");
+      c_load_unload ("emxomfld");
+      c_load_unload ("link386");
+    }
+  while (i < argc)
+    c_load_unload (argv[i++]);
+}
+
+
+/* List preloaded programs (client side). */
+
+static void c_list (void)
+{
+  char name[260], timeout[20], *p;
+  int seconds, header;
+
+  if (_emxload_list_start () != 0)
+    return;
+
+  header = FALSE;
+  while (_emxload_list_get (name, sizeof (name), &seconds) == 0)
+    {
+      if (!header)
+        {
+          puts ("Time-out ³ Program");
+          puts ("ÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
+          header = TRUE;
+        }
+      if (seconds == _EMXLOAD_INDEFINITE)
+        strcpy (timeout, "NONE");
+      else
+        sprintf (timeout, "%d'%.2d", seconds / 60, seconds % 60);
+      for (p = name; *p != 0; ++p)
+        if (*p == '/')
+          *p = '\\';
+      printf ("%8s ³ %s\n", timeout, name);
+    }
+}
+
+/* ------------------------------- MAIN ------------------------------- */
+
+/* How to call this program. */
+
+static void usage (void)
+{
+  fputs ("emxload " VERSION " -- "
+         "Copyright (c) 1993-1996 by Eberhard Mattes\n\n"
+         "Usage: emxload [-m <limit>] [-s <limit>] [-e] [-u[w]]\n"
+         "               [-gcc] [-g++] [-gobjc] [-gnat] [-omf] <program>...\n"
+         "       emxload -l\n"
+         "       emxload -q\n"
+         "       emxload -qw\n\n"
+         "Options:\n\n"
+         "-m <limit>   Unload programs after <limit> minutes (default: 10)\n"
+         "-s <limit>   Unload programs after <limit> seconds (default: 600)\n"
+         "-e           No limit\n"
+         "-u           Unload programs (overrides -m, -s and -e)\n"
+         "-uw          Like -u, but wait until completed\n"
+         "-gcc         Load gcc, cpp, cc1, as, ld, emxbind\n"
+         "-g++         Load gcc, cpp, cc1plus, as, ld, emxbind\n"
+         "-gobjc       Load gcc, cpp, cc1obj, as, ld, emxbind\n"
+         "-gnat        Load gcc, gnat1, as, ld, gnatbind, emxbind\n"
+         "-omf         Load emxomf, emxomfld, link386\n"
+         "-l           List preloaded programs\n"
+         "-q           Stop server\n"
+         "-qw          Like -w, but wait until completed\n", stderr);
+  exit (1);
+}
+
+
+/* Main line. */
+
+int main (int argc, char **argv)
+{
+  if (_osmode == DOS_MODE)
+    {
+      fputs ("There's no point in using this program under DOS\n", stderr);
+      return 1;
+    }
+  if (argc == 2 && strcmp (argv[1], "-server") == 0)
+    server ();
+  else if (argc == 3 && strcmp (argv[1], "-debug") == 0)
+    {
+      debug_fname = argv[2];
+      server ();
+    }
+  else if (argc == 2 && strcmp (argv[1], "-l") == 0)
+    c_list ();
+  else if (argc == 2 && strcmp (argv[1], "-q") == 0)
+    _emxload_stop (FALSE);
+  else if (argc == 2 && strcmp (argv[1], "-qw") == 0)
+    _emxload_stop (TRUE);
+  else
+    client (argc, argv);
+  return 0;
+}
Index: trunk/src/emx/src/emxload/makefile
===================================================================
--- trunk/src/emx/src/emxload/makefile	(revision 18)
+++ trunk/src/emx/src/emxload/makefile	(revision 18)
@@ -0,0 +1,50 @@
+#
+# /emx/src/emxload/makefile
+#
+# Copyright (c) 1993-1998 by Eberhard Mattes
+#
+# This file is part of emxload.
+#
+# emxload is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emxload is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emxload; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+#
+# Note: Unset GCCLOAD and run "emxload -q" before compiling emxload!
+#
+
+BIN=/emx/bin/
+I=d:/emx/include/
+
+CC=gcc
+CFLAGS=-Zomf -Zmt -Zcrtdll -O -Wall -I../include
+
+default:	all
+all:		emxload
+emxload:	$(BIN)emxload.exe
+
+emxload.obj: emxload.c $(I)emx/emxload.h
+	$(CC) $(CFLAGS) -c emxload.c
+
+$(BIN)emxload.exe: emxload.obj
+	-emxload -qw
+	$(CC) $(CFLAGS) -o $(BIN)emxload.exe -s emxload.obj
+
+clean:
+	-rm *.obj
+
+realclean: clean
+	-rm $(BIN)emxload.exe
+
+# End of /emx/src/emxload/makefile
Index: trunk/src/emx/src/emxomf/COPYING
===================================================================
--- trunk/src/emx/src/emxomf/COPYING	(revision 18)
+++ trunk/src/emx/src/emxomf/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxomf/emxaout.c
===================================================================
--- trunk/src/emx/src/emxomf/emxaout.c	(revision 18)
+++ trunk/src/emx/src/emxomf/emxaout.c	(revision 18)
@@ -0,0 +1,1404 @@
+/* emxaout.c -- Convert OS/2-style OMF object files to GNU-style a.out
+                object files
+  Copyright (c) 1994-1998 Eberhard Mattes
+
+This file is part of emxaout.
+
+emxaout is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxaout is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxaout; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/param.h>
+#include <sys/emxload.h>
+#include <ar.h>
+
+#define GROW_DEF_STATIC(NAME,TYPE) \
+  static struct grow NAME##_grow; \
+  static TYPE *NAME
+#define GROW_SETUP(NAME,INCR) \
+  (NAME = NULL, grow_init (&NAME##_grow, &NAME, sizeof (*(NAME)), INCR))
+#define GROW_FREE(NAME) \
+  grow_free (&NAME##_grow)
+#define GROW_COUNT(NAME) \
+  NAME##_grow.count
+#define GROW_ADD(NAME) \
+  (grow_by (&NAME##_grow, 1), NAME##_grow.count++)
+
+/* The version number of this program.  This is printed with the usage
+   message. */
+
+#define VERSION "0.9d"
+
+/* Insert private header files. */
+
+#include "defs.h"               /* Common definitions */
+#include "grow.h"               /* Growing objects */
+
+#define SEG_OTHER       0
+#define SEG_CODE        1
+#define SEG_DATA        2
+#define SEG_BSS         3
+#define SEG_SET         4
+#define SEG_DEBUG       5
+
+struct segment
+{
+  int name;
+  dword size;
+  byte *data;
+  int type;
+};
+
+struct group
+{
+  int name;
+};
+
+struct pubdef
+{
+  char *name;
+  dword offset;
+  int group;
+  int seg;
+  int frame;
+};
+
+struct extdef
+{
+  char *name;
+  int sym;
+  dword size;                   /* Non-zero for COMDEF */
+};
+
+struct symbol
+{
+  char *name;
+  struct nlist n;
+};
+
+struct thread
+{
+  int method;
+  int index;
+};
+
+
+/* Prototypes for public functions. */
+
+void error (const char *fmt, ...) NORETURN2 ATTR_PRINTF (1, 2);
+void error2 (const char *fmt, ...) NORETURN2 ATTR_PRINTF (1, 2);
+void *xmalloc (size_t n);
+void *xrealloc (void *ptr, size_t n);
+char *xstrdup (const char *s);
+
+
+/* The name of the current input file. */
+static const char *inp_fname;
+
+/* The name of the current output file. */
+static const char *out_fname = NULL;
+
+/* The current input file. */
+static FILE *inp_file;
+
+/* The current output file. */
+static FILE *out_file = NULL;
+
+/* Assume that the .obj file contains leading underscores -- don't add
+   extra underscores. */
+static int underscores = FALSE;
+
+static int rec_type;
+static int rec_len;
+static int rec_idx;
+static byte rec_buf[MAX_REC_SIZE+8];
+
+static int group_flat;
+
+static int seg_code;
+static int seg_data;
+static int seg_bss;
+
+static int cur_seg;
+static dword cur_off;
+
+static struct thread frame_threads[4];
+static struct thread target_threads[4];
+
+GROW_DEF_STATIC (lnames, char *);
+GROW_DEF_STATIC (groups, struct group);
+GROW_DEF_STATIC (segments, struct segment);
+GROW_DEF_STATIC (pubdefs, struct pubdef);
+GROW_DEF_STATIC (extdefs, struct extdef);
+GROW_DEF_STATIC (symbols, struct symbol);
+GROW_DEF_STATIC (trelocs, struct reloc);
+GROW_DEF_STATIC (drelocs, struct reloc);
+
+
+/* If there is an output file, close and delete it. */
+
+static void cleanup (void)
+{
+  if (out_file != NULL)
+    {
+      fclose (out_file);
+      remove (out_fname);
+    }
+}
+
+
+/* Display an error message on stderr, delete the output file and
+   quit.  This function is invoked like printf(): FMT is a
+   printf-style format string, all other arguments are formatted
+   according to FMT.  The message should not end with a newline. The
+   exit code is 2. */
+
+void error (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emxaout: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+  cleanup ();
+  exit (2);
+}
+
+
+/* Display an error message for the current input file on stderr,
+   delete the output file and quit.  This function is invoked like
+   printf(): FMT is a printf-style format string, all other arguments
+   are formatted according to FMT.  The message should not end with a
+   newline. The exit code is 2. */
+
+void error2 (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "%s[%ld+%d]: ", inp_fname,
+           ftell (inp_file) - (sizeof (struct omf_rec) + rec_len + 1),
+           rec_idx);
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+  cleanup ();
+  exit (2);
+}
+
+
+/* Allocate N bytes of memory.  Quit on failure.  This function is
+   used like malloc(), but we don't have to check the return value. */
+
+void *xmalloc (size_t n)
+{
+  void *p;
+  
+  p = malloc (n);
+  if (p == NULL && n != 0)
+    error ("Out of memory");
+  return p;
+}
+
+
+/* Change the allocation of PTR to N bytes.  Quit on failure.  This
+   function is used like realloc(), but we don't have to check the
+   return value. */
+
+void *xrealloc (void *ptr, size_t n)
+{
+  void *p;
+  
+  p = realloc (ptr, n);
+  if (p == NULL)
+    error ("Out of memory");
+  return p;
+}
+
+
+/* Create a duplicate of the string S on the heap.  Quit on failure.
+   This function is used like strdup(), but we don't have to check the
+   return value. */
+
+char *xstrdup (const char *s)
+{
+  char *p;
+  
+  p = xmalloc (strlen (s) + 1);
+  strcpy (p, s);
+  return p;
+}
+
+
+/* Display a warning message on stderr (and do not quit).  This
+   function is invoked like printf(): FMT is a printf-style format
+   string, all other arguments are formatted according to FMT. */
+
+void warning (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emxaout warning: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+}
+
+
+/* Display some hints on using this program, then quit. */
+
+static void usage (void)
+{
+  puts ("emxaout " VERSION " -- Copyright (c) 1994-1996 by Eberhard Mattes\n");
+  puts ("Usage:");
+  puts ("  emxaout [-u] [-o <output_file>] <input_file>");
+  puts ("\nOptions:");
+  puts ("  -u                 Don't add leading underscores");
+  puts ("  -o <output_file>   Write output to <output_file>");
+  exit (1);
+}
+
+
+/* Create the output file. */
+
+static void open_output (void)
+{
+  out_file = fopen (out_fname, "wb");
+  if (out_file == NULL)
+    error ("Cannot create output file `%s'", out_fname);
+}
+
+
+/* Close the output file.  Display an error message and quit on
+   failure. */
+
+static void close_output (void)
+{
+  if (fflush (out_file) != 0 || fclose (out_file) != 0)
+    {
+      out_file = NULL;
+      error ("Write error on output file `%s'", out_fname);
+    }
+  out_file = NULL;
+}
+
+
+/* Define or build the name of the output file.  If DST_FNAME is not
+   NULL, use it as name of the output file.  Otherwise, build the name
+   from INP_FNAME (the input file name) and EXT (the extension). */
+
+static void make_out_fname (const char *dst_fname, const char *inp_fname,
+                            const char *ext)
+{
+  static char tmp[MAXPATHLEN+1];
+
+  if (dst_fname == NULL)
+    {
+      if (strlen (inp_fname) + strlen (ext) > MAXPATHLEN)
+        error ("File name `%s' too long", inp_fname);
+      strcpy (tmp, inp_fname);
+      _remext (tmp);
+      strcat (tmp, ext);
+      out_fname = tmp;
+    }
+  else
+    out_fname = dst_fname;
+}
+
+
+static void get_mem (void *dst, int len)
+{
+  if (rec_idx + len > rec_len)
+    error2 ("String beyond end of record");
+  memcpy (dst, rec_buf + rec_idx, len);
+  rec_idx += len;
+}
+
+
+static void get_string (byte *dst)
+{
+  int len;
+
+  if (rec_idx >= rec_len)
+    error2 ("String beyond end of record");
+  len = rec_buf[rec_idx++];
+  get_mem (dst, len);
+  dst[len] = 0;
+}
+
+
+static int get_index (void)
+{
+  int result;
+
+  if (rec_idx >= rec_len)
+    error2 ("Index beyond end of record");
+  result = rec_buf[rec_idx++];
+  if (result & 0x80)
+    {
+      if (rec_idx >= rec_len)
+        error2 ("Index beyond end of record");
+      result = ((result & 0x7f) << 8) | rec_buf[rec_idx++];
+    }
+  return result;
+}
+
+
+static word get_dword (void)
+{
+  dword result;
+
+  if (rec_idx + 4 > rec_len)
+    error2 ("Dword beyond end of record");
+  result = rec_buf[rec_idx++];
+  result |= rec_buf[rec_idx++] << 8;
+  result |= rec_buf[rec_idx++] << 16;
+  result |= rec_buf[rec_idx++] << 24;
+  return result;
+}
+
+
+static word get_word (void)
+{
+  word result;
+
+  if (rec_idx + 2 > rec_len)
+    error2 ("Word beyond end of record");
+  result = rec_buf[rec_idx++];
+  result |= rec_buf[rec_idx++] << 8;
+  return result;
+}
+
+
+static word get_byte (void)
+{
+  if (rec_idx + 1 > rec_len)
+    error2 ("Byte beyond end of record");
+  return rec_buf[rec_idx++];
+}
+
+
+static dword get_word_or_dword (void)
+{
+  return (rec_type & REC32 ? get_dword () : get_word ());
+}
+
+
+static dword get_commlen (void)
+{
+  dword result;
+
+  result = get_byte ();
+  if (result <= 0x80)
+    return result;
+  switch (result)
+    {
+    case 0x81:
+      return get_word ();
+    case 0x84:
+      result = get_byte ();
+      result |= get_byte () << 8;
+      result |= get_byte () << 16;
+      return result;
+    case 0x88:
+      return get_dword ();
+    default:
+      error2 ("Unknown COMDAT length prefix");
+    }
+}
+
+
+static void init_module (void)
+{
+  int i;
+
+  GROW_SETUP (lnames, 8);
+  GROW_SETUP (groups, 8);
+  GROW_SETUP (segments, 8);
+  GROW_SETUP (pubdefs, 16);
+  GROW_SETUP (extdefs, 16);
+  GROW_SETUP (symbols, 16);
+  GROW_SETUP (trelocs, 32);
+  GROW_SETUP (drelocs, 32);
+
+  group_flat = -1;
+  seg_code = -1; seg_data = -1; seg_bss = -1;
+  cur_seg = -1;
+
+  for (i = 0; i < 4; ++i)
+    frame_threads[i].method = target_threads[i].method = -1;
+}
+
+
+static void term_module (void)
+{
+  int i;
+
+  for (i = 0; i < GROW_COUNT (lnames); ++i)
+    free (lnames[i]);
+  GROW_FREE (lnames);
+
+  GROW_FREE (groups);
+
+  for (i = 0; i < GROW_COUNT (segments); ++i)
+    if (segments[i].data != NULL)
+      free (segments[i].data);
+  GROW_FREE (segments);
+
+  for (i = 0; i < GROW_COUNT (pubdefs); ++i)
+    free (pubdefs[i].name);
+  GROW_FREE (pubdefs);
+
+  for (i = 0; i < GROW_COUNT (extdefs); ++i)
+    free (extdefs[i].name);
+  GROW_FREE (extdefs);
+
+  for (i = 0; i < GROW_COUNT (symbols); ++i)
+    if (symbols[i].name != NULL)
+      free (symbols[i].name);
+  GROW_FREE (symbols);
+
+  GROW_FREE (trelocs);
+  GROW_FREE (drelocs);
+}
+
+
+/* Convert an LNAMES record.
+
+   LNAMES record:
+   Ú
+   ³1   String length n
+   ³n   Name
+   À
+
+   Name indices are assigned sequentially. */
+
+static void conv_lnames (void)
+{
+  byte string[256];
+  int i;
+
+  while (rec_idx < rec_len)
+    {
+      get_string (string);
+      i = GROW_ADD (lnames);
+      lnames[i] = xstrdup (string);
+    }
+}
+
+
+/* Convert a GRPDEF record.
+
+   GRPDEF record:
+    1/2 Group name index
+   Ú
+   ³1   0xff (use segment index)
+   ³1/2 Segment index
+   À
+
+   Group indices are assigned sequentially. */
+
+static void conv_grpdef (void)
+{
+  int i, name, type, seg;
+  const char *group_name;
+
+  name = get_index ();
+  i = GROW_ADD (groups);
+  groups[i].name = name;
+
+  if (name < 1 || name > GROW_COUNT (lnames))
+    error2 ("GRPDEF: name index out of range");
+  group_name = lnames[name - 1];
+
+  if (strcmp (group_name, "FLAT") == 0)
+    group_flat = i;
+
+  while (rec_idx < rec_len)
+    {
+      type = get_byte ();
+      if (type != 0xff)
+        error2 ("GRPDEF: unknown type");
+      seg = get_index ();
+    }
+}
+
+
+static int is_set_seg (const char *name)
+{
+  return (name[0] == 'S' && name[1] == 'E' && name[2] == 'T'
+          && (name[3] >= '1' && name[3] <= '3')
+          && name[4] == '_' && name[5] == '_' && name[6] == '_'
+          && (name[7] == 'C' || name[7] == 'D')
+          && strcmp (name+8, "TOR_LIST__") == 0);
+}
+
+
+/* Convert a SEGDEF record.
+
+   SEGDEF record:
+    1   Segment attributes
+    0/2 Frame number (present only if A=000)
+    0/1 Offset (present only if A=000)
+    2/4 Segment length (4 bytes for 32-bit SEGDEF record)
+    1/2 Segment name index
+    1/2 Segment class index
+    1/2 Overlay name index
+
+    The segment attributes byte contains the following fields:
+
+    A (bits 5-7)        Alignment (101=relocatable, 32-bit alignment)
+    C (bits 2-4)        Combination (010=PUBLIC, 101=STACK)
+    B (bit 1)           Big (segment length is 64KB)
+    P (bit 0)           USE32 */
+
+static void conv_segdef (void)
+{
+  int i, type;
+  int attributes, alignment, combination, frame, offset, name, class, overlay;
+  dword length;
+  const char *seg_name, *class_name;
+
+  attributes = get_byte ();
+  alignment = attributes >> 5;
+  combination = (attributes >> 2) & 7;
+  if (alignment == 0)
+    {
+      frame = get_word ();
+      offset = get_byte ();
+    }
+  length = get_word_or_dword ();
+  name = get_index ();
+  class = get_index ();
+  overlay = get_index ();
+  if (!(rec_type & REC32) && (attributes & 2))
+    length = 1L << 16;
+
+  if (class < 1 || class > GROW_COUNT (lnames))
+    error2 ("SEGDEF: class index out of range");
+  class_name = lnames[class - 1];
+
+  if (name < 1 || name > GROW_COUNT (lnames))
+    error2 ("SEGDEF: name index out of range");
+  seg_name = lnames[name - 1];
+
+  type = SEG_OTHER;
+  if (strcmp (class_name, "CODE") == 0)
+    {
+      if (is_set_seg (seg_name))
+        type = SEG_SET;
+      else
+        type = SEG_CODE;
+    }
+  else if (strcmp (class_name, "DATA") == 0)
+    type = SEG_DATA;
+  else if (strcmp (class_name, "BSS") == 0)
+    type = SEG_BSS;
+  else if (strcmp (class_name, "DEBSYM") == 0)
+    type = SEG_DEBUG;
+  else if (strcmp (class_name, "DEBTYP") == 0)
+    type = SEG_DEBUG;
+
+  if (type != SEG_OTHER)
+    for (i = 0; i < GROW_COUNT (segments); ++i)
+      if (segments[i].type == type)
+        switch (type)
+          {
+          case SEG_CODE:
+            error2 ("Multiple code segments");
+          case SEG_DATA:
+            error2 ("Multiple data segments");
+          case SEG_BSS:
+            error2 ("Multiple bss segments");
+          case SEG_SET:
+          case SEG_DEBUG:
+            break;
+          }
+  i = GROW_ADD (segments);
+  segments[i].name = name;
+  segments[i].size = length;
+  segments[i].data = xmalloc (length);
+  segments[i].type = type;
+  memset (segments[i].data, 0, length);
+  switch (type)
+    {
+    case SEG_CODE:
+      seg_code = i;
+      break;
+    case SEG_DATA:
+      seg_data = i;
+      break;
+    case SEG_BSS:
+      seg_bss = i;
+      break;
+    }
+}
+
+
+/* Convert a PUBDEF record.
+
+   PUBDEF record:
+    1-2 Base group
+    1-2 Base segment
+    0/2 Base frame
+   Ú
+   ³1   String length n
+   ³n   Public name
+   ³2/4 Public offset (4 bytes for 32-bit PUBDEF record)
+   ³1-2 Type index
+   À
+
+   The base frame field is present only if the base segment field is
+   0. */
+
+static void conv_pubdef (void)
+{
+  int i, type, group, seg, frame;
+  dword offset;
+  byte name[1+256];
+
+  group = get_index ();
+  seg = get_index ();
+  if (seg == 0)
+    frame = get_word ();
+  else
+    frame = 0;
+
+  while (rec_idx < rec_len)
+    {
+      name[0] = '_';
+      get_string (name+1);
+      offset = get_word_or_dword ();
+      type = get_index ();
+      i = GROW_ADD (pubdefs);
+      pubdefs[i].name   = xstrdup (underscores ? name + 1 : name);
+      pubdefs[i].group  = group;
+      pubdefs[i].seg    = seg;
+      pubdefs[i].frame  = frame;
+      pubdefs[i].offset = offset;
+    }
+}
+
+
+/* Convert an EXTDEF record.
+
+   EXTDEF record:
+   Ú
+   ³1   String length n
+   ³n   External name
+   ³1-2 Type index
+   À 
+
+   Symbol indices are assigned sequentially by EXTDEF and COMDEF. */
+
+static void conv_extdef (void)
+{
+  int i, type;
+  byte name[1+256];
+
+  while (rec_idx < rec_len)
+    {
+      name[0] = '_';
+      get_string (name+1);
+      type = get_index ();
+      i = GROW_ADD (extdefs);
+      extdefs[i].name = xstrdup (underscores ? name + 1 : name);
+      extdefs[i].sym  = 0;
+      extdefs[i].size = 0;      /* EXTDEF */
+    }
+}
+
+
+/* Convert an COMDEF record.
+
+   COMDEF record:
+   Ú
+   ³1   String length n
+   ³n   Communal name
+   ³1-2 Type index
+   ³1   Data type (0x61: FAR data, 0x62: NEAR data)
+   ³1-5 Communal length
+   À
+
+   The length is encoded in 1 to 5 bytes, depending on the value:
+
+   0 through 0x7f       1 byte, containing the value
+   0 through 0xffff     0x81, followed by 16-bit word
+   0 through 0xffffff   0x84, followed by 24-bit word
+   0 through 0xffffffff 0x88, followed by 32-bit word
+
+   Symbol indices are assigned sequentially by EXTDEF and COMDEF. */
+
+static void conv_comdef (void)
+{
+  int i, type;
+  word data_type;
+  dword comm_count, comm_len;
+  byte name[1+256];
+
+  while (rec_idx < rec_len)
+    {
+      name[0] = '_';
+      get_string (name+1);
+      type = get_index ();
+      data_type = get_byte ();
+      switch (data_type)
+        {
+        case 0x61:
+          comm_count = get_commlen ();
+          comm_len = get_commlen ();
+          break;
+        case 0x62:
+          comm_count = 1;
+          comm_len = get_commlen ();
+          break;
+        default:
+          error2 ("COMDEF: unknown data type");
+        }
+      if (comm_count == 0 || comm_len == 0)
+        error2 ("COMDEF: size is zero");
+      i = GROW_ADD (extdefs);
+      extdefs[i].name = xstrdup (underscores ? name + 1 : name);
+      extdefs[i].sym  = 0;
+      extdefs[i].size = comm_count * comm_len;
+    }
+}
+
+
+/* Convert a LEDATA record.
+
+   LEDATA record:
+    1-2 Segment index
+    2/4 Enumerated data offset (4 bytes for 32-bit LEDATA record)
+    n   Data bytes (n is derived from record length) */
+
+static void conv_ledata (void)
+{
+  int len;
+  dword offset, seg;
+
+  seg = get_index ();
+  offset = get_word_or_dword ();
+  len = rec_len - rec_idx;
+
+  if (seg < 1 || seg > GROW_COUNT (segments))
+    error2 ("LEDATA: segment index out of range");
+
+  cur_seg = -1;
+  if (segments[seg-1].data != NULL)
+    {
+      cur_seg = seg - 1;
+      cur_off = offset;
+      if (segments[seg-1].type != SEG_DEBUG)
+        {
+          if (offset + len > segments[seg-1].size)
+            error2 ("LEDATA: data beyond end of segment");
+          else
+            get_mem (segments[seg-1].data + offset, len);
+        }
+    }
+}
+
+
+/* Convert an iterated data block, for LIDATA.
+
+   Iterated data block:
+    2/4 Repeat count
+    2   Block count (0: data bytes, otherwise nested block)
+    n   nested block or data bytes */
+
+static void conv_block (dword *poffset)
+{
+  dword rep_count, block_count, i, j;
+  int len, saved_idx;
+
+  rep_count = get_word_or_dword ();
+  block_count = get_word ();
+  if (rep_count == 0)
+    error2 ("LIDATA: repeat count is zero");
+  if (block_count == 0)
+    {
+      len = get_byte ();
+      if (*poffset + len * rep_count > segments[cur_seg].size)
+        error2 ("LIDATA: data beyond end of segment");
+      get_mem (segments[cur_seg].data + *poffset, len);
+      *poffset += len;
+      for (i = 1; i < rep_count; ++i)
+        {
+          memcpy (segments[cur_seg].data + *poffset,
+                  segments[cur_seg].data + *poffset - len, len);
+          *poffset += len;
+        }
+    }
+  else
+    {
+      saved_idx = rec_idx;
+      for (i = 0; i < rep_count; ++i)
+        {
+          rec_idx = saved_idx;
+          for (j = 0; j < block_count; ++j)
+            conv_block (poffset);
+        }
+    }
+}
+
+
+/* Convert a LIDATA record.
+
+   LIDATA record:
+    1-2 Segment index
+    2/4 Iterated data offset (4 bytes for 32-bit LIDATA record)
+    n   Data blocks */
+
+static void conv_lidata (void)
+{
+  dword offset, seg;
+
+  seg = get_index ();
+  offset = get_word_or_dword ();
+  if (seg < 1 || seg > GROW_COUNT (segments))
+    error2 ("LIDATA: segment index out of range");
+
+  if (segments[seg-1].data != NULL)
+    {
+      cur_seg = seg - 1;
+      cur_off = offset;
+      if (segments[cur_seg].type != SEG_DEBUG)
+        {
+          while (rec_len - rec_idx >= 4)
+            conv_block (&offset);
+        }
+    }
+  cur_seg = -1;                 /* FIXUPP for LIDATA not supported */
+}
+
+
+/* Convert a FIXUPP record.  This is the single interesting function
+   of this program.
+
+   FIXUPP record:
+   Ú
+   ³?   THREAD subrecord or FIXUP subrecord
+   À
+
+   THREAD subrecord:
+    1   Flags
+    0-2 Index (present only for FRAME methods F0, F1 and F2)
+
+   The flags byte contains the following fields:
+
+   0 (bit 7)            always 0 to indicate THREAD subrecord
+   D (bit 6)            0=target thread, 1=frame thread
+   0 (bit 5)            reserved
+   Method (bits 2-4)    method (T0 through T6 and F0 through F6)
+   Thred (bits 0-1)     thread number
+
+   FIXUP subrecord:
+    2   Locat
+    0-1 Fix data
+    0-2 Frame datum
+    0-2 Target datum
+    2/4 target displacement (4 bytes for 32-bit FIXUPP record)
+
+    The first locat byte contains the following fields:
+
+    1 (bit 7)           always 1 to indicate FIXUP subrecord
+    M (bit 6)           1=segment-relative fixup, 0=self-relative fixup
+    Location (bit 2-5)  Type of location to fix up:
+                          0010=16-bit selector
+                          0011=32-bit long pointer (16:16)
+                          1001=32-bit offset
+    Offset (bits 0-1)   Most significant bits of offset into LEDATA record
+
+    The second locat byte contains the least significant bits of the
+    offset into the LEDATA record.
+
+    The Fix data byte contains the following fields:
+
+    F (bit 7)           1=frame thread, 0=methods F0 through F5
+    Frame (bits 4-6)    frame thread number (F=1) or frame method (F=0)
+    T (bit 3)           1=target thread, 1=methods 
+    P (bit 2)           Bit 2 of target method
+    Targt (bits 0-1)    target thread number (T=1) or target method (T=0) */
+
+static void conv_fixupp (void)
+{
+  int i, first, locat, offset, fix_data, thred;
+  int frame_method, frame_index, target_method, target_index;
+  dword disp;
+  struct reloc r;
+  struct thread th;
+
+  while (rec_idx < rec_len)
+    {
+      first = get_byte ();
+      if (first & 0x80)
+        {
+          /* FIXUP subrecord */
+          offset = get_byte ();
+          offset |= (first & 3) << 8;
+          fix_data = get_byte ();
+          if (first & 0x40)
+            r.pcrel = 0;
+          else
+            r.pcrel = 1;
+          r.address = offset + cur_off;
+          r.unused = 0;
+          locat = (first >> 2) & 0x0f;
+          if (fix_data & 0x80)
+            {
+              thred = (fix_data >> 4) & 3;
+              frame_method = frame_threads[thred].method;
+              frame_index = frame_threads[thred].index;
+            }
+          else
+            {
+              frame_method = (fix_data >> 4) & 7;
+              frame_index = 0;
+              if (frame_method <= 2)
+                frame_index = get_index ();
+            }
+          if (fix_data & 0x08)
+            {
+              thred = fix_data & 3;
+              target_method = target_threads[thred].method;
+              target_index = target_threads[thred].index;
+            }
+          else
+            {
+              target_method = fix_data & 3;
+              target_index = get_index ();
+            }
+          disp = 0;
+          if (!(fix_data & 0x04))
+            disp = get_word_or_dword ();
+
+          if (cur_seg < 0)
+            error2 ("FIXUPP: not preceded by LEDATA or COMDAT");
+
+          /* Ignore all fixups for other segments, such as $$SYMBOLS
+             (which may have SEL-16 fixups). */
+
+          if (cur_seg == seg_code || cur_seg == seg_data)
+            {
+              switch (locat)
+                {
+                case 0:
+                  error2 ("FIXUPP: LOW-8 fixup not supported");
+                case 1:
+                  error2 ("FIXUPP: OFFSET-16 fixup not supported");
+                case 2:
+                  error2 ("FIXUPP: SEL-16 fixup not supported");
+                case 3:
+                  error2 ("FIXUPP: FAR-16:16 fixup not supported");
+                case 4:
+                  error2 ("FIXUPP: HIGH-8 fixup not supported");
+                case 5:
+                  error2 ("FIXUPP: OFFSET-16(LR) fixup not supported");
+                case 9:
+                  r.length = 2;
+                  break;
+                case 11:
+                  error2 ("FIXUPP: FAR-16:32 fixup not supported");
+                case 13:
+                  error2 ("FIXUPP: OFFSET-32(LR) fixup not supported");
+                default:
+                  error2 ("FIXUPP: unknown location");
+                }
+
+              switch (target_method)
+                {
+                case 0:         /* T0: SEGDEF */
+                  r.ext = 0;
+                  if (target_index == seg_code + 1)
+                    r.symbolnum = N_TEXT;
+                  else if (target_index == seg_data + 1)
+                    {
+                      r.symbolnum = N_DATA;
+                      disp += (seg_code >= 0 ? segments[seg_code].size : 0);
+                    }
+                  else if (target_index == seg_bss + 1)
+                    {
+                      r.symbolnum = N_BSS;
+                      disp += (seg_code >= 0 ? segments[seg_code].size : 0);
+                      disp += (seg_data >= 0 ? segments[seg_data].size : 0);
+                    }
+                  else if (target_index < 1
+                           || target_index > GROW_COUNT (segments))
+                    error2 ("FIXUPP: invalid segment index");
+                  else
+                    error2 ("FIXUPP: Target segment %s not supported",
+                            lnames[segments[target_index-1].name-1]);
+                  break;
+                case 2:         /* T2: EXTDEF */
+                  r.ext = 1;
+                  if (target_index < 1 || target_index > GROW_COUNT (extdefs))
+                    error2 ("FIXUPP: EXTDEF index out of range");
+                  r.symbolnum = target_index - 1;
+                  break;
+                default:
+                  error2 ("FIXUPP: TARGET method %d not supported",
+                          target_method);
+                }
+
+              switch (frame_method)
+                {
+                case 1:         /* F1: GRPDEF */
+                  if (frame_index != group_flat + 1)
+                    error2 ("FIXUPP: only group FLAT is supported "
+                            "for method F1");
+                  break;
+                default:
+                  error2 ("FIXUPP: FRAME method %d not supported",
+                          frame_method);
+                }
+
+              if (cur_seg == seg_code)
+                {
+                  i = GROW_ADD (trelocs);
+                  trelocs[i] = r;
+                }
+              else if (cur_seg == seg_data)
+                {
+                  i = GROW_ADD (drelocs);
+                  drelocs[i] = r;
+                }
+              else
+                abort ();
+
+              if (r.address + 4 > segments[cur_seg].size)
+                error2 ("FIXUPP: fixup beyond end of segment");
+              *((dword *)(segments[cur_seg].data + r.address))
+                += r.pcrel ? disp - (r.address + 4) : disp;
+            }
+        }
+      else
+        {
+          /* THREAD subrecord */
+          thred = first & 3;
+          if (first & 0x40)
+            {
+              th.method = (first >> 2) & 7;
+              th.index = 0;
+              if (th.method <= 2)
+                th.index = get_index ();
+              frame_threads[thred] = th;
+            }
+          else
+            {
+              th.method = (first >> 2) & 3;
+              th.index = get_index ();
+              target_threads[thred] = th;
+            }
+        }
+    }
+}
+
+
+/* Build the symbol table. */
+
+static void make_symtab (void)
+{
+  int i, j;
+  struct nlist n;
+  char skip;
+
+  /* Important: Write extdefs first, to be able to use EXTDEF indices
+     as symbol numbers. */
+
+  for (i = 0; i < GROW_COUNT (extdefs); ++i)
+    {
+      n.type = N_EXT;
+      n.string = 0;
+      n.value = extdefs[i].size;
+      n.other = 0;
+      n.desc = 0;
+      j = GROW_ADD (symbols);
+      symbols[j].name = xstrdup (extdefs[i].name);
+      symbols[j].n = n;
+      extdefs[i].sym = j;
+    }
+  for (i = 0; i < GROW_COUNT (pubdefs); ++i)
+    {
+      skip = FALSE;
+      if (pubdefs[i].group != group_flat + 1)
+        skip = TRUE;
+      else if (pubdefs[i].seg == seg_code + 1)
+        n.type = N_TEXT | N_EXT;
+      else if (pubdefs[i].seg == seg_data + 1)
+        n.type = N_DATA | N_EXT;
+      else
+        skip = TRUE;
+      if (!skip)
+        {
+          n.string = 0;
+          n.value = pubdefs[i].offset;
+          n.other = 0;
+          n.desc = 0;
+          j = GROW_ADD (symbols);
+          symbols[j].name = xstrdup (pubdefs[i].name);
+          symbols[j].n = n;
+        }
+    }
+}
+
+
+/* Write the symbol table. */
+
+static void write_symtab (void)
+{
+  int i;
+  dword str_size;
+
+  str_size = sizeof (dword);
+  for (i = 0; i < GROW_COUNT (symbols); ++i)
+    {
+      if (symbols[i].name == NULL)
+        symbols[i].n.string = 0;
+      else
+        {
+          symbols[i].n.string = str_size;
+          str_size += strlen (symbols[i].name) + 1;
+        }
+      fwrite (&symbols[i].n, sizeof (struct nlist), 1, out_file);
+    }
+  fwrite (&str_size, sizeof (dword), 1, out_file);
+  for (i = 0; i < GROW_COUNT (symbols); ++i)
+    if (symbols[i].name != NULL)
+      fwrite (symbols[i].name, strlen (symbols[i].name) + 1, 1, out_file);
+}
+
+
+/* Convert a MODEND record. */
+
+static void conv_modend (void)
+{
+  struct a_out_header h;
+  int i;
+
+  make_symtab ();
+  h.magic = 0407;
+  h.machtype = 0;
+  h.flags = 0;
+  h.text_size = (seg_code >= 0 ? segments[seg_code].size : 0);
+  h.data_size = (seg_data >= 0 ? segments[seg_data].size : 0);
+  h.bss_size =  (seg_bss  >= 0 ? segments[seg_bss ].size : 0);
+  h.sym_size = GROW_COUNT (symbols) * sizeof (struct nlist);
+  h.entry = 0;
+  h.trsize = GROW_COUNT (trelocs) * sizeof (struct reloc);
+  h.drsize = GROW_COUNT (drelocs) * sizeof (struct reloc);
+  fwrite (&h, sizeof (h), 1, out_file);
+  if (seg_code >= 0)
+    fwrite (segments[seg_code].data, segments[seg_code].size, 1, out_file);
+  if (seg_data >= 0)
+    fwrite (segments[seg_data].data, segments[seg_data].size, 1, out_file);
+  for (i = 0; i < GROW_COUNT (trelocs); ++i)
+    fwrite (&trelocs[i], sizeof (struct reloc), 1, out_file);
+  for (i = 0; i < GROW_COUNT (drelocs); ++i)
+    fwrite (&drelocs[i], sizeof (struct reloc), 1, out_file);
+  write_symtab ();
+}
+
+
+static void omf_to_o (void)
+{
+  struct omf_rec rec;
+
+  do
+    {
+      if (fread (&rec, sizeof (rec), 1, inp_file) != 1)
+        goto failure;
+      rec_type = rec.rec_type;
+      rec_len = rec.rec_len;
+      rec_idx = 0;
+      if (rec_len > sizeof (rec_buf))
+        {
+          rec_len = -1;         /* See error2() */
+          error2 ("Record too long");
+        }
+      if (fread (rec_buf, rec_len, 1, inp_file) != 1)
+        goto failure;
+      /*...check checksum...*/
+      --rec_len;
+      switch (rec_type)
+        {
+        case THEADR:
+          break;
+
+        case COMENT:
+          break;
+
+        case MODEND:
+        case MODEND|REC32:
+          conv_modend ();
+          break;
+
+        case EXTDEF:
+          conv_extdef ();
+          break;
+
+        case TYPDEF:
+          break;
+
+        case PUBDEF:
+        case PUBDEF|REC32:
+          conv_pubdef ();
+          break;
+
+        case LINNUM:
+        case LINNUM|REC32:
+          break;
+
+        case LNAMES:
+          conv_lnames ();
+          break;
+
+        case SEGDEF:
+        case SEGDEF|REC32:
+          conv_segdef ();
+          break;
+
+        case GRPDEF:
+          conv_grpdef ();
+          break;
+
+        case FIXUPP:
+        case FIXUPP|REC32:
+          conv_fixupp ();
+          break;
+
+        case LEDATA:
+        case LEDATA|REC32:
+          conv_ledata ();
+          break;
+
+        case LIDATA:
+        case LIDATA|REC32:
+          conv_lidata ();
+          break;
+
+        case COMDEF:
+          conv_comdef ();
+          break;
+
+        case COMDAT:
+        case COMDAT|REC32:
+          break;
+
+        default:
+          error2 ("Unknown record type: %.2x\n", rec.rec_type);
+        }
+    } while (rec_type != MODEND && rec_type != (MODEND|REC32));
+  return;
+
+failure:
+  if (ferror (inp_file))
+    error ("%s: %s", inp_fname, strerror (errno));
+  else
+    error ("%s: Unexpected end of file", inp_fname);
+}
+
+
+/* Convert the OMF file SRC_FNAME to an a.out file named DST_FNAME.
+   If DST_FNAME is NULL, the output file name is derived from
+   SRC_FNAME. */
+
+static void convert (const char *src_fname, const char *dst_fname)
+{
+  init_module ();
+
+  inp_fname = src_fname;
+  inp_file = fopen (inp_fname, "rb");
+  if (inp_file == NULL)
+    error ("Cannot open input file `%s'", inp_fname);
+
+  make_out_fname (dst_fname, inp_fname, ".o");
+  open_output ();
+  omf_to_o ();
+  close_output ();
+  fclose (inp_file);
+
+  term_module ();
+}
+
+
+/* Main function of emxaout.  Parse the command line and perform the
+   requested actions. */
+
+int main (int argc, char *argv[])
+{
+  int c, i;
+  char *opt_o;
+
+  /* Expand response files (@filename) and wildcard (*.o) on the
+     command line. */
+
+  _response (&argc, &argv);
+  _wildcard (&argc, &argv);
+
+  /* Set default values of some options. */
+
+  opt_o = NULL;
+  opterr = FALSE;
+
+  /* Parse the command line options. */
+
+  while ((c = getopt (argc, argv, "uo:")) != EOF)
+    switch (c)
+      {
+      case 'o':
+        if (opt_o != NULL)
+          usage ();
+        opt_o = optarg;
+        break;
+      case 'u':
+        underscores = TRUE;
+        break;
+      default:
+        usage ();
+      }
+
+  /* Check for non-option arguments. */
+
+  if (argc - optind == 0)
+    usage ();
+
+  if (opt_o != NULL)
+    {
+
+      /* If the -o option is used, there must be exactly one input
+         file name. */
+
+      if (argc - optind != 1)
+        usage ();
+      convert (argv[optind], opt_o);
+    }
+  else
+    {
+
+      /* The -o option is not used. Convert all the files named on the
+         command line. */
+
+      for (i = optind; i < argc; ++i)
+        convert (argv[i], NULL);
+    }
+
+  return 0;
+}
Index: trunk/src/emx/src/emxomf/emxomf.c
===================================================================
--- trunk/src/emx/src/emxomf/emxomf.c	(revision 18)
+++ trunk/src/emx/src/emxomf/emxomf.c	(revision 18)
@@ -0,0 +1,3466 @@
+/* emxomf.c -- Convert GNU-style a.out object files (with emx extensions)
+               to OS/2-style OMF (Object Module Formats) object files
+   Copyright (c) 1992-1998 Eberhard Mattes
+
+This file is part of emxomf.
+
+emxomf is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxomf is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxomf; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/param.h>
+#include <sys/emxload.h>
+#include <ar.h>
+
+/* The version number of this program.  This is printed with the usage
+   message. */
+
+#define VERSION "0.9d"
+
+/* Insert private header files. */
+
+#include "defs.h"               /* Common definitions */
+#include "emxomf.h"             /* Global definitions for emxomf */
+#include "stabshll.h"           /* Convert debug information */
+#include "grow.h"               /* Growing objects */
+
+/* This header must come after defs.h */
+
+#include <sys/omflib.h>         /* Handling OMF libraries */
+
+/* Flag bits for FLAGS field of the struct symbol structure. */
+
+#define SF_FAR16        0x01    /* 16:16 pointer */
+
+/* This structure holds additional data for symbols. */
+
+struct symbol
+{
+  int index;                    /* EXTDEF index */
+  int flags;                    /* SF_FAR16 */
+};
+
+/* This program keeps OMF symbols (names) in a list of lname
+   structures. */
+
+struct lname
+{
+  struct lname *next;           /* Pointer to next element */
+  char *name;                   /* Name of the symbol */
+  int index;                    /* OMF index of the symbol */
+};
+
+/* Names of files to be deleted on program termination are stored in a
+   list of delete structures. */
+
+struct delete
+{
+  struct delete *next;          /* Pointer to next element */
+  char *name;                   /* Name of the file to be deleted */
+};
+
+/* This structure holds the information about one class (set) of a.out
+   set elements.  Set elements are used for constructors and
+   destructors.  These structures are chained in a list.  See
+   write_set_data() for details. */
+
+struct set
+{
+  struct set *next;             /* Pointer to next class of set elements */
+  char *name;                   /* Name of the set (the a.out symbol) */
+  int seg_name[3];              /* Name indices of the three segments */
+  int seg_index[3];             /* Segment indices of the three segments */
+  int group_name;               /* Name index of the group */
+  int group_index;              /* Group index of the group */
+  int def;                      /* Non-zero if head element encountered */
+  int count;                    /* Number of non-head non-tail elements */
+  dword *data;                  /* Values of set elements (COUNT elements) */
+  byte *seg;                    /* Segments of set elements (COUNT elements) */
+};
+
+/* Default library requests (see -i option) are stored in a list of
+   libreq structures. */
+
+struct libreq
+{
+  char *name;                   /* Name of the default library */
+  struct libreq *next;          /* Pointer to next element */
+};
+
+/* This structure describes an OMF-style line number. */
+
+struct line
+{
+  dword addr;                   /* Start address of the line */
+  int line;                     /* Line number */
+  int file_index;               /* File index */
+};
+
+/* fetch_modstr() caches the string it has retrieved from other
+   modules of the same library.  The cache consists of a a linked list
+   of `struct modstr' structures. */
+
+struct modstr
+{
+  struct modstr *next;          /* Pointer to next node */
+  char *symbol;                 /* Symbol attached to the string */
+  char *str;                    /* The value of the string */
+};
+
+
+/* The number of symbols in the a.out file. */
+int sym_count = 0;
+
+/* The sym_ptr variable points to an array of a.out symbols.  There
+   are sym_count table entries.  Note that this table is complemented
+   by the sym_more table. */
+const struct nlist *sym_ptr = NULL;
+
+/* The str_ptr variable points to the a.out string table.  The
+   elements of sym_ptr contain offsets into this table.  The table
+   starts with a 32-bit number.  The rest of the table consists of
+   null-terminated strings. */
+const byte *str_ptr = NULL;
+
+/* The text_ptr variable points to the first byte of the text
+   segment.  text_size bytes are available at text_ptr. */
+byte *text_ptr = NULL;
+long text_size = 0;
+
+/* The data_ptr variable points to the first byte of the data
+   segment.  data_size bytes are available at data_ptr. */
+
+static byte *data_ptr;
+static long data_size;
+
+/* These varibles point to the text and data relocation tables. */
+
+static const struct reloc *text_rel;
+static const struct reloc *data_rel;
+
+/* Public variables for communication with stabshll.c. */
+
+struct buffer tt = BUFFER_INIT;
+struct buffer sst = BUFFER_INIT;
+struct buffer sst_reloc = BUFFER_INIT;
+struct grow sst_boundary_grow = GROW_INIT;
+struct grow tt_boundary_grow = GROW_INIT;
+int *sst_boundary = NULL;
+int *tt_boundary = NULL;
+
+
+/* Private variables. */
+
+/* The name of the current input file. */
+static const char *inp_fname;
+
+/* The name of the current output file. */
+static const char *out_fname = NULL;
+
+/* Use this file name for reporting errors.  This is either the name
+   of the input file or a library name plus module name:
+   library(module). */
+static const char *error_fname;
+
+/* The output directory.  This is set by the -O option. */
+static const char *output_dir = "";
+
+/* The current input file. */
+static FILE *inp_file;
+
+/* The current output file. */
+static FILE *out_file = NULL;
+
+/* While writing a LIB response file, this variable contains the
+   stream pointer.  Otherwise, this variable is NULL. */
+static FILE *response_file = NULL;
+
+/* When creating an OMF library (.lib file), this variable contains
+   the descriptor used by the omflib library.  Otherwise, this
+   variable is NULL. */
+static struct omflib *out_lib = NULL;
+
+/* This buffer receives error messages from the omflib library. */
+static char lib_errmsg[512];
+
+/* emxomf reads a complete a.out module into memory.  inp_buf points
+   to the buffer holding the current a.out module.  This pointer is
+   aliased by sym_ptr etc. */
+static byte *inp_buf;
+
+/* OMF records are constructed in this buffer.  The first three bytes
+   are used for the record type and record length.  One byte at the
+   end is used for the checksum. */
+static byte out_buf[1+2+MAX_REC_SIZE+1];
+
+/* Index into out_buf (to be more precise: it's a pointer into
+   out_data, which is an alias to out_buf+3) for the next byte of the
+   OMF record. */
+static int out_idx;
+
+/* The list of OMF names.  lnames is the head of the list, lname_add
+   is used to add another name to the end of the list. */
+static struct lname *lnames;
+static struct lname **lname_add;
+
+/* The list of sets.  sets is the head of the list, set_add is used to
+   add another set to the end of the list. */
+static struct set *sets;
+static struct set **set_add;
+
+/* For compatibility with emxomf 0.8h and older, generation of GRPDEF
+   records for sets can be enabled by using the -g option.  That
+   option sets this variable to TRUE.  By default, GRPDEF records are
+   not generated. */
+static int do_set_groups = FALSE;
+
+/* If this variable is TRUE, an a.out archive is split into several
+   OMF .obj files (-x option).  If this variable is FALSE, an a.out
+   archive is converted into an OMF library file. */
+static int opt_x = FALSE;
+
+/* This is the page size for OMF libraries.  It is set by the -p
+   option. */
+static int page_size = 16;
+
+/* The index of the next OMF name, used by find_lname().  Name indices
+   are established by LNAMES records written by write_lnames(). */
+static int lname_index;
+
+/* The index of the next segment, used by seg_def() for creating
+   SEGDEF records. */
+static int segdef_index;
+
+/* The index of the next group, used for creating GRPDEF records. */
+static int group_index;
+
+/* The index of the next symbol, used for creating EXTDEF and COMDEF
+   records. */
+static int sym_index;
+
+/* The index of the "WEAK$ZERO" symbol or 0. */
+static int weak_zero_index;
+
+/* OMF name indices: segments, classes, groups, etc. */
+static int ovl_name;            /* Overlay name, "" */
+static int text_seg_name;       /* Text segment, "TEXT32" */
+static int data_seg_name;       /* Data segment, "DATA32" */
+static int udat_seg_name;       /* Explicit data segment, see -D */
+static int stack_seg_name;      /* Stack segment, "STACK" */
+static int bss_seg_name;        /* Uninitialized data segment, "BSS32" */
+static int symbols_seg_name;    /* Symbols segment, "$$SYMBOLS" */
+static int types_seg_name;      /* Types segment */
+static int code_class_name;     /* Code class, "CODE" */
+static int data_class_name;     /* Data class, "DATA" */
+static int stack_class_name;    /* Stack class, "STACK" */
+static int bss_class_name;      /* Uninitialized data class, "BSS" */
+static int debsym_class_name;   /* Symbols class, "DEBSYM" */
+static int debtyp_class_name;   /* Types class, "DEBTYP" */
+static int flat_group_name;     /* FLAT group, "FLAT" */
+static int dgroup_group_name;   /* DGROUP group, "DGROUP" or "DATAGROUP" */
+
+/* Segment indices for the TEXT32, DATA32, STACK, BSS32, $$SYMBOLS,
+   $$TYPES and explicit data segments. */
+static int text_index;          /* Text segment, TEXT32 */
+static int data_index;          /* Data segment, DATA32 */
+static int udat_index;          /* Data segment set by -D or same as above */
+static int stack_index;         /* Stack segment, STACK */
+static int bss_index;           /* Uninitialized data segment, BSS32 */
+static int symbols_index;       /* Symbols segment, $$SYMBOLS */
+static int types_index;         /* Types segment, $$TYPES */
+
+/* Group indices for the FLAT and DGROUP groups. */
+static int flat_index;          /* FLAT group */
+static int dgroup_index;        /* DGROUP group */
+
+/* Next FIXUPP thread index to be used for the frame and target
+   thread, respectively. */
+static int frame_thread_index;  /* Frame thread */
+static int target_thread_index; /* Target thread */
+
+/* We define target threads for referencing the TEXT32, DATA32 (or the
+   one set by -D) and BSS32 segments and the FLAT group in FIXUPP
+   records.  A thread has not been defined if the variable is -1.
+   Otherwise, the value is the thread number. */
+static int text_thread;         /* TEXT32 segment */
+static int data_thread;         /* Data segment (DATA32 or -D) */
+static int bss_thread;          /* BSS32 segment */
+static int flat_thread;         /* FLAT group */
+
+/* This variable holds the module name.  See get_mod_name(). */
+static char mod_name[256];
+
+/* This growing array holds the file name table for generating line
+   number information.  */
+static char **file_list;
+static struct grow file_grow;
+
+/* This variable points to the a.out header of the input module. */
+static const struct a_out_header *a_out_h;
+
+/* This table contains additional information for the a.out symbols.
+   Each entry of the sym_ptr table is complemented by an entry of this
+   table. */
+static struct symbol *sym_more;
+
+/* The length of the a.out string table, in bytes.  This value
+   includes the 32-bit number at the start of the string table. */
+static long str_size;
+
+/* omflib_write_module() stored the page number of the module to this
+   variable. */
+static word mod_page;
+
+/* This variable is TRUE until we have written the first line to the
+   LIB response file.  It is used to suppress the line continuation
+   character `&'. */
+static int response_first = TRUE;
+
+/* This is the list of files to be deleted on program termination.
+   See delete_files(). */
+static struct delete *files_to_delete = NULL;
+
+/* The module type (-l and -m options).  It is MT_MODULE unless the -l
+   or -m option is used. */
+static enum {MT_MODULE, MT_MAIN, MT_LIB} mod_type = MT_MODULE;
+
+/* The start (entry point) symbol (-m option).  This is NULL unless
+   the -m option (or -l with argument) is used. */
+static char *entry_name = NULL;
+
+/* The name of the identifier manipulation DLL.  If this variable is
+   NULL, no IDMDLL record is written. */
+static char *idmdll_name = "GPPDEMID";
+
+/* If this variable is TRUE (-b option), we always use the 32-bit
+   variant of the OMF records.  If this variable is FALSE, we use the
+   16-bit variant whenever possible.  This non-documented feature is
+   used for debugging. */
+static int force_big = FALSE;
+
+/* The name of the LIB response file (-r and -R options).  This value
+   is NULL unless the -r or -R option is used. */
+static char *response_fname = NULL;
+
+/* When creating a LIB response file, emit commands for replacing
+   modules if this variable is TRUE (-R option).  Otherwise, emit
+   commands for adding modules (-r option). */
+static int response_replace;
+
+/* Delete input files after successful conversion if this variable is
+   TRUE (-d option). */
+static int delete_input_files = FALSE;
+
+/* Strip debug information if this variable is TRUE (-s option).
+   Otherwise, convert DBX debugging information to HLL debugging
+   information. */
+static int strip_symbols = FALSE;
+
+/* Print unknown symbol table entries if this variable is TRUE (-u
+   option). */
+static int unknown_stabs = FALSE;
+
+/* Supress certain warnings if this variable is TRUE (-q option). */
+static int quiet = FALSE;
+
+/* The libreq_head variable contains a pointer to the head of the list
+   of default libraries.  The -i option is used to add a default
+   library request.  The libreq_add pointer is used for appending new
+   elements to the tail of the list. */
+static struct libreq *libreq_head = NULL;
+static struct libreq **libreq_add = &libreq_head;
+
+/* fetch_mod_str() caches the string it has retrieved from other
+   modules of the same library.  modstr_cache points to the head of
+   the linked list of `struct modstr' structures. */
+
+static struct modstr *modstr_cache = NULL;
+
+/* Simulate the data array of an OMF record.  The data is stored along
+   with the record type (1 byte) and record length (2 bytes) in a
+   single buffer. */
+#define out_data (out_buf+1+2)
+
+/* The data segment name, set by the -D option.  If this value is
+   non-NULL, put variables into the named data segment, which isn't a
+   member of DGROUP. */
+
+static char *udat_seg_string = NULL;
+
+/* Prototypes for private functions. */
+
+static void doesn_fit (void) NORETURN2;
+static void usage (void) NORETURN2;
+static int ar_read_header (struct ar_hdr *dst, long pos);
+static long ar_member_size (const struct ar_hdr *p);
+
+
+/* Display an error message on stderr, delete the output file and
+   quit.  This function is invoked like printf(): FMT is a
+   printf-style format string, all other arguments are formatted
+   according to FMT.  The message should not end with a newline. The
+   exit code is 2. */
+
+void error (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emxomf: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  va_end (arg_ptr);
+  fputc ('\n', stderr);
+
+  /* If there is an output file, close and delete it. */
+
+  if (out_file != NULL)
+    {
+      fclose (out_file);
+      remove (out_fname);
+    }
+  exit (2);
+}
+
+
+/* Display a warning message on stderr (and do not quit).  This
+   function is invoked like printf(): FMT is a printf-style format
+   string, all other arguments are formatted according to FMT. */
+
+void warning (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emxomf warning: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  va_end (arg_ptr);
+  fputc ('\n', stderr);
+}
+
+
+/* Allocate N bytes of memory.  Quit on failure.  This function is
+   used like malloc(), but we don't have to check the return value. */
+
+void *xmalloc (size_t n)
+{
+  void *p;
+  
+  p = malloc (n);
+  if (p == NULL)
+    error ("Out of memory");
+  return p;
+}
+
+
+/* Change the allocation of PTR to N bytes.  Quit on failure.  This
+   function is used like realloc(), but we don't have to check the
+   return value. */
+
+void *xrealloc (void *ptr, size_t n)
+{
+  void *p;
+  
+  p = realloc (ptr, n);
+  if (p == NULL)
+    error ("Out of memory");
+  return p;
+}
+
+
+/* Create a duplicate of the string S on the heap.  Quit on failure.
+   This function is used like strdup(), but we don't have to check the
+   return value. */
+
+char *xstrdup (const char *s)
+{
+  char *p;
+  
+  p = xmalloc (strlen (s) + 1);
+  strcpy (p, s);
+  return p;
+}
+
+
+/* Find an a.out symbol.  The underscore character `_' is prepended to
+   NAME.  On success, a pointer to the symbol table entry (in the
+   array pointed to by sym_ptr) is returned.  If the symbol is not
+   found, NULL is returned. */
+
+const struct nlist *find_symbol (const char *name)
+{
+  int i, j, n, len, ok, t;
+  const byte *s;
+  
+  i = 4; len = strlen (name);
+
+  /* Search the string table for a matching string. */
+
+  while (i < str_size)
+    {
+      ok = TRUE; s = name;
+      if (str_ptr[i] == '_')
+        ++i;
+      else
+        ok = FALSE;
+      if (ok && memcmp (name, str_ptr+i, len+1) == 0)
+	{
+
+          /* Search the symbol table for an appropriate entry
+             referencing the string. */
+
+	  n = sym_count;
+          --i;                  /* Move back to the underscore */
+	  for (j = 0; j < n; ++j)
+	    if (sym_ptr[j].string == i)
+	      {
+		t = sym_ptr[j].type & ~N_EXT;
+		if (t == N_TEXT || t == N_DATA || t == N_BSS
+                    || (t == 0 && sym_ptr[j].value != 0))
+		  return sym_ptr+j;
+	      }
+	}
+      i += strlen (str_ptr+i) + 1;
+    }
+  return NULL;                  /* Symbol not found */
+}
+
+
+/* Initialize variables for starting a new OMF output file. */
+
+static void init_obj (void)
+{
+  /* Initialize the list of OMF-style names. */
+
+  lnames = NULL; lname_add = &lnames; lname_index = 1;
+
+  /* Initialize segments. */
+
+  segdef_index = 1; sym_index = 1; group_index = 1; weak_zero_index = 0;
+
+  /* Initialize FIXUPP threads. */
+
+  text_thread = -1; data_thread = -1; bss_thread = -1; flat_thread = -1;
+  frame_thread_index = 0; target_thread_index = 0;
+
+  /* Initialize set elements management. */
+
+  sets = NULL; set_add = &sets;
+
+  /* Initialize the buffers used for converting debugging
+     information. */
+
+  buffer_init (&tt);
+  buffer_init (&sst);
+  buffer_init (&sst_reloc);
+}
+
+
+/* Find an OMF-style name.  If NAME is not yet a known OMF-style name,
+   it is added to the list of OMF-style names.  The index of the name
+   is returned.  All the OMF-style names will be defined in LNAMES
+   records.  Note: INDEX must be assigned sequentially, append to end
+   of list!  Otherwise, write_lnames() would have to sort the list */
+
+static int find_lname (const char *name)
+{
+  struct lname *p;
+
+  /* Walk through the list of known OMF-style names.  If there is a
+     match, return the index of the name. */
+
+  for (p = lnames; p != NULL; p = p->next)
+    if (strcmp (name, p->name) == 0)
+      return p->index;
+
+  /* The name is not yet known.  Create a new entry. */
+
+  p = xmalloc (sizeof (struct lname));
+  p->name = xstrdup (name);
+  p->index = lname_index++;
+
+  /* Add the new entry to the tail of the list of names. */
+
+  p->next = NULL;
+  *lname_add = p;
+  lname_add = &p->next;
+
+  /* Return the index of the new name. */
+
+  return p->index;
+}
+
+
+/* Deallocate the memory used by the list of OMF-style names. */
+
+static void free_lnames (void)
+{
+  struct lname *p, *q;
+
+  for (p = lnames; p != NULL; p = q)
+    {
+      q = p->next;
+      free (p->name);
+      free (p);
+    }
+}
+
+
+/* Start a new OMF record.  TYPE is the record type. */
+
+static void init_rec (int type)
+{
+  out_buf[0] = (byte)type;
+  out_idx = 0;
+}
+
+
+/* Write an OMF record.  The record type has been defined by
+   init_rec(), the data has been defined by put_8(), put_idx() etc.
+   The checksum is computed by this function.  An OMF record has the
+   following format:
+
+   struct omf_record
+   {
+     byte type;                 The record type
+     word length;               The record length, exclusive TYPE and LENGTH
+     byte data[LENGTH-1];       The record data
+     byte checksum;             The check sum.  The sum of all the bytes in
+                                the record is 0 (module 256)
+   };
+
+   If we're writing a LIB file, we call omflib_write_record().
+   Otherwise, we build and write the record here.  An OMF record
+   usually contains multiple definitions, see write_lnames() for a
+   simple instance of the loop we use for packing multiple definitions
+   into OMF records. */
+
+static void write_rec (void)
+{
+  byte chksum;
+  int i;
+
+  if (out_lib != NULL)
+    {
+
+      /* Write the record to the library file. */
+
+      if (omflib_write_record (out_lib, out_buf[0], out_idx, out_data,
+                               TRUE, lib_errmsg) != 0)
+        error (lib_errmsg);
+    }
+  else
+    {
+
+      /* Store the record length, LSB first. */
+
+      out_buf[1] = (byte)(out_idx+1);
+      out_buf[2] = (byte)((out_idx+1) >> 8);
+
+      /* Compute the check sum. */
+
+      chksum = 0;
+      for (i = 0; i < 1+2+out_idx; ++i)
+        chksum += out_buf[i];
+      out_data[out_idx] = (byte)(256-chksum);
+
+      /* Write the record. */
+
+      if (fwrite (out_buf, 1+2+out_idx+1, 1, out_file) != 1)
+        error ("Write error on output file `%s'", out_fname);
+    }
+}
+
+
+/* This macro yields TRUE iff we can put another X bytes into the
+   current OMF record. */
+
+#define fits(X) (out_idx + (X) <= MAX_REC_SIZE-4)
+
+/* This function is called if we try to build too big an OMF record.
+   This cannot happen unless there is a bug in this program.  Display
+   an error message and quit. */
+
+static void doesn_fit (void)
+{
+  error ("Record too long");
+}
+
+
+/* Put the null-terminated string SRC into the current OMF record.  In
+   the OMF record, the string is preceded by a length byte.  The
+   string length must not exceed 255; if it is too long, display a
+   warning and truncate the string.  Moreover, there must be enough
+   space left in the OMF record; if there isn't, display an error
+   message and abort. */
+
+static void put_str (const char *src)
+{
+  int len;
+
+  len = strlen (src);
+  if (len > 255)
+    {
+      warning ("Symbol length truncated to 255 characters for `%s'", src);
+      len = 255;
+    }
+  if (!fits (1+len))
+    doesn_fit ();
+  out_data[out_idx++] = (byte)len;
+  memcpy (out_data+out_idx, src, len);
+  out_idx += len;
+}
+
+
+/* Put the symbol SRC, a null-terminated string, into the current OMF
+   record.  If SRC starts with the underscore character `_', that
+   character is skipped.  This is where the leading underscore
+   character of a.out symbols is removed.  C modules for emx.dll are
+   treated specially here: The leading underscore is not removed
+   unless the name looks like the name of an OS/2 API function.  The
+   symbol length (after removing the leading underscore) must not
+   exceed 255 characters.  There must be enough space left in the OMF
+   record.  If these conditions are not met, display an error message
+   and quit. */
+
+static void put_sym (const char *src)
+{
+  if (*src == '_')
+    ++src;
+  put_str (src);
+}
+
+/* Put an 8-bit byte into the current OMF record.  This macro does not
+   test for buffer / record overflow. */
+
+#define put_8(x) out_data[out_idx++] = (byte)(x)
+
+/* Put a 16-bit word (least significant byte first) into the current
+   OMF record.  If there is not enough space left in the OMF record,
+   display an error message and quit. */
+
+static void put_16 (int x)
+{
+  if (!fits (2))
+    doesn_fit ();
+  out_data[out_idx++] = (byte)x;
+  out_data[out_idx++] = (byte)(x >> 8);
+}
+
+
+/* Put a 24-bit word (least significant byte first) into the current
+   OMF record.  If there is not enough space left in the OMF record,
+   display an error message and quit. */
+
+static void put_24 (long x)
+{
+  if (!fits (3))
+    doesn_fit ();
+  out_data[out_idx++] = (byte)x;
+  out_data[out_idx++] = (byte)(x >> 8);
+  out_data[out_idx++] = (byte)(x >> 16);
+}
+
+
+/* Put a 32-bit word (least significant byte first) into the current
+   OMF record.  If there is not enough space left in the OMF record,
+   display an error message and quit. */
+
+static void put_32 (long x)
+{
+  if (!fits (4))
+    doesn_fit ();
+  out_data[out_idx++] = (byte)x;
+  out_data[out_idx++] = (byte)(x >> 8);
+  out_data[out_idx++] = (byte)(x >> 16);
+  out_data[out_idx++] = (byte)(x >> 24);
+}
+
+
+/* Put the index X into the current OMF record.  Indices are used for
+   identifying names (LNAMES), segments (SEGDEF), groups (GRPDEF)
+   etc.  Indices are stored in one or two bytes, depending on the
+   value.  Small indices (0 through 127) are stored as single byte.
+   Large indices (128 through 32767) are stored as two bytes: the
+   high-order byte comes first, with bit 7 set; the low-order byte
+   comes next.  If there is not enough space left in the OMF record or
+   if the value exceeds 32767, display an error message and quit. */
+
+static void put_idx (int x)
+{
+  if (x <= 0x7f)
+    {
+      if (!fits (1))
+        doesn_fit ();
+      out_data[out_idx++] = (byte)x;
+    }
+  else if (x <=0x7fff)
+    {
+      if (!fits (2))
+        doesn_fit ();
+      out_data[out_idx++] = (byte)((x >> 8) | 0x80);
+      out_data[out_idx++] = (byte)x;
+    }
+  else
+    error ("Index too large");
+}
+
+
+/* Put SIZE bytes from SRC into the current OMF record.  If there is
+   not enough space left in the OMF record, display an error message
+   and quit. */
+
+static void put_mem (const char *src, int size)
+{
+  if (!fits (size))
+    doesn_fit ();
+  memcpy (out_data+out_idx, src, size);
+  out_idx += size;
+}
+
+
+/* Write LNAMES records into the output file for defining all the
+   names stored in the LNAMES list.
+
+   LNAMES record:
+   Ú
+   ³1   String length n
+   ³n   Name
+   À
+
+   Name indices are assigned sequentially. */
+
+static void write_lnames (void)
+{
+  const struct lname *p;
+  int started;
+
+  started = FALSE;
+  for (p = lnames; p != NULL; p = p->next)
+    {
+      if (started && !fits (strlen (p->name)+1))
+        {
+          write_rec ();
+          started = FALSE;
+        }
+      if (!started)
+        {
+          init_rec (LNAMES);
+          started = TRUE;
+        }
+      put_str (p->name);
+    }
+  if (started)
+    write_rec ();
+}
+
+
+/* Add a string to the current EXTDEF record or start a new EXTDEF
+   record.  PSTARTED points to an object keeping state. */
+
+static void add_extdef (int *pstarted, const char *name)
+{
+  if (*pstarted && !fits (strlen (name)+3))
+    {
+      write_rec ();
+      *pstarted = FALSE;
+    }
+  if (!*pstarted)
+    {
+      init_rec (EXTDEF);
+      *pstarted = TRUE;
+    }
+  put_sym (name);
+  put_idx (0);                  /* type index */
+}
+
+
+/* Write EXTDEF records into the output file for all the external
+   symbols stored in the sym_ptr array.
+
+   EXTDEF record:
+   Ú
+   ³1   String length n
+   ³n   External name
+   ³1-2 Type index
+   À
+
+   Symbol indices are assigned sequentially. */
+
+static void write_extdef (void)
+{
+  const char *name;
+  int i, started;
+
+  started = FALSE;
+  for (i = 0; i < sym_count; ++i)
+    if (sym_ptr[i].type == (N_INDR|N_EXT))
+      ++i;                      /* Skip immediately following entry */
+    else if (sym_ptr[i].type == N_EXT && sym_ptr[i].value == 0)
+      {
+        name = str_ptr + sym_ptr[i].string;
+        sym_more[i].index = sym_index++;
+        if (memcmp (name, "__16_", 5) == 0)
+          sym_more[i].flags |= SF_FAR16;
+        add_extdef (&started, name);
+      }
+    else if (sym_ptr[i].type == N_WEAKU)
+      {
+        if (weak_zero_index == 0)
+          {
+            weak_zero_index = sym_index++;
+            add_extdef (&started, "WEAK$ZERO");
+          }
+        sym_more[i].index = sym_index++;
+        add_extdef (&started, str_ptr + sym_ptr[i].string);
+      }
+  if (started)
+    write_rec ();
+}
+
+/* Write WKEXT records into the output file for all undefined weak
+   symbols stored in the sym_ptr array.
+
+   WKEXT record:
+   Ú
+   ³1-2 weak EXTDEF index
+   ³1-2 default resolution EXTDEF index
+   À
+
+   */
+
+static void write_wkext (void)
+{
+  int i;
+
+  for (i = 0; i < sym_count; ++i)
+    if (sym_ptr[i].type == (N_INDR|N_EXT))
+      ++i;                      /* Skip immediately following entry */
+    else if (sym_ptr[i].type == N_WEAKU)
+      {
+        init_rec (COMENT);
+        put_8 (0x80);
+        put_8 (0xa8);
+        put_idx (sym_more[i].index);
+        put_idx (weak_zero_index);
+        write_rec ();
+      }
+}
+
+
+/* Write ALIAS records into the output file for all indirect
+   references. */
+
+static void write_alias (void)
+{
+  int i;
+  const char *pub_name;
+
+  for (i = 0; i < sym_count - 1; ++i)
+    if (sym_ptr[i].type == (N_INDR|N_EXT) && sym_ptr[i+1].type == N_EXT)
+      {
+        init_rec (ALIAS);
+        put_sym (str_ptr + sym_ptr[i].string);
+        put_sym (str_ptr + sym_ptr[i+1].string);
+        write_rec ();
+
+        if (out_lib != NULL)
+          {
+            pub_name = str_ptr + sym_ptr[i].string;
+            if (*pub_name == '_')
+              ++pub_name;
+            if (omflib_add_pub (out_lib, pub_name, mod_page, lib_errmsg) != 0)
+              error (lib_errmsg);
+          }
+      }
+}
+
+
+/* Write PUBDEF records into the output file for the public symbols of
+   the a.out-style symbol type TYPE.  Symbols of that type are defined
+   in the segment having the OMF segment index INDEX.  Ignore symbols
+   not fitting into a 16-bit PUBDEF record if BIG is FALSE.  Ignore
+   symbols fitting into a 16-bit PUBDEF record if BIG is TRUE.  START
+   is the virtual start address of the segment in the a.out file.
+
+   PUBDEF record:
+    1-2 Base group
+    1-2 Base segment
+    0/2 Base frame
+   Ú
+   ³1   String length n
+   ³n   Public name
+   ³2/4 Public offset (4 bytes for 32-bit PUBDEF record)
+   ³1-2 Type index
+   À
+
+   The base frame field is present only if the base segment field is
+   0. */
+
+static void write_pubdef1 (int type, int index, int big, dword start)
+{
+  int i, started;
+  const char *name, *pub_name;
+  dword address;
+
+  started = FALSE;
+  for (i = 0; i < sym_count; ++i)
+    if ((sym_ptr[i].type & ~N_EXT) == type)
+      {
+        address = sym_ptr[i].value - start;
+        if ((address >= 0x10000 || force_big) == big)
+          {
+            name = str_ptr + sym_ptr[i].string;
+            if ((sym_ptr[i].type & N_EXT)
+                || (type == N_TEXT && strncmp (name, "___POST$", 8) == 0))
+              {
+                if ((sym_ptr[i].type & N_EXT) && out_lib != NULL)
+                  {
+                    pub_name = name;
+                    if (*pub_name == '_')
+                      ++pub_name;
+                    if (omflib_add_pub (out_lib, pub_name, mod_page,
+                                        lib_errmsg) != 0)
+                      error (lib_errmsg);
+                  }
+                if (started && !fits (strlen (name) + 6))
+                  {
+                    write_rec ();
+                    started = FALSE;
+                  }
+                if (!started)
+                  {
+                    init_rec (big ? PUBDEF|REC32 : PUBDEF);
+                    put_idx (flat_index);
+                    put_idx (index);
+                    started = TRUE;
+                  }
+                put_sym (name);
+                if (big)
+                  put_32 (address);
+                else
+                  put_16 (address);
+                put_idx (0);        /* type index */
+              }
+          }
+      }
+  if (started)
+    write_rec ();
+}
+
+
+/* Write PUBDEF records into the output file for all the public N_TEXT
+   and N_DATA symbols stored in the sym_ptr array.  Common symbols are
+   handled by write_comdef() below. */
+
+static void write_pubdef (void)
+{
+  write_pubdef1 (N_TEXT, text_index, FALSE, 0);
+  write_pubdef1 (N_TEXT, text_index, TRUE, 0);
+  write_pubdef1 (N_DATA, udat_index, FALSE, text_size);
+  write_pubdef1 (N_DATA, udat_index, TRUE, text_size);
+}
+
+
+/* Write COMDEF records into the output file for all the common
+   symbols stored in the sym_ptr array.  Common symbols are used for
+   uninitialized variables.  The TYPE field of these symbols is 0
+   (plus N_EXT) and the VALUE field is non-zero (it is the size of the
+   variable).
+
+   COMDEF record:
+   Ú
+   ³1   String length n
+   ³n   Communal name
+   ³1-2 Type index
+   ³1   Data type (0x61: FAR data, 0x62: NEAR data)
+   ³1-5 Communal length
+   À
+
+   The length is encoded in 1 to 5 bytes, depending on the value:
+
+   0 through 0x7f       1 byte, containing the value
+   0 through 0xffff     0x81, followed by 16-bit word
+   0 through 0xffffff   0x84, followed by 24-bit word
+   0 through 0xffffffff 0x88, followed by 32-bit word */
+
+static void write_comdef (void)
+{
+  int i, started;
+  long size;
+  const char *name;
+
+  started = FALSE;
+  for (i = 0; i < sym_count; ++i)
+    if (sym_ptr[i].type == (N_INDR|N_EXT))
+      ++i;                      /* Skip immediately following entry */
+    else if (sym_ptr[i].type == N_EXT && sym_ptr[i].value != 0)
+      {
+        name = str_ptr + sym_ptr[i].string;
+        sym_more[i].index = sym_index++;
+        if (memcmp (name, "__16_", 5) == 0)
+          sym_more[i].flags |= SF_FAR16;
+        size = sym_ptr[i].value;
+        if (started && !fits (strlen (name) + 12))
+          {
+            write_rec ();
+            started = FALSE;
+          }
+        if (!started)
+          {
+            init_rec (COMDEF);
+            started = TRUE;
+          }
+        put_sym (name);
+        put_idx (0);                  /* Type index */
+        put_8 (0x62);                 /* Data type */
+        if (size < 0x80)
+          put_8 (size);
+        else if (size < 0x10000)
+          {
+            put_8 (0x81);
+            put_16 (size);
+          }
+        else if (size < 0x1000000)
+          {
+            put_8 (0x84);
+            put_24 (size);
+          }
+        else
+          {
+            put_8 (0x88);
+            put_32 (size);
+          }
+      }
+  if (started)
+    write_rec ();
+}
+
+
+/* Write a SEGDEF record to define a segment.  NAME_INDEX is the name
+   index of the segment name.  CLASS_INDEX is the name index of the
+   class name.  SIZE is the size of the segment in bytes.  STACK is
+   TRUE iff the segment is the stack segment.  seg_def() returns the
+   segment index of the new segment.
+
+   SEGDEF record:
+    1   Segment attributes
+    0/2 Frame number (present only if A=000)
+    0/1 Offset (present only if A=000)
+    2/4 Segment length (4 bytes for 32-bit SEGDEF record)
+    1/2 Segment name index
+    1/2 Segment class index
+    1/2 Overlay name index
+
+    The segment attributes byte contains the following fields:
+
+    A (bits 5-7)        Alignment (101=relocatable, 32-bit alignment)
+    C (bits 2-4)        Combination (010=PUBLIC, 101=STACK)
+    B (bit 1)           Big (segment length is 64KB)
+    P (bit 0)           USE32 */
+
+static int seg_def (int name_index, int class_index, long size, int stack)
+{
+  byte seg_attr;
+
+  seg_attr = (stack ? 0xb5 : 0xa9);
+  if (size > 0x10000 || force_big)
+    {
+      init_rec (SEGDEF|REC32);
+      put_8 (seg_attr);
+      put_32 (size);
+    }
+  else if (size == 0x10000)
+    {
+      init_rec (SEGDEF);
+      put_8 (seg_attr|2);
+      put_16 (0);
+    }
+  else
+    {
+      init_rec (SEGDEF);
+      put_8 (seg_attr);
+      put_16 (size);
+    }
+  put_idx (name_index);
+  put_idx (class_index);
+  put_idx (ovl_name);
+  write_rec ();
+  return segdef_index++;
+}
+
+
+/* This function is passed to qsort() for sorting a relocation table.
+   X1 and X2 point to reloc structures.  We compare the ADDRESS fields
+   of the structures. */
+
+static int reloc_compare (const void *x1, const void *x2)
+{
+  dword a1, a2;
+
+  a1 = ((struct reloc *)x1)->address;
+  a2 = ((struct reloc *)x2)->address;
+  if (a1 < a2)
+    return -1;
+  else if (a1 > a2)
+    return 1;
+  else
+    return 0;
+}
+
+
+/* Write the segment contents (data) of one OMF segment to the output
+   file.  Create LEDATA and FIXUPP records.  INDEX is the segment
+   index.  SEG_NAME is the name index of the segment name (not used).
+   SRC points to the data to be written (will be modified for
+   fixups!), SEG_SIZE is the number of bytes to be written.  REL
+   points to the relocation table (an array of struct reloc), REL_SIZE
+   is the size of the relocation table, in bytes(!).  SST_FLAG is TRUE
+   when writing the symbol segment $$SYMBOLS.  BOUNDARY points to an
+   array of indices into SRC where the data can be split between
+   records.  That array has BOUNDARY_COUNT entries.  SEG_TYPE is the
+   segment type (N_TEXT or N_DATA or -1) and is used for relocation.
+
+   We can split the data at arbitrary points after the last BOUNDARY
+   entry.  In consequence, write_seg() splits the data at arbitrary
+   points if BOUNDARY_COUNT is zero.
+
+   LEDATA record:
+    1-2 Segment index
+    2/4 Enumerated data offset (4 bytes for 32-bit LEDATA record)
+    n   Data bytes (n is derived from record length)
+
+   FIXUPP record:
+   Ú
+   ³?   THREAD subrecord or FIXUP subrecord
+   À
+
+   THREAD subrecord:
+    1   Flags
+    0-2 Index (present only for FRAME methods F0, F1 and F2)
+
+   The flags byte contains the following fields:
+
+   0 (bit 7)            always 0 to indicate THREAD subrecord
+   D (bit 6)            0=target thread, 1=frame thread
+   0 (bit 5)            reserved
+   Method (bits 2-4)    method (T0 through T6 and F0 through F6)
+   Thred (bits 0-1)     thread number
+
+   FIXUP subrecord:
+    2   Locat
+    0-1 Fix data
+    0-2 Frame datum
+    0-2 Target datum
+    2/4 target displacement (4 bytes for 32-bit FIXUPP record)
+
+    The first locat byte contains the following fields:
+
+    1 (bit 7)           always 1 to indicate FIXUP subrecord
+    M (bit 6)           1=segment-relative fixup, 0=self-relative fixup
+    Location (bit 2-5)  Type of location to fix up:
+                          0010=16-bit selector
+                          0011=32-bit long pointer (16:16)
+                          1001=32-bit offset
+    Offset (bits 0-1)   Most significant bits of offset into LEDATA record
+
+    The second locat byte contains the least significant bits of the
+    offset into the LEDATA record.
+
+    The Fix data byte contains the following fields:
+
+    F (bit 7)           1=frame thread, 0=methods F0 through F5
+    Frame (bits 4-6)    frame thread number (F=1) or frame method (F=0)
+    T (bit 3)           1=target thread, 1=methods 
+    P (bit 2)           Bit 2 of target method
+    Targt (bits 0-1)    target thread number (T=1) or target method (T=0)  */
+
+static void write_seg (int index, int seg_name, byte *src, long seg_size,
+                       const struct reloc *rel, long rel_size, int sst_flag,
+                       const int *boundary, int boundary_count, int seg_type)
+{
+  long n, off, tmp, end;
+  int i, reloc_count, reloc_idx, target_index, ok, data_off, far16;
+  int boundary_idx, started, *threadp;
+  struct reloc *reloc_tab;
+  const struct reloc *r;
+  byte locat;
+  dword start_data, start_bss;
+
+  target_index = 0; threadp = NULL; /* keep the compiler happy */
+
+  /* Copy and sort the relocation table. */
+
+  reloc_count = rel_size / sizeof (struct reloc);
+  reloc_tab = xmalloc (reloc_count * sizeof (struct reloc));
+  memcpy (reloc_tab, rel, reloc_count * sizeof (struct reloc));
+  qsort (reloc_tab, reloc_count, sizeof (struct reloc), reloc_compare);
+
+  /* First pass: apply fixups to data.  Adjust fixup frames for OMF
+     fixups.  In a.out files, frames are relative to address 0, in OMF
+     files, frames are relative to the start of the segment.  The
+     following two variables are used for doing these adjustments. */
+
+  start_data = text_size;
+  start_bss = start_data + data_size;
+
+  /* Scan the relocation table for entries applying to this segment. */
+
+  for (i = 0, r = reloc_tab; i < reloc_count; ++i, ++r)
+    if (r->length == 2)
+      {
+
+        /* Here we have a 32-bit relocation. */
+
+        if (r->ext)
+          {
+
+            /* The relocation refers to a symbol.  Look into the
+               symbol table to find the fixup type and target
+               address. */
+
+            switch (sym_ptr[r->symbolnum].type)
+              {
+              case N_EXT:
+              case N_WEAKU:
+                if (r->pcrel)
+                  *(dword *)(src + r->address) = 0;
+                break;
+              case N_TEXT:
+                break;
+              case N_TEXT|N_EXT:
+                *(dword *)(src + r->address) = 0;
+                break;
+              case N_DATA:
+              case N_DATA|N_EXT:
+                *(dword *)(src + r->address) -= start_data;
+                break;
+              case N_BSS:
+              case N_BSS|N_EXT:
+                *(dword *)(src + r->address) -= start_bss;
+                break;
+              default:
+                error ("write_seg: Invalid symbol type (0x%.2x)",
+                       sym_ptr[r->symbolnum].type);
+              }
+          }
+        else if (!(r->pcrel && (r->symbolnum & ~N_EXT) == seg_type))
+          {
+
+            /* The relocation does not refer to a symbol, it's an
+               internal relocation.  Get the fixup type from the
+               relocation table. */
+
+            switch (r->symbolnum & ~N_EXT)
+              {
+              case N_TEXT:
+                break;
+              case N_DATA:
+                *(dword *)(src + r->address) -= start_data;
+                break;
+              case N_BSS:
+                *(dword *)(src + r->address) -= start_bss;
+                break;
+              default:
+                error ("write_seg: Invalid relocation type");
+              }
+          }
+      }
+
+  /* Second pass: write LEDATA and FIXUPP records. */
+
+  off = 0; reloc_idx = 0; boundary_idx = 0;
+  while (seg_size > 0)
+    {
+
+      /* Compute the maximum number of bytes in the next LEDATA
+         record, depending on the maximum record size, the record type
+         (16-bit or 32-bit) and the number of bytes remaining.  The
+         number of bytes will be adjusted later to avoid splitting
+         entries of the $$SYMBOLS and $$TYPES segments. */
+
+      n = MAX_REC_SIZE - 5;
+      n -= (off >= 0x10000 || force_big ? 4 : 2);
+      if (seg_size < n)
+        n = seg_size;
+
+      /* Adjust the number of bytes to avoid splitting a fixup.  Find
+         the last relocation table entry which applies to this chunk.
+         Then, lower the chunk size to stop at the start of the
+         frame. */
+
+      i = reloc_idx; end = off + n;
+      while (i < reloc_count && reloc_tab[i].address < end)
+        ++i;
+      if (i > reloc_idx)
+        {
+          --i;
+          tmp = reloc_tab[i].address + (1 << reloc_tab[i].length) - off;
+          if (tmp > n)
+            n = reloc_tab[i].address - off;
+        }
+
+      /* Consult the BOUNDARY table to find the last point where we
+         are allowed to split the data into multiple LEDATA records.
+         This must be done after adjusting for relocation table
+         entries. */
+
+      end = off + n;
+      while (boundary_idx < boundary_count && boundary[boundary_idx] < end)
+        ++boundary_idx;
+      if (boundary_idx > 0)
+        {
+          tmp = boundary[boundary_idx-1] - off;
+          if (tmp > 0)
+            n = tmp;
+        }
+
+      /* Write the LEDATA record.  This is simple. */
+
+      if (off >= 0x10000 || force_big)
+        {
+          init_rec (LEDATA|REC32);
+          put_idx (index);
+          put_32 (off);
+        }
+      else
+        {
+          init_rec (LEDATA);
+          put_idx (index);
+          put_16 (off);
+        }
+      put_mem (src, n);
+      write_rec ();
+
+      /* Write the FIXUPP records for this LEDATA record.  Quite
+         hairy. */
+
+      end = off + n;
+      started = FALSE;
+      r = &reloc_tab[reloc_idx];
+
+      /* Look at all relocation table entries which apply to the
+         current LEDATA chunk. */
+
+      while (reloc_idx < reloc_count && r->address < end)
+        {
+
+          /* Set ok to TRUE if we should create a fixup for this
+             relocation table entry.  First, ignore all but 32-bit
+             relocations.  In the $$SYMBOLS segment, we also have
+             16-bit selector fixups.  far16 is later set to TRUE for
+             16:16 fixups. */
+
+          ok = (r->length == 2 || (sst_flag && r->length == 1));
+          far16 = FALSE;
+
+          if (r->ext)
+            {
+
+              /* The relocation refers to a symbol -- we won't use a
+                 target thread.  If the symbol is a 16:16 symbol, we
+                 set far16 to true to generate a 16:16 fixup. */
+
+              threadp = NULL;
+              if (sym_more[r->symbolnum].flags & SF_FAR16)
+                far16 = TRUE;
+            }
+          else if (r->pcrel && (r->symbolnum & ~N_EXT) == seg_type)
+            {
+              ok = FALSE;
+              if (!quiet)
+                warning ("Internal PC-relative relocation ignored");
+            }
+          else
+            {
+
+              /* The relocation does not refer to a symbol -- we use
+                 an appropriate target thread.  The target thread
+                 number is taken from or stored to *threadp.
+                 target_index is the OMF segment index. */
+
+              switch (r->symbolnum & ~N_EXT)
+                {
+                case N_TEXT:
+                  threadp = &text_thread;
+                  target_index = text_index;
+                  break;
+                case N_DATA:
+                  threadp = &data_thread;
+                  target_index = udat_index;
+                  break;
+                case N_BSS:
+                  threadp = &bss_thread;
+                  target_index = bss_index;
+                  break;
+                case N_ABS:
+                default:
+                  ok = FALSE;
+                  break;
+                }
+            }
+
+          if (ok)
+            {
+
+              /* Now we build the FIXUPP record. */
+
+              if (started && !fits (32))
+                {
+                  write_rec ();
+                  started = FALSE;
+                }
+              if (!started)
+                {
+                  init_rec (FIXUPP|REC32);
+                  started = TRUE;
+                }
+
+              /* If no frame thread has been defined for the FLAT
+                 group, define it now. */
+
+              if (flat_thread < 0 && !far16)
+                {
+                  if (frame_thread_index >= 4)
+                    error ("Too many frame threads");
+                  /* THREAD: D=1, METHOD=F1 */
+                  put_8 (0x44 | frame_thread_index);
+                  put_idx (flat_index);
+                  flat_thread = frame_thread_index++;
+                }
+
+              /* If we want to use a target thread and the target
+                 thread is not yet defined, define it now. */
+
+              if (threadp != NULL && *threadp < 0)
+                {
+                  if (target_thread_index >= 4)
+                    error ("Too many target threads");
+                  /* THREAD: D=0, METHOD=T4 */
+                  put_8 (0x10 | target_thread_index);
+                  put_idx (target_index);
+                  *threadp = target_thread_index++;
+                }
+
+              /* Compute and write the locat word. */
+
+              data_off = r->address - off;
+              if (far16)
+                locat = 0x8c;   /* Method 3: 16:16 far pointer */
+              else if (sst_flag && r->length == 1)
+                locat = 0x88;   /* Method 2: selector */
+              else
+                locat = 0xa4;   /* Method 9: 32-bit offset */
+              locat |= ((data_off >> 8) & 0x03);
+              if (!r->pcrel)
+                locat |= 0x40;
+              put_8 (locat);
+              put_8 (data_off);
+
+              /* Write the rest of the FIXUP subrecord. */
+
+              if (far16)
+                {
+                  /* F=0, FRAME=F2, T=0, P=1, TARGT=T2 */
+                  put_8 (0x26);
+                  put_idx (sym_more[r->symbolnum].index);
+                  put_idx (sym_more[r->symbolnum].index);
+                }
+              else if (r->ext)
+                {
+                  /* F=1, FRAME=F1, T=0, P=1, TARGT=T2 */
+                  put_8 (0x86 | (flat_thread << 4));
+                  put_idx (sym_more[r->symbolnum].index);
+                }
+              else
+                {
+                  /* F=1, FRAME=F1, T=1, P=1, TARGT=T4 */
+                  put_8 (0x8c | (flat_thread << 4) | *threadp);
+                }
+            }
+          ++reloc_idx; ++r;
+        }
+      if (started)
+        write_rec ();
+
+      /* Adjust pointers and counters for the next chunk. */
+
+      src += n; off += n; seg_size -= n;
+    }
+
+  /* Deallocate the sorted relocation table. */
+
+  free (reloc_tab);
+}
+
+
+/* Write a default library request record to the output file.  The
+   linker will search the library NAME to resolve external
+   references.  Create a COMENT record of class 0x9f.  The name is
+   stored without leading byte count, the linker gets the length of
+   the name from the record length. */
+
+static void request_lib (const char *name)
+{
+  init_rec (COMENT);
+  put_8 (0x40);
+  put_8 (0x9f);
+  put_mem (name, strlen (name));
+  write_rec ();
+}
+
+
+/* Write default library request records for all the -i options.  The
+   library names are stored in a list.  libreq_head points to the head
+   of the list. */
+
+static void write_libs (void)
+{
+  struct libreq *p;
+
+  for (p = libreq_head; p != NULL; p = p->next)
+    request_lib (p->name);
+}
+
+
+/* Write a record identifying the debug information style to the
+   output file.  The style we use is called HLL version 3.  Create a
+   COMENT record of class 0xa1. */
+
+static void write_debug_style (void)
+{
+  init_rec (COMENT);
+  put_8 (0x80);
+  put_8 (0xa1);                 /* Debug info style */
+  put_8 (3);                    /* Version 3 */
+  put_mem ("HL", 2);            /* HLL style debug tables */
+  write_rec ();
+}
+
+
+/* Write a link pass separator to the output file.  The linker makes
+   two passes through the object modules.  The first pass stops when
+   encountering the link pass separator.  This is used for improving
+   linking speed.  The second pass ignores the link pass separator.
+   The following records must precede the link pass separator: ALIAS,
+   CEXTDEF COMDEF, EXTDEF, GRPDEF, LCOMDEF, LEXTDEF, LNAMES, LPUBDEF,
+   PUBDEF, SEGDEF, TYPDEF, and most of the COMENT classes.  Create a
+   COMENT record of class 0xa2. */
+
+static void write_pass2 (void)
+{
+  init_rec (COMENT);
+  put_8 (0x40);
+  put_8 (0xa2);                 /* Link pass separator */
+  put_8 (0x01);
+  write_rec ();
+}
+
+
+/* Create segment names for all the sets.  It is here where sets are
+   created.  See write_set_data() for details. */
+
+static void define_set_names (void)
+{
+  int i, j;
+  struct set *set_ptr;
+  char tmp[512];
+  const char *name;
+  byte type;
+
+  /* Loop through the symbol table. */
+
+  for (i = 0; i < sym_count; ++i)
+    {
+      type = sym_ptr[i].type & ~N_EXT;
+      if ((type == N_SETA && sym_ptr[i].value == 0xffffffff)
+          || type == N_SETT || type == N_SETD)
+        {
+
+          /* This is a set element.  If type is N_SETA the symbol is
+             the head of the set, otherwise it is an ordinary set
+             element.  Search the table of sets to find out whether
+             this set is already known. */
+
+          name = str_ptr + sym_ptr[i].string;
+          for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
+            if (strcmp (set_ptr->name, name) == 0)
+              break;
+          if (set_ptr == NULL)
+            {
+
+              /* The set is not yet known.  Create a new table
+                 entry. */
+
+              set_ptr = xmalloc (sizeof (struct set));
+              set_ptr->name = xstrdup (name);
+              for (j = 0; j < 3; ++j)
+                {
+                  set_ptr->seg_name[j] = -1;
+                  set_ptr->seg_index[j] = -1;
+                }
+              set_ptr->group_name = -1;
+              set_ptr->count = 0;
+              set_ptr->data = NULL;
+              set_ptr->seg = NULL;
+              set_ptr->def = 0;
+              set_ptr->next = NULL;
+              *set_add = set_ptr;
+              set_add = &set_ptr->next;
+            }
+          else if (type == N_SETA && set_ptr->def)
+            error ("Set `%s' defined more than once", name);
+
+          if (type == N_SETA)
+            set_ptr->def = 1;   /* Write SET1 and SET3 segments */
+          else
+            {
+
+              /* Add the element to the set. */
+
+              ++set_ptr->count;
+              set_ptr->data = xrealloc (set_ptr->data, set_ptr->count * 4);
+              set_ptr->seg = xrealloc (set_ptr->seg, set_ptr->count);
+              set_ptr->data[set_ptr->count-1] = sym_ptr[i].value;
+              set_ptr->seg[set_ptr->count-1]
+                = (type == N_SETT ? N_TEXT : N_DATA);
+            }
+
+          /* Define the OMF segment names for this set, if not yet
+             done. */
+
+          if (set_ptr->seg_name[0] < 0)
+            {
+              strcpy (tmp, "SET#");
+              strcat (tmp, name);
+              for (j = 0; j < 3; ++j)
+                {
+                  tmp[3] = (char)('1' + j);
+                  set_ptr->seg_name[j] = find_lname (tmp);
+                }
+            }
+        }
+    }
+}
+
+
+/* Create the group name with group name index for each set. */
+
+static void define_set_groups (void)
+{
+  struct set *set_ptr;
+  char tmp[512];
+
+  for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
+    {
+      strcpy (tmp, "GROUP");
+      strcat (tmp, set_ptr->name);
+      set_ptr->group_name = find_lname (tmp);
+    }
+}
+
+
+/* Define three segments for each set.  The segment names have already
+   been defined, now write the SEGDEF records. */
+
+static void write_set_segs (void)
+{
+  int j;
+  struct set *set_ptr;
+
+  for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
+    for (j = 0; j < 3; ++j)
+      set_ptr->seg_index[j] =
+        seg_def (set_ptr->seg_name[j], code_class_name,
+                 4 * (j == 1 ? set_ptr->count : set_ptr->def), FALSE);
+}
+
+
+/* Write the GRPDEF records for all the sets.  One group consisting of
+   three segments is defined for each set.
+
+   GRPDEF record:
+    1/2 Group name index
+   Ú
+   ³1   0xff (use segment index)
+   ³1/2 Segment index
+   À
+
+   Group indices are assigned sequentially. */
+
+static void write_set_groups (void)
+{
+  int j;
+  struct set *set_ptr;
+
+  for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
+    {
+      set_ptr->group_index = group_index++;
+      init_rec (GRPDEF);
+      put_idx (set_ptr->group_name);
+      for (j = 0; j < 3; ++j)
+        {
+          put_8 (0xff); put_idx (set_ptr->seg_index[j]);
+        }
+      write_rec ();
+    }
+}
+
+
+/* Write the PUBDEF records for all the sets.  One PUBDEF record is
+   generated for each set, it defines the set name. */
+
+static void write_set_pub (void)
+{
+  struct set *set_ptr;
+
+  for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
+      if (set_ptr->def)
+        {
+          init_rec (force_big ? PUBDEF|REC32 : PUBDEF);
+          put_idx (flat_index);
+          put_idx (set_ptr->seg_index[0]);
+          put_sym (set_ptr->name);
+          if (force_big)
+            put_32 (0);
+          else
+            put_16 (0);
+          put_idx (0);        /* Type index */
+          write_rec ();
+        }
+}
+
+
+/* Write the segment contents for all the sets.  One or three segments
+   are written for each set XXX:
+
+   SET1XXX      long start = -2
+   SET2XXX      long table[]
+   SET3XXX      long end = 0
+
+   SET1XXX and SET3XXX are written only if there is a N_SETA symbol
+   for the set.  The N_SETA symbol defines the start of the set and
+   must have a value of -1 (see crt0.s).  SET2XXX is written for all
+   modules which contain N_SETT or N_SETD symbols.  All three segments
+   belong to the group GROUPXXX.  The linker combines all the segments
+   of GROUPXXX into a single object.  SET1XXX comes first, followed by
+   the SET2XXX segments of all modules of the program, followed by
+   SET3XXX.  That way, we obtain a table of all set elements of a
+   given set, preceded by -2 and terminated by 0.  A symbol XXX is
+   defined which points to the start of SET1XXX.  See
+   /emx/lib/gcc/main.c for code which uses sets. */
+
+static void write_set_data (void)
+{
+  struct set *set_ptr;
+  dword x;
+  int i, max_count;
+  dword *buf;
+  struct reloc *reloc_tab;
+
+  max_count = 0; buf = NULL; reloc_tab = NULL;
+  for (set_ptr = sets; set_ptr != NULL; set_ptr = set_ptr->next)
+    {
+
+      /* Write the first segment.  It consists of a 32-bit word
+         containing the number -2.  This is used by the startup code
+         to detect a delimited set. */
+
+      if (set_ptr->def)
+        {
+          x = 0xfffffffe;
+          write_seg (set_ptr->seg_index[0], set_ptr->seg_name[0],
+                     (byte *)&x, sizeof (x), NULL, 0, FALSE, NULL, 0, -1);
+        }
+
+      /* Write the second segment.  It consists of the set elements as
+         taken from the a.out module.  The elements are assumed to be
+         pointers into the text segment. */
+
+      if (set_ptr->count >= 1)
+        {
+
+          /* Enlarge the relocation table, if required. */
+
+          if (set_ptr->count > max_count)
+            {
+              max_count = set_ptr->count;
+              buf = xrealloc (buf, 4 * max_count);
+              memset (buf, 0, 4 * max_count);
+              reloc_tab = xrealloc (reloc_tab,
+                                    max_count * sizeof (struct reloc));
+            }
+
+          /* Create one relocation table entry for each set
+             element. */
+
+          for (i = 0; i < set_ptr->count; ++i)
+            {
+              buf[i] = set_ptr->data[i];
+              reloc_tab[i].address = i * 4;
+              reloc_tab[i].symbolnum = set_ptr->seg[i];
+              reloc_tab[i].pcrel = 0;
+              reloc_tab[i].length = 2;
+              reloc_tab[i].ext = 0;
+              reloc_tab[i].unused = 0;
+            }
+
+          /* Write the segment data and fixups. */
+
+          write_seg (set_ptr->seg_index[1], set_ptr->seg_name[1],
+                     (byte *)buf, set_ptr->count * 4, reloc_tab,
+                     set_ptr->count * sizeof (struct reloc), FALSE, NULL, 0,
+                     -1);
+        }
+
+      /* Write the third segment.  It consists of a 32-bit word
+         containing the value 0, marking the end of the table. */
+
+      if (set_ptr->def)
+        {
+          x = 0;
+          write_seg (set_ptr->seg_index[2], set_ptr->seg_name[2],
+                     (byte *)&x, sizeof (x), NULL, 0, FALSE, NULL, 0, -1);
+        }
+    }
+  if (buf != NULL)
+    free (buf);
+}
+
+
+/* Find a relocation table entry by fixup address. */
+
+static const struct reloc *find_reloc_fixup (const struct reloc *rel,
+                                             long rel_size, dword addr)
+{
+  int i, count;
+
+  count = rel_size / sizeof (struct reloc);
+  for (i = 0; i < count; ++i)
+    if (rel[i].address == addr)
+      return &rel[i];
+  return NULL;
+}
+
+
+static void free_modstr_cache (void)
+{
+  struct modstr *p1, *p2;
+
+  for (p1 = modstr_cache; p1 != NULL; p1 = p2)
+    {
+      p2 = p1->next;
+      free (p1->symbol);
+      free (p1->str);
+      free (p1);
+    }
+  modstr_cache = NULL;
+}
+
+
+/* Fetch a null-terminated string from a module.  REL points to the
+   relocation table entry of the pointer, ADDR is the pointer.  Copy
+   the string to DST, a buffer of DST_SIZE bytes.  Return TRUE if
+   successful, FALSE on failure. */
+
+static int fetch_modstr (const struct reloc *rel, dword addr,
+                         char *dst, size_t dst_size)
+{
+  const byte *seg_ptr;
+  dword seg_size;
+
+  if (rel == NULL) return FALSE;
+  if (rel->ext)
+    {
+      struct modstr *p;
+      byte *buf;
+      const char *sym_name;
+      const struct nlist *m_sym = NULL;
+      const struct a_out_header *m_ao = NULL;
+
+      /* We have to take the string from another module.  First try to
+         get the string from the cache. */
+
+      sym_name = str_ptr + sym_ptr[rel->symbolnum].string;
+      for (p = modstr_cache; p != NULL; p = p->next)
+        if (strcmp (p->symbol, sym_name) == 0)
+          break;
+      if (p == NULL)
+        {
+          long pos, size, m_str_size;
+          struct ar_hdr ar;
+          byte *t;
+          size_t buf_size, len;
+          const byte *m_str;
+          int i, m_sym_count, found;
+
+          /* Search all modules until finding the symbol. */
+
+          buf = NULL; buf_size = 0; found = FALSE;
+          pos = SARMAG;
+          while (ar_read_header (&ar, pos))
+            {
+              size = ar_member_size (&ar);
+              pos += (sizeof (ar) + size + 1) & -2;
+              if (strcmp (ar.ar_name, "__.SYMDEF") == 0
+                  || strcmp (ar.ar_name, "__.IMPORT") == 0
+                  || memcmp (ar.ar_name, "IMPORT#", 7) == 0)
+                continue;
+              if (size > buf_size)
+                {
+                  if (buf != NULL) free (buf);
+                  buf_size = size;
+                  buf = xmalloc (buf_size);
+                }
+              size = fread (buf, 1, size, inp_file);
+              if (ferror (inp_file))
+                error ("Cannot read `%s'", inp_fname);
+              m_ao = (const struct a_out_header *)buf;
+              if (size < sizeof (struct a_out_header) || m_ao->magic != 0407)
+                break;
+              t = buf + sizeof (struct a_out_header);
+              t += m_ao->text_size; t += m_ao->data_size;
+              t += m_ao->trsize; t += m_ao->drsize;
+              m_sym = (const struct nlist *)t; t += m_ao->sym_size;
+              m_str = t;
+              if (m_str + 4 - buf > size)
+                break;
+              m_str_size = *(long *)m_str;
+              m_sym_count = m_ao->sym_size / sizeof (struct nlist);
+              if (m_str + m_str_size - buf > size)
+                break;
+              for (i = 0; i < m_sym_count; ++i)
+                switch (m_sym[i].type)
+                  {
+                  case N_TEXT|N_EXT:
+                  case N_DATA|N_EXT:
+                    if (strcmp (m_str + m_sym[i].string, sym_name) == 0)
+                      {
+                        m_sym += i; found = TRUE; break;
+                      }
+                  }
+              if (found)
+                break;
+            }
+          if (!found)
+            error ("Symbol `%s' not found", sym_name);
+
+          addr = m_sym->value;
+          switch (m_sym->type)
+            {
+            case N_TEXT|N_EXT:
+              seg_ptr = buf + sizeof (struct a_out_header);
+              seg_size = m_ao->text_size;
+              break;
+            case N_DATA|N_EXT:
+              seg_ptr = buf + sizeof (struct a_out_header) + m_ao->text_size;
+              seg_size = m_ao->data_size;
+              break;
+            default:
+              abort ();
+            }
+
+          len = 0;
+          for (;;)
+            {
+              if (addr + len >= seg_size)
+                error ("String extends beyond end of segment");
+              if (seg_ptr[addr + len] == 0)
+                break;
+              ++len;
+            }
+
+          p = xmalloc (sizeof (struct modstr));
+          p->symbol = xstrdup (sym_name);
+          p->str = xmalloc (len + 1);
+          memcpy (p->str, seg_ptr + addr, len + 1);
+          p->next = modstr_cache;
+          modstr_cache = p;
+          if (buf != NULL) free (buf);
+        }
+      if (strlen (p->str) >= dst_size)
+        return FALSE;
+      strcpy (dst, p->str);
+      return TRUE;
+    }
+  else
+    {
+      dword si;
+
+      switch (rel->symbolnum)
+        {
+        case N_TEXT:
+          seg_ptr = text_ptr;
+          seg_size = text_size;
+          break;
+        case N_DATA:
+          seg_ptr = data_ptr;
+          seg_size = data_size;
+          break;
+        default:
+          return FALSE;
+        }
+      for (si = 0; addr + si < seg_size && si < dst_size; ++si)
+        {
+          dst[si] = seg_ptr[addr + si];
+          if (seg_ptr[addr + si] == 0)
+            return TRUE;
+        }
+      return FALSE;
+    }
+}
+
+
+/* Create an import record and a PUBDEF record. */
+
+static void make_import (const char *pub_name, const char *proc_name,
+                         long ord, const char *mod)
+{
+  /* Skip a leading underscore character if present. */
+
+  if (*pub_name == '_')
+    ++pub_name;
+
+  /* Make the symbol public in the output library. */
+
+  if (omflib_add_pub (out_lib, pub_name, mod_page, lib_errmsg) != 0)
+    error (lib_errmsg);
+
+  /* Write the import definition record. */
+
+  init_rec (COMENT);
+  put_8 (0x00);
+  put_8 (IMPDEF_CLASS);
+  put_8 (IMPDEF_SUBTYPE);
+  put_8 (proc_name == NULL ? 0x01 : 0x00); /* Import by ordinal or by name */
+  put_str (pub_name);           /* Underscore already removed above */
+  put_str (mod);
+  if (proc_name == NULL)
+    put_16 (ord);
+  else if (strcmp (proc_name, pub_name) == 0)
+    put_8 (0);
+  else
+    put_str (proc_name);
+  write_rec ();
+  init_rec (MODEND|REC32);
+  put_8 (0x00);                 /* Non-main module without start address */
+  write_rec ();
+}
+
+
+/* If the input file is an import module (method (I2) as created by
+   emximp), create an OMF-style import module and return TRUE.
+   Otherwise, return FALSE. */
+
+static int handle_import_i2 (void)
+{
+  int i, len1, mod_len;
+  long ord;
+  const char *name1, *name2, *proc_name, *p;
+  char mod[256], *q;
+
+  /* Search the symbol table for N_IMP1 and N_IMP2 symbols.  These are
+     unique to import modules. */
+
+  name1 = NULL; name2 = NULL;
+  for (i = 0; i < sym_count; ++i)
+    switch (sym_ptr[i].type)
+      {
+      case N_IMP1|N_EXT:
+        name1 = str_ptr + sym_ptr[i].string;
+        break;
+      case N_IMP2|N_EXT:
+        name2 = str_ptr + sym_ptr[i].string;
+        break;
+      default:
+        return FALSE;
+      }
+
+  /* If no N_IMP1 and N_IMP2 symbols have been found, the module is
+     not an import module. */
+
+  if (name1 == NULL || name2 == NULL)
+    return FALSE;
+
+  /* Parse the special symbols into module name and ordinal number.
+     name2 should look like
+
+       SYMBOL=MODULE.ORDINAL
+
+     where SYMBOL is name1, MODULE is the module name and ORDINAL is
+     the ordinal number. */
+
+  len1 = strlen (name1);
+  if (memcmp (name1, name2, len1) != 0)
+    error ("Invalid import record: names don't match");
+  name2 += len1;
+  if (*name2 != '=')
+    error ("Invalid import record: missing `='");
+  ++name2;
+  p = strchr (name2, '.');
+  if (p == NULL)
+    error ("Invalid import record: missing `.'");
+  mod_len = p - name2;
+  memcpy (mod, name2, mod_len);
+  mod[mod_len] = 0;
+  proc_name = NULL;
+  errno = 0;
+  ord = strtol (p + 1, &q, 10);
+  if (q != p + 1 && *q == 0 && errno == 0)
+    {
+      if (ord < 1 || ord > 65535)
+        error ("Invalid import record: invalid ordinal");
+    }
+  else
+    {
+      ord = -1;
+      proc_name = p + 1;
+      if (*proc_name == 0)
+        error ("Invalid import record: invalid name");
+    }
+
+  make_import (name1, proc_name, ord, mod);
+  return TRUE;
+}
+
+
+/* If the input file is an import module (method (I1) as created by
+   emximp), create an OMF-style import module and return TRUE.
+   Otherwise, return FALSE. */
+
+static int handle_import_i1 (void)
+{
+  int i;
+  const char *pub_name;
+  char proc_name[257], dll_name[257];
+  long table_off, ord, off;
+  long *table;
+  const struct reloc *rel;
+
+  /* There must be exactly one public symbol (which must defined for
+     N_TEXT), otherwise we cannot safely eliminate all the code.
+     Moreover, there must be an N_SETT|N_EXT entry for `__os2dll'. */
+
+  pub_name = NULL; table_off = -1;
+  for (i = 0; i < sym_count; ++i)
+    switch (sym_ptr[i].type)
+      {
+      case N_TEXT|N_EXT:
+        if (pub_name != NULL) return FALSE;
+        pub_name = str_ptr + sym_ptr[i].string;
+        break;
+
+      case N_DATA|N_EXT:
+      case N_BSS|N_EXT:
+        return FALSE;
+
+      case N_SETT|N_EXT:
+        if (strcmp (str_ptr + sym_ptr[i].string, "__os2dll") != 0)
+          return FALSE;
+        table_off = sym_ptr[i].value;
+        break;
+      }
+
+  if (pub_name == NULL || table_off == -1)
+    return FALSE;
+
+  /* The table must be completely present. */
+
+  if (table_off < 0 || table_off + 4 * 4 > text_size)
+    error ("Invalid import table: beyond end of segment");
+
+  /* Fetch the procedure name or the ordinal. */
+
+  table = (long *)(text_ptr + table_off);
+  if (table[0] == 0)
+    {
+      ord = 0;
+
+      /* Check and fetch the procedure name. */
+
+      rel = find_reloc_fixup (text_rel, a_out_h->trsize, table_off + 3 * 4);
+      if (!fetch_modstr (rel, table[3], proc_name, sizeof (proc_name)))
+        error ("Invalid import table: invalid pointer to procedure name");
+    }
+  else if (table[0] == 1)
+    {
+      ord = table[3];
+      if (ord < 1 || ord > 65535)
+        error ("Invalid import table: invalid ordinal number");
+    }
+  else
+    error ("Invalid import table: invalid flag");
+
+  /* Check the fixup address -- there must be a JMP instruction. */
+
+  off = table[1];
+  if (off < 1 || off + 4 > text_size)
+    error ("Invalid import table: invalid fixup address");
+  if (text_ptr[off-1] != 0xe9)
+    error ("Invalid import table: fixup does not belong to a JMP instruction");
+
+  /* Check and fetch the module name. */
+
+  rel = find_reloc_fixup (text_rel, a_out_h->trsize, table_off + 2 * 4);
+  if (!fetch_modstr (rel, table[2], dll_name, sizeof (dll_name)))
+    error ("Invalid import table: invalid pointer to module name");
+
+  make_import (pub_name, ord != 0 ? NULL : proc_name, ord, dll_name);
+  return TRUE;
+}
+
+
+/* Convert a filename from Unix format to OS/2 format.  All that has
+   to be done is replacing slashes with backslashes as IPMD doesn't
+   like slashes in file names.  The conversion is done in place. */
+
+static void convert_filename (char *name)
+{
+  while (*name != 0)
+    {
+      if (*name == '/')
+        *name = '\\';
+      ++name;
+    }
+}
+
+
+/* Derive the module name and store it to the mod_name variable.
+   Search the symbol table for an N_SO symbol.  If there is no such
+   symbol, use the output file name. */
+
+static void get_mod_name (void)
+{
+  int i, len, ok;
+  const char *p1, *p2;
+
+  ok = FALSE;
+  for (i = 0; i < sym_count; ++i)
+    if (sym_ptr[i].type == N_SO)
+      {
+        p1 = str_ptr + sym_ptr[i].string;
+        len = strlen (p1);
+        if (len > 0 && p1[len-1] != '/')
+          {
+            ok = TRUE;
+            _strncpy (mod_name, p1, sizeof (mod_name));
+            convert_filename (mod_name);
+            break;
+          }
+      }
+  if (!ok && out_lib == NULL)
+    {
+      p1 = out_fname;
+      for (p2 = p1; *p2 != 0; ++p2)
+        if (*p2 == '/' || *p2 == '\\' || *p2 == ':')
+          p1 = p2 + 1;
+      _strncpy (mod_name, p1, sizeof (mod_name));
+    }
+}
+
+
+/* Write the translator module header record.  When creating a .LIB
+   file, this function does nothing.  Otherwise, the module name is
+   expected in the mod_name variable. */
+
+static void write_theadr (void)
+{
+  if (out_lib == NULL)
+    {
+      init_rec (THEADR);
+      put_str (mod_name);
+      write_rec ();
+    }
+}
+
+/* Tell LINK386 what identifier manipulator DLL to call.  The name of
+   the DLL is given by `idmdll_name', the default value of which is
+   GPPDEMID.  The name can be changed with the -I option.  If -I- is
+   given, no IDMDLL record will be written.  The IDMDLL record will
+   also be suppressed if the program hasn't been compiled by the GNU
+   C++ compiler. */
+
+static void write_idmdll ()
+{
+  if (idmdll_name != NULL && find_symbol ("__gnu_compiled_cplusplus") != NULL)
+    {
+      init_rec (COMENT);
+      put_8 (0x00);
+      put_8 (0xaf);
+      put_str (idmdll_name);
+      put_str ("");             /* Initialization parameter */
+      write_rec ();
+    }
+}
+
+
+/* Find a file name for creating line number information. */
+
+static int file_find (const char *name)
+{
+  int i;
+
+  for (i = 0; i < file_grow.count; ++i)
+    if (strcmp (file_list[i], name) == 0)
+      return i;
+  if (file_grow.count >= 255)
+    {
+      warning ("Too many source files, cannot convert line number info");
+      return file_grow.count;
+    }
+  grow_by (&file_grow, 1);
+  i = file_grow.count++;
+  file_list[i] = xstrdup (name);
+  return i;
+}
+
+
+/* This function is passed to qsort() for sorting line numbers.  X1
+   and X2 point to struct line structures.  Line number entries are
+   sorted by address, file and line number. */
+
+static int line_compare (const void *x1, const void *x2)
+{
+  dword a1, a2;
+  int i1, i2;
+
+  a1 = ((const struct line *)x1)->addr;
+  a2 = ((const struct line *)x2)->addr;
+  if (a1 < a2)
+    return -1;
+  else if (a1 > a2)
+    return 1;
+  i1 = ((const struct line *)x1)->file_index;
+  i2 = ((const struct line *)x2)->file_index;
+  if (i1 < i2)
+    return -1;
+  else if (i1 > i2)
+    return 1;
+  i1 = ((const struct line *)x1)->line;
+  i2 = ((const struct line *)x2)->line;
+  if (i1 < i2)
+    return -1;
+  else if (i1 > i2)
+    return 1;
+  return 0;
+}
+
+
+/* Write line number information to the output file.  Unfortunately,
+   the line number information format currently used by IPMD is not
+   documented.  This code is based on experimentation. */
+
+static void write_linnum (void)
+{
+  int i, started, len, file_index;
+  int valid_lines;
+  struct line *line_list;
+  struct grow line_grow;
+  char buf[256];
+
+  /* Initialize growing arrays for file names and line numbers. */
+
+  grow_init (&file_grow, &file_list, sizeof (*file_list), 8);
+  grow_init (&line_grow, &line_list, sizeof (*line_list), 64);
+
+  /* Define file index for main source file. */
+
+  file_index = file_find (mod_name);
+  started = FALSE;
+
+  /* Go through the symbol table, defining line numbers and additional
+     source files. */
+
+  for (i = 0; i < sym_count; ++i)
+    switch (sym_ptr[i].type)
+      {
+      case N_SOL:
+        file_index = file_find (str_ptr + sym_ptr[i].string);
+        break;
+      case N_SLINE:
+        grow_by (&line_grow, 1);
+        line_list[line_grow.count].file_index = file_index;
+        line_list[line_grow.count].line = sym_ptr[i].desc;
+        line_list[line_grow.count].addr = sym_ptr[i].value;
+        ++line_grow.count;
+      }
+
+  /* Sort the line numbers by address, file and line number. */
+
+  qsort (line_list, line_grow.count, sizeof (*line_list), line_compare);
+
+  /* If there are multiple line numbers assigned to the same address,
+     keep but the last line number.  Delete line numbers by setting
+     the line number to -1. */
+
+  for (i = 0; i < line_grow.count - 1; ++i)
+    if (line_list[i].line >= 0 && line_list[i+1].line >= 0
+        && line_list[i].addr == line_list[i+1].addr)
+      line_list[i].line = -1;
+
+  /* Count the number of valid line numbers, that is, non-negative
+     line numbers. */
+
+  valid_lines = 0;
+  for (i = 0; i < line_grow.count; ++i)
+    if (line_list[i].line >= 0)
+      ++valid_lines;
+
+  /* Compute the size of the file names table. */
+
+  len = 3 * 4;
+  for (i = 0; i < file_grow.count; ++i)
+    len += 1 + strlen (file_list[i]);
+
+  /* Write the line number table. */
+
+  init_rec (LINNUM|REC32);
+  started = TRUE;
+  put_idx (0);                  /* Base Group */
+  put_idx (text_index);         /* Base Segment */
+
+  put_16 (0);                   /* Line number = 0 (special entry) */
+  put_8 (0);                    /* Entry type: source and offset */
+  put_8 (0);                    /* Reserved */
+  put_16 (valid_lines);         /* Count of line number entries */
+  put_16 (0);                   /* Segment number */
+  put_32 (len);                 /* Size of file names table */
+
+  for (i = 0; i < line_grow.count; ++i)
+    if (line_list[i].line >= 0)
+      {
+        if (started && !fits (8))
+          {
+            write_rec ();
+            started = FALSE;
+          }
+        if (!started)
+          {
+            init_rec (LINNUM|REC32);
+            put_idx (0);          /* Base Group */
+            put_idx (text_index); /* Base Segment */
+            started = TRUE;
+          }
+        put_16 (line_list[i].line);
+        put_16(line_list[i].file_index + 1);
+        put_32 (line_list[i].addr);
+      }
+
+  /* Now write the file names table. */
+
+  if (started && !fits (12))
+    {
+      write_rec ();
+      started = FALSE;
+    }
+  if (!started)
+    {
+      init_rec (LINNUM|REC32);
+      put_idx (0);          /* Base Group */
+      put_idx (text_index); /* Base Segment */
+      started = TRUE;
+    }
+  put_32 (0);                   /* First column */
+  put_32 (0);                   /* Number of columns */
+  put_32 (file_grow.count);     /* Number of source and listing files */
+
+  for (i = 0; i < file_grow.count; ++i)
+    {
+      len = strlen (file_list[i]);
+      if (len > sizeof (buf) - 1)
+        len = sizeof (buf) - 1;
+      memcpy (buf, file_list[i], len);
+      buf[len] = 0;
+      convert_filename (buf);
+      if (started && !fits (1 + len))
+        {
+          write_rec ();
+          started = FALSE;
+        }
+      if (!started)
+        {
+          init_rec (LINNUM|REC32);
+          put_idx (0);          /* Base Group */
+          put_idx (text_index); /* Base Segment */
+          started = TRUE;
+        }
+      put_8 (len);
+      put_mem (buf, len);
+    }
+
+  if (started)
+    write_rec ();
+
+  grow_free (&line_grow);
+  grow_free (&file_grow);
+}
+
+
+/* Print unknown symbol table entries (-u option). */
+
+static void list_unknown_stabs (void)
+{
+  int i;
+
+  for (i = 0; i < sym_count; ++i)
+    switch (sym_ptr[i].type)
+      {
+      case 0:       case 0     |N_EXT:
+      case N_ABS:   case N_ABS |N_EXT:
+      case N_TEXT:  case N_TEXT|N_EXT:
+      case N_DATA:  case N_DATA|N_EXT:
+      case N_BSS:   case N_BSS |N_EXT:
+                    case N_INDR|N_EXT:
+                    case N_WEAKU:
+      case N_SETA:  case N_SETA|N_EXT:
+      case N_SETT:  case N_SETT|N_EXT:
+      case N_SETD:  case N_SETD|N_EXT:
+      case N_GSYM:
+      case N_FUN:
+      case N_STSYM:
+      case N_LCSYM:
+      case N_RSYM:
+      case N_SLINE:
+      case N_SO:
+                    case N_IMP1|N_EXT:
+                    case N_IMP2|N_EXT:
+      case N_LSYM:
+      case N_SOL:
+      case N_PSYM:
+      case N_LBRAC:
+      case N_RBRAC:
+        break;
+      default:
+        fprintf (stderr, "Unknown symbol table entry: 0x%.2x \"%s\"\n",
+                 sym_ptr[i].type, str_ptr + sym_ptr[i].string);
+        break;
+      }
+}
+
+/* Convert an a.out module to an OMF module.  SIZE is the number of
+   bytes in the input file inp_file. */
+
+static void o_to_omf (long size)
+{
+  byte *t;
+  const struct nlist *entry_symbol;
+  int i;
+
+  /* Simplify things by reading the complete a.out module into
+     memory. */
+
+  inp_buf = xmalloc (size);
+  size = fread (inp_buf, 1, size, inp_file);
+  if (ferror (inp_file))
+    goto read_error;
+
+  /* Set up pointers to various sections of the module read into
+     memory. */
+
+  a_out_h = (struct a_out_header *)inp_buf;
+  if (size < sizeof (struct a_out_header) || a_out_h->magic != 0407)
+    error ("Input file `%s' is not an a.out file", error_fname);
+  text_size = a_out_h->text_size;
+  data_size = a_out_h->data_size;
+  t = inp_buf + sizeof (struct a_out_header);
+  text_ptr = t; t += text_size;
+  data_ptr = t; t += data_size;
+  text_rel = (const struct reloc *)t; t += a_out_h->trsize;
+  data_rel = (const struct reloc *)t; t += a_out_h->drsize;
+  sym_ptr = (const struct nlist *)t; t += a_out_h->sym_size;
+  str_ptr = t;
+  if (a_out_h->sym_size == 0)
+    str_size = 0;
+  else
+    {
+      if (str_ptr + 4 - inp_buf > size)
+        goto invalid;
+      str_size = *(long *)str_ptr;
+    }
+  sym_count = a_out_h->sym_size / sizeof (struct nlist);
+  if (str_ptr + str_size - inp_buf > size)
+    goto invalid;
+
+  /* Build the complementary array of symbol data. */
+
+  sym_more = xmalloc (sym_count * sizeof (struct symbol));
+  for (i = 0; i < sym_count; ++i)
+    {
+      sym_more[i].index = 0;
+      sym_more[i].flags = 0;
+    }
+
+  /* Print unknown symbol table entries if the -u option is given. */
+
+  if (unknown_stabs)
+    list_unknown_stabs ();
+
+  /* Find the start symbol if converting a main module. */
+
+  if (entry_name != NULL)
+    {
+      entry_symbol = find_symbol (entry_name);
+      if (entry_symbol == NULL)
+        error ("Entry symbol not found");
+      if ((entry_symbol->type & ~N_EXT) != N_TEXT)
+        error ("Entry symbol not in text segment");
+    }
+  else
+    entry_symbol = NULL;        /* keep the compiler happy */
+
+  /* Initialize variables for a new OMF module. */
+
+  init_obj ();
+
+  /* If the a.out module is an import module as created by emximp,
+     create an OMF import module.  Everything is done by
+     handle_import_i2() or handle_import_i1() in that case, therefore
+     we can simply return. */
+
+  if (out_lib != NULL && (handle_import_i2 () || handle_import_i1 ()))
+    return;
+
+  /* Initialize growing arrays for debug information conversion.
+     These two arrays contain indices at which the $$SYMBOLS and
+     $$TYPES segments, respectively, can be split into LEDATA records
+     by write_seg(). */
+
+  grow_init (&sst_boundary_grow, &sst_boundary, sizeof (*sst_boundary), 32);
+  grow_init (&tt_boundary_grow, &tt_boundary, sizeof (*tt_boundary), 32);
+
+  /* Create some OMF names. */
+
+  ovl_name = find_lname ("");
+  text_seg_name = find_lname ("TEXT32");
+  data_seg_name = find_lname ("DATA32");
+  bss_seg_name = find_lname ("BSS32");
+  if (udat_seg_string != NULL)
+    udat_seg_name = find_lname (udat_seg_string);
+  else
+    udat_seg_name = data_seg_name;
+  if (!strip_symbols)
+    {
+      symbols_seg_name = find_lname ("$$SYMBOLS");
+      types_seg_name = find_lname ("$$TYPES");
+    }
+  code_class_name = find_lname ("CODE");
+  data_class_name = find_lname ("DATA");
+  bss_class_name = find_lname ("BSS");
+  if (!strip_symbols)
+    {
+      debsym_class_name = find_lname ("DEBSYM");
+      debtyp_class_name = find_lname ("DEBTYP");
+    }
+  define_set_names ();
+  if (mod_type == MT_MAIN)
+    {
+      stack_seg_name = find_lname ("STACK");
+      stack_class_name = find_lname ("STACK");
+    }
+  flat_group_name = find_lname ("FLAT");
+  dgroup_group_name = find_lname ("DGROUP");
+  if (do_set_groups)
+    define_set_groups ();
+
+  /* Write the THREADR record. */
+
+  get_mod_name ();
+  write_theadr ();
+
+  /* Tell LINK386 what identifier manipulator DLL to use. */
+
+  write_idmdll ();
+
+  /* Write default library requests and the debug information style
+     record (COMENT records). */
+
+  write_libs ();
+  write_debug_style ();
+
+  /* Define all the OMF names (LNAMES record).  Of course, we must not
+     define new OMF names after this point. */
+
+  write_lnames ();
+
+  /* Define segments (SEGDEF records).  This must be done after
+     defining the names and before defining the groups. */
+
+  text_index = seg_def (text_seg_name, code_class_name, text_size,
+                        FALSE);
+  write_set_segs ();
+
+  if (udat_seg_string != NULL)
+    udat_index = seg_def (udat_seg_name, data_class_name, data_size,
+                          FALSE);
+  data_index = seg_def (data_seg_name, data_class_name,
+                        (udat_seg_string == NULL ? data_size : 0),
+                        FALSE);
+  if (udat_seg_string == NULL)
+    udat_index = data_index;
+
+  bss_index = seg_def (bss_seg_name, bss_class_name, a_out_h->bss_size,
+                       FALSE);
+
+  if (mod_type == MT_MAIN)
+    stack_index = seg_def (stack_seg_name, stack_class_name, 0x8000, TRUE);
+
+  if (!strip_symbols)
+    {
+      convert_debug ();         /* After seg_def of text, data & bss */
+      symbols_index = seg_def (symbols_seg_name, debsym_class_name,
+                               sst.size, FALSE);
+      types_index = seg_def (types_seg_name, debtyp_class_name,
+                             tt.size, FALSE);
+    }
+
+  /* Define groups (GRPDEF records).  This must be done after defining
+     segments. */
+
+  flat_index = group_index++;
+  init_rec (GRPDEF);
+  put_idx (flat_group_name);
+  write_rec ();
+
+  dgroup_index = group_index++;
+  init_rec (GRPDEF);
+  put_idx (dgroup_group_name);
+  put_8 (0xff); put_idx (bss_index);
+  put_8 (0xff); put_idx (data_index);
+  write_rec ();
+
+  if (do_set_groups)
+    write_set_groups ();
+
+  /* Define external, communal and public symbols (EXTDEF, WKEXT,
+     COMDEF, PUBDEF, and ALIAS records).  This must be done after
+     defining the groups. */
+
+  write_extdef ();
+  write_wkext ();
+  write_comdef ();
+  write_pubdef ();
+  write_set_pub ();
+  write_alias ();
+
+  /* Write link pass separator. */
+
+  write_pass2 ();
+
+  /* Write segment contents (LEDATA and FIXUPP records) and line
+     number information (LINNUM record). */
+
+  write_seg (text_index, text_seg_name, text_ptr, text_size,
+             text_rel, a_out_h->trsize, FALSE, NULL, 0, N_TEXT);
+  write_seg (udat_index, udat_seg_name, data_ptr, data_size,
+             data_rel, a_out_h->drsize, FALSE, NULL, 0, N_DATA);
+
+  write_set_data ();
+
+  if (!strip_symbols)
+    {
+      write_seg (types_index, types_seg_name, tt.buf, tt.size, NULL, 0, FALSE,
+                 tt_boundary, tt_boundary_grow.count, -1);
+      write_seg (symbols_index, symbols_seg_name, sst.buf, sst.size,
+                 (const struct reloc *)sst_reloc.buf, sst_reloc.size, TRUE,
+                 sst_boundary, sst_boundary_grow.count, -1);
+      write_linnum ();
+    }
+
+  /* End of module. */
+
+  init_rec (MODEND|REC32);
+  if (entry_name != NULL)
+    {
+      put_8 (0xc1);             /* Main module with start address */
+      put_8 (0x50);             /* ENDDAT: F5, T0 */
+      put_idx (text_index);
+      put_32 (entry_symbol->value);
+    }
+  else
+    put_8 (0x00);               /* Non-main module without start address */
+  write_rec ();
+
+  /* Clean up memory. */
+
+  free_lnames ();
+  free (inp_buf);
+  free (sym_more);
+  buffer_free (&tt);
+  buffer_free (&sst);
+  buffer_free (&sst_reloc);
+  grow_free (&sst_boundary_grow);
+  grow_free (&tt_boundary_grow);
+  return;
+
+read_error:
+  error ("Cannot read `%s'", error_fname);
+
+invalid:
+  error ("Malformed a.out file `%s'", error_fname);
+}
+
+
+/* Display some hints on using this program, then quit. */
+
+static void usage (void)
+{
+  puts ("emxomf " VERSION " -- Copyright (c) 1992-1995 by Eberhard Mattes\n");
+  puts ("Usage:");
+  puts ("  emxomf [-dgqs] [-l[<symbol>]] [-m <symbol>] [-p <page_size>]");
+  puts ("         [-i <default_lib>] [-I <idmdll>] [-D <dataseg>]");
+  puts ("         -o <output_file> <input_file>");
+  puts ("  emxomf [-dgqsx] [-l[<symbol>]] [-m <symbol>] [-p <page_size>]");
+  puts ("         [-O <directory>] [-r|R <response_file>] [-i <default_lib>]");
+  puts ("         [-I <idmdll>] [-D <dataseg>] <input_file>...");
+  puts ("\nOptions:");
+  puts ("  -d                 Delete input files except for archives");
+  puts ("  -g                 Create groups for sets");
+  puts ("  -i <default_lib>   Add default library request");
+  puts ("  -l[<symbol>]       Convert library modules, with optional entrypoint");
+  puts ("  -m <symbol>        Convert main module with entrypoint <symbol>");
+  puts ("  -o <output_file>   Write output to <output_file>");
+  puts ("  -p <page_size>     Set page size for LIB files");
+  puts ("  -q                 Suppress certain warnings");
+  puts ("  -r <response_file> Write response file for adding modules");
+  puts ("  -R <response_file> Write response file for replacing modules");
+  puts ("  -s                 Strip debugging information");
+  puts ("  -u                 List symbol table entries unknown to emxomf");
+  puts ("  -x                 Extract archive members");
+  puts ("  -D <dataseg>       Change the name of the data segment");
+  puts ("  -I <idmdll>        Name the identifier manipulation DLL");
+  puts ("  -O <directory>     Extract files to <directory>");
+  exit (1);
+}
+
+
+/* Create the output file.  If the -r or -R option is used, create the
+   LIB resonse file. */
+
+static void open_output (void)
+{
+  char *tmp, *p;
+
+  out_file = fopen (out_fname, "wb");
+  if (out_file == NULL)
+    error ("Cannot create output file `%s'", out_fname);
+  if (response_file != NULL)
+    {
+      if (response_first)
+        response_first = FALSE;
+      else
+        fprintf (response_file, " &\n");
+      tmp = alloca (strlen (out_fname) + 1);
+      strcpy (tmp, out_fname);
+      for (p = tmp; *p != 0; ++p)
+        if (*p == '/')
+          *p = '\\';
+      fprintf (response_file, "%s %s", (response_replace ? "-+" : "+"), tmp);
+    }
+}
+
+
+/* Close the output file.  Display an error message and quit on
+   failure. */
+
+static void close_output (void)
+{
+  if (fflush (out_file) != 0 || fclose (out_file) != 0)
+    {
+      out_file = NULL;
+      error ("Write error on output file `%s'", out_fname);
+    }
+  out_file = NULL;
+}
+
+
+/* Define or build the name of the output file.  If DST_FNAME is not
+   NULL, use it as name of the output file.  Otherwise, build the name
+   from INP_FNAME (the input file name) and EXT (the extension).  If
+   an output directory has been specified with the -O option, remove
+   the directory part of INP_FNAME and use output_dir instead. */
+
+static void make_out_fname (const char *dst_fname, const char *inp_fname,
+                            const char *ext)
+{
+  static char tmp1[MAXPATHLEN+3];
+  char tmp2[MAXPATHLEN+3];
+
+  if (dst_fname == NULL)
+    {
+      if (*output_dir != 0)
+        _splitpath (inp_fname, NULL, NULL, tmp2, NULL);
+      else
+        _strncpy (tmp2, inp_fname, MAXPATHLEN);
+      if (strlen (output_dir) + strlen (tmp2) + 5 > MAXPATHLEN)
+        error ("File name `%s' too long", inp_fname);
+      strcpy (tmp1, output_dir);
+      strcat (tmp1, tmp2);
+      _remext (tmp1);
+      strcat (tmp1, ext);
+      out_fname = tmp1;
+    }
+  else
+    out_fname = dst_fname;
+}
+
+
+/* Read the header of an archive member at file position POS.  Return
+   FALSE when reaching the end of the file. */
+
+static int ar_read_header (struct ar_hdr *dst, long pos)
+{
+  int size, i;
+
+  fseek (inp_file, pos, SEEK_SET);
+  size = fread  (dst, 1, sizeof (struct ar_hdr), inp_file);
+  if (size == 0)
+    return FALSE;
+  else if (size != sizeof (struct ar_hdr))
+    error ("Malformed archive `%s'", inp_fname);
+
+  /* Remove trailing blanks from the member name. */
+
+  i = sizeof (dst->ar_name) - 1;
+  while (i > 0 && dst->ar_name[i-1] == ' ')
+    --i;
+  dst->ar_name[i] = 0;
+  return TRUE;
+}
+
+
+/* Retrieve the size from the header of an archive member. */
+
+static long ar_member_size (const struct ar_hdr *p)
+{
+  long size;
+  char *e;
+
+  errno = 0;
+  size = strtol (p->ar_size, &e, 10);
+  if (e == p->ar_size || errno != 0 || size <= 0 || *e != ' ')
+    error ("Malformed archive header in `%s'", inp_fname);
+  return size;
+}
+
+
+/* Convert the a.out file SRC_FNAME to an OMF file named DST_FNAME.
+   If DST_FNAME is NULL, the output file name is derived from
+   SRC_FNAME. */
+
+static void convert (const char *src_fname, const char *dst_fname)
+{
+  char tmp1[MAXPATHLEN+3], tmp2[MAXPATHLEN+3];
+  char *p = NULL, *name, *end;
+  long size, index;
+  static char ar_magic[SARMAG+1] = ARMAG;
+  char ar_test[SARMAG];
+  struct ar_hdr ar;
+  long ar_pos;
+  struct delete *del;
+  char *long_names = NULL;
+  size_t long_names_size = 0;
+
+  inp_fname = src_fname;
+  error_fname = inp_fname;
+  mod_name[0] = 0;
+  inp_file = fopen (inp_fname, "rb");
+  if (inp_file == NULL)
+    error ("Cannot open input file `%s'", inp_fname);
+
+  /* Read some bytes from the start of the file to find out whether
+     this is an archive (.a) file or not. */
+
+  if (fread (ar_test, sizeof (ar_test), 1, inp_file) != 1)
+    error ("Cannot read input file `%s'", inp_fname);
+
+  /* Create a LIB response file if requested and not yet done. */
+
+  if (response_fname != NULL && response_file == NULL)
+    {
+      response_file = fopen (response_fname, "wt");
+      if (response_file == NULL)
+        error ("Cannot create response file `%s'", response_fname);
+    }
+
+  /* The rest of this function (save closing the input file) depends
+     on whether the input file is an archive or not. */
+
+  if (memcmp (ar_test, ar_magic, SARMAG) == 0)
+    {
+
+      /* The input file is an archive.  We cannot procede if the user
+         has specified an output file name and wants one OMF file to
+         be written for each module in the archive (well, we could do
+         it if there's exactly one module in the archive, but we
+         don't). */
+
+      if (dst_fname != NULL && opt_x)
+        error ("Cannot process archive if -o and -x are used");
+      ar_pos = SARMAG;
+
+      /* Create an OMF library file (.LIB file) if the -x option is
+         not given. */
+
+      if (!opt_x)
+        {
+          make_out_fname (dst_fname, inp_fname, ".lib");
+          out_lib = omflib_create (out_fname, page_size, lib_errmsg);
+          if (out_lib == NULL)
+            error (lib_errmsg);
+          if (omflib_header (out_lib, lib_errmsg) != 0)
+            error (lib_errmsg);
+        }
+
+      /* Loop over all the members of the archive. */
+
+      while (ar_read_header (&ar, ar_pos))
+        {
+          /* Decode the header. */
+
+          size = ar_member_size (&ar);
+          ar_pos += (sizeof (ar) + size + 1) & -2;
+
+          if (strcmp (ar.ar_name, "ARFILENAMES/") == 0)
+            {
+              size_t i;
+
+              /* The "ARFILENAMES/" member contains the long file
+                 names, each one is terminated with a newline
+                 character.  Member names starting with a space are
+                 also considered long file names because a leading
+                 space is used for names pointing into the
+                 "ARFILENAMES/" table.  Read the "ARFILENAMES/" member
+                 to LONG_NAMES. */
+
+              if (size != 0)
+                {
+                  long_names_size = (size_t)size;
+                  long_names = xmalloc (long_names_size);
+                  size = fread (long_names, 1, long_names_size, inp_file);
+                  if (ferror (inp_file))
+                    error ("Cannot read `%s'", inp_fname);
+                  if (size != long_names_size)
+                    error ("%s: ARFILENAMES/ member is truncated", inp_fname);
+
+                  /* Replace the newlines with nulls to make
+                     processing a bit more convenient. */
+
+                  for (i = 0; i < long_names_size; ++i)
+                    if (long_names[i] == '\n')
+                      long_names[i] = 0;
+                  if (long_names[long_names_size-1] != 0)
+                    error ("%s: ARFILENAMES/ member corrupt", inp_fname);
+                }
+            }
+          
+          /* Ignore the __.SYMDEF and __.IMPORT members.  Ignore
+             import modules unless creating a library file. */
+
+          else if (strcmp (ar.ar_name, "__.SYMDEF") != 0
+                   && strcmp (ar.ar_name, "__.IMPORT") != 0
+                   && (memcmp (ar.ar_name, "IMPORT#", 7) != 0 || !opt_x))
+            {
+
+              /* Convert the current member to OMF.  First, fetch the
+                 name of the member.  If the ar_name starts with a
+                 space, the decimal number following that space is an
+                 offset into the "ARFILENAMES/" member.  The number
+                 may be followed by a space and a substring of the
+                 long file name. */
+
+              name = ar.ar_name;
+              if (name[0] == ' ' && long_names != NULL
+                  && (index = strtol (name + 1, &end, 10)) >= 0
+                  && index < long_names_size - 1
+                  && (*end == 0 || *end == ' ')
+                  && (index == 0 || long_names[index-1] == 0))
+                name = long_names + index;
+
+              /* Extract the base name of the member. */
+
+              _splitpath (name, NULL, NULL, tmp2, NULL);
+              if (strlen (output_dir) + strlen (tmp2) + 5 > MAXPATHLEN)
+                error ("File name `%s' too long", tmp2);
+
+              /* Provide for informative error message.  Memory leak. */
+
+              p = xmalloc (strlen (inp_fname) + 3 + strlen (name));
+              sprintf (p, "%s(%s)", inp_fname, name);
+              error_fname = p;
+
+              /* Construct the module name for the THREADR record
+                 etc. */
+
+              _strncpy (mod_name, tmp2, sizeof (mod_name));
+              strcat (tmp2, ".obj");
+
+              /* Create the output file (-x option) or add a new
+                 module to the output library (no -x option). */
+
+              if (opt_x)
+                {
+                  strcpy (tmp1, output_dir);
+                  strcat (tmp1, tmp2);
+                  out_fname = tmp1;
+                  open_output ();
+                }
+              else
+                {
+                  if (omflib_write_module (out_lib, tmp2, &mod_page,
+                                           lib_errmsg) != 0)
+                    error (lib_errmsg);
+                }
+
+              /* Convert the member and close the output file. */
+
+              o_to_omf (size);
+              if (opt_x)
+                close_output ();
+            }
+          if (p != NULL) free (p);
+        }
+
+      /* Finish and close the library library if creating a library
+         file. */
+
+      if (!opt_x)
+        {
+          if (omflib_finish (out_lib, lib_errmsg) != 0
+              || omflib_close (out_lib, lib_errmsg) != 0)
+            error (lib_errmsg);
+          out_lib = NULL;
+        }
+    }
+  else
+    {
+
+      /* The input file is not an archive.  We assume it being an
+         a.out object file.  Get the size of the file for
+         o_to_omf(). */
+
+      if (fseek (inp_file, 0L, SEEK_END) != 0)
+        error ("Input file `%s' is not seekable", inp_fname);
+      size = ftell (inp_file);
+      fseek (inp_file, 0L, SEEK_SET);
+
+      /* Convert the file. */
+
+      make_out_fname (dst_fname, inp_fname, ".obj");
+      open_output ();
+      o_to_omf (size);
+      close_output ();
+
+      /* If input files are to be deleted (-d option), add the current
+         input file to the list of files to be deleted. */
+
+      if (delete_input_files)
+        {
+          del = xmalloc (sizeof (struct delete));
+          del->name = xstrdup (inp_fname);
+          del->next = files_to_delete;
+          files_to_delete = del;
+        }
+    }
+  fclose (inp_file);
+  free_modstr_cache ();
+  if (long_names != NULL)
+    free (long_names);
+}
+
+
+/* Delete all the files stored in the FILES_TO_DELETE list.  While
+   deleting the files, the list elements are deallocated. */
+
+static void delete_files (void)
+{
+  struct delete *p, *q;
+
+  for (p = files_to_delete; p != NULL; p = q)
+    {
+      q = p->next;
+      remove (p->name);
+      free (p->name);
+      free (p);
+    }
+}
+
+
+/* Main function of emxomf.  Parse the command line and perform the
+   requested actions. */
+
+int main (int argc, char *argv[])
+{
+  int c, i;
+  char *opt_o, *opt_O, *tmp;
+  struct libreq *lrp;
+
+  /* Keep emxomf in memory for the number of minutes indicated by the
+     GCCLOAD environment variable. */
+
+  _emxload_env ("GCCLOAD");
+
+  /* Get options from the EMXOMFOPT environment variable, expand
+     response files (@filename) and wildcard (*.o) on the command
+     line. */
+
+  _envargs (&argc, &argv, "EMXOMFOPT");
+  _response (&argc, &argv);
+  _wildcard (&argc, &argv);
+
+  /* Set default values of some options. */
+
+  opt_o = NULL; opt_O = NULL;
+  opterr = FALSE;
+
+  /* Parse the command line options. */
+
+  while ((c = getopt (argc, argv, "bdD:gi:I:m:l::o:p:qO:r:R:sux")) != EOF)
+    switch (c)
+      {
+      case 'b':
+        force_big = TRUE;
+        break;
+      case 'd':
+        delete_input_files = TRUE;
+        break;
+      case 'D':
+        udat_seg_string = optarg;
+        break;
+      case 'g':
+        do_set_groups = TRUE;
+        break;
+      case 'i':
+        lrp = xmalloc (sizeof (*lrp));
+        lrp->next = NULL;
+        lrp->name = xstrdup (optarg);
+        *libreq_add = lrp;
+        libreq_add = &lrp->next;
+        break;
+      case 'I':
+        if (strcmp (optarg, "-") == 0)
+          idmdll_name = NULL;
+        else
+          idmdll_name = optarg;
+        break;
+      case 'l':
+        if (mod_type != MT_MODULE)
+          usage ();
+        mod_type = MT_LIB;
+        entry_name = optarg;
+        break;
+      case 'm':
+        if (mod_type != MT_MODULE)
+          usage ();
+        mod_type = MT_MAIN;
+        entry_name = optarg;
+        break;
+      case 'o':
+        if (opt_o != NULL || opt_O != NULL)
+          usage ();
+        opt_o = optarg;
+        break;
+      case 'p':
+        errno = 0;
+        page_size = (int)strtol (optarg, &tmp, 0);
+        if (tmp == optarg || errno != 0 || *tmp != 0
+            || page_size < 16 || page_size > 32768
+            || (page_size & (page_size - 1)) != 0)
+          usage ();
+        break;
+      case 'q':
+        quiet = TRUE;
+        break;
+      case 'O':
+        if (opt_o != NULL || opt_O != NULL)
+          usage ();
+        opt_O = optarg;
+        break;
+      case 'r':
+      case 'R':
+        if (response_fname != NULL)
+          usage ();
+        response_fname = optarg;
+        response_replace = (c == 'R');
+        break;
+      case 's':
+        strip_symbols = TRUE;
+        break;
+      case 'u':
+        unknown_stabs = TRUE;
+        break;
+      case 'x':
+        opt_x = TRUE;
+        break;
+      default:
+        usage ();
+      }
+
+  /* Check for non-option arguments. */
+
+  if (argc - optind == 0)
+    usage ();
+
+  if (opt_o != NULL)
+    {
+
+      /* If the -o option is used, there must be exactly one input
+         file name. */
+
+      if (argc - optind != 1)
+        usage ();
+      convert (argv[optind], opt_o);
+    }
+  else
+    {
+
+      /* The -o option is not used.  If the -O option is used, set up
+         output_dir. */
+
+      if (opt_O != NULL)
+        {
+          i = strlen (opt_O);
+          tmp = xmalloc (i + 2);
+          strcpy (tmp, opt_O);
+          if (i > 0 && strchr (":\\/", tmp[i-1]) == NULL)
+            strcat (tmp, "/");
+          output_dir = tmp;
+        }
+
+      /* Convert all the files named on the command line. */
+
+      for (i = optind; i < argc; ++i)
+        convert (argv[i], NULL);
+    }
+
+  /* If a LIB response file has been created, finish and close it. */
+
+  if (response_file != NULL)
+    {
+      if (!response_first)
+        fprintf (response_file, "\n");
+      if (fflush (response_file) != 0 || fclose (response_file) != 0)
+        error ("Write error on response file `%s'", response_fname);
+    }
+
+  /* If the user wants input files to be deleted, delete them now. */
+
+  if (delete_input_files)
+    delete_files ();
+  return 0;
+}
Index: trunk/src/emx/src/emxomf/emxomf.h
===================================================================
--- trunk/src/emx/src/emxomf/emxomf.h	(revision 18)
+++ trunk/src/emx/src/emxomf/emxomf.h	(revision 18)
@@ -0,0 +1,44 @@
+/* emxomf.h -- Global header file for emxomf
+   Copyright (c) 1992-1996 Eberhard Mattes
+
+This file is part of emxomf.
+
+emxomf is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxomf is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxomf; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+/* These functions are defined in emxomf.c. */
+
+extern void error (const char *fmt, ...) NORETURN2 ATTR_PRINTF (1, 2);
+extern void warning (const char *fmt, ...) ATTR_PRINTF (1, 2);
+extern void *xmalloc (size_t n);
+void *xrealloc (void *ptr, size_t n);
+char *xstrdup (const char *s);
+extern const struct nlist *find_symbol (const char *name);
+
+/* These variables are defined in emxomf.c. */
+
+extern int sym_count;
+extern const struct nlist *sym_ptr;
+extern const byte *str_ptr;
+extern byte *text_ptr;
+extern long text_size;
+extern struct buffer tt;
+extern struct buffer sst;
+extern struct buffer sst_reloc;
+extern struct grow sst_boundary_grow;
+extern struct grow tt_boundary_grow;
+extern int *sst_boundary;
+extern int *tt_boundary;
Index: trunk/src/emx/src/emxomf/emxomfar.c
===================================================================
--- trunk/src/emx/src/emxomf/emxomfar.c	(revision 18)
+++ trunk/src/emx/src/emxomf/emxomfar.c	(revision 18)
@@ -0,0 +1,441 @@
+/* emxomfar.c -- Manage OMF libraries (.LIB files)
+   Copyright (c) 1992-1998 Eberhard Mattes
+
+This file is part of emxomfar.
+
+emxomfar is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxomfar is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxomfar; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+
+#define VERSION "0.9d"
+
+typedef unsigned char byte;
+typedef unsigned short word;
+
+#include <sys/omflib.h>
+
+#define FALSE 0
+#define TRUE  1
+
+/* The name of the original library file. */
+static char *lib_fname;
+
+/* The name of the new library file. */
+static char *new_fname;
+
+/* This is the command character. */
+static char cmd;
+
+/* This flag is non-zero if the v option is given. */
+static char verbose;
+
+/* This flag is non-zero if the c option is given. */
+static char silent;
+
+/* OMFLIB descriptor of the original library. */
+static struct omflib *lib;
+
+/* OMFLIB descriptor of the new library. */
+static struct omflib *new_lib;
+
+
+/* Tell the user how to run this program. */
+
+static void usage (void)
+{
+  fprintf (stderr, "emxomfar " VERSION " -- "
+           "Copyright (c) 1992-1996 by Eberhard Mattes\n\n");
+  fprintf (stderr, "Usage: emxomfar [-p#] <command> <library_file> [<module>]...\n");
+  fprintf (stderr, "\nCommands:\n");
+  fprintf (stderr, "  d    delete module from library\n");
+  fprintf (stderr, "  r    replace modules in library\n");
+  fprintf (stderr, "  t    list table of contents\n");
+  fprintf (stderr, "  x    extract modules from library\n");
+  fprintf (stderr, "\nOptions (append to command):\n");
+  fprintf (stderr, "  c    no warning when creating new library\n");
+  fprintf (stderr, "  v    verbose output\n");
+  fprintf (stderr, "\nOptions (prededing command):\n");
+  fprintf (stderr, "  -p#  set page size\n");
+  exit (1);
+}
+
+
+/* This function is passed to omflib_pubdef_walk to list the public
+   symbols. */
+
+static int list_pubdef (const char *name, char *error)
+{
+  printf ("  %s\n", name);
+  return 0;
+}
+
+
+/* Perform the requested action for the module NAME. */
+
+static void do_mod (const char *name)
+{
+  char error[512], c;
+  char mod_name[256];
+  int page;
+
+  c = 'a'; page = 0;
+  omflib_module_name (mod_name, name);
+  if (lib != NULL)
+    {
+      page = omflib_find_module (lib, name, error);
+      if (cmd == 'r')
+        {
+          if (page != 0)
+            {
+              c = 'r';
+              if (omflib_mark_deleted (lib, name, error) != 0)
+                {
+                  fprintf (stderr, "emxomfar: %s\n", error);
+                  exit (2);
+                }
+            }
+        }
+      else if (page == 0)
+        {
+          fprintf (stderr, "emxomfar: Module not found: %s\n", name);
+          return;
+        }
+    }
+  switch (cmd)
+    {
+    case 't':
+      if (verbose)
+        {
+          printf("%s (page %d):\n", mod_name, page);
+          if (omflib_pubdef_walk (lib, page, list_pubdef, error) != 0)
+            fprintf (stderr, "emxomfar: %s\n", error);
+          fputchar ('\n');
+        }
+      else
+        printf ("%s\n", mod_name);
+      break;
+    case 'x':
+      if (verbose)
+        printf ("x - %s\n", name);
+      if (omflib_extract (lib, name, error) != 0)
+        {
+          fprintf (stderr, "emxomfar: %s\n", error);
+          exit (2);
+        }
+      break;
+    case 'r':
+      if (verbose)
+        printf ("%c - %s\n", c, name);
+      if (omflib_add_module (new_lib, name, error) != 0)
+        {
+          fprintf (stderr, "emxomfar: %s(%s): %s\n", new_fname, name, error);
+          exit (2);
+        }
+      break;
+    case 'd':
+      if (verbose)
+        printf ("d - %s\n", mod_name);
+      if (omflib_mark_deleted (lib, name, error) != 0)
+        fprintf (stderr, "emxomfar: %s\n", error);
+      break;
+    }
+}
+
+
+/* Cleanup, for atexit. */
+
+static void cleanup (void)
+{
+  char error[512];
+
+  if (new_fname != NULL)
+    {
+      if (new_lib != NULL)
+        {
+          omflib_close (new_lib, error);
+          new_lib = NULL;
+        }
+      if (lib != NULL)
+        {
+          omflib_close (lib, error);
+          lib = NULL;
+        }
+      remove (new_fname);
+      if (lib_fname != NULL)
+        rename (lib_fname, new_fname);
+      new_fname = NULL;
+    }
+}
+
+
+/* Entrypoint.  Parse the command line, open files and perform the
+   requested action. */
+
+int main (int argc, char *argv[])
+{
+  char error[512], name[257], *s, new_cmd;
+  int page;
+  int i, n, create, page_size;
+  char ext_fname[512];
+  char bak_fname[512];
+
+  /* Expand response files and wildcards on th command line. */
+
+  _response (&argc, &argv);
+  _wildcard (&argc, &argv);
+
+  /* The default page size is 16. */
+
+  page_size = 16;
+
+  /* Parse the command line.  First, check for an -p# option. */
+
+  i = 1;
+  if (i < argc && argv[i][0] == '-')
+    {
+      s = argv[i]+1;
+      switch (*s)
+        {
+        case 'p':
+          ++s;
+          page_size = strtol (s, &s, 10);
+          if (page_size < 1 || *s != 0)
+            usage ();
+          ++i;
+          break;
+        default:
+          usage ();
+        }
+    }
+
+  /* At least 2 arguments must be given: the command and the library
+     name. */
+
+  if (argc - i < 2)
+    usage ();
+
+  /* Set initial values. */
+
+  verbose = FALSE; silent = FALSE; cmd = 0;
+
+  /* Skip a leading - character, it's optional. */
+
+  s = argv[i++];
+  if (*s == '-')
+    ++s;
+
+  /* Parse the command. */
+
+  while (*s != 0)
+    {
+      new_cmd = 0;
+      switch (*s)
+        {
+        case 'v':
+          verbose = TRUE;
+          break;
+        case 'c':
+          silent = TRUE;
+          break;
+        case 's':
+          if (cmd == 0)
+            new_cmd = 's';
+          break;
+        case 'd':
+        case 'r':
+        case 't':
+        case 'x':
+          new_cmd = *s;
+          break;
+        case 'q':
+          new_cmd = 'r';
+          break;
+        case 'u':
+          if (cmd == 0)
+            new_cmd = 'r';
+          break;
+        case 'l':
+        case 'o':
+          break;
+        default:
+          usage ();
+        }
+      ++s;
+      if (new_cmd != 0)
+        {
+          if (cmd != 0)
+            usage ();
+          cmd = new_cmd;
+        }
+    }
+
+  /* Complain if no command letter was given. */
+
+  if (cmd == 0)
+    usage ();
+
+  /* The s command is a no-op. */
+
+  if (cmd == 's')
+    return 0;
+
+  /* Add the .lib default extension to the library name.  The result
+     is in ext_fname. */
+
+  _strncpy (ext_fname, argv[i++], sizeof (ext_fname) - 4);
+  _defext (ext_fname, "lib");
+
+  /* Initialize file names and OMFLIB descriptors. */
+
+  lib_fname = ext_fname;
+  lib = NULL;
+  new_fname = NULL;
+  new_lib = NULL;
+
+  /* Make create non-zero iff we have to create a new library file. */
+
+  create = (cmd == 'r' && access (lib_fname, 4) != 0);
+
+  /* The r and d commands create a library file if it doesn't exist.
+     If it does exist, a backup file is created. */
+
+  if (cmd == 'r' || cmd == 'd')
+    {
+      if (create)
+        {
+          if (!silent)
+            printf ("Creating library file `%s'\n", lib_fname);
+          new_fname = lib_fname;
+          lib_fname = NULL;
+        }
+      else
+        {
+          _strncpy (bak_fname, lib_fname, sizeof (bak_fname) - 4);
+          _remext (bak_fname);
+          _defext (bak_fname, "bak");
+          if (_fncmp (lib_fname, bak_fname) == 0)
+            {
+              fprintf (stderr, "Cannot update backup file\n");
+              exit (1);
+            }
+          remove (bak_fname);
+          if (rename (lib_fname, bak_fname) != 0)
+            {
+              perror (lib_fname);
+              exit (2);
+            }
+          new_fname = lib_fname;
+          lib_fname = bak_fname;
+        }
+    }
+
+  /* If no new library file is to be created, the library file is
+     supposed to exist.  Open it. */
+
+  if (!create)
+    {
+      lib = omflib_open (lib_fname, error);
+      if (lib == NULL)
+        {
+          fprintf (stderr, "emxomfar: %s: %s\n", lib_fname, error);
+          exit (2);
+        }
+    }
+
+  /* Create the output library for the r and d commands. */
+
+  if (cmd == 'r' || cmd == 'd')
+    {
+      new_lib = omflib_create (new_fname, page_size, error);
+      if (new_lib == NULL)
+        {
+          fprintf (stderr, "emxomfar: %s: %s\n", new_fname, error);
+          exit (2);
+        }
+    }
+
+  /* Close files when done or when aborting. */
+
+  atexit (cleanup);
+
+  /* Write header of new library. */
+
+  if (cmd == 'r' || cmd == 'd')
+    {
+      if (omflib_header (new_lib, error) != 0)
+        {
+          fprintf (stderr, "emxomfar: %s\n", error);
+          exit (2);
+        }
+    }
+
+  if (i >= argc && !(cmd == 'r' || cmd == 'd'))
+    {
+
+      /* No arguments specified for the t and x commands: Apply
+         do_mod() to all modules of the library. */
+
+      n = omflib_module_count (lib, error);
+      if (n == -1)
+        {
+          fprintf (stderr, "emxomfar: %s\n", error);
+          exit (2);
+        }
+      for (i = 0; i < n; ++i)
+        {
+          if (omflib_module_info (lib, i, name, &page, error) != 0)
+            fprintf (stderr, "emxomfar: %s\n", error);
+          else
+            do_mod (name);
+        }
+    }
+  else
+    {
+      /* Apply do_mod() to all modules given on the command line. */
+
+      while (i < argc)
+        {
+          if (!(cmd == 'd' && strcmp (argv[i], "__.SYMDEF") == 0))
+            do_mod (argv[i]);
+          ++i;
+        }
+    }
+
+  /* Copy all the unmodified modules of the original library to the
+     new library. */
+
+  if (cmd == 'r' || cmd == 'd')
+    {
+      if ((!create && omflib_copy_lib (new_lib, lib, error) != 0)
+          || omflib_finish (new_lib, error) != 0
+          || omflib_close (new_lib, error) != 0)
+        {
+          fprintf (stderr, "emxomfar: %s\n", error);
+          exit (2);
+        }
+      new_lib = NULL; new_fname = NULL;
+    }
+
+  /* Close the source library. */
+
+  if (lib != NULL && omflib_close (lib, error) != 0)
+    fprintf (stderr, "emxomfar: %s\n", error);
+  return 0;
+}
Index: trunk/src/emx/src/emxomf/emxomfld.c
===================================================================
--- trunk/src/emx/src/emxomf/emxomfld.c	(revision 18)
+++ trunk/src/emx/src/emxomf/emxomfld.c	(revision 18)
@@ -0,0 +1,819 @@
+/* emxomfld.c --  Provide an ld-like interface to LINK386
+   Copyright (c) 1992-1998 Eberhard Mattes
+
+This file is part of emxomld.
+
+emxomfld is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxomfld is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxomfld; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <errno.h>
+#include <sys/moddef.h>
+#include "defs.h"
+
+#define VERSION "0.9d"
+
+#define FALSE 0
+#define TRUE  1
+
+/* A member of a linked list of strings such as file names. */
+typedef struct name_list
+{
+  struct name_list *next;
+  char *name;
+} name_list;
+
+
+/* The output file name, specified by the -o option.  */
+static const char *output_fname = NULL;
+
+/* The map file name (output), set by the -Zmap option. */
+static const char *map_fname = NULL;
+static int map_flag = FALSE;
+
+/* The module definition file name (input), set if a file matching
+   *.def is given on the command line. */
+static const char *def_fname = NULL;
+
+/* The binary resource file name (input), set if a file matching *.res
+   is given on the command line. */
+static const char *res_fname = NULL;
+
+/* Base address of the excecutable file, specified by the -T
+   option. */
+static const char *base = NULL;
+
+/* List of directories searched for libraries.  Each -L option adds a
+   directory to this list.  add_libdirs is used to add another entry
+   at the end of the list. */
+static name_list *libdirs = NULL;
+static name_list **add_libdirs = &libdirs;
+
+/* List of object files.  Each file given on the command line which
+   does not match *.def, *.lib and *.res is added to this list.
+   add_obj_fnames is used to add another entry at the end of the
+   list. */
+static name_list *obj_fnames = NULL;
+static name_list **add_obj_fnames = &obj_fnames;
+
+/* List of library files.  Each file matching *.lib given on the
+   command line is added to this list.  The -l option also adds an
+   entry to this list. add_lib_fnames is used to add another entry at
+   the end of the list. */
+static name_list *lib_fnames = NULL;
+static name_list **add_lib_fnames = &lib_fnames;
+
+/* List of LINK386 options.  LINK386 options can be specified with the
+   -O option.  add_options is used to add another entry at the end of
+   the list. */
+static name_list *options = NULL;
+static name_list **add_options = &options;
+
+/* The command line passed to LINK386. */
+static char command_line[260];
+
+/* The current length of the command line. */
+static int line_len;
+
+/* Non-zero if arguments go into the response file instead of
+   command_line. */
+static int response_flag;
+
+/* The name of the response file. */
+static char response_fname[L_tmpnam] = "";
+
+/* The response file. */
+static FILE *response_file = NULL;
+
+/* Non-zero if debugging information is to be omitted.  Set by the -s
+   and -S options. */
+static int strip_symbols = FALSE;
+
+/* Non-zero if emxomfld should create an .exe file and touch the
+   output file.  Set by the -Zexe option. */
+static int exe_flag = FALSE;
+
+/* Non-zero when creating a dynamic link library.  Set by the -Zdll
+   option. */
+static int dll_flag = FALSE;
+
+/* The stack size, specified by the -Zstack option, in Kbyte.  If the
+   -Zstack option is not used, this variable is 0. */
+static long stack_size = 0;
+
+/* The name of the linker to use.  By default, LINK386 is used.  This
+   can be overriden with the EMXOMFLD_LINKER environment variable. */
+static const char *linker_name = "link386";
+
+/* Prototypes. */
+
+static void usage (void) NORETURN2;
+static void *xmalloc (size_t n);
+static char *xstrdup (const char *s);
+static void add_name_list (name_list ***add, const char *src);
+static void conv_path (char *name);
+static void put_arg (const char *src, int path);
+static void put_args (const name_list *list, int paths);
+static void make_env (void);
+static void cleanup (void);
+static void arg_init (int rsp);
+static void arg_end (void);
+int main (int argc, char *argv[]);
+
+
+/* Tell the user how to run this program. */
+
+static void usage (void)
+{
+  fprintf (stderr, "emxomfld " VERSION " -- "
+           "Copyright (c) 1992-1996 by Eberhard Mattes\n\n");
+  fprintf (stderr,
+           "Usage: emxomfld -o <file> [-l <lib>] [-L <libdir>] [-T <base>] [-sS]\n"
+           "                [-Zexe] [-Zdll] [-Zstack <size>] [-Zmap[=<map_file>]]\n"
+           "                [-O <option>] <file>...\n");
+  exit (1);
+}
+
+
+/* Allocate N bytes of memory.  Quit on failure.  This function is
+   used like malloc(), but we don't have to check the return value. */
+
+static void *xmalloc (size_t n)
+{
+  void *p;
+  
+  p = malloc (n);
+  if (p == NULL)
+    {
+      fprintf (stderr, "emxomfld: out of memory\n");
+      exit (2);
+    }
+  return p;
+}
+
+
+/* Create a duplicate of the string S on the heap.  Quit on failure.
+   This function is used like strdup(), but we don't have to check the
+   return value. */
+
+static char *xstrdup (const char *s)
+{
+  char *p;
+  
+  p = xmalloc (strlen (s) + 1);
+  strcpy (p, s);
+  return p;
+}
+
+
+/* Add the name SRC to a list.  ADD is a pointer to the pointer of the
+   end of the list.  We duplicate the string before adding it to the
+   list. */
+
+static void add_name_list (name_list ***add, const char *src)
+{
+  name_list *new;
+
+  new = xmalloc (sizeof (name_list));
+  new->next = NULL;
+  new->name = xstrdup (src);
+  *(*add) = new;
+  (*add) = &new->next;
+}
+
+
+/* Replace forward slashes `/' in NAME with backslashes `\'.  LINK386
+   needs backslashes in path names. */
+
+static void conv_path (char *name)
+{
+  char *p;
+
+  for (p = name; *p != 0; ++p)
+    if (*p == '/')
+      *p = '\\';
+}
+
+
+/* Add the argument SRC to the command line or to the response file.
+   If PATH is non-zero, SRC is a path name and slashes are to be
+   replaced by backslashes.  If the command line gets too long, a
+   response file is created. */
+
+static void put_arg (const char *src, int path)
+{
+  int len, max_len;
+  char *tmp;
+
+  if (src != NULL)
+    {
+
+      /* Instead of a comma, we write a newline to the response
+         file. */
+
+      if (response_file != NULL && strcmp (src, ",") == 0)
+        {
+          fputc ('\n', response_file);
+          line_len = 0;
+          return;
+        }
+
+      /* Make a local copy of SRC to be able to modify it.  Then,
+         translate forward slashes to backslashes if PATH is
+         non-zero. */
+
+      len = strlen (src);
+      tmp = alloca (len + 1);
+      strcpy (tmp, src);
+      if (path)
+        conv_path (tmp);
+
+      /* Check if we've reached the maximum line length.  If the
+         maximum command line length is exceeded, create a response
+         file and write the remaining arguments to that file instead
+         of putting them on the command line. */
+
+      max_len = (response_file == NULL ? 110 : 52);
+      if (line_len + len + 1 > max_len)
+        {
+
+          /* If SRC is a single comma or a single semicolon, copy it
+             to the output, ignoring the maximum line length.  This is
+             to meet the LINK386 command syntax. The maximum line
+             length allows for enough commas and semicolons added this
+             way. */
+
+          if ((*tmp == ',' || *tmp == ';') && tmp[1] == 0)
+            {
+              if (response_file == NULL)
+                {
+                  command_line[line_len+0] = *tmp;
+                  command_line[line_len+1] = 0;
+                }
+              else
+                fputc (*tmp, response_file);
+              ++line_len;
+              return;
+            }
+
+          /* If a response file has not yet been opened, open it. */
+
+          if (response_file == NULL)
+            {
+
+              /* Complain if we are not allowed to use a response
+                 file. */
+
+              if (!response_flag)
+                {
+                  fprintf (stderr, "emxomfld: command line too long\n");
+                  exit (2);
+                }
+
+              /* Choose a unique file name and create the response
+                 file. */
+
+              strcpy (response_fname, "ldXXXXXX");
+              if (mktemp (response_fname) == NULL)
+                {
+                  perror ("emxomfld");
+                  exit (2);
+                }
+              response_file = fopen (response_fname, "wt");
+              if (response_file == NULL)
+                {
+                  perror ("emxomfld");
+                  exit (2);
+                }
+
+              /* Add the name of the response file to the command
+                 line. */
+
+              command_line[line_len++] = ' ';
+              command_line[line_len++] = '@';
+              strcpy (command_line+line_len, response_fname);
+            }
+          else if (line_len != 0)
+            {
+
+              /* Start a new line in the response file. */
+
+              fputs (" +\n", response_file);
+            }
+          line_len = 0;
+        }
+
+      /* Separate command line arguments by spaces (unless the
+         argument to be added starts with a delimiter. */
+
+      if (line_len != 0 && *src != ',' && *src != ';')
+        {
+          if (response_file == NULL)
+            command_line[line_len++] = ' ';
+          else
+            fputc (' ', response_file);
+        }
+
+      /* Finally write the argument to the command line or to the
+         response file and adjust the current line length. */
+
+      if (response_file == NULL)
+        strcpy (command_line + line_len, tmp);
+      else
+        fputs (tmp, response_file);
+      line_len += len;
+    }
+}
+
+
+/* Put a list of arguments onto the command line or into the response
+   file.  If PATHS is non-zero, the arguments are path names and
+   slashes are to be replaced by backslashes. */
+
+static void put_args (const name_list *list, int paths)
+{
+  while (list != NULL)
+    {
+      put_arg (list->name, paths);
+      list = list->next;
+    }
+}
+
+
+/* Build the environment for LINK386: define the LIB environment
+   variable. */
+
+static void make_env (void)
+{
+  static char tmp[4096];
+  char *p;
+  int len;
+  const name_list *list;
+
+  /* Create a string for putenv(). */
+
+  strcpy (tmp, "LIB=");
+  len = strlen (tmp);
+
+  /* Add the library directories to LIB, using `;' as separator. */
+
+  for (list = libdirs; list != NULL; list = list->next)
+    {
+      if (tmp[len-1] != ';')
+        tmp[len++] = ';';
+      strcpy (tmp+len, list->name);
+      conv_path (tmp+len);
+      len += strlen (list->name);
+    }
+
+  /* Append to the end the previous definition of LIB. */
+
+  p = getenv ("LIB");
+  if (p != NULL)
+    {
+      if (tmp[len-1] != ';')
+        tmp[len++] = ';';
+      strcpy (tmp+len, p);
+    }
+
+
+  /* Put the new value of LIB into the environment. */
+
+  putenv (tmp);
+}
+
+
+/* Start a new set of command line arguments.  If RSP is non-zero, we
+   are allowed to use a response file. */
+
+static void arg_init (int rsp)
+{
+  command_line[0] = 0;
+  line_len = 0;
+  response_flag = rsp;
+}
+
+
+/* Call this after adding all the command line arguments.  If a
+   response file has been created, add a newline and close it. */
+
+static void arg_end (void)
+{
+  if (response_file != NULL)
+    {
+      fputc ('\n', response_file);
+      if (fflush (response_file) != 0 || fclose (response_file) != 0)
+        {
+          perror ("emxomfld");
+          exit (2);
+        }
+      response_file = NULL;
+    }
+}
+
+
+/* Cleanup by closing (if open) and deleting (if pressent) the
+   response file.  This function is used with atexit(). */
+
+static void cleanup (void)
+{
+  if (response_file != NULL)
+    {
+      fclose (response_file);
+      response_file = NULL;
+    }
+  if (response_fname[0] != 0)
+    {
+      remove (response_fname);
+      response_fname[0] = 0;
+    }
+}
+
+
+/* Main function of emxomf.  Parse the command line and call LINK386
+   (and optionally RC). */
+
+int main (int argc, char *argv[])
+{
+  int c, rc, files;
+  int opt_i;
+  const char *ext;
+  char tmp[512], *t;
+
+  /* Close and delete the response file on exit. */
+
+  atexit (cleanup);
+
+  /* Prepare parsing of the command line. */
+
+  opt_i = FALSE; files = 0;
+  opterr = FALSE; optmode = GETOPT_KEEP;
+  if (argc < 2)
+    usage ();
+
+  /* Parse the command line options and other arguments. */
+
+  while ((c = getopt (argc, argv, "o:O:il:vL:T:sSxXZ:")) != EOF)
+    switch (c)
+      {
+      case 'i':                 /* Use /INFORMATION option of LINK386 */
+        opt_i = TRUE;
+        break;
+
+      case 'l':                 /* Add library */
+        add_name_list (&add_lib_fnames, optarg);
+        break;
+
+      case 'o':                 /* Set output file name */
+        output_fname = optarg;
+        break;
+
+      case 'L':                 /* Add library directory */
+        add_name_list (&add_libdirs, optarg);
+        break;
+
+      case 'T':                 /* Set base address */
+        base = optarg;
+        break;
+
+      case 's':                 /* Strip all symbols */
+      case 'S':                 /* Strip debugging symbols */
+        strip_symbols = TRUE;
+        break;
+
+      case 'x':                 /* Discard all local symbols */
+      case 'X':                 /* Discard local symbols starting with L */
+        break;
+
+      case 'v':                 /* For compatibility */
+        break;
+
+      case 'O':                 /* Specify LINK386 option */
+        add_name_list (&add_options, optarg);
+        break;
+
+      case 'Z':                 /* -Zdll, -Zexe, -Zmap, and -Zstack */
+        if (strcmp (optarg, "dll") == 0)
+          dll_flag = TRUE;
+        else if (strcmp (optarg, "exe") == 0)
+          exe_flag = TRUE;
+        else if (strcmp (optarg, "map") == 0)
+          map_flag = TRUE;
+        else if (strncmp (optarg, "map=", 4) == 0)
+          {
+            if (map_fname != NULL)
+              {
+                fprintf (stderr, "emxomfld: multiple map files files\n");
+                usage ();
+              }
+            map_fname = optarg + 4;
+            map_flag = TRUE;
+          }
+        else if (strcmp (optarg, "stack") == 0)
+          {
+            /* This makes assumptions on the internals of getopt(). */
+
+            if (optind >= argc || argv[optind][0] == '-')
+              usage ();
+            errno = 0;
+            stack_size = strtol (argv[optind], &t, 0);
+            if (errno != 0 || *t != 0 || t == argv[optind])
+              usage ();
+            ++optind;
+          }
+        else
+          {
+            fprintf (stderr, "emxomfld: invalid option\n");
+            usage ();
+          }
+        break;
+
+      case 0:                   /* Non-option argument */
+
+        /* Extract the extension to see what to do with this
+           argument. */
+
+        ext = _getext (optarg);
+
+        if (ext == NULL)
+          {
+            /* GCC's temporary files don't have an extension.  Add a
+               dot to the end of the name to prevent LINK386 from
+               adding `.obj'. */
+
+            sprintf (tmp, "%s.", optarg);
+            add_name_list (&add_obj_fnames, tmp);
+          }
+
+        /* If it's a .def file, use it as module definition file
+           (input). */
+
+        else if (stricmp (ext, ".def") == 0)
+          {
+            if (def_fname != NULL)
+              {
+                fprintf (stderr,
+                         "emxomfld: multiple module definition files\n");
+                usage ();
+              }
+            def_fname = optarg;
+          }
+
+        /* If it's a .res file, use it as binary resource file
+           (input). */
+
+        else if (stricmp (ext, ".res") == 0)
+          {
+            if (res_fname != NULL)
+              {
+                fprintf (stderr,
+                         "emxomfld: multiple binary resource files\n");
+                usage ();
+              }
+            res_fname = optarg;
+          }
+
+        /* If it's a .lib file, use it as library file.  We also
+           accept .a files for those who use OMF files disguised as
+           a.out files (to simplify their make files). */
+
+        else if (stricmp (ext, ".lib") == 0 || stricmp (ext, ".a") == 0)
+          add_name_list (&add_lib_fnames, optarg);
+
+        /* Otherwise, assume it's an object file. */
+
+        else
+          add_name_list (&add_obj_fnames, optarg);
+        ++files;
+        break;
+
+      default:
+        fprintf (stderr, "emxomfld: invalid option\n");
+        usage ();
+      }
+
+  /* Set default value for output file. */
+
+  if (output_fname == NULL)
+    {
+      fprintf (stderr,
+               "emxomfld: no output file, creating $$$.exe or $$$.dll\n");
+      output_fname = "$$$";
+    }
+
+  /* Check if there are any input files. */
+
+  if (files == 0)
+    {
+      fprintf (stderr, "emxomfld: no input files\n");
+      usage ();
+    }
+
+  /* Remove the output file if -Zexe is given. */
+
+  if (exe_flag)
+    remove (output_fname);
+
+  /* If neither -Zmap nor -Zmap=file is used, pass "nul" to LINK386 in
+     the map file field.  If -Zmap is used, construct the name of the
+     .map file.  If -Zmap=file is used, use `file' as the name of the
+     .map file. */
+
+  if (!map_flag)
+    map_fname = "nul";
+  else if (map_fname == NULL)
+    {
+      t = xstrdup (output_fname);
+      _remext (t);
+      map_fname = t;
+    }
+
+  t = getenv ("EMXOMFLD_LINKER");
+  if (t != NULL)
+    linker_name = t;
+
+  /* Start building the LINK386 command line.  We can use a response
+     file if the command line gets too long. */
+
+  arg_init (TRUE);
+
+  /* Default options are:
+
+     /BATCH             Run in batch mode (disable prompting, don't
+                        echo response file)
+
+     /NOLOGO            Don't display sign-on banner
+
+     /NOEXTDICTIONARY   Don't use extended dictionary (redefining
+                        library symbols is quite common)
+
+     /NOIGNORECASE      Make symbols case-sensitive
+
+     /PACKCODE          Group neighboring code segments (this is the
+                        default unless the SEGMENTS module definition
+                        statement is used for a segment of class
+                        'CODE').  Not grouping neighboring code
+                        segments would break sets */
+
+  put_arg (linker_name, TRUE);
+  put_arg ("/bat", FALSE);
+  put_arg ("/nol", FALSE);
+  put_arg ("/noe", FALSE);
+  put_arg ("/noi", FALSE);
+  put_arg ("/packc", FALSE);
+
+  /* Add the /INFORMATION option if the -i option was given.  This is
+     for debugging. */
+
+  if (opt_i)
+    put_arg ("/i", FALSE);
+
+  /* Add the /DEBUG option if the -s option was not given.  Without
+     this, LINK386 throws away debugging information. */
+
+  if (!strip_symbols)
+    put_arg ("/de", FALSE);
+
+  /* Add the /BASE:n option to set the base address.  This specifies
+     the preferred load address of object 1.  The base address being
+     used is 0x10000 unless a DLL is generated or the -T option was
+     given.  -Tno can be used to suppress the /BASE:n option. */
+
+  if (base == NULL && !dll_flag)
+    {
+      struct _md *md;
+
+      if (def_fname != NULL)
+        {
+          md = _md_open (def_fname);
+          if (md == NULL)
+            {
+              fprintf (stderr, "emxomfld: cannot open `%s'\n", def_fname);
+              exit (2);
+            }
+          if (_md_next_token (md) == _MD_LIBRARY)
+            dll_flag = TRUE;
+          _md_close (md);
+        }
+    }
+  if (base == NULL && !dll_flag)
+    base = "0x10000";
+  if (base != NULL && strcmp (base, "no") != 0)
+    {
+      sprintf (tmp, "/bas:%s", base);
+      put_arg (tmp, FALSE);
+    }
+
+  /* Add the /STACK:n option if the -Zstack option was given. */
+
+  if (stack_size != 0)
+    {
+      sprintf (tmp, "/st:0x%lx", stack_size * 1024);
+      put_arg (tmp, FALSE);
+    }
+
+  /* Add the LINK386 options specified with -O. */
+
+  put_args (options, FALSE);
+
+  /* Put the object file names onto the command line. */
+
+  put_args (obj_fnames, TRUE);
+  put_arg (",", FALSE);
+
+  /* Put the output file name onto the command line. */
+
+  put_arg (output_fname, TRUE);
+  put_arg (",", FALSE);
+
+  /* Put the map file name onto the command line. */
+
+  put_arg (map_fname, TRUE);
+  put_arg (",", FALSE);
+
+  /* Put the library file names onto the command line. */
+
+  put_args (lib_fnames, TRUE);
+  put_arg (",", FALSE);
+
+  /* Put the name of the module definition file onto the command line. */
+
+  put_arg (def_fname, TRUE);
+  put_arg (";", FALSE);
+  arg_end ();
+
+  /* Build the environment for LINK386. */
+
+  make_env ();
+
+  /* Call LINK386 via CMD.EXE (what a waste -- but I'm lazy) and abort
+     on failure. */
+
+  rc = system (command_line);
+  if (rc < 0)
+    {
+      perror (linker_name);
+      exit (2);
+    }
+
+  /* Run RC if LINK386 completed successfully and a binary resource
+     file was given on the command line. */
+
+  if (rc == 0 && res_fname != NULL)
+    {
+      arg_init (TRUE);
+      put_arg ("rc", TRUE);
+      put_arg (res_fname, TRUE);
+      put_arg (output_fname, TRUE);
+      arg_end ();
+      rc = system (command_line);
+      if (rc < 0)
+        {
+          perror ("emxomfld: rc");
+          exit (2);
+        }
+    }
+
+  /* If both LINK386 and RC competed successfully and the -Zexe option
+     was given, touch the output file (without .exe) to keep `make'
+     happy. */
+
+  if (rc == 0 && exe_flag)
+    {
+      int h;
+
+      h = open (output_fname,
+                O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+      if (h < 0)
+        {
+          perror ("emxomfld");
+          exit (2);
+        }
+      close (h);
+    }
+
+  /* Return the return code of LINK386 (or RC). */
+
+  return rc;
+}
Index: trunk/src/emx/src/emxomf/grow.c
===================================================================
--- trunk/src/emx/src/emxomf/grow.c	(revision 18)
+++ trunk/src/emx/src/emxomf/grow.c	(revision 18)
@@ -0,0 +1,333 @@
+/* grow.c -- Growing arrays, growing buffers and string pools
+   Copyright (c) 1993-1995 Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+/* Growing arrays.  Such an array consists of two parts: A struct grow
+   which is used in this module for controlling the object, and a
+   pointer (the `associated pointer') of the desired type to the
+   array.  The associated pointer may change when calling one of the
+   functions of these module for the struct grow of that array.*/
+
+/* Growing buffers.  A growing buffer is an array of bytes.  There are
+   functions for putting various binary types into the buffer, while
+   enlarging the buffer as required. */
+
+/* String pool.  A string pool contains null-terminated strings of
+   arbitrary length.  There are no duplicate strings in a string
+   pool. */
+
+#include <stdlib.h>
+#include <string.h>
+#include "defs.h"
+#include "grow.h"
+
+/* A program using this module has to define the following two
+   functions: */
+
+extern void *xrealloc (void *ptr, size_t n);
+extern void *xmalloc (size_t n);
+
+/* Initialize a growing array.  G points to the struct grow used for
+   controlling the array, PTR is a pointer to the associated pointer
+   of the desired type -- that pointer is used for accessing the
+   array.  SIZE is the size of one array element, INC is the number of
+   array elements to add when growing the array.  The smaller SIZE is,
+   the bigger you should choose INC. */
+
+void grow_init (struct grow *g, void *ptr, size_t size, int inc)
+{
+  g->count = 0;
+  g->alloc = 0;
+  g->ptr = ptr;
+  g->size = size;
+  g->inc = inc;
+  *g->ptr = NULL;
+}
+
+
+/* Deallocate a growing array.  Do not use the associated array
+   pointer after calling this function. */
+
+void grow_free (struct grow *g)
+{
+  if (g->ptr != NULL)
+    {
+      if (*g->ptr != NULL)
+        free (*g->ptr);
+      *g->ptr = NULL;
+    }
+  g->ptr = NULL;
+  g->count = 0;
+  g->alloc = 0;
+}
+
+
+/* Grow the growing array G to NEW_COUNT elements.  If the array is
+   already big enough, nothing is done.  Otherwise, the array is
+   enlarged by at least INC (of grow_init()) elements.  The associated
+   array pointer may change. */
+
+void grow_to (struct grow *g, int new_count)
+{
+  if (new_count > g->alloc)
+    {
+      g->alloc += g->inc;
+      if (g->alloc < new_count)
+        g->alloc = new_count;
+      *g->ptr = xrealloc (*g->ptr, g->alloc * g->size);
+    }
+}
+
+
+/* Grow the growing array G to make it big enough for INC additional
+   elements.  If the array is already big enough, nothing is done.
+   Otherwise, the array is enlarged by at least INC (of grow_init())
+   elements.  The associated array pointer may change. */
+
+void grow_by (struct grow *g, int inc)
+{
+  grow_to (g, g->count + inc);
+}
+
+
+/* Initialize a growing buffer.  B is a pointer to the buffer
+   descriptor. */
+
+void buffer_init (struct buffer *b)
+{
+  b->size = 0;
+  b->alloc = 0;
+  b->buf = NULL;
+}
+
+
+/* Deallocate a growing buffer.  Do not use the buffer after calling
+   this function. */
+
+void buffer_free (struct buffer *b)
+{
+  if (b->buf != NULL)
+    {
+      free (b->buf);
+      b->buf = NULL;
+    }
+}
+
+
+/* Grow the buffer B by N bytes.  The buffer size is always an
+   integral multiple of 512.  The buffer may move in memory. */
+
+static void buffer_grow_by (struct buffer *b, size_t n)
+{
+  if (b->size + n > b->alloc)
+    {
+      n = (n | 0x1ff) + 1;
+      b->alloc += n;
+      b->buf = xrealloc (b->buf, b->alloc);
+    }
+}
+
+
+/* Append the 8-bit byte X to the buffer B. */
+
+void buffer_byte (struct buffer *b, byte x)
+{
+  buffer_grow_by (b, 1);
+  b->buf[b->size++] = x;
+}
+
+
+/* Append the 16-bit word X to the buffer B.  The LSB comes first. */
+
+void buffer_word (struct buffer *b, word x)
+{
+  buffer_grow_by (b, 2);
+  b->buf[b->size++] = x & 0xff;
+  b->buf[b->size++] = (x >> 8) & 0xff;
+}
+
+
+/* Append the 32-bit word X to the buffer B.  The LSB comes first. */
+
+void buffer_dword (struct buffer *b, dword x)
+{
+  buffer_grow_by (b, 4);
+  b->buf[b->size++] = x & 0xff;
+  b->buf[b->size++] = (x >> 8) & 0xff;
+  b->buf[b->size++] = (x >> 16) & 0xff;
+  b->buf[b->size++] = (x >> 24) & 0xff;
+}
+
+
+/* Append LEN bytes at MEM to the buffer B. */
+
+void buffer_mem (struct buffer *b, const void *mem, int len)
+{
+  buffer_grow_by (b, len);
+  memcpy (b->buf + b->size, mem, len);
+  b->size += len;
+}
+
+
+/* Append the string STR to the buffer B.  The string is preceded by
+   its length (one byte).  If the string length exceeds 255
+   characters, the string is truncated to 255 characters. */
+
+void buffer_nstr (struct buffer *b, const char *str)
+{
+  int len;
+
+  if (str == NULL)
+    buffer_byte (b, 0);
+  else
+    {
+      len = strlen (str);
+      if (len > 255)
+        len = 255;
+      buffer_byte (b, len);
+      buffer_mem (b, str, len);
+    }
+}
+
+
+/* Append the string STR to the buffer B.  The string is preceded by
+   its length (one byte or two bytes).  If the string length exceeds
+   32767 characters, the string is truncated to 32767 characters. */
+
+void buffer_enc (struct buffer *b, const char *str)
+{
+  size_t len;
+
+  len = strlen (str);
+  if (len > 0x7fff)
+    len = 0x7fff;
+  if (len <= 0x7f)
+    buffer_byte (b, len);
+  else
+    {
+      buffer_byte (b, (len >> 8) | 0x80);
+      buffer_byte (b, len & 0xff);
+    }
+  buffer_mem (b, str, len);
+}
+
+
+/* Patch the 16-bit word in the buffer B at offset INDEX to X. */
+
+void buffer_patch_word (struct buffer *b, int index, word x)
+{
+  b->buf[index+0] = x & 0xff;
+  b->buf[index+1] = (x >> 8) & 0xff;
+}
+
+
+/* The size of the string pool hash table.  Should be prime. */
+
+#define STRPOOL_HASH_SIZE 211
+
+/* This structure holds one string.  Note that the first character of
+   the string is part of this structure. */
+
+struct string
+{
+  struct string *next;          /* Pointer to next string in same bucket */
+  char string[1];               /* The string */
+};
+
+/* A string pool consists of its hash table. */
+
+struct strpool
+{
+  struct string *table[STRPOOL_HASH_SIZE];
+};
+
+
+/* Create and return a new string pool.  Initially, the string pool is
+   empty. */
+
+struct strpool *strpool_init (void)
+{
+  int i;
+  struct strpool *p;
+
+  p = xmalloc (sizeof (*p));
+  for (i = 0; i < STRPOOL_HASH_SIZE; ++i)
+    p->table[i] = NULL;
+  return p;
+}
+
+/* Destroy the string pool P.  The hash table and the strings are
+   deallocated. */
+
+void strpool_free (struct strpool *p)
+{
+  struct string *v1, *v2;
+  int i;
+
+  for (i = 0; i < STRPOOL_HASH_SIZE; ++i)
+    for (v1 = p->table[i]; v1 != NULL; v1 = v2)
+      {
+        v2 = v1->next;
+        free (v1);
+      }
+  free (p);
+}
+
+
+/* Add the string S of LEN characters to the string pool P.  The
+   string must not contain null characters. A pointer to a string of
+   the string pool is returned.  If a string identical to S already
+   exists in the string pool, a pointer to that string is returned.
+   Otherwise, a new string entry is added to the string pool. */
+
+const char *strpool_addn (struct strpool *p, const char *s, int len)
+{
+  unsigned hash;
+  int i;
+  struct string *v;
+
+  hash = 0;
+  for (i = 0; i < len; ++i)
+    hash = hash * 65599 + s[i];
+  hash %= STRPOOL_HASH_SIZE;
+  for (v = p->table[hash]; v != NULL; v = v->next)
+    if (strlen (v->string) == len && memcmp (v->string, s, len) == 0)
+      return v->string;
+  v = xmalloc (sizeof (*v) + len);
+  memcpy (v->string, s, len);
+  v->string[len] = 0;
+  v->next = p->table[hash];
+  p->table[hash] = v;
+  return v->string;
+}
+
+
+/* Add the null-terminated string S to the string pool P.  A pointer
+   to a string of the string pool is returned.  If a string identical
+   to S already exists in the string pool, a pointer to that string is
+   returned.  Otherwise, a new string entry is added to the string
+   pool. */
+
+const char *strpool_add (struct strpool *p, const char *s)
+{
+  if (s == NULL)
+    return NULL;
+  return strpool_addn (p, s, strlen (s));
+}
Index: trunk/src/emx/src/emxomf/grow.h
===================================================================
--- trunk/src/emx/src/emxomf/grow.h	(revision 18)
+++ trunk/src/emx/src/emxomf/grow.h	(revision 18)
@@ -0,0 +1,60 @@
+/* grow.h -- Growing arrays, growing buffers and string pools
+   Copyright (c) 1993-1995 Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define GROW_INIT   {0, 0, 0, 0, NULL}
+#define BUFFER_INIT {0, 0, NULL}
+
+struct grow
+{
+  int count;
+  int alloc;
+  int size;
+  int inc;
+  void **ptr;
+};
+
+struct buffer
+{
+  size_t size;
+  size_t alloc;
+  byte *buf;
+};
+
+/* Note: PTR is a pointer to a pointer */
+void grow_init (struct grow *g, void *ptr, size_t size, int inc);
+void grow_free (struct grow *g);
+void grow_to (struct grow *g, int new_count);
+void grow_by (struct grow *g, int inc);
+
+void buffer_init (struct buffer *b);
+void buffer_free (struct buffer *b);
+void buffer_byte (struct buffer *b, byte x);
+void buffer_word (struct buffer *b, word x);
+void buffer_dword (struct buffer *b, dword x);
+void buffer_mem (struct buffer *b, const void *mem, int len);
+void buffer_nstr (struct buffer *b, const char *str);
+void buffer_enc (struct buffer *b, const char *str);
+void buffer_patch_word (struct buffer *b, int index, word x);
+
+struct strpool *strpool_init (void);
+void strpool_free (struct strpool *p);
+const char *strpool_addn (struct strpool *p, const char *s, int len);
+const char *strpool_add (struct strpool *p, const char *s);
Index: trunk/src/emx/src/emxomf/listomf.c
===================================================================
--- trunk/src/emx/src/emxomf/listomf.c	(revision 18)
+++ trunk/src/emx/src/emxomf/listomf.c	(revision 18)
@@ -0,0 +1,2380 @@
+/* listomf.c -- List OMF files (.obj and .lib files)
+   Copyright (c) 1993-1998 Eberhard Mattes
+
+This file is part of listomf.
+
+listomf is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+listomf is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with listomf; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __EMX__
+#include <io.h>
+#endif /* __EMX__ */
+#include <getopt.h>
+#include "defs.h"
+
+#define VERSION "0.9d"
+
+#pragma pack(1)
+
+struct timestamp
+{
+  byte hours;
+  byte minutes;
+  byte seconds;
+  byte hundredths;
+  byte day;
+  byte month;
+  word year;
+};
+
+#pragma pack()
+
+struct segment
+{
+  int name;
+  int class;
+  dword length;
+};
+
+struct group
+{
+  int name;
+};
+
+struct ext
+{
+  char *name;
+};
+
+enum debug
+{
+  debug_default,
+  debug_cv,
+  debug_hll
+};
+
+
+static int lname_count;
+static int lname_alloc;
+static char **lname_list;
+static int segment_count;
+static int segment_alloc;
+static struct segment *segment_list;
+static int group_count;
+static int group_alloc;
+static struct group *group_list;
+static int ext_count;
+static int ext_alloc;
+static struct ext *ext_list;
+static int pub_count;
+static int debug_type_index;
+static int done;
+static int rec_type;
+static int rec_len;
+static int rec_idx;
+static long rec_pos;
+static byte rec_buf[MAX_REC_SIZE+8];
+static enum debug debug_info;
+static int hll_style;
+static word line_count;
+static dword names_length;
+static int linnum_started;
+static byte linnum_entry_type;
+static word page_size;
+static word dict_blocks;
+static dword dict_offset;
+
+static char list_debug = TRUE;
+static char show_addr = FALSE;
+
+
+static void out_of_mem (void)
+{
+  fputs ("Out of memory\n", stderr);
+  exit (2);
+}
+
+
+static void *xmalloc (size_t n)
+{
+  void *p;
+
+  p = malloc (n);
+  if (p == NULL)
+    out_of_mem ();
+  return p;
+}
+
+
+static void *xrealloc (void *src, size_t n)
+{
+  void *p;
+
+  p = realloc (src, n);
+  if (p == NULL)
+    out_of_mem ();
+  return p;
+}
+
+
+static char *xstrdup (const char *src)
+{
+  char *p;
+
+  p = strdup (src);
+  if (p == NULL)
+    out_of_mem ();
+  return p;
+}
+
+
+static void show_record (const char *name)
+{
+  if (show_addr)
+    printf ("%ld: %s", rec_pos, name);
+  else
+    printf ("%s", name);
+  if (rec_type & REC32)
+    printf ("32");
+}
+
+
+static void get_mem (void *dst, int len)
+{
+  if (rec_idx + len > rec_len)
+    {
+      fprintf (stderr, "\nString at %d beyond end of record\n", rec_idx);
+      exit (2);
+    }
+  memcpy (dst, rec_buf + rec_idx, len);
+  rec_idx += len;
+}
+
+
+static void get_string (byte *dst)
+{
+  int len;
+
+  if (rec_idx >= rec_len)
+    {
+      fprintf (stderr, "\nString at %d beyond end of record\n", rec_idx);
+      exit (2);
+    }
+  len = rec_buf[rec_idx++];
+  get_mem (dst, len);
+  dst[len] = 0;
+}
+
+
+static byte *get_cpp_string (void)
+{
+  int len;
+  byte *p;
+
+  if (rec_idx >= rec_len)
+    {
+      fprintf (stderr, "\nString at %d beyond end of record\n", rec_idx);
+      exit (2);
+    }
+  len = rec_buf[rec_idx++];
+  if (len & 0x80)
+    len = ((len & 0x7f) << 8) + rec_buf[rec_idx++];
+  p = xmalloc (len + 1);
+  get_mem (p, len);
+  p[len] = 0;
+  return p;
+}
+
+
+static int get_index (void)
+{
+  int result;
+
+  if (rec_idx >= rec_len)
+    {
+      fprintf (stderr, "\nIndex at %d beyond end of record\n", rec_idx);
+      exit (2);
+    }
+  result = rec_buf[rec_idx++];
+  if (result & 0x80)
+    {
+      if (rec_idx >= rec_len)
+        {
+          fprintf (stderr, "\nIndex at %d beyond end of record\n", rec_idx);
+          exit (2);
+        }
+      result = ((result & 0x7f) << 8) | rec_buf[rec_idx++];
+    }
+  return result;
+}
+
+
+static dword get_dword (void)
+{
+  dword result;
+
+  if (rec_idx + 4 > rec_len)
+    {
+      fprintf (stderr, "\nDword at %d beyond end of record\n", rec_idx);
+      exit (2);
+    }
+  result = rec_buf[rec_idx++];
+  result |= rec_buf[rec_idx++] << 8;
+  result |= rec_buf[rec_idx++] << 16;
+  result |= rec_buf[rec_idx++] << 24;
+  return result;
+}
+
+
+static word get_word (void)
+{
+  word result;
+
+  if (rec_idx + 2 > rec_len)
+    {
+      fprintf (stderr, "\nWord at %d beyond end of record\n", rec_idx);
+      exit (2);
+    }
+  result = rec_buf[rec_idx++];
+  result |= rec_buf[rec_idx++] << 8;
+  return result;
+}
+
+
+static word get_byte (void)
+{
+  if (rec_idx + 1 > rec_len)
+    {
+      fprintf (stderr, "\nByte at %d beyond end of record\n", rec_idx);
+      exit (2);
+    }
+  return rec_buf[rec_idx++];
+}
+
+
+static dword get_word_or_dword (void)
+{
+  return (rec_type & REC32 ? get_dword () : get_word ());
+}
+
+
+static dword get_commlen (void)
+{
+  dword result;
+
+  result = get_byte ();
+  if (result <= 0x80)
+    return result;
+  switch (result)
+    {
+    case 0x81:
+      return get_word ();
+    case 0x84:
+      result = get_byte ();
+      result |= get_byte () << 8;
+      result |= get_byte () << 16;
+      return result;
+    case 0x88:
+      return get_dword ();
+    default:
+      fprintf (stderr, "\nUnknown COMDAT length prefix\n");
+      exit (2);
+    }
+}
+
+
+static void show_char (byte c)
+{
+  if (c == '\\')
+    printf ("\\\\");
+  else if (c < 0x20 || c > 0x7f)
+    printf ("\\%.3o", c);
+  else
+    putchar (c);
+}
+
+
+static void show_string (const byte *p)
+{
+  printf ("\"");
+  while (*p != 0)
+    show_char (*p++);
+  printf ("\"");
+}
+
+
+static void show_name (int index)
+{
+  if (index < 1 || index > lname_count)
+    printf ("#%d", index);
+  else
+    show_string (lname_list[index-1]);
+}
+
+
+static void show_seg (int index)
+{
+  if (index < 1 || index > segment_count)
+    printf ("#%d", index);
+  else
+    show_name (segment_list[index-1].name);
+}
+
+
+static void show_group (int index)
+{
+  if (index < 1 || index > group_count)
+    printf ("#%d", index);
+  else
+    show_name (group_list[index-1].name);
+}
+
+
+static void show_ext (int index)
+{
+  if (index < 1 || index > ext_count)
+    printf ("#%d", index);
+  else
+    show_string (ext_list[index-1].name);
+}
+
+
+static void show_enc (void)
+{
+  byte *p;
+
+  p = get_cpp_string ();
+  show_string (p);
+  free (p);
+}
+
+
+static void dump_block (int count, int indent)
+{
+  int x;
+
+  x = 0;
+  while (rec_idx < rec_len && count > 0)
+    {
+      --count;
+      if (x >= 16)
+        {
+          printf ("\n");
+          x = 0;
+        }
+      if (x == 0)
+        printf ("%*s", indent, "");
+      printf (" %.2x", rec_buf[rec_idx++]);
+      ++x;
+    }
+  if (x != 0)
+    printf ("\n");
+}
+
+
+static void dump_rest (void)
+{
+  dump_block (rec_len - rec_idx, 2);
+}
+
+
+static void add_ext (const byte *name)
+{
+  if (ext_count >= ext_alloc)
+    {
+      ext_alloc += 16;
+      ext_list = xrealloc (ext_list, ext_alloc * sizeof (*ext_list));
+    }
+  ext_list[ext_count++].name = xstrdup (name);
+}
+
+
+static void list_libhdr (void)
+{
+  byte flags;
+
+  printf ("LIBHDR:\n");
+  page_size = rec_len + 1 + 3;
+  printf ("  Page size: %u\n", page_size);
+  dict_offset = get_dword ();
+  printf ("  Dictionary offset: 0x%lx\n", dict_offset);
+  dict_blocks = get_word ();
+  printf ("  Dictionary blocks: %u\n", dict_blocks);
+  flags = get_byte ();
+  printf ("  Flags: 0x%.2x", flags);
+  if (flags & 0x01)
+    printf (" (case-sensitive)");
+  printf ("\n");
+}
+
+
+static void list_theadr (void)
+{
+  byte string[256];
+
+  if (page_size != 0)
+    printf ("------------------------------------------------------------\n");
+  show_record ("THEADR");
+  printf (" ");
+  get_string (string);
+  show_string (string);
+  printf ("\n");
+  lname_count = 0; segment_count = 0; group_count = 0;
+  ext_count = 0; pub_count = 0;
+  debug_type_index = 512;
+  debug_info = debug_default; hll_style = 0; linnum_started = FALSE;
+}
+
+
+static void list_coment (void)
+{
+  byte string[256], string2[256], string3[256];
+  byte flag, rec, subrec, c1, c2;
+  word ord = 0;
+  int len, ext1, ext2;
+
+  show_record ("COMENT");
+  printf (": ");
+  get_byte ();                  /* Comment type */
+  rec = get_byte ();
+  switch (rec)
+    {
+    case 0x9e:
+      printf ("DOSSEG\n");
+      break;
+
+    case 0x9f:
+      len = rec_len - rec_idx;
+      get_mem (string, len);
+      string[len] = 0;
+      printf ("Default library: ");
+      show_string (string);
+      break;
+
+    case 0xa0:
+      subrec = get_byte ();
+      switch (subrec)
+        {
+        case 0x01:
+          printf ("IMPDEF ");
+          flag = get_byte ();
+          get_string (string);
+          get_string (string2);
+          if (flag != 0)
+            {
+              ord = get_word ();
+              printf ("%s %s.%u", string, string2, ord);
+            }
+          else
+            {
+              get_string (string3);
+              if (string3[0] == 0)
+                strcpy (string3, string);
+              printf ("%s %s.%s", string, string2, string3);
+            }
+          break;
+
+        case 0x02:
+          printf ("EXPDEF ");
+          flag = get_byte ();
+          get_string (string);
+          get_string (string2);
+          if (flag & 0x80)
+            ord = get_word ();
+          show_string (string);
+          printf (" (");
+          show_string (string2);
+          printf (")");
+          if (flag & 0x80)
+            printf (" @%u", ord);
+          if (flag & 0x40)
+            printf (", resident");
+          if (flag & 0x20)
+            printf (", no data");
+          if (flag & 0x1f)
+            printf (", %u parameters", flag & 0x1f);
+          break;
+
+        case 0x04:
+          printf ("Protected DLL\n");
+          break;
+
+        default:
+          printf ("unknown comment class: %.2x\n", (unsigned)subrec);
+          dump_rest ();
+          return;               /* Don't print a newline */
+        }
+      break;
+
+    case 0xa1:
+      if (rec_idx + 3 > rec_len) /* Borland vs. IBM clash */
+        goto generic;
+      flag = get_byte ();
+      c1 = get_byte ();
+      c2 = get_byte ();
+      if (c1 == 'C' && c2 == 'V')
+        {
+          debug_info = debug_cv;
+          printf ("CodeView style (%u) debug tables", flag);
+        }
+      else if (c1 == 'H' && c2 == 'L')
+        {
+          debug_info = debug_hll;
+          hll_style = flag;
+          printf ("HLL style (%u) debug tables", flag);
+        }
+      else
+        printf ("New OMF extension");
+      break;
+
+    case 0xa2:
+      flag = get_byte ();
+      if (flag == 1)
+        printf ("Link pass separator");
+      else
+        printf ("Unknown link pass: %.2x", flag);
+      break;
+
+    case 0xa3:
+      get_string (string);
+      printf ("LIBMOD ");
+      show_string (string);
+      break;
+
+    case 0xa8:
+      ext1 = get_index ();
+      ext2 = get_index ();
+      printf ("WKEXT ");
+      show_ext (ext1);
+      printf (" ");
+      show_ext (ext2);
+      break;
+
+    case 0xaf:
+      get_string (string);
+      printf ("Identifier manipulator DLL: ");
+      show_string (string);
+      get_string (string);
+      printf (", initialization parameter: ");
+      show_string (string);
+      break;
+
+    default:
+generic:
+      printf ("unknown comment class: %.2x\n", rec);
+      dump_rest ();
+      return;                   /* Don't print a newline */
+    }
+  printf ("\n");
+}
+
+
+static void list_lnames (void)
+{
+  byte string[256];
+
+  show_record ("LNAMES");
+  printf (":\n");
+  while (rec_idx < rec_len)
+    {
+      get_string (string);
+      if (lname_count >= lname_alloc)
+        {
+          lname_alloc += 16;
+          lname_list = xrealloc (lname_list,
+                                 lname_alloc * sizeof (*lname_list));
+        }
+      lname_list[lname_count] = xstrdup (string);
+      ++lname_count;
+      printf ("  #%d: ", lname_count);
+      show_string (string);
+      printf ("\n");
+    }
+}
+
+
+static void list_segdef (void)
+{
+  int attributes, alignment, combination, frame, offset, name, class, overlay;
+  dword length;
+  struct segment *p;
+
+  frame = 0;                    /* Keep the compiler happy */
+
+  show_record ("SEGDEF");
+  printf (" #%d ", segment_count + 1);
+
+  attributes = get_byte ();
+  alignment = attributes >> 5;
+  combination = (attributes >> 2) & 7;
+  if (alignment == 0)
+    {
+      frame = get_word ();
+      offset = get_byte ();
+    }
+  length = get_word_or_dword ();
+  name = get_index ();
+  class = get_index ();
+  overlay = get_index ();
+  if (!(rec_type & REC32) && (attributes & 2))
+    length = 1L << 16;
+
+  if (segment_count >= segment_alloc)
+    {
+      segment_alloc += 8;
+      segment_list = xrealloc (segment_list,
+                               segment_alloc * sizeof (*segment_list));
+    }
+  p = &segment_list[segment_count++];
+  p->name = name;
+  p->class = class;
+  p->length = length;
+
+  show_name (name);
+  printf ("  ");
+  switch (alignment)
+    {
+    case 0:
+      printf ("AT %#.4x", frame);
+      break;
+    case 1:
+      printf ("BYTE");
+      break;
+    case 2:
+      printf ("WORD");
+      break;
+    case 3:
+      printf ("PARA");
+      break;
+    case 4:
+      printf ("PAGE");
+      break;
+    case 5:
+      printf ("DWORD");
+      break;
+    case 6:
+      printf ("unknown alignment: %d", alignment);
+      break;
+    }
+  printf (" ");
+  switch (combination)
+    {
+    case 0:
+      printf ("PRIVATE");
+      break;
+    case 2:
+    case 4:
+    case 7:
+      printf ("PUBLIC");
+      break;
+    case 5:
+      printf ("STACK");
+      break;
+    case 6:
+      printf ("COMMON");
+      break;
+    default:
+      printf ("unknown combination: %d", combination);
+      break;
+    }
+  if (attributes & 1)
+    printf (" USE32");
+  printf (" Length: %#lx", length);
+  printf (" CLASS ");
+  show_name (class);
+  printf ("\n");
+}
+
+
+static void list_grpdef (void)
+{
+  int name, type, seg;
+
+  show_record ("GRPDEF");
+  printf (" #%d ", group_count + 1);
+
+  name = get_index ();
+  if (group_count >= group_alloc)
+    {
+      group_alloc += 8;
+      group_list = xrealloc (group_list,
+                             group_alloc * sizeof (*group_list));
+    }
+  group_list[group_count++].name = name;
+  show_name (name);
+  printf (":");
+  while (rec_idx < rec_len)
+    {
+      type = get_byte ();
+      if (type != 0xff)
+        printf (" [unknown type: %#x] ", type);
+      seg = get_index ();
+      printf (" ");
+      show_seg (seg);
+    }
+  printf ("\n");
+}
+
+
+static void list_extdef (void)
+{
+  int type;
+  byte name[256];
+
+  show_record ("EXTDEF");
+  printf (":\n");
+
+  while (rec_idx < rec_len)
+    {
+      printf ("  #%d: ", ext_count + 1);
+      get_string (name);
+      show_string (name);
+      type = get_index ();
+      printf (", type: %d\n", type);
+      add_ext (name);
+    }
+}
+
+
+static void list_pubdef (void)
+{
+  int type, group, seg;
+  dword offset;
+  byte name[256];
+
+  show_record ("PUBDEF");
+  group = get_index ();
+  seg = get_index ();
+  printf (" base group: ");
+  show_group (group);
+  printf (", base seg: ");
+  show_seg (seg);
+  if (seg == 0)
+    printf (", frame=0x%.4x", get_word ());
+  printf ("\n");
+
+  while (rec_idx < rec_len)
+    {
+      printf ("  #%d: ", pub_count + 1);
+      get_string (name);
+      show_string (name);
+      offset = get_word_or_dword ();
+      type = get_index ();
+      printf (", offset: %#lx, type: %d\n", offset, type);
+      ++pub_count;
+    }
+}
+
+
+static void list_comdef (void)
+{
+  int type_index, data_type;
+  byte name[256];
+  dword comm_len, comm_count;
+
+  show_record ("COMDEF");
+  printf ("\n");
+  while (rec_idx < rec_len)
+    {
+      get_string (name);
+      type_index = get_index ();
+      data_type = get_byte ();
+      printf ("  #%d: ", ext_count + 1);
+      show_string (name);
+      printf (", type index: %d, ", type_index);
+      switch (data_type)
+        {
+        case 0x61:
+          comm_count = get_commlen ();
+          comm_len = get_commlen ();
+          printf ("FAR, %lu times %lu bytes\n", comm_count, comm_len);
+          break;
+        case 0x62:
+          comm_len = get_commlen ();
+          printf ("NEAR, %lu bytes\n", comm_len);
+          break;
+        default:
+          printf ("unknown data type: %#x\n", data_type);
+          dump_rest ();
+          return;
+        }
+      add_ext (name);
+    }
+  dump_rest ();
+}
+
+
+static void list_alias (void)
+{
+  byte name[256];
+
+  show_record ("ALIAS");
+  printf (": ");
+  get_string (name);
+  show_string (name);
+  printf (" ");
+  get_string (name);
+  show_string (name);
+  printf ("\n");
+  dump_rest ();
+}
+
+
+static void list_symbols (void)
+{
+  int len, next, total_rec_len, sst, location, loc_base, start;
+  word seg, file;
+  dword offset, length, reg, line;
+  dword type, prologue, body, reserved, near_far, compiler_id, class_type;
+  byte name[256];
+  struct timestamp ts;
+
+  total_rec_len = rec_len;
+  loc_base = rec_idx;
+  while (rec_idx < rec_len)
+    {
+      start = rec_idx;
+      len = get_byte ();
+      if (len == 0)
+        {
+          printf ("Length of SST entry is 0\n");
+          break;
+        }
+      --len;
+      sst = get_byte ();
+      next = rec_idx + len;
+      rec_len = next;
+      printf ("  ");
+      switch (sst)
+        {
+        case 0x00:
+          printf ("Begin ");
+          location = rec_idx - loc_base;
+          offset = get_dword ();
+          length = get_dword ();
+          printf ("offset: %#lx [@%#x], length: %#lx",
+                  offset, location, length);
+          if (rec_idx < rec_len)
+            {
+              get_string (name);
+              printf (" ");
+              show_string (name);
+            }
+          break;
+        case 0x01:
+        case 0x0f:
+        case 0x1a:
+        case 0x1d:
+          switch (sst)
+            {
+            case 0x01:
+              printf ("Proc ");
+              break;
+            case 0x0f:
+              printf ("Entry ");
+              break;
+            case 0x1a:
+              printf ("MemFunc ");
+              break;
+            case 0x1d:
+              printf ("C++Proc ");
+              break;
+            default:
+              abort ();
+            }
+          location = rec_idx - loc_base;
+          offset = get_dword ();
+          type = get_word ();
+          length = get_dword ();
+          prologue = get_word ();
+          body = get_dword ();
+          class_type = get_word ();
+          near_far = get_byte ();
+          if (sst == 0x1a || sst == 0x1d)
+            show_enc ();
+          else
+            {
+              get_string (name);
+              show_string (name);
+            }
+          printf (", offset: %#lx [@%#x], type: #%lu\n",
+                  offset, location, type);
+          printf ("       length: %#lx, pro: %#lx, pro+body: %#lx, ",
+                  length, prologue, body);
+          switch (near_far)
+            {
+            case 0x00:
+              printf ("16-bit near");
+              break;
+            case 0x04:
+              printf ("16-bit far");
+              break;
+            case 0x08:
+              printf ("32-bit near");
+              break;
+            case 0x0c:
+              printf ("32-bit far");
+              break;
+            default:
+              printf ("nf: %#lx", near_far);
+              break;
+            }
+          if (sst == 0x1a)      /* Member function */
+            printf ("\n       class type: #%lu", class_type);
+          break;
+        case 0x02:
+          printf ("End");
+          break;
+        case 0x04:
+          printf ("Auto ");
+          offset = get_dword ();
+          type = get_word ();
+          get_string (name);
+          show_string (name);
+          printf (", offset: %#lx, type: #%lu", offset, type);
+          break;
+        case 0x05:
+        case 0x1e:
+          if (sst == 0x1e)
+            printf ("C++Static ");
+          else
+            printf ("Static ");
+          location = rec_idx - loc_base;
+          offset = get_dword ();
+          seg = get_word ();
+          type = get_word ();
+          if (sst == 0x1e)
+            show_enc ();
+          else
+            {
+              get_string (name);
+              show_string (name);
+            }
+          printf (", offset: %#lx [@%#x], seg: %u [@%#x], type: #%lu",
+                  offset, location, seg, location + 4, type);
+          break;
+        case 0x0b:
+          printf ("CodeLabel ");
+          location = rec_idx - loc_base;
+          offset = get_dword ();
+          near_far = get_byte ();
+          get_string (name);
+          printf ("offset: %#lx [@%#x]", offset, location);
+          show_string (name);
+          break;
+        case 0x0c:
+          printf ("With");
+          break;
+        case 0x0d:
+          printf ("Reg ");
+          type = get_word ();
+          reg = get_byte ();
+          get_string (name);
+          show_string (name);
+          printf (", ");
+          switch (reg)
+            {
+            case 0x00:
+              printf ("AL");
+              break;
+            case 0x01:
+              printf ("CL");
+              break;
+            case 0x02:
+              printf ("DL");
+              break;
+            case 0x03:
+              printf ("BL");
+              break;
+            case 0x04:
+              printf ("AH");
+              break;
+            case 0x05:
+              printf ("CH");
+              break;
+            case 0x06:
+              printf ("DH");
+              break;
+            case 0x07:
+              printf ("BH");
+              break;
+            case 0x08:
+              printf ("AX");
+              break;
+            case 0x09:
+              printf ("CX");
+              break;
+            case 0x0a:
+              printf ("DX");
+              break;
+            case 0x0b:
+              printf ("BX");
+              break;
+            case 0x0c:
+              printf ("SP");
+              break;
+            case 0x0d:
+              printf ("BP");
+              break;
+            case 0x0e:
+              printf ("SI");
+              break;
+            case 0x0f:
+              printf ("DI");
+              break;
+            case 0x10:
+              printf ("EAX");
+              break;
+            case 0x11:
+              printf ("ECX");
+              break;
+            case 0x12:
+              printf ("EDX");
+              break;
+            case 0x13:
+              printf ("EBX");
+              break;
+            case 0x14:
+              printf ("ESP");
+              break;
+            case 0x15:
+              printf ("EBP");
+              break;
+            case 0x16:
+              printf ("ESI");
+              break;
+            case 0x17:
+              printf ("EDI");
+              break;
+            case 0x18:
+              printf ("ES"); /* error in documentation */
+              break;
+            case 0x19:
+              printf ("CS");
+              break;
+            case 0x1a:
+              printf ("SS");
+              break;
+            case 0x1b:
+              printf ("DS");
+              break;
+            case 0x1c:
+              printf ("FS");
+              break;
+            case 0x1d:
+              printf ("GS");
+              break;
+            case 0x20:
+              printf ("DX:AX");
+              break;
+            case 0x21:
+              printf ("ES:BX");
+              break;
+            case 0x22:
+              printf ("IP");
+              break;
+            case 0x23:
+              printf ("FLAGS");
+              break;
+            case 0x24:
+              printf ("EFLAGS");
+              break;
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+              printf ("ST(%lu)", reg - 0x80);
+              break;
+            default:
+              printf ("unknown register: %#.2lx", reg);
+            }
+          break;
+        case 0x0e:
+          printf ("Constant");
+          break;
+        case 0x10:
+          printf ("Skip");
+          break;
+        case 0x11:
+          printf ("ChangSeg ");
+          location = rec_idx - loc_base;
+          seg = get_word ();
+          reserved = get_word ();
+          printf ("segment: %u [@%#x]", seg, location);
+          printf (", reserved: %#lx", reserved);
+          break;
+        case 0x12:
+          printf ("Typedef");
+          break;
+        case 0x13:
+          printf ("Public");
+          break;
+        case 0x14:
+          printf ("Member ");
+          offset = get_dword ();
+          printf ("offset: %#lx, name: ", offset);
+          get_string (name);
+          show_string (name);
+          break;
+        case 0x15:
+          printf ("Based ");
+          offset = get_dword ();
+          type = get_word ();
+          printf ("offset: %#lx, type: #%lu, name: ", offset, type);
+          get_string (name);
+          show_string (name);
+          break;
+        case 0x16:
+          printf ("Tag ");
+          type = get_word ();
+          printf ("type: #%lu, name: ", type);
+          get_string (name);
+          show_string (name);
+          break;
+        case 0x17:
+          printf ("Table");
+          break;
+        case 0x18:
+          printf ("Map ");
+          get_string (name);
+          show_string (name);
+          printf (" to external ");
+          get_string (name);
+          show_string (name);
+          break;
+        case 0x19:
+          printf ("Class ");
+          type = get_word ();
+          printf ("type: #%lu, name: ", type);
+          show_enc ();
+          break;
+        case 0x1b:
+          printf ("AutoScoped ");
+          offset = get_dword ();
+          file = get_word ();
+          line = get_dword ();
+          type = get_word ();
+          get_string (name);
+          printf ("offset: %#lx, source file: %u, line: %lu, type: #%lu\n",
+                  offset, file, line, type);
+          printf ("    name: ");
+          show_string (name);
+          break;
+        case 0x1c:
+          printf ("StaticScoped ");
+          offset = get_dword ();
+          seg = get_word ();
+          file = get_word ();
+          line = get_dword ();
+          type = get_word ();
+          get_string (name);
+          printf ("offset: %#lx, segment: %u, source file: %u, "
+                  "line: %lu, type: %lu\n",
+                  offset, seg, file, line, type);
+          printf ("    name: ");
+          show_string (name);
+          break;
+        case 0x40:
+          printf ("CuInfo: ");
+          compiler_id = get_byte ();
+          switch (compiler_id)
+            {
+            case 0x01:
+              printf ("C");
+              break;
+            case 0x02:
+              printf ("C++");
+              break;
+            case 0x03:
+              printf ("PL/X-86");
+              break;
+            case 0x04:
+              printf ("PL/I");
+              break;
+            default:
+              printf ("unknown compiler id: %#lx", compiler_id);
+              break;
+            }
+          printf (", options: ");
+          get_string (name);
+          show_string (name);
+          printf (", compiler date: ");
+          get_string (name);
+          show_string (name);
+          printf ("\n    time stamp: ");
+          get_mem (&ts, sizeof (ts));
+          printf ("%d/%.2d/%.2d %.2d:%.2d:%.2d.%.2d",
+                  ts.year, ts.month, ts.day, ts.hours,
+                  ts.minutes, ts.seconds, ts.hundredths);
+          break;
+        default:
+          printf ("unknown SST type %#.2x at %d", sst, start);
+          break;
+        }
+      printf ("\n");
+      rec_idx = next;
+      rec_len = total_rec_len;
+    }
+}
+
+
+
+static void show_fid (void)
+{
+  int fid, index, i;
+  byte str[256];
+  dword d;
+
+  fid = get_byte ();
+  switch (fid)
+    {
+    case 0x80:
+      printf ("(nil)");
+      break;
+    case 0x81:
+      printf ("void");
+      break;
+    case 0x82:
+      get_string (str);
+      show_string (str);
+      break;
+    case 0x83:
+      index = get_word ();
+      switch (index)
+        {
+        case 0x80:
+          printf ("signed char");
+          break;
+        case 0x81:
+          printf ("signed short");
+          break;
+        case 0x82:
+          printf ("signed long");
+          break;
+        case 0x84:
+          printf ("unsigned char");
+          break;
+        case 0x85:
+          printf ("unsigned short");
+          break;
+        case 0x86:
+          printf ("unsigned long");
+          break;
+        case 0x88:
+          printf ("float");
+          break;
+        case 0x89:
+          printf ("double");
+          break;
+        case 0x8a:
+          printf ("long double");
+          break;
+        case 0x97:
+          printf ("void");
+          break;
+        case 0xa0:
+          printf ("signed char *");
+          break;
+        case 0xa1:
+          printf ("signed short *");
+          break;
+        case 0xa2:
+          printf ("signed long *");
+          break;
+        case 0xa4:
+          printf ("signed char *");
+          break;
+        case 0xa5:
+          printf ("signed short *");
+          break;
+        case 0xa6:
+          printf ("signed long *");
+          break;
+        case 0xa8:
+          printf ("float *");
+          break;
+        case 0xa9:
+          printf ("double *");
+          break;
+        case 0xaa:
+          printf ("long double *");
+          break;
+        case 0xb7:
+          printf ("void *");
+          break;
+        default:
+          printf ("#%d", index);
+          break;
+        }
+      break;
+    case 0x85:
+      i = get_word ();
+      printf ("%u", i);
+      break;
+    case 0x86:
+      d = get_dword ();
+      printf ("%lu", d);
+      break;
+    case 0x88:
+      i = get_byte ();
+      if (i >= 0x80)
+        i -= 0x80;
+      printf ("%d", i);
+      break;
+    case 0x89:
+      i = get_word ();
+      if (i >= 0x8000)
+        i -= 0x8000;
+      printf ("%d", i);
+      break;
+    case 0x8a:
+      d = get_dword ();
+      printf ("%ld", d);
+      break;
+    case 0x8b:
+      i = get_byte ();
+      printf ("%u", i);
+      break;
+    default:
+      fprintf (stderr, "unknown FID: %#.2x\n", fid);
+      exit (2);
+    }
+}
+
+
+static void list_protection (void)
+{
+  int flags;
+
+  flags = get_byte ();
+  switch (flags)
+    {
+    case 0x00:
+      printf ("private");
+      break;
+    case 0x01:
+      printf ("protected ");
+      break;
+    case 0x02:
+      printf ("public");
+      break;
+    default:
+      printf ("unknown protection: %#x", flags);
+      break;
+    }
+}
+
+
+static void list_types (void)
+{
+  int total_rec_len, type, qual, len, next, flags;
+  int args, max_args, fields;
+  dword size;
+
+  flags = 0;                    /* Keep the optimizer happy */
+  total_rec_len = rec_len;
+  while (rec_idx < rec_len)
+    {
+      len = get_word ();
+      next = rec_idx + len;
+      type = get_byte ();
+      qual = get_byte ();
+      printf ("  #%d: ", debug_type_index++);
+      if (next < total_rec_len)
+        rec_len = next;
+      switch (type)
+        {
+        case 0x40:
+          printf ("Class: ");
+          if (qual & 1)
+            printf ("is_struct ");
+          if (qual & ~1)
+            printf ("(qual: %#x) ", qual);
+          size = get_dword ();
+          fields = get_word ();
+          printf ("size: %#lx, %d items: ", size, fields);
+          printf ("#%u, name: ", get_word());
+          show_enc ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x41:
+          printf ("Base Class: ");
+          if (qual & 1)
+            printf ("virtual, ");
+          if ((qual & ~1))
+            printf ("(qual: %#x) ", qual);
+          list_protection ();
+          printf (", class: #%u, offset: ", get_word ());
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x42:
+          printf ("Friend: ");
+          if (qual & 1)
+            printf ("class ");
+          else
+            printf ("function ");
+          if (qual & ~1)
+            printf ("(qual: %#x) ", qual);
+          printf ("type: #%u ", get_word ());
+          printf (", name: ");
+          show_enc ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x43:
+          printf ("Class Definition: ");
+          if (qual != 0)
+            printf ("(qual: %#x) ", qual);
+          list_protection ();
+          printf (", typedef #%u", get_word ());
+          printf (", class #%u\n", get_word ());
+          dump_rest ();
+          break;
+
+        case 0x45:
+          printf ("Member function: ");
+          if (qual & 0x01)
+            printf ("static ");
+          if (qual & 0x02)
+            printf ("inline ");
+          if (qual & 0x04)
+            printf ("const ");
+          if (qual & 0x08)
+            printf ("volatile ");
+          if (qual & 0x10)
+            printf ("virtual ");
+          if (qual & ~0x1f)
+            printf ("(qual: %#x) ", qual);
+          list_protection ();
+          type = get_byte ();
+          switch (type)
+            {
+            case 0:
+              break;
+            case 1:
+              printf (", constructor");
+              break;
+            case 2:
+              printf (", destructor");
+              break;
+            default:
+              printf (", unknown type: %#x", type);
+              break;
+            }
+          type = get_word ();
+          printf (", type: #%u", type);
+          if (qual & 0x10)
+            {
+              printf (", virtual table index: ");
+              show_fid ();
+            }
+          printf ("\n    name: ");
+          show_enc ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x46:
+          printf ("Class Member: ");
+          if (qual & 0x01)
+            printf ("static ");
+          if (qual & 0x02)
+            printf ("vtbl_ptr ");
+          if (qual & 0x04)
+            printf ("vbase_ptr ");
+          if (qual & 0x08)
+            printf ("const ");
+          if (qual & 0x10)
+            printf ("volatile ");
+          if (qual & 0x20)
+            printf ("self_ptr ");
+          if ((qual & ~0x3f) != 0)
+            printf ("(qual: %#x) ", qual);
+          list_protection ();
+          printf (", type: #%u, offset: ", get_word ());
+          show_fid ();
+          printf (",\n    static name: ");
+          show_enc ();
+          printf (", name: ");
+          show_enc ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x48:
+          printf ("Reference: ");
+          if (qual != 0)
+            printf ("(qual: %#x) ", qual);
+          printf ("type: #%u\n", get_word ());
+          dump_rest ();
+          break;
+
+        case 0x49:
+          printf ("Member Pointer: ");
+          if (qual & 0x01)
+            printf ("has vbases, ");
+          if (qual & 0x02)
+            printf ("has mult-inh, ");
+          if (qual & 0x04)
+            printf ("const ");
+          if (qual & 0x08)
+            printf ("volatile ");
+          if (qual & ~0x0f)
+            printf ("qual: %#x, ", qual);
+          printf ("child type: #%u, ", get_word ());
+          printf ("class type: #%u, ", get_word ());
+          printf ("representation type: #%u\n", get_word ());
+          dump_rest ();
+          break;
+
+        case 0x52:
+          printf ("Set: ");
+          if (qual != 0)
+            printf ("qual: %#x, ", qual);
+          printf ("type: ");
+          show_fid ();
+          printf (", name: ");
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x54:
+          printf ("Function: ");
+          args = get_word ();
+          max_args = get_word ();
+          printf ("qual: %#x, %d argument%s (%d maximum), returns ",
+                  qual, args, (args == 1 ? "" : "s"), max_args);
+          show_fid ();
+          printf (",\n    argument list: ");
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x57:
+          printf ("Stack: ");
+          if (qual & 0x01)
+            printf ("32-bit ");
+          if (qual & 0x02)
+            printf ("far ");
+          if (qual & ~0x03)
+            printf ("qual: %#x, ", qual);
+          size = get_dword ();
+          printf ("size: %#lx, name: ", size);
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x5c:
+          printf ("Bit string: ");
+          if (qual & 1)
+            printf ("varying, ");
+          if (qual & 2)
+            printf ("signed, ");
+          if (qual & 4)
+            printf ("word alignment, ");
+          if (qual & 8)
+            printf ("display as value, ");
+          if (qual & 0x10)
+            printf ("descriptor, ");
+          if (qual & ~0x1f)
+            printf ("qual: %#x, ", qual);
+          printf ("offset: %d, size: ", get_byte ());
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x5d:
+          printf ("User defined type: ");
+          if (qual != 0)
+            printf ("qual: %#x, ", qual);
+          printf ("type: ");
+          show_fid ();
+          printf (", name: ");
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x6f:
+          printf ("Subrange: ");
+          if (qual != 0)
+            printf ("qual: %#x, ", qual);
+          printf ("type: ");
+          show_fid ();
+          printf (", start: ");
+          show_fid ();
+          printf (", end: ");
+          show_fid ();
+          printf (", name: ");
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x72:
+          printf ("Code Label: ");
+          if (qual & 1)
+            printf ("32-bit ");
+          else
+            printf ("16-bit ");
+          if (qual & 2)
+            printf ("far");
+          else
+            printf ("near");
+          if (qual & ~3)
+            printf (" (qual: %#x)", qual);
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x78:
+          printf ("Array: ");
+          if (qual & 1)
+            printf ("col-maj ");
+          else
+            printf ("row-maj ");
+          if (qual & 2)
+            printf ("(packed) ");
+          if (qual & 4)
+            printf ("desc provided) ");
+          if (qual & ~7)
+            printf ("(qual: %#x) ", qual);
+          size = get_dword ();
+          printf ("size: %#lx, bounds type: ", size);
+          show_fid ();
+          printf (", elements type: ");
+          show_fid ();
+          printf (", name: ");
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x79:
+          printf ("Structure: ");
+          if (qual != 0)
+            printf ("(qual: %#x) ", qual);
+          size = get_dword ();
+          fields = get_word ();
+          printf ("size: %#lx, %d fields: ", size, fields);
+          show_fid ();
+          printf (", names: ");
+          show_fid ();
+          printf (", tag: ");
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x7a:
+          printf ("Pointer: ");
+          show_fid ();
+          if (rec_idx < rec_len)
+            {
+              printf (", name: ");
+              show_fid ();
+            }
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x7b:
+          printf ("Enum: ");
+          if (qual != 0)
+            printf ("(qual: %#x) ", qual);
+          printf ("type: ");
+          show_fid ();
+          printf (", values: ");
+          show_fid ();
+          printf (", minimum: ");
+          show_fid ();
+          printf (", maximum: ");
+          show_fid ();
+          printf ("\n");
+          dump_rest ();
+          break;
+
+        case 0x7f:
+          printf ("List");
+          switch (qual)
+            {
+            case 0x01:
+              printf (" (field types)");
+              break;
+            case 0x02:
+              printf (" (field names and offsets)");
+              break;
+            case 0x03:
+              printf (" (enumeration)");
+              break;
+            case 0x04:
+              printf (" (arguments)");
+              break;
+            }
+          printf (":\n");
+          while (rec_idx < rec_len)
+            {
+              printf ("    ");
+              if (qual == 0x04)
+                flags = get_byte ();
+              show_fid ();
+              switch (qual)
+                {
+                case 0x02:
+                  printf (", offset: ");
+                  show_fid ();
+                  break;
+                case 0x03:
+                  printf (", value: ");
+                  show_fid ();
+                  break;
+                case 0x04:
+                  if (flags & 0x01)
+                    printf (" by value");
+                  else
+                    printf (" by address");
+                  if (flags & 0x02)
+                    printf (", descriptor provided");
+                  if (flags & ~0x03)
+                    printf (" (flags: %#x)", flags);
+                  break;
+                }
+              printf ("\n");
+            }
+          dump_rest ();
+          break;
+
+        default:
+          printf ("unknown complex type: %#.2x\n", type);
+          dump_rest ();
+          break;
+        }
+      rec_idx = next;
+      rec_len = total_rec_len;
+    }
+}
+
+
+static void list_ledata (void)
+{
+  int len;
+  dword offset, seg;
+  char *name;
+
+  show_record ("LEDATA");
+
+  seg = get_index ();
+  offset = get_word_or_dword ();
+  len = rec_len - rec_idx;
+
+  printf (" ");
+  show_seg (seg);
+  printf (" offset: %#lx length: %#x\n", offset, len);
+  name = lname_list[segment_list[seg-1].name-1];
+  if (strcmp (name, "$$SYMBOLS") == 0 && list_debug
+      && debug_info == debug_hll && hll_style >= 3)
+    list_symbols ();
+  else if (strcmp (name, "$$TYPES") == 0 && list_debug
+           && debug_info == debug_hll && hll_style >= 3)
+    list_types ();
+  else
+    dump_rest ();
+}
+
+
+static void list_block (int level)
+{
+  dword rep_count, block_count;
+  int indent, len;
+
+  indent = (level + 1) * 2;
+  rep_count = get_word_or_dword ();
+  block_count = get_word ();
+  if (block_count == 0)
+    {
+      len = get_byte ();
+      printf ("%*sRepeat count: %lu, data length: %d\n",
+              indent, "", rep_count, len);
+      dump_block (len, indent + 2);
+    }
+  else
+    {
+      printf ("%*sRepeat count: %lu, block count: %lu\n",
+              indent, "", rep_count, block_count);
+      while (block_count > 0)
+        {
+          list_block (level + 1);
+          --block_count;
+        }
+    }
+}
+
+
+static void list_lidata (void)
+{
+  dword offset, seg;
+
+  show_record ("LIDATA");
+
+  seg = get_index ();
+  offset = get_word_or_dword ();
+
+  printf (" ");
+  show_seg (seg);
+  printf (" offset: %#lx length: %#x\n", offset, rec_len - rec_idx);
+  while (rec_len - rec_idx >= 4)
+    list_block (0);
+  dump_rest ();
+}
+
+
+static void list_target (int method)
+{
+  switch (method)
+    {
+    case 0:
+      printf ("T0 (seg ");
+      show_seg (get_index ());
+      printf (")");
+      break;
+    case 1:
+      printf ("T1 (group ");
+      show_group (get_index ());
+      printf (")");
+      break;
+    case 2:
+      printf ("T2 (ext ");
+      show_ext (get_index ());
+      printf (")");
+      break;
+    default:
+      printf ("T%d (index #%d)", method & 3, get_index ());
+                break;
+    }
+}
+
+
+static void list_frame (int method)
+{
+  switch (method)
+    {
+    case 0:
+      printf ("F0 (seg ");
+      show_seg (get_index ());
+      printf (")");
+      break;
+    case 1:
+      printf ("F1 (group ");
+      show_group (get_index ());
+      printf (")");
+      break;
+    case 2:
+      printf ("F2 (ext");
+      show_ext (get_index ());
+      printf (")");
+      break;
+    case 4:
+      printf ("F4 (cur seg)");
+      break;
+    case 5:
+      printf ("F5 (target)");
+      break;
+    default:
+      printf ("F%d", method);
+      if (method <= 2)
+        printf (" (index #%d)", get_index ());
+      break;
+    }
+}
+
+
+static void list_fixupp (void)
+{
+  int first, locat, method, offset, fix_data;
+
+  show_record ("FIXUPP");
+  printf (":\n");
+  while (rec_idx < rec_len)
+    {
+      first = get_byte ();
+      if (first & 0x80)
+        {
+          printf ("  FIXUP ");
+          if (first & 0x40)
+            printf ("seg-rel, ");
+          else
+            printf ("self-rel, ");
+          locat = (first >> 2) & 0x0f;
+          switch (locat)
+            {
+            case 0:
+              printf ("LOW-8");
+              break;
+            case 1:
+              printf ("OFFSET-16");
+              break;
+            case 2:
+              printf ("SEL-16");
+              break;
+            case 3:
+              printf ("FAR-16:16");
+              break;
+            case 4:
+              printf ("HIGH-8");
+              break;
+            case 5:
+              printf ("OFFSET-16(LR)");
+              break;
+            case 9:
+              printf ("OFFSET-32");
+              break;
+            case 11:
+              printf ("FAR-16:32");
+              break;
+            case 13:
+              printf ("OFFSET-32(LR)");
+              break;
+            default:
+              printf ("unknown location: %d", locat);
+              break;
+            }
+          offset = get_byte ();
+          offset |= (first & 3) << 8;
+          printf (", offset: %#x, ", offset);
+          fix_data = get_byte ();
+          if (fix_data & 0x80)
+            printf ("frame thread %d", (fix_data >> 4) & 3);
+          else
+            list_frame ((fix_data >> 4) & 7);
+          if (fix_data & 0x08)
+            printf (", target thread %d P=%d",
+                    fix_data & 3, (fix_data >> 2) & 1);
+          else
+            {
+              printf (", ");
+              list_target (fix_data & 3);
+            }
+          if (!(fix_data & 0x04))
+            printf (", disp: %#lx", get_word_or_dword ());
+        }
+      else
+        {
+          method = (first >> 2) & 7;
+          printf ("  THREAD %d ", first & 3);
+          if (first & 0x40)
+            {
+              list_frame (method);
+              printf (", P=%d", (first >> 4) & 1);
+            }
+          else
+            list_target (method & 3);
+        }
+      printf ("\n");
+    }
+}
+
+
+static void list_hll_linnum (void)
+{
+  int group, segment;
+  dword i, addr, files, line, stmt, lst_line, first_col, num_cols;
+  word src_line, index;
+  byte reserved;
+  byte name[256];
+
+  group = get_index ();
+  segment = get_index ();
+  printf (": group: %d, segment: ", group);
+  show_seg (segment);
+  if (!linnum_started)
+    {
+      printf (", ");
+      line = get_word ();
+      if (line != 0)
+        printf ("must_be_zero: %ld, ", line);
+      linnum_entry_type = get_byte ();
+      switch (linnum_entry_type)
+        {
+        case 0x00:
+          printf ("source file");
+          break;
+        case 0x01:
+          printf ("listing file");
+          break;
+        case 0x02:
+          printf ("source & listing file");
+          break;
+        default:
+          printf ("undefined entry type: %#x", linnum_entry_type);
+          break;
+        }
+      reserved = get_byte ();
+      printf (", reserved=%#x\n", reserved);
+      line_count = get_word ();
+      segment = get_word ();
+      names_length = get_dword ();
+      printf ("%d line%s, segment: %u, name table length: %#lx",
+              line_count, (line_count == 1 ? "" : "s"), segment, names_length);
+      linnum_started = TRUE;
+    }
+  printf ("\n");
+  while (rec_idx < rec_len && line_count != 0)
+    {
+      switch (linnum_entry_type)
+        {
+        case 0x00:
+          src_line = get_word ();
+          index = get_word ();
+          addr = get_dword ();
+          printf ("  Line %6u of file %u at 0x%.8lx", src_line, index, addr);
+          break;
+        case 0x01:
+          lst_line = get_dword ();
+          stmt = get_dword ();
+          addr = get_dword ();
+          printf ("  Line %6lu, statement %6lu at 0x%.8lx",
+                  lst_line, stmt, addr);
+          break;
+        case 0x02:
+          src_line = get_word ();
+          index = get_word ();
+          lst_line = get_dword ();
+          stmt = get_dword ();
+          addr = get_dword ();
+          printf ("  Line %6u of file %u, ", src_line, index);
+          printf ("listing line %6lu, statement %6lu at 0x%.8lx",
+                  lst_line, stmt, addr);
+          break;
+        default:
+          printf ("  ????");
+          break;
+        }
+      printf ("\n");
+      --line_count;
+    }
+
+  /* Path table comes next, ignored... */
+
+  /* Note: this will fail if the name table is split */
+
+  if (rec_idx < rec_len)
+    {
+      first_col = get_dword ();
+      num_cols = get_dword ();
+      files = get_dword ();
+      printf ("  first column: %lu, columns: %lu, number of files: %ld\n",
+              first_col, num_cols, files);
+      for (i = 0; i < files; ++i)
+        {
+          printf ("  #%lu: ", i + 1);
+          get_string (name);
+          show_string (name);
+          printf ("\n");
+        }
+    }
+  if (line_count == 0)
+    linnum_started = FALSE;
+}
+
+
+static void list_modend (FILE *f)
+{
+  int type, end_data;
+  long pos;
+
+  show_record ("MODEND");
+  printf (": ");
+  type = get_byte ();
+  if (type & 0x80)
+    printf ("main ");
+  if (type & 0x40)
+    {
+      if (type & 0x01)
+        printf ("rel-");
+      printf ("start: ");
+      end_data = get_byte ();
+      if (end_data & 0x80)
+        printf ("frame thread %d", (end_data >> 4) & 3);
+      else
+        list_frame ((end_data >> 4) & 7);
+      if (end_data & 0x08)
+        printf (", target thread %d P=%d",
+                end_data & 3, (end_data >> 2) & 1);
+      else
+        {
+          printf (", ");
+          list_target (end_data & 3);
+        }
+      if (!(end_data & 0x04))   /* This bit must always be clear! */
+        printf (", disp: %#lx", get_word_or_dword ());
+    }
+  printf ("\n");
+  dump_rest ();
+  if (page_size == 0)
+    done = TRUE;
+  else
+    {
+      pos = ftell (f);
+      if (pos % page_size != 0)
+        fseek (f, page_size * (1 + pos / page_size), SEEK_SET);
+    }
+}
+
+
+static int list_libend (FILE *f)
+{
+  byte dblock[512];
+  unsigned dblockno, offset, bn;
+  int bucket, i, len;
+
+  done = TRUE;
+  printf ("LIBEND\n");
+  fseek (f, dict_offset, SEEK_SET);
+  for (dblockno = 0; dblockno < dict_blocks; ++dblockno)
+    {
+      printf ("Dictionary block %u: ", dblockno);
+      if (fread (dblock, 512, 1, f) != 1)
+        {
+          putchar ('\n');
+          return -1;
+        }
+      if (dblock[37] == 0xff)
+        printf ("full\n");
+      else
+        printf ("free space at 0x%.3x\n", dblock[37] * 2);
+      for (bucket = 0; bucket < 37; ++bucket)
+        if (dblock[bucket] != 0)
+          {
+            offset = dblock[bucket] * 2;
+            printf ("  Bucket %2u: offset=0x%.3x", bucket, offset);
+            if (offset < 38)
+              putchar ('\n');
+            else
+              {
+                len = dblock[offset];
+                ++offset;
+                if (offset + len + 2 > 512)
+                  printf (" (record extends beyond end of block)\n");
+                else
+                  {
+                    printf (" name=\"");
+                    for (i = 0; i < len; ++i)
+                      show_char (dblock[offset++]);
+                    bn = dblock[offset++];
+                    bn |= dblock[offset++] << 8;
+                    printf ("\" block=%u\n", bn);
+                  }
+              }
+          }
+    }
+  return 0;
+}
+
+
+static void list_omf (const char *fname)
+{
+  FILE *f;
+  struct omf_rec rec;
+
+  f = fopen (fname, "rb");
+  if (f == NULL)
+    {
+      perror (fname);
+      exit (2);
+    }
+  lname_count = 0; lname_alloc = 0; lname_list = NULL;
+  segment_count = 0; segment_alloc = 0; segment_list = NULL;
+  group_count = 0; group_alloc = 0; group_list = NULL;
+  ext_count = 0; ext_alloc = 0; ext_list = NULL;
+  pub_count = 0;
+  debug_type_index = 512; page_size = 0; done = FALSE;
+  debug_info = debug_default; hll_style = 0; linnum_started = FALSE;
+  do
+    {
+      if (show_addr)
+        rec_pos = ftell (f);
+      if (fread (&rec, sizeof (rec), 1, f) != 1)
+        goto failure;
+      rec_type = rec.rec_type;
+      rec_len = rec.rec_len;
+      rec_idx = 0;
+      if (rec_len > sizeof (rec_buf))
+        {
+          fprintf (stderr, "%s: Record too long", fname);
+          exit (2);
+        }
+      if (fread (rec_buf, rec_len, 1, f) != 1)
+        goto failure;
+      /*...check checksum...*/
+      --rec_len;
+      switch (rec_type)
+        {
+        case LIBHDR:
+          list_libhdr ();
+          break;
+        case LIBEND:
+          if (list_libend (f) != 0)
+            goto failure;
+          break;
+        case THEADR:
+          list_theadr ();
+          break;
+        case COMENT:
+          list_coment ();
+          break;
+        case MODEND:
+        case MODEND|REC32:
+          list_modend (f);
+          break;
+        case EXTDEF:
+          list_extdef ();
+          break;
+        case TYPDEF:
+          show_record ("TYPDEF");
+          printf ("\n");
+          dump_rest ();
+          break;
+        case PUBDEF:
+        case PUBDEF|REC32:
+          list_pubdef ();
+          break;
+        case LINNUM:
+        case LINNUM|REC32:
+          show_record ("LINNUM");
+          if (debug_info == debug_hll)
+            list_hll_linnum ();
+          else
+            {
+              printf ("\n");
+              dump_rest ();
+            }
+          break;
+        case LNAMES:
+          list_lnames ();
+          break;
+        case SEGDEF:
+        case SEGDEF|REC32:
+          list_segdef ();
+          break;
+        case GRPDEF:
+          list_grpdef ();
+          break;
+          break;
+        case FIXUPP:
+        case FIXUPP|REC32:
+          list_fixupp ();
+          break;
+        case LEDATA:
+        case LEDATA|REC32:
+          list_ledata ();
+          break;
+        case LIDATA:
+        case LIDATA|REC32:
+          list_lidata ();
+          break;
+        case COMDEF:
+          list_comdef ();
+          break;
+        case COMDAT:
+        case COMDAT|REC32:
+          show_record ("COMDAT");
+          printf ("\n");
+          dump_rest ();
+          break;
+        case ALIAS:
+          list_alias ();
+          break;
+        default:
+          printf ("Unknown record type at %ld: %.2x\n",
+                  ftell (f) - (sizeof (rec) + rec_len + 1), rec.rec_type);
+          dump_rest ();
+          break;
+        }
+    } while (!done);
+  fclose (f);
+  if (lname_list != NULL)
+    free (lname_list);
+  return;
+
+failure:
+  if (ferror (f))
+    perror (fname);
+  else
+    fprintf (stderr, "%s: Unexpected end of file", fname);
+  exit (2);
+}
+
+
+static void usage (void)
+{
+  fputs ("listomf " VERSION " -- "
+         "Copyright (c) 1993-1996 by Eberhard Mattes\n\n"
+         "Usage: listomf [-a] [-d] <input_file>\n\n"
+         "Options:\n"
+         "  -a    Show addresses of records\n"
+         "  -d    Don't interpret $$TYPES and $$SYMBOLS segments\n", stderr);
+  exit (1);
+}
+
+
+int main (int argc, char *argv[])
+{
+  int c;
+
+  opterr = 0;
+  while ((c = getopt (argc, argv, "ad")) != EOF)
+    switch (c)
+      {
+      case 'a':
+        show_addr = TRUE;
+        break;
+      case 'd':
+        list_debug = FALSE;
+        break;
+      default:
+        usage ();
+      }
+
+  if (argc - optind != 1)
+    usage ();
+
+#ifdef __EMX__
+  if (_isterm (1))
+    setvbuf (stdout, NULL, _IOLBF, BUFSIZ);
+  else
+    setvbuf (stdout, NULL, _IOFBF, BUFSIZ);
+#endif /* __EMX__ */
+
+  list_omf (argv[optind]);
+  return 0;
+}
Index: trunk/src/emx/src/emxomf/makefile
===================================================================
--- trunk/src/emx/src/emxomf/makefile	(revision 18)
+++ trunk/src/emx/src/emxomf/makefile	(revision 18)
@@ -0,0 +1,86 @@
+#
+# /emx/src/emxomf/makefile
+#
+# Copyright (c) 1992-1998 Eberhard Mattes
+#
+# This file is part of emx.
+#
+# emx is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emx is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emx; see the file COPYING.  If not, write to the
+# the Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+.SUFFIXES: .c .o
+
+BIN=\emx\bin\ #
+I=d:/emx/include/
+S=$(I)sys/
+L=d:/emx/lib/
+
+OMFLIB=$(L)omflib.a
+DEFS_H=../include/defs.h
+CC=gcc
+CFLAGS=-c -O -Wall -I../include
+LFLAGS=-s -Zsmall-conv
+
+.c.o:
+	$(CC) $(CFLAGS) $<
+
+default:	all
+all:		emxomf emxomfar emxomfld emxaout listomf
+emxomf:		$(BIN)emxomf.exe
+emxomfar:	$(BIN)emxomfar.exe
+emxomfld:	$(BIN)emxomfld.exe
+emxaout:	$(BIN)emxaout.exe
+listomf:	$(BIN)listomf.exe
+
+$(BIN)emxomf.exe: emxomf.o stabshll.o grow.o $(OMFLIB)
+	-emxload -uw $(BIN)emxomf
+	gcc $(LFLAGS) -o $(BIN)emxomf.exe emxomf.o stabshll.o grow.o -lomflib
+
+$(BIN)emxomfar.exe: emxomfar.o $(OMFLIB)
+	-emxload -uw $(BIN)emxomfar
+	gcc $(LFLAGS) -o $(BIN)emxomfar.exe emxomfar.o -lomflib
+
+$(BIN)emxomfld.exe: emxomfld.o $(L)moddef.a
+	-emxload -uw $(BIN)emxomfld
+	gcc $(LFLAGS) -o $(BIN)emxomfld.exe emxomfld.o -lmoddef
+	emxbind -qa $(BIN)emxomfld.exe -p
+
+$(BIN)emxaout.exe: emxaout.o grow.o
+	-emxload -uw $(BIN)emxaout
+	gcc $(LFLAGS) -o $(BIN)emxaout.exe emxaout.o grow.o
+
+$(BIN)listomf.exe: listomf.o
+	gcc $(LFLAGS) -o $(BIN)listomf.exe listomf.o
+
+emxomf.o: emxomf.c emxomf.h stabshll.h grow.h $(DEFS_H) $(S)omflib.h
+stabshll.o: stabshll.c emxomf.h stabshll.h grow.h $(DEFS_H)
+grow.o: grow.c grow.h $(DEFS_H)
+emxomfar.o: emxomfar.c $(S)omflib.h
+emxomfld.o: emxomfld.c $(DEFS_H) $(S)moddef.h
+emxaout.o: emxaout.c grow.h $(DEFS_H)
+listomf.o: listomf.c $(DEFS_H)
+
+clean:
+	-del *.o
+
+realclean:
+	-del $(BIN)emxomf.exe
+	-del $(BIN)emxomfar.exe
+	-del $(BIN)emxomfld.exe
+	-del $(BIN)emxaout.exe
+	-del $(BIN)listomf.exe
+
+# End of /emx/src/emxomf/makefile
Index: trunk/src/emx/src/emxomf/stabshll.c
===================================================================
--- trunk/src/emx/src/emxomf/stabshll.c	(revision 18)
+++ trunk/src/emx/src/emxomf/stabshll.c	(revision 18)
@@ -0,0 +1,3147 @@
+/* stabshll.c -- Convert GNU-style a.out debug information into
+                 IBM OS/2 HLL 3 debug information
+   Copyright (c) 1993-1998 Eberhard Mattes
+
+This file is part of emxomf.
+
+emxomf is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxomf is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxomf; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "defs.h"
+#include "emxomf.h"
+#include "grow.h"
+#include "stabshll.h"
+
+/* Field ID values for the type table. */
+
+#define FID_nil         0x80    /* No data */
+#define FID_void        0x81    /* Type void */
+#define FID_string      0x82    /* A length-prefixed string follows */
+#define FID_index       0x83    /* A type index follows */
+#define FID_span_16u    0x85    /* An unsigned 16-bit number follows */
+#define FID_span_32u    0x86    /* An unsigned 32-bit number follows */
+#define FID_span_8s     0x88    /* A signed 8-bit number follows */
+#define FID_span_16s    0x89    /* A signed 16-bit number follows */
+#define FID_span_32s    0x8a    /* A signed 32-bit number follows */
+#define FID_span_8u     0x8b    /* An unsigned 8-bit number follows */
+
+/* Static scope table subrecord types. */
+
+#define SST_begin       0x00    /* Begin block */
+#define SST_proc        0x01    /* Procedure */
+#define SST_end         0x02    /* End block or end procedure */
+#define SST_auto        0x04    /* Scoped variable */
+#define SST_static      0x05    /* Static variable */
+#define SST_reg         0x0d    /* Register variable */
+#define SST_changseg    0x11    /* Change default segment */
+#define SST_tag         0x16    /* Structure, union, enum tags */
+#define SST_class       0x19    /* C++ class */
+#define SST_memfunc     0x1a    /* C++ member function */
+#define SST_CPPproc     0x1d    /* C++ function */
+#define SST_CPPstatic   0x1e    /* C++ static variable */
+#define SST_cuinfo      0x40    /* Compile unit information */
+
+/* Class  visibility. */
+
+#define VIS_PRIVATE     0x00    /* private */
+#define VIS_PROTECTED   0x01    /* protected */
+#define VIS_PUBLIC      0x02    /* public */
+
+#define MEMBER_VIS      0x03    /* Member visibility mask */
+#define MEMBER_FUNCTION 0x08    /* It's a member function */
+#define MEMBER_VIRTUAL  0x10    /* Member function / base class is virtual */
+#define MEMBER_VOLATILE 0x20    /* Member function is volatile */
+#define MEMBER_CONST    0x40    /* Member function is const */
+#define MEMBER_STATIC   0x80    /* Member is static */
+#define MEMBER_CTOR     0x100   /* Member function is a constructor */
+#define MEMBER_DTOR     0x200   /* Member function is a destructor */
+#define MEMBER_BASE     0x400   /* It's a base class */
+
+/* Flags for ty_struc. */
+
+#define STRUC_FORWARD   0x01    /* Structure declared forward */
+
+enum type_tag
+{
+  ty_stabs_ref,                 /* Reference to stabs type */
+  ty_prim,                      /* Primitive type */
+  ty_alias,                     /* Equivalent type */
+  ty_pointer,                   /* Pointer type */
+  ty_func,                      /* Function */
+  ty_args,                      /* Function arguments */
+  ty_struc,                     /* Structure or union */
+  ty_types,                     /* Type list for structure/union */
+  ty_fields,                    /* Field list for structure/union */
+  ty_enu,                       /* Enumeration type */
+  ty_values,                    /* Enumeration values */
+  ty_array,                     /* Array */
+  ty_bits,                      /* Bit field / bit string */
+  ty_ref,                       /* Reference type (C++) */
+  ty_member,                    /* Member of a C++ class */
+  ty_class,                     /* A C++ class */
+  ty_memfunc,                   /* A C++ member function */
+  ty_baseclass                  /* A C++ base class */
+};
+
+/* A structure field. */
+
+struct field
+{
+  dword offset;                 /* Offset, in bytes */
+  const char *name;             /* Field name */
+};
+
+/* An enumeration value. */
+
+struct value
+{
+  long index;                   /* The value */
+  const char *name;             /* The name */
+};
+
+/* Temporary representation of a structure field. */
+
+struct tmp_field
+{
+  struct type *type;            /* The internal type */
+  dword offset;                 /* The offset of the field */
+  const char *name;             /* The field name */
+  const char *sname;            /* Static name */
+  int flags;                    /* Member flags (visibility) */
+};
+
+
+/* Internal representation of a type. */
+
+struct type
+{
+  enum type_tag tag;            /* The type of this type */
+  int index;                    /* The HLL index for this type */
+  struct type *next;            /* All types are chained in a single list */
+  union
+    {
+      int stabs_ref;            /* Reference a stabs type */
+      struct type *pointer;     /* Pointer to another type */
+      struct type *alias;       /* Alias for another type */
+      struct type *ref;         /* Reference to another type */
+      struct
+        {                       /* Structure */
+          struct type *types;   /* Types of the fields */
+          struct type *fields;  /* Field names and offsets */
+          dword size;           /* Size of the structure, in bytes */
+          word count;           /* Number of fields */
+          word flags;           /* Flags (STRUC_FORWARD) */
+          const char *name;     /* Name of the structure */
+        } struc;
+      struct
+        {                       /* Class */
+          struct type *members; /* Members */
+          dword size;           /* Size of the class, in bytes */
+          word count;           /* Number of fields */
+          const char *name;     /* Name of the class */
+        } class;
+      struct
+        {                       /* Enumeration */
+          struct type *type;    /* Base type */
+          struct type *values;  /* Values */
+          long first;           /* Smallest value */
+          long last;            /* Biggest value */
+          const char *name;     /* Name of the enum */
+        } enu;
+      struct
+        {                       /* Array */
+          struct type *itype;   /* Index type */
+          struct type *etype;   /* Element type */
+          long first;           /* First index */
+          long last;            /* Last index */
+        } array;
+      struct
+        {                       /* Bitfield */
+          struct type *type;    /* Base type */
+          long start;           /* First bit */
+          long count;           /* Number of bits */
+        } bits;
+      struct
+        {                       /* Function */
+          struct type *ret;     /* Return type */
+          struct type *args;    /* Argument types */
+          int arg_count;        /* Number of arguments */
+        } func;
+      struct
+        {                       /* Function arguments */
+          struct type **list;   /* Array of argument types */
+          int count;            /* Number of arguments */
+        } args;
+      struct
+        {                       /* List of types */
+          struct type **list;   /* Array of types */
+          int count;            /* Number of types */
+        } types;
+      struct
+        {                       /* Structure fields */
+          struct field *list;   /* The fields */
+          int count;            /* Number of fields */
+        } fields;
+      struct
+        {                       /* Class member */
+          struct type *type;    /* Type of the member */
+          dword offset;         /* Offset of the member, in bytes */
+          int flags;            /* Member flags (visibility etc.) */
+          const char *name;     /* Name of the member */
+          const char *sname;    /* Static name */
+        } member;
+      struct
+        {                       /* Enumeration values */
+          struct value *list;   /* Array of values */
+          int count;            /* Number of values */
+        } values;
+      struct
+        {                       /* Member function */
+          struct type *type;    /* Function type */
+          dword offset;         /* Offset in the virtual table */
+          int flags;            /* Member flags (visibility etc.) */
+          const char *name;     /* Name of the member function */
+        } memfunc;
+      struct
+        {                       /* Base class */
+          struct type *type;    /* The base class */
+          dword offset;         /* Offset of the base class */
+          int flags;            /* Visibility, virtual */
+        } baseclass;
+    } d;
+};
+
+
+/* A block. */
+
+struct block
+{
+  dword addr;                   /* Start address of the block */
+  size_t patch_ptr;             /* Index into SST buffer for patching */
+};
+
+/* Timestamp for the compiler unit information SST subrecord. */
+
+#pragma pack(1)
+
+struct timestamp
+{
+  byte hours;
+  byte minutes;
+  byte seconds;
+  byte hundredths;
+  byte day;
+  byte month;
+  word year;
+};
+
+#pragma pack()
+
+/* This variable points to the next character of a stabs type being
+   parsed. */
+
+static const char *parse_ptr;
+
+/* The next HLL type index.  When creating a complex type, this index
+   is used.  Then, this variable is incremented. */
+
+static int hll_type_index;
+
+/* We keep all internal types in a single list.  When creating a new
+   type, we first look through the list to find out whether an
+   identical type already exists.  Doing a linear search is
+   inefficient, but that doesn't matter here, according to
+   experience.  This variable points to the first type of the list. */
+
+static struct type *type_head;
+
+/* This growing array keeps track of stabs vs. internal types.  It is
+   indexed by stabs type numbers. */
+
+static struct type **stype_list;
+static struct grow stype_grow;
+
+/* We collect function arguments in this growing array. */
+
+static struct type **args_list;
+static struct grow args_grow;
+
+/* This stack (implemented with a growing array) keeps track of
+   begin/end block nesting. */
+
+static struct block *block_stack;
+static struct grow block_grow;
+
+/* This string pool contains field names etc. */
+
+static struct strpool *str_pool;
+
+/* This variable holds the sym_ptr index of the most recently
+   encountered N_LBRAC symbol. */
+
+static int lbrac_index;
+
+/* The index (in sst) of the most recently started SST subrecord. */
+
+static size_t subrec_start;
+
+/* The proc_patch_base contains the index where the base address and
+   function length are to be patched into the SST. */
+
+static size_t proc_patch_base;
+
+/* The base address used by the most recently proc record in the
+   SST. */
+
+static size_t proc_start_addr;
+
+/* The internal type of the most recently defined function.  Valid
+   only if last_fun_valid is TRUE. */
+
+static struct type last_fun_type;
+
+/* This variable is TRUE if a function has recently been defined. */
+
+static int last_fun_valid;
+
+/* The length of the prologue of the most recently defined
+   function. */
+
+static int prologue_length;
+
+/* The address of the most recently defined function. */
+
+static dword last_fun_addr;
+
+/* This variable is non-zero when converting a translated C++
+   program. */
+
+static int cplusplus_flag;
+
+/* Unnamed structures are numbered sequentially, using this
+   counter. */
+
+static int unnamed_struct_number;
+
+
+/* Start a type table record of type TYPE, with type qualifier QUAL.
+   tt_end() must be called to finish the record after writing the
+   record contents. */
+
+static void tt_start (byte type, byte qual)
+{
+  subrec_start = tt.size;
+  grow_by (&tt_boundary_grow, 1);
+  tt_boundary[tt_boundary_grow.count++] = tt.size;
+  buffer_word (&tt, 0);    /* Length of sub-record */
+  buffer_byte (&tt, type); /* Type of sub-record */
+  buffer_byte (&tt, qual); /* Type qualifier */
+}
+
+
+/* Finish a type table record.  This function must be called after
+   tt_start(). */
+
+static void tt_end (void)
+{
+  *(word *)(tt.buf + subrec_start) = tt.size - subrec_start - 2;
+}
+
+
+/* Put the type index TI into the type table.  TI = -1 encodes the
+   `nil' type (no type), 0x97 encodes the `void' type.  All other
+   values are type indices. */
+
+static void tt_index (int ti)
+{
+  if (ti == -1)                 /* nil */
+    buffer_byte (&tt, FID_nil);
+  else if (ti == 0x97)          /* void */
+    buffer_byte (&tt, FID_void);
+  else
+    {
+      buffer_byte (&tt, FID_index);
+      buffer_word (&tt, ti);
+    }
+}
+
+
+/* Put an 8-bit byte into the type table. */
+
+static void tt_byte (byte x)
+{
+  buffer_byte (&tt, x);
+}
+
+
+/* Put a 16-bit word into the type table. */
+
+static void tt_word (word x)
+{
+  buffer_word (&tt, x);
+}
+
+
+/* Put a 32-bit double word into the type table. */
+
+static void tt_dword (dword x)
+{
+  buffer_dword (&tt, x);
+}
+
+
+/* Put the name S into the type table. */
+
+static void tt_name (const char *s)
+{
+  buffer_byte (&tt, FID_string);
+  buffer_nstr (&tt, s);
+}
+
+
+/* Put the mangled name S into the type table. */
+
+static void tt_enc (const char *s)
+{
+  buffer_enc (&tt, s);
+}
+
+
+/* Put the unsigned number N into the type table.  Depending on the
+   magnitude of N, different encodings are used. */
+
+static void tt_unsigned_span (dword n)
+{
+  if (n <= 0xff)
+    {
+      buffer_byte (&tt, FID_span_8u);
+      buffer_byte (&tt, n);
+    }
+  else if (n <= 0xffff)
+    {
+      buffer_byte (&tt, FID_span_16u);
+      buffer_word (&tt, n);
+    }
+  else
+    {
+      buffer_byte (&tt, FID_span_32u);
+      buffer_dword (&tt, n);
+    }
+}
+
+
+/* Put the signed number N into the type table.  Depending on the
+   magnitude of N, different encodings are used. */
+
+static void tt_signed_span (long n)
+{
+  if (-127 <= n && n <= 127)
+    {
+      buffer_byte (&tt, FID_span_8s);
+      buffer_byte (&tt, n);
+    }
+  else if (-32767 <= n && n <= 32767)
+    {
+      buffer_byte (&tt, FID_span_16s);
+      buffer_word (&tt, n);
+    }
+  else
+    {
+      buffer_byte (&tt, FID_span_32s);
+      buffer_dword (&tt, n);
+    }
+}
+
+
+/* Start a static scope table subrecord of type TYPE.  sst_end() must
+   be called to finish the subrecord after writing the subrecord
+   data. */
+
+static void sst_start (byte type)
+{
+  subrec_start = sst.size;
+  grow_by (&sst_boundary_grow, 1);
+  sst_boundary[sst_boundary_grow.count++] = sst.size;
+  buffer_byte (&sst, 0);        /* Length of sub-record */
+  buffer_byte (&sst, type);     /* Type of sub-record */
+}
+
+
+/* Finish a static scope table subrecord.  This function must be
+   called after sst_start(). */
+
+static void sst_end (void)
+{
+  if (sst.size - subrec_start - 1 > 255)
+    error ("sst_end: Record too big");
+  sst.buf[subrec_start] = sst.size - subrec_start - 1;
+}
+
+
+/* Define a static variable in the static scope table.  NAME is the
+   name of the variable, ADDR is the address of the variable (segment
+   offset), TYPE_INDEX is the HLL type index.  If EXT is zero, SYM_SEG
+   is the segment (N_DATA, for instance).  If EXT is non-zero, SYM_SEG
+   is the stabs symbol index (for the relocation table).  This
+   function also creates appropriate relocation table entries. */
+
+static void sst_static (const char *name, dword addr, int type_index,
+                        int sym_seg, int ext)
+{
+  struct reloc r;
+
+  sst_start (SST_static);
+  r.address = sst.size;
+  buffer_dword (&sst, addr);      /* Segment offset */
+  buffer_word (&sst, 0);          /* Segment address */
+  buffer_word (&sst, type_index); /* Type index */
+  buffer_nstr (&sst, name);       /* Symbol name */
+  sst_end ();
+  r.ext = ext;
+  r.length = 2;
+  r.symbolnum = sym_seg;
+  r.pcrel = 0;
+  r.unused = 0;
+  buffer_mem (&sst_reloc, &r, sizeof (r));
+  r.address += 4;
+  r.length = 1;
+  buffer_mem (&sst_reloc, &r, sizeof (r));
+}
+
+
+/* Add a new internal type to the list of internal types.  If an
+   identical type already exists, a pointer to that type is returned.
+   Otherwise, a copy of the new type is added to the list and a
+   pointer to that type is returned.  It isn't worth my while to
+   improve the speed of this function, for instance by using
+   hashing. */
+
+static struct type *type_add (struct type *src)
+{
+  struct type *p;
+  int i;
+
+  if (src->tag == ty_alias)
+    abort ();
+  for (p = type_head; p != NULL; p = p->next)
+    if (p->tag == src->tag)
+      switch (p->tag)
+        {
+        case ty_stabs_ref:
+          if (p->d.stabs_ref == src->d.stabs_ref)
+            return p;
+          break;
+        case ty_prim:
+          if (p->index == src->index)
+            return p;
+          break;
+        case ty_pointer:
+          if (p->d.pointer == src->d.pointer)
+            return p;
+          break;
+        case ty_ref:
+          if (p->d.ref == src->d.ref)
+            return p;
+          break;
+        case ty_struc:
+          if (p->d.struc.fields == src->d.struc.fields
+              && p->d.struc.types == src->d.struc.types
+              && p->d.struc.name == src->d.struc.name
+              && p->d.struc.flags == src->d.struc.flags)
+            return p;
+          break;
+        case ty_class:
+          if (p->d.class.members == src->d.class.members
+              && p->d.class.name == src->d.class.name)
+            return p;
+          break;
+        case ty_enu:
+          if (p->d.enu.type == src->d.enu.type
+              && p->d.enu.values == src->d.enu.values
+              && p->d.enu.name == src->d.enu.name)
+            return p;
+          break;
+        case ty_array:
+          if (p->d.array.etype == src->d.array.etype
+              && p->d.array.itype == src->d.array.itype            
+              && p->d.array.first == src->d.array.first
+              && p->d.array.last == src->d.array.last)
+            return p;
+          break;
+        case ty_bits:
+          if (p->d.bits.type == src->d.bits.type
+              && p->d.bits.start == src->d.bits.start
+              && p->d.bits.count == src->d.bits.count)
+            return p;
+          break;
+        case ty_func:
+          if (p->d.func.ret == src->d.func.ret
+              && p->d.func.args == src->d.func.args)
+            return p;
+          break;
+        case ty_args:
+          if (p->d.args.count == src->d.args.count)
+            {
+              for (i = 0; i < p->d.args.count; ++i)
+                if (p->d.args.list[i] != src->d.args.list[i])
+                  break;
+              if (i >= p->d.args.count)
+                return p;
+            }
+          break;
+        case ty_types:
+          if (p->d.types.count == src->d.types.count)
+            {
+              for (i = 0; i < p->d.types.count; ++i)
+                if (p->d.types.list[i] != src->d.types.list[i])
+                  break;
+              if (i >= p->d.types.count)
+                return p;
+            }
+          break;
+        case ty_fields:
+          if (p->d.fields.count == src->d.fields.count)
+            {
+              for (i = 0; i < p->d.fields.count; ++i)
+                if (p->d.fields.list[i].offset != src->d.fields.list[i].offset
+                    || p->d.fields.list[i].name != src->d.fields.list[i].name)
+                  break;
+              if (i >= p->d.fields.count)
+                return p;
+            }
+          break;
+        case ty_member:
+          if (p->d.member.type == src->d.member.type
+              && p->d.member.offset == src->d.member.offset
+              && p->d.member.flags == src->d.member.flags
+              && p->d.member.name == src->d.member.name
+              && p->d.member.sname == src->d.member.sname)
+            return p;
+          break;
+        case ty_values:
+          if (p->d.values.count == src->d.values.count)
+            {
+              for (i = 0; i < p->d.values.count; ++i)
+                if (p->d.values.list[i].index != src->d.values.list[i].index
+                    || p->d.values.list[i].name != src->d.values.list[i].name)
+                  break;
+              if (i >= p->d.values.count)
+                return p;
+            }
+          break;
+        case ty_memfunc:
+          if (p->d.memfunc.type == src->d.memfunc.type
+              && p->d.memfunc.offset == src->d.memfunc.offset
+              && p->d.memfunc.flags == src->d.memfunc.flags
+              && p->d.memfunc.name == src->d.memfunc.name)
+            return p;
+          break;
+        case ty_baseclass:
+          if (p->d.baseclass.type == src->d.baseclass.type
+              && p->d.baseclass.offset == src->d.baseclass.offset
+              && p->d.baseclass.flags == src->d.baseclass.flags)
+            return p;
+          break;
+        default:
+          abort ();
+        }
+  p = xmalloc (sizeof (*p));
+  *p = *src;
+  p->next = type_head;
+  type_head = p;
+  switch (src->tag)
+    {
+    case ty_args:
+      i = src->d.args.count * sizeof (*(src->d.args.list));
+      p->d.args.list = xmalloc (i);
+      memcpy (p->d.args.list, src->d.args.list, i);
+      break;
+    case ty_types:
+      i = src->d.types.count * sizeof (*(src->d.types.list));
+      p->d.types.list = xmalloc (i);
+      memcpy (p->d.types.list, src->d.types.list, i);
+      break;
+    case ty_fields:
+      i = src->d.fields.count * sizeof (*(src->d.fields.list));
+      p->d.fields.list = xmalloc (i);
+      memcpy (p->d.fields.list, src->d.fields.list, i);
+      break;
+    case ty_values:
+      i = src->d.values.count * sizeof (*(src->d.values.list));
+      p->d.values.list = xmalloc (i);
+      memcpy (p->d.values.list, src->d.values.list, i);
+      break;
+    default:
+      break;
+    }
+  return p;
+}
+
+
+/* Associate the stabs type number NUMBER with the internal type
+   HLL. */
+
+static void stype_add (int number, struct type *hll)
+{
+  int i;
+
+  /* Stabs type numbers are greater than zero. */
+
+  if (number < 1)
+    error ("stype_add: Invalid type index %d", number);
+
+  /* Remember the current size of the table and grow the table as
+     required. */
+
+  i = stype_grow.alloc;
+  grow_to (&stype_grow, number);
+
+  /* Initialize the new table entries. */
+
+  while (i < stype_grow.alloc)
+    stype_list[i++] = NULL;
+
+  /* Put the type into the table. */
+
+  stype_list[number-1] = hll;
+}
+
+
+/* Find the internal type associated with the stabs type number
+   NUMBER.  If there is no such type, return NULL. */
+
+static struct type *stype_find (int number)
+{
+  /* Stabs type numbers are greater than zero. */
+
+  if (number < 1)
+    error ("stype_find: Invalid type index %d", number);
+
+  /* Adjust the index and check if it is within the current size of
+     the table. */
+
+  --number;
+  if (number >= stype_grow.alloc)
+    return NULL;
+  else
+    return stype_list[number];
+}
+
+
+/* Dereference stabs references until finding a non-reference. */
+
+static const struct type *follow_refs (const struct type *t)
+{
+  const struct type *t2;
+
+  while (t->tag == ty_stabs_ref)
+    {
+      t2 = stype_find (t->d.stabs_ref);
+      if (t2 == NULL)
+        break;
+      t = t2;
+    }
+  return t;
+}
+
+
+#if defined (DEBUG)
+
+/* This function is used to print an internal type for debugging. */
+
+static void show_type (struct type *tp)
+{
+  int i;
+
+  switch (tp->tag)
+    {
+    case ty_prim:
+      printf ("%#x", tp->index);
+      break;
+    case ty_stabs_ref:
+      printf ("t%d", tp->d.stabs_ref);
+      break;
+    case ty_alias:
+      show_type (tp->d.alias);
+      break;
+    case ty_pointer:
+      printf ("(");
+      show_type (tp->d.pointer);
+      printf (")*");
+      break;
+    case ty_ref:
+      printf ("(");
+      show_type (tp->d.ref);
+      printf (")&");
+      break;
+    case ty_struc:
+      printf ("{");
+      show_type (tp->d.struc.types);
+      printf ("}");
+      break;
+    case ty_class:
+      printf ("{");
+      show_type (tp->d.class.members);
+      printf ("}");
+      break;
+    case ty_enu:
+      printf ("{");
+      show_type (tp->d.enu.values);
+      printf ("}");
+      break;
+    case ty_array:
+      printf ("(");
+      show_type (tp->d.array.etype);
+      printf ("[%d]", tp->d.array.last + 1 - tp->d.array.first);
+      break;
+    case ty_bits:
+      show_type (tp->d.bits.type);
+      printf (":%ld:%ld", tp->d.bits.start, tp->d.bits.count);
+      break;
+    case ty_func:
+      show_type (tp->d.func.ret);
+      printf ("(");
+      if (tp->d.func.args != NULL)
+        show_type (tp->d.func.args);
+      printf (")");
+      break;
+    case ty_args:
+      for (i = 0; i < tp->d.args.count; ++i)
+        {
+          if (i != 0)
+            printf (", ");
+          show_type (tp->d.args.list[i]);
+        }
+      break;
+    case ty_types:
+      for (i = 0; i < tp->d.types.count; ++i)
+        {
+          if (i != 0)
+            printf (", ");
+          show_type (tp->d.types.list[i]);
+        }
+      break;
+    case ty_fields:
+      for (i = 0; i < tp->d.fields.count; ++i)
+        {
+          if (i != 0)
+            printf (", ");
+          printf ("%s", tp->d.fields.list[i].name);
+        }
+      break;
+    case ty_member:
+      printf ("%s", tp->d.member.name);
+      break;
+    case ty_values:
+      for (i = 0; i < tp->d.values.count; ++i)
+        {
+          if (i != 0)
+            printf (", ");
+          printf ("%s", tp->d.values.list[i].name);
+        }
+      break;
+    case ty_memfunc:
+      show_type (tp->d.memfunc.type);
+      break;
+    case ty_baseclass:
+      printf ("{");
+      show_type (tp->d.baseclass.type);
+      printf ("}");
+      break;
+    default:
+      error ("show_type: Unknown type: %d", tp->tag);
+    }
+}
+
+#endif
+
+
+/* Return the size of the internal type TP, in bytes. */
+
+static dword type_size (const struct type *tp)
+{
+  switch (tp->tag)
+    {
+    case ty_prim:
+
+      /* Primitive types. */
+
+      if (tp->index >= 0xa0 && tp->index <= 0xbf)
+        return 4;               /* Near pointer */
+      switch (tp->index)
+        {
+        case 0x97:              /* void */
+          return 0;
+        case 0x80:              /* 8 bit signed */
+        case 0x84:              /* 8 bit unsigned */
+        case 0x90:              /* 8 bit boolean */
+          return 1;
+        case 0x81:              /* 16 bit signed */
+        case 0x85:              /* 16 bit unsigned */
+          return 2;
+        case 0x82:              /* 32 bit signed */
+        case 0x86:              /* 32 bit unsigned */
+        case 0x88:              /* 32 bit real */
+          return 4;
+        case 0x89:              /* 64 bit real */
+          return 8;
+        case 0x8a:              /* 80 bit real (96 bits of storage) */
+          return 12;
+        }
+      error ("type_size: Unknown primitive type: %d", tp->index);
+
+    case ty_stabs_ref:
+
+      /* This should not happen. */
+
+      warning ("stabs type %d not defined", tp->d.stabs_ref);
+      return 4;
+
+    case ty_alias:
+
+      /* An alias.  Return the size of the referenced type. */
+
+      return type_size (tp->d.alias);
+
+    case ty_pointer:
+    case ty_ref:
+
+      /* Pointers and references are 32-bit values. */
+
+      return 4;
+
+    case ty_struc:
+
+      /* The size of a structure is stored in the type structure. */
+
+      if (tp->d.struc.flags & STRUC_FORWARD)
+        {
+          warning ("size of incomplete structure %s is unknown",
+                   tp->d.struc.name);
+          return 0;
+        }
+      return tp->d.struc.size;
+
+    case ty_class:
+
+      /* The size of a class is stored in the type structure. */
+
+      return tp->d.class.size;
+
+    case ty_enu:
+
+      /* Return the size of the base type for an enumeration type. */
+
+      return type_size (tp->d.enu.type);
+
+    case ty_array:
+
+      /* Multiply the element size with the number of array elements
+         for arrays. */
+
+      return ((tp->d.array.last + 1 - tp->d.array.first) *
+              type_size (tp->d.array.etype));
+
+    case ty_bits:
+
+      /* Use the size of the base type for bitfields. */
+
+      return type_size (tp->d.bits.type);
+
+    case ty_member:
+
+      /* Use the size of the member's type for members. */
+
+      return type_size (tp->d.member.type);
+
+    case ty_baseclass:
+
+      /* The size of a base class is the size of the base class :-) */
+
+      return type_size (tp->d.baseclass.type);
+
+    case ty_func:
+    case ty_args:
+    case ty_types:
+    case ty_fields:
+    case ty_values:
+    case ty_memfunc:
+
+      /* This cannot not happen. */
+
+      error ("type_size: cannot compute size for tag %d", tp->tag);
+
+    default:
+
+      /* This cannot happen. */
+
+      error ("type_size: unknown type: %d", tp->tag);
+    }
+}
+
+
+/* Turn a struct into a class.  This needs to be done when a struct is
+   referenced as base class (unfortunately, a simple class looks like
+   a struct). */
+
+static void struct_to_class (struct type *tp)
+{
+  struct type t, *t1, **list, **types;
+  struct field *fields;
+  int i, n;
+
+  if (tp->index != -1)
+    {
+      warning ("Base class cannot be converted from struct");
+      return;
+    }
+  n = tp->d.struc.count;
+  if (n == 0)
+    list = NULL;
+  else
+    {
+      if (tp->d.struc.fields->tag != ty_fields
+          || tp->d.struc.fields->d.fields.count != n)
+        {
+          warning ("Invalid struct field list");
+          return;
+        }
+      fields = tp->d.struc.fields->d.fields.list;
+      if (tp->d.struc.types->tag != ty_types
+          || tp->d.struc.types->d.types.count != n)
+        {
+          warning ("Invalid struct types list");
+          return;
+        }
+      types = tp->d.struc.types->d.types.list;
+      list = xmalloc (n * sizeof (*list));
+      for (i = 0; i < n; ++i)
+        {
+          t.tag = ty_member;
+          t.index = -1;
+          t.d.member.type = types[i];
+          t.d.member.offset = fields[i].offset;
+          t.d.member.flags = VIS_PUBLIC;
+          t.d.member.name = fields[i].name;
+          t.d.member.sname = NULL;
+          list[i] = type_add (&t);
+        }
+    }
+
+  t.tag = ty_types;
+  t.index = -1;
+  t.d.types.count = n;
+  t.d.types.list = list;
+  t1 = type_add (&t);
+
+  t = *tp;
+  tp->tag = ty_class;
+  tp->d.class.members = t1;
+  tp->d.class.size = t.d.struc.size;
+  tp->d.class.count = t.d.struc.count;
+  tp->d.class.name = t.d.struc.name;
+}
+
+
+/* Build and return the internal representation of the `long long'
+   type.  As IPMD doesn't know about `long long' we use the following
+   structure instead:
+
+     struct _long_long
+     {
+       unsigned long lo, hi;
+     };
+
+   This function could be optimized by remembering the type in a
+   global variable. */
+
+static struct type *make_long_long (void)
+{
+  struct type t, *t1, *t2, *t3, *types[2];
+  struct field fields[2];
+
+  /* Let t1 be `unsigned long'. */
+
+  t.tag = ty_prim;
+  t.index = 0x86;               /* 32 bit unsigned */
+  t1 = type_add (&t);
+
+  /* Let t2 be the field types: unsigned long, unsigned long. */
+
+  types[0] = t1;
+  types[1] = t1;
+  t.tag = ty_types;
+  t.index = -1;
+  t.d.types.count = 2;
+  t.d.types.list = types;
+  t2 = type_add (&t);
+
+  /* Let t3 be the fields: lo (at 0), hi (at 4). */
+
+  fields[0].offset = 0; fields[0].name = strpool_add (str_pool, "lo");
+  fields[1].offset = 4; fields[1].name = strpool_add (str_pool, "hi");
+  t.tag = ty_fields;
+  t.index = -1;
+  t.d.fields.count = 2;
+  t.d.fields.list = fields;
+  t3 = type_add (&t);
+
+  /* Build the structure type from t1, t2 and t3. */
+
+  t.tag = ty_struc;
+  t.d.struc.count = 2;
+  t.d.struc.size = 8;
+  t.d.struc.types = t2;
+  t.d.struc.fields = t3;
+  t.d.struc.name = strpool_add (str_pool, "_long_long");
+  t.d.struc.flags = 0;
+  return type_add (&t);
+}
+
+
+/* Parse a (signed) long long number in a stabs type.  The number is
+   given in octal or decimal notation.  The result is stored to
+   *NUMBER.  This function returns TRUE iff successful.  We don't
+   check for overflow. */
+
+static int parse_long_long (long long *number)
+{
+  long long n;
+  int neg, base;
+
+  n = 0; neg = FALSE; base = 10;
+  if (*parse_ptr == '-')
+    {
+      neg = TRUE;
+      ++parse_ptr;
+    }
+  if (*parse_ptr == '0')
+    base = 8;
+  if (!(*parse_ptr >= '0' && *parse_ptr < base + '0'))
+    {
+      *number = 0;
+      return FALSE;
+    }
+  while (*parse_ptr >= '0' && *parse_ptr < base + '0')
+    {
+      n = n * base + (*parse_ptr - '0');
+      ++parse_ptr;
+    }
+  *number = (neg ? -n : n);
+  return TRUE;
+}
+
+
+/* Parse a (signed) number in a stabs type.  The number is given in
+   octal or decimal notation.  The result is stored to *NUMBER.  This
+   function returns TRUE iff successful.  We don't check for
+   overflow. */
+
+static int parse_number (long *number)
+{
+  long long n;
+  int result;
+
+  result = parse_long_long (&n);
+  *number = (long)n;
+  return result;
+}
+
+
+/* Check the next character in a stabs type for C.  If the next
+   character matches C, the character is skipped and TRUE is
+   returned.  Otherwise, a warning message is displayed and FALSE is
+   returned. */
+
+static int parse_char (char c)
+{
+  if (*parse_ptr != c)
+    {
+      warning ("Invalid symbol data: `%c' expected", c);
+      return FALSE;
+    }
+  ++parse_ptr;
+  return TRUE;
+}
+
+
+/* Parse mangled arguments of a member functions.  For instance, ic
+   means an `int' argument and a `char' argument.  Return FALSE on
+   failure. */
+
+static int parse_mangled_args (void)
+{
+  while (*parse_ptr != ';')
+    {
+      switch (*parse_ptr)
+        {
+        case 0:
+          warning ("Missing semicolon after mangled arguments");
+          return FALSE;
+        default:
+          /* TODO */
+          break;
+        }
+      ++parse_ptr;
+    }
+  ++parse_ptr;                  /* Skip semicolon */
+  return TRUE;
+}
+
+
+/* Parse the visibility of a class or member. */
+
+static int parse_visibility (void)
+{
+  switch (*parse_ptr)
+    {
+    case '0':
+      ++parse_ptr;
+      return VIS_PRIVATE;
+    case '1':
+      ++parse_ptr;
+      return VIS_PROTECTED;
+    case '2':
+      ++parse_ptr;
+      return VIS_PUBLIC;
+    default:
+      ++parse_ptr;
+      warning ("Invalid visibility: %c", *parse_ptr);
+      if (*parse_ptr != 0)
+        ++parse_ptr;
+      return VIS_PUBLIC;
+    }
+}
+
+
+/* Add TYPE_NAME to `str_pool', replacing a NULL string with a unique
+   string. */
+
+static const char *add_struct_name (const char *type_name)
+{
+  char tmp[32];
+
+  if (type_name == NULL)
+    {
+      sprintf (tmp, "__%d", unnamed_struct_number++);
+      type_name = tmp;
+    }
+  return strpool_add (str_pool, type_name);
+}
+
+
+/* Parse a stabs type (which is named TYPE_NAME; TYPE_NAME is NULL for
+   an unnamed type) and return the internal representation of that
+   type. */
+
+static struct type *parse_type (const char *type_name)
+{
+  const char *saved_ptr, *p1;
+  struct type t, *result, *t1, *t2, *t3, **tlist;
+  int i, n, class_flag, is_void;
+  long num1, num2, size, lo, hi, valid, offset, width, code;
+  long long range_lo, range_hi;
+  struct tmp_field *tmp_fields, *tf;
+  struct value *tmp_values, *tv;
+  struct grow g1 = GROW_INIT;
+  enum type_tag tt;
+
+  valid = TRUE; result = NULL;
+  t.index = -1;
+  switch (*parse_ptr)
+    {
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      if (!parse_number (&num1))
+        goto syntax;
+      /* Special case: self reference => void */
+      is_void = FALSE;
+      if (*parse_ptr == '=' && parse_ptr[1] >= '0' && parse_ptr[1] <= '9')
+        {
+          saved_ptr = parse_ptr++;
+          if (!parse_number (&num2))
+            goto syntax;
+          if (num2 == num1)
+            is_void = TRUE;
+          else
+            parse_ptr = saved_ptr;
+        }
+      if (is_void)
+        {
+          t.tag = ty_prim;
+          t.index = 0x97;       /* void */
+          result = type_add (&t);
+          stype_add (num1, result);
+        }
+      else if (*parse_ptr == '=')
+        {
+          /* Nested definition */
+          ++parse_ptr;
+          result = parse_type (type_name);
+          stype_add (num1, result);
+        }
+      else
+        {
+          result = stype_find (num1);
+          if (result == NULL)
+            {
+              t.tag = ty_stabs_ref;
+              t.d.stabs_ref = num1;
+            }
+        }
+      break;
+
+    case 'r':
+
+      /* A range type: r<base_type>;<lower_bound>;<upper_bound>;
+
+         Special cases:
+
+         lower_bound | upper_bound | type
+         ------------+-------------+------------------------
+         n > 0       | 0           | floating point, n bytes
+
+         */
+
+      ++parse_ptr;
+      if (!parse_number (&num1) || !parse_char (';')
+          || !parse_long_long (&range_lo) || !parse_char (';')
+          || !parse_long_long (&range_hi) || !parse_char (';'))
+        goto syntax;
+      t.tag = ty_prim;
+      if (range_lo == -128 && range_hi == 127)
+        t.index = 0x80;         /* 8 bit signed */
+      else if (range_lo == -32768 && range_hi == 32767)
+        t.index = 0x80;         /* 16 bit signed */
+      else if (range_lo == -2147483647 - 1 && range_hi == 2147483647)
+        t.index = 0x82;         /* 32 bit signed */
+      else if (range_lo == 0 && range_hi == 127)
+        t.index = 0x84;         /* 8 bit character */
+      else if (range_lo == 0 && range_hi == 255)
+        t.index = 0x84;         /* 8 bit unsigned */
+      else if (range_lo == 0 && range_hi == 65535)
+        t.index = 0x85;         /* 16 bit unsigned */
+      else if (range_lo == 0 && range_hi == 0xffffffff)
+        t.index = 0x86;         /* 32 bit unsigned */
+      else if (range_lo == 0 && range_hi == -1)
+        {
+          if (type_name != NULL
+              && (strcmp (type_name, "long long unsigned int") == 0
+                  || strcmp (type_name, "long long int") == 0))
+            result = make_long_long ();
+          else
+            t.index = 0x86;     /* 32 bit unsigned */
+        }
+      else if ((unsigned long long)range_lo == 0x8000000000000000ULL
+               && range_hi == 0x7fffffffffffffffLL)
+        result = make_long_long ();
+      else if (range_lo == 4 && range_hi == 0)
+        t.index = 0x88;         /* 32 bit real */
+      else if (range_lo == 8 && range_hi == 0)
+        t.index = 0x89;         /* 64 bit real */
+      else if (range_lo == 12 && range_hi == 0)
+        t.index = 0x8a;         /* 80 bit real */
+      else
+        {
+          warning ("Unknown range type: %lld..%lld", range_lo, range_hi);
+          goto syntax;
+        }
+      break;
+
+    case '*':
+
+      /* A pointer type: *<type> */
+
+      ++parse_ptr;
+      t1 = parse_type (NULL);
+      t.tag = ty_pointer;
+      t.d.pointer = t1;
+      break;
+
+    case '&':
+
+      /* A reference type (C++): &<type> */
+
+      ++parse_ptr;
+      t1 = parse_type (NULL);
+      t.tag = ty_ref;
+      t.d.ref = t1;
+      break;
+
+    case '#':
+
+      /* A member function:
+
+         short format: ##<return_type>;
+
+         long format:  #<domain_type>,<return_type>{,<arg_type>};
+
+         */
+
+      ++parse_ptr;
+      if (*parse_ptr == '#')
+        {
+          ++parse_ptr;
+          t1 = parse_type (NULL);
+          if (!parse_char (';'))
+            goto syntax;
+        }
+      else
+        {
+          t2 = parse_type (NULL); /* Domain type */
+          if (!parse_char (','))
+            goto syntax;
+          t1 = parse_type (NULL); /* Return type */
+          while (*parse_ptr != ';')
+            {
+              if (!parse_char (','))
+                goto syntax;
+              t2 = parse_type (NULL); /* Argument type */
+            }
+          ++parse_ptr;
+        }
+
+      /* Make a function type from the return type t1 */
+
+      t.tag = ty_func;
+      t.d.func.ret = t1;
+      t.d.func.args = NULL;
+      t.d.func.arg_count = 0;
+      break;
+
+    case '@':
+
+      /* Special GNU-defined types:
+
+         @s<bits>;<code>;
+
+         BITS:          Number of bits
+         CODE:          Identifies the type:
+                        -16              bool
+                        -20              char
+
+
+      */
+
+      ++parse_ptr;
+      switch (*parse_ptr)
+        {
+        case 's':
+          ++parse_ptr;
+          if (!parse_number (&size) || !parse_char (';'))
+            goto syntax;
+          if (!parse_number (&code))
+            goto syntax;
+          if (size == 8 && code == -16)
+            {
+              t.tag = ty_prim;
+              t.index = 0x90;   /* 8 bit boolean */
+            }
+          else
+            {
+              warning ("Unknown GNU extension type code: %ld, %ld bits",
+                       code, size);
+              goto syntax;
+            }
+          if (!parse_char (';'))
+            goto syntax;
+          break;
+
+        default:
+          warning ("Unknown GNU extension type: @%c", *parse_ptr);
+          goto syntax;
+        }
+      break;
+
+    case 'x':
+
+      /* Incomplete type: xs<name>:
+                          xu<name>:
+                          xe<name>: */
+
+      ++parse_ptr;
+      switch (*parse_ptr)
+        {
+        case 's':
+        case 'u':
+          break;
+        case 'e':
+          warning ("Cannot convert incomplete enum type");
+          goto syntax;
+        default:
+          warning ("Unknown forward reference: %c", *parse_ptr);
+          goto syntax;
+        }
+      ++parse_ptr;
+      p1 = strchr (parse_ptr, ':');
+      if (p1 == NULL)
+        {
+          warning ("Invalid forward reference: missing colon");
+          goto syntax;
+        }
+      t.tag = ty_struc;
+      t.d.struc.types = NULL;
+      t.d.struc.fields = NULL;
+      t.d.struc.size = 0;
+      t.d.struc.count = 0;
+      t.d.struc.name = strpool_addn (str_pool, parse_ptr, p1 - parse_ptr);
+      t.d.struc.flags = STRUC_FORWARD;
+
+      /* Avoid adding an incomplete type if the complete one is
+         already defined.  We're ignoring scoping (TODO). */
+
+      for (t3 = type_head; t3 != NULL; t3 = t3->next)
+        if ((t3->tag == ty_struc && t3->d.struc.name == t.d.struc.name
+             && !(t3->d.struc.flags & STRUC_FORWARD))
+            || (t3->tag == ty_class && t3->d.class.name == t.d.struc.name))
+          {
+            result = t3;
+            break;
+          }
+      parse_ptr = p1 + 1;
+      break;
+
+    case 's':                   /* struct, class */
+    case 'u':                   /* union */
+
+      /* Structures, unions and classes:
+
+         s<size>[<baseclasses>]{<field>}{<method>}
+
+         BASECLASSES: !<#baseclasses>,{<baseclass>;}
+         BASECLASS:   <virtuality><visibility><offset>,<type>
+         FIELD:       <name>:[/0|1|2]<type>,<offset>,<width>;
+         FIELD:       <name>:[/0|1|2]<type>:<static_name>;
+         METHOD:      <name>::{<type>:<args>};
+
+         */
+
+      ++parse_ptr;
+      class_flag = FALSE;
+      if (!parse_number (&size))
+        goto syntax;
+      grow_init (&g1, &tmp_fields, sizeof (*tmp_fields), 8);
+
+      /* Parse the base classes, if present. */
+
+      if (*parse_ptr == '!')
+        {
+          long i, n;
+
+          ++parse_ptr;
+          class_flag = TRUE;
+          if (!parse_number (&n) || !parse_char (','))
+            goto syntax;
+          for (i = 0; i < n; ++i)
+            {
+              grow_by (&g1, 1);
+              tf = &tmp_fields[g1.count++];
+              tf->flags = MEMBER_BASE;
+              tf->name = NULL;
+              tf->sname = NULL;
+              switch (*parse_ptr)
+                {
+                case '0':
+                  ++parse_ptr;
+                  break;
+                case '1':
+                  tf->flags |= MEMBER_VIRTUAL;
+                  ++parse_ptr;
+                  break;
+                default:
+                  warning ("Invalid base class visibility: %c", *parse_ptr);
+                  if (*parse_ptr != 0)
+                    ++parse_ptr;
+                }
+
+              tf->flags |= parse_visibility ();
+              if (!parse_number (&offset) || !parse_char (','))
+                goto syntax;
+              tf->offset = offset >> 3;
+              t1 = parse_type (NULL);
+              switch (t1->tag)
+                {
+                case ty_class:
+                  break;
+                case ty_struc:
+                  struct_to_class (t1);
+                  break;
+                default:
+                  warning ("Invalid base class type");
+                }
+              tf->type = t1;
+              if (!parse_char (';'))
+                goto syntax;
+            }
+        }
+
+      while (*parse_ptr != ';')
+        {
+          p1 = strchr (parse_ptr, ':');
+          if (p1 == NULL)
+            {
+              warning ("Invalid structure type: missing colon");
+              goto syntax;
+            }
+          n = p1 - parse_ptr;
+          grow_by (&g1, 1);
+          tf = &tmp_fields[g1.count++];
+          tf->flags = VIS_PUBLIC;
+          tf->name = strpool_addn (str_pool, parse_ptr, n);
+          parse_ptr = p1 + 1;
+          if (*parse_ptr == ':')
+            {
+              class_flag = TRUE;
+              ++parse_ptr;
+              do
+                {
+                  t1 = parse_type (NULL);
+                  offset = 0;
+
+                  if (*parse_ptr != ':')
+                    {
+                      warning ("Arguments for member function missing");
+                      goto syntax;
+                    }
+                  ++parse_ptr;
+                  if (!parse_mangled_args ())
+                    goto syntax;
+                  tf->flags = parse_visibility () | MEMBER_FUNCTION;
+                  switch (*parse_ptr)
+                    {
+                    case 'A':
+                      ++parse_ptr;
+                      break;
+                    case 'B':
+                      tf->flags |= MEMBER_CONST;
+                      ++parse_ptr;
+                      break;
+                    case 'C':
+                      tf->flags |= MEMBER_VOLATILE;
+                      ++parse_ptr;
+                      break;
+                    case 'D':
+                      tf->flags |= MEMBER_CONST | MEMBER_VOLATILE;
+                      ++parse_ptr;
+                      break;
+                    default:
+                      warning ("Unknown member function qualifier: %c",
+                               *parse_ptr);
+                      if (*parse_ptr != 0)
+                        ++parse_ptr;
+                    }
+                  switch (*parse_ptr)
+                    {
+                    case '.':
+                      ++parse_ptr;
+                      break;
+                    case '*':
+                      tf->flags |= MEMBER_VIRTUAL;
+                      ++parse_ptr;
+                      if (!parse_number (&offset) || !parse_char (';'))
+                        {
+                          warning ("Invalid data for virtual member function");
+                          goto syntax;
+                        }
+                      parse_type (NULL);
+                      if (!parse_char (';'))
+                        {
+                          warning ("Invalid data for virtual member function");
+                          goto syntax;
+                        }
+                      break;
+                    case '?':
+                      tf->flags |= MEMBER_STATIC;
+                      ++parse_ptr;
+                      break;
+                    default:
+                      warning ("Unknown member function qualifier: %c",
+                               *parse_ptr);
+                      if (*parse_ptr != 0)
+                        ++parse_ptr;
+                    }
+                  tf->type = t1;
+                  tf->offset = offset;
+                  if (*parse_ptr != ';')
+                    {
+                      /* Another member function with the same name
+                         follows. */
+
+                      grow_by (&g1, 1);
+                      tf = &tmp_fields[g1.count++];
+                      tf->flags = VIS_PUBLIC | MEMBER_FUNCTION;
+                      tf->name = tf[-1].name;
+                    }
+                } while (*parse_ptr != ';');
+              ++parse_ptr;
+            }
+          else
+            {
+              if (*parse_ptr == '/')
+                {
+                  class_flag = TRUE;
+                  ++parse_ptr;
+                  tf->flags = parse_visibility ();
+                }
+              t1 = parse_type (NULL);
+              if (*parse_ptr == ':')
+                {
+                  /* Static member */
+
+                  ++parse_ptr;
+                  tf->flags |= MEMBER_STATIC;
+                  p1 = strchr (parse_ptr, ';');
+                  if (p1 == NULL)
+                    {
+                      warning ("Invalid static member: missing semicolon");
+                      goto syntax;
+                    }
+                  n = p1 - parse_ptr;
+                  tf->sname = strpool_addn (str_pool, parse_ptr, n);
+                  parse_ptr = p1 + 1;
+                  tf->offset = 0;
+                }
+              else
+                {
+                  if (!parse_char (',') || !parse_number (&offset))
+                    goto syntax;
+                  if (*parse_ptr == ',')
+                    {
+                      ++parse_ptr;
+                      if (!parse_number (&width))
+                        goto syntax;
+                    }
+                  else
+                    width = 0;      /* vtable pointer field */
+                  if (!parse_char (';'))
+                    goto syntax;
+                  if ((offset & 7) != 0 || width != 8 * type_size (t1))
+                    {
+                      t.tag = ty_bits;
+                      t.d.bits.type = t1;
+                      t.d.bits.start = offset & 7;
+                      t.d.bits.count = width;
+                      t1 = type_add (&t);
+                    }
+                }
+              tf->type = t1;
+              tf->offset = offset >> 3;
+            }
+        }
+      ++parse_ptr;
+      if (*parse_ptr == '~')
+        {
+          /* Type reference to the first base class.  This field is
+             present for classes which contain virtual functions. */
+
+          ++parse_ptr;
+          if (!parse_char ('%'))
+            goto syntax;
+          t1 = parse_type (NULL);
+          if (!parse_char (';'))
+            goto syntax;
+        }
+
+      if (class_flag)
+        {
+          tlist = xmalloc (g1.count * sizeof (*t.d.types.list));
+          for (i = 0; i < g1.count; ++i)
+            {
+              if (tmp_fields[i].flags & MEMBER_FUNCTION)
+                {
+                  t2 = tmp_fields[i].type;
+                  tt = follow_refs (t2)->tag;
+                  /* TODO: check later if ty_stabs_ref */
+                  if (tt != ty_func && tt != ty_stabs_ref)
+                    error ("Invalid type for member function %s",
+                           tmp_fields[i].name);
+                  t.tag = ty_memfunc;
+                  t.d.memfunc.type = t2;
+                  t.d.memfunc.name = tmp_fields[i].name;
+                  t.d.memfunc.flags = tmp_fields[i].flags;
+                  t.d.memfunc.offset = tmp_fields[i].offset;
+                }
+              else if (tmp_fields[i].flags & MEMBER_BASE)
+                {
+                  t.tag = ty_baseclass;
+                  t.d.baseclass.type = tmp_fields[i].type;
+                  t.d.baseclass.flags = tmp_fields[i].flags;
+                  t.d.baseclass.offset = tmp_fields[i].offset;
+                }
+              else
+                {
+                  t.tag = ty_member;
+                  t.d.member.type = tmp_fields[i].type;
+                  t.d.member.offset = tmp_fields[i].offset;
+                  t.d.member.flags = tmp_fields[i].flags;
+                  t.d.member.name = tmp_fields[i].name;
+                  t.d.member.sname = tmp_fields[i].sname;
+                }
+              t2 = type_add (&t);
+              tlist[i] = t2;
+            }
+          t.tag = ty_types;
+          t.d.types.count = g1.count;
+          t.d.types.list = tlist;
+          t1 = type_add (&t);
+          free (tlist);
+
+          t.tag = ty_class;
+          t.d.class.members = t1;
+          t.d.class.size = size;
+          t.d.class.count = g1.count;
+          t.d.class.name = add_struct_name (type_name);
+
+          /* Check if there is an incomplete type waiting to be filled
+             in (forward reference).  We're ignoring scoping (TODO). */
+
+          for (t3 = type_head; t3 != NULL; t3 = t3->next)
+            if (t3->tag == ty_struc && t3->d.struc.name == t.d.class.name
+                && t3->d.struc.types == NULL && t3->d.struc.fields == NULL
+                && (t3->d.struc.flags & STRUC_FORWARD))
+              {
+                if (t3->index != -1)
+                  warning ("This cannot happen, case 1");
+                result = t3;
+                t3->tag = ty_class;
+                t3->d.class = t.d.class;
+                break;
+              }
+        }
+      else
+        {
+          t.tag = ty_types;
+          t.d.types.count = g1.count;
+          t.d.types.list = xmalloc (g1.count * sizeof (*t.d.types.list));
+          for (i = 0; i < g1.count; ++i)
+            t.d.types.list[i] = tmp_fields[i].type;
+          t1 = type_add (&t);
+          free (t.d.types.list);
+
+          t.tag = ty_fields;
+          t.d.fields.count = g1.count;
+          t.d.fields.list = xmalloc (g1.count * sizeof (*t.d.fields.list));
+          for (i = 0; i < g1.count; ++i)
+            {
+              t.d.fields.list[i].offset = tmp_fields[i].offset;
+              t.d.fields.list[i].name = tmp_fields[i].name;
+            }
+          t2 = type_add (&t);
+
+          t.tag = ty_struc;
+          t.d.struc.count = g1.count;
+          t.d.struc.size = size;
+          t.d.struc.types = t1;
+          t.d.struc.fields = t2;
+          t.d.struc.name = add_struct_name (type_name);
+          t.d.struc.flags = 0;
+
+          /* Check if there is an incomplete type waiting to be filled
+             in (forward reference).  We're ignoring scoping (TODO). */
+
+          for (t3 = type_head; t3 != NULL; t3 = t3->next)
+            if (t3->tag == ty_struc && t3->d.struc.name == t.d.struc.name
+                && t3->d.struc.types == NULL && t3->d.struc.fields == NULL
+                && (t3->d.struc.flags & STRUC_FORWARD))
+              {
+                if (t3->index != -1)
+                  warning ("This cannot happen, case 1");
+                result = t3;
+                t3->d.struc = t.d.struc;
+                break;
+              }
+        }
+      grow_free (&g1);
+      break;
+
+    case 'e':
+
+      /* Enumeration type: e{<name>:<value>,}; */
+
+      ++parse_ptr;
+      grow_init (&g1, &tmp_values, sizeof (*tmp_values), 8);
+      while (*parse_ptr != ';')
+        {
+          p1 = strchr (parse_ptr, ':');
+          if (p1 == NULL)
+            {
+              warning ("Invalid enum type: missing colon");
+              goto syntax;
+            }
+          n = p1 - parse_ptr;
+          grow_by (&g1, 1);
+          tv = &tmp_values[g1.count++];
+          tv->name = strpool_addn (str_pool, parse_ptr, n);
+          parse_ptr = p1 + 1;
+          if (!parse_number (&tv->index) || !parse_char (','))
+            goto syntax;
+        }
+      ++parse_ptr;
+      t.tag = ty_values;
+      t.d.values.count = g1.count;
+      t.d.values.list = xmalloc (g1.count * sizeof (*t.d.values.list));
+      if (g1.count == 0)
+        lo = hi = 0;
+      else
+        lo = hi = tmp_values[0].index;
+      for (i = 0; i < g1.count; ++i)
+        {
+          t.d.values.list[i].index = tmp_values[i].index;
+          t.d.values.list[i].name = tmp_values[i].name;
+          if (tmp_values[i].index < lo)
+            lo = tmp_values[i].index;
+          if (tmp_values[i].index > hi)
+            hi = tmp_values[i].index;
+        }
+      t1 = type_add (&t);
+
+      t.tag = ty_prim;
+      t.index = 0x82;           /* 32 bit signed */
+      t2 = type_add (&t);
+
+      t.tag = ty_enu;
+      t.index = -1;
+      t.d.enu.values = t1;
+      t.d.enu.type = t2;
+      t.d.enu.name = add_struct_name (type_name);
+      t.d.enu.first = lo;
+      t.d.enu.last = hi;
+      grow_free (&g1);
+      break;
+
+    case 'a':
+
+      /* An array: ar<index_type>;<lower_bound>;<upper_bound>;<el_type> */
+
+      ++parse_ptr;
+      if (!parse_char ('r'))
+        goto syntax;
+      if (strncmp (parse_ptr, "0;", 2) == 0)
+        {
+          /* This invalid type index seems to be caused by a bug of
+             GCC 2.8.1.  Replace with a 32-bit signed integer. */
+
+          t.tag = ty_prim;
+          t.index = 0x82;       /* 32 bit signed */
+          t1 = type_add (&t);
+          ++parse_ptr;
+        }
+      else
+        t1 = parse_type (NULL); /* Index type */
+      if (!parse_char (';')
+          || !parse_number (&lo) || !parse_char (';')   /* Lower bound */
+          || !parse_number (&hi) || !parse_char (';'))  /* Upper bound */
+        goto syntax;
+      t2 = parse_type (NULL);   /* Elements type */
+      if (lo == 0 && hi == 0)   /* Variable-length array */
+        {
+          t.tag = ty_pointer;   /* Turn into pointer */
+          t.d.pointer = t2;
+        }
+      else
+        {
+          t.tag = ty_array;
+          t.d.array.first = lo;
+          t.d.array.last = hi;
+          t.d.array.itype = t1;
+          t.d.array.etype = t2;
+        }
+      break;
+
+    case 'f':
+
+      /* A function: f<return_type> */
+
+      ++parse_ptr;
+      t1 = parse_type (NULL);   /* Return type */
+      t.tag = ty_func;
+      t.d.func.ret = t1;
+      t.d.func.args = NULL;
+      t.d.func.arg_count = 0;
+      break;
+
+    default:
+      warning ("Unknown type: %c", *parse_ptr);
+      goto syntax;
+    }
+
+  /* Add the type to the tables. */
+
+  if (result == NULL)
+    result = type_add (&t);
+  return result;
+
+syntax:
+  grow_free (&g1);
+  t.tag = ty_prim;
+  t.index = 0x82;               /* 32 bit signed */
+  return type_add (&t);
+}
+
+
+/* Parse a stabs type (the name of the type is TYPE_NAME, which is
+   NULL for an unnamed type) and check for end of the string.  If not
+   all characters of the string have been parsed, a warning message is
+   displayed.  Return the internal representation of the type. */
+
+static struct type *parse_complete_type (const char *type_name)
+{
+  struct type *tp;
+
+  tp = parse_type (type_name);
+  if (*parse_ptr != 0)
+    warning ("unexpected character at end of stabs type: %c", *parse_ptr);
+  return tp;
+}
+
+
+/* Create an HLL type number for type TP. If a type number has already
+   been assigned to TP, use that number.  Otherwise, allocate a new
+   (complex) type number and define the type in the $$TYPES segment.
+   The HLL type number us stored to *HLL.
+
+   Note: This function must not be called between sst_start() and
+   sst_end() or tt_start() and tt_end() as entries are made both in
+   the SST ($$SYMBOLS) and the type table ($$TYPES). */
+
+static void make_type (struct type *tp, int *hll)
+{
+  struct type *t1;
+  int ti_1, ti_2, i, qual;
+  int patch1;
+
+#define RETURN(X) do {*hll = (X); return;} while (0)
+
+  if (tp->index == -2)
+    {
+      warning ("Cycle detected by make_type");
+      RETURN (0);
+    }
+  if (tp->index != -1)
+    RETURN (tp->index);
+  tp->index = -2;
+  switch (tp->tag)
+    {
+    case ty_stabs_ref:
+      t1 = stype_find (tp->d.stabs_ref);
+      if (t1 == NULL)
+        {
+          warning ("Undefined stabs type %d referenced", tp->d.stabs_ref);
+          RETURN (0x82);        /* 32 bit signed */
+        }
+      make_type (t1, &tp->index);
+      *hll = tp->index;
+      break;
+
+    case ty_alias:
+      make_type (tp->d.alias, &tp->index);
+      *hll = tp->index;
+      break;
+
+    case ty_pointer:
+      ti_1 = tp->d.pointer->index;
+      if (ti_1 >= 0x80 && ti_1 <= 0xa0)
+        {
+          tp->index = ti_1 + 0x20;
+          RETURN (tp->index);
+        }
+      *hll = tp->index = hll_type_index++;
+      tt_start (0x7a, 0x01);    /* 32-bit near pointer */
+      patch1 = tt.size;
+      tt_index (0);
+      tt_end ();
+      make_type (tp->d.pointer, &ti_1);
+      buffer_patch_word (&tt, patch1+1, ti_1);
+      break;
+
+    case ty_ref:
+      *hll = tp->index = hll_type_index++;
+      tt_start (0x48, 0x00);    /* Reference type (C++) */
+      patch1 = tt.size;
+      tt_word (0);
+      tt_end ();
+      make_type (tp->d.ref, &ti_1);
+      buffer_patch_word (&tt, patch1, ti_1);
+      break;
+
+    case ty_struc:
+      tt_start (0x79, 0x00);    /* Structure/Union */
+      tt_dword (tp->d.struc.size);
+      tt_word (tp->d.struc.count);
+      patch1 = tt.size;
+      tt_index (0);
+      tt_index (0);
+      tt_name (tp->d.struc.name);
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      if (tp->d.struc.types == NULL && tp->d.struc.fields == NULL)
+        {
+          ti_1 = 0;
+          ti_2 = 1;
+        }
+      else
+        {
+          make_type (tp->d.struc.types, &ti_1);
+          make_type (tp->d.struc.fields, &ti_2);
+        }
+      buffer_patch_word (&tt, patch1+1, ti_1);
+      buffer_patch_word (&tt, patch1+4, ti_2);
+      break;
+
+    case ty_class:
+      *hll = tp->index = hll_type_index++;
+      tt_start (0x40, 0x00);      /* Class */
+      tt_dword (tp->d.class.size);
+      tt_word (tp->d.class.count);
+      patch1 = tt.size;
+      tt_word (0);                /* Members */
+      tt_enc (tp->d.class.name);  /* Class name */
+      tt_end ();
+      make_type (tp->d.class.members, &ti_1);
+      buffer_patch_word (&tt, patch1, ti_1);
+      break;
+
+    case ty_member:
+      make_type (tp->d.member.type, &ti_1);
+      qual = 0;
+      if (tp->d.member.flags & MEMBER_STATIC)
+        qual |= 0x01;
+      tt_start (0x46, qual);
+      tt_byte (tp->d.member.flags & MEMBER_VIS);
+      tt_word (ti_1);
+      tt_unsigned_span (tp->d.member.offset);
+      if (tp->d.member.flags & MEMBER_STATIC)
+        tt_enc (tp->d.member.sname);
+      else
+        tt_enc ("");
+      tt_enc (tp->d.member.name);
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_enu:
+      make_type (tp->d.enu.type, &ti_1);
+      make_type (tp->d.enu.values, &ti_2);
+      tt_start (0x7b, 0x00);            /* Enum */
+      tt_index (ti_1);                  /* Element's data type */
+      tt_index (ti_2);                  /* List of values */
+      tt_signed_span (tp->d.enu.first); /* Minimum index */
+      tt_signed_span (tp->d.enu.last);  /* Maximum index */
+      tt_name (tp->d.enu.name);
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_array:
+      make_type (tp->d.array.itype, &ti_1);
+      make_type (tp->d.array.etype, &ti_2);
+      tt_start (0x78, 0x00);    /* Array */
+      tt_dword (type_size (tp));
+      tt_index (ti_1);
+      tt_index (ti_2);
+      tt_name ("");             /* Name */
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_bits:
+      tt_start (0x5c, 0x0a);    /* Bit string */
+      tt_byte (tp->d.bits.start);
+      tt_unsigned_span (tp->d.bits.count);
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_func:
+      make_type (tp->d.func.ret, &ti_1);
+      if (tp->d.func.args == NULL)
+        ti_2 = 0;
+      else
+        make_type (tp->d.func.args, &ti_2);
+      tt_start (0x54, 0x05);          /* Function */
+      tt_word (tp->d.func.arg_count); /* Number of parameters */
+      tt_word (tp->d.func.arg_count); /* Max. Number of parameters */
+      tt_index (ti_1);                /* Return value */
+      tt_index (ti_2);                /* Argument list */
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_args:
+      if (tp->d.args.count == 0)
+        {
+          tp->index = 0;
+          RETURN (tp->index);
+        }
+      for (i = 0; i < tp->d.args.count; ++i)
+        make_type (tp->d.args.list[i], &ti_1);
+      tt_start (0x7f, 0x04);    /* List (function parameters) */
+      for (i = 0; i < tp->d.args.count; ++i)
+        {
+          tt_byte (0x01);        /* Flag: pass by value, no descriptor */
+          tt_index (tp->d.args.list[i]->index);
+        }
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_types:
+      if (tp->d.types.count == 0)
+        {
+          tp->index = 0;
+          RETURN (tp->index);
+        }
+      *hll = tp->index = hll_type_index++;
+      tt_start (0x7f, 0x01);    /* List (structure field types) */
+      patch1 = tt.size;
+      for (i = 0; i < tp->d.types.count; ++i)
+        tt_index (0);
+      tt_end ();
+      for (i = 0; i < tp->d.types.count; ++i)
+        {
+          make_type (tp->d.types.list[i], &ti_1);
+          buffer_patch_word (&tt, patch1 + 1 + 3*i, ti_1);
+        }
+      break;
+
+    case ty_fields:
+      if (tp->d.fields.count == 0)
+        {
+          tp->index = 0;
+          RETURN (tp->index);
+        }
+      tt_start (0x7f, 0x02);    /* List (structure field names) */
+      for (i = 0; i < tp->d.fields.count; ++i)
+        {
+          tt_name (tp->d.fields.list[i].name);
+          tt_unsigned_span (tp->d.fields.list[i].offset);
+        }
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_values:
+      if (tp->d.values.count == 0)
+        {
+          tp->index = -1;
+          RETURN (tp->index);
+        }
+      tt_start (0x7f, 0x03);    /* Enum values */
+      for (i = 0; i < tp->d.values.count; ++i)
+        {
+          tt_name (tp->d.values.list[i].name);
+          tt_unsigned_span (tp->d.values.list[i].index);
+        }
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_memfunc:
+      make_type (tp->d.memfunc.type, &ti_1);
+      qual = 0;
+      if (tp->d.memfunc.flags & MEMBER_STATIC)
+        qual |= 0x01;
+      if (tp->d.memfunc.flags & MEMBER_CONST)
+        qual |= 0x04;
+      if (tp->d.memfunc.flags & MEMBER_VOLATILE)
+        qual |= 0x08;
+      if (tp->d.memfunc.flags & MEMBER_VIRTUAL)
+        qual |= 0x10;
+      tt_start (0x45, qual);          /* Member Function */
+      tt_byte (tp->d.memfunc.flags & MEMBER_VIS); /* Protection */
+      if (tp->d.memfunc.flags & MEMBER_CTOR)
+        tt_byte (1);                  /* Constructor */
+      else if (tp->d.memfunc.flags & MEMBER_DTOR)
+        tt_byte (2);                  /* Destructor */
+      else
+        tt_byte (0);                  /* Regular member function */
+      tt_word (ti_1);                 /* Type index of function */
+      if (tp->d.memfunc.flags & MEMBER_VIRTUAL)
+        tt_unsigned_span (tp->d.memfunc.offset); /* Index into vtable */
+      tt_enc (tp->d.memfunc.name);    /* Name of the function */
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    case ty_baseclass:
+      make_type (tp->d.baseclass.type, &ti_1);
+      qual = 0;
+      if (tp->d.baseclass.flags & MEMBER_VIRTUAL)
+        qual |= 0x01;
+      tt_start (0x41, qual);      /* Base Class */
+      tt_byte (tp->d.baseclass.flags & MEMBER_VIS);
+      tt_word (ti_1);             /* Type */
+      tt_unsigned_span (tp->d.baseclass.offset);
+      tt_end ();
+      *hll = tp->index = hll_type_index++;
+      break;
+
+    default:
+      error ("make_type: unknown tag %d", tp->tag);
+    }
+}
+
+
+/* Parse an unnamed stabs type and return an HLL type index for it. */
+
+static int hll_type (void)
+{
+  struct type *tp;
+  int ti;
+
+  tp = parse_complete_type (NULL);
+  make_type (tp, &ti);
+  return ti;
+}
+
+
+/* Return the symbol name of symbol *INDEX, concatenating the names of
+   successive symbol table entries if necessary.  A pointer to the
+   string is stored to *STR.  If symbols are concatenated, *INDEX is
+   adjusted to refer to the last symbol table entry used, in order to
+   refer to the next symbol after incrementing by one.  If TRUE is
+   returned, the caller should free the string when it is no longer
+   needed.  If FALSE is returned, the string must not be freed. */
+
+static int concat_symbols (int *index, const char **str)
+{
+  int i, n, len;
+  char *new;
+  const char *p;
+
+  len = 0;
+  for (i = *index; i < sym_count; ++i)
+    {
+      p = str_ptr + sym_ptr[i].string;
+      n = strlen (p);
+      if (n > 0 && p[n-1] == '\\')
+        len += n - 1;
+      else
+        {
+          len += n;
+          break;
+        }
+    }
+  if (i == *index)
+    {
+      *str = str_ptr + sym_ptr[i].string;
+      return FALSE;
+    }
+  else
+    {
+      new = xmalloc (len + 1);
+      *str = new;
+      for (i = *index; i < sym_count; ++i)
+        {
+          p = str_ptr + sym_ptr[i].string;
+          n = strlen (p);
+          if (n > 0 && p[n-1] == '\\')
+            {
+              memcpy (new, p, n - 1);
+              new += n - 1;
+            }
+          else
+            {
+              memcpy (new, p, n);
+              new += n;
+              break;
+            }
+        }
+      *new = 0;
+      *index = i;
+      return TRUE;
+    }
+}
+
+
+/* Parse a stabs type definition and store the internal representation
+   of that type.  The sym_ptr index is passed in INDEX.  As we might
+   have to concatenate successive symbol table entries, *INDEX is
+   updated to refer to the next symbol. */
+
+static void parse_typedef (int *index)
+{
+  char *name;
+  const char *str, *p;
+  struct type *t;
+  int n, alloc_flag;
+
+  alloc_flag = concat_symbols (index, &str);
+  p = strchr (str, ':');
+  if (p != NULL)
+    {
+      n = p - str;
+      name = alloca (n + 1);
+      memcpy (name, str, n);
+      name[n] = 0;
+#if defined (DEBUG)
+      printf ("LSYM/LCSYM/GSYM/PSYM/RSYM/STSYM/FUN %s\n", str);
+#endif
+      parse_ptr = p + 1;
+      switch (*parse_ptr)
+        {
+        case 'f':
+        case 'F':
+          ++parse_ptr;
+          /* Note: don't call parse_complete_type() as there's a comma
+             at the end for nested functions. */
+          t = parse_type (NULL);
+          break;
+
+        case 't':
+        case 'T':
+          ++parse_ptr;
+          if (*parse_ptr == 't')
+            ++parse_ptr;        /* synonymous type */
+          t = parse_complete_type (name);
+#if defined (DEBUG)
+          printf ("  type: ");
+          show_type (t);
+          printf ("\n");
+#endif
+          break;
+
+        case 'p':
+        case 'r':
+        case 'G':
+        case 'S':
+        case 'V':
+          ++parse_ptr;
+          t = parse_complete_type (name);
+#if defined (DEBUG)
+          printf ("  type: ");
+          show_type (t);
+          printf ("\n");
+#endif
+          break;
+
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+          t = parse_complete_type (name);
+#if defined (DEBUG)
+          printf ("  type: ");
+          show_type (t);
+          printf ("\n");
+#endif
+          break;
+        }
+    }
+  if (alloc_flag)
+    free ((void *)str);         /* remove const attribute */
+}
+
+
+/* Write a `begin' subrecord to the SST.  The block begins at ADDR in
+   the text segment. */
+
+static size_t hll_begin (dword addr)
+{
+  size_t ptr;
+  struct reloc r;
+
+  sst_start (SST_begin);
+  r.address = sst.size;
+  ptr = sst.size;
+  buffer_dword (&sst, addr);    /* Segment offset */
+  buffer_dword (&sst, 0);       /* Length of block -- patched later */
+#if 0
+  buffer_nstr (&sst, "");       /* Name of block (optional) */
+#endif
+  sst_end ();
+
+  r.ext = 0;
+  r.length = 2;
+  r.symbolnum = N_TEXT;
+  r.pcrel = 0;
+  r.unused = 0;
+  buffer_mem (&sst_reloc, &r, sizeof (r));
+  return ptr;
+}
+
+
+/* Start of a block.  Write a `begin' subrecord to the SST.  The block
+   begins at ADDR in the text segment.  Push the block onto the block
+   stack. */
+
+static void block_begin (dword addr)
+{
+  size_t ptr;
+
+  ptr = hll_begin (addr);
+  grow_by (&block_grow, 1);
+  block_stack[block_grow.count].patch_ptr = ptr;
+  block_stack[block_grow.count].addr = addr;
+  ++block_grow.count;
+}
+
+
+/* Write an `end' subrecord to the SST.  PATCH_PTR is the sst index of
+   the `begin' subrecord for this block.  Add ADD_START to the start
+   address of the block and set the length of the block to LENGTH, in
+   bytes. */
+
+static void hll_end (size_t patch_ptr, int add_start, size_t length)
+{
+  *(dword *)(sst.buf+patch_ptr+0) += add_start;
+  *(dword *)(sst.buf+patch_ptr+4) = length;
+  sst_start (SST_end);
+  sst_end ();
+}
+
+
+/* Return TRUE iff symbol table entry S defines a function. */
+
+static int is_fun (const struct nlist *s)
+{
+  const char *p;
+
+  if (s->type != N_FUN)
+    return FALSE;
+  p = strchr (str_ptr + s->string, ':');
+  if (p == NULL)
+    return FALSE;
+  return (p[1] == 'F' || p[1] == 'f');
+}
+
+
+/* Approximate a function prologue length by examining the code.  The
+   function starts at START and ends at END. */
+
+static int get_prologue_length (dword start, dword end)
+{
+  dword i;
+
+  if (end > text_size)
+    end = text_size;
+  i = start;
+  if (i < end && text_ptr[i] == 0x55) ++i;                  /* PUSH EBP */
+  if (i + 1 < end && text_ptr[i+0] == 0x89
+      && text_ptr[i+1] == 0xe5)                             /* MOV  EBP, ESP */
+    i += 2;
+  if (i + 2 < end && text_ptr[i+0] == 0x83
+      && text_ptr[i+1] == 0xec)                             /* SUB  ESP, n8 */
+    i += 3;
+  return i - start;
+}
+
+
+/* End of a function reached.  Try to find the function length.  I is
+   the sym_ptr index of the current symbol -- we search the symbol
+   table starting at I to find the next function for estimating the
+   function length. */
+
+static void fun_end (int i)
+{
+  int p_len;
+  dword addr;
+
+  addr = text_size;
+  while (i < sym_count)
+    {
+      if (is_fun (&sym_ptr[i]))
+        {
+          addr = sym_ptr[i].value;
+          break;
+        }
+      ++i;
+    }
+  if (prologue_length != -1)
+    p_len = prologue_length;
+  else
+    p_len = get_prologue_length (proc_start_addr, addr);
+  *(dword *)(sst.buf+proc_patch_base + 0) = addr - proc_start_addr;
+  *(word *)(sst.buf+proc_patch_base + 4) = p_len;
+  *(dword *)(sst.buf+proc_patch_base + 6) = addr - proc_start_addr;
+  proc_patch_base = 0;
+  sst_start (SST_end);
+  sst_end ();
+}
+
+
+/* End of a block (N_RBRAC encountered).  I is the sym_ptr index of
+   the N_RBRAC symbol.  If we reach the outmost block level, we call
+   fun_end(). */
+
+static void block_end (int i)
+{
+  if (block_grow.count == 0)
+    warning ("Invalid N_RBRAC without N_LBRAC");
+  else
+    {
+      --block_grow.count;
+      hll_end (block_stack[block_grow.count].patch_ptr, 0,
+               sym_ptr[i].value - block_stack[block_grow.count].addr);
+      if (block_grow.count == 0 && proc_patch_base != 0)
+        fun_end (i);
+    }
+}
+
+
+/* Define a function.  SYMBOL points to the sym_ptr entry.  The
+   function arguments are taken from the args_list array.  Several
+   fields of the SST entry are filled-in later, when reaching the end
+   of the function.  proc_patch_base is used for remembering the place
+   where to patch the SST entry. */
+
+static void define_fun (const struct nlist *symbol)
+{
+  struct type t, *t1, *t2;
+  struct reloc r;
+  const char *str, *p;
+  char *name;
+  int n, ti;
+
+  str = str_ptr + symbol->string;
+  p = strchr (str, ':');
+  if (p == NULL)
+    abort ();
+  n = p - str;
+  name = alloca (n + 1);
+  memcpy (name, str, n);
+  name[n] = 0;
+
+  proc_start_addr = symbol->value;
+
+  if (args_grow.count == 0)
+    t1 = NULL;
+  else
+    {
+      t.tag = ty_args;
+      t.index = -1;
+      t.d.args.count = args_grow.count;
+      t.d.args.list = xmalloc (args_grow.count * sizeof (*args_list));
+      memcpy (t.d.args.list, args_list, args_grow.count * sizeof (*args_list));
+      t1 = type_add (&t);
+      free (t.d.args.list);
+    }
+  last_fun_type.d.func.args = t1;
+  last_fun_type.d.func.arg_count = args_grow.count;
+  t2 = type_add (&last_fun_type);
+  make_type (t2, &ti);
+  sst_start (cplusplus_flag ? SST_CPPproc : SST_proc);
+  r.address = sst.size;
+  buffer_dword (&sst, symbol->value); /* Segment offset */
+  buffer_word (&sst, ti);       /* Type index */
+  proc_patch_base = sst.size;
+  buffer_dword (&sst, 0);       /* Length of proc */
+  buffer_word (&sst, 0);        /* Length of prologue */
+  buffer_dword (&sst, 0);       /* Length of prologue and body */
+  buffer_word (&sst, 0);        /* Class type (for member functions) */
+  buffer_byte (&sst, 8);        /* 32-bit near */
+  if (cplusplus_flag)
+    buffer_enc (&sst, name);    /* Proc name */
+  else
+    buffer_nstr (&sst, name);   /* Proc name */
+  sst_end ();
+  r.ext = 0;
+  r.length = 2;
+  r.symbolnum = N_TEXT;
+  r.pcrel = 0;
+  r.unused = 0;
+  buffer_mem (&sst_reloc, &r, sizeof (r));
+}
+
+
+/* Locate the next N_LBRAC starting at symbol I.  If found, set
+   lbrac_index to the index of N_LBRAC and start a new block.  If
+   there is no N_LBRAC, set lbrac_index to -1. */
+
+static void next_lbrac (int i)
+{
+  lbrac_index = -1;
+  for (; i < sym_count; ++i)
+    if (sym_ptr[i].type == N_RBRAC || is_fun (&sym_ptr[i]))
+      return;
+    else if (sym_ptr[i].type == N_LBRAC)
+      {
+        lbrac_index = i;
+        block_begin (sym_ptr[i].value);
+        return;
+      }
+}
+
+
+/* Parse a stabs symbol.  The sym_ptr index is passed in INDEX.  As we
+   might have to concatenate successive symbol table entries, *INDEX
+   is updated to refer to the next symbol.  WHERE is the segment where
+   the symbol is defined (N_DATA, for instance).  If WHERE is -1,
+   there is no segment.  MSG is used for warning messages. This
+   function is called recursively for static functions (F) There's up
+   to one level of recursion.  The arguments of a function are read
+   twice: If FLAG is TRUE, we turn the arguments into local symbols;
+   if FLAG is FALSE, we put arguments into the args_list array. */
+
+static void parse_symbol (int *index, int where, const char *msg, int flag)
+{
+  char *name;
+  const char *str, *p;
+  const struct nlist *symbol, *sym2;
+  struct type *t1;
+  int i, n, ti, alloc_flag;
+
+  symbol = &sym_ptr[*index];
+  alloc_flag = concat_symbols (index, &str);
+  p = strchr (str, ':');
+  if (p != NULL)
+    {
+      n = p - str;
+      name = alloca (n + 1);
+      memcpy (name, str, n);
+      name[n] = 0;
+#if defined (DEBUG)
+      printf ("%s %s\n", msg, str);
+#endif
+      parse_ptr = p + 1;
+      switch (*parse_ptr)
+        {
+        case 'G':
+
+          /* Static storage, global scope */
+
+          ++parse_ptr;
+          ti = hll_type ();
+#if defined (DEBUG)
+          printf ("  type=%#x\n", ti);
+#endif
+          sym2 = find_symbol (name);
+          if (sym2 == NULL)
+            {
+              warning ("Cannot find address of global variable %s", name);
+              return;
+            }
+          if (sym2->type == N_EXT)
+            sst_static (name, 0, ti, sym2 - sym_ptr, 1);
+          else
+            sst_static (name, sym2->value, ti, sym2->type, 0);
+          break;
+
+        case 'S':
+        case 'V':
+
+          /* S = static storage, file scope,
+             V = static storage, local scope */
+
+          if (where == -1)
+            {
+              warning ("Cannot use symbol type %c with N_%s", *parse_ptr, msg);
+              return;
+            }
+          ++parse_ptr;
+          ti = hll_type ();
+#if defined (DEBUG)
+          printf ("  type=%#x\n", ti);
+#endif
+          sst_static (name, symbol->value, ti, where, 0);
+          break;
+
+        case 'p':
+
+          /* Function argument. */
+
+          if (where != -1)
+            {
+              warning ("Cannot use argument symbol with N_%s", msg);
+              return;
+            }
+          ++parse_ptr;
+          if (flag)
+            {
+              ti = hll_type ();
+#if defined (DEBUG)
+              printf ("  type=%#x\n", ti);
+#endif
+              sst_start (SST_auto);
+              buffer_dword (&sst, symbol->value);  /* Offset into stk frame */
+              buffer_word (&sst, ti);              /* Type index */
+              buffer_nstr (&sst, name);            /* Symbol name */
+              sst_end ();
+            }
+          else
+            {
+              t1 = parse_complete_type (NULL);
+              grow_by (&args_grow, 1);
+              args_list[args_grow.count++] = t1;
+            }
+          break;
+
+        case 'r':
+
+          /* Register variable. */
+
+          if (where != -1)
+            {
+              warning ("Cannot use register symbol with N_%s", msg);
+              return;
+            }
+          ++parse_ptr;
+          ti = hll_type ();
+          switch (symbol->value)
+            {
+            case 0:             /* EAX */
+              i = 0x10;
+              break;
+            case 1:             /* ECX */
+              i = 0x11;
+              break;
+            case 2:             /* EDX */
+              i = 0x12;
+              break;
+            case 3:             /* EBX */
+              i = 0x13;
+              break;
+            case 4:             /* ESP */
+              i = 0x14;
+              break;
+            case 5:             /* EBP */
+              i = 0x15;
+              break;
+            case 6:             /* ESI */
+              i = 0x16;
+              break;
+            case 7:             /* EDI */
+              i = 0x17;
+              break;
+            case 12:            /* ST(0) */
+              i = 0x80;
+              break;
+            case 13:            /* ST(1) */
+              i = 0x81;
+              break;
+            case 14:            /* ST(2) */
+              i = 0x82;
+              break;
+            case 15:            /* ST(3) */
+              i = 0x83;
+              break;
+            case 16:            /* ST(4) */
+              i = 0x84;
+              break;
+            case 17:            /* ST(5) */
+              i = 0x85;
+              break;
+            case 18:            /* ST(6) */
+              i = 0x86;
+              break;
+            case 19:            /* ST(7) */
+              i = 0x87;
+              break;
+            default:
+              warning ("unknown register %lu", symbol->value);
+              return;
+            }
+          sst_start (SST_reg);      /* Register variable */
+          buffer_word (&sst, ti);   /* Type index */
+          buffer_byte (&sst, i);    /* Register number */
+          buffer_nstr (&sst, name); /* Symbol name */
+          sst_end ();
+          break;
+
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+
+          /* Local symbol. */
+
+          if (where != -1)
+            {
+              warning ("Cannot use local symbol with N_%s", msg);
+              return;
+            }
+          ti = hll_type ();
+#if defined (DEBUG)
+          printf ("  type=%#x\n", ti);
+#endif
+          sst_start (SST_auto);
+          buffer_dword (&sst, symbol->value);    /* Offset into stk frame */
+          buffer_word (&sst, ti);                /* Type index */
+          buffer_nstr (&sst, name);              /* Symbol name */
+          sst_end ();
+          break;
+
+        case 'F':
+        case 'f':
+
+          /* Function. */
+
+          ++parse_ptr;
+          if (where != N_TEXT)
+            {
+              warning ("Cannot use function with N_%s", msg);
+              return;
+            }
+          last_fun_type.tag = ty_func;
+          last_fun_type.index = -1;
+          last_fun_type.d.func.ret = parse_type (NULL);
+
+          /* Don't check for end of string -- parse_ptr points to a
+             comma for nested functions! */
+
+          last_fun_type.d.func.args = NULL;
+          last_fun_type.d.func.arg_count = 0;
+          last_fun_valid = TRUE;
+          args_grow.count = 0;
+          last_fun_addr = symbol->value;
+          prologue_length = -1;
+
+          for (i = *index + 1; i < sym_count && sym_ptr[i].type == N_PSYM; ++i)
+            parse_symbol (&i, -1, "PSYM", FALSE);
+
+          define_fun (symbol);
+
+          /* Now look for N_LBRAC */
+
+          next_lbrac (i);
+          if (lbrac_index != -1)
+            {
+              if (prologue_length == -1)
+                prologue_length = sym_ptr[lbrac_index].value - last_fun_addr;
+            }
+
+          /* Parameters */
+
+          while (*index + 1 < sym_count && sym_ptr[*index+1].type == N_PSYM)
+            {
+              ++(*index);
+              parse_symbol (index, -1, "PSYM", TRUE);
+            }
+
+          /* If there's no N_LBRAC, write SST_end now */
+
+          if (lbrac_index == -1)
+            fun_end (*index+1);
+          break;
+        }
+    }
+  if (alloc_flag)
+    free ((void *)str);         /* Remove the const attribute */
+}
+
+
+/* Create a type tag for HLL type index INDEX.  TYPE is either SST_tag
+   (for structures and unions) or SST_class (for classes).  NAME is
+   the name of the structure, union or class. */
+
+static void type_tag (int type, int index, const char *name)
+{
+  if (name != NULL)
+    {
+      sst_start (type);
+      buffer_word (&sst, index);
+      if (type == SST_class)
+        buffer_enc (&sst, name);
+      else
+        buffer_nstr (&sst, name);
+      sst_end ();
+    }
+}
+
+
+/* Write a CuInfo SST entry to tell the debugger what compiler (C or
+   C++) has been used. */
+
+static void write_cuinfo (void)
+{
+  struct timestamp ts;
+  time_t now;
+  struct tm *tp;
+  byte lang;
+
+  if (cplusplus_flag)
+    lang = 0x02;                /* C++ */
+  else
+    lang = 0x01;                /* C */
+
+  time (&now);
+  tp = localtime (&now);
+  ts.year = tp->tm_year + 1900;
+  ts.month = tp->tm_mon + 1;
+  ts.day = tp->tm_mday;
+  ts.hours = tp->tm_hour;
+  ts.minutes = tp->tm_min;
+  ts.seconds = tp->tm_sec;
+  ts.hundredths = 0;
+  sst_start (SST_cuinfo);
+  buffer_byte (&sst, lang);
+  buffer_nstr (&sst, "    ");       /* Compiler options */
+  buffer_nstr (&sst, "");           /* Compiler date */
+  buffer_mem (&sst, &ts, sizeof (ts));
+  sst_end ();
+}
+
+
+/* Write a ChangSeg SST entry to define the text segment. */
+
+static void write_changseg (void)
+{
+  struct reloc r;
+
+  sst_start (SST_changseg);
+  r.address = sst.size;
+  buffer_word (&sst, 0);        /* Segment number */
+  buffer_word (&sst, 0);        /* Reserved */
+  sst_end ();
+  r.ext = 0;
+  r.length = 1;
+  r.symbolnum = N_TEXT;
+  r.pcrel = 0;
+  r.unused = 0;
+  buffer_mem (&sst_reloc, &r, sizeof (r));
+}
+
+
+/* Convert debug information.  The data is taken from the symbol and
+   string tables of the current a.out module.  Output is put into the
+   tt, sst etc. buffers. */
+
+void convert_debug (void)
+{
+  int i;
+  struct type *t1, *t2;
+
+  str_pool = strpool_init ();
+  grow_init (&stype_grow, &stype_list, sizeof (*stype_list), 32);
+  type_head = NULL; hll_type_index = 512;
+  grow_init (&block_grow, &block_stack, sizeof (*block_stack), 16);
+  grow_init (&args_grow, &args_list, sizeof (*args_list), 16);
+  last_fun_valid = FALSE; prologue_length = -1;
+  unnamed_struct_number = 1;
+
+  /* Check whether converting a translated C++ program. */
+
+  cplusplus_flag = (find_symbol ("__gnu_compiled_cplusplus") != NULL);
+
+  /* Parse the typedefs to avoid forward references. */
+
+  for (i = 0; i < sym_count; ++i)
+    switch (sym_ptr[i].type)
+      {
+      case N_LSYM:
+      case N_LCSYM:
+      case N_GSYM:
+      case N_PSYM:
+      case N_RSYM:
+      case N_STSYM:
+      case N_FUN:
+        parse_typedef (&i);
+        break;
+      }
+
+  /* Provide information about the compiler. */
+
+  write_cuinfo ();
+
+  /* Change the default segment. */
+
+  write_changseg ();
+
+  /* Parse the other symbol table entries. */
+
+  lbrac_index = -1; block_grow.count = 0; proc_patch_base = 0;
+  for (i = 0; i < sym_count; ++i)
+    switch (sym_ptr[i].type)
+      {
+      case N_LSYM:
+        parse_symbol (&i, -1, "LSYM", TRUE);
+        break;
+
+      case N_GSYM:
+        parse_symbol (&i, -1, "GSYM", TRUE);
+        break;
+
+      case N_LCSYM:
+        parse_symbol (&i, N_BSS, "LCSYM", TRUE);
+        break;
+
+      case N_STSYM:
+        parse_symbol (&i, N_DATA, "STSYM", TRUE);
+        break;
+
+      case N_RSYM:
+        parse_symbol (&i, -1, "RSYM", TRUE);
+        break;
+
+      case N_LBRAC:
+        if (lbrac_index == -1)  /* N_LBRAC without local symbols */
+          block_begin (sym_ptr[i].value);
+        else if (i != lbrac_index)
+          warning ("Invalid N_LBRAC");
+        next_lbrac (i + 1);
+        break;
+
+      case N_RBRAC:
+        block_end (i);
+        next_lbrac (i + 1);
+        break;
+
+      case N_FUN:
+        parse_symbol (&i, N_TEXT, "FUN", TRUE);
+        break;
+      }
+
+  /* Create tags for structures, unions and classes. */
+
+  for (t1 = type_head; t1 != NULL; t1 = t1->next)
+    if (t1->index != -1)
+      switch (t1->tag)
+        {
+        case ty_struc:
+          type_tag (SST_tag, t1->index, t1->d.struc.name);
+          break;
+        case ty_class:
+          type_tag (SST_class, t1->index, t1->d.class.name);
+          break;
+        default:
+          break;
+        }
+
+  /* Deallocate memory. */
+
+  grow_free (&stype_grow);
+  grow_free (&args_grow);
+  grow_free (&block_grow);
+  for (t1 = type_head; t1 != NULL; t1 = t2)
+    {
+      t2 = t1->next;
+      switch (t1->tag)
+        {
+        case ty_args:
+          if (t1->d.args.list != NULL)
+            free (t1->d.args.list);
+          break;
+        case ty_types:
+          if (t1->d.types.list != NULL)
+            free (t1->d.types.list);
+          break;
+        case ty_fields:
+          if (t1->d.fields.list != NULL)
+            free (t1->d.fields.list);
+          break;
+        case ty_values:
+          if (t1->d.values.list != NULL)
+            free (t1->d.values.list);
+          break;
+        default:
+          break;
+        }
+      free (t1);
+    }
+  type_head = NULL;
+  strpool_free (str_pool);
+  str_pool = NULL;
+}
Index: trunk/src/emx/src/emxomf/stabshll.h
===================================================================
--- trunk/src/emx/src/emxomf/stabshll.h	(revision 18)
+++ trunk/src/emx/src/emxomf/stabshll.h	(revision 18)
@@ -0,0 +1,26 @@
+/* stabshll.h -- Convert GNU-style a.out debug information into
+                 IBM OS/2 HLL 2 debug information
+   Copyright (c) 1993-1995 Eberhard Mattes
+
+This file is part of emxomf.
+
+emxomf is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxomf is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxomf; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+/* Used by emxomf.  May also be used for emxbind, but isn't
+   currently. */
+
+void convert_debug (void);
Index: trunk/src/emx/src/emxstack/COPYING
===================================================================
--- trunk/src/emx/src/emxstack/COPYING	(revision 18)
+++ trunk/src/emx/src/emxstack/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxstack/emxstack.c
===================================================================
--- trunk/src/emx/src/emxstack/emxstack.c	(revision 18)
+++ trunk/src/emx/src/emxstack/emxstack.c	(revision 18)
@@ -0,0 +1,657 @@
+/* emxstack.c -- Fix the stack size
+   Copyright (c) 1994-1998 Eberhard Mattes
+
+This file is part of emxstack.
+
+emxstack is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxstack is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxstack; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/dirtree.h>
+#include "defs.h"
+
+#define VERSION "0.9d"
+
+/* How to open a file.  This type is used for my_open(). */
+
+enum open_mode
+{
+  open_read, open_read_write
+};
+
+/* A file.  F is the stream.  NAME is the name of the file. */
+
+struct file
+{
+  FILE *f;
+  const char *name;
+};
+
+
+/* Mode of operation. */
+
+static enum op
+{
+  op_none,                      /* No command specified */
+  op_show,                      /* Display stack size */
+  op_check,                     /* Check whether fix is required */
+  op_fix,                       /* Fix stack size */
+  op_update,                    /* Update stack size */
+  op_force                      /* Set stack size */
+} operation;
+
+/* This variable is 2 if verbose output is requested (-v), 1 by
+   default, and 0 if emxstack should be quiet (-q). */
+
+static int verbosity;
+
+/* New stack size. */
+
+static long new_stack_size;
+
+/* Minimum stack size. */
+
+static long min_stack_size;
+
+
+/* Combine two 16-bit words (low word L and high word H) into a 32-bit
+   word. */
+
+#define COMBINE(L,H) ((L) | (long)((H) << 16))
+
+/* Round up to the next integral multiple of the page size. */
+
+#define ROUND_PAGE(X)  ((((X) - 1) & ~0xfff) + 0x1000)
+
+
+static void error (const char *fmt, ...) NORETURN2;
+
+
+/* Print an error message and abort.  This function is called like
+   printf() but never returns.  The message will be prefixed with
+   "emxbind: " and a newline will be added at the end. */
+
+static void error (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  fprintf (stderr, "emxstack: ");
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+  exit (2);
+}
+
+
+/* Print an error message and abort.  This function is called like
+   printf() but never returns.  The message will be prefixed with the
+   file name NAME and a newline will be added at the end. */
+
+static void file_error (const char *fmt, const char *name, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, name);
+  fprintf (stderr, "%s: ", name);
+  vfprintf (stderr, fmt, arg_ptr);
+  fputc ('\n', stderr);
+  exit (2);
+}
+
+
+/* Display a warning message.  If the -c or -f commands are used
+   without -v, the message is supressed. */
+
+static void file_warning (const char *fmt, const char *name, ...)
+{
+  va_list arg_ptr;
+
+  if (verbosity >= 2 || (operation != op_check && operation != op_fix))
+    {
+      va_start (arg_ptr, name);
+      fprintf (stderr, "%s: ", name);
+      vfprintf (stderr, fmt, arg_ptr);
+      fputc ('\n', stderr);
+    }
+}
+
+
+/* Read SIZE bytes from the file F to the buffer DST.  If there aren't
+   SIZE bytes at the current location of the read/write pointer, an
+   error message will be displayed and the program will be
+   terminated. */
+
+static void my_read (void *dst, size_t size, struct file *f)
+{
+  if (fread (dst, 1, size, f->f) != size)
+    {
+      if (ferror (f->f))
+        file_error ("%s", f->name, strerror (errno));
+      else
+        file_error ("End of file reached", f->name);
+    }
+}
+
+
+/* Write SIZE bytes from SRC to the file F. */
+
+static void my_write (const void *src, size_t size, struct file *f)
+{
+  if (fwrite (src, 1, size, f->f) != size)
+    file_error ("%s", f->name, strerror (errno));
+}
+
+
+/* Open the file named NAME and let F reference that file.  OMODE is
+   the open mode.  The file is always opened in binary mode. */
+
+static void my_open (struct file *f, const char *name, enum open_mode omode)
+{
+  const char *ms;
+
+  switch (omode)
+    {
+    case open_read:
+      ms = "rb";
+      break;
+    case open_read_write:
+      ms = "r+b";
+      break;
+    default:
+      ms = NULL;
+      break;
+    }
+  f->name = name;
+  f->f = fopen (name, ms);
+  if (f->f == NULL)
+    file_error ("%s", name, strerror (errno));
+}
+
+
+/* Close the file F if it is open. */
+
+static void my_close (struct file *f)
+{
+  if (fflush (f->f) != 0 || fclose (f->f) != 0)
+    file_error ("%s", f->name, strerror (errno));
+}
+
+
+/* Set the read/write pointer of the file F to location POS. */
+
+static void my_seek (struct file *f, long pos)
+{
+  if (fseek (f->f, pos, SEEK_SET) != 0)
+    file_error ("%s", f->name, strerror (errno));
+}
+
+
+/* Return the length of the file F.  Note that this function moves the
+   read/write pointer to the end of the file. */
+
+static long my_size (struct file *f)
+{
+  long n;
+
+  if (fseek (f->f, 0L, SEEK_END) != 0 || (n = ftell (f->f)) < 0)
+    error ("seek failed (`%s')", f->name);
+  return n;
+}
+
+
+/* Tell the user how to use this program. */
+
+static void usage (void)
+{
+  fputs ("emxstack " VERSION " -- "
+         "Copyright (c) 1994-1995 by Eberhard Mattes\n\n", stderr);
+  fputs ("Usage: emxstack <command> [<options>] <file>...\n", stderr);
+  fputs ("\nCommands:\n", stderr);
+  fputs ("-c        Check whether stack size should be fixed\n", stderr);
+  fputs ("-d        Display stack size\n", stderr);
+  fputs ("-f        Fix stack size for emx 0.9\n", stderr);
+  fputs ("-s<n>     Set stack size to <n> Kbyte\n", stderr);
+  fputs ("-u<n>     Update stack size to <n> Kbyte (if less than <n> Kbyte)\n",
+         stderr);
+  fputs ("\nOptions:\n", stderr);
+  fputs ("-p        Act on all files in PATH\n", stderr);
+  fputs ("-q        Be quiet\n", stderr);
+  fputs ("-v        Be verbose\n", stderr);
+  exit (1);
+}
+
+
+/* Process the file F. */
+
+static void process_file (struct file *f)
+{
+  struct exe1_header h1;
+  struct exe2_header h2;
+  struct os2_header ho;
+  struct object stack_obj, temp_obj;
+  long off_new_exe, off_stack_obj, size;
+  long stack_size, stack_kb;
+  dword i;
+  int uses_emx;
+  byte buf[2];
+
+  /* Read the DOS EXE header. */
+
+  size = my_size (f);
+  if (size < sizeof (h1))
+    {
+      file_warning ("Not an executable file", f->name);
+      return;
+    }
+  my_seek (f, 0);
+  my_read (&h1, sizeof (h1), f);
+  if (h1.magic != 0x5a4d)
+    {
+      file_warning ("Not an executable file", f->name);
+      return;
+    }
+
+  /* Read the second part of the DOS EXE header. */
+
+  if (size < sizeof (h1) + sizeof (h2)
+      || h1.reloc_ptr < sizeof (h1) + sizeof (h2))
+    {
+      file_warning ("DOS executable", f->name);
+      return;
+    }
+  my_read (&h2, sizeof (h2), f);
+  off_new_exe = COMBINE (h2.new_lo, h2.new_hi);
+
+  /* Read the magic word of the new EXE header. */
+
+  if (off_new_exe + 2 > size)
+    {
+      file_warning ("DOS executable", f->name);
+      return;
+    }
+  my_seek (f, off_new_exe);
+  my_read (buf, 2, f);
+  if (!(buf[0] == 'L' && buf[1] == 'X'))
+    {
+      file_warning ("Not an LX executable file", f->name);
+      return;
+    }
+
+  /* Read the LX header. */
+
+  my_seek (f, off_new_exe);
+  my_read (&ho, sizeof (ho), f);
+
+  /* Skip dynamic link libraries; they don't have a stack object. */
+
+  if (ho.mod_flags & 0x8000)
+    {
+      file_warning ("Dynamic link library", f->name);
+      return;
+    }
+
+  /* Retrieve the stack size from the object-relative initial value of
+     ESP.  We ignore the stack_size field of the LX header -- it is
+     not set by emxbind and was not set in older versions of
+     LINK386. */
+
+  stack_size = ho.stack_esp;
+  stack_kb = stack_size / 1024;
+
+  /* Check whether the object number for ESP is valid. */
+
+  if (ho.stack_obj < 1 || ho.stack_obj > ho.obj_count)
+    file_error ("Invalid stack object number", f->name);
+
+  /* Read the object record for the stack. */
+
+  off_stack_obj = (off_new_exe + ho.obj_offset
+                   + (ho.stack_obj - 1) * sizeof (struct object));
+  my_seek (f, off_stack_obj);
+  my_read (&stack_obj, sizeof (stack_obj), f);
+
+  /* Scan the import module table to check whether the executable
+     imports EMX.DLL, EMXLIBC.DLL, or EMXWRAP.DLL.  If at least one of
+     these DLLs is imported, `uses_emx' is set to true. */
+
+  uses_emx = 0;
+  my_seek (f, off_new_exe + ho.impmod_offset);
+  for (i = 0; i < ho.impmod_count; ++i)
+    {
+      byte len, name[255+1];
+
+      my_read (&len, 1, f);
+      if (len != 0)
+        my_read (name, len, f);
+      name[len] = 0;
+      if (stricmp (name, "EMX") == 0 || stricmp (name, "EMXLIBC") == 0
+          || stricmp (name, "EMXWRAP") == 0)
+        {
+          uses_emx = TRUE;
+          break;
+        }
+    }
+
+  /* Now perform the action requested by the user. */
+
+  switch (operation)
+    {
+    case op_show:
+      printf ("%s: %lu Kbyte\n", f->name, stack_kb);
+      break;
+
+    case op_check:
+      if (!uses_emx)
+        file_warning ("Does not use emx.dll", f->name);
+      else if (stack_size <= 16384)
+        printf ("%s: Needs to be fixed\n", f->name);
+      else if (verbosity >= 2)
+        printf ("%s: Does not need to be fixed\n", f->name);
+      break;
+
+    case op_fix:
+      if (!uses_emx)
+        {
+          file_warning ("Does not use emx.dll", f->name);
+          break;
+        }
+      /*NOBREAK*/
+
+    case op_update:
+      if (stack_size >= min_stack_size)
+        {
+          printf ("%s: Stack size is %lu Kbyte; not changed\n",
+                  f->name, stack_kb);
+          break;
+        }
+      /*NOBREAK*/
+
+    case op_force:
+
+      /* Changing the stack size when there are pages assigned to the
+         stack object or any succeeding non-resource object is
+         difficult as the page map must be changed.  Changing the
+         stack size when there are any non-resource objects following
+         the stack object is difficult or impossible as relocations
+         may have to be changed or invented.  Therefore, we fail if
+         there are pages assigned to the stack object or if any
+         non-resource objects follow the stack object. */
+
+      if (stack_obj.map_count != 0)
+        {
+          file_warning ("Stack object has page map entries"
+                        " -- stack size not changed", f->name);
+          return;
+        }
+
+      my_seek (f, off_stack_obj + sizeof (struct object));
+      for (i = ho.stack_obj + 1; i <= ho.obj_count; ++i)
+        {
+          my_read (&temp_obj, sizeof (temp_obj), f);
+          if (!(temp_obj.attr_flags & 0x08))
+            {
+              file_warning ("A non-resource object succeeds the stack object"
+                            " -- stack size not changed", f->name);
+              return;
+            }
+        }
+
+      if (verbosity >= 2)
+        printf ("%s: Stack size was %lu Kbyte\n", f->name, stack_kb);
+
+      /* Update the initial value of ESP and the size of the stack
+         object. */
+
+      ho.stack_esp = new_stack_size;
+      stack_obj.virt_size = ROUND_PAGE (new_stack_size);
+
+      /* Set the stack_size field to zero -- it is not used. */
+
+      ho.stack_size = 0;
+
+      /* Write the modified LX header. */
+
+      my_seek (f, off_new_exe);
+      my_write (&ho, sizeof (ho), f);
+
+      /* Write the modified stack object record. */
+
+      my_seek (f, off_stack_obj);
+      my_write (&stack_obj, sizeof (stack_obj), f);
+      break;
+
+    default:
+      abort ();
+    }
+}
+
+
+/* Process the file FNAME. */
+
+static void process_fname (const char *fname)
+{
+  struct file f;
+
+  switch (operation)
+    {
+    case op_show:
+    case op_check:
+      my_open (&f, fname, open_read);
+      break;
+
+    case op_update:
+    case op_force:
+      my_open (&f, fname, open_read_write);
+      break;
+
+    default:
+      abort ();
+    }
+  process_file (&f);
+  my_close (&f);
+}
+
+
+/* Process all files in directory NAME. */
+
+static void process_dir (const char *name)
+{
+  struct _dt_tree *tree;
+  struct _dt_node *p;
+  char path[512], *s;
+
+  tree = _dt_read (name, "*.exe", 0);
+  if (tree == NULL)
+    {
+      file_warning ("Cannot open directory", name);
+      return;
+    }
+  strcpy (path, name);
+  s = strchr (path, 0);
+  if (s != path && strchr ("\\:/", s[-1]) == NULL)
+    *s++ = '\\';
+  for (p = tree->tree; p != NULL; p = p->next)
+    if (!(p->attr & 0x10))
+      {
+        strcpy (s, p->name);
+        process_fname (path);
+      }
+  _dt_free (tree);
+}
+
+
+/* Process all directories listed in LIST. */
+
+static void process_env (const char *list)
+{
+  char dir[512];
+  const char *end;
+  int i;
+
+  if (list == NULL || *list == 0)
+    return;
+  for (;;)
+    {
+      while (*list == ' ' || *list == '\t') ++list;
+      if (*list == 0) break;
+      end = list;
+      while (*end != 0 && *end != ';') ++end;
+      i = end - list;
+      while (i>0 && (list[i-1] == ' ' || list[i-1] == '\t')) --i;
+      if (i != 0)
+        {
+          memcpy (dir, list, i);
+          dir[i] = 0;
+          process_dir (dir);
+        }
+      if (*end == 0) break;
+      list = end + 1;
+    }
+}
+
+
+/* Set the mode of operation to X. */
+
+static void set_op (enum op x)
+{
+  if (operation != op_none)
+    error ("More than one operation specified");
+  operation = x;
+}
+
+
+/* Get the new stack size from the argument of the option currently
+   being parsed. */
+
+static void get_new_stack_size (void)
+{
+  long n;
+  char *e;
+
+  errno = 0;
+  n = strtol (optarg, &e, 0);
+  if (errno != 0 || n < 20 || n > 512*1024 || e == optarg || *e != 0)
+    error ("invalid stack size specified");
+  new_stack_size = ROUND_PAGE (n * 1024);
+}
+  
+
+/* The main function of emxstack. */
+
+int main (int argc, char *argv[])
+{
+  int c;
+  int path;
+
+  /* Expand wildcards. */
+
+  _wildcard (&argc, &argv);
+
+  /* Set default values. */
+
+  verbosity = 1; path = FALSE;
+  new_stack_size = 0;
+  min_stack_size = 0;
+  operation = op_none;
+
+  /* Let getopt() display error messages. */
+
+  opterr = TRUE;
+  optswchar = "-";
+  optind = 0;
+
+  /* Display usage information when called without arguments. */
+
+  if (argc < 2 || strcmp (argv[1], "-?") == 0)
+    usage ();
+
+  /* Parse the command line options. */
+
+  while ((c = getopt (argc, argv, "cdfpqs:u:v")) != EOF)
+    switch (c)
+      {
+      case 'c':
+        set_op (op_check);
+        break;
+
+      case 'd':
+        set_op (op_show);
+        break;
+
+      case 'f':
+        set_op (op_update);
+        min_stack_size = 17 * 1024;
+        new_stack_size = 8 * 1024 * 1024;
+        break;
+
+      case 'p':
+        path = TRUE;
+        break;
+
+      case 's':
+        set_op (op_force);
+        get_new_stack_size ();
+        min_stack_size = 0;
+        break;
+
+      case 'u':
+        set_op (op_update);
+        get_new_stack_size ();
+        min_stack_size = new_stack_size;
+        break;
+
+      case 'q':
+        verbosity = 0;
+        break;
+
+      case 'v':
+        verbosity = 2;
+        break;
+
+      default:
+        exit (1);
+      }
+
+  if (operation == op_none)
+    error ("No operation given on the command line");
+
+  if (path)
+    {
+      /* Use PATH. */
+
+      if (optind < argc)
+        error ("No files must be given on the command line if -p is used");
+      process_env (getenv ("PATH"));
+    }
+
+  else
+    {
+      /* Process the remaining arguments as files. */
+
+      int i;
+
+      i = optind;
+      if (i >= argc)
+        error ("No files given on the command line");
+      while (i < argc)
+        process_fname (argv[i++]);
+    }
+  return 0;
+}
Index: trunk/src/emx/src/emxstack/makefile
===================================================================
--- trunk/src/emx/src/emxstack/makefile	(revision 18)
+++ trunk/src/emx/src/emxstack/makefile	(revision 18)
@@ -0,0 +1,51 @@
+#
+# /emx/src/emxstack/makefile
+#
+# Copyright (c) 1994-1998 by Eberhard Mattes
+#
+# This file is part of emxstack.
+#
+# emxstack is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emxstack is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emxstack; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+.SUFFIXES: .c .o
+
+BIN=d:\emx\bin\ #
+INC=..\include\ #
+
+CC=gcc
+CFLAGS=-O -Wall -I../include
+LFLAGS=-s -Zsmall-conv
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+default:	all
+all:		emxstack
+emxstack:	$(BIN)emxstack.exe
+
+emxstack.o: emxstack.c $(INC)defs.h
+
+$(BIN)emxstack.exe: emxstack.o
+	gcc $(LFLAGS) -o $(BIN)emxstack.exe emxstack.o
+
+clean:
+	-del *.o
+
+realclean: clean
+	-del $(BIN)emxstack.exe
+
+# End of /emx/src/emxstack/makefile
Index: trunk/src/emx/src/emxtsf/COPYING
===================================================================
--- trunk/src/emx/src/emxtsf/COPYING	(revision 18)
+++ trunk/src/emx/src/emxtsf/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxtsf/emxtsf.c
===================================================================
--- trunk/src/emx/src/emxtsf/emxtsf.c	(revision 18)
+++ trunk/src/emx/src/emxtsf/emxtsf.c	(revision 18)
@@ -0,0 +1,456 @@
+/* emxtsf.c -- Simplify construction of .TSF files
+   Copyright (c) 1996-1998 Eberhard Mattes
+
+This file is part of emxtsf.
+
+emxtsf is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxtsf is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxtsf; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/moddef.h>
+
+/* The version number of this program.  This is printed with the usage
+   message. */
+
+#define VERSION "0.9d"
+
+
+struct sym
+{
+  struct sym *next;
+  int ord;
+  char def;
+  char *name;
+};
+
+#define HASHSIZE        997
+static struct sym *sym_hash[HASHSIZE];
+static const char *dll_name;
+static int warning_level;
+
+static void *xmalloc (size_t n)
+{
+  void *p;
+
+  p = malloc (n);
+  if (p == NULL)
+    {
+      fprintf (stderr, "Out of memory\n");
+      exit (2);
+    }
+  return p;
+}
+
+
+static void usage (void)
+{
+  fputs ("emxtsf " VERSION " -- Copyright (c) 1996 by Eberhard Mattes\n\n"
+         "Usage: emxtsf [-d <dll_name>] [-w <level>] <tss_file> <map_file> <def_file>\n",
+         stderr);
+  exit (1);
+}
+
+
+static int hash (const char *name, int len)
+{
+  unsigned h;
+  int i;
+
+  h = 0;
+  for (i = 0; i < len; ++i)
+    h = (h << 2) ^ (unsigned char)name[i];
+  return h % HASHSIZE;
+}
+
+
+static struct sym *find_sym (const char *name, int len)
+{
+  struct sym *sp;
+
+  for (sp = sym_hash[hash (name, len)]; sp != NULL; sp = sp->next)
+    if (strlen (sp->name) == len && memcmp (sp->name, name, len) == 0)
+      return sp;
+  return NULL;
+}
+
+
+static void read_map (const char *fname)
+{
+  FILE *f;
+  char line[512];
+  char start;
+  unsigned seg, off;
+  int pos, i, h, len;
+  struct sym *sp;
+
+  f = fopen (fname, "r");
+  if (f == NULL)
+    {
+      perror (fname);
+      exit (2);
+    }
+  start = 0;
+  while (!start && fgets (line, sizeof (line), f) != NULL)
+    start = strcmp (line, "  Address         Publics by Value\n") == 0;
+  if (!start || fgets (line, sizeof (line), f) == NULL || line[0] != '\n')
+    {
+      fprintf (stderr, "%s: Publics not found\n", fname);
+      exit (2);
+    }
+
+  while (fgets (line, sizeof (line), f) != NULL && line[0] != '\n')
+    {
+      if (sscanf (line, " %x:%x %n", &seg, &off, &pos) != 2)
+        break;
+      if (strncmp (line + pos, "Imp", 3) == 0)
+        continue;
+      while (line[pos] == ' ')
+        ++pos;
+      i = pos;
+      while (line[i] != ' ' && line[i] != '\n' && line[i] != 0)
+        ++i;
+      if (i > pos && line[i] == '\n')
+        {
+          len = i - pos;
+          if (find_sym (line + pos, len) != NULL)
+            {
+              fprintf (stderr, "%s: Symbol `%.*s' multiply defined\n",
+                       fname, len, line + pos);
+              exit (2);
+            }
+          h = hash (line + pos, len);
+          sp = xmalloc (sizeof (*sp));
+          sp->ord = 0;
+          sp->def = 0;
+          sp->name = xmalloc (len + 1);
+          memcpy (sp->name, line + pos, len);
+          sp->name[len] = 0;
+          sp->next = sym_hash[h];
+          sym_hash[h] = sp;
+        }
+    }
+
+  fclose (f);
+}
+
+
+static int handle_def (struct _md *md, const _md_stmt *stmt,
+                       _md_token token, void *arg)
+{
+  struct sym *sp;
+  const char *name;
+
+  switch (token)
+    {
+    case _MD_EXPORTS:
+      if (stmt->export.ordinal != 0)
+        {
+          name = stmt->export.internalname;
+          if (*name == 0)
+            name = stmt->export.entryname;
+          sp = find_sym (name, strlen (name));
+          if (sp != NULL)
+            sp->ord = stmt->export.ordinal;
+        }
+      break;
+
+    case _MD_parseerror:
+      fprintf (stderr, "%s:%ld: %s\n", (char *)arg, _md_get_linenumber (md),
+               _md_errmsg (stmt->error.code));
+      exit (2);
+
+    default:
+      break;
+    }
+  return 0;
+}
+
+
+static void read_def (const char *fname)
+{
+  struct _md *md;
+
+  md = _md_open (fname);
+  if (md == NULL)
+    {
+      perror (fname);
+      exit (2);
+    }
+  _md_next_token (md);
+  _md_parse (md, handle_def, (void *)fname);
+  _md_close (md);
+}
+
+
+static const char *tss_fname;
+static int tss_lineno;
+
+static void syntax (void)
+{
+  fprintf (stderr, "%s:%d: Syntax error\n", tss_fname, tss_lineno);
+  exit (2);
+}
+
+
+static void read_tss (const char *fname)
+{
+  FILE *f;
+  char line[512], *s, c;
+  char fun[512], fun2[520];
+  char group[40], type[40], mem[128];
+  char *prefix;
+  struct sym *sp;
+  int i, j, len, off, minor, uminor;
+
+  f = fopen (fname, "r");
+  if (f == NULL)
+    {
+      perror (fname);
+      exit (2);
+    }
+
+  tss_fname = fname;
+  tss_lineno = 0;
+  group[0] = 0; type[0] = 0;
+  uminor = 0x7fff;
+  if (dll_name == NULL)
+    prefix = "";
+  else
+    {
+      prefix = xmalloc (strlen (dll_name) + 3);
+      sprintf (prefix, "%s: ", dll_name);
+    }
+
+  while (fgets (line, sizeof (line), f) != NULL)
+    {
+      ++tss_lineno;
+      s = strchr (line, '\n');
+      if (s != NULL) *s = 0;
+      if (line[0] == ';' || line[0] == 0)
+        continue;
+      if (line[1] != ' ' || line[2] == ' ')
+        syntax ();
+      if (line[0] == 'G')
+        {
+          _strncpy (group, line + 2, sizeof (group));
+          continue;
+        }
+      if (line[0] == 'T')
+        {
+          _strncpy (type, line + 2, sizeof (type));
+          continue;
+        }
+      if (group[0] == 0 || type[0] == 0)
+        syntax ();
+      i = 2;
+      while (line[i] != ' ' && line[i] != '(' && line[i] != 0)
+        ++i;
+      len = i - 2;
+      if (len >= sizeof (fun) - 1)
+        len = sizeof (fun) - 2;
+      memcpy (fun, line + 2, len);
+      fun[len] = 0;
+      sp = find_sym (fun, len);
+      if (sp == NULL)
+        {
+          fun[0] = '_';
+          memcpy (fun + 1, line + 2, len);
+          fun[++len] = 0;
+          sp = find_sym (fun, len);
+          if (sp == NULL)
+            {
+              fprintf (stderr, "%s:%d: Symbol `%s' not found\n",
+                       tss_fname, tss_lineno, fun + 1);
+              continue;
+            }
+        }
+      if (sp->def)
+        {
+          fprintf (stderr, "%s:%d: Symbol `%s' multiply defined\n",
+                   tss_fname, tss_lineno, fun);
+          continue;
+        }
+      sp->def = 1;
+      if (line[0] == 'I')
+        continue;
+      if (sp->ord != 0)
+        minor = sp->ord;
+      else
+        minor = uminor--;
+      while (line[i] == ' ')
+        ++i;
+      if (line[i] != '(')
+        syntax ();
+      ++i;
+      printf ("TRACE\n"
+              "MINOR=0x%.4x,\n"
+              "TP=.%s,\n"
+              "TYPE=(PRE,%s),\n"
+              "GROUP=%s,\n"
+              "DESC=\"%s%s  Pre-Invocation\",\n",
+              minor, fun, type, group, prefix, fun);
+      while (line[i] == ' ')
+        ++i;
+      if (line[i] != ')')
+        {
+          off = 4;
+          for (;;)
+            {
+              c = line[i];
+              ++i;
+              if (line[i] != ' ')
+                syntax ();
+              while (line[i] == ' ')
+                ++i;
+              j = i;
+              while (line[i] != ' ' && line[i] != ',' && line[i] != ')'
+                     && line[i] != 0)
+                ++i;
+              if (i == j)
+                syntax ();
+
+              printf ("FMT=\"%.*s = ", i - j, line + j);
+              switch (c)
+                {
+                case 'q':
+                  fputs ("%P%Q", stdout);
+                  sprintf (mem, "MEM32=(FESP+%d,D,8)", off);
+                  off += 8;
+                  break;
+                case 'i':
+                  fputs ("%P%D", stdout);
+                  sprintf (mem, "MEM32=(FESP+%d,D,4)", off);
+                  off += 4;
+                  break;
+                case 'p':
+                  fputs ("%P%F", stdout);
+                  sprintf (mem, "MEM32=(FESP+%d,D,4)", off);
+                  off += 4;
+                  break;
+                case 's':
+                  fputs ("\\\"%P%S\\\"", stdout);
+                  sprintf (mem, "ASCIIZ32=(FESP+%d,I,128)", off);
+                  off += 4;
+                  break;
+                default:
+                  syntax ();
+                }
+              printf ("\",\n%s,\n", mem);
+              while (line[i] == ' ')
+                ++i;
+              if (line[i] == ')')
+                break;
+              if (line[i] != ',')
+                syntax ();
+              ++i;
+              while (line[i] == ' ')
+                ++i;
+            }
+        }
+      ++i;
+      while (line[i] == ' ')
+        ++i;
+      if (line[i] != 0 && line[i] != ';')
+        syntax ();
+      puts ("FMT=\"Return address = %P%F\",");
+      puts ("MEM32=(FESP+0,D,4)\n");
+      sprintf (fun2, "__POST$%s", fun);
+      sp = find_sym (fun2, strlen (fun2));
+      if (sp != NULL)
+        {
+          printf ("TRACE\n"
+                  "MINOR=0x%.4x,\n"
+                  "TP=.%s,\n"
+                  "TYPE=(POST,%s),\n"
+                  "GROUP=%s,\n"
+                  "DESC=\"%s%s  Post-Invocation\",\n",
+                  minor + 0x8000, fun2, type, group, prefix, fun);
+          switch (line[0])
+            {
+            case 'v':
+              break;
+            case 'i':
+              puts ("FMT=\"Return value = %D\",\n"
+                    "REGS=(EAX)");
+              break;
+            case 'p':
+              puts ("FMT=\"Return value = %F\",\n"
+                    "REGS=(EAX)");
+              break;
+            case 'q':
+              puts ("FMT=\"Return value = %Q\",\n"
+                    "REGS=(EAX,EDX)");
+              break;
+            default:
+              syntax ();
+            }
+          putchar ('\n');
+        }
+      else if (warning_level >= 2)
+        fprintf (stderr, "%s:%d: Epilogue not found for symbol `%s'\n",
+                 tss_fname, tss_lineno, fun);
+    }
+  fclose (f);
+}
+
+
+static void list_untraced (void)
+{
+  int h;
+  struct sym *sp;
+
+  for (h = 0; h < HASHSIZE; ++h)
+    for (sp = sym_hash[h]; sp != NULL; sp = sp->next)
+      if (!sp->def && sp->ord != 0)
+        fprintf (stderr, "Not traced: %s\n", sp->name);
+}
+
+
+int main (int argc, char *argv[])
+{
+  int c;
+  long n;
+  char *end;
+
+  while ((c = getopt (argc, argv, "d:w:")) != -1)
+    switch (c)
+      {
+      case 'd':
+        dll_name = optarg;
+        break;
+      case 'w':
+        n = strtol (optarg, &end, 10);
+        if (end == optarg || *end != 0 || n < 0 || n > 2)
+          usage ();
+        warning_level = (int)n;
+        break;
+      default:
+        usage ();
+      }
+
+  if (argc - optind != 3)
+    usage ();
+
+  read_map (argv[optind+1]);
+  read_def (argv[optind+2]);
+  read_tss (argv[optind+0]);
+  if (warning_level >= 1)
+    list_untraced ();
+  return 0;
+}
Index: trunk/src/emx/src/emxtsf/makefile
===================================================================
--- trunk/src/emx/src/emxtsf/makefile	(revision 18)
+++ trunk/src/emx/src/emxtsf/makefile	(revision 18)
@@ -0,0 +1,50 @@
+#
+# /emx/src/emxtsf/makefile
+#
+# Copyright (c) 1996 by Eberhard Mattes
+#
+# This file is part of emxtsf.
+#
+# emxtsf is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emxtsf is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emxtsf; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+.SUFFIXES: .c .o
+
+BIN=/emx/bin/
+
+CC=gcc
+CFLAGS=-O -Wall
+LFLAGS=-s -Zsmall-conv
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+default:	all
+all:		emxtsf
+emxtsf:		$(BIN)emxtsf.exe
+
+$(BIN)emxtsf.exe: emxtsf.o
+	gcc $(LFLAGS) -o $(BIN)emxtsf.exe emxtsf.o -lmoddef
+
+emxtsf.o: emxtsf.c
+
+clean:
+	-rm *.o
+
+realclean: clean
+	-del $(BIN)emxtsf.exe
+
+# End of /emx/src/emxtsf/makefile
Index: trunk/src/emx/src/emxupd/COPYING
===================================================================
--- trunk/src/emx/src/emxupd/COPYING	(revision 18)
+++ trunk/src/emx/src/emxupd/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/emxupd/emxupd.c
===================================================================
--- trunk/src/emx/src/emxupd/emxupd.c	(revision 18)
+++ trunk/src/emx/src/emxupd/emxupd.c	(revision 18)
@@ -0,0 +1,160 @@
+/* emxupd.c -- Update a DLL or EXE which is in use
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of emxupd.
+
+emxupd is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emxupd is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emxupd; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOSERRORS
+#define INCL_DOSFILEMGR
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <os2.h>
+
+APIRET APIENTRY DosReplaceModule (PCSZ pszOld, PCSZ pszNew, PCSZ pszBackup);
+
+
+static void usage (void)
+{
+  puts ("Usage: emxupd <source_file> <target_path>\n"
+        "       emxupd -d <old_file>\n"
+        "Options:\n"
+        "  -d   Delete the file");
+  exit (1);
+}
+
+
+static void replace_module (const char *old_path, const char *new_path)
+{
+  ULONG rc;
+
+  /* First try to delete or copy the file the standard way.  Note that
+     DosReplaceModule works only if the file is really in use. */
+
+  if (new_path == NULL)
+    rc = DosDelete (old_path);
+  else
+    rc = DosCopy (new_path, old_path, DCPY_EXISTING | DCPY_FAILEAS);
+
+  /* If deleting or copying the file failed due to the module being in
+     use, call DosReplaceModule. */
+
+  if (rc == ERROR_SHARING_VIOLATION)
+    {
+      rc = DosReplaceModule (old_path, new_path, NULL);
+      if (rc == 0 && new_path == NULL)
+        rc = DosDelete (old_path);
+    }
+
+  /* Examine the return code. */
+
+  switch (rc)
+    {
+    case 0:
+      return;
+    case ERROR_FILE_NOT_FOUND:
+      puts ("File not found.");
+      exit (2);
+    case ERROR_PATH_NOT_FOUND:
+      puts ("Path not found.");
+      exit (2);
+    case ERROR_MODULE_IN_USE:
+      puts ("Module is in use.");
+      exit (2);
+    default:
+      printf ("Operation failed, error code = %lu.\n", rc);
+      exit (2);
+    }
+}
+
+
+#define PATH_DELIM_P(c) ((c) == ':' || (c) == '\\' || (c) == '/')
+
+static void update (const char *source_path, const char *target_path)
+{
+  ULONG rc;
+  FILESTATUS3 info;
+  size_t len;
+  const char *last;
+  char concat[CCHMAXPATH];
+
+  /* If TARGET_PATH is a directory, append the last component of
+     SOURCE_PATH to TARGET_PATH. */
+
+  rc = DosQueryPathInfo (target_path, FIL_STANDARD, &info, sizeof (info));
+  if (rc == 0 && (info.attrFile & FILE_DIRECTORY))
+    {
+      len = strlen (target_path);
+      last = _getname (source_path);
+      if (len != 0 && PATH_DELIM_P (target_path[len-1]))
+        len -= 1;
+      if (len + strlen (last) + 1 > sizeof (concat))
+        {
+          printf ("Path name too long\n");
+          exit (2);
+        }
+      memcpy (concat, target_path, len);
+      concat[len] = '\\';
+      strcpy (concat + len + 1, last);
+      target_path = concat;
+    }
+
+  /* Replace the module. */
+
+  replace_module (target_path, source_path);
+  printf ("\"%s\" replaced with \"%s\".\n", target_path, source_path);
+}
+
+
+static void delete (const char *old_path)
+{
+  replace_module (old_path, NULL);
+  printf ("\"%s\" deleted.\n", old_path);
+}
+
+
+int main (int argc, char *argv[])
+{
+  int c;
+  char delete_flag = FALSE;
+
+  /* This check is not required as we use LINK386 for linking. */
+
+  if (_osmode != OS2_MODE)
+    exit (2);
+
+  /* Parse the command line options. */
+
+  while ((c = getopt (argc, argv, "d")) != -1)
+    switch (c)
+      {
+      case 'd':
+        delete_flag = 1;
+        break;
+      default:
+        usage ();
+      }
+
+  if (delete_flag && argc - optind == 1)
+    delete (argv[optind+0]);
+  else if (!delete_flag && argc - optind == 2)
+    update (argv[optind+0], argv[optind+1]);
+  else
+    usage ();
+  return 0;
+}
Index: trunk/src/emx/src/emxupd/makefile
===================================================================
--- trunk/src/emx/src/emxupd/makefile	(revision 18)
+++ trunk/src/emx/src/emxupd/makefile	(revision 18)
@@ -0,0 +1,46 @@
+#
+# /emx/src/emxupd/makefile
+#
+# Copyright (c) 1996 by Eberhard Mattes
+#
+# This file is part of emxupd.
+#
+# emxupd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emxupd is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emxupd; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+BIN=/emx/bin/
+
+CC=gcc
+CFLAGS=-O -Zomf -Zsys -Wall
+LFLAGS=-s -Zsmall-conv $(CFLAGS)
+
+default:	all
+all:		emxupd
+emxupd:	$(BIN)emxupd.exe
+
+emxupd.obj: emxupd.c
+	$(CC) $(CFLAGS) -c emxupd.c
+
+$(BIN)emxupd.exe: emxupd.obj
+	$(CC) $(LFLAGS) -o $(BIN)emxupd.exe emxupd.obj
+
+clean:
+	-rm *.obj
+
+realclean: clean
+	-rm $(BIN)emxupd.exe
+
+# End of /emx/src/emxupd/makefile
Index: trunk/src/emx/src/include/defs.h
===================================================================
--- trunk/src/emx/src/include/defs.h	(revision 18)
+++ trunk/src/emx/src/include/defs.h	(revision 18)
@@ -0,0 +1,288 @@
+/* defs.h -- Various definitions for emx development utilities
+   Copyright (c) 1992-1998 Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define FALSE 0
+#define TRUE  1
+
+#ifdef __GNUC__
+#define NORETURN2        __attribute__ ((noreturn))
+#define ATTR_PRINTF(s,f) __attribute__ ((__format__ (__printf__, s, f)))
+#else
+#define NORETURN2
+#define ATTR_PRINTF(s,f)
+#endif
+
+
+/* Stabs constants. */
+
+#define N_EXT           0x01    /* Symbol is external */
+#define N_ABS           0x02    /* Absolute address */
+#define N_TEXT          0x04    /* In .text segment */
+#define N_DATA          0x06    /* In .data segment */
+#define N_BSS           0x08    /* In .bss segment */
+
+#define N_INDR          0x0a
+#define N_WEAKU         0x0d    /* Includes N_EXT! */
+
+#define N_SETA          0x14
+#define N_SETT          0x16
+#define N_SETD          0x18
+
+#define N_GSYM          0x20
+#define N_FUN           0x24
+#define N_STSYM         0x26
+#define N_LCSYM         0x28
+#define N_RSYM          0x40
+#define N_SLINE         0x44
+#define N_SO            0x64
+#define N_LSYM          0x80
+#define N_SOL           0x84
+#define N_PSYM          0xa0
+#define N_LBRAC         0xc0
+#define N_RBRAC         0xe0
+
+#define N_IMP1          0x68    /* Import reference (emx specific) */
+#define N_IMP2          0x6a    /* Import definition (emx specific) */
+
+/* The maximum OMF record size supported by OMF linkers.  This value
+   includes the record type, length and checksum fields. */
+
+#define MAX_REC_SIZE    1024
+
+/* OMF record types.  To get the 32-bit variant of a record type, add
+   REC32. */
+
+#define THEADR          0x80    /* Translator module header record */
+#define COMENT          0x88    /* Comment record */
+#define MODEND          0x8a    /* Module end record */
+#define EXTDEF          0x8c    /* External names definition record */
+#define TYPDEF          0x8e    /* Type definition record */
+#define PUBDEF          0x90    /* Public names definition record */
+#define LINNUM          0x94    /* Line numbers record */
+#define LNAMES          0x96    /* List of names record */
+#define SEGDEF          0x98    /* Segment definition record */
+#define GRPDEF          0x9a    /* Group definition record */
+#define FIXUPP          0x9c    /* Fixup record */
+#define LEDATA          0xa0    /* Logical enumerated data record */
+#define LIDATA          0xa2    /* Logical iterated data record */
+#define COMDEF          0xb0    /* Communal names definition record */
+#define COMDAT          0xc2    /* Common block */
+#define ALIAS           0xc6    /* Alias definition record */
+#define LIBHDR          0xf0    /* Library header */
+#define LIBEND          0xf1    /* Library end */
+
+/* Add this constant (using the | operator) to get the 32-bit variant
+   of a record type.  Some fields will contain 32-bit values instead
+   of 16-bit values. */
+
+#define REC32           0x01
+
+/* BIND_OFFSET is the offset from the beginning of the emxbind patch
+   area to the data fields of that area.  The first BIND_OFFSET bytes
+   of the emxbind patch area are used for storing the emx version
+   number. */
+
+#define BIND_OFFSET         16
+
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+/* The header of an a.out file. */
+
+struct a_out_header
+{
+  word magic;                   /* Magic word, must be 0407 */
+  byte machtype;                /* Machine type */
+  byte flags;                   /* Flags */
+  long text_size;               /* Length of text, in bytes */
+  long data_size;               /* Length of initialized data, in bytes */
+  long bss_size;                /* Length of uninitialized data, in bytes */
+  long sym_size;                /* Length of symbol table, in bytes */
+  long entry;                   /* Start address (entry point) */
+  long trsize;                  /* Length of relocation info for text, bytes */
+  long drsize;                  /* Length of relocation info for data, bytes */
+};
+
+/* This is the layout of a relocation table entry. */
+
+struct reloc
+{
+  dword address;                /* Fixup location */
+  dword symbolnum:24;           /* Symbol number or segment */
+  dword pcrel:1;                /* Self-relative fixup if non-zero */
+  dword length:2;               /* Fixup size (0: 1 byte, 1: 2, 2: 4 bytes) */
+  dword ext:1;                  /* Reference to symbol or segment */
+  dword unused:4;               /* Not used */
+};
+
+/* This is the layout of a symbol table entry. */
+
+struct nlist
+{
+  dword string;                 /* Offset in string table */
+  byte type;                    /* Type of the symbol */
+  byte other;                   /* Other information */
+  word desc;                    /* More information */
+  dword value;                  /* Value (address) */
+};
+
+/* This is the header of a DOS executable file. */
+
+struct exe1_header
+{
+  word magic;                   /* Magic number, "MZ" (0x5a4d) */
+  word last_page;               /* Number of bytes in last page */
+  word pages;                   /* Size of the file in 512-byte pages */
+  word reloc_size;              /* Number of relocation entries */
+  word hdr_size;                /* Size of header in 16-byte paragraphs */
+  word min_alloc;               /* Minimum allocation (paragraphs) */
+  word max_alloc;               /* Maximum allocation (paragraphs) */
+  word ss, sp;                  /* Initial stack pointer */
+  word chksum;                  /* Checksum */
+  word ip, cs;                  /* Entry point */
+  word reloc_ptr;               /* Location of the relocation table */
+  word ovl;                     /* Overlay number */
+};
+
+/* This is an additional header of a DOS executable file.  It contains
+   a pointer to the new EXE header. */
+
+struct exe2_header
+{
+  word res1[16];                /* Reserved */
+  word new_lo;                  /* Low word of the location of the header */
+  word new_hi;                  /* High word of the location of the header */
+};
+
+/* This is the layout of the OS/2 LX header. */
+
+struct os2_header
+{
+  word magic;                   /* Magic number, "LX" (0x584c) */
+  byte byte_order;              /* Byte order */
+  byte word_order;              /* Word order */
+  dword level;                  /* Format level */
+  word cpu;                     /* CPU type */
+  word os;                      /* Operating system type */
+  dword ver;                    /* Module version */
+  dword mod_flags;              /* Module flags */
+  dword mod_pages;              /* Number of pages in the EXE file */
+  dword entry_obj;              /* Object number for EIP */
+  dword entry_eip;              /* Entry point */
+  dword stack_obj;              /* Object number for ESP */
+  dword stack_esp;              /* Stack */
+  dword pagesize;               /* System page size */
+  dword pageshift;              /* Page offset shift */
+  dword fixup_size;             /* Fixup section size */
+  dword fixup_checksum;         /* Fixup section checksum */
+  dword loader_size;            /* Loader section size */
+  dword loader_checksum;        /* Loader section checksum */
+  dword obj_offset;             /* Object table offset */
+  dword obj_count;              /* Number of objects in module */
+  dword pagemap_offset;         /* Object page table offset */
+  dword itermap_offset;         /* Object iterated pages offset */
+  dword rsctab_offset;          /* Resource table offset */
+  dword rsctab_count;           /* Number of resource table entries */
+  dword resname_offset;         /* Resident name table offset */
+  dword entry_offset;           /* Entry table offset */
+  dword moddir_offset;          /* Module directives offset */
+  dword moddir_count;           /* Number of module directives */
+  dword fixpage_offset;         /* Fixup page table offset */
+  dword fixrecord_offset;       /* Fixup record table offset */
+  dword impmod_offset;          /* Import module table offset */
+  dword impmod_count;           /* Number of import module table entries */
+  dword impprocname_offset;     /* Import procedure table offset */
+  dword page_checksum_offset;   /* Per page checksum table offset */
+  dword enum_offset;            /* Data pages offset */
+  dword preload_count;          /* Number of preload pages */
+  dword nonresname_offset;      /* Non-resident name table offset */
+  dword nonresname_size;        /* Non-resident name table size */
+  dword nonresname_checksum;    /* Non-resident name table checksum */
+  dword auto_obj;               /* Auto data segment object number */
+  dword debug_offset;           /* Debug information offset */
+  dword debug_size;             /* Debug information size */
+  dword instance_preload;       /* Number of instance preload pages */
+  dword instance_demand;        /* Number of instance load-on-demand pages */
+  dword heap_size;              /* Heap size */
+  dword stack_size;             /* Stack size */
+  dword reserved[5];            /* Reserved */
+};
+
+/* This is the layout of an object table entry. */
+
+struct object
+{
+  dword virt_size;              /* Virtual size */
+  dword virt_base;              /* Relocation base address */
+  dword attr_flags;             /* Object attributes and flags */
+  dword map_first;              /* Page table index */
+  dword map_count;              /* Number of page table entries */
+  dword reserved;               /* Reserved */
+};
+
+/* This is the layout of the emxbind patch area for DOS.  It is
+   located at the beginning of the loadable image. */
+
+struct dos_bind_header
+{
+  byte hdr[BIND_OFFSET];        /* emx version number */
+  byte bind_flag;               /* Non-zero if this program is bound */
+  byte fill_1;                  /* Padding for proper alignment */
+  word hdr_loc_lo;              /* Location of the a.out header */
+  word hdr_loc_hi;              /* (split into two words due to alignment) */
+  byte options[64];             /* emx options to be used under DOS */
+};
+
+/* This is the layout of the emxbind patch area for OS/2.  It is
+   located at the beginning of the data segment.  This table contains
+   information required for dumping core and for forking. */
+
+struct os2_bind_header
+{
+  dword text_base;              /* Base address of the text segment */
+  dword text_end;               /* End address of the text segment */
+  dword data_base;              /* Base address of initialized data */
+  dword data_end;               /* End address of initialized data */
+  dword bss_base;               /* Base address of uninitialized data */
+  dword bss_end;                /* End address of uninitialized data */
+  dword heap_base;              /* Base address of the heap */
+  dword heap_end;               /* End address of the heap */
+  dword heap_brk;               /* End address of the used heap space */
+  dword heap_off;               /* Location of heap data in the executable */
+  dword os2_dll;                /* Address of the import table for (I1) */
+  dword stack_base;             /* Base address of the stack */
+  dword stack_end;              /* End address of the stack */
+  dword flags;                  /* Flags (DLL) and interface number */
+  dword reserved[2];            /* Not yet used */
+  byte options[64];             /* emx options to be used under OS/2 */
+};
+
+#pragma pack(1)
+
+struct omf_rec
+{
+  byte rec_type;
+  word rec_len;
+};
+
+#pragma pack()
Index: trunk/src/emx/src/lib/Attic/ctype/_tolower.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/_tolower.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/_tolower.c	(revision 18)
@@ -0,0 +1,8 @@
+/* _tolower.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int _tolower (int c)
+{
+  return c + 'a' - 'A';
+}
Index: trunk/src/emx/src/lib/Attic/ctype/_toupper.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/_toupper.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/_toupper.c	(revision 18)
@@ -0,0 +1,8 @@
+/* _toupper.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int _toupper (int c)
+{
+  return c - 'a' + 'A';
+}
Index: trunk/src/emx/src/lib/Attic/ctype/ctype.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/ctype.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/ctype.c	(revision 18)
@@ -0,0 +1,144 @@
+/* ctype.c (emx+gcc) -- Copyright (c) 1990-1993 by Eberhard Mattes */
+
+#include <ctype.h>
+
+unsigned char _ctype[257] =
+          {
+/* -1 */    0,
+/* 00 */    _CNTRL,
+/* 01 */    _CNTRL,
+/* 02 */    _CNTRL,
+/* 03 */    _CNTRL,
+/* 04 */    _CNTRL,
+/* 05 */    _CNTRL,
+/* 06 */    _CNTRL,
+/* 07 */    _CNTRL,
+/* 08 */    _CNTRL,
+/* 09 */    _CNTRL|_SPACE,
+/* 0A */    _CNTRL|_SPACE,
+/* 0B */    _CNTRL|_SPACE,
+/* 0C */    _CNTRL|_SPACE,
+/* 0D */    _CNTRL|_SPACE,
+/* 0E */    _CNTRL,
+/* 0F */    _CNTRL,
+/* 10 */    _CNTRL,
+/* 11 */    _CNTRL,
+/* 12 */    _CNTRL,
+/* 13 */    _CNTRL,
+/* 14 */    _CNTRL,
+/* 15 */    _CNTRL,
+/* 16 */    _CNTRL,
+/* 17 */    _CNTRL,
+/* 18 */    _CNTRL,
+/* 19 */    _CNTRL,
+/* 1A */    _CNTRL,
+/* 1B */    _CNTRL,
+/* 1C */    _CNTRL,
+/* 1D */    _CNTRL,
+/* 1E */    _CNTRL,
+/* 1F */    _CNTRL,
+/* 20 */    _PRINT|_SPACE,
+/* 21 */    _PRINT|_PUNCT,
+/* 22 */    _PRINT|_PUNCT,
+/* 23 */    _PRINT|_PUNCT,
+/* 24 */    _PRINT|_PUNCT,
+/* 25 */    _PRINT|_PUNCT,
+/* 26 */    _PRINT|_PUNCT,
+/* 27 */    _PRINT|_PUNCT,
+/* 28 */    _PRINT|_PUNCT,
+/* 29 */    _PRINT|_PUNCT,
+/* 2A */    _PRINT|_PUNCT,
+/* 2B */    _PRINT|_PUNCT,
+/* 2C */    _PRINT|_PUNCT,
+/* 2D */    _PRINT|_PUNCT,
+/* 2E */    _PRINT|_PUNCT,
+/* 2F */    _PRINT|_PUNCT,
+/* 30 */    _PRINT|_DIGIT|_XDIGIT,
+/* 31 */    _PRINT|_DIGIT|_XDIGIT,
+/* 32 */    _PRINT|_DIGIT|_XDIGIT,
+/* 33 */    _PRINT|_DIGIT|_XDIGIT,
+/* 34 */    _PRINT|_DIGIT|_XDIGIT,
+/* 35 */    _PRINT|_DIGIT|_XDIGIT,
+/* 36 */    _PRINT|_DIGIT|_XDIGIT,
+/* 37 */    _PRINT|_DIGIT|_XDIGIT,
+/* 38 */    _PRINT|_DIGIT|_XDIGIT,
+/* 39 */    _PRINT|_DIGIT|_XDIGIT,
+/* 3A */    _PRINT|_PUNCT,
+/* 3B */    _PRINT|_PUNCT,
+/* 3C */    _PRINT|_PUNCT,
+/* 3D */    _PRINT|_PUNCT,
+/* 3E */    _PRINT|_PUNCT,
+/* 3F */    _PRINT|_PUNCT,
+/* 40 */    _PRINT|_PUNCT,
+/* 41 */    _PRINT|_UPPER|_XDIGIT,
+/* 42 */    _PRINT|_UPPER|_XDIGIT,
+/* 43 */    _PRINT|_UPPER|_XDIGIT,
+/* 44 */    _PRINT|_UPPER|_XDIGIT,
+/* 45 */    _PRINT|_UPPER|_XDIGIT,
+/* 46 */    _PRINT|_UPPER|_XDIGIT,
+/* 47 */    _PRINT|_UPPER,
+/* 48 */    _PRINT|_UPPER,
+/* 49 */    _PRINT|_UPPER,
+/* 4A */    _PRINT|_UPPER,
+/* 4B */    _PRINT|_UPPER,
+/* 4C */    _PRINT|_UPPER,
+/* 4D */    _PRINT|_UPPER,
+/* 4E */    _PRINT|_UPPER,
+/* 4F */    _PRINT|_UPPER,
+/* 50 */    _PRINT|_UPPER,
+/* 51 */    _PRINT|_UPPER,
+/* 52 */    _PRINT|_UPPER,
+/* 53 */    _PRINT|_UPPER,
+/* 54 */    _PRINT|_UPPER,
+/* 55 */    _PRINT|_UPPER,
+/* 56 */    _PRINT|_UPPER,
+/* 57 */    _PRINT|_UPPER,
+/* 58 */    _PRINT|_UPPER,
+/* 59 */    _PRINT|_UPPER,
+/* 5A */    _PRINT|_UPPER,
+/* 5B */    _PRINT|_PUNCT,
+/* 5C */    _PRINT|_PUNCT,
+/* 5D */    _PRINT|_PUNCT,
+/* 5E */    _PRINT|_PUNCT,
+/* 5F */    _PRINT|_PUNCT,
+/* 60 */    _PRINT|_PUNCT,
+/* 61 */    _PRINT|_LOWER|_XDIGIT,
+/* 62 */    _PRINT|_LOWER|_XDIGIT,
+/* 63 */    _PRINT|_LOWER|_XDIGIT,
+/* 64 */    _PRINT|_LOWER|_XDIGIT,
+/* 65 */    _PRINT|_LOWER|_XDIGIT,
+/* 66 */    _PRINT|_LOWER|_XDIGIT,
+/* 67 */    _PRINT|_LOWER,
+/* 68 */    _PRINT|_LOWER,
+/* 69 */    _PRINT|_LOWER,
+/* 6A */    _PRINT|_LOWER,
+/* 6B */    _PRINT|_LOWER,
+/* 6C */    _PRINT|_LOWER,
+/* 6D */    _PRINT|_LOWER,
+/* 6E */    _PRINT|_LOWER,
+/* 6F */    _PRINT|_LOWER,
+/* 70 */    _PRINT|_LOWER,
+/* 71 */    _PRINT|_LOWER,
+/* 72 */    _PRINT|_LOWER,
+/* 73 */    _PRINT|_LOWER,
+/* 74 */    _PRINT|_LOWER,
+/* 75 */    _PRINT|_LOWER,
+/* 76 */    _PRINT|_LOWER,
+/* 77 */    _PRINT|_LOWER,
+/* 78 */    _PRINT|_LOWER,
+/* 79 */    _PRINT|_LOWER,
+/* 7A */    _PRINT|_LOWER,
+/* 7B */    _PRINT|_PUNCT,
+/* 7C */    _PRINT|_PUNCT,
+/* 7D */    _PRINT|_PUNCT,
+/* 7E */    _PRINT|_PUNCT,
+/* 7F */    _CNTRL,
+/* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* A0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* B0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* C0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* D0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* E0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* F0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+          };
Index: trunk/src/emx/src/lib/Attic/ctype/isalnum.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isalnum.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isalnum.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isalnum.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (isalnum) (int c)
+{
+  return isalnum (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/isalpha.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isalpha.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isalpha.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isalpha.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (isalpha) (int c)
+{
+  return isalpha (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/isascii.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isascii.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isascii.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isascii.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int _isascii (int c)
+{
+  return isascii (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/iscntrl.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/iscntrl.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/iscntrl.c	(revision 18)
@@ -0,0 +1,8 @@
+/* iscntrl.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (iscntrl) (int c)
+{
+  return iscntrl (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/isdigit.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isdigit.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isdigit.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isdigit.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (isdigit) (int c)
+{
+  return isdigit (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/isgraph.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isgraph.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isgraph.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isgraph.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (isgraph) (int c)
+{
+  return isgraph (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/islower.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/islower.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/islower.c	(revision 18)
@@ -0,0 +1,8 @@
+/* islower.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (islower) (int c)
+{
+  return islower (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/isprint.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isprint.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isprint.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isprint.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (isprint) (int c)
+{
+  return isprint (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/ispunct.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/ispunct.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/ispunct.c	(revision 18)
@@ -0,0 +1,8 @@
+/* ispunct.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (ispunct) (int c)
+{
+  return ispunct (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/isspace.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isspace.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isspace.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isspace.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (isspace) (int c)
+{
+  return isspace (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/isupper.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isupper.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isupper.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isupper.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (isupper) (int c)
+{
+  return isupper (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/isxdigit.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/isxdigit.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/isxdigit.c	(revision 18)
@@ -0,0 +1,8 @@
+/* isxdigit.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int (isxdigit) (int c)
+{
+  return isxdigit (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/makefile	(revision 18)
@@ -0,0 +1,32 @@
+#
+# /emx/src/lib/ctype/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+MORE_LIBC_CCFLAGS = -D_CTYPE_FUN
+
+local: ;
+
+ctype.o: ctype.c $(I)ctype.h
+isalnum.o: isalnum.c $(I)ctype.h
+isalpha.o: isalpha.c $(I)ctype.h
+isascii.o: isascii.c $(I)ctype.h
+iscntrl.o: iscntrl.c $(I)ctype.h
+isdigit.o: isdigit.c $(I)ctype.h
+isgraph.o: isgraph.c $(I)ctype.h
+islower.o: islower.c $(I)ctype.h
+isprint.o: isprint.c $(I)ctype.h
+ispunct.o: ispunct.c $(I)ctype.h
+isspace.o: isspace.c $(I)ctype.h
+isupper.o: isupper.c $(I)ctype.h
+isxdigit.o: isxdigit.c $(I)ctype.h
+toascii.o: toascii.c $(I)ctype.h
+tolower.o: tolower.c $(I)ctype.h
+toupper.o: toupper.c $(I)ctype.h
+_tolower.o: _tolower.c $(I)ctype.h
+_toupper.o: _toupper.c $(I)ctype.h
+
+$(DSTLIB): ctype.o toascii.o tolower.o toupper.o _tolower.o _toupper.o \
+    isalnum.o isalpha.o iscntrl.o isdigit.o isgraph.o islower.o isprint.o \
+    ispunct.o isspace.o isupper.o isxdigit.o isascii.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/Attic/ctype/toascii.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/toascii.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/toascii.c	(revision 18)
@@ -0,0 +1,8 @@
+/* toascii.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int _toascii (int c)
+{
+  return toascii (c);
+}
Index: trunk/src/emx/src/lib/Attic/ctype/tolower.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/tolower.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/tolower.c	(revision 18)
@@ -0,0 +1,11 @@
+/* tolower.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int tolower (int c)
+{
+  if (c >= 'A' && c <= 'Z')
+    return c + 'a' - 'A';
+  else
+    return c;
+}
Index: trunk/src/emx/src/lib/Attic/ctype/toupper.c
===================================================================
--- trunk/src/emx/src/lib/Attic/ctype/toupper.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/ctype/toupper.c	(revision 18)
@@ -0,0 +1,11 @@
+/* toupper.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <ctype.h>
+
+int toupper (int c)
+{
+  if (c >= 'a' && c <= 'z')
+    return c - 'a' + 'A';
+  else
+    return c;
+}
Index: trunk/src/emx/src/lib/Attic/dllnrt/386/crt3.s
===================================================================
--- trunk/src/emx/src/lib/Attic/dllnrt/386/crt3.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllnrt/386/crt3.s	(revision 18)
@@ -0,0 +1,21 @@
+/ crt3.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+/ This module is used by the following types of executables:
+/
+/ - DLLs without runtime environment
+
+        .globl  __emx_init
+        .globl  __emx_syscall
+        .globl  __cdll_flag
+
+__emx_init:
+        ret     $4
+
+        .align  2, 0x90
+
+__emx_syscall:
+        jmp     __emx_syscall
+
+        .data
+
+__cdll_flag:    .byte 1
Index: trunk/src/emx/src/lib/Attic/dllnrt/dllinit.c
===================================================================
--- trunk/src/emx/src/lib/Attic/dllnrt/dllinit.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllnrt/dllinit.c	(revision 18)
@@ -0,0 +1,19 @@
+/* dllnrt/dllinit.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+void __ctordtorInit (void);
+void __ctordtorTerm (void);
+
+unsigned long _DLL_InitTerm (unsigned long mod_handle, unsigned long flag)
+{
+  switch (flag)
+    {
+    case 0:
+      __ctordtorInit ();
+      return 1;
+    case 1:
+      __ctordtorTerm ();
+      return 1;
+    default:
+      return 0;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/dllnrt/getenv.c
===================================================================
--- trunk/src/emx/src/lib/Attic/dllnrt/getenv.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllnrt/getenv.c	(revision 18)
@@ -0,0 +1,15 @@
+/* sdll/getenv.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#define INCL_DOSMISC
+#include <os2emx.h>
+
+char *getenv (const char *name)
+{
+  PSZ value;
+
+  if (DosScanEnv (name, &value) == 0)
+    return (char *)value;
+  else
+    return NULL;
+}
Index: trunk/src/emx/src/lib/Attic/dllnrt/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/dllnrt/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllnrt/makefile	(revision 18)
@@ -0,0 +1,29 @@
+#
+# /emx/src/lib/dllnrt/makefile
+#
+OMF=1
+DSTLIB=$(L)c_dllnrt.lib
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+.SOURCE.s: ..
+
+.PHONY: dllnrt dstlib
+
+default: dllnrt
+
+dllnrt .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(DSTLIB)
+
+crt3.obj: crt3.s
+dllinit.obj: dllinit.c
+getenv.obj: getenv.c
+
+$(DSTLIB): crt3.obj dllinit.obj getenv.obj
+	emxomfar r $(DSTLIB) *.obj
+
+clean:
+	-del $(CPU)\*.obj
Index: trunk/src/emx/src/lib/Attic/dllrt/386/crt3.s
===================================================================
--- trunk/src/emx/src/lib/Attic/dllrt/386/crt3.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllrt/386/crt3.s	(revision 18)
@@ -0,0 +1,12 @@
+/ crt3.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+/ This module is used by the following types of executables:
+/
+/ - Custom C runtime DLLs
+/ - Stand-alone DLLs
+
+        .globl  __cdll_flag
+
+        .data
+
+__cdll_flag:    .byte 1
Index: trunk/src/emx/src/lib/Attic/dllrt/dllinit.c
===================================================================
--- trunk/src/emx/src/lib/Attic/dllrt/dllinit.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllrt/dllinit.c	(revision 18)
@@ -0,0 +1,24 @@
+/* dllrt/dllinit.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+int _CRT_init (void);
+void _CRT_term (void);
+void __ctordtorInit (void);
+void __ctordtorTerm (void);
+
+unsigned long _DLL_InitTerm (unsigned long mod_handle, unsigned long flag)
+{
+  switch (flag)
+    {
+    case 0:
+      if (_CRT_init () != 0)
+        return 0;
+      __ctordtorInit ();
+      return 1;
+    case 1:
+      __ctordtorTerm ();
+      _CRT_term ();
+      return 1;
+    default:
+      return 0;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/dllrt/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/dllrt/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllrt/makefile	(revision 18)
@@ -0,0 +1,30 @@
+#
+# /emx/src/lib/dllrt/makefile
+#
+LIBBASE=c_dllrt
+.INCLUDE: /emx/src/lib/libc0.mak
+APP=../../app/
+
+local: ;
+
+crt3.o: crt3.s
+dllinit.o: dllinit.c
+
+crt2.o: $(APP)$(CPU)/crt2.s
+	$(GCC) -c -x assembler-with-cpp -I. $(APP)$(CPU)/crt2.s
+
+getenv.o: $(APP)getenv.c $(I)stdlib.h $(I)string.h
+	$(GCC) -c $(APP)getenv.c
+
+putenv.o: $(APP)putenv.c $(I)stdlib.h $(I)string.h
+	$(GCC) -c $(APP)putenv.c
+
+iodata.o: $(APP)iodata.c $(I)emx/io.h $(FCNTL)
+	$(GCC) -c -D_NFILES=256 $(APP)iodata.c
+
+stdio.o: $(APP)stdio.c $(I)emx/io.h $(FCNTL) $(BUILTIN) $(S)fmutex.h \
+		$(S)rmutex.h $(I)emx/startup.h
+	$(GCC) -c -D_NFILES=256 $(APP)stdio.c
+
+$(DSTLIB): crt2.o crt3.o dllinit.o getenv.o iodata.o putenv.o stdio.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/Attic/dllso/386/crt3.s
===================================================================
--- trunk/src/emx/src/lib/Attic/dllso/386/crt3.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllso/386/crt3.s	(revision 18)
@@ -0,0 +1,12 @@
+/ crt3.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+/ This module is used by the following types of executables:
+/
+/ - Custom C runtime DLLs
+/ - Stand-alone DLLs
+
+        .globl  __cdll_flag
+
+        .data
+
+__cdll_flag:    .byte 1
Index: trunk/src/emx/src/lib/Attic/dllso/dllinit.c
===================================================================
--- trunk/src/emx/src/lib/Attic/dllso/dllinit.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllso/dllinit.c	(revision 18)
@@ -0,0 +1,24 @@
+/* dllso/dllinit.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+int _CRT_init (void);
+void _CRT_term (void);
+void __ctordtorInit (void);
+void __ctordtorTerm (void);
+
+unsigned long _DLL_InitTerm (unsigned long mod_handle, unsigned long flag)
+{
+  switch (flag)
+    {
+    case 0:
+      if (_CRT_init () != 0)
+        return 0;
+      __ctordtorInit ();
+      return 1;
+    case 1:
+      __ctordtorTerm ();
+      _CRT_term ();
+      return 1;
+    default:
+      return 0;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/dllso/getenv.c
===================================================================
--- trunk/src/emx/src/lib/Attic/dllso/getenv.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllso/getenv.c	(revision 18)
@@ -0,0 +1,15 @@
+/* dllso/getenv.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#define INCL_DOSMISC
+#include <os2emx.h>
+
+char *getenv (const char *name)
+{
+  PSZ value;
+
+  if (DosScanEnv (name, &value) == 0)
+    return (char *)value;
+  else
+    return NULL;
+}
Index: trunk/src/emx/src/lib/Attic/dllso/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/dllso/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/dllso/makefile	(revision 18)
@@ -0,0 +1,24 @@
+#
+# /emx/src/lib/dllso/makefile
+#
+OMF=1
+LIBBASE=c_dllso
+.INCLUDE: /emx/src/lib/libc0.mak
+APP=../../app/
+
+local: ;
+
+crt3.obj: crt3.s
+dllinit.obj: dllinit.c
+
+iodata.obj: $(APP)iodata.c $(I)emx/io.h $(FCNTL)
+	$(GCC) -c -Zomf -D_NFILES=40 $(APP)iodata.c
+
+stdio.obj: $(APP)stdio.c $(I)emx/io.h $(FCNTL) $(BUILTIN) $(S)fmutex.h \
+		$(S)rmutex.h $(I)emx/startup.h
+	$(GCC) -c -Zomf -D_NFILES=40 $(APP)stdio.c
+
+getenv.obj: getenv.c
+
+$(DSTLIB): crt3.obj dllinit.obj getenv.obj iodata.obj stdio.obj
+	emxomfar r $(DSTLIB) *.obj
Index: trunk/src/emx/src/lib/Attic/gcc/386/cmpdi2.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/cmpdi2.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/cmpdi2.s	(revision 18)
@@ -0,0 +1,34 @@
+/ cmpdi2.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  ___cmpdi2
+
+        .text
+
+        ALIGN
+
+/ int __cmpdi2 (long long x, long long y)
+
+/define ret_addr   0(%esp)
+#define x_lo       4(%esp)
+#define x_hi       8(%esp)
+#define y_lo      12(%esp)
+#define y_hi      16(%esp)
+
+___cmpdi2:
+        PROFILE_NOFRAME
+        xorl    %eax, %eax              /* 0: x < y */
+        movl    x_hi, %edx
+        cmpl    y_hi, %edx
+        jl      9f
+        movb    $2, %al                 /* 2: x > y */
+        jg      9f
+        movl    x_lo, %edx
+        cmpl    y_lo, %edx
+        ja      9f                      /* 2: x > y */
+        movb    $0, %al
+        jb      9f                      /* 0: x < y */
+        movb    $1, %al                 /* 1: x = y */
+        ALIGN
+9:      EPILOGUE(__cmpdi2)
Index: trunk/src/emx/src/lib/Attic/gcc/386/divsi3.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/divsi3.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/divsi3.s	(revision 18)
@@ -0,0 +1,14 @@
+/ divsi3.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  ___divsi3
+
+        ALIGN
+
+___divsi3:
+        PROFILE_NOFRAME
+        movl    1*4(%esp), %eax
+        cltd
+        idivl   2*4(%esp)
+        EPILOGUE(__divsi3)
Index: trunk/src/emx/src/lib/Attic/gcc/386/ehfinit.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/ehfinit.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/ehfinit.s	(revision 18)
@@ -0,0 +1,22 @@
+/ ehfinit.s (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  ___eh_frame_init
+        .globl  ___eh_frame_term
+        .weak   ___eh_frame_init2
+        .weak   ___eh_frame_term2
+
+        .text
+___eh_frame_init:
+        lea     ___eh_frame_init2, %eax
+        testl   %eax, %eax
+        jnz     ___eh_frame_init2
+        ret
+
+        ALIGN
+___eh_frame_term:
+        lea     ___eh_frame_term2, %eax
+        testl   %eax, %eax
+        jnz     ___eh_frame_term2
+        ret
Index: trunk/src/emx/src/lib/Attic/gcc/386/fixdfsi.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/fixdfsi.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/fixdfsi.s	(revision 18)
@@ -0,0 +1,33 @@
+/ fixdfsi.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  ___fixdfsi
+
+        .text
+
+        ALIGN
+
+#define tmp           -8(%ebp)
+#define cw1           -4(%ebp)
+#define cw2           -2(%ebp)
+/define saved_ebp      0(%ebp)
+/define ret_addr       4(%ebp)
+#define x              8(%ebp)
+
+___fixdfsi:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        subl    $8, %esp
+        fstcw   cw1
+        movw    cw1, %ax
+        orw     $0x0c00, %ax            /* truncate towards zero */
+        movw    %ax, cw2
+        fldcw   cw2
+        fldl    x
+        fistpl  tmp
+        fldcw   cw1
+        movl    tmp, %eax
+        leave
+        EPILOGUE(__fixdfsi)
Index: trunk/src/emx/src/lib/Attic/gcc/386/fixudfdi.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/fixudfdi.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/fixudfdi.s	(revision 18)
@@ -0,0 +1,50 @@
+/ fixudfdi.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl ___fixunsdfdi
+
+        .text
+
+	ALIGN
+
+/ ldexp (1.0, 63)
+
+LC0:    .long   0x00000000
+        .long   0x43e00000
+
+#define tmp_lo       -12(%ebp)
+#define tmp_hi        -8(%ebp)
+#define cw1           -4(%ebp)
+#define cw2           -2(%ebp)
+/define saved_ebp      0(%ebp)
+/define ret_addr       4(%ebp)
+#define x              8(%ebp)
+
+___fixunsdfdi:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        subl    $12, %esp
+        fstcw   cw1
+        movw    cw1, %ax
+        orw     $0x0c00, %ax            /* truncate towards zero */
+        movw    %ax, cw2
+        fldcw   cw2
+        fldl    x
+        fcoml   LC0
+        fstsww  %ax
+        sahf
+        jb      1f
+        fsubl   LC0
+        fistpq  tmp_lo
+        addl    $0x80000000, tmp_hi
+        jmp     2f
+
+        ALIGN
+1:      fistpq  tmp_lo
+2:      movl    tmp_lo, %eax
+        movl    tmp_hi, %edx
+        fldcw   cw1
+        leave
+        EPILOGUE(__fixunsdfdi)
Index: trunk/src/emx/src/lib/Attic/gcc/386/fixudfsi.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/fixudfsi.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/fixudfsi.c	(revision 18)
@@ -0,0 +1,12 @@
+/* fixudfsi.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <math.h>
+
+long __fixunsdfsi (double a)
+{
+  if (a < 2147483648.0)
+    return (long)a;
+  else
+    return ((long)(a - 2147483648.0)) + (long)0x80000000;
+}
Index: trunk/src/emx/src/lib/Attic/gcc/386/fixusfdi.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/fixusfdi.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/fixusfdi.s	(revision 18)
@@ -0,0 +1,50 @@
+/ fixusfdi.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl ___fixunssfdi
+
+        .text
+
+	ALIGN
+
+/ ldexp (1.0, 63)
+
+LC2:    .long   0x00000000
+        .long   0x43e00000
+
+#define tmp_lo       -12(%ebp)
+#define tmp_hi        -8(%ebp)
+#define cw1           -4(%ebp)
+#define cw2           -2(%ebp)
+/define saved_ebp      0(%ebp)
+/define ret_addr       4(%ebp)
+#define x              8(%ebp)
+
+___fixunssfdi:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        subl    $12, %esp
+        fstcw   cw1
+        movw    cw1, %ax
+        orw     $0x0c00, %ax            /* truncate towards zero */
+        movw    %ax, cw2
+        fldcw   cw2
+        flds    x
+        fcoml   LC2
+        fstsww  %ax
+        sahf
+        jb      1f
+        fsubl   LC2
+        fistpq  tmp_lo
+        addl    $0x80000000, tmp_hi
+        jmp     2f
+
+        ALIGN
+1:      fistpq  tmp_lo
+2:      movl    tmp_lo, %eax
+        movl    tmp_hi, %edx
+        fldcw   cw1
+        leave
+        EPILOGUE(__fixunssfdi)
Index: trunk/src/emx/src/lib/Attic/gcc/386/fixuxfdi.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/fixuxfdi.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/fixuxfdi.s	(revision 18)
@@ -0,0 +1,50 @@
+/ fixuxfdi.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl ___fixunsxfdi
+
+        .text
+
+	ALIGN
+
+/ ldexp (1.0, 63)
+
+LC1:    .long   0x00000000
+        .long   0x43e00000
+
+#define tmp_lo       -12(%ebp)
+#define tmp_hi        -8(%ebp)
+#define cw1           -4(%ebp)
+#define cw2           -2(%ebp)
+/define saved_ebp      0(%ebp)
+/define ret_addr       4(%ebp)
+#define x              8(%ebp)
+
+___fixunsxfdi:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        subl    $12, %esp
+        fstcw   cw1
+        movw    cw1, %ax
+        orw     $0x0c00, %ax            /* truncate towards zero */
+        movw    %ax, cw2
+        fldcw   cw2
+        fldt    x
+        fcoml   LC1
+        fstsww  %ax
+        sahf
+        jb      1f
+        fsubl   LC1
+        fistpq  tmp_lo
+        addl    $0x80000000, tmp_hi
+        jmp     2f
+
+        ALIGN
+1:      fistpq  tmp_lo
+2:      movl    tmp_lo, %eax
+        movl    tmp_hi, %edx
+        fldcw   cw1
+        leave
+        EPILOGUE(__fixunsxfdi)
Index: trunk/src/emx/src/lib/Attic/gcc/386/muldi3.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/muldi3.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/muldi3.s	(revision 18)
@@ -0,0 +1,40 @@
+/ muldi3.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  ___muldi3
+
+        .text
+
+        ALIGN
+
+/ long long __muldi3 (long long x, long long y)
+
+#define tmp_lo    -8(%ebp)
+#define tmp_hi    -4(%ebp)
+/define saved_ebp  0(%ebp)
+/define ret_addr   4(%ebp)
+#define x_lo       8(%ebp)
+#define x_hi      12(%ebp)
+#define y_lo      16(%ebp)
+#define y_hi      20(%ebp)
+
+___muldi3:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        subl    $8, %esp
+        movl    x_lo, %eax
+        mull    y_lo
+        movl    %eax, tmp_lo
+        movl    %edx, tmp_hi
+        movl    x_lo, %eax
+        mull    y_hi
+        addl    %eax, tmp_hi
+        movl    y_lo, %eax
+        mull    x_hi
+        addl    tmp_hi, %eax
+        movl    %eax, %edx
+        movl    tmp_lo, %eax
+        leave
+        EPILOGUE(__muldi3)
Index: trunk/src/emx/src/lib/Attic/gcc/386/probe.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/probe.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/probe.s	(revision 18)
@@ -0,0 +1,34 @@
+/ probe.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl ___probe
+
+/ void __probe (size_t n)
+
+/ Note: this function does not modify any registers and removes
+/       its argument from the stack.
+/       Do not call this function from a C program!
+
+        .text
+        ALIGN
+___probe:
+        xchgl   1*4(%esp), %ebx         /* save %ebx, put n into %ebx */
+        pushl   %eax                    /* save %eax */
+        movl    %esp, %eax
+        subl    %ebx, %eax              /* low address -> %eax */
+        andl    $-4, %eax               /* round down */
+        movl    %esp, %ebx              /* high address -> %ebx */
+        ALIGN
+1:      subl    $0x1000, %ebx           /* move down */
+        cmpl    %eax, %ebx              /* low address reached? */
+        jb      2f
+        testl   %eax, (%ebx)            /* reference the page */
+        jmp     1b                      /* repeat */
+
+        ALIGN
+2:      testl   %eax, (%eax)            /* reference last page */
+        popl    %eax                    /* restore %eax */
+        movl    1*4(%esp), %ebx         /* restore %ebx */
+        EPILOGUE_NO_RET(__probe)
+        ret     $4                      /* return, remove arg from stack */
Index: trunk/src/emx/src/lib/Attic/gcc/386/ucmpdi2.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/ucmpdi2.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/ucmpdi2.s	(revision 18)
@@ -0,0 +1,34 @@
+/ ucmpdi2.s (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  ___ucmpdi2
+
+        .text
+
+        ALIGN
+
+/ int __ucmpdi2 (unsigned long long x, unsigned long long y)
+
+/define ret_addr   0(%esp)
+#define x_lo       4(%esp)
+#define x_hi       8(%esp)
+#define y_lo      12(%esp)
+#define y_hi      16(%esp)
+
+___ucmpdi2:
+        PROFILE_NOFRAME
+        xorl    %eax, %eax              /* 0: x < y */
+        movl    x_hi, %edx
+        cmpl    y_hi, %edx
+        jb      9f
+        movb    $2, %al                 /* 2: x > y */
+        ja      9f
+        movl    x_lo, %edx
+        cmpl    y_lo, %edx
+        ja      9f                      /* 2: x > y */
+        movb    $0, %al
+        jb      9f                      /* 0: x < y */
+        movb    $1, %al                 /* 1: x = y */
+        ALIGN
+9:      EPILOGUE(__ucmpdi2)
Index: trunk/src/emx/src/lib/Attic/gcc/386/udivsi3.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/udivsi3.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/udivsi3.s	(revision 18)
@@ -0,0 +1,14 @@
+/ udivsi3.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  ___udivsi3
+
+        ALIGN
+
+___udivsi3:
+        PROFILE_NOFRAME
+        movl    1*4(%esp), %eax
+        xorl    %edx, %edx
+        divl    2*4(%esp)
+        EPILOGUE(__udivsi3)
Index: trunk/src/emx/src/lib/Attic/gcc/386/ulldiv.s
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/386/ulldiv.s	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/386/ulldiv.s	(revision 18)
@@ -0,0 +1,112 @@
+/ ulldiv.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+/ There's a better solution: set x':=x, y':=y. Shift right both x' and
+/ y' until x' < 2^32. Then divide x' by y'. The result can be off by -1
+/ due to the approximation. This can be checked by multiplying the
+/ result by y and comparing to x-y. This verification step is not
+/ required for x < 2^32.
+/
+        .globl  __ulldiv
+
+        .text
+
+        ALIGN
+
+/ _ulldiv_t _ulldiv (unsigned long long x, unsigned long long y)
+
+/define saved_ebp     0(%ebp)
+/define ret_addr      4(%ebp)
+#define dst           8(%ebp)
+#define x_lo         12(%ebp)
+#define x_hi         16(%ebp)
+#define y_lo         20(%ebp)
+#define y_hi         24(%ebp)
+
+#define quot_lo       0(%edi)
+#define quot_hi       4(%edi)
+#define rem_lo        8(%edi)
+#define rem_hi       12(%edi)
+
+#define tmp_lo       %ebx
+#define tmp_hi       %esi
+
+__ulldiv:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        movl    dst, %edi
+        cmpl    $0, y_hi
+        jz      Ldiv32
+        movl    x_lo, %eax
+        movl    x_hi, %edx
+        movl    %eax, tmp_lo
+        movl    %edx, tmp_hi
+        xorl    %eax, %eax
+        xorl    %edx, %edx
+        movl    $64, %ecx
+        ALIGN
+1:      shll    $1, tmp_lo                      /* Shift 128 bits */
+        rcll    $1, tmp_hi
+        rcll    $1, %eax
+        rcll    $1, %edx
+        subl    y_lo, %eax                      /* Subtract divisor */
+        sbbl    y_hi, %edx
+        jb      2f                              /* Negative -> */
+        incl    tmp_lo                          /* Set bit 0 of quotient */
+        loop    1b
+        jmp     3f
+
+        ALIGN
+2:      addl    y_lo, %eax                      /* Restore divisor */
+        adcl    y_hi, %edx
+        loop    1b
+3:      movl    %eax, rem_lo
+        movl    %edx, rem_hi
+        movl    tmp_lo, quot_lo
+        movl    tmp_hi, quot_hi
+4:      movl    %edi, %eax
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        leave
+        EPILOGUE(_ulldiv)
+
+/
+/ Divide 64-bit number by 32-bit number
+/
+/ 2^32 a + b         a    2^32 (a mod c) + b
+/ ---------- = 2^32 --- + ------------------   (integer division)
+/      c             c           c
+/
+/
+/ (2^32 a + b) mod c = (2^32 (a mod c) + b) mod c
+/
+/ Proof:
+
+/ Divide by 2^32 c by successive subtraction (k steps) of 2^32 c.
+/
+/ 2^32 a + b            2^32 a + b - 2^32 k c            2^32 (a-kc) + b
+/ ---------- = 2^32 k + --------------------- = 2^32 k + ---------------
+/     c                            c                            c
+/
+/ For k = [a/c], the equality 0 <= a-kc < c is true. Then, a-kc = a mod c.
+/ For this k, the final division cannot overflow.
+/
+/
+        ALIGN
+Ldiv32:
+        movl    x_hi, %eax
+        xorl    %edx, %edx
+        divl    y_lo
+        movl    %eax, quot_hi           /* high-order 32 bits of result */
+        movl    x_lo, %eax              /* remainder of prev. div. in %edx */
+        divl    y_lo
+        movl    %eax, quot_lo
+        movl    %edx, rem_lo
+        movl    $0, rem_hi
+        jmp     4b
Index: trunk/src/emx/src/lib/Attic/gcc/bb.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/bb.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/bb.c	(revision 18)
@@ -0,0 +1,1108 @@
+/* bb.c
+   Extracted from libgcc2.c and modified by Eberhard Mattes, Jun 1998 */
+
+/* Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#ifdef EMX
+#include <stdlib.h>
+#include <strings.h>
+#include <time.h>
+#include <sys/types.h>
+
+#define bzero(a,b)   memset(a,0,b)
+#define popen(a,b)   _popen(a,b)
+#define fstat(a,b)   _fstat(a,b)
+#define pclose(a)    _pclose(a)
+#endif /* EMX */
+
+/* Structure emitted by -a  */
+struct bb
+{
+  long zero_word;
+  const char *filename;
+  long *counts;
+  long ncounts;
+  struct bb *next;
+  const unsigned long *addresses;
+
+  /* Older GCC's did not emit these fields.  */
+  long nwords;
+  const char **functions;
+  const long *line_nums;
+  const char **filenames;
+  char *flags;
+};
+
+#ifdef BLOCK_PROFILER_CODE
+BLOCK_PROFILER_CODE
+#else
+#ifndef inhibit_libc
+
+/* Simple minded basic block profiling output dumper for
+   systems that don't provide tcov support.  At present,
+   it requires atexit and stdio.  */
+
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
+#include <stdio.h>
+char *ctime ();
+
+#ifdef __EMX__
+#include "gbl-ctor.h"
+#else /* not __EMX__ */
+#include "gbl-ctors.h"
+#endif /* not __EMX__ */
+#include "gcov-io.h"
+
+static struct bb *bb_head;
+
+/* Return the number of digits needed to print a value */
+/* __inline__ */ static int num_digits (long value, int base)
+{
+  int minus = (value < 0 && base != 16);
+  unsigned long v = (minus) ? -value : value;
+  int ret = minus;
+
+  do
+    {
+      v /= base;
+      ret++;
+    }
+  while (v);
+
+  return ret;
+}
+
+void
+__bb_exit_func (void)
+{
+  FILE *da_file, *file;
+  long time_value;
+  int i;
+
+  if (bb_head == 0)
+    return;
+
+  i = strlen (bb_head->filename) - 3;
+
+  if (!strcmp (bb_head->filename+i, ".da"))
+    {
+      /* Must be -fprofile-arcs not -a.
+	 Dump data in a form that gcov expects.  */
+
+      struct bb *ptr;
+
+      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+	{
+	  /* If the file exists, and the number of counts in it is the same,
+	     then merge them in.  */
+	     
+#ifdef EMX
+	  if ((da_file = fopen (ptr->filename, "rb")) != 0)
+#else /* not EMX */
+	  if ((da_file = fopen (ptr->filename, "r")) != 0)
+#endif /* not EMX */
+	    {
+	      long n_counts = 0;
+	      unsigned char tmp;
+	      int i;
+	      int ret = 0;
+
+	      
+	      if (__read_long (&n_counts, da_file, 8) != 0)
+		{
+		  fprintf (stderr, "arc profiling: Can't read output file %s.\n",
+			   ptr->filename);
+		  continue;
+		}
+
+	      if (n_counts == ptr->ncounts)
+		{
+		  int i;
+
+		  for (i = 0; i < n_counts; i++)
+		    {
+		      long v = 0;
+		      unsigned char tmp;
+		      int j;
+		      int ret = 0;
+
+		      if (__read_long (&v, da_file, 8) != 0)
+			{
+			  fprintf (stderr, "arc profiling: Can't read output file %s.\n",
+				   ptr->filename);
+			  break;
+			}
+		      ptr->counts[i] += v;
+		    }
+		}
+
+	      if (fclose (da_file) == EOF)
+		fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+			 ptr->filename);
+	    }
+#ifdef EMX
+	  if ((da_file = fopen (ptr->filename, "wb")) == 0)
+#else /* not EMX */
+	  if ((da_file = fopen (ptr->filename, "w")) == 0)
+#endif /* not EMX */
+	    {
+	      fprintf (stderr, "arc profiling: Can't open output file %s.\n",
+		       ptr->filename);
+	      continue;
+	    }
+
+	  /* ??? Should first write a header to the file.  Preferably, a 4 byte
+	     magic number, 4 bytes containing the time the program was
+	     compiled, 4 bytes containing the last modification time of the
+	     source file, and 4 bytes indicating the compiler options used.
+
+	     That way we can easily verify that the proper source/executable/
+	     data file combination is being used from gcov.  */
+
+	  if (__write_long (ptr->ncounts, da_file, 8) != 0)
+	    {
+	      
+	      fprintf (stderr, "arc profiling: Error writing output file %s.\n",
+		       ptr->filename);
+	    }
+	  else
+	    {
+	      int j;
+	      long *count_ptr = ptr->counts;
+	      int ret = 0;
+	      for (j = ptr->ncounts; j > 0; j--)
+		{
+		  if (__write_long (*count_ptr, da_file, 8) != 0)
+		    {
+		      ret=1;
+		      break;
+		    }
+		  count_ptr++;
+		}
+	      if (ret)
+		fprintf (stderr, "arc profiling: Error writing output file %s.\n",
+			 ptr->filename);
+	    }
+	  
+	  if (fclose (da_file) == EOF)
+	    fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+		     ptr->filename);
+	}
+
+      return;
+    }
+
+  /* Must be basic block profiling.  Emit a human readable output file.  */
+
+  file = fopen ("bb.out", "a");
+
+  if (!file)
+    perror ("bb.out");
+
+  else
+    {
+      struct bb *ptr;
+
+      /* This is somewhat type incorrect, but it avoids worrying about
+	 exactly where time.h is included from.  It should be ok unless
+	 a void * differs from other pointer formats, or if sizeof (long)
+	 is < sizeof (time_t).  It would be nice if we could assume the
+	 use of rationale standards here.  */
+
+      time ((void *) &time_value);
+      fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
+
+      /* We check the length field explicitly in order to allow compatibility
+	 with older GCC's which did not provide it.  */
+
+      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+	{
+	  int i;
+	  int func_p	= (ptr->nwords >= sizeof (struct bb)
+			   && ptr->nwords <= 1000
+			   && ptr->functions);
+	  int line_p	= (func_p && ptr->line_nums);
+	  int file_p	= (func_p && ptr->filenames);
+	  int addr_p	= (ptr->addresses != 0);
+	  long ncounts	= ptr->ncounts;
+	  long cnt_max  = 0;
+	  long line_max = 0;
+	  long addr_max = 0;
+	  int file_len	= 0;
+	  int func_len	= 0;
+	  int blk_len	= num_digits (ncounts, 10);
+	  int cnt_len;
+	  int line_len;
+	  int addr_len;
+
+	  fprintf (file, "File %s, %ld basic blocks \n\n",
+		   ptr->filename, ncounts);
+
+	  /* Get max values for each field.  */
+	  for (i = 0; i < ncounts; i++)
+	    {
+	      const char *p;
+	      int len;
+
+	      if (cnt_max < ptr->counts[i])
+		cnt_max = ptr->counts[i];
+
+	      if (addr_p && addr_max < ptr->addresses[i])
+		addr_max = ptr->addresses[i];
+
+	      if (line_p && line_max < ptr->line_nums[i])
+		line_max = ptr->line_nums[i];
+
+	      if (func_p)
+		{
+		  p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
+		  len = strlen (p);
+		  if (func_len < len)
+		    func_len = len;
+		}
+
+	      if (file_p)
+		{
+		  p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
+		  len = strlen (p);
+		  if (file_len < len)
+		    file_len = len;
+		}
+	    }
+
+	  addr_len = num_digits (addr_max, 16);
+	  cnt_len  = num_digits (cnt_max, 10);
+	  line_len = num_digits (line_max, 10);
+
+	  /* Now print out the basic block information.  */
+	  for (i = 0; i < ncounts; i++)
+	    {
+	      fprintf (file,
+		       "    Block #%*d: executed %*ld time(s)",
+		       blk_len, i+1,
+		       cnt_len, ptr->counts[i]);
+
+	      if (addr_p)
+		fprintf (file, " address= 0x%.*lx", addr_len,
+			 ptr->addresses[i]);
+
+	      if (func_p)
+		fprintf (file, " function= %-*s", func_len,
+			 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
+
+	      if (line_p)
+		fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
+
+	      if (file_p)
+		fprintf (file, " file= %s",
+			 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
+
+	      fprintf (file, "\n");
+	    }
+
+	  fprintf (file, "\n");
+	  fflush (file);
+	}
+
+      fprintf (file, "\n\n");
+      fclose (file);
+    }
+}
+
+void
+__bb_init_func (struct bb *blocks)
+{
+  /* User is supposed to check whether the first word is non-0,
+     but just in case....  */
+
+  if (blocks->zero_word)
+    return;
+
+#ifdef ON_EXIT
+  /* Initialize destructor.  */
+  if (!bb_head)
+    ON_EXIT (__bb_exit_func, 0);
+#endif
+
+  /* Set up linked list.  */
+  blocks->zero_word = 1;
+  blocks->next = bb_head;
+  bb_head = blocks;
+}
+
+#ifndef MACHINE_STATE_SAVE
+#define MACHINE_STATE_SAVE(ID)
+#endif
+#ifndef MACHINE_STATE_RESTORE
+#define MACHINE_STATE_RESTORE(ID)
+#endif
+
+#include <string.h>
+
+/* Number of buckets in hashtable of basic block addresses.  */
+
+#define BB_BUCKETS 311
+
+/* Maximum length of string in file bb.in.  */
+
+#define BBINBUFSIZE 500
+
+/* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
+   "BBINBUFSIZE" but want to avoid trouble with preprocessors.  */
+
+#define BBINBUFSIZESTR "499"
+
+struct bb_edge
+{
+  struct bb_edge *next;
+  unsigned long src_addr;
+  unsigned long dst_addr;
+  unsigned long count;
+};
+
+enum bb_func_mode
+{
+  TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
+};
+
+struct bb_func
+{
+  struct bb_func *next;
+  char *funcname;
+  char *filename;
+  enum bb_func_mode mode;
+};
+
+/* This is the connection to the outside world.
+   The BLOCK_PROFILER macro must set __bb.blocks
+   and __bb.blockno.  */
+
+struct {
+  unsigned long blockno;
+  struct bb *blocks;
+} __bb;
+
+/* Vars to store addrs of source and destination basic blocks 
+   of a jump.  */
+
+static unsigned long bb_src = 0;
+static unsigned long bb_dst = 0;
+
+static FILE *bb_tracefile = (FILE *) 0;
+static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
+static struct bb_func *bb_func_head = (struct bb_func *) 0;
+static unsigned long bb_callcount = 0;
+static int bb_mode = 0;
+
+static unsigned long *bb_stack = (unsigned long *) 0;
+static size_t bb_stacksize = 0;
+
+static int reported = 0;
+
+/* Trace modes:
+Always             :   Print execution frequencies of basic blocks
+                       to file bb.out.
+bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
+bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
+bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
+bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
+*/
+
+#ifdef HAVE_POPEN
+
+/*#include <sys/types.h>*/
+#include <sys/stat.h>
+/*#include <malloc.h>*/
+
+/* Commands executed by gopen.  */
+
+#define GOPENDECOMPRESS "gzip -cd "
+#define GOPENCOMPRESS "gzip -c >"
+
+/* Like fopen but pipes through gzip.  mode may only be "r" or "w".
+   If it does not compile, simply replace gopen by fopen and delete
+   '.gz' from any first parameter to gopen.  */
+
+static FILE *
+gopen (char *fn, char *mode)
+{
+  int use_gzip;
+  char *p;
+
+#ifdef EMX
+  if (mode[1] && (mode[1] != 'b' || mode[2]))
+    return (FILE *) 0;
+#else /* not EMX */
+  if (mode[1])
+    return (FILE *) 0;
+#endif /* not EMX */
+
+  if (mode[0] != 'r' && mode[0] != 'w') 
+    return (FILE *) 0;
+
+  p = fn + strlen (fn)-1;
+  use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
+	      || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
+
+  if (use_gzip)
+    {
+      if (mode[0]=='r')
+        {
+          FILE *f;
+          char *s = (char *) malloc (sizeof (char) * strlen (fn)
+				     + sizeof (GOPENDECOMPRESS));
+          strcpy (s, GOPENDECOMPRESS);
+          strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
+          f = popen (s, mode);
+          free (s);
+          return f;
+        }
+
+      else
+        {
+          FILE *f;
+          char *s = (char *) malloc (sizeof (char) * strlen (fn)
+				     + sizeof (GOPENCOMPRESS));
+          strcpy (s, GOPENCOMPRESS);
+          strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
+          if (!(f = popen (s, mode)))
+            f = fopen (s, mode);
+          free (s);
+          return f;
+        }
+    }
+
+  else
+    return fopen (fn, mode);
+}
+
+static int
+gclose (FILE *f)
+{
+  struct stat buf;
+
+  if (f != 0)
+    {
+      if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
+        return pclose (f);
+
+      return fclose (f);
+    }
+  return 0;
+}
+
+#endif /* HAVE_POPEN */
+
+/* Called once per program.  */
+
+static void
+__bb_exit_trace_func ()
+{
+  FILE *file = fopen ("bb.out", "a");
+  struct bb_func *f;
+  struct bb_edge *e;
+  struct bb *b;
+        
+  if (!file)
+    perror ("bb.out");
+
+  if (bb_mode & 1)
+    {
+      if (!bb_tracefile)
+        perror ("bbtrace");
+      else
+#ifdef HAVE_POPEN
+#ifdef EMX
+        {
+          if (_osmode == DOS_MODE)
+            fclose (bb_tracefile);
+          else
+            gclose (bb_tracefile);
+        }
+#else /* not EMX */
+        gclose (bb_tracefile);
+#endif /* not EMX */
+#else
+        fclose (bb_tracefile);
+#endif /* HAVE_POPEN */
+    }
+
+  /* Check functions in `bb.in'.  */
+
+  if (file)
+    {
+      long time_value;
+      const struct bb_func *p;
+      int printed_something = 0;
+      struct bb *ptr;
+      long blk;
+
+      /* This is somewhat type incorrect.  */
+      time ((void *) &time_value);
+
+      for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
+        {
+          for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+            {
+              if (!ptr->filename || p->filename != (char *) 0 && strcmp (p->filename, ptr->filename))
+                continue;
+              for (blk = 0; blk < ptr->ncounts; blk++)
+                {
+                  if (!strcmp (p->funcname, ptr->functions[blk]))
+                    goto found;
+                }
+            }
+  
+          if (!printed_something)
+            {
+              fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
+              printed_something = 1;
+            }
+
+          fprintf (file, "\tFunction %s", p->funcname);
+          if (p->filename)
+              fprintf (file, " of file %s", p->filename);
+          fprintf (file, "\n" );
+  
+found:        ;
+        }
+
+      if (printed_something)
+       fprintf (file, "\n");
+
+    }
+
+  if (bb_mode & 2)
+    {
+      if (!bb_hashbuckets)
+        {
+          if (!reported)
+            {
+              fprintf (stderr, "Profiler: out of memory\n");
+              reported = 1;
+            }
+          return;
+        }
+    
+      else if (file)
+        {
+          long time_value;
+          int i;
+          unsigned long addr_max = 0;
+          unsigned long cnt_max  = 0;
+          int cnt_len;
+          int addr_len;
+    
+          /* This is somewhat type incorrect, but it avoids worrying about
+             exactly where time.h is included from.  It should be ok unless
+             a void * differs from other pointer formats, or if sizeof (long)
+             is < sizeof (time_t).  It would be nice if we could assume the
+             use of rationale standards here.  */
+    
+          time ((void *) &time_value);
+          fprintf (file, "Basic block jump tracing");
+
+          switch (bb_mode & 12)
+            {
+              case 0:
+                fprintf (file, " (with call)");
+              break;
+
+              case 4:
+		/* Print nothing.  */
+              break;
+
+              case 8:
+                fprintf (file, " (with call & ret)");
+              break;
+
+              case 12:
+                fprintf (file, " (with ret)");
+              break;
+            }
+
+          fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
+    
+          for (i = 0; i < BB_BUCKETS; i++)
+            {
+               struct bb_edge *bucket = bb_hashbuckets[i];
+               for ( ; bucket; bucket = bucket->next )
+                 {
+                   if (addr_max < bucket->src_addr) 
+                     addr_max = bucket->src_addr;
+                   if (addr_max < bucket->dst_addr) 
+                     addr_max = bucket->dst_addr;
+                   if (cnt_max < bucket->count) 
+                     cnt_max = bucket->count;
+                 }
+            }
+          addr_len = num_digits (addr_max, 16);
+          cnt_len  = num_digits (cnt_max, 10);
+    
+          for ( i = 0; i < BB_BUCKETS; i++)
+            {
+               struct bb_edge *bucket = bb_hashbuckets[i];
+               for ( ; bucket; bucket = bucket->next )
+                 {
+                   fprintf (file, "Jump from block 0x%.*lx to "
+                                  "block 0x%.*lx executed %*d time(s)\n", 
+                            addr_len, bucket->src_addr, 
+                            addr_len, bucket->dst_addr, 
+                            cnt_len, bucket->count);
+                 }
+            }
+  
+          fprintf (file, "\n");
+
+        }
+    }
+
+   if (file)
+     fclose (file);
+
+   /* Free allocated memory.  */
+
+   f = bb_func_head;
+   while (f)
+     {
+       struct bb_func *old = f;
+
+       f = f->next;
+       if (old->funcname) free (old->funcname);
+       if (old->filename) free (old->filename);
+       free (old);
+     }
+
+   if (bb_stack)
+     free (bb_stack);
+
+   if (bb_hashbuckets)
+     {
+       int i;
+
+       for (i = 0; i < BB_BUCKETS; i++)
+         {
+           struct bb_edge *old, *bucket = bb_hashbuckets[i];
+
+           while (bucket)
+             {
+               old = bucket;
+               bucket = bucket->next;
+               free (old);
+             }
+         }
+       free (bb_hashbuckets);
+     }
+
+   for (b = bb_head; b; b = b->next)
+     if (b->flags) free (b->flags);
+}
+
+/* Called once per program.  */
+
+static void
+__bb_init_prg ()
+{
+
+  FILE *file;
+  char buf[BBINBUFSIZE];
+  const char *p;
+  const char *pos;
+  enum bb_func_mode m;
+
+#ifdef ON_EXIT
+  /* Initialize destructor.  */
+  ON_EXIT (__bb_exit_func, 0);
+#endif
+
+  if (!(file = fopen ("bb.in", "r")))
+    return;
+
+  while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
+    {
+      p = buf;
+      if (*p == '-') 
+        { 
+          m = TRACE_OFF; 
+          p++; 
+        }
+      else 
+        { 
+          m = TRACE_ON; 
+        }
+      if (!strcmp (p, "__bb_trace__"))
+        bb_mode |= 1;
+      else if (!strcmp (p, "__bb_jumps__"))
+        bb_mode |= 2;
+      else if (!strcmp (p, "__bb_hidecall__"))
+        bb_mode |= 4;
+      else if (!strcmp (p, "__bb_showret__"))
+        bb_mode |= 8;
+      else 
+        {
+          struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
+          if (f)
+            {
+              unsigned long l;
+              f->next = bb_func_head;
+              if (pos = strchr (p, ':'))
+                {
+                  if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
+                    continue;
+                  strcpy (f->funcname, pos+1);
+                  l = pos-p;
+                  if ((f->filename = (char *) malloc (l+1)))
+                    {
+                      strncpy (f->filename, p, l);
+                      f->filename[l] = '\0';
+                    }
+                  else
+                    f->filename = (char *) 0;
+                }
+              else
+                {
+                  if (!(f->funcname = (char *) malloc (strlen (p)+1)))
+                    continue;
+                  strcpy (f->funcname, p);
+                  f->filename = (char *) 0;
+                }
+              f->mode = m;
+              bb_func_head = f;
+	    }
+         }
+    }
+  fclose (file);
+
+#ifdef HAVE_POPEN 
+
+  if (bb_mode & 1)
+#ifdef EMX
+    {
+      if (_osmode == DOS_MODE)
+        bb_tracefile = fopen ("bbtrace", "wb");
+      else
+        bb_tracefile = gopen ("bbtrace.gz", "wb");
+    }
+#else /* not EMX */
+      bb_tracefile = gopen ("bbtrace.gz", "w");
+#endif /* not EMX */
+
+#else
+
+  if (bb_mode & 1)
+#ifdef EMX
+      bb_tracefile = fopen ("bbtrace", "wb");
+#else /* not EMX */
+      bb_tracefile = fopen ("bbtrace", "w");
+#endif /* not EMX */
+
+#endif /* HAVE_POPEN */
+
+  if (bb_mode & 2)
+    {
+      bb_hashbuckets = (struct bb_edge **) 
+                   malloc (BB_BUCKETS * sizeof (struct bb_edge *));
+      if (bb_hashbuckets)
+        bzero ((char *) bb_hashbuckets, BB_BUCKETS);
+    }
+
+  if (bb_mode & 12)
+    {
+      bb_stacksize = 10;
+      bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
+    }
+
+#ifdef ON_EXIT
+      /* Initialize destructor.  */
+      ON_EXIT (__bb_exit_trace_func, 0);
+#endif
+
+}
+
+/* Called upon entering a basic block.  */
+
+void
+__bb_trace_func ()
+{
+  struct bb_edge *bucket;
+
+  MACHINE_STATE_SAVE("1")
+
+  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
+    goto skip;
+
+  bb_dst = __bb.blocks->addresses[__bb.blockno];
+  __bb.blocks->counts[__bb.blockno]++;
+
+  if (bb_tracefile)
+    {
+      fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
+    }
+
+  if (bb_hashbuckets)
+    {
+      struct bb_edge **startbucket, **oldnext;
+
+      oldnext = startbucket
+	= & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
+      bucket = *startbucket;
+
+      for (bucket = *startbucket; bucket; 
+           oldnext = &(bucket->next), bucket = *oldnext)
+        {
+          if (bucket->src_addr == bb_src
+	      && bucket->dst_addr == bb_dst)
+            {
+              bucket->count++;
+              *oldnext = bucket->next;
+              bucket->next = *startbucket;
+              *startbucket = bucket;
+              goto ret;
+            }
+        }
+
+      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
+
+      if (!bucket)
+        {
+          if (!reported)
+            {
+              fprintf (stderr, "Profiler: out of memory\n");
+              reported = 1;
+            }
+        }
+
+      else
+        {
+          bucket->src_addr = bb_src;
+          bucket->dst_addr = bb_dst;
+          bucket->next = *startbucket;
+          *startbucket = bucket;
+          bucket->count = 1;
+        }
+    }
+
+ret:
+  bb_src = bb_dst;
+
+skip:
+  ;
+
+  MACHINE_STATE_RESTORE("1")
+
+}
+
+/* Called when returning from a function and `__bb_showret__' is set.  */
+
+static void
+__bb_trace_func_ret ()
+{
+  struct bb_edge *bucket;
+
+  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
+    goto skip;
+
+  if (bb_hashbuckets)
+    {
+      struct bb_edge **startbucket, **oldnext;
+
+      oldnext = startbucket
+	= & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
+      bucket = *startbucket;
+
+      for (bucket = *startbucket; bucket; 
+           oldnext = &(bucket->next), bucket = *oldnext)
+        {
+          if (bucket->src_addr == bb_dst
+	       && bucket->dst_addr == bb_src)
+            {
+              bucket->count++;
+              *oldnext = bucket->next;
+              bucket->next = *startbucket;
+              *startbucket = bucket;
+              goto ret;
+            }
+        }
+
+      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
+
+      if (!bucket)
+        {
+          if (!reported)
+            {
+              fprintf (stderr, "Profiler: out of memory\n");
+              reported = 1;
+            }
+        }
+
+      else
+        {
+          bucket->src_addr = bb_dst;
+          bucket->dst_addr = bb_src;
+          bucket->next = *startbucket;
+          *startbucket = bucket;
+          bucket->count = 1;
+        }
+    }
+
+ret:
+  bb_dst = bb_src;
+
+skip:
+  ;
+
+}
+
+/* Called upon entering the first function of a file.  */
+
+static void
+__bb_init_file (struct bb *blocks)
+{
+
+  const struct bb_func *p;
+  long blk, ncounts = blocks->ncounts;
+  const char **functions = blocks->functions;
+
+  /* Set up linked list.  */
+  blocks->zero_word = 1;
+  blocks->next = bb_head;
+  bb_head = blocks;
+
+  blocks->flags = 0;
+  if (!bb_func_head
+      || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
+    return;
+
+  for (blk = 0; blk < ncounts; blk++)
+    blocks->flags[blk] = 0;
+
+  for (blk = 0; blk < ncounts; blk++)
+    {
+      for (p = bb_func_head; p; p = p->next)
+        {
+          if (!strcmp (p->funcname, functions[blk])
+	      && (!p->filename || !strcmp (p->filename, blocks->filename)))
+            {
+              blocks->flags[blk] |= p->mode;
+            }
+        }
+    }
+
+}
+
+/* Called when exiting from a function.  */
+
+void
+__bb_trace_ret ()
+{
+
+  MACHINE_STATE_SAVE("2")
+
+  if (bb_callcount)
+    {
+      if ((bb_mode & 12) && bb_stacksize > bb_callcount)
+        {
+          bb_src = bb_stack[bb_callcount];
+          if (bb_mode & 8)
+            __bb_trace_func_ret ();
+        }
+
+      bb_callcount -= 1;
+    }
+
+  MACHINE_STATE_RESTORE("2")
+
+}
+
+/* Called when entering a function.  */
+
+void
+__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
+{
+  static int trace_init = 0;
+
+  MACHINE_STATE_SAVE("3")
+
+  if (!blocks->zero_word)
+    { 
+      if (!trace_init)
+        { 
+          trace_init = 1;
+          __bb_init_prg ();
+        }
+      __bb_init_file (blocks);
+    }
+
+  if (bb_callcount)
+    {
+
+      bb_callcount += 1;
+
+      if (bb_mode & 12)
+        {
+          if (bb_callcount >= bb_stacksize)
+            {
+              size_t newsize = bb_callcount + 100;
+
+              bb_stack = (unsigned long *) realloc (bb_stack, newsize);
+              if (! bb_stack)
+                {
+                  if (!reported)
+                    {
+                      fprintf (stderr, "Profiler: out of memory\n");
+                      reported = 1;
+                    }
+                  bb_stacksize = 0;
+                  goto stack_overflow;
+                }
+	      bb_stacksize = newsize;
+            }
+          bb_stack[bb_callcount] = bb_src;
+
+          if (bb_mode & 4)
+            bb_src = 0;
+
+        }
+
+stack_overflow:;
+
+    }
+
+  else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
+    {
+      bb_callcount = 1;
+      bb_src = 0;
+
+      if (bb_stack)
+          bb_stack[bb_callcount] = bb_src;
+    }
+
+  MACHINE_STATE_RESTORE("3")
+}
+
+#endif /* not inhibit_libc */
+#endif /* not BLOCK_PROFILER_CODE */
Index: trunk/src/emx/src/lib/Attic/gcc/bi_del.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/bi_del.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/bi_del.c	(revision 18)
@@ -0,0 +1,49 @@
+/* bi_del.c
+   Extracted from libgcc2.c and modified by Eberhard Mattes, Jul 1995 */
+
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+#include <stdlib.h>
+
+/* operator delete (void *), described in 17.3.3.3.  This function is used
+   by C++ programs to return to the free store a block of memory allocated
+   as a single object. */
+
+#ifdef WEAK_ALIAS
+void __builtin_delete (void *ptr)
+     __attribute__ ((weak, alias ("___builtin_delete")));
+void
+___builtin_delete (void *ptr)
+#else
+void
+__builtin_delete (void *ptr)
+#endif
+{
+  if (ptr)
+    free (ptr);
+}
Index: trunk/src/emx/src/lib/Attic/gcc/bi_new.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/bi_new.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/bi_new.c	(revision 18)
@@ -0,0 +1,64 @@
+/* bi_new.c
+   Extracted from libgcc2.c and modified by Eberhard Mattes, Jul 1995 */
+
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+#include <stdlib.h>
+
+/* operator new (size_t), described in 17.3.3.5.  This function is used by
+   C++ programs to allocate a block of memory to hold a single object. */
+
+typedef void (*vfp)(void);
+extern vfp __new_handler;
+extern void __default_new_handler (void);
+
+#ifdef WEAK_ALIAS
+void * __builtin_new (size_t sz)
+     __attribute__ ((weak, alias ("___builtin_new")));
+void *
+___builtin_new (size_t sz)
+#else
+void *
+__builtin_new (size_t sz)
+#endif
+{
+  void *p;
+  vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
+
+  /* malloc (0) is unpredictable; avoid it.  */
+  if (sz == 0)
+    sz = 1;
+  p = (void *) malloc (sz);
+  while (p == 0)
+    {
+      (*handler) ();
+      p = (void *) malloc (sz);
+    }
+  
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/gcc/bi_vdel.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/bi_vdel.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/bi_vdel.c	(revision 18)
@@ -0,0 +1,48 @@
+/* bi_vdel.c
+   Extracted from libgcc2.c and modified by Eberhard Mattes, Jul 1995 */
+
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+/* operator delete [] (void *), described in 17.3.3.4.  This function is
+   used by C++ programs to return to the free store a block of memory
+   allocated as an array. */
+
+extern void __builtin_delete (void *);
+
+#ifdef WEAK_ALIAS
+void __builtin_vec_delete (void *ptr)
+     __attribute__ ((weak, alias ("___builtin_vec_delete")));
+void
+___builtin_vec_delete (void *ptr)
+#else
+void
+__builtin_vec_delete (void *ptr)
+#endif
+{
+  __builtin_delete (ptr);
+}
Index: trunk/src/emx/src/lib/Attic/gcc/bi_vnew.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/bi_vnew.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/bi_vnew.c	(revision 18)
@@ -0,0 +1,49 @@
+/* bi_vnew.c
+   Extracted from libgcc2.c and modified by Eberhard Mattes, Jul 1995 */
+
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+#include <stdlib.h>
+
+/* void * operator new [] (size_t), described in 17.3.3.6.  This function
+   is used by C++ programs to allocate a block of memory for an array.  */
+
+extern void * __builtin_new (size_t);
+
+#ifdef WEAK_ALIAS
+void * __builtin_vec_new (size_t sz)
+     __attribute__ ((weak, alias ("___builtin_vec_new")));
+void *
+___builtin_vec_new (size_t sz)
+#else
+void *
+__builtin_vec_new (size_t sz)
+#endif
+{
+  return __builtin_new (sz);
+}
Index: trunk/src/emx/src/lib/Attic/gcc/bounds.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/bounds.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/bounds.c	(revision 18)
@@ -0,0 +1,3 @@
+/* bounds.c (emx+gcc) */
+
+int __bounds_checking_on = 0;
Index: trunk/src/emx/src/lib/Attic/gcc/divdi3.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/divdi3.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/divdi3.c	(revision 18)
@@ -0,0 +1,8 @@
+/* divdi3.c (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+long long __divdi3 (long long x, long long y)
+{
+  return _lldiv (x, y).quot;
+}
Index: trunk/src/emx/src/lib/Attic/gcc/dummy.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/dummy.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/dummy.c	(revision 18)
@@ -0,0 +1,5 @@
+/* dummy.c */
+
+void __dummy (void)
+{
+}
Index: trunk/src/emx/src/lib/Attic/gcc/eh.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/eh.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/eh.c	(revision 18)
@@ -0,0 +1,725 @@
+/* eh.c
+   Extracted from libgcc2.c and modified by Eberhard Mattes, Jun 1998 */
+
+/* Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#include "tconfig.h"
+#include "machmode.h"
+#include "defaults.h"
+#include <stddef.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+/* Shared exception handling support routines.  */
+
+/* Language-specific information about the active exception(s).  If there
+   are no active exceptions, it is set to 0.  */
+void *__eh_info;
+
+void
+__default_terminate ()
+{
+  abort ();
+}
+
+void (*__terminate_func)() = __default_terminate;
+
+void
+__terminate ()
+{
+  (*__terminate_func)();
+}
+
+void *
+__throw_type_match (void *catch_type, void *throw_type, void *obj)
+{
+#if 0
+ printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
+	 catch_type, throw_type);
+#endif
+ if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
+   return obj;
+ return 0;
+}
+
+void
+__empty ()
+{
+}
+
+
+/* Support routines for setjmp/longjmp exception handling.  */
+
+/* Calls to __sjthrow are generated by the compiler when an exception
+   is raised when using the setjmp/longjmp exception handling codegen
+   method.  */
+
+extern void longjmp (void *, int);
+
+static void *top_elt[2];
+void **__dynamic_handler_chain = top_elt;
+
+/* Routine to get the head of the current thread's dynamic handler chain
+   use for exception handling.
+
+   TODO: make thread safe.  */
+
+void ***
+__get_dynamic_handler_chain ()
+{
+  return &__dynamic_handler_chain;
+}
+
+/* This is used to throw an exception when the setjmp/longjmp codegen
+   method is used for exception handling.
+
+   We call __terminate if there are no handlers left (we know this
+   when the dynamic handler chain is top_elt).  Otherwise we run the
+   cleanup actions off the dynamic cleanup stack, and pop the top of
+   the dynamic handler chain, and use longjmp to transfer back to the
+   associated handler.  */
+
+void
+__sjthrow ()
+{
+  void ***dhc = __get_dynamic_handler_chain ();
+  void *jmpbuf;
+  void (*func)(void *, int);
+  void *arg;
+  void ***cleanup;
+
+  /* The cleanup chain is one word into the buffer.  Get the cleanup
+     chain.  */
+  cleanup = (void***)&(*dhc)[1];
+
+  /* If there are any cleanups in the chain, run them now.  */
+  if (cleanup[0])
+    {
+      double store[200];
+      void **buf = (void**)store;
+      buf[1] = 0;
+      buf[0] = (*dhc);
+
+      /* try { */
+#ifdef DONT_USE_BUILTIN_SETJMP
+      if (! setjmp (&buf[2]))
+#else
+      if (! __builtin_setjmp (&buf[2]))
+#endif
+	{
+	  *dhc = buf;
+	  while (cleanup[0])
+	    {
+	      func = (void(*)(void*, int))cleanup[0][1];
+	      arg = (void*)cleanup[0][2];
+
+	      /* Update this before running the cleanup.  */
+	      cleanup[0] = (void **)cleanup[0][0];
+
+	      (*func)(arg, 2);
+	    }
+	  *dhc = buf[0];
+	}
+      /* catch (...) */
+      else
+	{
+	  __terminate ();
+	}
+    }
+  
+  /* We must call terminate if we try and rethrow an exception, when
+     there is no exception currently active and when there are no
+     handlers left.  */
+  if (! __eh_info || (*dhc) == top_elt)
+    __terminate ();
+    
+  /* Find the jmpbuf associated with the top element of the dynamic
+     handler chain.  The jumpbuf starts two words into the buffer.  */
+  jmpbuf = &(*dhc)[2];
+
+  /* Then we pop the top element off the dynamic handler chain.  */
+  *dhc = (void**)(*dhc)[0];
+
+  /* And then we jump to the handler.  */
+
+#ifdef DONT_USE_BUILTIN_SETJMP
+  longjmp (jmpbuf, 1);
+#else
+  __builtin_longjmp (jmpbuf, 1);
+#endif
+}
+
+/* Run cleanups on the dynamic cleanup stack for the current dynamic
+   handler, then pop the handler off the dynamic handler stack, and
+   then throw.  This is used to skip the first handler, and transfer
+   control to the next handler in the dynamic handler stack.  */
+
+void
+__sjpopnthrow ()
+{
+  void ***dhc = __get_dynamic_handler_chain ();
+  void *jmpbuf;
+  void (*func)(void *, int);
+  void *arg;
+  void ***cleanup;
+
+  /* The cleanup chain is one word into the buffer.  Get the cleanup
+     chain.  */
+  cleanup = (void***)&(*dhc)[1];
+
+  /* If there are any cleanups in the chain, run them now.  */
+  if (cleanup[0])
+    {
+      double store[200];
+      void **buf = (void**)store;
+      buf[1] = 0;
+      buf[0] = (*dhc);
+
+      /* try { */
+#ifdef DONT_USE_BUILTIN_SETJMP
+      if (! setjmp (&buf[2]))
+#else
+      if (! __builtin_setjmp (&buf[2]))
+#endif
+	{
+	  *dhc = buf;
+	  while (cleanup[0])
+	    {
+	      func = (void(*)(void*, int))cleanup[0][1];
+	      arg = (void*)cleanup[0][2];
+
+	      /* Update this before running the cleanup.  */
+	      cleanup[0] = (void **)cleanup[0][0];
+
+	      (*func)(arg, 2);
+	    }
+	  *dhc = buf[0];
+	}
+      /* catch (...) */
+      else
+	{
+	  __terminate ();
+	}
+    }
+
+  /* Then we pop the top element off the dynamic handler chain.  */
+  *dhc = (void**)(*dhc)[0];
+
+  __sjthrow ();
+}
+
+
+/* Support code for all exception region-based exception handling.  */
+
+/* This value identifies the place from which an exception is being
+   thrown.  */
+
+void *__eh_pc;
+
+#ifdef EH_TABLE_LOOKUP
+
+EH_TABLE_LOOKUP
+
+#else
+
+typedef struct exception_table {
+  void *start;
+  void *end;
+  void *exception_handler;
+} exception_table;
+
+/* This routine takes a PC and a pointer to the exception region TABLE for
+   its translation unit, and returns the address of the exception handler
+   associated with the closest exception table handler entry associated
+   with that PC, or 0 if there are no table entries the PC fits in.
+
+   In the advent of a tie, we have to give the last entry, as it represents
+   an inner block.  */
+
+static void *
+find_exception_handler (void *pc, exception_table *table)
+{
+  if (table)
+    {
+      int pos;
+      int best = -1;
+
+      /* We can't do a binary search because the table isn't guaranteed
+	 to be sorted from function to function.  */
+      for (pos = 0; table[pos].exception_handler != (void *) -1; ++pos)
+	{
+	  if (table[pos].start <= pc && table[pos].end > pc)
+	    {
+	      /* This can apply.  Make sure it is at least as small as
+		 the previous best.  */
+	      if (best == -1 || (table[pos].end <= table[best].end
+				 && table[pos].start >= table[best].start))
+		best = pos;
+	    }
+	  /* But it is sorted by starting PC within a function.  */
+	  else if (best >= 0 && table[pos].start > pc)
+	    break;
+	}
+      if (best != -1)
+	return table[best].exception_handler;
+    }
+
+  return (void *) 0;
+}
+#endif /* EH_TABLE_LOOKUP */
+
+
+#ifndef DWARF2_UNWIND_INFO
+/* Support code for exception handling using inline unwinders or
+   __unwind_function.  */
+
+#ifndef EH_TABLE_LOOKUP
+typedef struct exception_table_node {
+  exception_table *table;
+  void *start;
+  void *end;
+  struct exception_table_node *next;
+} exception_table_node;
+
+static struct exception_table_node *exception_table_list;
+
+void *
+__find_first_exception_table_match (void *pc)
+{
+  register exception_table_node *tnp;
+
+  for (tnp = exception_table_list; tnp != 0; tnp = tnp->next)
+    {
+      if (tnp->start <= pc && tnp->end >= pc)
+	return find_exception_handler (pc, tnp->table);
+    }
+
+  return (void *) 0;
+}
+
+void
+__register_exceptions (exception_table *table)
+{
+  exception_table_node *node;
+  exception_table *range = table + 1;
+
+  if (range->start == (void *) -1)
+    return;
+
+  node = (exception_table_node *) malloc (sizeof (exception_table_node));
+  node->table = table;
+
+  /* This look can be optimized away either if the table
+     is sorted, or if we pass in extra parameters.  */
+  node->start = range->start;
+  node->end = range->end;
+  for (range++ ; range->start != (void *) (-1); range++)
+    {
+      if (range->start < node->start)
+	node->start = range->start;
+      if (range->end > node->end)
+	node->end = range->end;
+    }
+
+  node->next = exception_table_list;
+  exception_table_list = node;
+}
+#endif /* !EH_TABLE_LOOKUP */
+
+/* Throw stub routine.
+
+   This is work in progress, but not completed yet.  */
+
+void
+__throw ()
+{
+  abort ();
+}
+
+/* See expand_builtin_throw for details.  */
+
+void **__eh_pcnthrow () {
+  static void *buf[2] = {
+    &__eh_pc,
+    &__throw
+  };
+  return buf;
+}
+
+#if #machine(i386)
+void
+__unwind_function(void *ptr)
+{
+  asm("movl 8(%esp),%ecx");
+  /* Undo current frame */
+  asm("movl %ebp,%esp");
+  asm("popl %ebp");
+  /* like ret, but stay here */
+  asm("addl $4,%esp");
+  
+  /* Now, undo previous frame.  */
+  /* This is a test routine, as we have to dynamically probe to find out
+     what to pop for certain, this is just a guess.  */
+  asm("leal -16(%ebp),%esp");
+  asm("pop %ebx");
+  asm("pop %esi");
+  asm("pop %edi");
+  asm("movl %ebp,%esp");
+  asm("popl %ebp");
+
+  asm("movl %ecx,0(%esp)");
+  asm("ret");
+}
+#elif #machine(rs6000) && !defined _ARCH_PPC
+__unwind_function(void *ptr)
+{
+  asm("mr 31,1");
+  asm("l 1,0(1)");
+  asm("l 31,-4(1)");
+  asm("# br");
+
+  asm("mr 31,1");
+  asm("l 1,0(1)");
+  /* use 31 as a scratch register to restore the link register.  */
+  asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
+  asm("l 31,-4(1)");
+  asm("# br");
+  asm("mtctr 3;bctr # b 3");
+}
+#elif (#machine(rs6000) || #machine(powerpc)) && defined _ARCH_PPC
+__unwind_function(void *ptr)
+{
+  asm("mr 31,1");
+  asm("lwz 1,0(1)");
+  asm("lwz 31,-4(1)");
+  asm("# br");
+
+  asm("mr 31,1");
+  asm("lwz 1,0(1)");
+  /* use 31 as a scratch register to restore the link register.  */
+  asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
+  asm("lwz 31,-4(1)");
+  asm("# br");
+  asm("mtctr 3;bctr # b 3");
+}
+#elif #machine(vax)
+__unwind_function(void *ptr)
+{
+  __label__ return_again;
+
+  /* Replace our frame's return address with the label below.
+     During execution, we will first return here instead of to
+     caller, then second return takes caller's frame off the stack.
+     Two returns matches two actual calls, so is less likely to
+     confuse debuggers.  `16' corresponds to RETURN_ADDRESS_OFFSET.  */
+  __asm ("movl %0,16(fp)" : : "p" (&& return_again));
+  return;
+
+ return_again:
+  return;
+}
+#else
+__unwind_function(void *ptr)
+{
+  abort ();
+}
+#endif /* powerpc */
+
+
+#else /* DWARF2_UNWIND_INFO */
+/* Support code for exception handling using static unwind information.  */
+
+#include "frame.h"
+
+/* This type is used in get_reg and put_reg to deal with ABIs where a void*
+   is smaller than a word, such as the Irix 6 n32 ABI.  We cast twice to
+   avoid a warning about casting between int and pointer of different
+   sizes.  */
+
+typedef int ptr_type __attribute__ ((mode (pointer)));
+
+/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
+   frame called by UDATA or 0.  */
+
+static void*
+get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
+{
+  if (udata->saved[reg] == REG_SAVED_OFFSET)
+    return (void *)(ptr_type)
+      *(word_type *)(udata->cfa + udata->reg_or_offset[reg]);
+  else if (udata->saved[reg] == REG_SAVED_REG && sub_udata)
+    return get_reg (udata->reg_or_offset[reg], sub_udata, 0);
+  else
+    abort ();
+}
+
+/* Overwrite the saved value for register REG in frame UDATA with VAL.  */
+
+static void
+put_reg (unsigned reg, void *val, frame_state *udata)
+{
+  if (udata->saved[reg] == REG_SAVED_OFFSET)
+    *(word_type *)(udata->cfa + udata->reg_or_offset[reg])
+      = (word_type)(ptr_type) val;
+  else
+    abort ();
+}
+
+/* Copy the saved value for register REG from frame UDATA to frame
+   TARGET_UDATA.  Unlike the previous two functions, this can handle
+   registers that are not one word large.  */
+
+static void
+copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
+{
+  if (udata->saved[reg] == REG_SAVED_OFFSET
+      && target_udata->saved[reg] == REG_SAVED_OFFSET)
+    memcpy (target_udata->cfa + target_udata->reg_or_offset[reg],
+	    udata->cfa + udata->reg_or_offset[reg],
+	    __builtin_dwarf_reg_size (reg));
+  else
+    abort ();
+}
+
+/* Retrieve the return address for frame UDATA, where SUB_UDATA is a
+   frame called by UDATA or 0.  */
+
+static inline void *
+get_return_addr (frame_state *udata, frame_state *sub_udata)
+{
+  return __builtin_extract_return_addr
+    (get_reg (udata->retaddr_column, udata, sub_udata));
+}
+
+/* Overwrite the return address for frame UDATA with VAL.  */
+
+static inline void
+put_return_addr (void *val, frame_state *udata)
+{
+  val = __builtin_frob_return_addr (val);
+  put_reg (udata->retaddr_column, val, udata);
+}
+
+/* Given the current frame UDATA and its return address PC, return the
+   information about the calling frame in CALLER_UDATA.  */
+
+static void *
+next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
+{
+  caller_udata = __frame_state_for (pc, caller_udata);
+  if (! caller_udata)
+    return 0;
+
+  /* Now go back to our caller's stack frame.  If our caller's CFA register
+     was saved in our stack frame, restore it; otherwise, assume the CFA
+     register is SP and restore it to our CFA value.  */
+  if (udata->saved[caller_udata->cfa_reg])
+    caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);
+  else
+    caller_udata->cfa = udata->cfa;
+  caller_udata->cfa += caller_udata->cfa_offset;
+
+  return caller_udata;
+}
+
+#ifdef INCOMING_REGNO
+/* Is the saved value for register REG in frame UDATA stored in a register
+   window in the previous frame?  */
+
+static int
+in_reg_window (int reg, frame_state *udata)
+{
+  if (udata->saved[reg] != REG_SAVED_OFFSET)
+    return 0;
+
+#ifdef STACK_GROWS_DOWNWARD
+  return udata->reg_or_offset[reg] > 0;
+#else
+  return udata->reg_or_offset[reg] < 0;
+#endif
+}
+#endif /* INCOMING_REGNO */
+
+/* We first search for an exception handler, and if we don't find
+   it, we call __terminate on the current stack frame so that we may
+   use the debugger to walk the stack and understand why no handler
+   was found.
+
+   If we find one, then we unwind the frames down to the one that
+   has the handler and transfer control into the handler.  */
+
+void
+__throw ()
+{
+  void *pc, *handler, *retaddr;
+  frame_state ustruct, ustruct2;
+  frame_state *udata = &ustruct;
+  frame_state *sub_udata = &ustruct2;
+  frame_state my_ustruct, *my_udata = &my_ustruct;
+  long args_size;
+
+  /* This is required for C++ semantics.  We must call terminate if we
+     try and rethrow an exception, when there is no exception currently
+     active.  */
+  if (! __eh_info)
+    __terminate ();
+    
+  /* Start at our stack frame.  */
+label:
+  udata = __frame_state_for (&&label, udata);
+  if (! udata)
+    __terminate ();
+
+  /* We need to get the value from the CFA register.  At this point in
+     compiling __throw we don't know whether or not we will use the frame
+     pointer register for the CFA, so we check our unwind info.  */
+  if (udata->cfa_reg == __builtin_dwarf_fp_regnum ())
+    udata->cfa = __builtin_fp ();
+  else
+    udata->cfa = __builtin_sp ();
+  udata->cfa += udata->cfa_offset;
+
+  memcpy (my_udata, udata, sizeof (*udata));
+
+  /* Do any necessary initialization to access arbitrary stack frames.
+     On the SPARC, this means flushing the register windows.  */
+  __builtin_unwind_init ();
+
+  /* Now reset pc to the right throw point.  */
+  pc = __eh_pc;
+
+  handler = 0;
+  for (;;)
+    { 
+      frame_state *p = udata;
+      udata = next_stack_level (pc, udata, sub_udata);
+      sub_udata = p;
+
+      /* If we couldn't find the next frame, we lose.  */
+      if (! udata)
+	break;
+
+      handler = find_exception_handler (pc, udata->eh_ptr);
+
+      /* If we found one, we can stop searching.  */
+      if (handler)
+	{
+	  args_size = udata->args_size;
+	  break;
+	}
+
+      /* Otherwise, we continue searching.  We subtract 1 from PC to avoid
+	 hitting the beginning of the next region.  */
+      pc = get_return_addr (udata, sub_udata) - 1;
+    }
+
+  /* If we haven't found a handler by now, this is an unhandled
+     exception.  */
+  if (! handler)
+    __terminate ();
+
+  if (pc == __eh_pc)
+    /* We found a handler in the throw context, no need to unwind.  */
+    udata = my_udata;
+  else
+    {
+      int i;
+      void *val;
+
+      /* Unwind all the frames between this one and the handler by copying
+	 their saved register values into our register save slots.  */
+
+      /* Remember the PC where we found the handler.  */
+      void *handler_pc = pc;
+
+      /* Start from the throw context again.  */
+      pc = __eh_pc;
+      memcpy (udata, my_udata, sizeof (*udata));
+
+      while (pc != handler_pc)
+	{
+	  frame_state *p = udata;
+	  udata = next_stack_level (pc, udata, sub_udata);
+	  sub_udata = p;
+
+	  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+	    if (i != udata->retaddr_column && udata->saved[i])
+	      {
+#ifdef INCOMING_REGNO
+		/* If you modify the saved value of the return address
+		   register on the SPARC, you modify the return address for
+		   your caller's frame.  Don't do that here, as it will
+		   confuse get_return_addr.  */
+		if (in_reg_window (i, udata)
+		    && udata->saved[udata->retaddr_column] == REG_SAVED_REG
+		    && udata->reg_or_offset[udata->retaddr_column] == i)
+		  continue;
+#endif
+		copy_reg (i, udata, my_udata);
+	      }
+
+	  pc = get_return_addr (udata, sub_udata) - 1;
+	}
+
+#ifdef INCOMING_REGNO
+      /* But we do need to update the saved return address register from
+	 the last frame we unwind, or the handler frame will have the wrong
+	 return address.  */
+      if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)
+	{
+	  i = udata->reg_or_offset[udata->retaddr_column];
+	  if (in_reg_window (i, udata))
+	    copy_reg (i, udata, my_udata);
+	}
+#endif
+    }
+  /* udata now refers to the frame called by the handler frame.  */
+
+  /* Emit the stub to adjust sp and jump to the handler.  */
+  retaddr = __builtin_eh_stub ();
+
+  /* And then set our return address to point to the stub.  */
+  if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET)
+    put_return_addr (retaddr, my_udata);
+  else
+    __builtin_set_return_addr_reg (retaddr);
+
+  /* Set up the registers we use to communicate with the stub.
+     We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack.  */
+  __builtin_set_eh_regs (handler,
+#ifdef STACK_GROWS_DOWNWARD
+			 udata->cfa - my_udata->cfa
+#else
+			 my_udata->cfa - udata->cfa
+#endif
+			 + args_size
+			 );
+
+  /* Epilogue:  restore the handler frame's register values and return
+     to the stub.  */
+}
+#endif /* !DWARF2_UNWIND_INFO */
Index: trunk/src/emx/src/lib/Attic/gcc/exceptio.cc
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/exceptio.cc	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/exceptio.cc	(revision 18)
@@ -0,0 +1,198 @@
+// Functions for Exception Support for -*- C++ -*-
+// Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA. 
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#pragma implementation "exception"
+
+#include "typeinfo"
+#include "exception"
+
+/* Define terminate, unexpected, set_terminate, set_unexpected as
+   well as the default terminate func and default unexpected func.  */
+
+extern terminate_handler __terminate_func __attribute__((__noreturn__));
+
+void
+terminate ()
+{
+  __terminate_func ();
+}
+
+void
+__default_unexpected ()
+{
+  terminate ();
+}
+
+static unexpected_handler __unexpected_func = __default_unexpected;
+
+terminate_handler
+set_terminate (terminate_handler func)
+{
+  terminate_handler old = __terminate_func;
+
+  __terminate_func = func;
+  return old;
+}
+
+unexpected_handler
+set_unexpected (unexpected_handler func)
+{
+  unexpected_handler old = __unexpected_func;
+
+  __unexpected_func = func;
+  return old;
+}
+
+void
+unexpected ()
+{
+  __unexpected_func ();
+}
+
+/* C++-specific state about the current exception.
+   This must match init_exception_processing().
+
+   Note that handlers and caught are not redundant; when rethrown, an
+   exception can have multiple active handlers and still be considered
+   uncaught.  */
+
+struct cp_eh_info
+{
+  void *value;
+  void *type;
+  void (*cleanup)(void *, int);
+  bool caught;
+  cp_eh_info *next;
+  long handlers;
+};
+
+/* Language-specific EH info pointer, defined in libgcc2.  */
+
+extern cp_eh_info *__eh_info;  // actually void*
+
+/* Is P the type_info node for a pointer of some kind?  */
+
+extern bool __is_pointer (void *);
+
+/* Compiler hook to return a pointer to the info for the current exception.
+   Used by get_eh_info ().  */
+
+extern "C" cp_eh_info *
+__cp_exception_info (void)
+{
+  return __eh_info;
+}
+
+/* Compiler hook to push a new exception onto the stack.
+   Used by expand_throw().  */
+
+extern "C" void
+__cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
+{
+  cp_eh_info *p = new cp_eh_info;
+  p->value = value;
+  p->type = type;
+  p->cleanup = cleanup;
+  p->handlers = 0;
+  p->caught = false;
+  p->next = __eh_info;
+  __eh_info = p;
+}
+
+/* Compiler hook to pop an exception that has been finalized.  Used by
+   push_eh_cleanup().  P is the info for the exception caught by the
+   current catch block.  */
+
+extern "C" void
+__cp_pop_exception (cp_eh_info *p)
+{
+  cp_eh_info **q = &__eh_info;
+
+  --p->handlers;
+
+  /* Don't really pop if there are still active handlers for our exception,
+     or if our exception is being rethrown (i.e. if the active exception is
+     our exception and it is uncaught).  */
+  if (p->handlers != 0
+      || (p == *q && !p->caught))
+    return;
+
+  for (; *q; q = &((*q)->next))
+    if (*q == p)
+      break;
+
+  if (! *q)
+    terminate ();
+
+  *q = p->next;
+
+  if (p->cleanup)
+    /* 3 is a magic value for destructors; see build_delete().  */
+    p->cleanup (p->value, 3);
+  else if (__is_pointer (p->type))
+    /* do nothing; pointers are passed directly in p->value.  */;
+  else
+    delete p->value;
+
+  delete p;
+}
+
+extern "C" void
+__uncatch_exception (void)
+{
+  cp_eh_info *p = __cp_exception_info ();
+  if (p)
+    p->caught = false;
+  /* otherwise __throw will call terminate(); don't crash here.  */
+}
+
+extern "C" void
+__throw_bad_cast (void)
+{
+  throw bad_cast ();
+}
+
+extern "C" void
+__throw_bad_typeid (void)
+{
+  throw bad_typeid ();
+}
+
+/* Has the current exception been caught?  */
+
+bool
+uncaught_exception ()
+{
+  cp_eh_info *p = __cp_exception_info ();
+  return p && ! p->caught;
+}
+
+const char * exception::
+what () const
+{
+  return typeid (*this).name ();
+}
Index: trunk/src/emx/src/lib/Attic/gcc/frame.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/frame.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/frame.c	(revision 18)
@@ -0,0 +1,660 @@
+/* frame.c -- modified by Eberhard Mattes, Sep 1998 */
+/* Subroutines needed for unwinding stack frames for exception handling.  */
+/* Compile this one with gcc.  */
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   Contributed by Jason Merrill <jason@cygnus.com>.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#ifdef EMX
+#include <stdlib.h>
+#endif /* EMX */
+
+/* It is incorrect to include config.h here, because this file is being
+   compiled for the target, and hence definitions concerning only the host
+   do not apply.  */
+
+#include "tconfig.h"
+#include "defaults.h"
+
+#ifdef DWARF2_UNWIND_INFO
+#include "gansidecl.h"
+#include "dwarf2.h"
+#include <stddef.h>
+#include "frame.h"
+
+/* Don't use `fancy_abort' here even if config.h says to use it.  */
+#ifdef abort
+#undef abort
+#endif
+
+/* Some types used by the DWARF 2 spec.  */
+
+typedef          int  sword __attribute__ ((mode (SI)));
+typedef unsigned int  uword __attribute__ ((mode (SI)));
+typedef unsigned int  uaddr __attribute__ ((mode (pointer)));
+typedef          int  saddr __attribute__ ((mode (pointer)));
+typedef unsigned char ubyte;
+
+/* The first few fields of a CIE.  The CIE_id field is 0xffffffff for a CIE,
+   to distinguish it from a valid FDE.  FDEs are aligned to an addressing
+   unit boundary, but the fields within are unaligned.  */
+
+struct dwarf_cie {
+  uword length;
+  sword CIE_id;
+  ubyte version;
+  char augmentation[0];
+} __attribute__ ((packed, aligned (__alignof__ (void *))));
+
+/* The first few fields of an FDE.  */
+
+struct dwarf_fde {
+  uword length;
+  sword CIE_delta;
+  void* pc_begin;
+  uaddr pc_range;
+} __attribute__ ((packed, aligned (__alignof__ (void *))));
+
+typedef struct dwarf_fde fde;
+
+/* Objects to be searched for frame unwind info.  */
+
+static struct object *objects;
+
+/* The information we care about from a CIE.  */
+
+struct cie_info {
+  char *augmentation;
+  void *eh_ptr;
+  int code_align;
+  int data_align;
+  unsigned ra_regno;
+};
+
+/* The current unwind state, plus a saved copy for DW_CFA_remember_state.  */
+
+struct frame_state_internal
+{
+  struct frame_state s;
+  struct frame_state_internal *saved_state;
+};
+
+  
+/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
+   by R, and return the new value of BUF.  */
+
+static void *
+decode_uleb128 (unsigned char *buf, unsigned *r)
+{
+  unsigned shift = 0;
+  unsigned result = 0;
+
+  while (1)
+    {
+      unsigned byte = *buf++;
+      result |= (byte & 0x7f) << shift;
+      if ((byte & 0x80) == 0)
+	break;
+      shift += 7;
+    }
+  *r = result;
+  return buf;
+}
+
+/* Decode the signed LEB128 constant at BUF into the variable pointed to
+   by R, and return the new value of BUF.  */
+
+static void *
+decode_sleb128 (unsigned char *buf, int *r)
+{
+  unsigned shift = 0;
+  unsigned result = 0;
+  unsigned byte;
+
+  while (1)
+    {
+      byte = *buf++;
+      result |= (byte & 0x7f) << shift;
+      shift += 7;
+      if ((byte & 0x80) == 0)
+	break;
+    }
+  if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
+    result |= - (1 << shift);
+
+  *r = result;
+  return buf;
+}
+
+/* Read unaligned data from the instruction buffer.  */
+
+union unaligned {
+  void *p;
+  unsigned b2 __attribute__ ((mode (HI)));
+  unsigned b4 __attribute__ ((mode (SI)));
+  unsigned b8 __attribute__ ((mode (DI)));
+} __attribute__ ((packed));
+static inline void *
+read_pointer (void *p)
+{ union unaligned *up = p; return up->p; }
+static inline unsigned
+read_1byte (void *p)
+{ return *(unsigned char *)p; }
+static inline unsigned
+read_2byte (void *p)
+{ union unaligned *up = p; return up->b2; }
+static inline unsigned
+read_4byte (void *p)
+{ union unaligned *up = p; return up->b4; }
+static inline unsigned long
+read_8byte (void *p)
+{ union unaligned *up = p; return up->b8; }
+
+
+/* Ordering function for FDEs.  Functions can't overlap, so we just compare
+   their starting addresses.  */
+
+static inline saddr
+fde_compare (fde *x, fde *y)
+{
+  return (saddr)x->pc_begin - (saddr)y->pc_begin;
+}
+
+/* Return the address of the FDE after P.  */
+
+static inline fde *
+next_fde (fde *p)
+{
+  return (fde *)(((char *)p) + p->length + sizeof (p->length));
+}
+
+/* One iteration of an insertion sort, for adding new FDEs to the array.
+   Usually the new FDE will go in at the end, so we can expect close to
+   O(n) performance.  If this turns out to be overly optimistic, we can have
+   the linker sort the FDEs so we don't have to do it at run time.  */
+
+static void
+fde_insert (fde **array, size_t i, fde *this_fde)
+{
+  array[i] = this_fde;
+
+  for (; i > 0 && fde_compare (array[i], array[i-1]) < 0; --i)
+    {
+      this_fde = array[i];
+      array[i] = array[i-1];
+      array[i-1] = this_fde;
+    }
+}
+
+static size_t
+count_fdes (fde *this_fde)
+{
+  size_t count;
+
+  for (count = 0; this_fde->length != 0; this_fde = next_fde (this_fde))
+    {
+      /* Skip CIEs and linked once FDE entries.  */
+      if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
+	continue;
+
+      ++count;
+    }
+
+  return count;
+}
+
+static void
+add_fdes (fde *this_fde, fde **array, size_t *i_ptr,
+	  void **beg_ptr, void **end_ptr)
+{
+  size_t i = *i_ptr;
+  void *pc_begin = *beg_ptr;
+  void *pc_end = *end_ptr;
+
+  for (; this_fde->length != 0; this_fde = next_fde (this_fde))
+    {
+      /* Skip CIEs and linked once FDE entries.  */
+      if (this_fde->CIE_delta == 0 || this_fde->pc_begin == 0)
+	continue;
+
+      fde_insert (array, i++, this_fde);
+
+      if (this_fde->pc_begin < pc_begin)
+	pc_begin = this_fde->pc_begin;
+      if (this_fde->pc_begin + this_fde->pc_range > pc_end)
+	pc_end = this_fde->pc_begin + this_fde->pc_range;
+    }
+
+  *i_ptr = i;
+  *beg_ptr = pc_begin;
+  *end_ptr = pc_end;
+}
+
+/* Set up a sorted array of pointers to FDEs for a loaded object.  We
+   count up the entries before allocating the array because it's likely to
+   be faster.  */
+
+static void
+frame_init (struct object* ob)
+{
+  fde *this_fde;
+  size_t count;
+  fde **array;
+  void *pc_begin, *pc_end;
+
+  if (ob->fde_array)
+    {
+      fde **p = ob->fde_array;
+      for (count = 0; *p; ++p)
+	count += count_fdes (*p);
+    }
+  else
+    count = count_fdes (ob->fde_begin);
+
+  ob->count = count;
+  array = (fde **) malloc (sizeof (fde *) * count);
+
+  pc_begin = (void*)(uaddr)-1;
+  pc_end = 0;
+  count = 0;
+
+  if (ob->fde_array)
+    {
+      fde **p = ob->fde_array;
+      for (; *p; ++p)
+	add_fdes (*p, array, &count, &pc_begin, &pc_end);
+    }
+  else
+    add_fdes (ob->fde_begin, array, &count, &pc_begin, &pc_end);
+
+  ob->fde_array = array;
+  ob->pc_begin = pc_begin;
+  ob->pc_end = pc_end;
+}
+
+/* Return a pointer to the FDE for the function containing PC.  */
+
+static fde *
+find_fde (void *pc)
+{
+  struct object *ob;
+  size_t lo, hi;
+
+  for (ob = objects; ob; ob = ob->next)
+    {
+      if (ob->pc_begin == 0)
+	frame_init (ob);
+      if (pc >= ob->pc_begin && pc < ob->pc_end)
+	break;
+    }
+
+  if (ob == 0)
+    return 0;
+
+  /* Standard binary search algorithm.  */
+  for (lo = 0, hi = ob->count; lo < hi; )
+    {
+      size_t i = (lo + hi) / 2;
+      fde *f = ob->fde_array[i];
+
+      if (pc < f->pc_begin)
+	hi = i;
+      else if (pc > f->pc_begin + f->pc_range)
+	lo = i + 1;
+      else
+	return f;
+    }
+
+  return 0;
+}
+
+
+static inline struct dwarf_cie *
+get_cie (fde *f)
+{
+  return ((void *)&f->CIE_delta) - f->CIE_delta;
+}
+
+/* Extract any interesting information from the CIE for the translation
+   unit F belongs to.  */
+
+static void *
+extract_cie_info (fde *f, struct cie_info *c)
+{
+  void *p;
+  int i;
+
+  c->augmentation = get_cie (f)->augmentation;
+
+  if (strcmp (c->augmentation, "") != 0
+      && strcmp (c->augmentation, "eh") != 0
+      && c->augmentation[0] != 'z')
+    return 0;
+
+  p = c->augmentation + strlen (c->augmentation) + 1;
+
+  if (strcmp (c->augmentation, "eh") == 0)
+    {
+      c->eh_ptr = read_pointer (p);
+      p += sizeof (void *);
+    }
+  else
+    c->eh_ptr = 0;
+
+  p = decode_uleb128 (p, &c->code_align);
+  p = decode_sleb128 (p, &c->data_align);
+  c->ra_regno = *(unsigned char *)p++;
+
+  /* If the augmentation starts with 'z', we now see the length of the
+     augmentation fields.  */
+  if (c->augmentation[0] == 'z')
+    {
+      p = decode_uleb128 (p, &i);
+      p += i;
+    }
+
+  return p;
+}
+
+/* Decode one instruction's worth of of DWARF 2 call frame information.
+   Used by __frame_state_for.  Takes pointers P to the instruction to
+   decode, STATE to the current register unwind information, INFO to the
+   current CIE information, and PC to the current PC value.  Returns a
+   pointer to the next instruction.  */
+
+static void *
+execute_cfa_insn (void *p, struct frame_state_internal *state,
+		  struct cie_info *info, void **pc)
+{
+  unsigned insn = *(unsigned char *)p++;
+  unsigned reg;
+  int offset;
+
+  if (insn & DW_CFA_advance_loc)
+    *pc += ((insn & 0x3f) * info->code_align);
+  else if (insn & DW_CFA_offset)
+    {
+      reg = (insn & 0x3f);
+      p = decode_uleb128 (p, &offset);
+      offset *= info->data_align;
+      state->s.saved[reg] = REG_SAVED_OFFSET;
+      state->s.reg_or_offset[reg] = offset;
+    }
+  else if (insn & DW_CFA_restore)
+    {
+      reg = (insn & 0x3f);
+      state->s.saved[reg] = REG_UNSAVED;
+    }
+  else switch (insn)
+    {
+    case DW_CFA_set_loc:
+      *pc = read_pointer (p);
+      p += sizeof (void *);
+      break;
+    case DW_CFA_advance_loc1:
+      *pc += read_1byte (p);
+      p += 1;
+      break;
+    case DW_CFA_advance_loc2:
+      *pc += read_2byte (p);
+      p += 2;
+      break;
+    case DW_CFA_advance_loc4:
+      *pc += read_4byte (p);
+      p += 4;
+      break;
+
+    case DW_CFA_offset_extended:
+      p = decode_uleb128 (p, &reg);
+      p = decode_uleb128 (p, &offset);
+      offset *= info->data_align;
+      state->s.saved[reg] = REG_SAVED_OFFSET;
+      state->s.reg_or_offset[reg] = offset;
+      break;
+    case DW_CFA_restore_extended:
+      p = decode_uleb128 (p, &reg);
+      state->s.saved[reg] = REG_UNSAVED;
+      break;
+
+    case DW_CFA_undefined:
+    case DW_CFA_same_value:
+    case DW_CFA_nop:
+      break;
+
+    case DW_CFA_register:
+      {
+	unsigned reg2;
+	p = decode_uleb128 (p, &reg);
+	p = decode_uleb128 (p, &reg2);
+	state->s.saved[reg] = REG_SAVED_REG;
+	state->s.reg_or_offset[reg] = reg2;
+      }
+      break;
+
+    case DW_CFA_def_cfa:
+      p = decode_uleb128 (p, &reg);
+      p = decode_uleb128 (p, &offset);
+      state->s.cfa_reg = reg;
+      state->s.cfa_offset = offset;
+      break;
+    case DW_CFA_def_cfa_register:
+      p = decode_uleb128 (p, &reg);
+      state->s.cfa_reg = reg;
+      break;
+    case DW_CFA_def_cfa_offset:
+      p = decode_uleb128 (p, &offset);
+      state->s.cfa_offset = offset;
+      break;
+      
+    case DW_CFA_remember_state:
+      {
+	struct frame_state_internal *save =
+	  (struct frame_state_internal *)
+	  malloc (sizeof (struct frame_state_internal));
+	memcpy (save, state, sizeof (struct frame_state_internal));
+	state->saved_state = save;
+      }
+      break;
+    case DW_CFA_restore_state:
+      {
+	struct frame_state_internal *save = state->saved_state;
+	memcpy (state, save, sizeof (struct frame_state_internal));
+	free (save);
+      }
+      break;
+
+      /* FIXME: Hardcoded for SPARC register window configuration.  */
+    case DW_CFA_GNU_window_save:
+      for (reg = 16; reg < 32; ++reg)
+	{
+	  state->s.saved[reg] = REG_SAVED_OFFSET;
+	  state->s.reg_or_offset[reg] = (reg - 16) * sizeof (void *);
+	}
+      break;
+
+    case DW_CFA_GNU_args_size:
+      p = decode_uleb128 (p, &offset);
+      state->s.args_size = offset;
+      break;
+
+    default:
+      abort ();
+    }
+  return p;
+}
+
+
+/* Called from crtbegin.o to register the unwind info for an object.  */
+
+void
+__register_frame_info (void *begin, struct object *ob)
+{
+  ob->fde_begin = begin;
+
+  ob->pc_begin = ob->pc_end = 0;
+  ob->fde_array = 0;
+  ob->count = 0;
+
+  ob->next = objects;
+  objects = ob;
+}
+
+/* Similar, but BEGIN is actually a pointer to a table of unwind entries
+   for different translation units.  Called from the file generated by
+   collect2.  */
+
+void
+__register_frame_info_table (void *begin, struct object *ob)
+{
+  ob->fde_begin = begin;
+  ob->fde_array = begin;
+
+  ob->pc_begin = ob->pc_end = 0;
+  ob->count = 0;
+
+  ob->next = objects;
+  objects = ob;
+}
+
+/* Called from crtend.o to deregister the unwind info for an object.  */
+
+void
+__deregister_frame_info (void *begin)
+{
+  struct object **p = &objects;
+
+  while (*p)
+    {
+      if ((*p)->fde_begin == begin)
+	{
+	  struct object *ob = *p;
+	  *p = (*p)->next;
+
+	  /* If we've run init_frame for this object, free the FDE array.  */
+	  if (ob->pc_begin)
+	    free (ob->fde_array);
+
+	  return;
+	}
+      p = &((*p)->next);
+    }
+  abort ();
+}
+
+/* Called from __throw to find the registers to restore for a given
+   PC_TARGET.  The caller should allocate a local variable of `struct
+   frame_state' (declared in frame.h) and pass its address to STATE_IN.  */
+
+struct frame_state *
+__frame_state_for (void *pc_target, struct frame_state *state_in)
+{
+  fde *f;
+  void *insn, *end, *pc;
+  struct cie_info info;
+  struct frame_state_internal state;
+
+  f = find_fde (pc_target);
+  if (f == 0)
+    return 0;
+
+  insn = extract_cie_info (f, &info);
+  if (insn == 0)
+    return 0;
+
+  memset (&state, 0, sizeof (state));
+  state.s.retaddr_column = info.ra_regno;
+  state.s.eh_ptr = info.eh_ptr;
+
+  /* First decode all the insns in the CIE.  */
+  end = next_fde ((fde*) get_cie (f));
+  while (insn < end)
+    insn = execute_cfa_insn (insn, &state, &info, 0);
+
+  insn = ((fde *)f) + 1;
+
+  if (info.augmentation[0] == 'z')
+    {
+      int i;
+      insn = decode_uleb128 (insn, &i);
+      insn += i;
+    }
+
+  /* Then the insns in the FDE up to our target PC.  */
+  end = next_fde (f);
+  pc = f->pc_begin;
+  while (insn < end && pc <= pc_target)
+    insn = execute_cfa_insn (insn, &state, &info, &pc);
+
+  memcpy (state_in, &state.s, sizeof (state.s));
+  return state_in;
+}
+#endif /* DWARF2_UNWIND_INFO */
+
+#ifdef EMX
+static void reg_table (int *ptr, struct object *ob)
+{
+  if (*ptr != 0)
+    __register_frame_info_table (ptr, ob);
+}
+
+static void dereg_table (int *ptr)
+{
+  if (*ptr != 0)
+    __deregister_frame_info (ptr);
+}
+
+/* See also /emx/src/lib/gcc/386/ehfinit.s */
+
+void __eh_frame_init2 (int *ptr, struct object *ob)
+{
+  int n;
+
+  if (*ptr == -2)                 /* emxomf */
+    reg_table (ptr + 1, ob);
+  else
+    {
+      if (*ptr == -1) --ptr;      /* Fix GNU ld bug */
+      n = *ptr++;                 /* Get size of vector */
+      if (*ptr == -1)             /* First element must be -1, see crt0.s */
+        reg_table (ptr + 1, ob);
+    }
+}
+
+void __eh_frame_term2 (int *ptr)
+{
+  int n;
+
+  if (*ptr == -2)                 /* emxomf */
+    dereg_table (ptr + 1);
+  else
+    {
+      if (*ptr == -1) --ptr;      /* Fix GNU ld bug */
+      n = *ptr++;                 /* Get size of vector */
+      if (*ptr == -1)             /* First element must be -1, see crt0.s */
+        dereg_table (ptr + 1);
+    }
+}
+#endif /* EMX */
Index: trunk/src/emx/src/lib/Attic/gcc/gbl-ctor.h
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/gbl-ctor.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/gbl-ctor.h	(revision 18)
@@ -0,0 +1,92 @@
+/* Definitions relating to the special __do_global_init function used
+   for getting g++ file-scope static objects constructed.  This file
+   will get included either by libgcc2.c (for systems that don't support
+   a .init section) or by crtstuff.c (for those that do).
+   Copyright (C) 1991, 1995, 1996, 1998 Free Software Foundation, Inc.
+   Contributed by Ron Guilmette (rfg@segfault.us.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/*	This file contains definitions and declarations of things
+	relating to the normal start-up-time invocation of C++
+	file-scope static object constructors.  These declarations
+	and definitions are used by *both* libgcc2.c and by crtstuff.c.
+
+	Note that this file should only be compiled with GCC.
+*/
+
+#ifdef NEED_ATEXIT
+#ifndef HAVE_ATEXIT
+#define HAVE_ATEXIT	1	/* Take it from libgcc2.c */
+#endif
+#endif
+
+#ifdef HAVE_ATEXIT
+#if defined (WINNT) || defined (NEED_ATEXIT)
+extern int atexit (void (*) (void));
+#endif
+#define ON_EXIT(FUNC,ARG) atexit ((FUNC))
+#else
+#ifdef sun
+extern int on_exit (void *, void *);	/* The man page says it returns int. */
+#define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
+#endif
+#endif
+
+/*  Declare a pointer to void function type.  */
+
+typedef void (*func_ptr) (void);
+
+/* Declare the set of symbols use as begin and end markers for the lists
+   of global object constructors and global object destructors.  */
+
+extern func_ptr __CTOR_LIST__[];
+extern func_ptr __DTOR_LIST__[];
+
+/* Declare the routine which need to get invoked at program exit time.  */
+
+extern void __do_global_dtors ();
+
+/* Define a macro with the code which needs to be executed at program
+   start-up time.  This macro is used in two places in crtstuff.c (for
+   systems which support a .init section) and in one place in libgcc2.c
+   (for those system which do *not* support a .init section).  For all
+   three places where this code might appear, it must be identical, so
+   we define it once here as a macro to avoid various instances getting
+   out-of-sync with one another.  */
+
+/* Some systems place the number of pointers
+   in the first word of the table.
+   On other systems, that word is -1.
+   In all cases, the table is null-terminated.
+   If the length is not recorded, count up to the null.  */
+
+/* Some systems use a different strategy for finding the ctors.
+   For example, svr3.  */
+#ifndef DO_GLOBAL_CTORS_BODY
+#define DO_GLOBAL_CTORS_BODY						\
+do {									\
+  unsigned long nptrs = (unsigned long) __CTOR_LIST__[0];		\
+  unsigned i;								\
+  if (nptrs == -1)							\
+    for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++);		\
+  for (i = nptrs; i >= 1; i--)						\
+    __CTOR_LIST__[i] ();						\
+} while (0) 
+#endif
+
Index: trunk/src/emx/src/lib/Attic/gcc/gcov-io.h
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/gcov-io.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/gcov-io.h	(revision 18)
@@ -0,0 +1,136 @@
+/* Machine-independent I/O routines for gcov.
+   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Contributed by Bob Manson <manson@cygnus.com>.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#ifndef GCOV_IO_H
+#define GCOV_IO_H
+#include <stdio.h>
+
+/* These routines only work for signed values. */
+
+/* Store a portable representation of VALUE in DEST using BYTES*8-1 bits.
+   Return a non-zero value if VALUE requires more than BYTES*8-1 bits
+   to store. */
+
+static int
+__store_long (value, dest, bytes)
+     long value;
+     char *dest;
+     int bytes;
+{
+  int upper_bit = (value < 0 ? 128 : 0);
+  int i;
+
+  if (value < 0)
+    {
+      long oldvalue = value;
+      value = -value;
+      if (oldvalue != -value)
+	return 1;
+    }
+
+  for(i = 0 ; i < (sizeof (value) < bytes ? sizeof (value) : bytes) ; i++) {
+    dest[i] = value & (i == (bytes - 1) ? 127 : 255);
+    value = value / 256;
+  }
+
+  if (value && value != -1)
+    return 1;
+
+  for(; i < bytes ; i++) 
+    dest[i] = 0;
+  dest[bytes - 1] |= upper_bit;
+  return 0;
+}
+
+/* Retrieve a quantity containing BYTES*8-1 bits from SOURCE and store
+   the result in DEST. Returns a non-zero value if the value in SOURCE
+   will not fit in DEST. */
+
+static int
+__fetch_long (dest, source, bytes)
+     long *dest;
+     char *source;
+     int bytes;
+{
+  long value = 0;
+  int i;
+
+  for (i = bytes - 1; i > (sizeof (*dest) - 1); i--)
+    if (source[i] & (i == (bytes - 1) ? 127 : 255 ))
+      return 1;
+
+  for (; i >= 0; i--)
+    value = value * 256 + (source[i] & (i == (bytes - 1) ? 127 : 255));
+
+  if ((source[bytes - 1] & 128) && (value > 0))
+    value = - value;
+
+  *dest = value;
+  return 0;
+}
+
+/* Write a BYTES*8-bit quantity to FILE, portably. Returns a non-zero
+   value if the write fails, or if VALUE can't be stored in BYTES*8
+   bits.
+
+   Note that VALUE may not actually be large enough to hold BYTES*8
+   bits, but BYTES characters will be written anyway.
+
+   BYTES may be a maximum of 10. */
+
+static int
+__write_long (value, file, bytes)
+     long value;
+     FILE *file;
+     int bytes;
+{
+  char c[10];
+
+  if (bytes > 10 || __store_long (value, c, bytes))
+    return 1;
+  else
+    return fwrite(c, 1, bytes, file) != bytes;
+}
+
+/* Read a quantity containing BYTES bytes from FILE, portably. Return
+   a non-zero value if the read fails or if the value will not fit
+   in DEST.
+
+   Note that DEST may not be large enough to hold all of the requested
+   data, but the function will read BYTES characters anyway.
+
+   BYTES may be a maximum of 10. */
+
+static int
+__read_long (dest, file, bytes)
+     long *dest;
+     FILE *file;
+     int bytes;
+{
+  char c[10];
+
+  if (bytes > 10 || fread(c, 1, bytes, file) != bytes)
+    return 1;
+  else
+    return __fetch_long (dest, c, bytes);
+}
+
+#endif
Index: trunk/src/emx/src/lib/Attic/gcc/lldiv.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/lldiv.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/lldiv.c	(revision 18)
@@ -0,0 +1,41 @@
+/* lldiv.c (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+_lldiv_t _lldiv (long long x, long long y)
+{
+  _ulldiv_t tmp;
+  _lldiv_t r;
+
+  if (x < 0)
+    {
+      if (y < 0)
+        {
+          tmp = _ulldiv (-x, -y);
+          r.quot = tmp.quot;
+          r.rem = -tmp.rem;
+        }
+      else
+        {
+          tmp = _ulldiv (-x, y);
+          r.quot = -tmp.quot;
+          r.rem = -tmp.rem;
+        }
+    }
+  else
+    {
+      if (y < 0)
+        {
+          tmp = _ulldiv (x, -y);
+          r.quot = -tmp.quot;
+          r.rem = tmp.rem;
+        }
+      else
+        {
+          tmp = _ulldiv (x, y);
+          r.quot = tmp.quot;
+          r.rem = tmp.rem;
+        }
+    }
+  return r;
+}
Index: trunk/src/emx/src/lib/Attic/gcc/main.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/main.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/main.c	(revision 18)
@@ -0,0 +1,17 @@
+/* main.c (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes */
+/*                     Copyright (c) 1992-1994 by Kai Uwe Rommel */
+
+#include <stdlib.h>
+
+extern void __ctordtorInit (void);
+extern void __ctordtorTerm (void);
+
+/* This module is always statically linked in order to get a
+   statically linked __ctordtorInit() which uses the __CTOR_LIST__ and
+   __DTOR_LIST__ of the executable. */
+
+void __main (void)
+{
+  __ctordtorInit ();
+  atexit (__ctordtorTerm);
+}
Index: trunk/src/emx/src/lib/Attic/gcc/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/makefile	(revision 18)
@@ -0,0 +1,92 @@
+#
+# /emx/src/lib/gcc/makefile
+#
+GCCSRC = g:/emx/gnu/gcc-2.8
+
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.PHONY: clean default dstlib lib_386 libgcc libgcc-p
+
+.SOURCE.c: ..
+.SOURCE.cc: ..
+.SOURCE.h: ..
+.SOURCE.s: ..
+
+.SOURCE.c: ../$(CPU)
+.SOURCE.s: ../$(CPU)
+
+LIBGCC=$(L)$(LIBNAME).a
+
+GCCFLAGS=-DEMX -DHAVE_ATEXIT -DHAVE_POPEN -I$(GCCSRC) -I$(GCCSRC)/config
+.c.o:
+	$(GCC) $(GCCFLAGS) -c $<
+
+.cc.o:
+	$(GCC) -DEMX -c $<
+
+default: libgcc
+
+libgcc: lib_$(CPU)
+libgcc-p: lib_p_$(CPU)
+
+lib_386 .SETDIR=st_386:
+	$(MAKE) -f ../makefile dstlib LIBNAME=gcc $(PASSDOWN) MT_CCFLAGS=
+
+lib_p_386 .SETDIR=st_p_386:
+	$(MAKE) -f ../makefile dstlib LIBNAME=gcc_p $(PASSDOWN) MT_CCFLAGS=-pg
+
+dstlib: $(LIBGCC)
+
+clean:
+	-del st_$(CPU)\*.o $(DELOPT)
+	-del st_p_$(CPU)\*.o $(DELOPT)
+
+bb.o: bb.c gbl-ctor.h gcov-io.h
+bi_del.o: bi_del.c
+bi_new.o: bi_new.c
+bi_vdel.o: bi_vdel.c
+bi_vnew.o: bi_vnew.c
+bounds.o: bounds.c
+dummy.o: dummy.c
+ehfinit.o: ehfinit.s $(ASM386H)
+exceptio.o: exceptio.cc
+frame.o: frame.c
+main.o: main.c $(I)stdlib.h
+new.o: new.cc
+new1.o: new1.cc
+new2.o: new2.cc
+probe.o: probe.s $(ASM386H)
+purevirt.o: purevirt.c $(I)unistd.h $(I)io.h
+setnewha.o: setnewha.c
+tinfo.o: tinfo.cc tinfo.h
+tinfo2.o: tinfo2.cc tinfo.h
+
+eh.o: eh.c
+	$(GCC) $(GCCFLAGS) -fexceptions -c ../eh.c
+
+udivsi3.o: udivsi3.s $(ASM386H)
+divsi3.o: divsi3.s $(ASM386H)
+fixdfsi.o: fixdfsi.s $(ASM386H)
+fixudfdi.o: fixudfdi.s $(ASM386H)
+fixudfsi.o: fixudfsi.c
+fixusfdi.o: fixusfdi.s $(ASM386H)
+fixuxfdi.o: fixuxfdi.s $(ASM386H)
+muldi3.o: muldi3.s $(ASM386H)
+cmpdi2.o: cmpdi2.s $(ASM386H)
+ucmpdi2.o: ucmpdi2.s $(ASM386H)
+lldiv.o: lldiv.c $(I)stdlib.h
+ulldiv.o: ulldiv.s $(ASM386H)
+divdi3.o: divdi3.c $(I)stdlib.h
+moddi3.o: moddi3.c $(I)stdlib.h
+udivdi3.o: udivdi3.c $(I)stdlib.h
+umoddi3.o: umoddi3.c $(I)stdlib.h
+
+$(LIBGCC): bb.o bi_del.o bi_new.o bi_vdel.o bi_vnew.o \
+    bounds.o dummy.o eh.o ehfinit.o exceptio.o frame.o main.o \
+    new.o new1.o new2.o \
+    probe.o purevirt.o setnewha.o tinfo.o tinfo2.o \
+    udivsi3.o divsi3.o \
+    fixdfsi.o fixudfdi.o fixudfsi.o fixusfdi.o fixuxfdi.o \
+    muldi3.o udivdi3.o divdi3.o moddi3.o umoddi3.o cmpdi2.o ucmpdi2.o \
+    lldiv.o ulldiv.o
+	$(AR) r $(LIBGCC) *.o
Index: trunk/src/emx/src/lib/Attic/gcc/moddi3.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/moddi3.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/moddi3.c	(revision 18)
@@ -0,0 +1,8 @@
+/* moddi3.c (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+long long __moddi3 (long long x, long long y)
+{
+  return _lldiv (x, y).rem;
+}
Index: trunk/src/emx/src/lib/Attic/gcc/new.cc
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/new.cc	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/new.cc	(revision 18)
@@ -0,0 +1,31 @@
+// Implementation file for the -*- C++ -*- dynamic memory management header.
+// Copyright (C) 1996 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA. 
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#pragma implementation "new"
+#include "new"
+
+const nothrow_t nothrow = { };
Index: trunk/src/emx/src/lib/Attic/gcc/new1.cc
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/new1.cc	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/new1.cc	(revision 18)
@@ -0,0 +1,54 @@
+// Support routine for the -*- C++ -*- dynamic memory management.
+// Copyright (C) 1997 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA. 
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#include "new"
+
+extern "C" void *malloc (size_t);
+
+typedef void (*vfp)(void);
+extern vfp __new_handler;
+extern void __default_new_handler (void);
+
+void *operator new (size_t sz, const nothrow_t&) throw()
+{
+  void *p;
+  vfp handler = __new_handler;
+
+  /* malloc (0) is unpredictable; avoid it.  */
+  if (sz == 0)
+    sz = 1;
+  p = (void *) malloc (sz);
+  while (p == 0)
+    {
+      if (! handler)
+	return 0;
+      (*handler) ();
+      p = (void *) malloc (sz);
+    }
+  
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/gcc/new2.cc
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/new2.cc	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/new2.cc	(revision 18)
@@ -0,0 +1,33 @@
+// Support routine for the -*- C++ -*- dynamic memory management.
+// Copyright (C) 1997 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA. 
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#include "new"
+
+void *operator new[] (size_t sz, const nothrow_t& nothrow) throw()
+{
+  return ::operator new(sz, nothrow);
+}
Index: trunk/src/emx/src/lib/Attic/gcc/purevirt.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/purevirt.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/purevirt.c	(revision 18)
@@ -0,0 +1,12 @@
+/* purevirt.c */
+
+#include <unistd.h>
+#include <io.h>
+
+void __pure_virtual (void)
+{
+  static char msg[] = "Pure virtual method called\n";
+
+  _write (STDERR_FILENO, msg, sizeof (msg) - 1);
+  _exit (255);
+}
Index: trunk/src/emx/src/lib/Attic/gcc/setnewha.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/setnewha.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/setnewha.c	(revision 18)
@@ -0,0 +1,84 @@
+/* setnewha.c
+   Extracted from libgcc2.c and modified by Eberhard Mattes, Aug 1995 */
+
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+#include <unistd.h>
+
+/* set_new_handler (fvoid_t *) and the default new handler, described in
+   17.3.3.2 and 17.3.3.5.  These functions define the result of a failure
+   to allocate the amount of memory requested from operator new or new []. */
+
+#ifndef inhibit_libc
+/* This gets us __GNU_LIBRARY__.  */
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
+#include <stdio.h>
+
+#ifdef __GNU_LIBRARY__
+  /* Avoid forcing the library's meaning of `write' on the user program
+     by using the "internal" name (for use within the library)  */
+#define write(fd, buf, n)	__write((fd), (buf), (n))
+#endif
+#ifdef EMX
+#include <io.h>
+#define write(fd, buf, n)	_write((fd), (buf), (n))
+#define set_new_handler		_set_new_handler
+#endif /* EMX */
+#endif /* inhibit_libc */
+
+typedef void (*vfp)(void);
+void __default_new_handler (void);
+
+vfp __new_handler = (vfp)0;
+
+vfp
+set_new_handler (vfp handler)
+{
+  vfp prev_handler;
+
+  prev_handler = __new_handler;
+  if (handler == 0) handler = __default_new_handler;
+  __new_handler = handler;
+  return prev_handler;
+}
+
+#define MESSAGE "Virtual memory exceeded in `new'\n"
+
+void
+__default_new_handler ()
+{
+#ifndef inhibit_libc
+  /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
+  /* This should really print the name of the program, but that is hard to
+     do.  We need a standard, clean way to get at the name.  */
+  write (2, MESSAGE, sizeof (MESSAGE));
+#endif
+  /* don't call exit () because that may call global destructors which
+     may cause a loop.  */
+  _exit (-1);
+}
Index: trunk/src/emx/src/lib/Attic/gcc/tinfo.cc
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/tinfo.cc	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/tinfo.cc	(revision 18)
@@ -0,0 +1,125 @@
+// Methods for type_info for -*- C++ -*- Run Time Type Identification.
+// Copyright (C) 1994, 1996 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA. 
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#include <stddef.h>
+#include "tinfo.h"
+#include "new"			// for placement new
+
+// This file contains the minimal working set necessary to link with code
+// that uses virtual functions and -frtti but does not actually use RTTI
+// functionality.
+
+type_info::
+~type_info ()
+{ }
+
+extern "C" void
+__rtti_class (void *addr, const char *name,
+	      const __class_type_info::base_info *bl, size_t bn)
+{ new (addr) __class_type_info (name, bl, bn); }
+
+extern "C" void
+__rtti_si (void *addr, const char *n, const type_info *ti)
+{
+  new (addr) __si_type_info
+    (n, static_cast <const __user_type_info &> (*ti));
+}
+
+extern "C" void
+__rtti_user (void *addr, const char *name)
+{ new (addr) __user_type_info (name); }
+
+// dynamic_cast helper methods.
+// Returns a pointer to the desired sub-object or 0.
+
+void * __user_type_info::
+dcast (const type_info& to, int, void *addr, const type_info *, void *) const
+{ return (*this == to) ? addr : 0; }
+
+void * __si_type_info::
+dcast (const type_info& to, int require_public, void *addr,
+       const type_info *sub, void *subptr) const
+{
+  if (*this == to)
+    return addr;
+  return base.dcast (to, require_public, addr, sub, subptr);
+}
+
+void* __class_type_info::
+dcast (const type_info& desired, int is_public, void *objptr,
+       const type_info *sub, void *subptr) const
+{
+  if (*this == desired)
+    return objptr;
+
+  void *match_found = 0;
+  for (int i = 0; i < n_bases; i++)
+    {
+      if (is_public && base_list[i].access != PUBLIC)
+	continue;
+
+      void *p = (char *)objptr + base_list[i].offset;
+      if (base_list[i].is_virtual)
+	p = *(void **)p;
+      p = base_list[i].base->dcast (desired, is_public, p, sub, subptr);
+      if (p)
+	{
+	  if (match_found == 0)
+	    match_found = p;
+	  else if (match_found != p)
+	    {
+	      if (sub)
+		{
+		  // Perhaps we're downcasting from *sub to desired; see if
+		  // subptr is a subobject of exactly one of {match_found,p}.
+
+		  const __user_type_info &d =
+		    static_cast <const __user_type_info &> (desired);
+
+		  void *os = d.dcast (*sub, 1, match_found);
+		  void *ns = d.dcast (*sub, 1, p);
+
+		  if (os == ns)
+		    /* ambiguous -- subptr is a virtual base */;
+		  else if (os == subptr)
+		    continue;
+		  else if (ns == subptr)
+		    {
+		      match_found = p;
+		      continue;
+		    }
+		}
+
+	      // base found at two different pointers,
+	      // conversion is not unique
+	      return 0;
+	    }
+	}
+    }
+
+  return match_found;
+}
Index: trunk/src/emx/src/lib/Attic/gcc/tinfo.h
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/tinfo.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/tinfo.h	(revision 18)
@@ -0,0 +1,55 @@
+// RTTI support internals for -*- C++ -*-
+// Copyright (C) 1994, 1995, 1996 Free Software Foundation
+
+#include "typeinfo"
+
+// Class declarations shared between the typeinfo implementation files.
+
+// type_info for a class with no base classes (or an enum).
+
+struct __user_type_info : public type_info {
+  __user_type_info (const char *n) : type_info (n) {}
+
+  // If our type can be converted to the desired type, 
+  // return the pointer, adjusted accordingly; else return 0.
+  virtual void* dcast (const type_info &, int, void *,
+		       const type_info * = 0, void * = 0) const;
+};
+
+// type_info for a class with one public, nonvirtual base class.
+
+class __si_type_info : public __user_type_info {
+  const __user_type_info &base;
+
+public:
+  __si_type_info (const char *n, const __user_type_info &b)
+    : __user_type_info (n), base (b) { }
+
+  virtual void *dcast (const type_info &, int, void *,
+		       const type_info * = 0, void * = 0) const;
+};
+
+// type_info for a general class.
+
+typedef unsigned int USItype	__attribute__ ((mode (SI)));
+
+struct __class_type_info : public __user_type_info {
+  enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 };
+
+  struct base_info {
+    const __user_type_info *base;
+    USItype offset: 29;
+    bool is_virtual: 1;
+    access access: 2;
+  };
+
+  const base_info *base_list;
+  size_t n_bases;
+
+  __class_type_info (const char *name, const base_info *bl, size_t bn)
+    : __user_type_info (name), base_list (bl), n_bases (bn) {}
+
+  // This is a little complex.
+  virtual void* dcast (const type_info &, int, void *,
+		       const type_info * = 0, void * = 0) const;
+};
Index: trunk/src/emx/src/lib/Attic/gcc/tinfo2.cc
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/tinfo2.cc	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/tinfo2.cc	(revision 18)
@@ -0,0 +1,323 @@
+// Methods for type_info for -*- C++ -*- Run Time Type Identification.
+// Copyright (C) 1994, 1996 Free Software Foundation
+
+// This file is part of GNU CC.
+
+// GNU CC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// GNU CC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GNU CC; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA. 
+
+// As a special exception, if you link this library with other files,
+// some of which are compiled with GCC, to produce an executable,
+// this library does not by itself cause the resulting executable
+// to be covered by the GNU General Public License.
+// This exception does not however invalidate any other reasons why
+// the executable file might be covered by the GNU General Public License.
+
+#include <stddef.h>
+#include "tinfo.h"
+#include "new"			// for placement new
+
+// service function for comparing types by name.
+
+static inline int
+fast_compare (const char *n1, const char *n2) {
+  int c;
+  if (n1 == n2) return 0;
+  if (n1 == 0) return *n2;
+  else if (n2 == 0) return *n1;
+
+  c = (int)*n1++ - (int)*n2++;
+  return c == 0 ? strcmp (n1, n2) : c;
+};
+
+bool
+type_info::before (const type_info &arg) const
+{
+  return fast_compare (name (), arg.name ()) < 0;
+}
+
+#ifdef _WIN32
+bool type_info::
+operator== (const type_info& arg) const
+{
+  return fast_compare (name (), arg.name ()) == 0;
+}
+
+bool type_info::
+operator!= (const type_info& arg) const
+{
+  return fast_compare (name (), arg.name ()) != 0;
+}
+#endif
+
+// type info for pointer type.
+
+struct __pointer_type_info : public type_info {
+  const type_info& type;
+
+  __pointer_type_info (const char *n, const type_info& ti)
+    : type_info (n), type (ti) {}
+};
+
+// type info for attributes
+
+struct __attr_type_info : public type_info {
+  enum cv { NONE = 0, CONST = 1, VOLATILE = 2, CONSTVOL = 1 | 2 };
+
+  const type_info& type;
+  cv attr;
+
+  __attr_type_info (const char *n, cv a, const type_info& t)
+    : type_info (n), type (t), attr (a) {}
+};
+
+// type_info for builtin type
+
+struct __builtin_type_info : public type_info {
+  __builtin_type_info (const char *n): type_info (n) {}
+};
+
+// type info for function.
+
+struct __func_type_info : public type_info {
+  __func_type_info (const char *n) : type_info (n) {}
+};
+
+// type info for pointer to member function.
+
+struct __ptmf_type_info : public type_info {
+  __ptmf_type_info (const char *n) : type_info (n) {}
+};
+
+// type info for pointer to data member.
+
+struct __ptmd_type_info : public type_info {
+  __ptmd_type_info (const char *n): type_info (n) {}
+};
+
+// type info for array.
+
+struct __array_type_info : public type_info {
+  __array_type_info (const char *n): type_info (n) {}
+};
+
+// Entry points for the compiler.
+
+/* Low level match routine used by compiler to match types of catch
+   variables and thrown objects.  */
+
+extern "C" void*
+__throw_type_match_rtti (void *catch_type_r, void *throw_type_r, void *objptr)
+{
+  const type_info &catch_type = *(const type_info *)catch_type_r;
+  const type_info &throw_type = *(const type_info *)throw_type_r;
+  
+  if (catch_type == throw_type)
+    return objptr;
+  
+#if 0
+  printf ("We want to match a %s against a %s!\n",
+	  throw_type.name (), catch_type.name ());
+#endif
+
+  void *new_objptr = 0;
+
+  if (const __user_type_info *p
+      = dynamic_cast <const __user_type_info *> (&throw_type))
+    {
+      /* The 1 skips conversions to private bases. */
+      new_objptr = p->dcast (catch_type, 1, objptr);
+    }
+  else if (const __pointer_type_info *fr =
+	   dynamic_cast <const __pointer_type_info *> (&throw_type))
+    {
+      const __pointer_type_info *to =
+	   dynamic_cast <const __pointer_type_info *> (&catch_type);
+
+      if (! to)
+	goto fail;
+
+      const type_info *subfr = &fr->type, *subto = &to->type;
+      __attr_type_info::cv cvfrom, cvto;
+
+      if (const __attr_type_info *at
+	  = dynamic_cast <const __attr_type_info *> (subfr))
+	{
+	  cvfrom = at->attr;
+	  subfr = &at->type;
+	}
+      else
+	cvfrom = __attr_type_info::NONE;
+      
+      if (const __attr_type_info *at
+	  = dynamic_cast <const __attr_type_info *> (subto))
+	{
+	  cvto = at->attr;
+	  subto = &at->type;
+	}
+      else
+	cvto = __attr_type_info::NONE;
+
+      if (((cvfrom & __attr_type_info::CONST)
+	   > (cvto & __attr_type_info::CONST))
+	  || ((cvfrom & __attr_type_info::VOLATILE)
+	      > (cvto & __attr_type_info::VOLATILE)))
+	goto fail;
+
+      if (*subto == *subfr)
+	new_objptr = objptr;
+      else if (*subto == typeid (void)
+	       && dynamic_cast <const __func_type_info *> (subfr) == 0)
+	new_objptr = objptr;
+      else if (const __user_type_info *p
+	       = dynamic_cast <const __user_type_info *> (subfr))
+	{
+	  /* The 1 skips conversions to private bases. */
+	  new_objptr = p->dcast (*subto, 1, objptr);
+	}
+      else if (const __pointer_type_info *pfr
+	       = dynamic_cast <const __pointer_type_info *> (subfr))
+	{
+	  // Multi-level pointer conversion.
+
+	  const __pointer_type_info *pto
+	    = dynamic_cast <const __pointer_type_info *> (subto);
+
+	  if (! pto)
+	    goto fail;
+	    
+	  bool constp = (cvto & __attr_type_info::CONST);
+	  for (subto = &pto->type, subfr = &pfr->type; ;
+	       subto = &pto->type, subfr = &pfr->type)
+	    {
+	      if (const __attr_type_info *at
+		  = dynamic_cast <const __attr_type_info *> (subfr))
+		{
+		  cvfrom = at->attr;
+		  subfr = &at->type;
+		}
+	      else
+		cvfrom = __attr_type_info::NONE;
+      
+	      if (const __attr_type_info *at
+		  = dynamic_cast <const __attr_type_info *> (subto))
+		{
+		  cvto = at->attr;
+		  subto = &at->type;
+		}
+	      else
+		cvto = __attr_type_info::NONE;
+
+	      if (((cvfrom & __attr_type_info::CONST)
+		   > (cvto & __attr_type_info::CONST))
+		  || ((cvfrom & __attr_type_info::VOLATILE)
+		      > (cvto & __attr_type_info::VOLATILE)))
+		goto fail;
+
+	      if (! constp
+		  && (((cvfrom & __attr_type_info::CONST)
+		       < (cvto & __attr_type_info::CONST))
+		      || ((cvfrom & __attr_type_info::VOLATILE)
+			  < (cvto & __attr_type_info::VOLATILE))))
+		goto fail;
+
+	      if (*subto == *subfr)
+		{
+		  new_objptr = objptr;
+		  break;
+		}
+
+	      pto = dynamic_cast <const __pointer_type_info *> (subto);
+	      pfr = dynamic_cast <const __pointer_type_info *> (subfr);
+	      if (! pto || ! pfr)
+		goto fail;		
+
+	      if (! (cvto & __attr_type_info::CONST))
+		constp = false;
+	    }
+	}
+    }
+ fail:
+
+#if 0
+  if (new_objptr)
+    printf ("It converts, delta is %d\n", new_objptr-objptr);
+#endif
+  return new_objptr;
+}
+
+/* Called from __cp_pop_exception.  Is P the type_info node for a pointer
+   of some kind?  */
+
+bool
+__is_pointer (void *p)
+{
+  const type_info *t = reinterpret_cast <const type_info *>(p);
+  const __pointer_type_info *pt =
+    dynamic_cast <const __pointer_type_info *> (t);
+  return pt != 0;
+}
+
+extern "C" void
+__rtti_ptr (void *addr, const char *n, const type_info *ti)
+{ new (addr) __pointer_type_info (n, *ti); }
+
+extern "C" void
+__rtti_attr (void *addr, const char *n, int attrval, const type_info *ti)
+{
+  new (addr) __attr_type_info
+    (n, static_cast <__attr_type_info::cv> (attrval), *ti);
+}
+
+extern "C" void
+__rtti_func (void *addr, const char *name)
+{ new (addr) __func_type_info (name); }
+
+extern "C" void
+__rtti_ptmf (void *addr, const char *name)
+{ new (addr) __ptmf_type_info (name); }
+
+extern "C" void
+__rtti_ptmd (void *addr, const char *name)
+{ new (addr) __ptmd_type_info (name); }
+
+extern "C" void
+__rtti_array (void *addr, const char *name)
+{ new (addr) __array_type_info (name); }
+
+extern "C" void *
+__dynamic_cast (const type_info& (*from)(void), const type_info& (*to)(void),
+		int require_public, void *address,
+		const type_info & (*sub)(void), void *subptr)
+{
+  return static_cast <const __user_type_info &> (from ()).dcast
+    (to (), require_public, address, &(sub ()), subptr);
+}
+
+// type_info nodes and functions for the builtin types.  The mangling here
+// must match the mangling in gcc/cp/rtti.c.
+
+#define BUILTIN(mangled)					\
+unsigned char __ti##mangled [sizeof (__builtin_type_info)]	\
+  __attribute__ ((aligned (__alignof__ (void *))));		\
+extern "C" const type_info &__tf##mangled (void) {		\
+  if ((*(void **) __ti##mangled) == 0)				\
+    new (__ti##mangled) __builtin_type_info (#mangled);		\
+  return *(type_info *)__ti##mangled;				\
+}
+
+BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b);
+BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f);
+BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc);
Index: trunk/src/emx/src/lib/Attic/gcc/udivdi3.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/udivdi3.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/udivdi3.c	(revision 18)
@@ -0,0 +1,8 @@
+/* udivdi3.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+unsigned long long __udivdi3 (unsigned long long x, unsigned long long y)
+{
+  return _ulldiv (x, y).quot;
+}
Index: trunk/src/emx/src/lib/Attic/gcc/umoddi3.c
===================================================================
--- trunk/src/emx/src/lib/Attic/gcc/umoddi3.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/gcc/umoddi3.c	(revision 18)
@@ -0,0 +1,8 @@
+/* umoddi3.c (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+unsigned long long __umoddi3 (unsigned long long x, unsigned long long y)
+{
+  return _ulldiv (x, y).rem;
+}
Index: trunk/src/emx/src/lib/Attic/graph/ega.h
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/ega.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/ega.h	(revision 18)
@@ -0,0 +1,23 @@
+/* ega.h (emx+gcc) -- Copyright (c) 1994 by Steffen Haecker */
+
+extern unsigned short _g_out[];
+
+#define MASK(X) \
+  _outp8 (0x3cf, X)
+
+#define OUT1(X) \
+  _outp16 (0x3ce, X)
+
+#define OUT2(X,Y) \
+  _g_out[0] = X; \
+  _g_out[1] = Y; \
+  _outps16 (0x3ce, _g_out, 2)
+
+#define OUT3(X,Y,Z) \
+  _g_out[0] = X; \
+  _g_out[1] = Y; \
+  _g_out[2] = Z; \
+  _outps16 (0x3ce, _g_out, 3)
+
+#define BITPLANE(X) \
+  _outp8 (0x3cf, X)
Index: trunk/src/emx/src/lib/Attic/graph/egaclear.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/egaclear.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/egaclear.c	(revision 18)
@@ -0,0 +1,14 @@
+/* egaclear.c (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes */
+
+#include <memory.h>
+#include <sys/hw.h>
+#include "graph2.h"
+#include "ega.h"
+
+
+void _ega_clear (int color)
+{
+  OUT3 (color << 8, 0x0f01, 0xff08);
+  memset (_g_mem, 0, (_g_xsize / 8) * _g_ysize);
+  OUT2 (0xff08, 0x0001);
+}
Index: trunk/src/emx/src/lib/Attic/graph/egaget.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/egaget.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/egaget.c	(revision 18)
@@ -0,0 +1,37 @@
+/* egaget.c (emx+gcc) -- Copyright (c) 1994 by Steffen Haecker */
+
+#include <stdlib.h>
+#include <sys/hw.h>
+#include "graph2.h"
+#include "ega.h"
+
+
+int _ega_get (unsigned x, unsigned y)
+{
+  int ret;
+  unsigned char mask, *p;
+
+  if (x >= _g_clipx0 && x <= _g_clipx1 && y >= _g_clipy0 && y <= _g_clipy1)
+    {
+      ret = 0;
+      mask = 0x80 >> (x & 7);
+      p = _g_mem + (y * 80 + x / 8);
+      GLOCK;
+      OUT1 (0x0304);            /* BITPLANE (3); */
+      if (*p & mask)
+        ret |= 8;
+      BITPLANE (2);
+      if (*p & mask)
+        ret |= 4;
+      BITPLANE (1);
+      if (*p & mask)
+        ret |= 2;
+      BITPLANE (0);
+      if (*p & mask)
+        ++ret;
+      GUNLOCK;
+      return ret;
+    }
+  else
+    return -1;
+}
Index: trunk/src/emx/src/lib/Attic/graph/egahline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/egahline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/egahline.c	(revision 18)
@@ -0,0 +1,40 @@
+/* egahline.c (emx+gcc) -- Copyright (c) 1994 by Steffen Haecker */
+
+#include <stdlib.h>
+#include <memory.h>
+#include <sys/hw.h>
+#include "graph2.h"
+#include "ega.h"
+
+
+void _ega_hline (unsigned x, unsigned y, unsigned n, int color)
+{
+  unsigned x1, length;
+  unsigned char lmask, rmask;
+  volatile unsigned char *p;
+
+  x1 = x + n - 1;
+  p = _g_mem + y * 80 + x / 8;
+  length = x1 / 8 - x / 8;
+  lmask = 0xff >> (x & 7);
+  rmask = 0xff << (7 - (x1 & 7));
+  if (length == 0)
+    lmask &= rmask;
+  GLOCK;
+  OUT3 (color << 8, 0x0f01, (lmask << 8) | 8);
+  ++(*p);
+  if (length > 0)
+    {
+      --length; ++p;
+      if (length > 0)
+        {
+          MASK (0xff);
+          memset ((void *)p, 0, length);
+          p += length;
+        }
+      MASK (rmask);
+      ++(*p);
+    }
+  OUT2 (0xff08, 0x0001);
+  GUNLOCK;
+}
Index: trunk/src/emx/src/lib/Attic/graph/egaline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/egaline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/egaline.c	(revision 18)
@@ -0,0 +1,87 @@
+/* egaline.c (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/hw.h>
+#include "graph2.h"
+#include "ega.h"
+
+void _ega_line (int x0, int y0, int x1, int y1, int color)
+{
+  if (_gline_clip (x0, y0, &x1, &y1) && _gline_clip (x1, y1, &x0, &y0))
+    {
+      int dx, dy, temp, iy, n, e;
+      volatile unsigned char *p;
+      unsigned char mask, accu;
+
+      dx = x1 - x0;
+      if (dx < 0)
+        {
+          dx = -dx;
+          temp = x1; x1 = x0; x0 = temp;
+          temp = y1; y1 = y0; y0 = temp;
+        }
+      ++dx;
+      dy = y1 - y0; iy = _g_xsize / 8;
+      if (dy < 0)
+        {
+          dy = -dy;
+          iy = -iy;
+        }
+      ++dy;
+      GLOCK;
+      OUT3 (color << 8, 0x0f01, 0x0008);
+      p = _g_mem + (_g_xsize / 8) * y0 + (x0 / 8);
+      mask = 0x80 >> (x0 & 7);
+      if (dx >= dy)
+        {
+          n = dx; e = dy / 2;
+          accu = 0;
+          do
+            {
+              accu |= mask;
+              if (mask == 0x01)
+                {
+                  MASK (accu); ++(*p); accu = 0;
+                  mask = 0x80; ++p;
+                }
+              else
+                mask >>= 1;
+              e += dy;
+              if (e >= dx)
+                {
+                  e -= dx;
+                  MASK (accu); ++(*p); accu = 0;
+                  p += iy;
+                }
+            } while (--n != 0);
+          if (accu != 0)
+            {
+              MASK (accu); ++(*p);
+            }
+        }
+      else
+        {
+          n = dy; e = dx / 2;
+          MASK (mask);
+          do
+            {
+              ++(*p);
+              p += iy;
+              e += dx;
+              if (e >= dy)
+                {
+                  e -= dy;
+                  if (mask == 0x01)
+                    {
+                      mask = 0x80; ++p;
+                    }
+                  else
+                    mask >>= 1;
+                  MASK (mask);
+                }
+            } while (--n != 0);
+        }
+      OUT2 (0xff08, 0x0001);
+      GUNLOCK;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/graph/egaset.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/egaset.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/egaset.c	(revision 18)
@@ -0,0 +1,22 @@
+/* egaset.c (emx+gcc) -- Copyright (c) 1994 by Steffen Haecker */
+
+#include <stdlib.h>
+#include <sys/hw.h>
+#include "graph2.h"
+#include "ega.h"
+
+
+void _ega_set (unsigned x, unsigned y, int color)
+{
+  volatile unsigned char *p;
+
+  if (x >= _g_clipx0 && x <= _g_clipx1 && y >= _g_clipy0 && y <= _g_clipy1)
+    {
+      GLOCK;
+      p = _g_mem + y * 80 + x / 8;
+      OUT2 (0x205, (0x8000 >> (x & 7)) | 8);
+      *p; *p = (unsigned char)color;
+      OUT2 (0xff00, 0x0005);
+      GUNLOCK;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/graph/egavline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/egavline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/egavline.c	(revision 18)
@@ -0,0 +1,24 @@
+/* egavline.c (emx+gcc) -- Copyright (c) 1994 by Steffen Haecker */
+
+#include <stdlib.h>
+#include <sys/hw.h>
+#include "graph2.h"
+#include "ega.h"
+
+
+void _ega_vline (unsigned x, unsigned y, unsigned n, int color)
+{
+  volatile unsigned char *p;
+
+  GLOCK;
+  OUT3 (color << 8, 0x0f01, (0x8000 >> (x & 7)) | 8);
+  p = _g_mem + (y * 80 + x / 8);
+  while (n > 0)
+    {
+      ++(*p);
+      p += 80;
+      --n;
+    }
+  OUT2 (0xff08, 1);
+  GUNLOCK;
+}
Index: trunk/src/emx/src/lib/Attic/graph/gbox.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gbox.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gbox.c	(revision 18)
@@ -0,0 +1,68 @@
+/* gbox.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#define INCL_VIO
+#include <os2emx.h>
+#include "graph2.h"
+
+void g_box (int x0, int y0, int x1, int y1, int color, int fill_flag)
+{
+  int temp, dx, dy;
+
+  if (y0 > y1)
+    {
+      temp = y0; y0 = y1; y1 = temp;
+    }
+  if (x0 > x1)
+    {
+      temp = x0; x0 = x1; x1 = temp;
+    }
+  if (x0 > _g_clipx1 || x1 < _g_clipx0 || y0 > _g_clipy1 || y1 < _g_clipy0)
+    return;
+  if (fill_flag)
+    {
+      if (y0 < _g_clipy0)
+        y0 = _g_clipy0;
+      if (y1 > _g_clipy1)
+        y1 = _g_clipy1;
+      if (x0 < _g_clipx0)
+        x0 = _g_clipx0;
+      if (x1 > _g_clipx1)
+        x1 = _g_clipx1;
+      GLOCK;
+      if (x1-x0 >= 3 || y1-y0 <= 4)
+        {
+          for (; y0 <= y1; ++y0)
+            g_hline (y0, x0, x1, color);
+        }
+      else
+        {
+          for (; x0 <= x1; ++x0)
+            g_vline (x0, y0, y1, color);
+        }
+      GUNLOCK;
+    }
+  else
+    {
+      dx = x1-x0; dy = y1-y0;
+      if (dx == 0)
+        g_vline (x0, y0, y1, color);
+      else if (dy == 0)
+        g_hline (y0, x0, x1, color);
+      else
+        {
+          if (dx != 1 || dy == 1)
+            {
+              g_hline (y0, x0, x1, color);
+              g_hline (y1, x0, x1, color);
+              ++y0; --y1;
+            }
+          if (dy != 1)
+            {
+              g_vline (x0, y0, y1, color);
+              g_vline (x1, y0, y1, color);
+            }
+        }
+    }
+}
Index: trunk/src/emx/src/lib/Attic/graph/gclear.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gclear.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gclear.c	(revision 18)
@@ -0,0 +1,24 @@
+/* gclear.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#include "graph2.h"
+
+
+static void _no_clear (int color)
+{
+}
+
+
+static void (*_j_clear) (int color) = _no_clear;
+
+void g_clear (int color)
+{
+  GLOCK;
+  _j_clear (color);
+  GUNLOCK;
+}
+
+
+GPRIM_DEF (clear);
+GPRIM_ALL (clear);
Index: trunk/src/emx/src/lib/Attic/graph/gclip.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gclip.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gclip.c	(revision 18)
@@ -0,0 +1,25 @@
+/* gclip.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#include "graph2.h"
+
+void g_clip (int x0, int y0, int x1, int y1)
+{
+  if (x0 < 0)
+    _g_clipx0 = 0;
+  else
+    _g_clipx0 = x0;
+  if (y0 < 0)
+    _g_clipy0 = 0;
+  else
+    _g_clipy0 = y0;
+  if (x1 >= _g_xsize)
+    _g_clipx1 = _g_xsize - 1;
+  else
+    _g_clipx1 = x1;
+  if (y1 >= _g_ysize)
+    _g_clipy1 = _g_ysize - 1;
+  else
+    _g_clipy1 = y1;
+}
Index: trunk/src/emx/src/lib/Attic/graph/gellipse.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gellipse.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gellipse.c	(revision 18)
@@ -0,0 +1,258 @@
+/* gellipse.c (emx+gcc) -- Copyright (c) 1987-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#define INCL_VIO
+#include <os2emx.h>
+#include "graph2.h"
+
+static void gcirfx (int cx, int cy, int rx, int ry, int color)
+{
+  int x, y, r, x1, y1, oy, ox, y0, qr, qx, qy, z;
+
+  r = rx + 1;
+  x = r - 1; y = 0; qy = 0; qx = x * x; qr = r * r;
+  ox = -1; oy = -1; y0 = -1;
+  for (;;)
+    {
+      z = y * ry; y1 = z / rx;
+      z = x * ry; x1 = z / rx;
+      if (y1 != oy)
+        {
+          g_hline (cy-y1, cx-x, cx+x, color);
+          if (y1 != 0)    /* draw diameter only once */
+            g_hline (cy+y1, cx-x, cx+x, color);
+        }
+      if (x1 != ox)
+        {
+          if (y0 != -1 && y1 < ox)
+            {
+              g_hline (cy-ox, cx-y0, cx+y0, color);
+              g_hline (cy+ox, cx-y0, cx+y0, color);
+            }
+        }
+      oy = y1; ox = x1; y0 = y;
+      if (x <= y)
+        break;
+      qy = qy + 2 * y + 1;
+      ++y;
+      if (qx+qy > qr)
+        {
+          qx = qx - 2 * x + 1;
+          --x;
+        }
+    }
+}
+
+
+static void gcirpx (int cx, int cy, int rx, int ry, int color)
+{
+  int x, y, r, x1, y1, oy, ox, y0, x2, y2, qr, qx, qy, z;
+
+  r = rx + 1;
+  x = r - 1; y = 0; qy = 0; qx = x * x; qr = r * r;
+  ox = -1; oy = -1; y0 = -1; x2 = rx; y2 = 0;
+  for (;;)
+    {
+      z = y * ry; y1 = z / rx;
+      z = x * ry; x1 = z / rx;
+      if (y1 != oy)
+        {
+          if (x > x2)
+            {
+              g_set (cx-x, cy-y1, color);
+              g_set (cx+x, cy-y1, color);
+              if (y1 != 0)  /* set these points only once */
+                {
+                  g_set (cx-x, cy+y1, color);
+                  g_set (cx+x, cy+y1, color);
+                }
+            }
+          else
+            {
+              g_hline (cy-y1, cx-x, cx-x2, color);
+              g_hline (cy-y1, cx+x, cx+x2, color);
+              if (y1 != 0)   /* set these 'points' only once */
+                {
+                  g_hline (cy+y1, cx-x, cx-x2, color);
+                  g_hline (cy+y1, cx+x, cx+x2, color);
+                }
+            }
+          x2 = x-1;
+        }
+      if (x1 != ox)
+        {
+          if (y0 != -1 && y1 < ox)
+            {
+              g_hline (cy-ox, cx-y0, cx-y2, color);
+              g_hline (cy+ox, cx-y0, cx-y2, color);
+              if (y2 == 0)  /* draw the dots only once */
+                y2 = 1;
+              g_hline (cy-ox, cx+y0, cx+y2, color);
+              g_hline (cy+ox, cx+y0, cx+y2, color);
+              y2 = y0+1;
+            }
+        }
+      oy = y1; ox = x1; y0 = y;
+      if (x <= y)
+        break;
+      qy = qy + 2 * y + 1;
+      ++y;
+      if (qx+qy > qr)
+        {
+          qx = qx - 2 * x + 1;
+          --x;
+        }
+    }
+  if (x2 >= y2)
+    {
+      g_hline (cy-y1, cx-y2, cx-x2, color);
+      g_hline (cy-y1, cx+y2, cx+x2, color);
+      if (y1 != 0)
+        {
+          g_hline (cy+y1, cx-y2, cx-x2, color);
+          g_hline (cy+y1, cx+y2, cx+x2, color);
+        }
+    }
+}
+
+
+static void gcirfy (int cx, int cy, int rx, int ry, int color)
+{
+  int x, y, r, x1, y1, oy, ox, x0, qr, qx, qy, z;
+
+  r = ry + 1;
+  x = r - 1; y = 0; qy = 0; qx = x * x; qr = r * r;
+  ox = -1; oy = -1; x0 = -1;
+  for (;;)
+    {
+      z = y * rx; y1 = z / ry;
+      z = x * rx; x1 = z / ry;
+      if (x != ox)
+        {
+          g_hline (cy-x, cx-y1, cx+y1, color);
+          g_hline (cy+x, cx-y1, cx+y1, color);
+        }
+      if (y != oy)
+        {
+          if (x0 != -1 && x > oy)
+            {
+              g_hline (cy-oy, cx-x0, cx+x0, color);
+              if (oy != 0)   /* draw diameter only once */
+                g_hline (cy+oy, cx-x0, cx+x0, color);
+            }
+        }
+      ox = x; oy = y; x0 = x1;
+      if (x <= y)
+        break;
+      qy = qy + 2 * y + 1;
+      ++y;
+      if (qx+qy > qr)
+        {
+          qx = qx - 2 * x + 1;
+          --x;
+        }
+    }
+}
+
+
+static void gcirpy (int cx, int cy, int rx, int ry, int color)
+{
+  int x, y, r, x1, y1, oy, ox, y0, x2, y2, qr, qx, qy, z;
+
+  r = ry + 1;
+  x = r - 1; y = 0; qy = 0; qx = x * x; qr = r * r;
+  ox = -1; oy = -1; y0 = -1; x2 = rx; y2 = 0;
+  for (;;)
+    {
+      z = y * rx; y1 = z / ry;
+      z = x * rx; x1 = z / ry;
+      if (y1 != oy)
+        {
+          if (x > x2)
+            {
+              g_set (cx-y1, cy-x, color);
+              g_set (cx-y1, cy+x, color);
+              if (y1 != 0)  /* set these points only once */
+                {
+                  g_set (cx+y1, cy-x, color);
+                  g_set (cx+y1, cy+x, color);
+                }
+            }
+          else
+            {
+              g_vline (cx-y1, cy-x, cy-x2, color);
+              g_vline (cx-y1, cy+x, cy+x2, color);
+              if (y1 != 0)   /* set these 'points' only once */
+                {
+                  g_vline (cx+y1, cy-x, cy-x2, color);
+                  g_vline (cx+y1, cy+x, cy+x2, color);
+                }
+            }
+          x2 = x-1;
+        }
+      if (x1 != ox)
+        {
+          if (y0 != -1 && y1 < ox)
+            {
+              g_vline (cx-ox, cy-y0, cy-y2, color);
+              g_vline (cx+ox, cy-y0, cy-y2, color);
+              if (y2 == 0)  /* draw the dots only once */
+                y2 = 1;
+              g_vline (cx-ox, cy+y0, cy+y2, color);
+              g_vline (cx+ox, cy+y0, cy+y2, color);
+              y2 = y0+1;
+            }
+        }
+      oy = y1; ox = x1; y0 = y;
+      if (x <= y)
+        break;
+      qy = qy + 2 * y + 1;
+      ++y;
+      if (qx+qy > qr)
+        {
+          qx = qx - 2 * x + 1;
+          --x;
+        }
+    }
+  if (x2 >= y2)
+    {
+      g_vline (cx-y1, cy-y2, cy-x2, color);
+      g_vline (cx-y1, cy+y2, cy+x2, color);
+      if (y1 != 0)
+        {
+          g_vline (cx+y1, cy-y2, cy-x2, color);
+          g_vline (cx+y1, cy+y2, cy+x2, color);
+        }
+    }
+}
+
+
+void g_ellipse (int cx, int cy, int rx, int ry, int color, int fill_flag)
+{
+  if (rx == 0 && ry == 0)
+    g_set (cx, cy, color);
+  else if (rx == 0)
+    g_vline (cx, cy-ry, cy+ry, color);
+  else if (ry == 0)
+    g_hline (cy, cx-rx, cx+rx, color);
+  else
+    {
+      GLOCK;
+      if (rx >= ry)
+        {
+          if (fill_flag)
+            gcirfx (cx, cy, rx, ry, color);
+          else
+            gcirpx (cx, cy, rx, ry, color);
+        }
+      else
+        {
+          if (fill_flag)
+            gcirfy (cx, cy, rx, ry, color);
+          else
+            gcirpy (cx, cy, rx, ry, color);
+        }
+      GUNLOCK;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/graph/gget.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gget.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gget.c	(revision 18)
@@ -0,0 +1,22 @@
+/* gget.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#include "graph2.h"
+
+static int _no_get (unsigned x, unsigned y)
+{
+  return -1;
+}
+
+
+static int (*_j_get) (unsigned x, unsigned y) = _no_get;
+
+int g_get (int x, int y)
+{
+  return _j_get (x, y);
+}
+
+
+GPRIM_DEF (get);
+GPRIM_ALL (get);
Index: trunk/src/emx/src/lib/Attic/graph/ghline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/ghline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/ghline.c	(revision 18)
@@ -0,0 +1,57 @@
+/* ghline.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#include "graph2.h"
+
+void _no_hline (unsigned x, unsigned y, unsigned n, int color)
+{
+}
+
+
+static void (*_j_hline) (unsigned x, unsigned y, unsigned n, int color)
+     = _no_hline;
+
+
+void g_hline (int y, int x0, int x1, int color)
+{
+  int f, n;
+
+  if (y >= _g_clipy0 && y <= _g_clipy1)
+    {
+      f = 1;
+      if (x0 < _g_clipx0)
+        {
+          x0 = _g_clipx0; --f;
+        }
+      if (x1 < _g_clipx0)
+        {
+          if (f == 0)
+            return;
+          x1 = _g_clipx0;
+        }
+      f = 1;
+      if (x0 > _g_clipx1)
+        {
+          x0 = _g_clipx1; --f;
+        }
+      if (x1 > _g_clipx1)
+        {
+          if (f == 0)
+            return;
+          x1 = _g_clipx1;
+        }
+      if (x0 <= x1)
+        n = x1 - x0 + 1;
+      else
+        {
+          n = x0 - x1 + 1;
+          x0 = x1;
+        }
+      _j_hline (x0, y, n, color);
+    }
+}
+
+
+GPRIM_DEF (hline);
+GPRIM_ALL (hline);
Index: trunk/src/emx/src/lib/Attic/graph/gline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gline.c	(revision 18)
@@ -0,0 +1,59 @@
+/* gline.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#include "graph2.h"
+
+
+static int round (int n)
+{
+  if (n & 1)
+    return n/2+1;
+  else
+    return n/2;
+}
+
+
+int _gline_clip (int x1, int y1, int *x2p, int *y2p)
+{
+  if (*y2p < _g_clipy0 && y1 >= _g_clipy0)
+    {
+      *x2p = x1 + round (2 * (_g_clipy0 - y1) * (*x2p - x1) / (*y2p - y1));
+      *y2p = _g_clipy0;
+    }
+  else if (*y2p > _g_clipy1 && y1 <= _g_clipy1)
+    {
+      *x2p = x1 + round (2 * (_g_clipy1 - y1) * (*x2p - x1) / (*y2p - y1));
+      *y2p = _g_clipy1;
+    }
+  if (*x2p < _g_clipx0 && x1 >= _g_clipx0)
+    {
+      *y2p = y1 + round (2 * (_g_clipx0 - x1) * (*y2p - y1) / (*x2p - x1));
+      *x2p = _g_clipx0;
+    }
+  else if (*x2p > _g_clipx1 && x1 <= _g_clipx1)
+    {
+      *y2p = y1 + round (2* (_g_clipx1 - x1) * (*y2p - y1) / (*x2p - x1));
+      *x2p = _g_clipx1;
+    }
+  return (*x2p >= _g_clipx0 && *x2p <= _g_clipx1
+          && *y2p >= _g_clipy0 && *y2p <= _g_clipy1);
+}
+
+
+static void _no_line (int x0, int y0, int x1, int y1, int color)
+{
+}
+
+
+static void (*_j_line) (int x0, int y0, int x1, int y1, int color) = _no_line;
+
+
+void g_line (int x0, int y0, int x1, int y1, int color)
+{
+  _j_line (x0, y0, x1, y1, color);
+}
+
+
+GPRIM_DEF (line);
+GPRIM_ALL (line);
Index: trunk/src/emx/src/lib/Attic/graph/gpolygon.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gpolygon.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gpolygon.c	(revision 18)
@@ -0,0 +1,252 @@
+/* gpolygon.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#define INCL_VIO
+#include <os2emx.h>
+#include "graph2.h"
+
+struct dda
+{
+  int n, m;
+  int e, x, y;
+  int xi, yi;
+  int c;
+};
+
+struct line
+{
+  int x0, y0, x1, y1;
+  int y;
+};
+
+struct seg
+{
+  int x0, x1, i;
+};
+
+
+static int cmpx (const void *p1, const void *p2)
+{
+  const struct seg *s1, *s2;
+  int n1, n2;
+
+  s1 = p1; s2 = p2;
+  n1 = s1->x0;
+  n2 = s2->x0;
+  if (n1 == n2)
+    {
+      n1 = s1->x1;
+      n2 = s2->x1;
+    }
+  if (n1 < n2)
+    return -1;
+  else if (n1 > n2)
+    return 1;
+  else
+    return 0;
+}
+
+
+static void gpolyfill (const int *x, const int *y, int n, int color)
+{
+  int y1;
+  struct line lt;
+  struct dda dt;
+  int i, j1, j2, k, t, m;
+  int x1, x2;
+  struct dda *dda;
+  struct seg *seg;
+  struct line *line;
+
+  dda = alloca (n * sizeof (*dda));
+  seg = alloca (n * sizeof (*seg));
+  line = alloca (n * sizeof (*line));
+  /* initialize line descriptors */
+  y1 = y[0];
+  for (i = 0; i < n; ++i)
+    {
+      lt.x0 = x[i];
+      lt.y0 = y[i];
+      if (i < n-1)
+        {
+          lt.x1 = x[i+1];
+          lt.y1 = y[i+1];
+        }
+      else
+        {
+          lt.x1 = x[0];
+          lt.y1 = y[0];
+        }
+      if (lt.y0 > lt.y1)
+        {
+          t = lt.x0; lt.x0 = lt.x1; lt.x1 = t;
+          t = lt.y0; lt.y0 = lt.y1; lt.y1 = t;
+        }
+      if (lt.y0 < y1)
+        y1 = lt.y0;
+      line[i] = lt;
+    }
+  /* initialize DDAs */
+  for (i = 0; i < n; ++i)
+    {
+      lt = line[i];
+      dt.y = lt.y0;
+      dt.x = lt.x0;
+      dt.n = 1 + abs (lt.y1 - lt.y0);
+      dt.m = 1 + abs (lt.x1 - lt.x0);
+      if (lt.y1 > lt.y0)
+        dt.yi = 1;
+      else
+        dt.yi = -1;
+      if (lt.x1 > lt.x0)
+        dt.xi = 1;
+      else
+        dt.xi = -1;
+      if (dt.n > dt.m)
+        {
+          dt.c = dt.n;
+          dt.e = dt.m/2;
+        }
+      else
+        {
+          dt.c = dt.m;
+          dt.e = dt.n/2;
+        }
+      dda[i] = dt;
+      lt.y = lt.y0-1;
+      line[i] = lt;
+    }
+  /* one iteration per scan line */
+  for (;;)
+    {
+      m = 0;
+      /* find intersection of lines with scan line */
+      for (i = 0; i < n; ++i)
+        {
+          if (line[i].y == y1-1)
+            {
+              dt = dda[i];
+              if (dt.c < 1)
+                line[i].y = y1 - 2;
+              else
+                {
+                  line[i].y = dt.y;
+                  x1 = dt.x;
+                  if (dt.n > dt.m)
+                    {
+                      x2 = dt.x;
+                      --dt.c;
+                      dt.y += dt.yi;
+                      dt.e += dt.m;
+                      if (dt.e >= dt.n)
+                        {
+                          dt.e -= dt.n;
+                          dt.x += dt.xi;
+                        }
+                    }
+                  else
+                    {
+                      for (;;)
+                        {
+                          --dt.c;
+                          dt.x += dt.xi;
+                          dt.e += dt.n;
+                          if (dt.e >= dt.m)
+                            {
+                              dt.e -= dt.m;
+                              dt.y += dt.yi;
+                              break;
+                            }
+                        }
+                      x2 = dt.x - dt.xi;
+                    }
+                  dda[i] = dt;
+                  if (x1 < x2)
+                    {
+                      seg[m].x0 = x1;
+                      seg[m].x1 = x2;
+                    }
+                  else
+                    {
+                      seg[m].x0 = x2;
+                      seg[m].x1 = x1;
+                    }
+                  if (y1 == line[i].y0 || y1 == line[i].y1)
+                    seg[m].i = i;
+                  else
+                    seg[m].i = -1;
+                  ++m;
+                }
+            }
+        }
+      /* find vertices to be removed */
+      if (m == 0)
+        break;
+      for (i = 0; i < m; ++i)
+        if (seg[i].i >= 0)
+          {
+            if (i < m-1)
+              k = i + 1;
+            else
+              k = 0;
+            if (seg[k].i >= 0)
+              {
+                j1 = seg[i].i;
+                j2 = seg[k].i;
+                t = abs(j1-j2);
+                if (t == 1 || t == n-1)
+                  /* segments of two adjacent line */
+                  if ((y1 == line[j1].y0) != (y1 == line[j2].y0))
+                    /* it's not a `v' or `^' corner */
+                    if (line[j1].y0 != line[j1].y1 &&
+                        line[j2].y0 != line[j2].y1)
+                      /* no horizontal line */
+                      {
+                        if (seg[k].x0 < seg[i].x0)
+                          seg[i].x0 = seg[k].x0;
+                        if (seg[k].x1 > seg[i].x1)
+                          seg[i].x1 = seg[k].x1;
+                        seg[i].i = -1; /* ignore */
+                        seg[k].i = -2; /* remove */
+                      }
+              }
+          }
+      /* remove line segments */
+      for (i = 0; i < m;)
+        if (seg[i].i == -2)
+          seg[i] = seg[--m];
+        else
+          ++i;
+      /* draw line segments */
+      if (m >= 2)
+        qsort (seg, m, sizeof (struct seg), cmpx);
+      for (i = 0; i+1 < m; i += 2)
+        g_hline (y1, seg[i].x0, seg[i+1].x1, color);
+      ++y1;
+    }
+}
+
+
+void g_polygon (const int *x, const int *y, int n, int color, int fill_flag)
+{
+  int i;
+
+  if (n >= 3)
+    {
+      GLOCK;
+      if (fill_flag)
+        gpolyfill (x, y, n, color);
+      else
+        {
+          for (i = 0; i < n-1; ++i)
+            g_line (x[i], y[i], x[i+1], y[i+1], color);
+          g_line (x[n-1], y[n-1], x[0], y[0], color);
+        }
+      GUNLOCK;
+    }
+  else if (n == 2)
+    g_line (x[0], y[0], x[1], y[1], color);
+  else if (n == 1)
+    g_set (x[0], y[0], color);
+}
Index: trunk/src/emx/src/lib/Attic/graph/graph1.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/graph1.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/graph1.c	(revision 18)
@@ -0,0 +1,341 @@
+/* graph1.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#include <dos.h>
+#include <memory.h>
+#include <sys/hw.h>
+#define INCL_DOSMEMMGR
+#define INCL_DOSPROCESS
+#define INCL_VIO
+#include <os2emx.h>
+#include <os2thunk.h>
+#include "graph2.h"
+
+#define FALSE 0
+#define TRUE  1
+
+static int graph_mode = 0;
+static int setmode = 0;
+static int old_mode_number = 3;
+static int _g_save_saved = 0;
+static int _g_save_planes = 0;
+static int _g_save_segsize = 0;
+
+#if 0
+static void *_g_save_buf = NULL;
+#endif
+
+static VIOMODEINFO old_vio_mode;
+static VIOMODEINFO new_vio_mode;
+static VIOPHYSBUF phys;
+
+int g_xsize = 1;
+int g_ysize = 1;
+int g_colors = 1;
+
+int _g_xsize = 1;
+int _g_ysize = 1;
+int _g_colors = 1;
+
+int _g_clipx0 = 0;
+int _g_clipy0 = 0;
+int _g_clipx1 = 0;
+int _g_clipy1 = 0;
+
+int _g_locklevel = 0;
+
+unsigned char *_g_mem = NULL;
+
+unsigned short _g_out[3];
+
+/* This is required by emxomf to define the symbol. */
+__asm__ (".stabs \"__j_graph\", 21, 0, 0, 0xffffffff");
+
+extern int _j_graph[];
+
+static int g_mode_on (int width, int height, int mode_number);
+static void g_mode_off (void);
+static void g_mode_ega (void);
+static void g_mode_vgl (void);
+static void g_init2 (void);
+static void g_mode_s (void);
+static void set_jumps (int mode);
+
+
+int _ggetmode (void)
+{
+  union REGS r;
+
+  r.h.ah = 0x0f;
+  _int86 (0x10, &r, &r);
+  return r.h.al;
+}
+
+
+void _gsetmode (int mode)
+{
+  union REGS r;
+
+  r.h.ah = 0x00;
+  r.h.al = (unsigned char)mode;
+  _int86 (0x10, &r, &r);
+}
+
+
+void g_wmode (int wmode)
+{
+}
+
+
+void g_lock (void)
+{
+  BYTE not_locked;
+
+  if (_osmode == OS2_MODE && _g_locklevel == 0)
+    {
+      ++_g_locklevel;
+      VioScrLock (LOCKIO_WAIT, &not_locked, 0);
+    }
+}
+
+
+void g_unlockall (void)
+{
+  if (_g_locklevel != 0)
+    {
+      _g_locklevel = 1;
+      g_unlock ();
+    }
+}
+
+
+void g_unlock (void)
+{
+  if (_osmode == OS2_MODE && _g_locklevel > 0)
+    {
+      --_g_locklevel;
+      if (_g_locklevel == 0)
+        VioScrUnLock (0);
+    }
+}
+
+
+int g_modeset (int mode, int flag)
+{
+  g_xsize = g_ysize = g_colors = 1; setmode = 0;
+  switch (mode)
+    {
+    case G_MODE_EGA_C:
+      g_xsize = 640; g_ysize = 200; g_colors = 16; setmode = 14;
+      break;
+    case G_MODE_EGA_E:
+      g_xsize = 640; g_ysize = 350; g_colors = 16; setmode = 16;
+      break;
+    case G_MODE_VGA_H:
+      g_xsize = 640; g_ysize = 480; g_colors = 16; setmode = 18;
+      break;
+    case G_MODE_VGA_L:
+      g_xsize = 320; g_ysize = 200; g_colors = 256; setmode = 19;
+      break;
+    default:
+      mode = G_MODE_OFF;
+      break;
+    }
+  return mode;
+}
+
+
+int g_mode (int mode)
+{
+  g_unlockall ();
+  if (mode == G_MODE_OFF)
+    {
+      if (graph_mode != 0)
+        {
+          g_mode_off ();
+          graph_mode = 0;
+        }
+      return FALSE;
+    }
+  else
+    {
+      g_mode (G_MODE_OFF);
+      g_lock ();
+      if (_osmode == OS2_MODE)
+        {
+          _g_save_saved = 0;
+          old_vio_mode.cb = sizeof (old_vio_mode);
+          VioGetMode (&old_vio_mode, 0);
+        }
+      else
+        old_mode_number = _ggetmode ();
+      mode = g_modeset (mode, G_SET_KEEP);
+      if (setmode == 0)
+        {
+          g_unlock ();
+          return FALSE;
+        }
+      _g_xsize = g_xsize; _g_ysize = g_ysize; _g_colors = g_colors;
+      _g_clipx0 = 0; _g_clipx1 = _g_xsize - 1;
+      _g_clipy0 = 0; _g_clipy1 = _g_ysize - 1;
+      switch (setmode)
+        {
+        case 14:                /* G_MODE_EGA_C */
+        case 16:                /* G_MODE_EGA_E */
+        case 18:                /* G_MODE_VGA_H */
+          _g_save_planes = 4;
+          _g_save_segsize = (_g_xsize / 8) * _g_ysize;
+          if (!g_mode_on (80, 25, setmode))
+            {
+              g_unlock ();
+              return FALSE;
+            }
+          g_mode_ega ();
+          break;
+        case 19:    /* G_MODE_VGA_L */
+          _g_save_planes = 1;
+          _g_save_segsize = _g_xsize * _g_ysize;
+          if (!g_mode_on (40, 25, setmode))
+            {
+              g_unlock ();
+              return FALSE;
+            }
+          g_mode_vgl ();
+          break;
+        }
+      g_wmode (G_NORM);
+      graph_mode = setmode;
+      g_init2 ();
+      g_mode_s ();
+      if (_osmode == OS2_MODE)
+        g_clear (G_BLACK);
+      g_unlock ();
+      return TRUE;
+    }
+}
+
+
+static int g_mode_on (int width, int height, int mode_number)
+{
+  if (_osmode == OS2_MODE)
+    {
+#if 0
+      TID tid;
+
+      if (DosAllocMem (&_g_save_buf, _g_save_planes * _g_save_segsize,
+                       PAG_COMMIT|PAG_READ|PAG_WRITE|OBJ_TILE))
+        return FALSE;
+      if (DosCreateThread (&tid, redraw_wait, 0, 2, 0x2000) != 0)
+        return FALSE;
+      if (DosCreateThread (&tid, mode_wait, 0, 2, 0x2000) != 0)
+        return FALSE;
+#endif
+      new_vio_mode = old_vio_mode;
+      switch (_g_colors)
+        {
+        case 4:
+          new_vio_mode.color = 2; break;
+        case 16:
+          new_vio_mode.color = 4; break;
+        case 256:
+          new_vio_mode.color = 8; break;
+        default:
+          if (setmode == 15 || setmode == 17)
+            new_vio_mode.color = 0;
+          else
+            new_vio_mode.color = 1;
+          break;
+        }
+      new_vio_mode.fbType = VGMT_OTHER | VGMT_GRAPHICS;
+      new_vio_mode.hres = _g_xsize;
+      new_vio_mode.vres = _g_ysize;
+      new_vio_mode.row = height;
+      new_vio_mode.col = width;
+      VioSetMode (&new_vio_mode, 0);
+      phys.pBuf = (PBYTE)0xa0000;
+      phys.cb = 0x10000;
+      if (VioGetPhysBuf (&phys, 0) != 0)
+        return FALSE;
+      _g_mem = MAKEP (phys.asel[0], 0);
+    }
+  else
+    {
+      if (_g_mem == NULL)
+        _g_mem = _memaccess (0xa0000, 0xaffff, 1);
+      if (_g_mem == NULL)
+        return FALSE;
+      _gsetmode (mode_number);
+    }
+  return TRUE;
+}
+
+
+static void g_mode_off (void)
+{
+  if (_osmode == OS2_MODE)
+    {
+      VioSetMode (&old_vio_mode, 0);
+#if 0
+      VioSavRedrawUndo (1, 1, 0);
+      VioModeUndo (1, 1, 0);
+      DosFreeMem (_g_save_buf);
+#endif
+    }
+  else
+    _gsetmode (old_mode_number);
+  set_jumps (0);
+}
+
+
+static void g_init2 (void)
+{
+}
+
+
+struct jentry
+{
+  int mode;
+  void **dst;
+  void *func;
+};
+
+
+static void set_jumps (int mode)
+{
+  const int *ip;
+  const struct jentry *p;
+
+  ip = &_j_graph[0];
+  if ((unsigned)*ip < 0x10000)  /* ld */
+    ++ip;
+  while (*ip != 0)
+    {
+      if (*ip != -1 && *ip != -2) /* ld, emxomf */
+        {
+          p = (const struct jentry *)*ip;
+          if (p->mode == mode)
+            *p->dst = p->func;
+        }
+      ++ip;
+    }
+}
+
+
+static void g_mode_ega (void)
+{
+  
+  _portaccess (0x3ce, 0x3cf);
+  set_jumps (GJ_EGA);
+}
+
+
+static void g_mode_vgl (void)
+{
+  set_jumps (GJ_VGL);
+}
+
+
+static void g_mode_s (void)
+{
+}
Index: trunk/src/emx/src/lib/Attic/graph/graph2.h
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/graph2.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/graph2.h	(revision 18)
@@ -0,0 +1,81 @@
+/* graph2.h (emx+gcc) */
+
+extern int _g_xsize;
+extern int _g_ysize;
+extern int _g_colors;
+extern int _g_pages;
+
+extern int _g_clipx0;
+extern int _g_clipy0;
+extern int _g_clipx1;
+extern int _g_clipy1;
+
+extern int _g_locklevel;
+
+extern unsigned char *_g_mem;
+
+int _ggetmode (void);
+void _gsetmode (int mode);
+
+int _gline_clip (int x1, int y1, int *x2p, int *y2p);
+
+
+#define GLOCK \
+  do \
+    if (_osmode == OS2_MODE && _g_locklevel == 0) \
+      { \
+        BYTE not_locked; \
+        VioScrLock (LOCKIO_WAIT, &not_locked, 0); \
+      } \
+    while (0)
+
+#define GUNLOCK \
+  do \
+    if (_osmode == OS2_MODE && _g_locklevel == 0) \
+      VioScrUnLock (0); \
+    while (0)
+
+
+#define GJ_VGL          1
+#define GJ_EGA          2
+
+/* A primitive table entry consists of 3 words:
+
+   o  the mode number (zero means default)
+   o  the address of the variable holding the function address
+   o  the address of the function implementing the primitive for the
+      mode.
+
+   The table must reside in the .text section as we use N_SETT|N_EXT
+   (23) to reference it.  Note that emxomf does not support N_SETD!
+   Therefore, the following macros should be used after a function
+   definition. */
+
+#define GPRIM_DEF(NAME)  GPRIM2 (NAME, 0, no)
+#define GPRIM_VGL(NAME)  GPRIM2 (NAME, 1, vgl)
+#define GPRIM_EGA(NAME)  GPRIM2 (NAME, 2, ega)
+
+#define GPRIM_ALL(NAME)  GPRIM_VGL (NAME); GPRIM_EGA (NAME)
+
+#define GPRIM2(NAME,NUMBER,PREFIX) \
+  __asm__ ("Lj_" #PREFIX "_" #NAME ": " \
+           ".int " #NUMBER ";" \
+           ".int __j_" #NAME ";" \
+           ".int __" #PREFIX "_" #NAME ";" \
+           ".stabs \"__j_graph\", 23, 0, 0, Lj_" #PREFIX "_" #NAME)
+
+
+/* Copied from os2emx.h */
+
+#if !defined (NULLHANDLE)
+
+typedef unsigned char BYTE;
+typedef unsigned short USHORT;
+typedef USHORT HVIO;
+
+#define LOCKIO_WAIT 1
+
+USHORT VioScrLock (USHORT fWait, BYTE *pfNotLocked, HVIO hvio);
+USHORT VioScrUnLock (HVIO hvio);
+
+#endif
Index: trunk/src/emx/src/lib/Attic/graph/gset.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gset.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gset.c	(revision 18)
@@ -0,0 +1,21 @@
+/* gset.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#include "graph2.h"
+
+static void _no_set (unsigned x, unsigned y, int color)
+{
+}
+
+
+static void (*_j_set) (unsigned x, unsigned y, int color) = _no_set;
+
+void g_set (int x, int y, int color)
+{
+  _j_set (x, y, color);
+}
+
+
+GPRIM_DEF (set);
+GPRIM_ALL (set);
Index: trunk/src/emx/src/lib/Attic/graph/gtriangl.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gtriangl.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gtriangl.c	(revision 18)
@@ -0,0 +1,265 @@
+/* gtriangl.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#define INCL_VIO
+#include <os2emx.h>
+#include "graph2.h"
+
+static void set3a (int x1, int y1, int x2, int y2, int x3, int y3, int color)
+{
+  int xl, xincl, errl, xdl, ydl;
+  int xr, xincr, errr, xdr, ydr;
+  int xxl, xxr, oxl, oxr, minx, maxx;
+  int y;
+
+  ydr = 1 + y3 - y1;
+  if (x1 < x3)
+    {
+      xincr = 1;
+      xdr = 1 + x3 - x1;
+    }
+  else
+    {
+      xincr = -1;
+      xdr = 1 + x1 - x3;
+    }
+  if (xdr <= ydr)
+    errr = xdr/2;
+  else
+    errr = ydr/2;
+  xl = x1;
+  xr = x1;
+
+  ydl = 1 + y2 - y1;
+  if (x1 < x2)
+    {
+      xincl = 1;
+      xdl = 1 + x2 - x1;
+    }
+  else
+    {
+      xincl = -1;
+      xdl = 1 + x1 - x2;
+    }
+  if (xdl <= ydl)
+    errl = xdl/2;
+  else
+    errl = ydl/2;
+
+  for (y = y1; y <= y2; ++y)
+    {
+      oxl = xl; oxr = xr;
+      if (xdl <= ydl)
+        {
+          xxl = xl;
+          errl += xdl;
+          if (errl >= ydl)
+            {
+              errl -= ydl;
+              xl += xincl;
+            }
+        }
+      else
+        for (;;)
+          {
+            xxl = xl;
+            xl += xincl;
+            errl += ydl;
+            if (errl >= xdl)
+              {
+                errl -= xdl;
+                break;
+              }
+          }
+      if (xdr <= ydr)
+        {
+          xxr = xr;
+          errr += xdr;
+          if (errr >= ydr)
+            {
+              errr -= ydr;
+              xr += xincr;
+            }
+        }
+      else
+        for (;;)
+          {
+            xxr = xr;
+            xr += xincr;
+            errr += ydr;
+            if (errr >= xdr)
+              {
+                errr -= xdr;
+                break;
+              }
+          }
+      if (oxl < oxr)
+        minx = oxl;
+      else
+        minx = oxr;
+      if (xxl < minx)
+        minx = xxl;
+      if (xxr < minx)
+        minx = xxr;
+      if (oxl > oxr)
+        maxx = oxl;
+      else
+        maxx = oxr;
+      if (xxl > maxx)
+        maxx = xxl;
+      if (xxr > maxx)
+        maxx = xxr;
+      g_hline (y, minx, maxx, color);
+    }
+
+  xl = x2;
+  ydl = 1 + y3 - y2;
+  if (x2 < x3)
+    {
+      xincl = 1;
+      xdl = 1 + x3 - x2;
+    }
+  else
+    {
+      xincl = -1;
+      xdl = 1 + x2 - x3;
+        }
+  if (xdl <= ydl)
+    errl = xdl/2;
+  else
+    errl = ydl/2;
+
+  if (xdl <= ydl)
+    {
+      errl += xdl;
+      if (errl >= ydl)
+        {
+          errl -= ydl;
+          xl += xincl;
+        }
+    }
+  else
+    for (;;)
+      {
+        xl += xincl;
+        errl += ydl;
+        if (errl >= xdl)
+          {
+            errl -= xdl;
+            break;
+          }
+      }
+
+  for (y = y2+1; y <= y3; ++y)
+    {
+      oxl = xl; oxr = xr;
+      if (xdl <= ydl)
+        {
+          xxl = xl;
+          errl += xdl;
+          if (errl >= ydl)
+            {
+              errl -= ydl;
+              xl += xincl;
+            }
+        }
+      else
+        for (;;)
+          {
+            xxl = xl;
+            xl += xincl;
+            errl += ydl;
+            if (errl >= xdl)
+              {
+                errl -= xdl;
+                break;
+              }
+          }
+      if (xdr <= ydr)
+        {
+          xxr = xr;
+          errr += xdr;
+          if (errr >= ydr)
+            {
+              errr -= ydr;
+              xr += xincr;
+            }
+        }
+      else
+        for (;;)
+          {
+            xxr = xr;
+            xr += xincr;
+            errr += ydr;
+            if (errr >= xdr)
+              {
+                errr -= xdr;
+                break;
+              }
+          }
+      if (oxl < oxr)
+        minx = oxl;
+      else
+        minx = oxr;
+      if (xxl < minx)
+        minx = xxl;
+      if (xxr < minx)
+        minx = xxr;
+      if (oxl > oxr)
+        maxx = oxl;
+      else
+        maxx = oxr;
+      if (xxl > maxx)
+        maxx = xxl;
+      if (xxr > maxx)
+        maxx = xxr;
+      g_hline (y, minx, maxx, color);
+    }
+}
+
+
+void g_triangle (int x1, int y1, int x2, int y2, int x3, int y3, int color,
+                 int fill_flag)
+{
+  int temp, xmin, xmax;
+
+  GLOCK;
+  if (fill_flag)
+    {
+      if (y1 > y2)
+        {
+          temp = y2; y2 = y1; y1 = temp;
+          temp = x2; x2 = x1; x1 = temp;
+        }
+      if (y1 > y3)
+        {
+          temp = y3; y3 = y1; y1 = temp;
+          temp = x3; x3 = x1; x1 = temp;
+        }
+      if (y2 > y3)
+        {
+          temp = y3; y3 = y2; y2 = temp;
+          temp = x3; x3 = x2; x2 = temp;
+        }
+      if (y1 == y3) /* y1 == y2 && y2 == y3 */
+        {
+          xmin = x1;
+          if (x2 < xmin) xmin = x2;
+          if (x3 < xmin) xmin = x3;
+          xmax = x1;
+          if (x2 > xmax) xmax = x2;
+          if (x3 > xmax) xmax = x3;
+          g_hline (y1, xmin, xmax, color);
+        }
+      else
+        set3a (x1, y1, x2, y2, x3, y3, color);
+    }
+  else
+    {
+      g_line (x3, y3, x1, y1, color);
+      g_line (x1, y1, x2, y2, color);
+      g_line (x2, y2, x3, y3, color);
+    }
+  GUNLOCK;
+}
Index: trunk/src/emx/src/lib/Attic/graph/gvgapal.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gvgapal.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gvgapal.c	(revision 18)
@@ -0,0 +1,31 @@
+/* gvgapal.c (emx+gcc) -- Copyright (c) 1987-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#define INCL_VIO
+#include <os2emx.h>
+#include "graph2.h"
+#include <sys/hw.h>
+
+static int port_flag = 0;
+
+void g_vgapal (const char *pal, int first, int n, int wait_flag)
+{
+  if (port_flag == 0)
+    {
+      if (_portaccess (0x3c8, 0x3c9) == 0 && _portaccess (0x3da, 0x3da) == 0)
+        port_flag = 1;
+      else
+        port_flag = -1;
+    }
+  if (port_flag == 1 && n >= 1 && first >= 0 && first <= 255
+      && first + n <= 256)
+    {
+      GLOCK;
+      if (wait_flag)
+        _wait01 (0x3da, 0x08);
+      _outp8 (0x3c8, first);
+      _outps8dac (0x3c9, pal, 3 * n);
+      GUNLOCK;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/graph/gvline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gvline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gvline.c	(revision 18)
@@ -0,0 +1,59 @@
+/* gvline.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#include "graph2.h"
+
+
+void _no_vline (unsigned x, unsigned y, unsigned n, int color)
+{
+}
+
+
+static void (*_j_vline) (unsigned x, unsigned y, unsigned n, int color)
+     = _no_vline;
+
+
+void g_vline (int x, int y0, int y1, int color)
+{
+  int f, n;
+
+  if (x >= _g_clipx0 && x <= _g_clipx1)
+    {
+      f = 1;
+      if (y0 < _g_clipy0)
+        {
+          y0 = _g_clipy0; --f; 
+        }
+      if (y1 < _g_clipy0)
+        {
+          if (f == 0)
+            return;
+          y1 = _g_clipy0;
+        }
+      f = 1;
+      if (y0 > _g_clipy1)
+        {
+          y0 = _g_clipy1; --f;
+        }
+      if (y1 > _g_clipy1)
+        {
+          if (f == 0)
+            return;
+          y1 = _g_clipy1;
+        }
+      if (y0 <= y1)
+        n = y1 - y0 + 1;
+      else
+        {
+          n = y0 - y1 + 1;
+          y0 = y1;
+        }
+      if (n > 0)
+        _j_vline (x, y0, n, color);
+    }
+}
+
+
+GPRIM_DEF (vline);
+GPRIM_ALL (vline);
Index: trunk/src/emx/src/lib/Attic/graph/gwaitv.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/gwaitv.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/gwaitv.c	(revision 18)
@@ -0,0 +1,27 @@
+/* gwaitv.c (emx+gcc) -- Copyright (c) 1987-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <graph.h>
+#define INCL_VIO
+#include <os2emx.h>
+#include "graph2.h"
+#include <sys/hw.h>
+
+static int port_flag = 0;
+
+void g_waitv (void)
+{
+  if (port_flag == 0)
+    {
+      if (_portaccess (0x3da, 0x3da) == 0)
+        port_flag = 1;
+      else
+        port_flag = -1;
+    }
+  if (port_flag == 1)
+    {
+     GLOCK;
+     _wait01 (0x3da, 0x08);
+      GUNLOCK;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/graph/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/makefile	(revision 18)
@@ -0,0 +1,59 @@
+#
+# /emx/src/lib/graph/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+
+.PHONY: clean default dstlib graph
+
+LIBGRAPH=$(L)graph.a
+
+LIBC_CCFLAGS = -fomit-frame-pointer
+
+default: graph
+
+graph .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(LIBGRAPH)
+
+clean:
+	-del $(CPU)\*.o $(DELOPT)
+
+graph1.o: graph1.c $(I)graph.h graph2.h
+gbox.o: gbox.c $(I)graph.h graph2.h
+gclear.o: gclear.c $(I)graph.h graph2.h
+gclip.o: gclip.c $(I)graph.h graph2.h
+gellipse.o: gellipse.c $(I)graph.h graph2.h
+gget.o: gget.c $(I)graph.h graph2.h
+ghline.o: ghline.c $(I)graph.h graph2.h
+gline.o: gline.c $(I)graph.h graph2.h
+gpolygon.o: gpolygon.c $(I)graph.h graph2.h
+gset.o: gset.c $(I)graph.h graph2.h
+gtriangl.o: gtriangl.c $(I)graph.h graph2.h
+gvgapal.o: gvgapal.c $(I)graph.h graph2.h
+gvline.o: gvline.c $(I)graph.h graph2.h
+gwaitv.o: gwaitv.c $(I)graph.h graph2.h
+
+egaclear.o: egaclear.c graph2.h ega.h
+egaget.o: egaget.c graph2.h ega.h
+egahline.o: egahline.c graph2.h ega.h
+egaline.o: egaline.c graph2.h ega.h
+egavline.o: egavline.c graph2.h ega.h
+egaset.o: egaset.c graph2.h ega.h
+
+vglclear.o: vglclear.c graph2.h
+vglget.o: vglget.c graph2.h
+vglhline.o: vglhline.c graph2.h
+vglline.o: vglline.c graph2.h
+vglvline.o: vglvline.c graph2.h
+vglset.o: vglset.c graph2.h
+
+$(LIBGRAPH): graph1.o gbox.o gclear.o gclip.o gellipse.o gget.o ghline.o \
+    gline.o gpolygon.o gset.o gtriangl.o gvgapal.o gvline.o gwaitv.o \
+    egaclear.o egaget.o egahline.o egaline.o egaset.o egavline.o \
+    vglclear.o vglget.o vglhline.o vglline.o vglset.o vglvline.o
+	-del $(LIBGRAPH)
+	$(AR) r $(LIBGRAPH) *.o
Index: trunk/src/emx/src/lib/Attic/graph/vglclear.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/vglclear.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/vglclear.c	(revision 18)
@@ -0,0 +1,9 @@
+/* vglclear.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <memory.h>
+#include "graph2.h"
+
+void _vgl_clear (int color)
+{
+  memset (_g_mem, color, _g_xsize * _g_ysize);
+}
Index: trunk/src/emx/src/lib/Attic/graph/vglget.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/vglget.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/vglget.c	(revision 18)
@@ -0,0 +1,20 @@
+/* vglget.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "graph2.h"
+
+
+int _vgl_get (unsigned x, unsigned y)
+{
+  int ret;
+
+  if (x >= _g_clipx0 && x <= _g_clipx1 && y >= _g_clipy0 && y <= _g_clipy1)
+    {
+      GLOCK;
+      ret = _g_mem[x + y * _g_xsize];
+      GUNLOCK;
+      return ret;
+    }
+  else
+    return -1;
+}
Index: trunk/src/emx/src/lib/Attic/graph/vglhline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/vglhline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/vglhline.c	(revision 18)
@@ -0,0 +1,13 @@
+/* vglhline.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <memory.h>
+#include "graph2.h"
+
+
+void _vgl_hline (unsigned x, unsigned y, unsigned n, int color)
+{
+  GLOCK;
+  memset (_g_mem + y * 320 + x, color, n);
+  GUNLOCK;
+}
Index: trunk/src/emx/src/lib/Attic/graph/vglline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/vglline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/vglline.c	(revision 18)
@@ -0,0 +1,62 @@
+/* vglline.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "graph2.h"
+
+void _vgl_line (int x0, int y0, int x1, int y1, int color)
+{
+  if (_gline_clip (x0, y0, &x1, &y1) && _gline_clip (x1, y1, &x0, &y0))
+    {
+      int dx, dy, temp, iy, n, e;
+      unsigned char *p;
+
+      dx = x1 - x0;
+      if (dx < 0)
+        {
+          dx = -dx;
+          temp = x1; x1 = x0; x0 = temp;
+          temp = y1; y1 = y0; y0 = temp;
+        }
+      ++dx;
+      dy = y1 - y0; iy = 320;
+      if (dy < 0)
+        {
+          dy = -dy;
+          iy = -iy;
+        }
+      ++dy;
+      GLOCK;
+      p = _g_mem + x0 + 320 * y0;
+      if (dx >= dy)
+        {
+          n = dx; e = dy / 2;
+          do
+            {
+              *p = (unsigned char)color;
+              ++p;
+              e += dy;
+              if (e >= dx)
+                {
+                  e -= dx;
+                  p += iy;
+                }
+            } while (--n != 0);
+        }
+      else
+        {
+          n = dy; e = dx / 2;
+          do
+            {
+              *p = (unsigned char)color;
+              p += iy;
+              e += dx;
+              if (e >= dy)
+                {
+                  e -= dy;
+                  ++p;
+                }
+            } while (--n != 0);
+        }
+      GUNLOCK;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/graph/vglset.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/vglset.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/vglset.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vglset.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "graph2.h"
+
+
+void _vgl_set (unsigned x, unsigned y, int color)
+{
+  if (x >= _g_clipx0 && x <= _g_clipx1 && y >= _g_clipy0 && y <= _g_clipy1)
+    {
+      GLOCK;
+      _g_mem[x + y * _g_xsize] = (unsigned char)color;
+      GUNLOCK;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/graph/vglvline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/graph/vglvline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/graph/vglvline.c	(revision 18)
@@ -0,0 +1,20 @@
+/* vglvline.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "graph2.h"
+
+
+void _vgl_vline (unsigned x, unsigned y, unsigned n, int color)
+{
+  volatile unsigned char *p;
+
+  GLOCK;
+  p = _g_mem + x + 320 * y;
+  while (n > 0)
+    {
+      *p = (unsigned char)color;
+      p += 320;
+      --n;
+    }
+  GUNLOCK;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/calloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/calloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/calloc.c	(revision 18)
@@ -0,0 +1,18 @@
+/* calloc.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+
+void *calloc (size_t elements, size_t size)
+{
+  size_t bytes;
+  void *p;
+
+  bytes = elements * size;
+  if (size != 0 && bytes / size != elements) /* Check for overflow */
+    return NULL;
+  p = malloc (bytes);
+  if (p != NULL)
+    memset (p, 0, bytes);
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/expand.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/expand.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/expand.c	(revision 18)
@@ -0,0 +1,154 @@
+/* expand.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "malloc1.h"
+
+/* Try to expand a block in place.  MEM points to the start of the
+   block, SIZE is the new size.  Shrinking the size of a block always
+   succeeds.  Return MEM on success.  Return NULL on failure (the
+   block has been made as big as possible). */
+
+void *_expand (void *mem, size_t size)
+{
+  void *p;
+
+  HEAP_LOCK;
+  p = _expand2 (mem, size, TRUE, FALSE);
+  HEAP_UNLOCK;
+  return p;
+}
+
+
+/* Try to expand a block in place.  The heap must be locked before
+   calling this function.  If EXPAND_HEAP is zero, expanding the heap
+   is not allowed.  Shrinking the size of a block always succeeds.
+   Return MEM on success.  Return NULL on failure (the block has been
+   made as big as possible). */
+
+void *_expand2 (void *mem, size_t size, int expand_heap, int tile)
+{
+  msize_t in_use, len, xlen;
+  maddr_t a;
+  mheader_t *base, *block;
+  void *p;
+
+  /* Sanity-check the SIZE argument. */
+
+  if (size > MAX_SIZE)
+    return NULL;
+
+  /* Round up SIZE to a multiple of 4. */
+
+  size = ROUNDUP (size);
+
+  /* When tiling, check whether the block can be expanded in place
+     without crossing a 64K boundary. */
+
+  if (tile)
+    {
+      a = ADDR (mem);
+      if ((a & 0xffff) != 0 && (a & 0xffff) + size > 0x10000)
+        return NULL;
+    }
+
+  /* Let base point to the block header and read the block header.  We
+     need only the in-use bit of the block header */
+
+  base = mem;
+  --base;
+  in_use = base->size;
+
+  /* Jump here after expanding the heap.  Collaps free blocks starting
+     at MEM (which is included). */
+
+restart:
+  base->size &= ~MF_FLAGS;      /* Mark block temporarily in-use */
+  len = base->size;             /* Get the length of the block */
+
+  /* Collaps free blocks following block MEM.  len will be set to the
+     size of block MEM plus the combined size of all the free blocks
+     following block MEM. */
+
+  for (;;)
+    {
+      block = MHEADER ((char *)base + MHEADER_SIZE + len);
+      if (block == _malloc_rover)
+        _malloc_rover = base;   /* avoid invalid _malloc_rover */
+      xlen = block->size;
+      if (!(xlen & MF_FREE))    /* block in use? */
+        break;                  /* yes -> end of contiguous area */
+      len += MHEADER_SIZE + SIZE (xlen);
+    }
+
+  /* If the size of the block (plus the combined size of the free
+     blocks) is big enough, we won. */
+
+  if (len >= size)
+    goto success;
+
+  /* Set the length of block MEM to the combined size of MEM and the
+     following free blocks.  That's how big we can make the block
+     without relocating it.  Restore the in-use bit. */
+
+  base->size = SIZE (len) | (in_use & MF_FREE);
+
+  /* If the block isn't the last block of the heap or if we aren't
+     allowed to expand the heap, fail. */
+
+  if (block->size != END_OF_HEAP || !expand_heap)
+    return NULL;
+
+  /* Expand the heap as much as required to accomodate for the
+     requested block size, but round the size of the heap up to the
+     next multiple of the page size. */
+
+  xlen = (size - len + MHEADER_SIZE + 0xfff) & ~0xfff;
+  p = _sbrk (xlen);
+
+  /* Fail if expanding the heap failed. */
+
+  if (p == (void *)(-1))
+    return NULL;
+
+  /* Fail if someone has used brk() or sbrk() to change the size of
+     the data segment.  This heap implementation requires a contiguous
+     heap. */
+
+  if (p != _malloc_top + 1)
+    return NULL;
+
+  /* Turn the new heap space into a free block and adjust the pointer
+     to the end of the heap.  Then restart.  As the free blocks have
+     been collapsed, the second pass will be quick. */
+
+  _malloc_top->size = (xlen - MHEADER_SIZE) | MF_FREE;
+  _malloc_top = MHEADER ((char *)_malloc_top + xlen);
+  _malloc_top->size = END_OF_HEAP;
+  goto restart;
+
+  /* The size of block MEM plus the combined size of the free blocks
+     following MEM is big enough to serve the request.  Split the
+     combined block into two blocks: block MEM of size SIZE and
+     optionally a free block following MEM. */
+
+success:
+
+  /* Create a free block if there's enough space left.  Otherwise
+     assign the bytes left over to block MEM. */
+
+  if (len - size > MHEADER_SIZE)
+    {
+      block = MHEADER ((char *)base + MHEADER_SIZE + size);
+      block->size = (len - size - MHEADER_SIZE) | MF_FREE;
+      len = size;
+    }
+
+  /* Set the size of block MEM and restore the in-use bit. */
+
+  base->size = SIZE (len) | (in_use & MF_FREE);
+
+  /* Return MEM. */
+
+  ++base;
+  return base;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/free.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/free.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/free.c	(revision 18)
@@ -0,0 +1,14 @@
+/* free.c (emx+gcc) -- Copyright (c) 1990-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "malloc1.h"
+
+void free (void *mem)
+{
+  if (mem != NULL)
+    {
+      HEAP_LOCK;
+      FREE (mem);
+      HEAP_UNLOCK;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/heapchk.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/heapchk.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/heapchk.c	(revision 18)
@@ -0,0 +1,97 @@
+/* heapchk.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <emx/startup.h>
+#include "malloc1.h"
+
+static int dummy;
+
+#define HEAP_NO_FILL 0xf7dc6a4e /* illegal fill value */
+
+static int _heapset2 (unsigned fill);
+
+
+int _heapchk (void)
+{
+  return _heapset (HEAP_NO_FILL);
+}
+
+
+int _heapset (unsigned fill)
+{
+  int r;
+
+  HEAP_LOCK;
+  r = _heapset2 (fill);
+  HEAP_UNLOCK;
+  return r;
+}
+
+
+static int _heapset2 (unsigned fill)
+{
+  mheader_t *p, *last;
+  msize_t len;
+  maddr_t next;
+  int met_rover;
+
+  met_rover = 0;
+  if (_malloc_rover == NULL && _malloc_bottom == NULL && _malloc_top == NULL)
+    return _HEAPEMPTY;
+  if (_malloc_rover == NULL || _malloc_bottom == NULL || _malloc_top == NULL)
+    return _HEAPBADBEGIN;
+  if (ADDR (_malloc_bottom) >= ADDR (_malloc_top))
+    return _HEAPBADBEGIN;
+  if (FLAGS (ADDR (_malloc_bottom)) != 0)
+    return _HEAPBADBEGIN;
+  if (!_cdll_flag && ADDR (_malloc_bottom) <= ADDR (&dummy))
+    return _HEAPBADBEGIN;
+
+  if (FLAGS (ADDR (_malloc_top)) != 0)
+    return _HEAPBADEND;
+  last = _sbrk (0);
+  if (ADDR (_malloc_top) >= ADDR (last))
+    return _HEAPBADEND;
+  if (_malloc_top->size != END_OF_HEAP)
+    return _HEAPBADEND;
+
+  p = _malloc_bottom;
+  while (p != _malloc_top)
+    {
+      /* Hitting a `size' member equal to END_OF_HEAP before hitting
+         _malloc_top is an error. */
+
+      if (p->size == END_OF_HEAP)
+        return _HEAPBADNODE;
+
+      /* Check the `size' member. */
+
+      len = p->size;
+      if (len > 0x7fffffff)
+        return _HEAPBADNODE;
+
+      /* Compute and check the address of the next block. */
+
+      next = ADDR (p) + MHEADER_SIZE + SIZE (len);
+      if (next <= ADDR (p) || next > ADDR (_malloc_top) || (len & MF_RESERVED))
+        return _HEAPBADNODE;
+
+      /* If filling is requested and the block is free, fill it. */
+
+      if (fill != HEAP_NO_FILL && (len & MF_FREE))
+        memset ((char *)p + MHEADER_SIZE, (int)fill, SIZE (len));
+
+      /* Increment MET_ROVER if we have met the roving pointer. */
+
+      if (p == _malloc_rover)
+        ++met_rover;
+
+      /* Move on to the next block. */
+
+      p = MHEADER (next);
+    }
+  if (met_rover != 1)
+    return _HEAPBADROVER;
+  return _HEAPOK;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/makefile	(revision 18)
@@ -0,0 +1,27 @@
+#
+# /emx/src/lib/malloc1/makefile
+#
+LIBBASE=malloc1
+.INCLUDE: /emx/src/lib/libc0.mak
+
+local: ;
+
+calloc.o: calloc.c $(I)stdlib.h $(I)string.h $(I)malloc.h
+expand.o: expand.c $(I)stdlib.h $(I)malloc.h malloc1.h
+free.o: free.c $(I)stdlib.h $(I)malloc.h malloc1.h
+heapchk.o: heapchk.c $(I)stdlib.h $(I)string.h $(I)malloc.h malloc1.h \
+		$(I)emx/startup.h
+malloc.o: malloc.c $(I)stdlib.h $(I)malloc.h malloc1.h
+malloc2.o: malloc2.c $(I)stdlib.h malloc1.h \
+    $(BUILTIN) $(S)smutex.h $(S)fmutex.h
+msize.o: msize.c $(I)stdlib.h $(I)malloc.h malloc1.h
+realloc.o: realloc.c $(I)stdlib.h $(I)malloc.h malloc1.h
+realloc2.o: realloc2.c $(I)stdlib.h $(I)string.h malloc1.h
+tcalloc.o: tcalloc.c $(I)stdlib.h $(I)string.h $(I)malloc.h
+tfree.o: tfree.c $(I)stdlib.h $(I)malloc.h malloc1.h
+tmalloc.o: tmalloc.c $(I)stdlib.h $(I)malloc.h malloc1.h
+trealloc.o: trealloc.c $(I)stdlib.h $(I)malloc.h malloc1.h
+
+$(DSTLIB): calloc.o expand.o free.o heapchk.o malloc.o malloc2.o msize.o \
+    realloc.o realloc2.o tcalloc.o tfree.o tmalloc.o trealloc.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/Attic/malloc1/malloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/malloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/malloc.c	(revision 18)
@@ -0,0 +1,25 @@
+/* malloc.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "malloc1.h"
+
+void *malloc (size_t size)
+{
+  void *p;
+
+  if (size > MAX_SIZE)
+    return NULL;
+  if (_malloc_rover == NULL && !_emx_malloc_init ())
+    return NULL;
+  HEAP_LOCK;
+  p = _malloc2 (size, TRUE, FALSE);
+  HEAP_UNLOCK;
+  return p;
+}
+
+
+/* See malloc2.c */
+
+void _emx_malloc_magic (void)
+{
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/malloc1.h
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/malloc1.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/malloc1.h	(revision 18)
@@ -0,0 +1,55 @@
+/* malloc1.h (emx+gcc) */
+
+#define END_OF_HEAP 0xfffffffe      /* MF_FREE not set! */
+#define ALIGNMENT       4
+#define MAX_SIZE        0x40000000
+
+#define MF_FLAGS        0x03
+#define MF_FREE         0x01
+#define MF_RESERVED     0x02
+
+#define FALSE           0
+#define TRUE            1
+
+typedef unsigned long maddr_t;  /* A pointer as unsigned integer */
+typedef unsigned long msize_t;  /* The size of a block */
+
+typedef struct
+{
+  /* Bit 0 (MF_FREE) clear means the block is in use,
+     Bit 1 (MF_RESERVED) is reserved (always zero) */
+  msize_t size;
+} mheader_t;
+
+extern mheader_t *_malloc_rover;
+extern mheader_t *_malloc_bottom;
+extern mheader_t *_malloc_top;
+
+#define MHEADER_SIZE    (sizeof (mheader_t))
+#define ADDR(p)         ((maddr_t)(p))
+#define MHEADER(p)      ((mheader_t *)(p))
+#define FREE(mem)       ((MHEADER (mem))[-1].size |= MF_FREE)
+#define SIZE(x)         ((x) & ~MF_FLAGS)
+#define FLAGS(x)        ((x) & MF_FLAGS)
+#define ROUNDUP(x)      (((x) + (ALIGNMENT-1)) & ~(ALIGNMENT-1))
+
+int _emx_malloc_init (void);
+void _emx_malloc_magic (void);
+void *_expand2 (void *mem, size_t size, int expand_heap, int tile);
+void *_malloc2 (size_t size, int expand_heap, int tile);
+void *_realloc2 (void *mem, size_t size, int tile);
+
+#if defined (__MT__)
+
+void _heap_lock (void);
+void _heap_unlock (void);
+
+#define HEAP_LOCK   _heap_lock()
+#define HEAP_UNLOCK _heap_unlock()
+
+#else
+
+#define HEAP_LOCK
+#define HEAP_UNLOCK
+
+#endif /* defined (__MT__) */
Index: trunk/src/emx/src/lib/Attic/malloc1/malloc2.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/malloc2.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/malloc2.c	(revision 18)
@@ -0,0 +1,276 @@
+/* malloc2.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/smutex.h> and <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <sys/smutex.h>
+#include <stdlib.h>
+#include "malloc1.h"
+
+#define CHUNK_SIZE 65536
+
+/* To do: take size of last free block into account, if no used block
+          follows and if sbrk() must be called. */
+
+/* Bug: sbrk/brk must not be called by user program to change data
+        segment size (very complicated to fix). malloc returns NULL if it
+        thinks the data segment size has been changed. */
+
+#ifdef __MT__
+static _rmutex _heap_rmutex;
+#endif
+
+mheader_t *_malloc_rover = NULL;
+mheader_t *_malloc_bottom = NULL;
+mheader_t *_malloc_top = NULL;
+
+int _emx_malloc_init (void)
+{
+  maddr_t n;
+  void *p;
+  int result;
+#ifdef __MT__
+  static _smutex lock;
+#endif
+
+/* This is an attempt at provoking a linker error if malloc() has been
+   replaced and -ltmalloc has been forgotten.  By referencing the
+   _emx_malloc_magic() function, we force in the module compiled from
+   malloc.c.  That will hopefully conflict with the replacement
+   malloc(). */
+
+  _emx_malloc_magic ();
+
+#ifdef __MT__
+  _smutex_request (&lock);
+#endif
+
+  if (_malloc_rover != NULL)
+    result = TRUE;
+  else
+    {
+#ifdef __MT__
+      _rmutex_checked_create (&_heap_rmutex, 0);
+#endif
+      n = ADDR (_sbrk (0));
+      if ((n & (ALIGNMENT-1)) != 0)
+        _sbrk (ALIGNMENT - (n & (ALIGNMENT-1)));
+
+      p = _sbrk (2 * MHEADER_SIZE);
+      if (p == (void *)(-1) || (ADDR (p) & (ALIGNMENT-1)) != 0)
+        result = FALSE;
+      else
+        {
+          _malloc_bottom = _malloc_rover = p;
+          _malloc_top = _malloc_bottom + 1;
+          _malloc_bottom->size = 1;     /* length = 0, free */
+          _malloc_top->size = END_OF_HEAP; /* End of heap      */
+          result = TRUE;
+        }
+    }
+
+#ifdef __MT__
+  _smutex_release (&lock);
+#endif
+  return result;
+}
+
+#ifdef __MT__
+
+/* Lock the heap. */
+
+void _heap_lock (void)
+{
+  _rmutex_checked_request (&_heap_rmutex, _FMR_IGNINT);
+}
+
+/* Release the heap. */
+
+void _heap_unlock (void)
+{
+  _rmutex_checked_release (&_heap_rmutex);
+}
+
+#endif
+
+/* Pass 1: search from _malloc_rover to end of heap
+   Pass 2: search from start of heap to _malloc_rover
+   Pass 3: search from _malloc_rover to end of heap (after growing heap)
+
+   If EXPAND_HEAP is non-zero, we are allowed to expand the heap. */
+
+void *_malloc2 (size_t size, int expand_heap, int tile)
+{
+  mheader_t *block, *base;
+  void *p;
+  msize_t len, n;
+  maddr_t a;
+  int pass;
+
+  /* Sanity-check SIZE.  Don't call sbrk() with negative argument */
+
+  if (size > MAX_SIZE)
+    return NULL;
+
+  /* Round up SIZE to a multiple of 4. */
+
+  size = ROUNDUP (size);
+
+  pass = 1;
+
+  /* Start new pass at _malloc_rover. */
+
+restart:
+  block = base = _malloc_rover;
+
+  /* Skip blocks which are in use.  Jump to free_start when we find a
+     free block. */
+
+in_use:
+  if (block->size & MF_FREE)
+    goto free_start;
+
+  /* Same as in_use, but we already know that the current block is in
+     use (speed hack). */
+
+not_free:
+
+  /* The second pass stops at _malloc_rover. */
+
+  if (pass == 2 && ADDR (block) > ADDR (_malloc_rover))
+    {
+      block = _malloc_top;
+      goto not_found;
+    }
+
+  /* Start next pass when reaching the end of the heap. */
+
+  if (block->size == END_OF_HEAP)
+    {
+      if (block != _malloc_top)
+        return NULL;
+      if (pass >= 2)
+        goto not_found;
+      ++pass; block = _malloc_bottom;
+      goto in_use;
+    }
+
+  /* Move to the next block and repeat loop. */
+
+  block = MHEADER (ADDR (block) + MHEADER_SIZE + block->size);
+  goto in_use;
+
+  /* We found a free block.  Now collapse successive free blocks until
+     the block is big enough or there is not another adjacent free
+     block. */
+
+free_start:
+
+  /* BASE points to the start of the free block we're examining.  LEN
+     is used to accumulate the length of successive free blocks. */
+
+  base = block;
+  len = SIZE (base->size);
+
+  /* If tiling is in effect, the block must not cross a 64K boundary.
+     Compute N, the number of extra bytes required at the beginning of
+     the block, based on the address of the current block, to align
+     the data properly. */
+
+  n = 0;
+  if (tile)
+    {
+
+      /* If the requested size is 64K or more or if the data crosses a
+         64K boundary, align the block to a 64K boundary. */
+
+      a = ADDR (base) + MHEADER_SIZE;
+      if (((a + size) & 0xffff) < size)
+        {
+          n = a & 0xffff;
+          if (n != 0)
+            n = 0x10000 - n;
+        }
+    }
+
+free_loop:
+
+  /* If the block is big enough, quit the loop and use the block. */
+
+  if (len >= size + n)
+    goto found;
+
+  /* Move to the next block. */
+
+  block = MHEADER (ADDR (base) + MHEADER_SIZE + len);
+
+  /* If that block is in use, quit the loop and skip used blocks until
+     another free block is found. */
+
+  if (!(block->size & MF_FREE))
+    goto not_free;
+
+  /* Update LEN and collaps the current block and the new block into
+     one free block, updating _malloc_rover if necessary.  Then repeat
+     the loop. */
+
+  len += MHEADER_SIZE + SIZE (block->size);
+  if (_malloc_rover == block)
+    _malloc_rover = base;
+  base->size = len | MF_FREE;
+  goto free_loop;
+
+  /* A big enough block was found.  Split it into up to three blocks,
+     one of which will be marked used and returned to the caller. */
+
+found:
+
+  /* If alignment is required, create a free block of size n
+     (including the header), then advance the pointer.  This may
+     create a block of size 0 (excluding the header). */
+
+  if (n != 0)
+    {
+      if ((n & MF_FLAGS) != 0)
+        abort ();
+      base->size = (n - MHEADER_SIZE) | MF_FREE;
+      base = MHEADER (ADDR (base) + n); len -= n;
+    }
+
+  /* If there are more than 4 bytes left, create a free block after
+     the block to be used.  If there are 4 bytes left, we simply make
+     the block 4 bytes too big. */
+
+  if (len - size > MHEADER_SIZE)
+    {
+      base->size = size;        /* MF_FREE not set, ie, in use */
+      block = MHEADER (ADDR (base) + MHEADER_SIZE + size);
+      block->size = (len - size - MHEADER_SIZE) | MF_FREE;
+    }
+  else
+    base->size = len;           /* in use! */
+  _malloc_rover = base;
+  return (void *)(ADDR (base) + MHEADER_SIZE);
+
+not_found:
+  if (!expand_heap)
+    return NULL;
+  if (tile)
+    n = (size + 0x10000 + 0xfff) & ~0xfff;
+  else
+    {
+      n = (size + MHEADER_SIZE + 0xfff) & ~0xfff;
+      if (n < CHUNK_SIZE)
+        n = CHUNK_SIZE;         /* Memory is cheap, searching expensive */
+    }
+  p = _sbrk (n);
+  if (p == (void *)(-1))
+    return NULL;
+  if (p != _malloc_top + 1)
+    return NULL;
+  _malloc_top->size = (n - MHEADER_SIZE) | MF_FREE;
+  _malloc_top = MHEADER (ADDR (_malloc_top) + n);
+  _malloc_top->size = END_OF_HEAP;
+  pass = 3; _malloc_rover = base;
+  goto restart;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/msize.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/msize.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/msize.c	(revision 18)
@@ -0,0 +1,12 @@
+/* msize.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "malloc1.h"
+
+size_t _msize (const void *mem)
+{
+  if (mem == NULL)
+    return 0;
+  else
+    return SIZE (MHEADER (mem)[-1].size);
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/realloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/realloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/realloc.c	(revision 18)
@@ -0,0 +1,31 @@
+/* realloc.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "malloc1.h"
+
+/* Resize a block of memory.  If this cannot done in-place, move the
+   block. */
+
+void *realloc (void *mem, size_t new_size)
+{
+  void *p;
+
+  /* First handle the trivial cases: if MEM is NULL, realloc() behaves
+     like malloc(). */
+
+  if (mem == NULL)
+    return malloc (new_size);
+
+  /* If the new size is 0, free the block. */
+
+  if (new_size == 0)
+    {
+      free (mem);
+      return NULL;
+    }
+
+  HEAP_LOCK;
+  p = _realloc2 (mem, new_size, FALSE);
+  HEAP_UNLOCK;
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/realloc2.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/realloc2.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/realloc2.c	(revision 18)
@@ -0,0 +1,60 @@
+/* realloc2.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include "malloc1.h"
+
+
+void *_realloc2 (void *mem, size_t new_size, int tile)
+{
+  void *p;
+  mheader_t *block;
+  msize_t old_size;
+
+  /* Get a pointer to the block header, read the old size and mark the
+     block in-use. */
+
+  block = mem;
+  --block;
+  old_size = SIZE (block->size);
+  block->size = old_size;       /* Block is in use */
+
+  /* Try to expand the block in-place, without expanding the heap. */
+
+  if (_expand2 (mem, new_size, FALSE, tile) != NULL)
+    return mem;
+
+  /* To save space, try to move the block to an entirely new location
+     in the heap. */
+
+  p = _malloc2 (new_size, FALSE, tile);
+  if (p != NULL)
+    {
+      memcpy (p, mem, old_size);
+      FREE (mem);
+      return p;
+    }
+
+  /* Now try to expand the heap to expand the block.  This works only
+     if the block is the last used one of the heap. */
+
+  if (_expand2 (mem, new_size, TRUE, tile) != NULL)
+    return mem;
+
+  /* No chance is left but expanding the heap and allocating a new
+     block at the end of the heap.  A speed optimization could be done
+     here: searching the heap after MEM would be sufficient. */
+
+  p = _malloc2 (new_size, TRUE, tile);
+  if (p != NULL)
+    {
+      memcpy (p, mem, old_size);
+      FREE (mem);
+      return p;
+    }
+
+  /* Everything failed.  Shrink the block to the original size. */
+
+  _expand2 (mem, old_size, FALSE, tile);
+  return NULL;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/tcalloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/tcalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/tcalloc.c	(revision 18)
@@ -0,0 +1,18 @@
+/* tcalloc.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+
+void *_tcalloc (size_t elements, size_t size)
+{
+  size_t bytes;
+  void *p;
+
+  bytes = elements * size;
+  if (size != 0 && bytes / size != elements) /* Check for overflow */
+    return NULL;
+  p = _tmalloc (bytes);
+  if (p != NULL)
+    memset (p, 0, bytes);
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/tfree.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/tfree.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/tfree.c	(revision 18)
@@ -0,0 +1,10 @@
+/* tfree.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "malloc1.h"
+
+void _tfree (void *mem)
+{
+  if (mem != NULL)
+    FREE (mem);
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/tmalloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/tmalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/tmalloc.c	(revision 18)
@@ -0,0 +1,18 @@
+/* tmalloc.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "malloc1.h"
+
+void *_tmalloc (size_t size)
+{
+  void *p;
+
+  if (size > MAX_SIZE)
+    return NULL;
+  if (_malloc_rover == NULL && !_emx_malloc_init ())
+    return NULL;
+  HEAP_LOCK;
+  p = _malloc2 (size, TRUE, TRUE);
+  HEAP_UNLOCK;
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/malloc1/trealloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/malloc1/trealloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/malloc1/trealloc.c	(revision 18)
@@ -0,0 +1,31 @@
+/* trealloc.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "malloc1.h"
+
+/* Resize a block of memory.  If this cannot done in-place, move the
+   block. */
+
+void *_trealloc (void *mem, size_t new_size)
+{
+  void *p;
+
+  /* First handle the trivial cases: if MEM is NULL, _trealloc()
+     behaves like _tmalloc(). */
+
+  if (mem == NULL)
+    return _tmalloc (new_size);
+
+  /* If the new size is 0, free the block. */
+
+  if (new_size == 0)
+    {
+      _tfree (mem);
+      return NULL;
+    }
+
+  HEAP_LOCK;
+  p = _realloc2 (mem, new_size, TRUE);
+  HEAP_UNLOCK;
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/nls/fncmp.c
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/fncmp.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/fncmp.c	(revision 18)
@@ -0,0 +1,24 @@
+/* fncmp.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/nls.h>
+
+int _fncmp (const unsigned char *string1, const unsigned char *string2)
+{
+  int d;
+  unsigned char c1, c2;
+
+  for (;;)
+    {
+      c1 = *string1;
+      if (!_nls_is_dbcs_lead (c1))
+        c1 = _nls_toupper_tab[c1];
+      c2 = *string2;
+      if (!_nls_is_dbcs_lead (c2))
+        c2 = _nls_toupper_tab[c2];
+      d = (int)c1 - (int)c2;
+      if (d != 0 || *string1 == 0 || *string2 == 0)
+        return d;
+      ++string1; ++string2;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/nls/fnlwr.c
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/fnlwr.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/fnlwr.c	(revision 18)
@@ -0,0 +1,71 @@
+/* fnlwr.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/nls.h>
+
+static char cache_curdrive = 0;
+static char cache_filesys[26] =
+    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+#define DIRSEP_P(c) ((c) == '\\' || (c) == '/')
+
+void _fnlwr2 (char *name, const char *base)
+{
+  char c, dr[3], fs[16];
+  int i;
+
+  /* Do not translate UNC paths to lower case. */
+
+  if (DIRSEP_P (base[0]) && DIRSEP_P (base[1]) && !DIRSEP_P (base[2]))
+    return;
+
+  c = _fngetdrive (base);
+  if (c == 0)
+    {
+      if (cache_curdrive == 0)
+        cache_curdrive = _getdrive ();
+      c = cache_curdrive;
+    }
+  else if (name == base)
+    name[0] = (char)(c - 'A' + 'a');
+  i = c - 'A';
+  if (cache_filesys[i] == 0)
+    {
+      dr[0] = c;
+      dr[1] = ':';
+      dr[2] = 0;
+      if (_filesys (dr, fs, sizeof (fs)) != 0)
+        return;
+      if (strcmp (fs, "FAT") == 0 || strcmp (fs, "CDFS") == 0)
+        cache_filesys[i] = 'u';     /* upper-casing */
+      else
+        cache_filesys[i] = 'p';     /* case-preserving, perhaps */
+    }
+  if (cache_filesys[i] == 'u')
+    _nls_strlwr (name);
+}
+
+
+void _fnlwr (char *name)
+{
+  _fnlwr2 (name, name);
+}
+
+
+void _rfnlwr (void)
+{
+  int i;
+
+  for (i = 0; i < 26; ++i)
+    cache_filesys[i] = 0;
+  cache_curdrive = 0;
+}
+
+
+void _sfnlwr (const char *name)
+{
+  cache_curdrive = _fngetdrive (name);
+  if (cache_curdrive == 0)
+    cache_curdrive = _getdrive ();
+}
Index: trunk/src/emx/src/lib/Attic/nls/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/makefile	(revision 18)
@@ -0,0 +1,21 @@
+#
+# /emx/src/lib/nls/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+fncmp.o: fncmp.c $(I)sys/nls.h $(I)stdlib.h
+fnlwr.o: fnlwr.c $(I)stdlib.h $(I)ctype.h $(I)sys/nls.h
+nlsctype.o: nlsctype.c $(I)stdlib.h $(I)sys/nls.h $(I)emx/nls.h \
+		$(I)emx/syscalls.h $(I)emx/locale.h
+nlsinit.o: nlsinit.c $(I)sys/nls.h $(I)emx/nls.h
+nlsslwr.o: nlsslwr.c $(I)sys/nls.h
+nlssupr.o: nlssupr.c $(I)sys/nls.h
+nlstolwr.o: nlstolwr.c $(I)sys/nls.h $(I)emx/nls.h $(I)emx/startup.h
+nlstoupr.o: nlstoupr.c $(I)sys/nls.h $(I)emx/nls.h $(I)emx/startup.h \
+		$(I)emx/syscalls.h
+
+$(DSTLIB): fncmp.o fnlwr.o nlsctype.o nlsinit.o nlssupr.o nlsslwr.o \
+    nlstolwr.o nlstoupr.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/Attic/nls/nlsctype.c
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/nlsctype.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/nlsctype.c	(revision 18)
@@ -0,0 +1,30 @@
+/* dbcsctype.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/nls.h>
+#include <emx/locale.h>
+#include <emx/nls.h>
+#include <emx/syscalls.h>
+#include <emx/startup.h>
+
+unsigned char _nls_ctype_tab[256] = {0};
+
+/* Initialize table identifying DBCS lead bytes. */
+
+void _nls_ctype_init (void)
+{
+  int i;
+
+  __nls_ctype (_nls_ctype_tab);
+
+  /* Switch multibyte character processing to DBCS If there's at least
+     one DBCS lead byte. */
+
+  for (i = 0; i < 256; ++i)
+    if (_nls_is_dbcs_lead (i))
+      break;
+  if (i < 256)
+    _cur_mbyte.mode = _MB_DBCS;
+}
+
+_CRT_INIT1 (_nls_ctype_init)
Index: trunk/src/emx/src/lib/Attic/nls/nlsinit.c
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/nlsinit.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/nlsinit.c	(revision 18)
@@ -0,0 +1,10 @@
+/* nlsinit.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <sys/nls.h>
+#include <emx/nls.h>
+
+void _nls_init (void)
+{
+  _nls_ctype_init ();
+  _nls_tolower_init ();         /* Calls _nls_toupper_init() */
+}
Index: trunk/src/emx/src/lib/Attic/nls/nlsslwr.c
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/nlsslwr.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/nlsslwr.c	(revision 18)
@@ -0,0 +1,23 @@
+/* nlsslwr.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <sys/nls.h>
+
+unsigned char *_nls_strlwr (unsigned char *string)
+{
+  unsigned char *s;
+
+  s = string;
+  while (*s != 0)
+    if (_nls_is_dbcs_lead (*s))
+      {
+        if (s[1] == 0)          /* Invalid DBCS character */
+          return string;
+        s += 2;
+      }
+    else
+      {
+        *s = _nls_tolower_tab[*s];
+        ++s;
+      }
+  return string;
+}
Index: trunk/src/emx/src/lib/Attic/nls/nlssupr.c
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/nlssupr.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/nlssupr.c	(revision 18)
@@ -0,0 +1,23 @@
+/* nlssupr.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <sys/nls.h>
+
+unsigned char *_nls_strupr (unsigned char *string)
+{
+  unsigned char *s;
+
+  s = string;
+  while (*s != 0)
+    if (_nls_is_dbcs_lead (*s))
+      {
+        if (s[1] == 0)          /* Invalid DBCS character */
+          return string;
+        s += 2;
+      }
+    else
+      {
+        *s = _nls_toupper_tab[*s];
+        ++s;
+      }
+  return string;
+}
Index: trunk/src/emx/src/lib/Attic/nls/nlstolwr.c
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/nlstolwr.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/nlstolwr.c	(revision 18)
@@ -0,0 +1,23 @@
+/* nlstolwr.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <sys/nls.h>
+#include <emx/nls.h>
+#include <emx/startup.h>
+
+unsigned char _nls_tolower_tab[256] = {0};
+
+void _nls_tolower_init (void)
+{
+  int i;
+
+  _nls_toupper_init ();
+  for (i = 0; i < 256; ++i)
+    _nls_tolower_tab[i] = (unsigned char)i;
+  for (i = 0; i < 256; ++i)
+    if (_nls_toupper_tab[i] != i)
+      _nls_tolower_tab[_nls_toupper_tab[i]] = (unsigned char)i;
+  for (i = 'A'; i <= 'Z'; ++i)
+    _nls_tolower_tab[i] = (unsigned char)(i - 'A' + 'a');
+}
+
+_CRT_INIT1 (_nls_tolower_init)
Index: trunk/src/emx/src/lib/Attic/nls/nlstoupr.c
===================================================================
--- trunk/src/emx/src/lib/Attic/nls/nlstoupr.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/nls/nlstoupr.c	(revision 18)
@@ -0,0 +1,19 @@
+/* nlstoupr.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <sys/nls.h>
+#include <emx/nls.h>
+#include <emx/syscalls.h>
+#include <emx/startup.h>
+
+unsigned char _nls_toupper_tab[256] = {0};
+
+void _nls_toupper_init (void)
+{
+  int i;
+
+  for (i = 0; i < 256; ++i)
+    _nls_toupper_tab[i] = (unsigned char)i;
+  __nls_memupr (_nls_toupper_tab, 256);
+}
+
+_CRT_INIT1 (_nls_toupper_init)
Index: trunk/src/emx/src/lib/Attic/tmalloc/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/tmalloc/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/tmalloc/makefile	(revision 18)
@@ -0,0 +1,30 @@
+#
+# /emx/src/lib/tmalloc/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+
+.PHONY: clean default dstlib tmalloc
+
+LIBTMALLOC=$(L)tmalloc.a
+
+default: tmalloc
+
+tmalloc .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(LIBTMALLOC)
+
+clean:
+	-del $(CPU)\*.o $(DELOPT)
+
+tcalloc.o: tcalloc.c $(I)stdlib.h $(I)string.h $(I)malloc.h
+tfree.o: tfree.c $(I)stdlib.h $(I)malloc.h tmalloc.h
+tmalloc.o: tmalloc.c $(I)stdlib.h $(I)malloc.h $(I)os2thunk.h tmalloc.h
+trealloc.o: trealloc.c $(I)stdlib.h $(I)malloc.h tmalloc.h
+
+$(LIBTMALLOC): tcalloc.o tfree.o tmalloc.o trealloc.o
+	-del $(LIBTMALLOC)
+	$(AR) r $(LIBTMALLOC) *.o
Index: trunk/src/emx/src/lib/Attic/tmalloc/tcalloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/tmalloc/tcalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/tmalloc/tcalloc.c	(revision 18)
@@ -0,0 +1,18 @@
+/* tcalloc.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+
+void *_tcalloc (size_t elements, size_t size)
+{
+  size_t bytes;
+  void *p;
+
+  bytes = elements * size;
+  if (size != 0 && bytes / size != elements) /* Check for overflow */
+    return NULL;
+  p = _tmalloc (bytes);
+  if (p != NULL)
+    memset (p, 0, bytes);
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/tmalloc/tfree.c
===================================================================
--- trunk/src/emx/src/lib/Attic/tmalloc/tfree.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/tmalloc/tfree.c	(revision 18)
@@ -0,0 +1,9 @@
+/* tfree.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "tmalloc.h"
+
+void _tfree (void *mem)
+{
+  free (TM_HEADER (mem)->parent);
+}
Index: trunk/src/emx/src/lib/Attic/tmalloc/tmalloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/tmalloc/tmalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/tmalloc/tmalloc.c	(revision 18)
@@ -0,0 +1,105 @@
+/* tmalloc.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <os2thunk.h>
+#include "tmalloc.h"
+
+typedef unsigned long ULONG;
+
+void *_tmalloc (size_t size)
+{
+  void *p, *u;
+  struct tmh *h;
+  size_t parent_size;
+  unsigned attempt;
+  char ok;
+
+  if (size <= 0x8000)
+    {
+      /* If the size is reasonable small, try to just allocate a block
+         big enough.  If we are lucky, the block does not cross a
+         64KByte boundary. */
+
+      p = malloc (size + TM_OVERHEAD);
+      if (p == NULL)
+        return NULL;
+      h = p; u = TM_USER (h);
+      if (_THUNK_PTR_SIZE_OK (u, size))
+        {
+          h->parent = p;
+          h->size = size;
+          return u;
+        }
+      free (p);
+    }
+
+  /* Compute the size of a block which can hold SIZE bytes without
+     crossing a 64KByte boundary, however the block gets aligned.  We
+     allocate extra SIZE or 0x10000 bytes, whatever is smaller. */
+
+  if (size < 0x10000)
+    parent_size = 2 * size + TM_OVERHEAD;
+  else
+    parent_size = size + 0x10000 + TM_OVERHEAD;
+
+  /* Make two attempts.  The second attempt allocates another 0x10000
+     bytes by increasing parent_size. */
+
+  for (attempt = 0;; ++attempt)
+    {
+      /* Check for overflow. */
+
+      if (parent_size < size)
+        return NULL;
+
+      /* Allocate the parent block. */
+
+      p = malloc (parent_size);
+      if (p == NULL)
+        return NULL;
+
+      /* If the first SIZE bytes (after our header) of the block don't
+         cross a 64KByte boundary, we use SIZE bytes (plus our header)
+         at the beginning of the block. */
+
+      h = p; u = TM_USER (h);
+      if (size < 0x10000)
+        ok = _THUNK_PTR_SIZE_OK (u, size);
+      else
+        ok = (((unsigned long)u & 0xffff) == 0);
+      if (ok)
+        {
+          h->parent = p;
+          h->size = size;
+          return u;
+        }
+
+      /* Skip to the (attempt+1)th 64KByte boundary for the user block. */
+
+      u = (void *)(((unsigned long)p + (attempt + 1) * 0x10000) & ~0xffff);
+
+      if ((char *)u - (char *)p + size > parent_size)
+        abort ();
+
+      /* Use that user block if there is enough space for the
+         header. */
+
+      if ((char *)u - (char *)p >= TM_OVERHEAD)
+        {
+          h = TM_HEADER (u);
+          h->parent = p;
+          h->size = size;
+          return u;
+        }
+
+      /* In the first pass, there may be not enough space for
+         TM_OVERHEAD bytes just preceding the first 64KByte boundary.
+         Retry by allocating an additional 0x10000 bytes to ensure the
+         existence of a suitable 64KByte boundary. */
+
+      if (attempt >= 1)
+        abort ();
+      free (p);
+      parent_size += 0x10000;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/tmalloc/tmalloc.h
===================================================================
--- trunk/src/emx/src/lib/Attic/tmalloc/tmalloc.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/tmalloc/tmalloc.h	(revision 18)
@@ -0,0 +1,14 @@
+/* tmalloc.h (emx+gcc) */
+
+/* This structure immediately precedes the block pointed to by
+   _tmalloc()'s return value. */
+
+struct tmh
+{
+  void *parent;
+  size_t size;
+};
+
+#define TM_OVERHEAD     (sizeof (struct tmh))
+#define TM_USER(p)      ((void *)((char *)(p) + TM_OVERHEAD))
+#define TM_HEADER(p)    ((struct tmh *)((char *)(p) - TM_OVERHEAD))
Index: trunk/src/emx/src/lib/Attic/tmalloc/trealloc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/tmalloc/trealloc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/tmalloc/trealloc.c	(revision 18)
@@ -0,0 +1,41 @@
+/* trealloc.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include "tmalloc.h"
+
+void *_trealloc (void *mem, size_t new_size)
+{
+  void *p;
+  size_t copy;
+
+  /* First handle the trivial cases: if MEM is NULL, _trealloc()
+     behaves like _tmalloc(). */
+
+  if (mem == NULL)
+    return _tmalloc (new_size);
+
+  /* If the new size is 0, free the block. */
+
+  if (new_size == 0)
+    {
+      _tfree (mem);
+      return NULL;
+    }
+
+  /* Do not attempt to call realloc() and hope for proper alignment.
+     If the new block is not properly aligned, we have to call
+     _tmalloc().  If that fails, we are in trouble as we cannot safely
+     restore the original block with proper alignment. */
+
+  /* Allocate a new block. */
+
+  p = _tmalloc (new_size);
+  if (p == NULL)
+    return NULL;
+  copy = TM_HEADER (mem)->size;
+  if (new_size < copy)
+    copy = new_size;
+  memcpy (p, mem, copy);
+  _tfree (mem);
+  return p;
+}
Index: trunk/src/emx/src/lib/Attic/video/makefile
===================================================================
--- trunk/src/emx/src/lib/Attic/video/makefile	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/makefile	(revision 18)
@@ -0,0 +1,113 @@
+#
+# /emx/src/lib/video/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+
+.PHONY: clean default dstlib video
+
+V=$(I)sys/video.h video2.h
+W=$(I)sys/winmgr.h winmgr2.h
+
+LIBVIDEO=$(L)video.a
+
+default: video
+
+video .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(LIBVIDEO)
+
+clean:
+	-del $(CPU)\*.o $(DELOPT)
+
+vattrib.o: vattrib.c $(V)
+vbacksp.o: vbacksp.c $(V)
+vclear.o: vclear.c $(V)
+vclreol.o: vclreol.c $(V)
+vctype.o: vctype.c $(V) video3.h
+vdelline.o: vdelline.c $(V)
+vdimen.o: vdimen.c $(V)
+vfopen.o: vfopen.c $(V) $(I)stdio.h $(I)emx/io.h
+vgetattr.o: vgetattr.c $(V)
+vgetctyp.o: vgetctyp.c $(V) video3.h
+vgetline.o: vgetline.c $(V) video3.h
+vgetxy.o: vgetxy.c $(V)
+vgotoxy.o: vgotoxy.c $(V) video3.h
+vhardwar.o: vhardwar.c $(V) video3.h
+vhidecur.o: vhidecur.c $(V) video3.h
+vinit.o: vinit.c $(V) video3.h
+vinsline.o: vinsline.c $(V)
+vprintf.o: vprintf.c $(V)
+vputc.o: vputc.c $(V)
+vputline.o: vputline.c $(V) video3.h
+vputm.o: vputm.c $(V) video3.h
+vputmask.o: vputmask.c $(V) video3.h
+vputn.o: vputn.c $(V) video3.h
+vscroll.o: vscroll.c $(V) video3.h
+vscrollu.o: vscrollu.c $(V)
+vvprintf.o: vvprintf.c $(V) $(I)emx/io.h
+
+winmgr1.o: winmgr1.c $(I)sys/video.h $(W)
+winmgr2.o: winmgr2.c $(I)sys/video.h $(W)
+wmattall.o: wmattall.c $(W)
+wmbacksp.o: wmbacksp.c $(W)
+wmborder.o: wmborder.c $(W)
+wmbottom.o: wmbottom.c $(W)
+wmclear.o: wmclear.c $(W)
+wmclose.o: wmclose.c $(W)
+wmclosea.o: wmclosea.c $(W)
+wmclreol.o: wmclreol.c $(W)
+wmctype.o: wmctype.c $(W)
+wmdelcha.o: wmdelcha.c $(W)
+wmdelete.o: wmdelete.c $(W)
+wmdellin.o: wmdellin.c $(W)
+wmdimen.o: wmdimen.c $(W)
+wmdown.o: wmdown.c $(W)
+wmexit.o: wmexit.c $(I)sys/video.h $(W)
+wmfind.o: wmfind.c $(W)
+wmgetatt.o: wmgetatt.c $(W)
+wmgetpos.o: wmgetpos.c $(W)
+wmgetx.o: wmgetx.c $(W)
+wmgetxy.o: wmgetxy.c $(W)
+wmgety.o: wmgety.c $(W)
+wmfopen.o: wmfopen.c $(W) $(I)stdio.h $(I)emx/io.h
+wmgotoxy.o: wmgotoxy.c $(W)
+wminscha.o: wminscha.c $(W)
+wminslin.o: wminslin.c $(W)
+wmmove.o: wmmove.c $(W)
+wmopen.o: wmopen.c $(W)
+wmprintf.o: wmprintf.c $(W)
+wmputaat.o: wmputaat.c $(W)
+wmputc.o: wmputc.c $(W)
+wmputca.o: wmputca.c $(W)
+wmputcaa.o: wmputcaa.c $(W)
+wmputcat.o: wmputcat.c $(W)
+wmputs.o: wmputs.c $(W)
+wmputsa.o: wmputsa.c $(W)
+wmputsaa.o: wmputsaa.c $(W)
+wmputsat.o: wmputsat.c $(W)
+wmscroll.o: wmscroll.c $(W)
+wmtop.o: wmtop.c $(W)
+wmup.o: wmup.c $(W)
+wmupdate.o: wmupdate.c $(W)
+wmvprint.o: wmvprint.c $(W) $(I)emx/io.h
+wmwrap.o: wmwrap.c $(W)
+
+$(LIBVIDEO): vattrib.o vbacksp.o vclear.o vclreol.o vctype.o \
+    vdelline.o vdimen.o vfopen.o vgetattr.o vgetctyp.o vgetline.o vgetxy.o \
+    vgotoxy.o vhardwar.o vhidecur.o vinit.o vinsline.o vprintf.o \
+    vputc.o vputline.o vputm.o vputmask.o vputn.o vputs.o vscroll.o \
+    vscrollu.o vvprintf.o \
+    winmgr1.o winmgr2.o wmattall.o wmbacksp.o wmborder.o \
+    wmbottom.o wmclear.o wmclose.o wmclosea.o wmclreol.o wmctype.o \
+    wmdelcha.o wmdelete.o wmdellin.o wmdimen.o wmdown.o wmexit.o \
+    wmfind.o wmfopen.o wmgetatt.o wmgetpos.o wmgetx.o wmgetxy.o wmgety.o \
+    wmgotoxy.o wminscha.o wminslin.o wmmove.o wmopen.o wmprintf.o \
+    wmputaat.o wmputc.o wmputca.o wmputcaa.o wmputcat.o \
+    wmputs.o wmputsa.o wmputsaa.o wmputsat.o wmscroll.o wmtop.o wmup.o \
+    wmupdate.o wmvprint.o wmwrap.o
+	-del $(LIBVIDEO)
+	$(AR) r $(LIBVIDEO) *.o
Index: trunk/src/emx/src/lib/Attic/video/vattrib.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vattrib.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vattrib.c	(revision 18)
@@ -0,0 +1,9 @@
+/* vattrib.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+void v_attrib (int a)
+{
+  _v_attr = a;
+}
Index: trunk/src/emx/src/lib/Attic/video/vbacksp.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vbacksp.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vbacksp.c	(revision 18)
@@ -0,0 +1,23 @@
+/* vbacksp.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+void v_backsp (int count)
+{
+  while (count > 0)
+    {
+      --count;
+      if (_v_x <= 0)
+        {
+          if (_v_y > 0)
+            {
+              _v_x = _v_width-1;
+              --_v_y;
+            }
+        }
+      else
+        --_v_x;
+    }
+  v_gotoxy (_v_x, _v_y);
+}
Index: trunk/src/emx/src/lib/Attic/video/vclear.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vclear.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vclear.c	(revision 18)
@@ -0,0 +1,10 @@
+/* vclear.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+void v_clear (void)
+{
+  v_scroll (0, 0, _v_width-1, _v_height-1, 1, V_SCROLL_CLEAR);
+  v_gotoxy (_v_x, _v_y);
+}
Index: trunk/src/emx/src/lib/Attic/video/vclreol.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vclreol.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vclreol.c	(revision 18)
@@ -0,0 +1,9 @@
+/* vclreol.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+void v_clreol (void)
+{
+  v_putn (' ', _v_width - _v_x);
+}
Index: trunk/src/emx/src/lib/Attic/video/vctype.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vctype.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vctype.c	(revision 18)
@@ -0,0 +1,36 @@
+/* vctype.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_ctype (int start, int end)
+{
+  static VIOCURSORINFO cinfo;
+
+  if ((unsigned)start < 0x20 && (unsigned)end < 0x20)
+    {
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          cinfo.yStart = (USHORT)(start + 1);
+          cinfo.cEnd = (USHORT)(end + 1);
+          cinfo.cx = 0;             /* Default width */
+          cinfo.attr = 0;           /* Current attribute */
+          VioSetCurType (&cinfo, 0);
+        }
+#endif
+#if defined (IF_DOS)
+      IF_DOS
+        {
+          union REGS r;
+
+          r.h.ah = 0x01;
+          r.h.cl = end;
+          r.h.ch = start;
+          _int86 (0x10, &r, &r);
+        }
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/vdelline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vdelline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vdelline.c	(revision 18)
@@ -0,0 +1,10 @@
+/* vdelline.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+
+void v_delline (int count)
+{
+  v_scroll (0, _v_y, _v_width-1, _v_height-1, count, V_SCROLL_UP);
+}
Index: trunk/src/emx/src/lib/Attic/video/vdimen.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vdimen.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vdimen.c	(revision 18)
@@ -0,0 +1,10 @@
+/* vdimen.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+void v_dimen (int *width, int *height)
+{
+  *width = _v_width;
+  *height = _v_height;
+}
Index: trunk/src/emx/src/lib/Attic/video/vfopen.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vfopen.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vfopen.c	(revision 18)
@@ -0,0 +1,74 @@
+/* vfopen.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/video.h>
+#include <emx/io.h>
+#include "video2.h"
+
+static int _vflush (FILE *stream, int c)
+{
+  int n;
+
+  if (c == _FLUSH_FILL)
+    return -1;
+  n = stream->_ptr - stream->_buffer;
+  if (n > 0)
+    {
+      if (c >= 0 && n < stream->_buf_size)
+        {
+          *stream->_ptr = (char)c;
+          ++n;
+          c = -1;               /* Don't write character separately */
+        }
+      _v_puts_len (stream->_buffer, n);
+    }
+  stream->_ptr = stream->_buffer;
+  stream->_wcount = stream->_buf_size;
+  if (c >= 0)
+    {
+      if (stream->_buf_size == 0)
+        v_putc (c);
+      else
+        {
+          *stream->_ptr++ = (char)c;
+          --stream->_wcount;
+        }
+    }
+  return 0;
+}
+
+
+FILE *v_fopen (void)
+{
+  FILE *stream;
+
+  stream = _newstream ();
+  if (stream == NULL)
+    return NULL;
+  stream->_buffer = NULL;
+  stream->_ptr = NULL;
+  stream->_rcount = 0;
+  stream->_wcount = 0;
+  stream->_handle = -1;
+  stream->_flags = _IOOPEN|_IOSPECIAL|_IOBUFNONE|_IOWRT|_IONBF;
+  stream->_buf_size = 0;
+  stream->_flush = _vflush;
+  stream->_tmpidx = 0;
+  if (_setmore (stream, 1) != 0)
+    return NULL;
+  return stream;
+}
+
+
+int v_fclose (FILE *stream)
+{
+  int result;
+
+  if ((stream->_flags & (_IOOPEN|_IOSPECIAL)) != (_IOOPEN|_IOSPECIAL)
+      || stream->_flush != _vflush)
+    return -1;
+  result = fflush (stream);
+  _closestream (stream);
+  return result;
+}
Index: trunk/src/emx/src/lib/Attic/video/vgetattr.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vgetattr.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vgetattr.c	(revision 18)
@@ -0,0 +1,9 @@
+/* vgetattr.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+int v_getattr (void)
+{
+  return _v_attr;
+}
Index: trunk/src/emx/src/lib/Attic/video/vgetctyp.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vgetctyp.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vgetctyp.c	(revision 18)
@@ -0,0 +1,32 @@
+/* vgetctyp.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_getctype (int *start, int *end)
+{
+  static VIOCURSORINFO cinfo;
+
+#if defined (IF_OS2)
+  IF_OS2
+    {
+      VioGetCurType (&cinfo, 0);
+      *start = cinfo.yStart -1;
+      *end = cinfo.cEnd -1;
+    }
+#endif
+#if defined (IF_DOS)
+  IF_DOS
+    {
+      union REGS r;
+
+      r.h.ah = 0x03;
+      r.h.bh = 0x00;
+      _int86 (0x10, &r, &r);
+      *start = r.h.ch & 0x1f;
+      *end = r.h.cl & 0x1f;
+    }
+#endif
+}
Index: trunk/src/emx/src/lib/Attic/video/vgetline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vgetline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vgetline.c	(revision 18)
@@ -0,0 +1,54 @@
+/* vgetline.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_getline (char *dst, int x, int y, int count)
+{
+  if (count > 0)
+    {
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          USHORT len;
+
+          len = (USHORT)(count * 2);
+          VioReadCellStr (dst, &len, (USHORT)y, (USHORT)x, 0);
+        }
+#endif
+#if defined (IF_DOS)
+      IF_DOS
+        {
+          union REGS r;
+          int i;
+
+          if (_v_mem != NULL)
+            memcpy (dst, _v_mem + (y * _v_width + x) * 2, (size_t)(count * 2));
+          else
+            {
+              for (i = 0; i < count; ++i)
+                {
+                  r.h.ah = 0x02;
+                  r.h.bh = 0;
+                  r.h.dl = x + i;
+                  r.h.dh = y;
+                  _int86 (0x10, &r, &r);
+                  r.h.ah = 0x08;
+                  _int86 (0x10, &r, &r);
+                  dst[0] = r.h.al;
+                  dst[1] = r.h.ah;
+                  dst += 2;
+                }
+              r.h.ah = 0x02;
+              r.h.bh = 0x00;
+              r.h.dl = (unsigned char)_v_x;
+              r.h.dh = (unsigned char)_v_y;
+              _int86 (0x10, &r, &r);
+            }
+        }
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/vgetxy.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vgetxy.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vgetxy.c	(revision 18)
@@ -0,0 +1,10 @@
+/* vgetxy.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+void v_getxy (int *x, int *y)
+{
+  *x = _v_x;
+  *y = _v_y;
+}
Index: trunk/src/emx/src/lib/Attic/video/vgotoxy.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vgotoxy.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vgotoxy.c	(revision 18)
@@ -0,0 +1,32 @@
+/* vgotoxy.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_gotoxy (int x, int y)
+{
+  if ((unsigned)x < _v_width && (unsigned)y < _v_height)
+    {
+      _v_x = x; _v_y = y;
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          VioSetCurPos ((USHORT)y, (USHORT)x, 0);
+        }
+#endif
+#if defined (IF_DOS)
+      IF_DOS
+        {
+          union REGS r;
+          
+          r.h.ah = 0x02;
+          r.h.bh = 0x00;
+          r.h.dl = (unsigned char)x;
+          r.h.dh = (unsigned char)y;
+          _int86 (0x10, &r, &r);
+        }
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/vhardwar.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vhardwar.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vhardwar.c	(revision 18)
@@ -0,0 +1,37 @@
+/* vhardwar.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+int v_hardware (void)
+{
+  static VIOMODEINFO info;
+
+#if defined (IF_OS2)
+  IF_OS2
+    {
+      info.cb = sizeof (info);
+      VioGetMode (&info, 0);
+      if (!(info.fbType & VGMT_OTHER))
+        return V_MONOCHROME;
+      if (info.vres / info.row < 10)
+        return V_COLOR_8;
+      else
+        return V_COLOR_12;
+    }
+#endif
+#if defined (IF_DOS)
+  IF_DOS
+    {
+      union REGS r;
+
+      _int86 (0x11, &r, &r);
+      if ((r.h.al & 0x30) == 0x30)
+        return V_MONOCHROME;
+      else
+        return V_COLOR_8;
+    }
+#endif
+}
Index: trunk/src/emx/src/lib/Attic/video/vhidecur.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vhidecur.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vhidecur.c	(revision 18)
@@ -0,0 +1,33 @@
+/* vhidecur.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_hidecursor (void)
+{
+  static VIOCURSORINFO cinfo;
+
+#if defined (IF_OS2)
+  IF_OS2
+    {
+      cinfo.yStart = 0;
+      cinfo.cEnd = 0;
+      cinfo.cx = 0;             /* Default width */
+      cinfo.attr = 0xffff;      /* Invisible */
+      VioSetCurType (&cinfo, 0);
+    }
+#endif
+#if defined (IF_DOS)
+  IF_DOS
+    {
+      union REGS r;
+      
+      r.h.ah = 0x01;
+      r.h.cl = 0x00;
+      r.h.ch = 0x20;
+      _int86 (0x10, &r, &r);
+    }
+#endif
+}
Index: trunk/src/emx/src/lib/Attic/video/video2.h
===================================================================
--- trunk/src/emx/src/lib/Attic/video/video2.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/video2.h	(revision 18)
@@ -0,0 +1,28 @@
+/* video2.h (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#if defined (__EMX__)
+#define IF_DOS
+#define IF_OS2
+#elif defined (__IBMC__)
+#define IF_OS2
+#endif
+
+#if defined (IF_DOS) && defined (IF_OS2)
+#undef IF_OS2
+#undef IF_DOS
+#define IF_OS2   if (_osmode == OS2_MODE)
+#define IF_DOS   else
+#endif
+
+#if !defined (__EMX__)
+typedef void * _Seg16 _far16ptr;
+#endif
+
+extern int _v_width;
+extern int _v_height;
+extern int _v_x;
+extern int _v_y;
+extern int _v_attr;
+extern char *_v_mem;
+
+void _v_puts_len (const char *p, int len);
Index: trunk/src/emx/src/lib/Attic/video/video3.h
===================================================================
--- trunk/src/emx/src/lib/Attic/video/video3.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/video3.h	(revision 18)
@@ -0,0 +1,14 @@
+/* video3.h (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#if defined (IF_OS2)
+#define INCL_VIO
+#if defined (__EMX__)
+#include <os2emx.h>
+#else
+#include <os2.h>
+#endif
+#endif
+
+#if defined (IF_DOS)
+#include <dos.h>
+#endif
Index: trunk/src/emx/src/lib/Attic/video/vinit.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vinit.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vinit.c	(revision 18)
@@ -0,0 +1,91 @@
+/* vinit.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+#if defined (__EMX__)
+#include <sys/hw.h>
+#include <os2thunk.h>
+#else
+extern void _scrsize (int *dst);
+#endif
+
+int _v_width = 0;
+int _v_height = 0;
+int _v_x = 0;
+int _v_y = 0;
+int _v_attr = 0x07;
+char *_v_mem = NULL;
+
+static void _v_getxy (int *x, int *y)
+{
+#if defined (IF_OS2)
+  IF_OS2
+    {
+      USHORT row, col;
+
+      VioGetCurPos (&row, &col, 0);
+      *x = col; *y = row;
+    }
+#endif
+#if defined (IF_DOS)
+  IF_DOS
+    {
+      union REGS r;
+
+      r.h.ah = 0x03;
+      r.h.bh = 0x00;
+      _int86 (0x10, &r, &r);
+      *x = r.h.dl; *y = r.h.dh;
+    }
+#endif
+}
+
+
+int v_init (void)
+{
+  int two[2];
+
+  _scrsize (two);
+  _v_width = two[0];
+  _v_height = two[1];
+  _v_getxy (&_v_x, &_v_y);
+  _v_mem = NULL;
+#if defined (IF_OS2)
+  IF_OS2
+    {
+      _far16ptr addr;
+      USHORT len;
+
+      len = (USHORT)(_v_width * _v_height * 2);
+      if (VioGetBuf ((PULONG)&addr, &len, 0) == 0)
+#if defined (__EMX__)
+        _v_mem = MAKEP (SELECTOROF (addr), OFFSETOF (addr));
+#else
+        _v_mem = addr;
+#endif
+    }
+#endif
+#if defined (IF_DOS)
+  IF_DOS
+    {
+      unsigned addr, end_addr;
+      union REGS r;
+
+      r.h.ah = 0x0f;
+      _int86 (0x10, &r, &r);
+      if (r.h.al == 7 || r.h.al < 4)
+        {
+          _int86 (0x11, &r, &r);
+          if ((r.h.al & 0x30) == 0x30)
+            addr = 0xb0000;
+          else
+            addr = 0xb8000;
+          end_addr = (addr + _v_height * _v_width * 2 - 1) | 0xfff;
+          _v_mem = _memaccess (addr, end_addr, 1);
+        }
+    }
+#endif
+  return 1;
+}
Index: trunk/src/emx/src/lib/Attic/video/vinsline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vinsline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vinsline.c	(revision 18)
@@ -0,0 +1,10 @@
+/* vinsline.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+
+void v_insline (int count)
+{
+  v_scroll (0, _v_y, _v_width-1, _v_height-1, count, V_SCROLL_DOWN);
+}
Index: trunk/src/emx/src/lib/Attic/video/vprintf.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vprintf.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vprintf.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdarg.h>
+#include <sys/video.h>
+#include "video2.h"
+
+int v_printf (const char *fmt, ...)
+{
+  va_list arg_ptr;
+  int result;
+
+  va_start (arg_ptr, fmt);
+  result = v_vprintf (fmt, arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/Attic/video/vputc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vputc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vputc.c	(revision 18)
@@ -0,0 +1,24 @@
+/* vputc.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/video.h>
+#include "video2.h"
+
+void v_putc (char c)
+{
+  if (c != '\n')
+    {
+      v_putn (c, 1);
+      ++_v_x;
+    }
+  if (c == '\n' || _v_x >= _v_width)
+    {
+      _v_x = 0;
+      ++_v_y;
+      if (_v_y >= _v_height)
+        {
+          --_v_y;
+          v_scrollup ();
+        }
+    }
+  v_gotoxy (_v_x, _v_y);
+}
Index: trunk/src/emx/src/lib/Attic/video/vputline.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vputline.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vputline.c	(revision 18)
@@ -0,0 +1,54 @@
+/* vputline.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_putline (const char *src, int x, int y, int count)
+{
+  if (count > 0)
+    {
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          VioWrtCellStr ((PCH)src, (USHORT)(2 * count),
+                         (USHORT)y, (USHORT)x, 0);
+        }
+#endif
+#if defined (IF_DOS)
+      IF_DOS
+        {
+          if (_v_mem != NULL)
+            memcpy (_v_mem + (y * _v_width + x) * 2, src, (size_t)(count * 2));
+          else
+            {
+              union REGS r;
+              int i;
+
+              for (i = 0; i < count; ++i)
+                {
+                  r.h.ah = 0x02;
+                  r.h.bh = 0;
+                  r.h.dl = x + i;
+                  r.h.dh = y;
+                  _int86 (0x10, &r, &r);
+                  r.h.ah = 0x09;
+                  r.h.bh = 0;
+                  r.h.al = src[0];
+                  r.h.bl = src[1];
+                  r.x.cx = 1;
+                  _int86 (0x10, &r, &r);
+                  src += 2;
+                }
+              r.h.ah = 0x02;
+              r.h.bh = 0;
+              r.h.dl = (unsigned char)_v_x;
+              r.h.dh = (unsigned char)_v_y;
+              _int86 (0x10, &r, &r);
+            }
+        }
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/vputm.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vputm.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vputm.c	(revision 18)
@@ -0,0 +1,65 @@
+/* vputm.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_putm (const char *p, int len)
+{
+  if (len > 0)
+    {
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          BYTE attr;
+
+          attr = (BYTE)_v_attr;
+          VioWrtCharStrAtt ((PCH)p, (USHORT)len, (USHORT)_v_y, (USHORT)_v_x,
+                            &attr, 0);
+        }
+#endif
+#if defined (IF_DOS)
+      IF_DOS
+        {
+          if (_v_mem != NULL)
+            {
+              char *dst;
+
+              dst = _v_mem + (_v_y * _v_width + _v_x) * 2;
+              while (len > 0)
+                {
+                  dst[0] = *p++;
+                  dst[1] = (char)_v_attr;
+                  --len; dst += 2;
+                }
+            }
+          else
+            {
+              int i;
+              union REGS r;
+
+              for (i = 0; i < len; ++i)
+                {
+                  r.h.ah = 0x02;
+                  r.h.bh = 0x00;
+                  r.h.dl = (unsigned char)_v_x + i;
+                  r.h.dh = (unsigned char)_v_y;
+                  _int86 (0x10, &r, &r);
+                  r.h.ah = 0x09;
+                  r.h.bh = 0;
+                  r.h.bl = (unsigned char)_v_attr;
+                  r.h.al = p[i];
+                  r.x.cx = 1;
+                  _int86 (0x10, &r, &r);
+                }
+              r.h.ah = 0x02;
+              r.h.bh = 0x00;
+              r.h.dl = (unsigned char)_v_x;
+              r.h.dh = (unsigned char)_v_y;
+              _int86 (0x10, &r, &r);
+            }
+        }
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/vputmask.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vputmask.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vputmask.c	(revision 18)
@@ -0,0 +1,78 @@
+/* vputmask.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_putmask (const char *src, const char *mask, int x, int y, int count)
+{
+  int i, off;
+  char *dst;
+
+  if (_v_mem != NULL)
+    {
+      off = (y * _v_width + x) * 2;
+      dst = _v_mem + off;
+      for (i = 0; i < count; ++i)
+        {
+          if (*mask++)
+            {
+              dst[0] = src[0];
+              dst[1] = src[1];
+            }
+          dst += 2; src += 2;
+        }
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          VioShowBuf ((USHORT)off, (USHORT)(count * 2), 0);
+        }
+#endif
+    }
+  else
+    {
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          for (i = 0; i < count; ++i)
+            {
+              if (*mask++)
+                VioWrtNCell ((PCH)src, 1, (USHORT)y, (USHORT)(x + i), 0);
+              src += 2;
+            }
+        }
+#endif
+#if defined (IF_DOS)
+      IF_DOS
+        {
+          union REGS r;
+
+          for (i = 0; i < count; ++i)
+            {
+              if (*mask++)
+                {
+                  r.h.ah = 0x02;
+                  r.h.bh = 0;
+                  r.h.dl = x + i;
+                  r.h.dh = y;
+                  _int86 (0x10, &r, &r);
+                  r.h.ah = 0x09;
+                  r.h.bh = 0;
+                  r.h.al = src[0];
+                  r.h.bl = src[1];
+                  r.x.cx = 1;
+                  _int86 (0x10, &r, &r);
+                  
+                }
+              src += 2;
+            }
+          r.h.ah = 0x02;
+          r.h.bh = 0;
+          r.h.dl = (unsigned char)_v_x;
+          r.h.dh = (unsigned char)_v_y;
+          _int86 (0x10, &r, &r);
+        }
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/vputn.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vputn.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vputn.c	(revision 18)
@@ -0,0 +1,51 @@
+/* vputn.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_putn (char c, int count)
+{
+  if (count > 0)
+    {
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          BYTE cell[2];
+
+          cell[0] = c;
+          cell[1] = (BYTE)_v_attr;
+          VioWrtNCell (cell, (USHORT)count, (USHORT)_v_y, (USHORT)_v_x, 0);
+        }
+#endif
+#if defined (IF_DOS)
+      IF_DOS
+        {
+          if (_v_mem != NULL)
+            {
+              char *p;
+
+              p = _v_mem + (_v_y * _v_width + _v_x) * 2;
+              while (count > 0)
+                {
+                  p[0] = c;
+                  p[1] = (char)_v_attr;
+                  --count; p += 2;
+                }
+            }
+          else
+            {
+              union REGS r;
+
+              r.h.ah = 0x09;
+              r.h.bh = 0;
+              r.h.bl = (unsigned char)_v_attr;
+              r.h.al = c;
+              r.x.cx = count;
+              _int86 (0x10, &r, &r);
+            }
+        }
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/vputs.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vputs.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vputs.c	(revision 18)
@@ -0,0 +1,66 @@
+/* vputs.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/video.h>
+#include "video2.h"
+
+static void _v_puts1 (const char *p, int len)
+{
+  int max, cnt;
+
+  while (len > 0)
+    {
+      max = _v_width - _v_x;
+      if (len < max)
+        cnt = len;
+      else
+        cnt = max;
+      if (cnt > 0)
+        {
+          v_putm (p, cnt);
+          if (cnt == max)
+            {
+              _v_x = 0;
+              ++_v_y;
+              if (_v_y >= _v_height)
+                {
+                  --_v_y;
+                  v_scrollup ();
+                }
+            }
+          else
+            _v_x += cnt;
+          v_gotoxy (_v_x, _v_y);
+        }
+      len -= cnt;
+      p += cnt;
+    }
+}
+
+
+void _v_puts_len (const char *p, int len)
+{
+  const char *q;
+  int n;
+
+  do
+    {
+      q = memchr (p, '\n', (size_t)len);
+      if (q == NULL)
+        _v_puts1 (p, len);
+      else
+        {
+          n = q - p;
+          _v_puts1 (p, n);
+          v_putc ('\n');
+          p = q + 1;
+          len -= n + 1;
+        }
+    } while (q != NULL);
+}
+
+
+void v_puts (const char *p)
+{
+  _v_puts_len (p, (int)strlen (p));
+}
Index: trunk/src/emx/src/lib/Attic/video/vscroll.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vscroll.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vscroll.c	(revision 18)
@@ -0,0 +1,76 @@
+/* vscroll.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+#include "video3.h"
+
+void v_scroll (int tl_x, int tl_y, int br_x, int br_y, int count, int flag)
+{
+  if (count > 0)
+    {
+#if defined (IF_OS2)
+      IF_OS2
+        {
+          BYTE cell[2];
+
+          cell[0] = ' ';
+          cell[1] = (BYTE)_v_attr;
+          switch (flag)
+            {
+            case V_SCROLL_UP:
+              VioScrollUp ((USHORT)tl_y, (USHORT)tl_x,
+                           (USHORT)br_y, (USHORT)br_x, (USHORT)count, cell, 0);
+              break;
+            case V_SCROLL_DOWN:
+              VioScrollDn ((USHORT)tl_y, (USHORT)tl_x,
+                           (USHORT)br_y, (USHORT)br_x, (USHORT)count, cell, 0);
+              break;
+            case V_SCROLL_LEFT:
+              VioScrollLf ((USHORT)tl_y, (USHORT)tl_x,
+                           (USHORT)br_y, (USHORT)br_x, (USHORT)count, cell, 0);
+              break;
+            case V_SCROLL_RIGHT:
+              VioScrollRt ((USHORT)tl_y, (USHORT)tl_x,
+                           (USHORT)br_y, (USHORT)br_x, (USHORT)count, cell, 0);
+              break;
+            case V_SCROLL_CLEAR:
+              VioScrollUp ((USHORT)tl_y, (USHORT)tl_x,
+                           (USHORT)br_y, (USHORT)br_x,
+                           (USHORT)0xffff, cell, 0);
+              break;
+            }
+        }
+#endif
+#if defined (IF_DOS)
+      IF_DOS
+        {
+          union REGS r;
+
+          r.h.al = count;
+          switch (flag)
+            {
+            case V_SCROLL_UP:
+              r.h.ah = 0x06;
+              break;
+            case V_SCROLL_DOWN:
+              r.h.ah = 0x07;
+              break;
+            case V_SCROLL_LEFT:
+            case V_SCROLL_RIGHT:
+              return;
+            case V_SCROLL_CLEAR:
+              r.h.ah = 0x06;
+              r.h.al = 0;
+              break;
+            }
+          r.h.cl = (unsigned char)tl_x;
+          r.h.ch = (unsigned char)tl_y;
+          r.h.dl = (unsigned char)br_x;
+          r.h.dh = (unsigned char)br_y;
+          r.h.bh = (unsigned char)_v_attr;
+          _int86 (0x10, &r, &r);
+        }
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/vscrollu.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vscrollu.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vscrollu.c	(revision 18)
@@ -0,0 +1,10 @@
+/* vscrollu.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/video.h>
+#include "video2.h"
+
+void v_scrollup (void)
+{
+  v_scroll (0, 0, _v_width-1, _v_height-1, 1, V_SCROLL_UP);
+}
Index: trunk/src/emx/src/lib/Attic/video/vvprintf.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/vvprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/vvprintf.c	(revision 18)
@@ -0,0 +1,43 @@
+/* vvprintf.c (emx+gcc) -- Copyright (c) 1987-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/video.h>
+#include "video2.h"
+#include <emx/io.h>
+
+static int _v_flush (FILE *stream, int c)
+{
+  int n;
+
+  n = stream->_ptr - stream->_buffer;
+  if (n > 0)
+    _v_puts_len (stream->_buffer, n);
+  stream->_ptr = stream->_buffer;
+  *stream->_ptr++ = (char)c;
+  stream->_wcount = stream->_buf_size - 1;
+  return 0;
+}
+
+
+int v_vprintf (const char *fmt, va_list arg_ptr)
+{
+  FILE trick;
+  struct _file2 trick2;
+  int result;
+  char buf[512];
+
+  trick._buffer = buf;
+  trick._ptr = buf;
+  trick._rcount = 0;
+  trick._wcount = sizeof (buf);
+  trick._handle = -1;
+  trick._flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOWRT;
+  trick._buf_size = sizeof (buf);
+  trick._flush = _v_flush;
+  trick._ungetc_count = 0;
+  _setdummymore (&trick, &trick2);
+  result = _output (&trick, fmt, arg_ptr);
+  _v_flush (&trick, 0);
+  return result;
+}
Index: trunk/src/emx/src/lib/Attic/video/winmgr1.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/winmgr1.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/winmgr1.c	(revision 18)
@@ -0,0 +1,537 @@
+/* winmgr1.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#if defined (__IBMC__)
+#define __TILED__
+#endif
+#include <stdlib.h>
+#include <string.h>
+/* #include <dos.h> */
+#include <sys/video.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+wm_handle _wm_tab    = NULL;
+wm_handle *_wm_idx   = NULL;
+
+char * _wm_screen    = NULL;
+char * _wm_line      = NULL;
+
+int _wm_count        = 0;
+int _wm_max          = 0;
+int _wm_saved_cstart = 0;
+int _wm_saved_cend   = 0;
+int _wm_saved_x      = 0;
+int _wm_saved_y      = 0;
+int _wm_width        = 0;
+int _wm_height       = 0;
+
+wm_handle _wm_cursor = NULL;
+int _wm_c_hide       = TRUE;
+
+
+void _wm_cursor1 (void)
+{
+  int ax, ay;
+
+  if (_wm_cursor != NULL)
+    {
+      ax = _wm_cursor->x + _wm_cursor->x0;
+      ay = _wm_cursor->y + _wm_cursor->y0;
+      if (ax < 0 || ax >= _wm_width || ay < 0 || ay >= _wm_height)
+        v_hidecursor ();
+      else if (!_wm_cursor->c_vis)
+        v_hidecursor ();
+      else if (_wm_cursor->open && (_wm_cursor->visible ||
+                                    MASK (_wm_cursor,
+                                          _wm_cursor->x + _wm_cursor->ax,
+                                          _wm_cursor->y + _wm_cursor->ay)))
+        {
+          v_ctype (_wm_cursor->c_start, _wm_cursor->c_end);
+          v_gotoxy (ax, ay);
+        }
+      else if (!_wm_c_hide)
+        {
+          v_ctype (_wm_saved_cstart, _wm_saved_cend);
+          v_gotoxy (ax, ay);
+        }
+      else
+        v_hidecursor ();
+    }
+  else
+    v_hidecursor ();
+}
+
+
+void _wm_store1 (wm_handle wh, int x, int y, char c, int a)
+{
+  char *p;
+
+  p = &DATA (wh, x, y);
+  *p++ = c;
+  *p = (char)a;
+}
+
+
+
+void _wm_clrline1 (wm_handle wh, int y, int x0, int x1)
+{
+  _wm_clrline2 (&DATA (wh, x0, y), x1-x0+1, (char)wh->wattr);
+}
+
+
+
+void _wm_line1 (wm_handle wh, int y)
+{
+  char *src;
+  int yoffs;
+
+  if (wh->open)
+    {
+      yoffs = y * wh->bwidth;
+      src = &wh->data[2*(0+yoffs)];
+      if (wh->visible)
+        _wm_move2 (src, y+wh->by0, wh->bx0, wh->bx1, 1);
+      else
+        _wm_line2 (&wh->mask[0+yoffs], src, y+wh->by0, wh->bx0, wh->bx1);
+    }
+}
+
+
+void _wm_allvisible (wm_handle wh)
+{
+  memset (wh->mask, TRUE, (size_t)wh->masksize);
+  wh->visible = TRUE;
+}
+
+
+void _wm_hide2 (wm_handle wh1, wm_handle wh2)
+{
+  int x0, xc, y, y0, y9;
+  char *mask;
+
+  wh1->visible = FALSE;
+  x0 = MAX (wh1->bx0, wh2->bx0);
+  xc = MIN (wh1->bx1, wh2->bx1) - x0 + 1;
+  if (xc > 0)
+    {
+      y0 = MAX (wh1->by0, wh2->by0);
+      y9 = MIN (wh1->by1, wh2->by1);
+      mask = &MASK (wh1, x0 - wh1->bx0, y0 - wh1->by0);
+      for (y = y0; y <= y9; y++)
+        {
+          memset (mask, FALSE, (size_t)xc);
+          mask += wh1->bwidth;
+        }
+    }
+}
+
+
+void _wm_hide1 (void)
+{
+  int i, j;
+  wm_handle a, b;
+
+  for (i = _wm_count-1; i >= 0; --i)
+    _wm_allvisible (_wm_idx[i]);
+  for (i = _wm_count-1; i >= 0; --i)
+    {
+      a = _wm_idx[i];
+      if (a->open)
+        for (j = i-1; j >= 0; j--)
+          {
+            b = _wm_idx[j];
+            if (b->open && _wm_jam1 (a, b))
+              _wm_hide2 (b, a);
+          }
+    }
+}
+
+
+void _wm_unhide1 (wm_handle wh, wm_handle new_wh)
+{
+  int ay, ry0, ay0, ay9, x0, x9, mx;
+  int i;
+  wm_handle p;
+  char *src, *mask;
+
+  _wm_allvisible (wh);
+  for (i = 0; i < _wm_count; ++i)
+    {
+      p = _wm_idx[i];
+      if (p != wh)
+        {
+          if (p->open && _wm_jam1 (wh, p))
+            _wm_hide2 (wh, p);
+        }
+    }
+  if (new_wh != NULL && _wm_jam1 (wh, new_wh))
+    _wm_hide2 (wh, new_wh);
+  x0 = wh->bx0; x9 = wh->bx1; mx = 0;
+  ay0 = wh->by0; ay9 = wh->by1; ry0 = 0;
+  if (x0 < 0)
+    {
+      mx = -x0;
+      x0 = 0;
+    }
+  if (x9 >= _wm_width)
+    x9 = _wm_width-1;
+  if (ay0 < 0)
+    {
+      ry0 = -ay0;
+      ay0 = 0;
+    }
+  if (ay9 >= _wm_height)
+    ay9 = _wm_height-1;
+  src = &_wm_screen[2*(x0+ay0*_wm_width)];
+  mask = &MASK (wh, mx, ry0);
+  for (ay = ay0; ay <= ay9; ++ay)
+    {
+      if (wh->visible)
+        _wm_move2 (src, ay, x0, x9, 1);
+      else
+        {
+          _wm_line2 (mask, src, ay, x0, x9);
+          mask += wh->bwidth;
+        }
+      src += 2*_wm_width;
+    }
+}
+
+
+void _wm_clr1 (wm_handle wh)
+{
+  int y;
+
+  for (y = 0; y < wh->height; ++y)
+    _wm_clrline1 (wh, y+wh->ay, wh->ax, wh->width-1+wh->ax);
+}
+
+
+void _wm_border1 (wm_handle wh, int title_flag, int title_attr,
+                  const char *title)
+{
+  char ul, ur, ll, lr, ho, ve, tl, tr;
+  int x2, y2;
+  int i, attr;
+
+  switch (wh->border)
+    {
+    case 0:
+      return;
+    case 1:
+      ul = (char)'Ú'; ur = (char)'¿';
+      ll = (char)'À'; lr = (char)'Ù';
+      ho = (char)'Ä'; ve = (char)'³';
+      tl = (char)'Ž'; tr = (char)'Ã';
+      break;
+    case 2:
+      ul = (char)'É'; ur = (char)'»';
+      ll = (char)'È'; lr = (char)'Œ';
+      ho = (char)'Í'; ve = (char)'º';
+      tl = (char)'¹'; tr = (char)'Ì';
+      break;
+    case 3:
+      ul = (char)0xd5; ur = (char)0xb8;
+      ll = (char)0xd4; lr = (char)0xbe;
+      ho = (char)0xcd; ve = (char)0xb3;
+      tl = (char)0xb5; tr = (char)0xc6;
+      break;
+    case 4:
+      ul = (char)0xd6; ur = (char)0xb7;
+      ll = (char)0xd3; lr = (char)0xbd;
+      ho = (char)0xc4; ve = (char)0xba;
+      tl = (char)0xb6; tr = (char)0xc7;
+      break;
+    default:
+      ul = ur = ll = lr = ho = ve = tl = tr = (char)wh->border;
+    }
+  attr = wh->battr;
+  x2 = wh->x1+1 - wh->bx0;
+  y2 = wh->y1+1 - wh->by0;
+  _wm_store1 (wh, 0, 0, ul, attr);
+  _wm_store1 (wh, 0, y2, ll, attr);
+  for (i = wh->ay; i < y2; i++)
+    _wm_store1 (wh, 0, i, ve, attr);
+  _wm_store1 (wh, x2, 0, ur, attr);
+  _wm_store1 (wh, x2, y2, lr, attr);
+  for (i = wh->ay; i < y2; i++)
+    _wm_store1 (wh, x2, i, ve, attr);
+  for (i = wh->ax; i < x2; i++)
+    _wm_store1 (wh, i, 0, ho, attr);
+  for (i = wh->ax; i < x2; i++)
+    _wm_store1 (wh, i, y2, ho, attr);
+  if (title != NULL)
+    {
+      int tlen, twid, tx;
+      
+      tlen = (int)strlen (title);
+      if (title_flag == 0)
+        twid = wh->bwidth-2;
+      else
+        {
+          twid = wh->bwidth-4;
+          if (tlen > twid)
+            {
+              twid += 2;
+              title_flag = 0;
+            }
+        }
+      if (tlen > twid)
+        tlen = twid;
+      tx = 1+(twid-tlen)/2;
+      if (title_flag)
+        {
+          _wm_store1 (wh, tx       , 0, tl, attr);
+          _wm_store1 (wh, tx+1+tlen, 0, tr, attr);
+          ++tx;
+        }
+      for (i = 0; i < tlen; ++i)
+        _wm_store1 (wh, tx++, 0, title[i], title_attr);
+    }
+}
+
+
+void _wm_put1 (wm_handle wh)
+{
+  int y;
+
+  if (wh->open)
+    {
+      for (y = 0; y < wh->bheight; ++y)
+        _wm_line1 (wh, y);
+      _wm_cursor1 ();
+    }
+  wh->update_req = FALSE;
+}
+
+
+int _wm_jam1 (wm_handle wh1, wm_handle wh2)
+{
+  return (wh1->bx0 <= wh2->bx1 &&
+          wh2->bx0 <= wh1->bx1 &&
+          wh1->by0 <= wh2->by1 &&
+          wh2->by0 <= wh1->by1);
+}
+
+
+int _wm_idx1 (wm_handle wh)
+{
+  int i;
+
+  for (i = 0; i < _wm_count; ++i)
+    if (_wm_idx[i] == wh)
+      return i;
+  return -1;
+}
+
+
+void _wm_copy1 (wm_handle wh, wm_handle old_wh)
+{
+  int ay, x0, x9, xc, i, ry0, ay0, ay9, mx;
+  wm_handle p;
+  char *dst, *src, *mask;
+
+  if (wh->open)
+    {
+      _wm_allvisible (wh);
+      for (i = 0; i < _wm_count; ++i)
+        {
+          p = _wm_idx[i];
+          if (p != wh)
+            {
+              if (p->open && _wm_jam1 (wh, p))
+                _wm_hide2 (wh, p);
+            }
+        }
+      if (old_wh != NULL && _wm_jam1 (wh, old_wh))
+        _wm_hide2 (wh, old_wh);
+      x0 = wh->bx0; x9 = wh->bx1; mx = 0;
+      ay0 = wh->by0; ay9 = wh->by1; ry0 = 0;
+      if (x0 < 0)
+        {
+          mx = -x0;
+          x0 = 0;
+        }
+      if (x9 >= _wm_width)
+        x9 = _wm_width-1;
+      if (ay0 < 0)
+        {
+          ry0 = -ay0;
+          ay0 = 0;
+        }
+      if (ay9 >= _wm_height)
+        ay9 = _wm_height-1;
+      xc = x9-x0+1;
+      if (xc > 0)
+        {
+          src = &_wm_line[2*x0];
+          dst = &_wm_screen[2*(x0+ay0*_wm_width)];
+          mask = &MASK (wh, mx, ry0);
+          for (ay = ay0; ay <= ay9; ay++)
+            {
+              _wm_move2 (_wm_line, ay, 0, _wm_width-1, 0);
+              if (wh->visible)
+                memmove (dst, src, (size_t)(2 * xc));
+              else
+                {
+                  _wm_copy2 (mask, dst, src, xc);
+                  mask += wh->bwidth;
+                }
+              dst += 2*_wm_width;
+            }
+        }
+    }
+}
+
+
+int wm_init (int n)
+{
+  int i;
+
+  if (n <= 0)
+    return FALSE;
+  if (!v_init ())
+    return FALSE;
+  v_dimen (&_wm_width, &_wm_height);
+  v_getctype (&_wm_saved_cstart, &_wm_saved_cend);
+  v_ctype (-1, -1);
+  v_getxy (&_wm_saved_x, &_wm_saved_y);
+  _wm_cursor = NULL;
+  _wm_c_hide = TRUE;
+  _wm_count = 0;
+  _wm_tab = calloc ((size_t)n, sizeof (struct _wm_window));
+  _wm_idx = calloc ((size_t)n, sizeof (wm_handle));
+  _wm_screen = _tmalloc ((size_t)(2 * _wm_width * _wm_height));
+  _wm_line = _tmalloc ((size_t)(2*_wm_width));
+  if (_wm_tab == NULL || _wm_idx == NULL || _wm_screen == NULL ||
+      _wm_line == NULL)
+    {
+      if (_wm_tab != NULL)
+        {
+          free (_wm_tab); _wm_tab = NULL;
+        }
+      if (_wm_idx != NULL)
+        {
+          free (_wm_idx); _wm_idx = NULL;
+        }
+      if (_wm_screen != NULL)
+        {
+          _tfree (_wm_screen); _wm_screen = NULL;
+        }
+      if (_wm_line != NULL)
+        {
+          _tfree (_wm_line); _wm_line = NULL;
+        }
+      _wm_max = 0;
+      return FALSE;
+    }
+  else
+    {
+      _wm_max = n;
+      for (i = 0; i < _wm_max; ++i)
+        _wm_tab[i].used = 0;
+      return TRUE;
+    }
+}
+
+
+wm_handle wm_create (int x0, int y0, int x1, int y1, int border, int battr,
+                     int wattr)
+{
+  int i, bx0, by0, bx1, by1;
+  long ldatasize;
+  unsigned datasize;
+  wm_handle wh;
+
+  if (_wm_tab == NULL || x1 < x0 || y1 < y0 || x1-x0 > 1000 || y1-y0 > 1000)
+    return NULL;
+  for (i = 0; i < _wm_max; ++i)
+    if (_wm_tab[i].used != WM_USED)
+      break;
+  if (i >= _wm_max)
+    return NULL;                /* No slot found */
+  wh = &_wm_tab[i];
+  wh->x0 = x0; wh->y0 = y0;
+  wh->x1 = x1; wh->y1 = y1;
+  bx0 = x0; by0 = y0;
+  bx1 = x1; by1 = y1;
+  if (border != 0)
+    {
+      --bx0; --by0;
+      ++bx1; ++by1;
+    }
+  wh->bx0 = bx0; wh->by0 = by0;
+  wh->bx1 = bx1; wh->by1 = by1;
+  wh->width = x1-x0+1; wh->bwidth = bx1-bx0+1;
+  wh->height = y1-y0+1; wh->bheight = by1-by0+1;
+  wh->ax = x0-bx0; wh->ay = y0-by0;
+  ldatasize = (long)wh->bwidth * (long)wh->bheight;
+#if !defined (__32BIT__)
+  if (ldatasize >= 32768L)
+    return NULL;
+#endif
+  datasize = (unsigned)ldatasize;
+  wh->data = _tmalloc (2*datasize);
+  wh->mask = malloc (datasize);
+  if (wh->data == NULL || wh->mask == NULL)
+    {
+      if (wh->data != NULL) _tfree (wh->data);
+      if (wh->mask != NULL) free (wh->mask);
+      return NULL;              /* Out of memory */
+    }
+  wh->masksize = (int)datasize;
+  wh->border = border;
+  wh->battr = battr; wh->wattr = wattr;
+  wh->x = 0; wh->y = 0;
+  wh->used = WM_USED; wh->open = FALSE; wh->display = FALSE;
+  wh->update_flag = TRUE; wh->update_req = FALSE;
+  wh->wrap = TRUE;
+  wh->c_vis = TRUE;
+  wh->c_start = _wm_saved_cstart; wh->c_end = _wm_saved_cend;
+  _wm_idx[_wm_count++] = wh;
+  wh->visible = TRUE;
+  _wm_clr1 (wh);
+  _wm_border1 (wh, 0, 0, NULL);
+  _wm_hide1 ();
+  _wm_cursor1 ();
+  return wh;
+}
+
+
+void wm_attrib (wm_handle wh, int a)
+{
+  if (wh->used != WM_USED)
+    return;
+  wh->wattr = a;
+}
+
+
+void wm_cursor (wm_handle wh)
+{
+  if (wh != NULL && wh->used != WM_USED)
+    return;
+  _wm_cursor = wh;
+  _wm_cursor1 ();
+}
+
+
+void wm_chide (int flag)
+{
+  _wm_c_hide = flag;
+  _wm_cursor1 ();
+}
+
+
+void wm_cvis (wm_handle wh, int flag)
+{
+  if (wh != NULL && wh->used != WM_USED)
+    return;
+  wh->c_vis = flag;
+  _wm_cursor1 ();
+}
+
+
+wm_handle wm_get_cursor (void)
+{
+  return _wm_cursor;
+}
Index: trunk/src/emx/src/lib/Attic/video/winmgr2.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/winmgr2.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/winmgr2.c	(revision 18)
@@ -0,0 +1,112 @@
+/* winmgr2.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/video.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void _wm_copy2 (char *mask, char *dst, char *src, int width)
+{
+  while (width-- > 0)
+    {
+      if (*mask++)
+        {
+          *dst++ = *src++;
+          *dst++ = *src++;
+        }
+      else
+        {
+          dst += 2; src += 2;
+        }
+    }
+}
+
+
+
+void _wm_clrline2 (char *dst, int width, char a)
+{
+  while (width-- > 0)
+    {
+      *dst++ = ' ';
+      *dst++ = a;
+    }
+}
+
+
+
+void _wm_line2 (char *mask, char *data, int y, int x0, int x1)
+{
+  if (y >= 0 && y < _wm_height)
+    {
+      if (x0 < 0)
+        {
+          mask -= x0;
+          data -= 2*x0;
+          x0 = 0;
+        }
+      if (x1 >= _wm_width)
+        x1 = _wm_width-1;
+      v_putmask (data, mask, x0, y, 1 + x1 - x0);
+    }
+}
+
+
+
+void _wm_move2 (char *data, int y, int x0, int x1, int dir)
+{
+  if (y >= 0 && y < _wm_height)
+    {
+      if (x0 < 0)
+        {
+          data -= 2 * x0;
+          x0 = 0;
+        }
+      if (x1 >= _wm_width)
+        x1 = _wm_width-1;
+      if (dir)
+        v_putline (data, x0, y, 1 + x1 - x0);
+      else
+        v_getline (data, x0, y, 1 + x1 - x0);
+    }
+}
+
+
+void _wm_putc2 (char c, int x, int y, int a)
+{
+  if (x >= 0 && x < _wm_width && y >= 0 && y < _wm_height)
+    {
+      v_gotoxy (x, y);
+      v_attrib (a);
+      v_putn (c, 1);
+    }
+}
+
+
+void _wm_puts2 (char *dst, const char *src, int cnt, int a)
+{
+  while (cnt > 0)
+    {
+      *dst++ = *src++;
+      *dst++ = (char)a;
+      --cnt;
+    }
+}
+
+
+void _wm_putsa2 (char *dst, const char *src, int cnt)
+{
+  memcpy (dst, src, (size_t)(2 * cnt));
+}
+
+
+void _wm_puta2 (char *dst, int a, int cnt)
+{
+  ++dst;
+  while (cnt > 0)
+    {
+      *dst = (char)a;
+      dst += 2;
+      --cnt;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/winmgr2.h
===================================================================
--- trunk/src/emx/src/lib/Attic/video/winmgr2.h	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/winmgr2.h	(revision 18)
@@ -0,0 +1,84 @@
+/* winmgr1.h */
+
+#define FALSE 0
+#define TRUE  1
+
+#define WM_USED 0x6d77fa10
+
+struct _wm_window
+{
+  int used;               /* WM_USED, if this slot is used                 */
+  int visible;            /* TRUE, if whole window is visible              */
+  int display;            /* open && update_flag                           */
+  int update_flag;        /* TRUE, if updating screen immediately          */
+  int update_req;         /* TRUE, if screen window has to be updated      */
+  int open;               /* TRUE, if window open                          */
+  int wrap;               /* TRUE, if end-of-line-wrap is activated        */
+  char *data;             /* Window contents                               */
+  char *mask;             /* Visible characters of window (FALSE/TRUE)     */
+  int masksize;           /* Length of mask array                          */
+  int x0, y0, x1, y1;     /* Usable area of window                         */
+  int bx0, by0, bx1, by1; /* Whole window including border                 */
+  int ax, ay;             /* x0-bx0 and y0-by0 (border width 0 or 1)       */
+  int border;             /* Border flag                                   */
+  int battr;              /* Border attributes                             */
+  int wattr;              /* Window contents attributes                    */
+  int x, y;               /* Cursor position                               */
+  int width;              /* Window width                                  */
+  int height;             /* Window height                                 */
+  int bwidth;             /* Window width including border                 */
+  int bheight;            /* Window height including border                */
+  int c_vis;              /* TRUE: visible cursor, FALSE: invisible cursor */
+  int c_start, c_end;     /* Cursor type                                   */
+};
+
+extern wm_handle _wm_tab;
+extern wm_handle *_wm_idx;
+
+extern char *_wm_screen;
+extern char *_wm_line;
+
+extern int _wm_width;
+extern int _wm_height;
+extern int _wm_count;
+extern int _wm_max;
+extern int _wm_saved_cstart;
+extern int _wm_saved_cend;
+extern int _wm_saved_x;
+extern int _wm_saved_y;
+
+extern wm_handle _wm_cursor;           /* Window selected by wm_cursor */
+extern int _wm_c_hide;                 /* Cursor mode                  */
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+#define DATA(wh,x,y) ((wh)->data[2*((x)+(y)*(wh)->bwidth)])
+#define MASK(wh,x,y) ((wh)->mask[(x)+(y)*(wh)->bwidth])
+
+void _wm_puts_len (wm_handle wh, const char *p, int len);
+
+void _wm_cursor1 (void);
+void _wm_put1 (wm_handle wh);
+void _wm_clrline1 (wm_handle wh, int y, int x0, int x1);
+void _wm_clr1 (wm_handle wh);
+int  _wm_idx1 (wm_handle wh);
+void _wm_unhide1 (wm_handle wh, wm_handle new_wh);
+void _wm_copy1 (wm_handle wh, wm_handle old_wh);
+void _wm_hide1 (void);
+int  _wm_jam1 (wm_handle wh1, wm_handle wh2);
+void _wm_store1 (wm_handle wh, int x, int y, char c, int a);
+void _wm_line1 (wm_handle wh, int y);
+void _wm_hide2 (wm_handle wh1, wm_handle wh2);
+void _wm_border1 (wm_handle wh, int title_flag, int title_attr,
+    const char *title);
+void _wm_allvisible (wm_handle wh);
+
+void _wm_putc2 (char c, int x, int y, int a);
+void _wm_puts2 (char *dst, const char *src, int cnt, int a);
+void _wm_putsa2 (char *dst, const char *src, int cnt);
+void _wm_puta2 (char *dst, int a, int cnt);
+void _wm_move2 (char *data, int y, int x0, int x1, int dir);
+void _wm_line2 (char *mask, char *data, int y, int x0, int x1);
+void _wm_copy2 (char *mask, char *dst, char *src, int width);
+void _wm_clrline2 (char *dst, int width, char a);
Index: trunk/src/emx/src/lib/Attic/video/wmattall.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmattall.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmattall.c	(revision 18)
@@ -0,0 +1,28 @@
+/* wmattall.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_attrib_all (wm_handle wh, int a)
+{
+  int i, x, y, height, width, bwidth;
+  char *mem;
+
+  y = wh->ay;
+  x = wh->ax;
+  height = wh->height;
+  width = wh->width;
+  bwidth = 2 * wh->bwidth;
+  mem = &DATA (wh, x, y);
+  for (i = 0; i < height; ++i)
+    {
+      _wm_puta2 (mem, a, width);
+      mem += bwidth;
+      ++y;
+    }
+  if (wh->display)
+    _wm_put1 (wh);
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmbacksp.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmbacksp.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmbacksp.c	(revision 18)
@@ -0,0 +1,25 @@
+/* wmbacksp.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_backsp (wm_handle wh, int count)
+{
+  if (wh->used != WM_USED)
+    return;
+  while (count > 0)
+    {
+      --count;
+      if (wh->x <= 0)
+        {
+          if (wh->y > 0)
+            {
+              wh->x = wh->width - 1;
+              --wh->y;
+            }
+        }
+      else
+        --wh->x;
+    }
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmborder.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmborder.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmborder.c	(revision 18)
@@ -0,0 +1,19 @@
+/* wmborder.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_border (wm_handle wh, int bflag, int battr, const char *title,
+                int tflag, int tattr)
+{
+  if (wh->used != WM_USED || bflag == 0 || wh->border == 0)
+    return;
+  wh->border = bflag;
+  wh->battr = battr;
+  _wm_border1 (wh, tflag, tattr, title);
+  if (wh->display)
+    _wm_put1 (wh);
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmbottom.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmbottom.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmbottom.c	(revision 18)
@@ -0,0 +1,26 @@
+/* wmbottom.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_bottom (wm_handle wh)
+{
+  int i, idx;
+  wm_handle p;
+
+  if (wh->used != WM_USED)
+    return;
+  idx = _wm_idx1 (wh);
+  if (idx < 0)
+    return;
+  for (i = idx; i-1 >= 0; --i)
+    _wm_idx[i] = _wm_idx[i-1];
+  _wm_idx[0] = wh;
+  _wm_hide1 ();
+  for (i = 1; i <= idx; ++i)
+    {
+      p = _wm_idx[i];
+      if (p->open && _wm_jam1 (p, wh))
+        _wm_put1 (p);
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmclear.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmclear.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmclear.c	(revision 18)
@@ -0,0 +1,16 @@
+/* wmclear.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_clear (wm_handle wh)
+{
+  if (wh->used != WM_USED)
+    return;
+  _wm_clr1 (wh);
+  if (wh->display)
+    _wm_put1 (wh);
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmclose.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmclose.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmclose.c	(revision 18)
@@ -0,0 +1,31 @@
+/* wmclose.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_close (wm_handle wh)
+{
+  int i;
+  wm_handle p;
+
+  if (wh->used != WM_USED)
+    return;
+  if (wh->open)
+    {
+      _wm_unhide1 (wh, NULL);
+      wh->open = FALSE;
+      wh->display = FALSE;
+      _wm_hide1 ();
+      for (i = 0; i < _wm_count; ++i)
+        {
+          p = _wm_idx[i];
+          if (p == wh)
+            break;
+          if (p->open && _wm_jam1 (p, wh))
+            _wm_put1 (p);
+        }
+      wh->visible = FALSE;
+      _wm_cursor1 ();
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmclosea.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmclosea.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmclosea.c	(revision 18)
@@ -0,0 +1,25 @@
+/* wmclosea.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_close_all (void)
+{
+  int i;
+  wm_handle p;
+
+  for (i = _wm_count-1; i >= 0; --i)
+    {
+      p = _wm_idx[i];
+      if (p->open)
+        {
+          _wm_unhide1 (p, NULL);
+          p->open = FALSE;
+          p->display = FALSE;
+          p->visible = FALSE;
+        }
+    }
+  _wm_hide1 ();
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmclreol.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmclreol.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmclreol.c	(revision 18)
@@ -0,0 +1,16 @@
+/* wmclreol.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_clr_eol (wm_handle wh, int x, int y)
+{
+  if (wh->used != WM_USED)
+    return;
+  _wm_clrline1 (wh, y+wh->ay, x+wh->ax, wh->width-1+wh->ax);
+  if (wh->display)
+    _wm_line1 (wh, y+wh->ay);
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmctype.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmctype.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmctype.c	(revision 18)
@@ -0,0 +1,16 @@
+/* wmctype.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_ctype (wm_handle wh, int start, int end)
+{
+  if (wh->used != WM_USED)
+    return;
+  if (start >= 0 && start < 32 && end >= 0 && end < 32)
+    {
+      wh->c_start = start;
+      wh->c_end = end;
+    }
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmdelcha.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmdelcha.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmdelcha.c	(revision 18)
@@ -0,0 +1,40 @@
+/* wmdelcha.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_del_char (wm_handle wh, int x, int y, int count)
+{
+  char *mem;
+  int idx, px, py, len;
+
+  if (wh->used != WM_USED || count <= 0)
+    return;
+  if (x + count >= wh->width)
+    count = wh->width - x;
+  len = wh->width - x - count;
+  px = x + wh->ax;
+  py = y + wh->ay;
+  idx = px + py * wh->bwidth;
+  mem = &wh->data[2*idx];
+  memmove (mem, mem + 2 * count, (size_t)(2 * len));
+  while (count > 0 && x+len < wh->width)
+    {
+      mem[2*len+0] = ' ';
+      mem[2*len+1] = (char)wh->wattr;
+      --count; ++len;
+    }
+  if (wh->display)
+    {
+      px = x+wh->x0;
+      py = y+wh->y0;
+      if (wh->visible)
+        _wm_move2 (mem, py, px, wh->bx1, 1);
+      else
+        _wm_line2 (&wh->mask[idx], mem, py, px, wh->bx1);
+    }
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmdelete.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmdelete.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmdelete.c	(revision 18)
@@ -0,0 +1,31 @@
+/* wmdelete.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#if defined (__IBMC__)
+#define __TILED__
+#endif
+#include <stdlib.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+
+void wm_delete (wm_handle wh)
+{
+  int i, idx;
+
+  if (wh->used != WM_USED)
+    return;
+  idx = _wm_idx1 (wh);
+  if (idx < 0)
+    return;
+  --_wm_count;
+  for (i = idx; i < _wm_count; ++i)
+    _wm_idx[i] = _wm_idx[i+1];
+  _tfree (wh->data);
+  free (wh->mask);
+  wh->used = 0;
+  if (_wm_cursor == wh)
+    {
+      _wm_cursor = NULL;
+      _wm_cursor1 ();
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmdellin.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmdellin.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmdellin.c	(revision 18)
@@ -0,0 +1,31 @@
+/* wmdellin.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_del_line (wm_handle wh, int y, int count)
+{
+  int i;
+  char *p1, *p2;
+
+  if (wh->used != WM_USED || count <= 0)
+    return;
+  if (count > wh->height)
+    count = wh->height;
+  for (i = y; i < wh->height-count; ++i)
+    {
+      p1 = &DATA (wh, wh->ax, i+wh->ay);
+      p2 = p1 + 2 * count * wh->bwidth;
+      memmove (p1, p2, (size_t)(2 * wh->width));
+    }
+  for (i = wh->height-count; i < wh->height; ++i)
+    _wm_clrline1 (wh, i+wh->ay, wh->ax,
+                  wh->width-1+wh->ax);
+  if (wh->display)
+    _wm_put1 (wh);
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+} 
+
Index: trunk/src/emx/src/lib/Attic/video/wmdimen.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmdimen.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmdimen.c	(revision 18)
@@ -0,0 +1,13 @@
+/* wmdimen.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_dimen (wm_handle wh, int *width, int *height)
+{
+  if (width != NULL)
+    *width = wh->width;
+  if (height != NULL)
+    *height = wh->height;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmdown.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmdown.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmdown.c	(revision 18)
@@ -0,0 +1,21 @@
+/* wmdown.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_down (wm_handle wh)
+{
+  int idx;
+  wm_handle p;
+
+  if (wh->used != WM_USED)
+    return;
+  idx = _wm_idx1 (wh);
+  if (idx < 0 || idx == 0)
+    return;
+  _wm_idx[idx] = _wm_idx[idx-1]; _wm_idx[idx-1] = wh;
+  _wm_hide1 ();                                      /* Hide lower windows */
+  p = _wm_idx[idx];
+  if (p->open && _wm_jam1 (wh, p))
+    _wm_put1 (p);
+}
Index: trunk/src/emx/src/lib/Attic/video/wmexit.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmexit.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmexit.c	(revision 18)
@@ -0,0 +1,38 @@
+/* wmexit.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#if defined (__IBMC__)
+#define __TILED__
+#endif
+#include <stdlib.h>
+#include <sys/video.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_exit (void)
+{
+  int i;
+  wm_handle p;
+
+  if (_wm_tab != NULL)
+    {
+      for (i = 0; i < _wm_max; ++i)
+        {
+          p = &_wm_tab[i];
+          if (p->used == WM_USED)
+            {
+              _tfree (p->data);
+              free (p->mask);
+            }
+        }
+      free (_wm_tab);
+      free (_wm_idx);
+      _tfree (_wm_screen);
+      _tfree (_wm_line);
+      _wm_tab = NULL;
+      _wm_idx = NULL;
+      _wm_screen = NULL;
+      _wm_idx = NULL;
+      v_gotoxy (_wm_saved_x, _wm_saved_y);
+      v_ctype (_wm_saved_cstart, _wm_saved_cend);
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmfind.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmfind.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmfind.c	(revision 18)
@@ -0,0 +1,25 @@
+/* wmfind.c (emx+gcc) -- Copyright (c) 1987-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+wm_handle wm_find (int x, int y)
+{
+  int i;
+  wm_handle wh;
+
+  for (i = 0; i < _wm_count; ++i)
+    {
+      wh = _wm_idx[i];
+      if (wh->open && x >= wh->bx0 && y >= wh->by0
+          && x <= wh->bx1 && y <= wh->by1)
+        {
+          if (wh->visible)
+            return wh;
+          else if (MASK (wh, x-wh->bx0, y-wh->by0))
+            return wh;
+        }
+    }
+  return NULL;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmfopen.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmfopen.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmfopen.c	(revision 18)
@@ -0,0 +1,76 @@
+/* wmfopen.c (emx+gcc) -- Copyright (c) 1993-2000 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/winmgr.h>
+#include <emx/io.h>
+#include "winmgr2.h"
+
+static int _wmflush (FILE *stream, int c)
+{
+  int n;
+  wm_handle wh;
+
+  if (c == _FLUSH_FILL)
+    return -1;
+  wh = (wm_handle)stream->_tmpidx;
+  n = stream->_ptr - stream->_buffer;
+  if (n > 0)
+    {
+      if (c >= 0 && n < stream->_buf_size)
+        {
+          *stream->_ptr = (char)c;
+          ++n;
+          c = -1;               /* Don't write character separately */
+        }
+      wm_putsn (wh, stream->_buffer, n);
+    }
+  stream->_ptr = stream->_buffer;
+  stream->_wcount = stream->_buf_size;
+  if (c >= 0)
+    {
+      if (stream->_buf_size == 0)
+        wm_putc (wh, c);
+      else
+        {
+          *stream->_ptr++ = (char)c;
+          --stream->_wcount;
+        }
+    }
+  return 0;
+}
+
+
+FILE *wm_fopen (wm_handle wh)
+{
+  FILE *stream;
+
+  stream = _newstream ();
+  if (stream == NULL)
+    return NULL;
+  stream->_buffer = NULL;
+  stream->_ptr = NULL;
+  stream->_rcount = 0;
+  stream->_wcount = 0;
+  stream->_handle = -1;
+  stream->_flags = _IOOPEN|_IOSPECIAL|_IOBUFNONE|_IOWRT|_IONBF;
+  stream->_buf_size = 0;
+  stream->_flush = _wmflush;
+  stream->_tmpidx = (int)wh;
+  if (_setmore (stream, 1) != 0)
+    return NULL;
+  return stream;
+}
+
+
+int wm_fclose (FILE *stream)
+{
+  int result;
+
+  if ((stream->_flags & (_IOOPEN|_IOSPECIAL)) != (_IOOPEN|_IOSPECIAL)
+      || stream->_flush != _wmflush)
+    return -1;
+  result = fflush (stream);
+  _closestream (stream);
+  return result;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmgetatt.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmgetatt.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmgetatt.c	(revision 18)
@@ -0,0 +1,9 @@
+/* wmgetatt.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+int wm_get_attrib (wm_handle wh)
+{
+  return wh->wattr;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmgetpos.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmgetpos.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmgetpos.c	(revision 18)
@@ -0,0 +1,13 @@
+/* wmgetpos.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_get_pos (wm_handle wh, int *x, int *y)
+{
+  if (x != NULL)
+    *x = wh->x0;
+  if (y != NULL)
+    *y = wh->y0;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmgetx.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmgetx.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmgetx.c	(revision 18)
@@ -0,0 +1,9 @@
+/* wmgetx.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+int wm_getx (wm_handle wh)
+{
+  return wh->x;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmgetxy.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmgetxy.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmgetxy.c	(revision 18)
@@ -0,0 +1,13 @@
+/* wmgetxy.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_getxy (wm_handle wh, int *x, int *y)
+{
+  if (x != NULL)
+    *x = wh->x;
+  if (y != NULL)
+    *y = wh->y;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmgety.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmgety.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmgety.c	(revision 18)
@@ -0,0 +1,9 @@
+/* wmgety.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+int wm_gety (wm_handle wh)
+{
+  return wh->y;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmgotoxy.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmgotoxy.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmgotoxy.c	(revision 18)
@@ -0,0 +1,16 @@
+/* wmgotoxy.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_gotoxy (wm_handle wh, int x, int y)
+{
+  if (wh->used != WM_USED)
+    return;
+  if (x >= 0 && x < wh->width && y >= 0 && y < wh->height)
+    {
+      wh->x = x;
+      wh->y = y;
+    }
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wminscha.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wminscha.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wminscha.c	(revision 18)
@@ -0,0 +1,39 @@
+/* wminscha.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_ins_char (wm_handle wh, int x, int y, int count)
+{
+  char *mem;
+  int idx, px, py, len;
+
+  if (wh->used != WM_USED || count <= 0)
+    return;
+  if (x+count >= wh->width)
+    count = wh->width-x;
+  len = wh->width-x - count;
+  px = x + wh->ax;
+  py = y + wh->ay;
+  idx = px + py * wh->bwidth;
+  mem = &wh->data[2*idx];
+  memmove (mem + 2 * count, mem, (size_t)(2 * len));
+  while (--count >= 0)
+    {
+      mem[2*count+0] = ' ';
+      mem[2*count+1] = (char)wh->wattr;
+    }
+  if (wh->display)
+    {
+      px = x+wh->x0;
+      py = y+wh->y0;
+      if (wh->visible)
+        _wm_move2 (mem, py, px, wh->bx1, 1);
+      else
+        _wm_line2 (&wh->mask[idx], mem, py, px, wh->bx1);
+    }
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wminslin.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wminslin.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wminslin.c	(revision 18)
@@ -0,0 +1,30 @@
+/* wminslin.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_ins_line (wm_handle wh, int y, int count)
+{
+  int i;
+  char *p1, *p2;
+
+  if (wh->used != WM_USED || count <= 0)
+    return;
+  if (count > wh->height)
+    count = wh->height;
+  for (i = wh->height - count - 1; i >= y; --i)
+    {
+      p1 = &DATA (wh, wh->ax, i+wh->ay);
+      p2 = p1 + 2 * count * wh->bwidth;
+      memmove (p2, p1, (size_t)(2 * wh->width));
+    }
+  for (i = 0; i < count; ++i)
+    _wm_clrline1 (wh, i+y+wh->ay, wh->ax,
+                  wh->width-1+wh->ax);
+  if (wh->display)
+    _wm_put1 (wh);
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmmove.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmmove.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmmove.c	(revision 18)
@@ -0,0 +1,38 @@
+/* wmmove.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_move (wm_handle wh, int new_x, int new_y)
+{
+  int i, dx, dy;
+  wm_handle p;
+  struct _wm_window new_win, old_win;
+
+  if (wh->used != WM_USED)
+    return;
+  dx = new_x - wh->x0;
+  dy = new_y - wh->y0;
+  old_win = new_win = *wh;
+  new_win.x0 += dx; new_win.x1 += dx; new_win.bx0 += dx; new_win.bx1 += dx;
+  new_win.y0 += dy; new_win.y1 += dy; new_win.by0 += dy; new_win.by1 += dy;
+  if (new_win.open)
+    {
+      _wm_unhide1 (wh, &new_win);                         /* Show background */
+      *wh = new_win;
+      _wm_copy1 (wh, &old_win);                           /* Save background */
+      _wm_hide1 ();                                    /* Hide lower windows */
+      for (i = 0; i < _wm_count; ++i)
+        {
+          p = _wm_idx[i];
+          if (p == wh)
+            break;
+          if (p->open && _wm_jam1 (p, &old_win))
+            _wm_put1 (p);
+        }
+      _wm_put1 (wh);                              /* Restore window contents */
+    }
+  else
+    *wh = new_win;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmopen.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmopen.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmopen.c	(revision 18)
@@ -0,0 +1,20 @@
+/* wmopen.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_open (wm_handle wh)
+{
+  if (wh->used != WM_USED)
+    return;
+  if (!wh->open)
+    {
+      wh->open = TRUE;
+      wh->display = wh->update_flag;
+      _wm_copy1 (wh, NULL);
+      _wm_hide1 ();
+      _wm_put1 (wh);
+      _wm_cursor1 ();
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmprintf.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmprintf.c	(revision 18)
@@ -0,0 +1,16 @@
+/* wmprintf.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdarg.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+int wm_printf (wm_handle wh, const char *fmt, ...)
+{
+  va_list arg_ptr;
+  int result;
+
+  va_start (arg_ptr, fmt);
+  result = wm_vprintf (wh, fmt, arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputaat.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputaat.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputaat.c	(revision 18)
@@ -0,0 +1,53 @@
+/* wmputaat.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_puta_at (wm_handle wh, int x, int y, int a, int len)
+{
+  int max, cnt, i, px, py, mx, my;
+  char *mem;
+
+  while (len > 0)
+    {
+      max = wh->width - x;
+      if (len < max)
+        cnt = len;
+      else
+        cnt = max;
+      if (cnt > 0)
+        {
+          px = x + wh->ax;
+          py = y + wh->ay;
+          i = px + py * wh->bwidth;
+          mem = &wh->data[2*i];
+          _wm_puta2 (mem, a, cnt);                      /* Copy to memory */
+          if (wh->display)            /* Copy from memory to video buffer */
+            {
+              mx = x+wh->x0;
+              my = y+wh->y0;
+              if (wh->visible)
+                _wm_move2 (mem, my, mx, mx+cnt-1, 1);
+              else
+                _wm_line2 (&wh->mask[i], mem, my, mx, mx+cnt-1);
+            }
+          else
+            wh->update_req = TRUE;
+          if (cnt == max)
+            {
+              if (wh->wrap)
+                {
+                  x = 0;
+                  ++y;
+                  if (y >= wh->height)
+                    break;
+                }
+              else
+                break;
+            }
+          else
+            x += cnt;
+        }
+      len -= cnt;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputc.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputc.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputc.c	(revision 18)
@@ -0,0 +1,44 @@
+/* wmputc.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_putc (wm_handle wh, char c)
+{
+  int mx, my;
+
+  switch (c)
+    {
+    case '\n':
+      wh->x = 0;
+      ++wh->y;
+      break;
+    default:
+      mx = wh->x+wh->ax;
+      my = wh->y+wh->ay;
+      if (wh->display)
+        {
+          if (wh->visible || MASK (wh, mx, my))
+            _wm_putc2 (c, wh->x+wh->x0, wh->y+wh->y0, wh->wattr);
+        }
+      else
+        wh->update_req = TRUE;
+      _wm_store1 (wh, mx, my, c, wh->wattr);
+      if (++wh->x >= wh->width)
+        {
+          if (wh->wrap)
+            {
+              wh->x = 0;
+              ++wh->y;
+            }
+          else
+            --wh->x;
+        }
+    }
+  if (wh->y >= wh->height)
+    {
+      --wh->y;
+      wm_scroll (wh, 1);
+    }
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputca.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputca.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputca.c	(revision 18)
@@ -0,0 +1,36 @@
+/* wmputca.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_putca (wm_handle wh, char c, int a)
+{
+  int mx, my;
+
+  mx = wh->x + wh->ax;
+  my = wh->y + wh->ay;
+  if (wh->display)
+    {
+      if (wh->visible || MASK (wh, mx, my))
+        _wm_putc2 (c, wh->x+wh->x0, wh->y+wh->y0, a);
+    }
+  else
+    wh->update_req = TRUE;
+  _wm_store1 (wh, mx, my, c, a);
+  if (++wh->x >= wh->width)
+    {
+      if (wh->wrap)
+        {
+          wh->x = 0;
+          ++wh->y;
+        }
+      else
+        --wh->x;
+    }
+  if (wh->y >= wh->height)
+    {
+      --wh->y;
+      wm_scroll (wh, 1);
+    }
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputcaa.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputcaa.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputcaa.c	(revision 18)
@@ -0,0 +1,24 @@
+/* wmputcaa.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_putca_at (wm_handle wh, int x, int y, char c, int a)
+{
+  int mx, my;
+
+  if (x >= 0 && x < wh->width && y >= 0 && y < wh->height)
+    {
+      mx = x+wh->ax;
+      my = y+wh->ay;
+      if (wh->display)
+        {
+          if (wh->visible || MASK (wh, mx, my))
+            _wm_putc2 (c, x+wh->x0, y+wh->y0, a);
+        }
+      else
+        wh->update_req = TRUE;
+      _wm_store1 (wh, mx, my, c, a);
+    }
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputcat.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputcat.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputcat.c	(revision 18)
@@ -0,0 +1,24 @@
+/* wmputcat.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_putc_at (wm_handle wh, int x, int y, char c)
+{
+  int mx, my;
+
+  if (x >= 0 && x < wh->width && y >= 0 && y < wh->height)
+    {
+      mx = x + wh->ax;
+      my = y + wh->ay;
+      if (wh->display)
+        {
+          if (wh->visible || MASK (wh, mx, my))
+            _wm_putc2 (c, x+wh->x0, y+wh->y0, wh->wattr);
+        }
+      else
+        wh->update_req = TRUE;
+      _wm_store1 (wh, mx, my, c, wh->wattr);
+    }
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputs.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputs.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputs.c	(revision 18)
@@ -0,0 +1,90 @@
+/* wmputs.c (emx+gcc) -- Copyright (c) 1987-2000 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+static void _wm_puts1 (wm_handle wh, const char *p, int len)
+{
+  int max, cnt, i, px, py, mx, my;
+  char *mem;
+
+  while (len > 0)
+    {
+      max = wh->width-wh->x;
+      if (len < max)
+        cnt = len;
+      else
+        cnt = max;
+      if (cnt > 0)
+        {
+          px = wh->x+wh->ax;
+          py = wh->y+wh->ay;
+          i = px+py*wh->bwidth;
+          mem = &wh->data[2*i];
+          _wm_puts2 (mem, p, cnt, wh->wattr);           /* Copy to memory */
+          if (wh->display)            /* Copy from memory to video buffer */
+            {
+              mx = wh->x+wh->x0;
+              my = wh->y+wh->y0;
+              if (wh->visible)
+                _wm_move2 (mem, my, mx, mx+cnt-1, 1);
+              else
+                _wm_line2 (&wh->mask[i], mem, my, mx, mx+cnt-1);
+            }
+          else
+            wh->update_req = TRUE;
+          if (cnt == max)
+            {
+              if (wh->wrap)
+                {
+                  wh->x = 0;
+                  ++wh->y;
+                  if (wh->y >= wh->height)
+                    {
+                      --wh->y;
+                      wm_scroll (wh, 1);
+                    }
+                }
+              else
+                {
+                  wh->x = wh->width - 1;
+                  break;
+                }
+            }
+          else
+            wh->x += cnt;
+        }
+      len -= cnt;
+      p += cnt;
+    }
+}
+
+
+void wm_putsn (wm_handle wh, const char *p, int len)
+{
+  const char *q;
+  int n;
+
+  do
+    {
+      q = memchr (p, '\n', (size_t)len);
+      if (q == NULL)
+        _wm_puts1 (wh, p, len);
+      else
+        {
+          n = q - p;
+          _wm_puts1 (wh, p, n);
+          wm_putc (wh, '\n');
+          p = q + 1;
+          len -= n + 1;
+        }
+    } while (q != NULL);
+}
+
+
+void wm_puts (wm_handle wh, const char *p)
+{
+  wm_putsn (wh, p, (int)strlen (p));
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputsa.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputsa.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputsa.c	(revision 18)
@@ -0,0 +1,60 @@
+/* wmputsa.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_putsa (wm_handle wh, const char *p, int len)
+{
+  int max, cnt, i, px, py, mx, my;
+  char *mem;
+
+  while (len > 0)
+    {
+      max = wh->width-wh->x;
+      if (len < max)
+        cnt = len;
+      else
+        cnt = max;
+      if (cnt > 0)
+        {
+          px = wh->x + wh->ax;
+          py = wh->y + wh->ay;
+          i = px + py * wh->bwidth;
+          mem = &wh->data[2*i];
+          _wm_putsa2 (mem, p, cnt);                     /* Copy to memory */
+          if (wh->display)            /* Copy from memory to video buffer */
+            {
+              mx = wh->x+wh->x0;
+              my = wh->y+wh->y0;
+              if (wh->visible)
+                _wm_move2 (mem, my, mx, mx+cnt-1, 1);
+              else
+                _wm_line2 (&wh->mask[i], mem, my, mx, mx+cnt-1);
+            }
+          else
+            wh->update_req = TRUE;
+          if (cnt == max)
+            {
+              if (wh->wrap)
+                {
+                  wh->x = 0;
+                  ++wh->y;
+                  if (wh->y >= wh->height)
+                    {
+                      --wh->y;
+                      wm_scroll (wh, 1);
+                    }
+                }
+              else
+                {
+                  wh->x = wh->width-1;
+                  break;
+                }
+            }
+          else
+            wh->x += cnt;
+        }
+      len -= cnt;
+      p += 2*cnt;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputsaa.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputsaa.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputsaa.c	(revision 18)
@@ -0,0 +1,54 @@
+/* wmputsaa.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_putsa_at (wm_handle wh, int x, int y, const char *p, int len)
+{
+  int max, cnt, i, px, py, mx, my;
+  char *mem;
+
+  while (len > 0)
+    {
+      max = wh->width-x;
+      if (len < max)
+        cnt = len;
+      else
+        cnt = max;
+      if (cnt > 0)
+        {
+          px = x + wh->ax;
+          py = y + wh->ay;
+          i = px + py * wh->bwidth;
+          mem = &wh->data[2*i];
+          _wm_putsa2 (mem, p, cnt);                     /* Copy to memory */
+          if (wh->display)            /* Copy from memory to video buffer */
+            {
+              mx = x + wh->x0;
+              my = y + wh->y0;
+              if (wh->visible)
+                _wm_move2 (mem, my, mx, mx+cnt-1, 1);
+              else
+                _wm_line2 (&wh->mask[i], mem, my, mx, mx+cnt-1);
+            }
+          else
+            wh->update_req = TRUE;
+          if (cnt == max)
+            {
+              if (wh->wrap)
+                {
+                  x = 0;
+                  ++y;
+                  if (y >= wh->height)
+                    break;
+                }
+              else
+                break;
+            }
+          else
+            x += cnt;
+        }
+      len -= cnt;
+      p += 2*cnt;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmputsat.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmputsat.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmputsat.c	(revision 18)
@@ -0,0 +1,56 @@
+/* wmputsat.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_puts_at (wm_handle wh, int x, int y, const char *p)
+{
+  int max, len, cnt, i, px, py, mx, my;
+  char *mem;
+
+  len = (int)strlen (p);
+  while (len > 0)
+    {
+      max = wh->width-x;
+      if (len < max)
+        cnt = len;
+      else
+        cnt = max;
+      if (cnt > 0)
+        {
+          px = x + wh->ax;
+          py = y + wh->ay;
+          i = px + py * wh->bwidth;
+          mem = &wh->data[2*i];
+          _wm_puts2 (mem, p, cnt, wh->wattr);           /* Copy to memory */
+          if (wh->display)            /* Copy from memory to video buffer */
+            {
+              mx = x+wh->x0;
+              my = y+wh->y0;
+              if (wh->visible)
+                _wm_move2 (mem, my, mx, mx+cnt-1, 1);
+              else
+                _wm_line2 (&wh->mask[i], mem, my, mx, mx+cnt-1);
+            }
+          else
+            wh->update_req = TRUE;
+          if (cnt == max)
+            {
+              if (wh->wrap)
+                {
+                  x = 0;
+                  ++y;
+                  if (y >= wh->height)
+                    break;
+                }
+              else
+                break;
+            }
+          else
+            x += cnt;
+        }
+      len -= cnt;
+      p += cnt;
+    }
+}
Index: trunk/src/emx/src/lib/Attic/video/wmscroll.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmscroll.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmscroll.c	(revision 18)
@@ -0,0 +1,30 @@
+/* wmscroll.c (emx+gcc) -- Copyright (c) 1987-1994 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_scroll (wm_handle wh, int count)
+{
+  int y;
+  char *p1, *p2;
+
+  if (wh->used != WM_USED)
+    return;
+  if (count > wh->height)
+    count = wh->height;
+  for (y = 0; y < wh->height - count; ++y)
+    {
+      p1 = &DATA (wh, wh->ax, y + wh->ay);
+      p2 = p1 + 2 * count * wh->bwidth;
+      memmove (p1, p2, (size_t)(2 * wh->width));
+    }
+  for (y = wh->height-count; y < wh->height; ++y)
+    _wm_clrline1 (wh, y + wh->ay, wh->ax,
+                  wh->width - 1 + wh->ax);
+  if (wh->display)
+    _wm_put1 (wh);
+  else
+    wh->update_req = TRUE;
+  _wm_cursor1 ();
+}
Index: trunk/src/emx/src/lib/Attic/video/wmtop.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmtop.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmtop.c	(revision 18)
@@ -0,0 +1,20 @@
+/* wmtop.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_top (wm_handle wh)
+{
+  int i, idx;
+
+  if (wh->used != WM_USED)
+    return;
+  idx = _wm_idx1 (wh);
+  if (idx < 0)
+    return;
+  for (i = idx; i+1 < _wm_count; ++i)
+    _wm_idx[i] = _wm_idx[i+1];
+  _wm_idx[_wm_count-1] = wh;
+  _wm_hide1 ();                                 /* Hide lower windows      */
+  _wm_put1 (wh);                                /* Restore window contents */
+}
Index: trunk/src/emx/src/lib/Attic/video/wmup.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmup.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmup.c	(revision 18)
@@ -0,0 +1,18 @@
+/* wmup.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_up (wm_handle wh)
+{
+  int idx;
+
+  if (wh->used != WM_USED)
+    return;
+  idx = _wm_idx1 (wh);
+  if (idx < 0 || idx+1 == _wm_count)
+    return;
+  _wm_idx[idx] = _wm_idx[idx+1]; _wm_idx[idx+1] = wh;
+  _wm_hide1 ();                                 /* Hide lower windows      */
+  _wm_put1 (wh);                                /* Restore window contents */
+}
Index: trunk/src/emx/src/lib/Attic/video/wmupdate.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmupdate.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmupdate.c	(revision 18)
@@ -0,0 +1,15 @@
+/* wmupdate.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_update (wm_handle wh, int flag)
+{
+  if (wh->used != WM_USED)
+    return;
+  if (wh->update_req)
+    _wm_put1 (wh);                            /* Restore window contents */
+  wh->update_req = FALSE;
+  wh->update_flag = flag;
+  wh->display = flag && wh->open;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmvprint.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmvprint.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmvprint.c	(revision 18)
@@ -0,0 +1,47 @@
+/* wmvprint.c (emx+gcc) -- Copyright (c) 1987-2000 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/winmgr.h>
+#include <emx/io.h>
+#include "winmgr2.h"
+
+static int _wm_flush (FILE *stream, int c)
+{
+  int n;
+  wm_handle wh;
+
+  wh = (wm_handle)stream->_tmpidx;
+  n = stream->_ptr - stream->_buffer;
+  if (n > 0)
+    wm_putsn (wh, stream->_buffer, n);
+  stream->_ptr = stream->_buffer;
+  *stream->_ptr++ = (char)c;
+  stream->_wcount = stream->_buf_size - 1;
+  return 0;
+}
+
+
+int wm_vprintf (wm_handle wh, const char *fmt, va_list arg_ptr)
+{
+  FILE trick;
+  struct _file2 trick2;
+  int result;
+  char buf[512];
+
+  trick._buffer = buf;
+  trick._ptr = buf;
+  trick._rcount = 0;
+  trick._wcount = sizeof (buf);
+  trick._handle = -1;
+  trick._flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOWRT;
+  trick._buf_size = sizeof (buf);
+  trick._flush = _wm_flush;
+  trick._tmpidx = (int)wh;
+  trick._ungetc_count = 0;
+  _setdummymore (&trick, &trick2);
+  result = _output (&trick, fmt, arg_ptr);
+  _wm_flush (&trick, 0);
+  _wm_cursor1 ();
+  return result;
+}
Index: trunk/src/emx/src/lib/Attic/video/wmwrap.c
===================================================================
--- trunk/src/emx/src/lib/Attic/video/wmwrap.c	(revision 18)
+++ trunk/src/emx/src/lib/Attic/video/wmwrap.c	(revision 18)
@@ -0,0 +1,11 @@
+/* wmwrap.c (emx+gcc) -- Copyright (c) 1987-1993 by Eberhard Mattes */
+
+#include <sys/winmgr.h>
+#include "winmgr2.h"
+
+void wm_wrap (wm_handle wh, int wrap_flag)
+{
+  if (wh->used != WM_USED)
+    return;
+  wh->wrap = wrap_flag;
+}
Index: trunk/src/emx/src/lib/add_libc.cmd
===================================================================
--- trunk/src/emx/src/lib/add_libc.cmd	(revision 18)
+++ trunk/src/emx/src/lib/add_libc.cmd	(revision 18)
@@ -0,0 +1,54 @@
+@echo off
+setlocal
+if "%1"=="st" goto ok_st
+if "%1"=="mt" goto ok_mt
+:usage
+echo Usage: add_libc st
+echo        add_libc mt
+goto end
+
+:ok_st
+set n=st\c.a
+goto ok2
+
+:ok_mt
+set n=mt\c.a
+goto ok2
+
+:ok2
+if not "%2"=="" goto usage
+ar d \emx\lib\%n% __.SYMDEF
+cd conv\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\ctype\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\emxload\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\io\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\locale\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\malloc\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\math\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\mbyte\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\misc\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\nls\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\process\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\startup\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\str\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\termios\%1
+ar r \emx\lib\%n% *.o
+cd ..\..\time\%1
+ar r \emx\lib\%n% *.o
+cd ..\..
+ar s \emx\lib\%n%
+:end
+endlocal
Index: trunk/src/emx/src/lib/alias/386/emxalias.cmd
===================================================================
--- trunk/src/emx/src/lib/alias/386/emxalias.cmd	(revision 18)
+++ trunk/src/emx/src/lib/alias/386/emxalias.cmd	(revision 18)
@@ -0,0 +1,1 @@
+@echo .stabs "_%1", 11, 0, 0, 0; .stabs "_%2", 1, 0, 0, 0|as -o %3
Index: trunk/src/emx/src/lib/alias/makefile
===================================================================
--- trunk/src/emx/src/lib/alias/makefile	(revision 18)
+++ trunk/src/emx/src/lib/alias/makefile	(revision 18)
@@ -0,0 +1,509 @@
+#
+# /emx/src/lib/alias/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.PHONY: clean default alias dstlib alias1 alias2
+
+LIBALIAS=$(L)c_alias.a
+
+default: alias
+
+alias .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(LIBALIAS)
+
+clean:
+	-del $(CPU)\*.o $(DELOPT)
+
+access.o:
+	emxalias access _access access.o
+acosl.o:
+	emxalias acosl _acosl acosl.o
+alarm.o:
+	emxalias alarm _alarm alarm.o
+asinl.o:
+	emxalias asinl _asinl asinl.o
+atan2l.o:
+	emxalias atan2l _atan2l atan2l.o
+atanl.o:
+	emxalias atanl _atanl atanl.o
+atold.o:
+	emxalias _atold _atofl atold.o
+bcmp.o:
+	emxalias bcmp _bcmp bcmp.o
+bcopy.o:
+	emxalias bcopy _bcopy bcopy.o
+brk.o:
+	emxalias brk _brk brk.o
+bzero.o:
+	emxalias bzero _bzero bzero.o
+cbrt.o:
+	emxalias cbrt _cbrt cbrt.o
+cbrtl.o:
+	emxalias cbrtl _cbrtl cbrtl.o
+ceill.o:
+	emxalias ceill _ceill ceill.o
+cfgetisp.o:
+	emxalias cfgetispeed _cfgetispeed cfgetisp.o
+cfgetosp.o:
+	emxalias cfgetospeed _cfgetospeed cfgetosp.o
+cfsetisp.o:
+	emxalias cfsetispeed _cfsetispeed cfsetisp.o
+cfsetosp.o:
+	emxalias cfsetospeed _cfsetospeed cfsetosp.o
+chdir.o:
+	emxalias chdir _chdir chdir.o
+chmod.o:
+	emxalias chmod _chmod chmod.o
+chsize.o:
+	emxalias chsize _chsize chsize.o
+close.o:
+	emxalias close _close close.o
+closedir.o:
+	emxalias closedir _closedir closedir.o
+copysig.o:
+	emxalias copysign _copysign copysig.o
+copysigf.o:
+	emxalias copysignf _copysignf copysigf.o
+copysigl.o:
+	emxalias copysignl _copysignl copysigl.o
+coshl.o:
+	emxalias coshl _coshl coshl.o
+cosl.o:
+	emxalias cosl _cosl cosl.o
+creat.o:
+	emxalias creat _creat creat.o
+cuserid.o:
+	emxalias cuserid _cuserid cuserid.o
+daylight.o:
+	emxalias daylight _daylight daylight.o
+dup.o:
+	emxalias dup _dup dup.o
+dup2.o:
+	emxalias dup2 _dup2 dup2.o
+edata.o:
+	emxalias edata _edata edata.o
+end.o:
+	emxalias end _end end.o
+endpwent.o:
+	emxalias endpwent _endpwent endpwent.o
+environ.o:
+	emxalias environ _environ environ.o
+eof.o:
+	emxalias eof _eof eof.o
+etext.o:
+	emxalias etext _etext etext.o
+execl.o:
+	emxalias execl _execl execl.o
+execle.o:
+	emxalias execle _execle execle.o
+execlp.o:
+	emxalias execlp _execlp execlp.o
+execlpe.o:
+	emxalias execlpe _execlpe execlpe.o
+execv.o:
+	emxalias execv _execv execv.o
+execve.o:
+	emxalias execve _execve execve.o
+execvp.o:
+	emxalias execvp _execvp execvp.o
+execvpe.o:
+	emxalias execvpe _execvpe execvpe.o
+expl.o:
+	emxalias expl _expl expl.o
+fabsl.o:
+	emxalias fabsl _fabsl fabsl.o
+fcloseal.o:
+	emxalias fcloseall _fcloseall fcloseal.o
+fcntl.o:
+	emxalias fcntl _fcntl fcntl.o
+fdopen.o:
+	emxalias fdopen _fdopen fdopen.o
+ffs.o:
+	emxalias ffs _ffs ffs.o
+fgetchar.o:
+	emxalias fgetchar _fgetchar fgetchar.o
+fileleng.o:
+	emxalias filelength _filelength fileleng.o
+flock.o:
+	emxalias flock _flock flock.o
+floorl.o:
+	emxalias floorl _floorl floorl.o
+flushall.o:
+	emxalias flushall _flushall flushall.o
+fmodl.o:
+	emxalias fmodl _fmodl fmodl.o
+fnmatch.o:
+	emxalias fnmatch _fnmatch fnmatch.o
+fork.o:
+	emxalias fork _fork fork.o
+fpathcon.o:
+	emxalias fpathconf _fpathconf fpathcon.o
+fputchar.o:
+	emxalias fputchar _fputchar fputchar.o
+frexpl.o:
+	emxalias frexpl _frexpl frexpl.o
+fstat.o:
+	emxalias fstat _fstat fstat.o
+fsync.o:
+	emxalias fsync _fsync fsync.o
+ftime.o:
+	emxalias ftime _ftime ftime.o
+ftruncat.o:
+	emxalias ftruncate _ftruncate ftruncat.o
+ftw.o:
+	emxalias ftw _ftw ftw.o
+gcvt.o:
+	emxalias gcvt _gcvt gcvt.o
+getcwd.o:
+	emxalias getcwd _getcwd getcwd.o
+getegid.o:
+	emxalias getegid _getegid getegid.o
+geteuid.o:
+	emxalias geteuid _geteuid geteuid.o
+getgid.o:
+	emxalias getgid _getgid getgid.o
+getgrgid.o:
+	emxalias getgrgid _getgrgid getgrgid.o
+getgrnam.o:
+	emxalias getgrnam _getgrnam getgrnam.o
+getgroup.o:
+	emxalias getgroups _getgroups getgroup.o
+getlogin.o:
+	emxalias getlogin _getlogin getlogin.o
+getopt.o:
+	emxalias getopt _getopt getopt.o
+getpages.o:
+	emxalias getpagesize _getpagesize getpages.o
+getpass.o:
+	emxalias getpass _getpass getpass.o
+getpgrp.o:
+	emxalias getpgrp _getpgrp getpgrp.o
+getpid.o:
+	emxalias getpid _getpid getpid.o
+getppid.o:
+	emxalias getppid _getppid getppid.o
+getpwent.o:
+	emxalias getpwent _getpwent getpwent.o
+getpwnam.o:
+	emxalias getpwnam _getpwnam getpwnam.o
+getpwuid.o:
+	emxalias getpwuid _getpwuid getpwuid.o
+gettimeo.o:
+	emxalias gettimeofday _gettimeofday gettimeo.o
+getuid.o:
+	emxalias getuid _getuid getuid.o
+getw.o:
+	emxalias getw _getw getw.o
+getwd.o:
+	emxalias getwd _getwd getwd.o
+glob.o:
+	emxalias glob _glob glob.o
+globfree.o:
+	emxalias globfree _globfree globfree.o
+huge.o:
+	emxalias HUGE _HUGE_VAL huge.o
+hypot.o:
+	emxalias hypot _hypot hypot.o
+hypotl.o:
+	emxalias hypotl _hypotl hypotl.o
+index.o:
+	emxalias index _index index.o
+ioctl.o:
+	emxalias ioctl _ioctl ioctl.o
+isascii.o:
+	emxalias isascii _isascii isascii.o
+isatty.o:
+	emxalias isatty _isatty isatty.o
+kill.o:
+	emxalias kill _kill kill.o
+ldexpl.o:
+	emxalias ldexpl _ldexpl ldexpl.o
+lhuge.o:
+	emxalias _LHUGE _LHUGE_VAL lhuge.o
+log10l.o:
+	emxalias log10l _log10l log10l.o
+logl.o:
+	emxalias logl _logl logl.o
+lseek.o:
+	emxalias lseek _lseek lseek.o
+memccpy.o:
+	emxalias memccpy _memccpy memccpy.o
+memicmp.o:
+	emxalias memicmp _memicmp memicmp.o
+mkdir.o:
+	emxalias mkdir _mkdir mkdir.o
+mkstemp.o:
+	emxalias mkstemp _mkstemp mkstemp.o
+mktemp.o:
+	emxalias mktemp _mktemp mktemp.o
+modfl.o:
+	emxalias modfl _modfl modfl.o
+nextaft.o:
+	emxalias nextafter _nextafter nextaft.o
+nextaftf.o:
+	emxalias nextafterf _nextafterf nextaftf.o
+nextaftl.o:
+	emxalias nextafterl _nextafterl nextaftl.o
+open.o:
+	emxalias open _open open.o
+opendir.o:
+	emxalias opendir _opendir opendir.o
+optarg.o:
+	emxalias optarg _optarg optarg.o
+opterr.o:
+	emxalias opterr _opterr opterr.o
+optind.o:
+	emxalias optind _optind optind.o
+optmode.o:
+	emxalias optmode _optmode optmode.o
+optopt.o:
+	emxalias optopt _optopt optopt.o
+optswcha.o:
+	emxalias optswchar _optswchar optswcha.o
+pathconf.o:
+	emxalias pathconf _pathconf pathconf.o
+pause.o:
+	emxalias pause _pause pause.o
+pclose.o:
+	emxalias pclose _pclose pclose.o
+pipe.o:
+	emxalias pipe _pipe pipe.o
+popen.o:
+	emxalias popen _popen popen.o
+powl.o:
+	emxalias powl _powl powl.o
+profil.o:
+	emxalias profil _profil profil.o
+ptrace.o:
+	emxalias ptrace _ptrace ptrace.o
+putenv.o:
+	emxalias putenv _putenv putenv.o
+putw.o:
+	emxalias putw _putw putw.o
+read.o:
+	emxalias read _read read.o
+readdir.o:
+	emxalias readdir _readdir readdir.o
+readv.o:
+	emxalias readv _readv readv.o
+rewinddi.o:
+	emxalias rewinddir _rewinddir rewinddi.o
+rindex.o:
+	emxalias rindex _rindex rindex.o
+rint.o:
+	emxalias rint _rint rint.o
+rintl.o:
+	emxalias rintl _rintl rintl.o
+rmdir.o:
+	emxalias rmdir _rmdir rmdir.o
+sbrk.o:
+	emxalias sbrk _sbrk sbrk.o
+seekdir.o:
+	emxalias seekdir _seekdir seekdir.o
+select.o:
+	emxalias select _select select.o
+setbuffe.o:
+	emxalias setbuffer _setbuffer setbuffe.o
+setgid.o:
+	emxalias setgid _setgid setgid.o
+setmode.o:
+	emxalias setmode _setmode setmode.o
+setnewha.o:
+	emxalias set_new_handler _set_new_handler setnewha.o
+setpgid.o:
+	emxalias setpgid _setpgid setpgid.o
+setpwent.o:
+	emxalias setpwent _setpwent setpwent.o
+settimeo.o:
+	emxalias settimeofday _settimeofday settimeo.o
+setuid.o:
+	emxalias setuid _setuid setuid.o
+sigactio.o:
+	emxalias sigaction _sigaction sigactio.o
+sigaddse.o:
+	emxalias sigaddset _sigaddset sigaddse.o
+sigdelse.o:
+	emxalias sigdelset _sigdelset sigdelse.o
+sigempty.o:
+	emxalias sigemptyset _sigemptyset sigempty.o
+sigfills.o:
+	emxalias sigfillset _sigfillset sigfills.o
+sigismem.o:
+	emxalias sigismember _sigismember sigismem.o
+siglongj.o:
+	emxalias siglongjmp _siglongjmp siglongj.o
+sigpendi.o:
+	emxalias sigpending _sigpending sigpendi.o
+sigprocm.o:
+	emxalias sigprocmask _sigprocmask sigprocm.o
+sigsetjm.o:
+	emxalias sigsetjmp _sigsetjmp sigsetjm.o
+sigsuspe.o:
+	emxalias sigsuspend _sigsuspend sigsuspe.o
+sinhl.o:
+	emxalias sinhl _sinhl sinhl.o
+sinl.o:
+	emxalias sinl _sinl sinl.o
+sleep.o:
+	emxalias sleep _sleep sleep.o
+snprintf.o:
+	emxalias snprintf _snprintf snprintf.o
+sopen.o:
+	emxalias sopen _sopen sopen.o
+spawnl.o:
+	emxalias spawnl _spawnl spawnl.o
+spawnle.o:
+	emxalias spawnle _spawnle spawnle.o
+spawnlp.o:
+	emxalias spawnlp _spawnlp spawnlp.o
+spawnlpe.o:
+	emxalias spawnlpe _spawnlpe spawnlpe.o
+spawnv.o:
+	emxalias spawnv _spawnv spawnv.o
+spawnve.o:
+	emxalias spawnve _spawnve spawnve.o
+spawnvp.o:
+	emxalias spawnvp _spawnvp spawnvp.o
+spawnvpe.o:
+	emxalias spawnvpe _spawnvpe spawnvpe.o
+sqrtl.o:
+	emxalias sqrtl _sqrtl sqrtl.o
+stat.o:
+	emxalias stat _stat stat.o
+strdup.o:
+	emxalias strdup _strdup strdup.o
+stricmp.o:
+	emxalias stricmp _stricmp stricmp.o
+strlwr.o:
+	emxalias strlwr _strlwr strlwr.o
+strnicmp.o:
+	emxalias strnicmp _strnicmp strnicmp.o
+strnset.o:
+	emxalias strnset _strnset strnset.o
+strptime.o:
+	emxalias strptime _strptime strptime.o
+strrev.o:
+	emxalias strrev _strrev strrev.o
+strset.o:
+	emxalias strset _strset strset.o
+strtof.o:
+	emxalias strtof _strtof strtof.o
+strtold.o:
+	emxalias strtold _strtold strtold.o
+strupr.o:
+	emxalias strupr _strupr strupr.o
+swab.o:
+	emxalias swab _swab swab.o
+sysconf.o:
+	emxalias sysconf _sysconf sysconf.o
+syserrli.o:
+	emxalias sys_errlist _sys_errlist syserrli.o
+sysnerr.o:
+	emxalias sys_nerr _sys_nerr sysnerr.o
+tanhl.o:
+	emxalias tanhl _tanhl tanhl.o
+tanl.o:
+	emxalias tanl _tanl tanl.o
+tcdrain.o:
+	emxalias tcdrain _tcdrain tcdrain.o
+tcflow.o:
+	emxalias tcflow _tcflow tcflow.o
+tcflush.o:
+	emxalias tcflush _tcflush tcflush.o
+tcgetatt.o:
+	emxalias tcgetattr _tcgetattr tcgetatt.o
+tcgetpgr.o:
+	emxalias tcgetpgrp _tcgetpgrp tcgetpgr.o
+tcsendbr.o:
+	emxalias tcsendbreak _tcsendbreak tcsendbr.o
+tcsetatt.o:
+	emxalias tcsetattr _tcsetattr tcsetatt.o
+tcsetpgr.o:
+	emxalias tcsetpgrp _tcsetpgrp tcsetpgr.o
+tell.o:
+	emxalias tell _tell tell.o
+telldir.o:
+	emxalias telldir _telldir telldir.o
+tempnam.o:
+	emxalias tempnam _tempnam tempnam.o
+times.o:
+	emxalias times _times times.o
+timezone.o:
+	emxalias timezone _timezone timezone.o
+toascii.o:
+	emxalias toascii _toascii toascii.o
+trunc.o:
+	emxalias trunc _trunc trunc.o
+truncl.o:
+	emxalias truncl _truncl truncl.o
+truncate.o:
+	emxalias truncate _truncate truncate.o
+ttyname.o:
+	emxalias ttyname _ttyname ttyname.o
+tzname.o:
+	emxalias tzname _tzname tzname.o
+tzset.o:
+	emxalias tzset _tzset tzset.o
+ulimit.o:
+	emxalias ulimit _ulimit ulimit.o
+umask.o:
+	emxalias umask _umask umask.o
+uname.o:
+	emxalias uname _uname uname.o
+unlink.o:
+	emxalias unlink _unlink unlink.o
+utime.o:
+	emxalias utime _utime utime.o
+utimes.o:
+	emxalias utimes _utimes utimes.o
+vsnprint.o:
+	emxalias vsnprintf _vsnprintf vsnprint.o
+wait.o:
+	emxalias wait _wait wait.o
+waitpid.o:
+	emxalias waitpid _waitpid waitpid.o
+write.o:
+	emxalias write _write write.o
+writev.o:
+	emxalias writev _writev writev.o
+
+
+alias1: access.o acosl.o alarm.o asinl.o atan2l.o atanl.o atold.o \
+    bcmp.o bcopy.o brk.o bzero.o cbrt.o cbrtl.o ceill.o cfgetisp.o cfgetosp.o \
+    cfsetisp.o cfsetosp.o chdir.o chmod.o chsize.o close.o closedir.o \
+    copysig.o copysigf.o copysigl.o \
+    coshl.o cosl.o creat.o cuserid.o daylight.o dup.o dup2.o edata.o \
+    end.o endpwent.o environ.o eof.o etext.o execl.o execle.o execlp.o \
+    execlpe.o execv.o execve.o execvp.o execvpe.o expl.o fabsl.o fcloseal.o \
+    fcntl.o fdopen.o ffs.o fgetchar.o fileleng.o flock.o floorl.o flushall.o \
+    fmodl.o fnmatch.o fork.o fpathcon.o fputchar.o frexpl.o fstat.o fsync.o \
+    ftime.o ftruncat.o ftw.o gcvt.o getcwd.o getegid.o geteuid.o getgid.o \
+    getgrgid.o getgrnam.o getgroup.o getlogin.o getopt.o getpages.o \
+    getpass.o getpgrp.o getpid.o getppid.o getpwent.o getpwnam.o \
+    getpwuid.o gettimeo.o getuid.o getw.o getwd.o glob.o globfree.o huge.o \
+    hypot.o hypotl.o index.o ioctl.o isascii.o isatty.o kill.o ldexpl.o \
+    lhuge.o log10l.o logl.o lseek.o memccpy.o memicmp.o mkdir.o mkstemp.o \
+    mktemp.o modfl.o nextaft.o nextaftf.o nextaftl.o
+
+alias2: open.o opendir.o optarg.o opterr.o optind.o optmode.o \
+    optopt.o optswcha.o pathconf.o pause.o pclose.o pipe.o popen.o powl.o \
+    profil.o ptrace.o putenv.o putw.o read.o readdir.o readv.o rewinddi.o \
+    rindex.o rint.o rintl.o rmdir.o sbrk.o seekdir.o select.o setbuffe.o \
+    setgid.o setmode.o setnewha.o setpgid.o setpwent.o settimeo.o setuid.o \
+    sigactio.o sigaddse.o sigdelse.o sigempty.o sigfills.o sigismem.o \
+    siglongj.o sigpendi.o sigprocm.o sigsetjm.o sigsuspe.o sinhl.o sinl.o \
+    sleep.o snprintf.o sopen.o spawnl.o spawnle.o spawnlp.o spawnlpe.o \
+    spawnv.o spawnve.o spawnvp.o spawnvpe.o sqrtl.o stat.o strdup.o \
+    stricmp.o strlwr.o strnicmp.o strnset.o strptime.o strrev.o strset.o \
+    strtof.o strtold.o strupr.o swab.o sysconf.o syserrli.o sysnerr.o \
+    tanhl.o tanl.o tcdrain.o tcflow.o tcflush.o tcgetatt.o tcgetpgr.o \
+    tcsendbr.o tcsetatt.o tcsetpgr.o tell.o telldir.o tempnam.o times.o \
+    timezone.o toascii.o trunc.o truncl.o truncate.o ttyname.o tzname.o \
+    tzset.o ulimit.o umask.o uname.o unlink.o utime.o utimes.o vsnprint.o \
+    wait.o waitpid.o write.o writev.o
+$(LIBALIAS): alias1 alias2
+	-del $(LIBALIAS)
+	$(AR) r $(LIBALIAS) *.o
Index: trunk/src/emx/src/lib/app/Attic/386/crt2.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/crt2.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/crt2.s	(revision 18)
@@ -0,0 +1,42 @@
+/ crt2.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+/ This module is used by the following types of executables:
+/
+/ - Statically linked application programs
+/ - Custom C runtime DLLs
+
+        .globl  __entry1
+        .globl  __environ
+        .globl  __org_environ
+
+        .text
+
+__entry1:
+        popl    %esi
+        cld
+        xorl    %ebp, %ebp      /* End of stack frames */
+        leal    (%esp), %edi    /* argv[] */
+        movl    %edi, __environ
+        movl    %edi, __org_environ
+        pushl   %edi            /* envp */
+        call    L_ptr_tbl
+        pushl   %edi            /* argv */
+        call    L_ptr_tbl
+        pushl   %ecx            /* argc */
+        EPILOGUE_NO_RET(_entry1)
+        jmp     *%esi
+
+L_ptr_tbl:
+        xorl    %eax, %eax
+        movl    $-1, %ecx
+1:      incl    %ecx
+        scasl
+        jne     1b
+        ret
+
+        .data
+
+        .comm   __environ, 4
+        .comm   __org_environ, 4
Index: trunk/src/emx/src/lib/app/Attic/386/crt3.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/crt3.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/crt3.s	(revision 18)
@@ -0,0 +1,11 @@
+/ crt3.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+/ This module is used by the following types of executables:
+/
+/ - Statically linked application programs
+
+        .globl  __cdll_flag
+
+        .data
+
+__cdll_flag:    .byte 0
Index: trunk/src/emx/src/lib/app/Attic/386/emxio.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/emxio.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/emxio.s	(revision 18)
@@ -0,0 +1,8 @@
+/ emxio.s (emx+gcc)
+
+        .globl  __os2_emxio
+
+        .text
+
+__os2_emxio:
+        .asciz  "EMXIO"
Index: trunk/src/emx/src/lib/app/Attic/386/inp16.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/inp16.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/inp16.s	(revision 18)
@@ -0,0 +1,19 @@
+/ inp16.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__inp16
+	ALIGN
+__inp16:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        inw     %dx, %ax
+        movzwl  %ax, %eax
+        EPILOGUE(_inp16)
+
+2:	.long	1, 1b+1, __os2_emxio, 3
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/inp32.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/inp32.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/inp32.s	(revision 18)
@@ -0,0 +1,18 @@
+/ inp32.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__inp32
+	ALIGN
+__inp32:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        inl     %dx, %eax
+        EPILOGUE(_inp32)
+
+2:	.long	1, 1b+1, __os2_emxio, 5
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/inp8.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/inp8.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/inp8.s	(revision 18)
@@ -0,0 +1,19 @@
+/ inp8.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__inp8
+	ALIGN
+__inp8:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        inb     %dx, %al
+        movzbl  %al, %eax
+        EPILOGUE(_inp8)
+
+2:	.long	1, 1b+1, __os2_emxio, 1
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/inps16.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/inps16.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/inps16.s	(revision 18)
@@ -0,0 +1,23 @@
+/ inps16.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__inps16
+	ALIGN
+__inps16:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        pushl   %edi
+        movl    2*4(%esp), %edx                 /* port */
+        movl    3*4(%esp), %edi                 /* dst */
+        movl    4*4(%esp), %ecx                 /* count */
+        rep
+        insw
+        popl    %edi
+        EPILOGUE(_inps16)
+
+2:	.long	1, 1b+1, __os2_emxio, 10
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/inps32.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/inps32.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/inps32.s	(revision 18)
@@ -0,0 +1,23 @@
+/ inps32.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__inps32
+	ALIGN
+__inps32:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        pushl   %edi
+        movl    2*4(%esp), %edx                 /* port */
+        movl    3*4(%esp), %edi                 /* dst */
+        movl    4*4(%esp), %ecx                 /* count */
+        rep
+        insl
+        popl    %edi
+        EPILOGUE(_inps32)
+
+2:	.long	1, 1b+1, __os2_emxio, 12
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/inps8.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/inps8.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/inps8.s	(revision 18)
@@ -0,0 +1,23 @@
+/ inps8.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__inps8
+	ALIGN
+__inps8:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        pushl   %edi
+        movl    2*4(%esp), %edx                 /* port */
+        movl    3*4(%esp), %edi                 /* dst */
+        movl    4*4(%esp), %ecx                 /* count */
+        rep
+        insb
+        popl    %edi
+        EPILOGUE(_inps8)
+
+2:	.long	1, 1b+1, __os2_emxio, 7
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/outp16.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/outp16.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/outp16.s	(revision 18)
@@ -0,0 +1,19 @@
+/ outp16.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__outp16
+	ALIGN
+__outp16:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        movl    2*4(%esp), %eax
+        outw    %ax, %dx
+        EPILOGUE(_outp16)
+
+2:	.long	1, 1b+1, __os2_emxio, 4
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/outp32.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/outp32.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/outp32.s	(revision 18)
@@ -0,0 +1,19 @@
+/ outp32.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__outp32
+	ALIGN
+__outp32:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        movl    2*4(%esp), %eax
+        outl    %eax, %dx
+        EPILOGUE(_outp32)
+
+2:	.long	1, 1b+1, __os2_emxio, 6
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/outp8.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/outp8.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/outp8.s	(revision 18)
@@ -0,0 +1,19 @@
+/ outp8.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__outp8
+	ALIGN
+__outp8:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        movl    2*4(%esp), %eax
+        outb    %al, %dx
+        EPILOGUE(_outp8)
+
+2:	.long	1, 1b+1, __os2_emxio, 2
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/outps16.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/outps16.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/outps16.s	(revision 18)
@@ -0,0 +1,23 @@
+/ outps16.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__outps16
+	ALIGN
+__outps16:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        pushl   %esi
+        movl    2*4(%esp), %edx                 /* port */
+        movl    3*4(%esp), %esi                 /* src */
+        movl    4*4(%esp), %ecx                 /* count */
+        rep
+        outsw
+        popl    %esi
+        EPILOGUE(_outps16)
+
+2:	.long	1, 1b+1, __os2_emxio, 11
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/outps32.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/outps32.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/outps32.s	(revision 18)
@@ -0,0 +1,23 @@
+/ outps32.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__outps32
+	ALIGN
+__outps32:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        pushl   %esi
+        movl    2*4(%esp), %edx                 /* port */
+        movl    3*4(%esp), %esi                 /* src */
+        movl    4*4(%esp), %ecx                 /* count */
+        rep
+        outsl
+        popl    %esi
+        EPILOGUE(_outps32)
+
+2:	.long	1, 1b+1, __os2_emxio, 13
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/outps8.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/outps8.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/outps8.s	(revision 18)
@@ -0,0 +1,23 @@
+/ outps8.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__outps8
+	ALIGN
+__outps8:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        pushl   %esi
+        movl    2*4(%esp), %edx                 /* port */
+        movl    3*4(%esp), %esi                 /* src */
+        movl    4*4(%esp), %ecx                 /* count */
+        rep
+        outsb
+        popl    %esi
+        EPILOGUE(_outps8)
+
+2:	.long	1, 1b+1, __os2_emxio, 8
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/outps8da.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/outps8da.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/outps8da.s	(revision 18)
@@ -0,0 +1,27 @@
+/ outps8da.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__outps8dac
+	ALIGN
+__outps8dac:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        pushl   %esi
+        movl    2*4(%esp), %edx                 /* port */
+        movl    3*4(%esp), %esi                 /* src */
+        movl    4*4(%esp), %ecx                 /* count */
+        ALIGN
+2:      movb    (%esi), %al
+        outb    %al, %dx
+        incl    %esi
+        nop
+        loop    2b
+        popl    %esi
+        EPILOGUE(_outps8dac)
+
+2:	.long	1, 1b+1, __os2_emxio, 18
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/outpt.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/outpt.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/outpt.s	(revision 18)
@@ -0,0 +1,47 @@
+/ outpt.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__outpt
+	ALIGN
+__outpt:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        pushl   %esi
+        movl    2*4(%esp), %esi                 /* table */
+        ALIGN
+3:      movl    0*4(%esi), %ecx
+        jecxz   9f
+        movl    1*4(%esi), %edx
+        movl    2*4(%esi), %eax
+        addl    $3*4, %esi
+        orl     %eax, %eax
+        jz      3f
+        decl    %eax
+        jz      4f
+        decl    %eax
+        jnz     9f
+        rep
+        outsl
+        jmp     3b
+
+        ALIGN
+3:      rep
+        outsb
+        jmp     3b
+
+        ALIGN
+4:      rep
+        outsw
+        jmp     3b
+
+        ALIGN
+9:      popl    %esi
+        EPILOGUE(_outpt)
+
+2:	.long	1, 1b+1, __os2_emxio, 9
+L1:	.asciz	"emxio"
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/wait0.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/wait0.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/wait0.s	(revision 18)
@@ -0,0 +1,22 @@
+/ wait0.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__wait0
+	ALIGN
+__wait0:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        movb    2*4(%esp), %cl
+        ALIGN
+4:      inb     %dx, %al
+        testb   %cl, %al
+        jnz     4b
+        EPILOGUE(_wait0)
+
+2:	.long	1, 1b+1, __os2_emxio, 16
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/wait01.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/wait01.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/wait01.s	(revision 18)
@@ -0,0 +1,26 @@
+/ wait01.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__wait01
+	ALIGN
+__wait01:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        movb    2*4(%esp), %cl
+        ALIGN
+4:      inb     %dx, %al
+        testb   %cl, %al
+        jnz     4b
+        ALIGN
+5:      inb     %dx, %al
+        testb   %cl, %al
+        jz      5b
+        EPILOGUE(_wait01)
+
+2:	.long	1, 1b+1, __os2_emxio, 14
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/wait1.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/wait1.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/wait1.s	(revision 18)
@@ -0,0 +1,22 @@
+/ wait1.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__wait1
+	ALIGN
+__wait1:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        movb    2*4(%esp), %cl
+        ALIGN
+4:      inb     %dx, %al
+        testb   %cl, %al
+        jz      4b
+        EPILOGUE(_wait1)
+
+2:	.long	1, 1b+1, __os2_emxio, 17
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/Attic/386/wait10.s
===================================================================
--- trunk/src/emx/src/lib/app/Attic/386/wait10.s	(revision 18)
+++ trunk/src/emx/src/lib/app/Attic/386/wait10.s	(revision 18)
@@ -0,0 +1,26 @@
+/ wait10.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+	.text
+
+	.globl	__wait10
+	ALIGN
+__wait10:
+        PROFILE_NOFRAME
+1:	.byte   0xe9
+        .long   0
+        movl    1*4(%esp), %edx
+        movb    2*4(%esp), %cl
+        ALIGN
+4:      inb     %dx, %al
+        testb   %cl, %al
+        jz      4b
+        ALIGN
+5:      inb     %dx, %al
+        testb   %cl, %al
+        jnz     5b
+        EPILOGUE(_wait10)
+
+2:	.long	1, 1b+1, __os2_emxio, 15
+	.stabs  "__os2dll", 23, 0, 0, 2b
Index: trunk/src/emx/src/lib/app/getenv.c
===================================================================
--- trunk/src/emx/src/lib/app/getenv.c	(revision 18)
+++ trunk/src/emx/src/lib/app/getenv.c	(revision 18)
@@ -0,0 +1,18 @@
+/* getenv.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+
+char *getenv (const char *name)
+{
+  int len;
+  char **p;
+
+  if (name == NULL || _environ == NULL)
+    return NULL;
+  len = strlen (name);
+  for (p = _environ; *p != NULL; ++p)
+    if (strncmp (*p, name, len) == 0 && (*p)[len] == '=')
+      return *p + len + 1;
+  return NULL;
+}
Index: trunk/src/emx/src/lib/app/iodata.c
===================================================================
--- trunk/src/emx/src/lib/app/iodata.c	(revision 18)
+++ trunk/src/emx/src/lib/app/iodata.c	(revision 18)
@@ -0,0 +1,16 @@
+/* iodata.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <fcntl.h>
+#include <emx/io.h>
+
+/* The following variables are used for backward compatibility with
+   existing libraries (-Zcrtdll -lsocket!).  See also io/_fd.c,
+   app/stdio.c, and startup/startup.c. */
+
+int _files[_NFILES];
+int _lookahead[_NFILES];
+const int _nfiles = _NFILES;
+
+struct fdvec _fdvec_head = {_files, _lookahead, NULL, _NFILES};
+
+int _io_ninherit = 40;
Index: trunk/src/emx/src/lib/app/makefile
===================================================================
--- trunk/src/emx/src/lib/app/makefile	(revision 18)
+++ trunk/src/emx/src/lib/app/makefile	(revision 18)
@@ -0,0 +1,44 @@
+#
+# /emx/src/lib/app/makefile
+#
+LIBBASE=c_app
+.INCLUDE: /emx/src/lib/libc0.mak
+
+local: ;
+
+crt2.o: crt2.s $(ASM386H)
+emxio.o: emxio.s
+getenv.o: getenv.c $(I)stdlib.h $(I)string.h
+inp8.o: inp8.s $(ASM386H)
+inp16.o: inp16.s $(ASM386H)
+inp32.o: inp32.s $(ASM386H)
+inps8.o: inps8.s $(ASM386H)
+inps16.o: inps16.s $(ASM386H)
+inps32.o: inps32.s $(ASM386H)
+outp8.o: outp8.s $(ASM386H)
+outp16.o: outp16.s $(ASM386H)
+outp32.o: outp32.s $(ASM386H)
+outps8.o: outps8.s $(ASM386H)
+outps8da.o: outps8da.s $(ASM386H)
+outps16.o: outps16.s $(ASM386H)
+outps32.o: outps32.s $(ASM386H)
+outpt.o: outpt.s $(ASM386H)
+putenv.o: putenv.c $(I)stdlib.h $(I)string.h $(ERRNO) $(I)emx/time.h \
+		$(I)emx/startup.h
+wait0.o: wait0.s $(ASM386H)
+wait01.o: wait01.s $(ASM386H)
+wait1.o: wait1.s $(ASM386H)
+wait10.o: wait10.s $(ASM386H)
+
+iodata.o: ../iodata.c $(FCNTL) $(I)emx/io.h
+	$(GCC) -c -D_NFILES=40 ../iodata.c
+
+stdio.o: ../stdio.c $(I)stdio.h $(FCNTL) $(BUILTIN) $(S)fmutex.h \
+		$(S)rmutex.h $(I)emx/io.h $(I)emx/startup.h
+	$(GCC) -c -D_NFILES=40 ../stdio.c
+
+$(DSTLIB): crt2.o crt3.o \
+    emxio.o getenv.o inp8.o inp16.o inp32.o inps8.o inps16.o inps32.o \
+    iodata.o outp8.o outp16.o outp32.o outps8.o outps8da.o outps16.o \
+    outps32.o outpt.o putenv.o stdio.o wait0.o wait01.o wait1.o wait10.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/app/putenv.c
===================================================================
--- trunk/src/emx/src/lib/app/putenv.c	(revision 18)
+++ trunk/src/emx/src/lib/app/putenv.c	(revision 18)
@@ -0,0 +1,57 @@
+/* putenv.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <emx/startup.h>
+#include <emx/time.h>           /* _tzset_flag */
+
+int _putenv (const char *string)
+{
+  char *s, **p;
+  int len, env_size;
+
+  if (string == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  _tzset_flag = 0;              /* Call tzset() */
+  s = strchr (string, '=');
+  if (s == NULL)
+    len = strlen (string);        /* Use complete string */
+  else
+    len = s - string;
+  p = _environ;
+  env_size = 0;
+  if (p != NULL)
+    while (*p != NULL)
+      {
+        s = *p;
+        if (strncmp (s, string, len) == 0 && (s[len] == 0 || s[len] == '='))
+          break;
+        ++p; ++env_size;
+      }
+  if (p == NULL || *p == NULL)
+    {
+      if (_environ == _org_environ)
+        {
+          p = malloc ((env_size+2) * sizeof (char *));
+          if (p == NULL) return -1;
+          _environ = p;
+          if (env_size != 0)
+            memcpy (_environ, _org_environ, env_size * sizeof (char *));
+        }
+      else
+        {
+          p = realloc (_environ, (env_size+2) * sizeof (char *));
+          if (p == NULL) return -1;
+          _environ = p;
+        }
+      _environ[env_size+0] = (char *)string;
+      _environ[env_size+1] = NULL;
+    }
+  else
+    *p = (char *)string;
+  return 0;
+}
Index: trunk/src/emx/src/lib/app/stdio.c
===================================================================
--- trunk/src/emx/src/lib/app/stdio.c	(revision 18)
+++ trunk/src/emx/src/lib/app/stdio.c	(revision 18)
@@ -0,0 +1,130 @@
+/* stdio.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/io.h>
+#include <emx/startup.h>
+
+/* See app/iodata.c. */
+
+extern int _nfiles;
+extern int _files[];
+
+#if defined (__MT__)
+_rmutex _streamv_rmutex;        /* See io/_newstre.c */
+#endif
+
+
+/* These variables must be initialized as no extended dictionary
+   entries are built for COMDEF. */
+
+FILE _streamv[_NFILES] = {{0}};
+
+struct streamvec _streamvec_head = {_streamv, NULL, _NFILES};
+
+#if defined (__MT__)
+
+/* If we don't preallocate the first entry, _CRT_init() will call
+   malloc() which breaks fork() because the heap object of the EXE
+   file won't be used. */
+
+static struct _file2 _streamv2[_NFILES];
+
+struct streamvec2 _streamvec2_head = {_streamv2, NULL, _NFILES};
+
+#endif
+
+/* The buffer for stdin. */
+
+static char ibuf[BUFSIZ];
+
+
+/* Initialize the streams -- this function will be called by
+   _startup() via the __crtinit1__ set vector. */
+
+void _init_streams (void)
+{
+  int i;
+
+#if defined (__MT__)
+  _rmutex_checked_create (&_streamv_rmutex, 0);
+#endif
+
+  for (i = 0; i < _nfiles && i < _streamvec_head.n; ++i)
+    {
+      _streamv[i]._flags = 0;
+      /* O_TEXT is set by init_files() for all valid handles. */
+      if (_files[i] != 0)
+        {
+          _streamv[i]._flags |= _IOOPEN;
+          _streamv[i]._ptr = NULL;
+          _streamv[i]._buffer = NULL;
+          _streamv[i]._rcount = 0;
+          _streamv[i]._wcount = 0;
+          _streamv[i]._handle = i;
+          _streamv[i]._buf_size = 0;
+          _streamv[i]._tmpidx = 0;
+          _streamv[i]._pid = 0;
+          _streamv[i]._flush = _flushstream;
+          _streamv[i]._ungetc_count = 0;
+          switch (i)
+            {
+            case 0:
+
+              /* stdin is always buffered. */
+
+              _streamv[0]._flags |= _IOREAD | _IOFBF | _IOBUFUSER;
+              _streamv[0]._ptr = ibuf;
+              _streamv[0]._buffer = ibuf;
+              _streamv[0]._buf_size = BUFSIZ;
+              break;
+
+            case 1:
+
+              /* stdout is buffered unless it's connected to a
+                 device. */
+
+              _streamv[i]._flags |= (_IOWRT | _IOBUFNONE
+                                     | ((_files[i] & F_DEV)
+                                        ? _IONBF : _IOFBF));
+              break;
+
+            case 2:
+
+              /* stderr is always unbuffered. */
+
+              _streamv[i]._flags |= _IOWRT | _IOBUFNONE | _IONBF;
+              break;
+
+            default:
+
+              /* All other streams are buffered unless connected to a
+                 device. */
+
+              _streamv[i]._flags |= (_IORW | _IOBUFNONE
+                                     | ((_files[i] & F_DEV)
+                                        ? _IONBF : _IOFBF));
+              break;
+            }
+          if (_setmore (&_streamv[i], 0) != 0)
+            abort ();
+        }
+    }
+}
+
+
+/* Shutdown the streams -- this function will be called by _cleanup()
+   via the __crtexit1__ set vector.  Do not close the streams as this
+   function is called by abort() and the signal handler might want to
+   print something.  (ISO 9899-1990 lets this undefined.) */
+
+void _exit_streams (void)
+{
+  _flushall ();
+  _rmtmp ();
+}
+
+_CRT_INIT1 (_init_streams)
+_CRT_EXIT1 (_exit_streams)
Index: trunk/src/emx/src/lib/cdll/emxio.def
===================================================================
--- trunk/src/emx/src/lib/cdll/emxio.def	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxio.def	(revision 18)
@@ -0,0 +1,23 @@
+;
+; emxio.def (for emxlibc.dll)
+;
+LIBRARY EMXIO
+EXPORTS
+  _inp8                         @1
+  _outp8                        @2
+  _inp16                        @3
+  _outp16                       @4
+  _inp32                        @5
+  _outp32                       @6
+  _inps8                        @7
+  _outps8                       @8
+  _outpt                        @9
+  _inps16                       @10
+  _outps16                      @11
+  _inps32                       @12
+  _outps32                      @13
+  _wait01                       @14
+  _wait10                       @15
+  _wait0                        @16
+  _wait1                        @17
+  _outps8dac                    @18
Index: trunk/src/emx/src/lib/cdll/emxlibc.def
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibc.def	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibc.def	(revision 18)
@@ -0,0 +1,854 @@
+;
+; emxlibc.def
+;
+LIBRARY EMXLIBC INITINSTANCE
+DESCRIPTION 'emxlibc.dll 0.9d -- Copyright (c) 1992-2000 by Eberhard Mattes'
+DATA
+   MULTIPLE NONSHARED
+EXPORTS
+  EMX_REVISION = emx_revision @1 RESIDENTNAME
+
+  _execl                        @100 NONAME
+  _execle                       @101 NONAME
+  _execlp                       @102 NONAME
+  _execlpe                      @103 NONAME
+  _execv                        @104 NONAME
+  _execve                       @105 NONAME
+  _execvp                       @106 NONAME
+  _execvpe                      @107 NONAME
+  _fork                         @108 NONAME
+  _getpid                       @109 NONAME
+  _getppid                      @110 NONAME
+  _ptrace                       @111 NONAME
+  _spawnl                       @112 NONAME
+  _spawnle                      @113 NONAME
+  _spawnlp                      @114 NONAME
+  _spawnlpe                     @115 NONAME
+  _spawnv                       @116 NONAME
+  _spawnve                      @117 NONAME
+  _spawnvp                      @118 NONAME
+  _spawnvpe                     @119 NONAME
+  system                        @120 NONAME
+  _wait                         @121 NONAME
+  _waitpid                      @122 NONAME
+  _sigaction                    @123 NONAME
+  _sigaddset                    @124 NONAME
+  _sigdelset                    @125 NONAME
+  _sigemptyset                  @126 NONAME
+  _sigfillset                   @127 NONAME
+  _sigismember                  @128 NONAME
+  _sigpending                   @129 NONAME
+  _sigprocmask                  @130 NONAME
+  _sigsuspend                   @131 NONAME
+  _profil                       @132 NONAME
+  _fmutex_create                @133 NONAME
+  _fmutex_open                  @134 NONAME
+  _fmutex_close                 @135 NONAME
+  __fmutex_request_internal     @136 NONAME
+  __fmutex_release_internal     @137 NONAME
+  _fmutex_checked_close         @138 NONAME
+  _fmutex_checked_create        @139 NONAME
+  _fmutex_checked_open          @140 NONAME
+  _fmutex_checked_release       @141 NONAME
+  _fmutex_checked_request       @142 NONAME
+  __smutex_request_internal     @143 NONAME
+  _rmutex_checked_close         @144 NONAME
+  _rmutex_checked_create        @145 NONAME
+  _rmutex_checked_open          @146 NONAME
+  _rmutex_close                 @147 NONAME
+  _rmutex_create                @148 NONAME
+  _rmutex_open                  @149 NONAME
+  _fmutex_dummy                 @150 NONAME
+  _rmutex_dummy                 @151 NONAME
+
+  _bcmp                         @200 NONAME
+  _bcopy                        @201 NONAME
+  _bzero                        @202 NONAME
+  _index                        @203 NONAME
+  _memccpy                      @204 NONAME
+  memchr                        @205 NONAME
+  memcmp                        @206 NONAME
+  memcpy                        @207 NONAME
+  _memicmp                      @208 NONAME
+  memmove                       @209 NONAME
+  memset                        @210 NONAME
+  _rindex                       @211 NONAME
+  strcat                        @212 NONAME
+  strchr                        @213 NONAME
+  strcmp                        @214 NONAME
+  strcpy                        @215 NONAME
+  strcspn                       @216 NONAME
+  _strdup                       @217 NONAME
+  strerror                      @218 NONAME
+  _stricmp                      @219 NONAME
+  strlen                        @220 NONAME
+  _strlwr                       @221 NONAME
+  strncat                       @222 NONAME
+  strncmp                       @223 NONAME
+  strncpy                       @224 NONAME
+  _strnicmp                     @225 NONAME
+  _strnset                      @226 NONAME
+  strpbrk                       @227 NONAME
+  strrchr                       @228 NONAME
+  _strrev                       @229 NONAME
+  _strset                       @230 NONAME
+  strspn                        @231 NONAME
+  strstr                        @232 NONAME
+  strtok                        @233 NONAME
+  _strupr                       @234 NONAME
+  _swab                         @235 NONAME
+  _memcount                     @236 NONAME
+  _memswap                      @237 NONAME
+  _strncpy                      @238 NONAME
+  _ffs                          @239 NONAME
+  _memdif                       @240 NONAME
+  strcoll                       @241 NONAME
+  strxfrm                       @242 NONAME
+  _memrchr                      @243 NONAME
+
+  isalnum                       @300 NONAME
+  isalpha                       @301 NONAME
+  _isascii                      @302 NONAME
+  iscntrl                       @303 NONAME
+  isdigit                       @304 NONAME
+  isgraph                       @305 NONAME
+  islower                       @306 NONAME
+  isprint                       @307 NONAME
+  ispunct                       @308 NONAME
+  isspace                       @309 NONAME
+  isupper                       @310 NONAME
+  isxdigit                      @311 NONAME
+  _toascii                      @312 NONAME
+  tolower                       @313 NONAME
+  toupper                       @314 NONAME
+  _ctype                        @315 NONAME
+  _tolower                      @316 NONAME
+  _toupper                      @317 NONAME
+
+  _cfgetispeed                  @350 NONAME
+  _cfgetospeed                  @351 NONAME
+  _cfsetispeed                  @352 NONAME
+  _cfsetospeed                  @353 NONAME
+  _tcdrain                      @354 NONAME
+  _tcflow                       @355 NONAME
+  _tcflush                      @356 NONAME
+  _tcgetattr                    @357 NONAME
+  _tcgetpgrp                    @358 NONAME
+  _tcsendbreak                  @359 NONAME
+  _tcsetattr                    @360 NONAME
+  _tcsetpgrp                    @361 NONAME
+
+  calloc                        @400 NONAME
+  free                          @401 NONAME
+  malloc                        @402 NONAME
+  realloc                       @403 NONAME
+  _expand                       @404 NONAME
+  _heapchk                      @405 NONAME
+  _heapset                      @406 NONAME
+  _msize                        @407 NONAME
+  _tcalloc                      @408 NONAME
+  _tfree                        @409 NONAME
+  _tmalloc                      @410 NONAME
+  _trealloc                     @411 NONAME
+  _heapmin                      @412 NONAME
+  _mheap                        @413 NONAME
+  _uaddmem                      @414 NONAME
+  _ucalloc                      @415 NONAME
+  _uclose                       @416 NONAME
+  _ucreate                      @417 NONAME
+  _ucreate2                     @418 NONAME
+  _udefault                     @419 NONAME
+  _udestroy                     @420 NONAME
+  _uheapchk                     @421 NONAME
+  _uheapmin                     @422 NONAME
+  _uheapset                     @423 NONAME
+  _uheap_walk                   @424 NONAME
+  _uheap_walk2                  @425 NONAME
+  _umalloc                      @426 NONAME
+  _uopen                        @427 NONAME
+  _ustats                       @428 NONAME
+  _utcalloc                     @429 NONAME
+  _utmalloc                     @430 NONAME
+  _heap_walk                    @431 NONAME
+  _uheap_type                   @432 NONAME
+  _theapmin                     @433 NONAME
+  _utdefault                    @434 NONAME
+
+  _access                       @500 NONAME
+  _chmod                        @501 NONAME
+  _chsize                       @502 NONAME
+  clearerr                      @503 NONAME
+  _close                        @504 NONAME
+  _creat                        @505 NONAME
+  _dup                          @506 NONAME
+  _dup2                         @507 NONAME
+  _eof                          @508 NONAME
+  fclose                        @509 NONAME
+  _fcloseall                    @510 NONAME
+  _fcntl                        @511 NONAME
+  _fdopen                       @512 NONAME
+  fflush                        @513 NONAME
+  fgetc                         @514 NONAME
+  _fgetchar                     @515 NONAME
+  fgetpos_09b                   @516 NONAME
+  fgets                         @517 NONAME
+  _filelength                   @518 NONAME
+  _flushall                     @519 NONAME
+  fopen                         @520 NONAME
+  fprintf                       @521 NONAME
+  fputc                         @522 NONAME
+  _fputchar                     @523 NONAME
+  fputs                         @524 NONAME
+  fread                         @525 NONAME
+  freopen                       @526 NONAME
+  fscanf                        @527 NONAME
+  fseek                         @528 NONAME
+  fsetpos_09b                   @529 NONAME
+  _fstat                        @530 NONAME
+  _fsync                        @531 NONAME
+  ftell                         @532 NONAME
+  _ftruncate                    @533 NONAME
+  fwrite                        @534 NONAME
+  gets                          @535 NONAME
+  _getw                         @536 NONAME
+  _ioctl                        @537 NONAME
+  _isatty                       @538 NONAME
+  _lseek                        @539 NONAME
+  _mktemp                       @540 NONAME
+  _open                         @541 NONAME
+  _pclose                       @542 NONAME
+  _pipe                         @543 NONAME
+  _popen                        @544 NONAME
+  printf                        @545 NONAME
+  puts                          @546 NONAME
+  _putw                         @547 NONAME
+  _read                         @548 NONAME
+  remove                        @549 NONAME
+  rename                        @550 NONAME
+  rewind                        @551 NONAME
+  scanf                         @552 NONAME
+  _select                       @553 NONAME
+  setbuf                        @554 NONAME
+  _setbuffer                    @555 NONAME
+  _setmode                      @556 NONAME
+  setvbuf                       @557 NONAME
+  _sopen                        @558 NONAME
+  sprintf                       @559 NONAME
+  sscanf                        @560 NONAME
+  _stat                         @561 NONAME
+  _tell                         @562 NONAME
+  _tempnam                      @563 NONAME
+  tmpfile                       @564 NONAME
+  tmpnam                        @565 NONAME
+  _truncate                     @566 NONAME
+  _umask                        @567 NONAME
+  ungetc                        @568 NONAME
+  _unlink                       @569 NONAME
+  _utime                        @570 NONAME
+  _utimes                       @571 NONAME
+  vfprintf                      @572 NONAME
+  vfscanf                       @573 NONAME
+  vprintf                       @574 NONAME
+  vscanf                        @575 NONAME
+  vsprintf                      @576 NONAME
+  vsscanf                       @577 NONAME
+  _write                        @578 NONAME
+  _crlf                         @579 NONAME
+  _fbuf                         @581 NONAME
+  _fill                         @582 NONAME
+  _flush                        @583 NONAME
+  _fopen                        @584 NONAME
+  _fseek_hdr                    @585 NONAME
+  _fsetmode                     @586 NONAME
+  _fsopen                       @587 NONAME
+  _input                        @588 NONAME
+  _isterm                       @589 NONAME
+  _newstream                    @590 NONAME
+  _output                       @591 NONAME
+  _rmtmp                        @592 NONAME
+  _seek_hdr                     @593 NONAME
+  _vsopen                       @594 NONAME
+  _streamv                      @595 NONAME
+  _fmode_bin                    @597 NONAME
+  _nfiles                       @598 NONAME ; For backward compatibility
+  _ead_add                      @599 NONAME
+  _ead_clear                    @600 NONAME
+  _ead_copy                     @601 NONAME
+  _ead_count                    @602 NONAME
+  _ead_create                   @603 NONAME
+  _ead_delete                   @604 NONAME
+  _ead_destroy                  @605 NONAME
+  _ead_fea2list_size            @606 NONAME
+  _ead_fea2list_to_fealist      @607 NONAME
+  _ead_fealist_to_fea2list      @608 NONAME
+  _ead_find                     @609 NONAME
+  _ead_get_fea2list             @610 NONAME
+  _ead_get_flags                @611 NONAME
+  _ead_get_name                 @612 NONAME
+  _ead_get_value                @613 NONAME
+  _ead_name_len                 @614 NONAME
+  _ead_read                     @615 NONAME
+  _ead_replace                  @616 NONAME
+  _ead_sort                     @617 NONAME
+  _ead_use_fea2list             @618 NONAME
+  _ead_value_size               @619 NONAME
+  _ead_write                    @620 NONAME
+  _ea_free                      @621 NONAME
+  _ea_get                       @622 NONAME
+  _ea_put                       @623 NONAME
+  _ea_remove                    @624 NONAME
+  _flock                        @625 NONAME
+  _mfopen                       @626 NONAME
+  _mfclose                      @627 NONAME
+  _pipe_size                    @628 NONAME
+  _imphandle                    @629 NONAME
+  _files                        @630 NONAME ; For backward compatibility
+  _lookahead                    @631 NONAME ; For backward compatibility
+  _readv                        @632 NONAME
+  _writev                       @633 NONAME
+  _ttyname                      @634 NONAME
+  _snprintf                     @635 NONAME
+  _vsnprintf                    @636 NONAME
+  _mkstemp                      @637 NONAME
+  fgetpos                       @638 NONAME
+  fsetpos                       @639 NONAME
+  _fassign                      @640 NONAME
+  _fd_flags                     @641 NONAME ; For -lsocket
+  _fd_lookahead                 @642 NONAME ; For -lsocket
+  _fd_init                      @643 NONAME ; For -lsocket
+  feof                          @644 NONAME
+  ferror                        @645 NONAME
+  fileno                        @646 NONAME
+  getchar                       @647 NONAME
+  putchar                       @648 NONAME
+  _getc_inline                  @649 NONAME
+  _putc_inline                  @650 NONAME
+
+  abort                         @700 NONAME
+  abs                           @701 NONAME
+  _alarm                        @702 NONAME
+  atexit                        @703 NONAME
+  atof                          @704 NONAME
+  atoi                          @705 NONAME
+  atol                          @706 NONAME
+  bsearch                       @707 NONAME
+  _chdir                        @708 NONAME
+  _closedir                     @709 NONAME
+  div                           @710 NONAME
+  _endpwent                     @711 NONAME
+  exit                          @712 NONAME
+  _ftw                          @713 NONAME
+  _getcwd                       @714 NONAME
+  _getegid                      @715 NONAME
+  getenv                        @716 NONAME
+  _geteuid                      @717 NONAME
+  _getgid                       @718 NONAME
+  _getlogin                     @719 NONAME
+  _getopt                       @720 NONAME
+  _getpagesize                  @721 NONAME
+  _getpwent                     @722 NONAME
+  _getpwnam                     @723 NONAME
+  _getpwuid                     @724 NONAME
+  _getuid                       @725 NONAME
+  _getwd                        @726 NONAME
+  _kill                         @727 NONAME
+  labs                          @728 NONAME
+  ldiv                          @729 NONAME
+  longjmp                       @730 NONAME
+; mkdir_08e                     @731 NONAME ; see emxlibc2.def
+  _opendir                      @732 NONAME
+  _optarg                       @733 NONAME
+  _opterr                       @734 NONAME
+  _optind                       @735 NONAME
+  _optmode                      @736 NONAME
+  _optswchar                    @737 NONAME
+  perror                        @738 NONAME
+  _putenv                       @739 NONAME
+  qsort                         @740 NONAME
+  raise                         @741 NONAME
+  rand                          @742 NONAME
+  _readdir                      @743 NONAME
+  _rewinddir                    @744 NONAME
+  _rmdir                        @745 NONAME
+  _sbrk                         @746 NONAME
+  _seekdir                      @747 NONAME
+  setjmp                        @748 NONAME
+  _setpwent                     @749 NONAME
+  signal                        @750 NONAME
+  _sleep                        @751 NONAME
+  srand                         @752 NONAME
+  strtod                        @753 NONAME
+  strtol                        @754 NONAME
+  strtoul                       @755 NONAME
+  _sys_errlist                  @756 NONAME
+  _sys_nerr                     @757 NONAME
+  _telldir                      @758 NONAME
+  _ulimit                       @759 NONAME
+  _abspath                      @760 NONAME
+  _assert                       @761 NONAME
+  _atoll                        @762 NONAME
+  _beginthread                  @763 NONAME ; For multithread library
+  _chdir2                       @764 NONAME
+  _chdrive                      @765 NONAME
+  _cleanup                      @766 NONAME
+  _core                         @767 NONAME
+  _defext                       @768 NONAME
+  _endthread                    @769 NONAME ; For multithread library
+  _errno_fun                    @770 NONAME ; For multithread library
+  _exit                         @771 NONAME
+  _filesys                      @772 NONAME
+  _fnexplode                    @773 NONAME
+  _fnexplodefree                @774 NONAME
+  _fngetdrive                   @775 NONAME
+  _fnisabs                      @776 NONAME
+  _fullpath                     @777 NONAME
+  _getcwd1                      @778 NONAME
+  _getcwd2                      @779 NONAME
+  _getdrive                     @780 NONAME
+  _getext                       @781 NONAME
+  _itoa                         @782 NONAME
+  _lltoa                        @783 NONAME
+  _ltoa                         @784 NONAME
+  _os2_bad                      @785 NONAME
+  _path                         @786 NONAME
+  _read_kbd                     @787 NONAME
+  _remext                       @788 NONAME
+  _response                     @789 NONAME
+  _scrsize                      @790 NONAME
+  _searchenv                    @791 NONAME
+  _splitpath                    @792 NONAME
+  _startup                      @793 NONAME
+  _swchar                       @795 NONAME
+  _syserrno                     @796 NONAME
+  _thread                       @797 NONAME ; For multithread library
+  _gettid                       @798 NONAME
+  _ulltoa                       @799 NONAME
+  _ultoa                        @800 NONAME
+  _wildcard                     @801 NONAME
+  _environ                      @802 NONAME
+  _org_environ                  @803 NONAME
+  _emx_env                      @804 NONAME
+  _emx_vcmp                     @805 NONAME
+  _emx_vprt                     @806 NONAME
+  _osmajor                      @807 NONAME
+  _osminor                      @808 NONAME
+  _osmode                       @809 NONAME
+; _dos_init                     @810 NONAME ; see emxlibc2.def
+; _dos_syscall                  @811 NONAME ; see emxlibc2.def
+; _entry1_08e                   @812 NONAME ; see emxlibc2.def
+; _ctor_ptr                     @813 NONAME ; see emxlibc2.def
+; _dtor_ptr                     @814 NONAME ; see emxlibc2.def
+  _entry1                       @815 NONAME
+  _entry2                       @816 NONAME
+; _DLL_InitTerm                 @817 NONAME ; see emxlibc2.def
+; _CRT_init_08f                 @818 NONAME ; see emxlibc2.def
+  _CRT_term                     @819 NONAME
+  _uname                        @820 NONAME
+  _int86                        @821 NONAME
+  _mkdir                        @822 NONAME
+  _sleep2                       @823 NONAME
+  _getname                      @824 NONAME
+  _dt_free                      @825 NONAME
+  _dt_read                      @826 NONAME
+  _dt_sort                      @827 NONAME
+  _dt_split                     @828 NONAME
+  _splitargs                    @829 NONAME
+  _cuserid                      @830 NONAME
+  _pause                        @831 NONAME
+  _getpass                      @832 NONAME
+  _fnisrel                      @833 NONAME
+  _emx_rev                      @834 NONAME
+  _makepath                     @835 NONAME
+  _threadstore                  @836 NONAME ; For multithread library
+  __threadid                    @837 NONAME ; For multithread library
+  _getext2                      @838 NONAME
+  _execname                     @839 NONAME
+  _strtold                      @840 NONAME
+  _atofl                        @841 NONAME
+  _envargs                      @842 NONAME
+  __ctordtorInit1               @843 NONAME
+  __ctordtorTerm1               @844 NONAME
+  _CRT_init                     @845 NONAME
+  _errno                        @846 NONAME
+  _gcvt                         @847 NONAME
+  _sysconf                      @848 NONAME
+  _fpathconf                    @849 NONAME
+  _pathconf                     @850 NONAME
+  _getgrgid                     @851 NONAME
+  _getgrnam                     @852 NONAME
+  _fnmatch                      @853 NONAME
+  _getgroups                    @854 NONAME
+  _setgid                       @855 NONAME
+  _setuid                       @856 NONAME
+  _getpgrp                      @857 NONAME
+  _setsid                       @858 NONAME
+  _setpgid                      @859 NONAME
+  _optopt                       @860 NONAME
+  _sigsetjmp                    @861 NONAME
+  _siglongjmp                   @862 NONAME
+  _getvol                       @863 NONAME
+  errno                         @864 NONAME ; For single-thread library
+  _getpass1                     @865 NONAME
+  _getpass2                     @866 NONAME
+  _brk                          @867 NONAME
+  _uldiv                        @868 NONAME
+  _glob                         @869 NONAME
+  _globfree                     @870 NONAME
+  _uflags                       @871 NONAME
+  _fnslashify                   @872 NONAME
+  _strtoll                      @873 NONAME
+  _strtoull                     @874 NONAME
+  _strtof                       @875 NONAME
+  _setsyserrno                  @876 NONAME
+
+  acos                          @900 NONAME
+  asin                          @901 NONAME
+  atan                          @902 NONAME
+  atan2                         @903 NONAME
+  _cbrt                         @904 NONAME
+  ceil                          @905 NONAME
+  cos                           @906 NONAME
+  cosh                          @907 NONAME
+  exp                           @908 NONAME
+  fabs                          @909 NONAME
+  floor                         @910 NONAME
+  fmod                          @911 NONAME
+  frexp                         @912 NONAME
+  _hypot                        @913 NONAME
+  ldexp                         @914 NONAME
+  log                           @915 NONAME
+  log10                         @916 NONAME
+  modf                          @917 NONAME
+  pow                           @918 NONAME
+  _rint                         @919 NONAME
+  sin                           @920 NONAME
+  sinh                          @921 NONAME
+  sqrt                          @922 NONAME
+  tan                           @923 NONAME
+  tanh                          @924 NONAME
+  _trunc                        @925 NONAME
+  _fxam                         @926 NONAME
+  _clear87                      @927 NONAME
+  _control87                    @928 NONAME
+  _status87                     @929 NONAME
+  _fpreset                      @930 NONAME
+  _acosl                        @931 NONAME
+  _asinl                        @932 NONAME
+  _atanl                        @933 NONAME
+  _atan2l                       @934 NONAME
+  _cbrtl                        @935 NONAME
+  _ceill                        @936 NONAME
+  _cosl                         @937 NONAME
+  _coshl                        @938 NONAME
+  _expl                         @939 NONAME
+  _fabsl                        @940 NONAME
+  _floorl                       @941 NONAME
+  _fmodl                        @942 NONAME
+  _frexpl                       @943 NONAME
+  _hypotl                       @944 NONAME
+  _ldexpl                       @945 NONAME
+  _logl                         @946 NONAME
+  _log10l                       @947 NONAME
+  _modfl                        @948 NONAME
+  _powl                         @949 NONAME
+  _rintl                        @950 NONAME
+  _sinl                         @951 NONAME
+  _sinhl                        @952 NONAME
+  _sqrtl                        @953 NONAME
+  _tanl                         @954 NONAME
+  _tanhl                        @955 NONAME
+  _truncl                       @956 NONAME
+  _fxaml                        @957 NONAME
+  _HUGE_VAL                     @958 NONAME
+  _LHUGE_VAL                    @959 NONAME
+  _copysign                     @960 NONAME
+  _copysignf                    @961 NONAME
+  _copysignl                    @962 NONAME
+  __fpclassify                  @963 NONAME
+  __fpclassifyf                 @964 NONAME
+  __fpclassifyl                 @965 NONAME
+  __isfinite                    @966 NONAME
+  __isfinitef                   @967 NONAME
+  __isfinitel                   @968 NONAME
+  __isnan                       @969 NONAME
+  __isnanf                      @970 NONAME
+  __isnanl                      @971 NONAME
+  __isnormal                    @972 NONAME
+  __isnormalf                   @973 NONAME
+  __isnormall                   @974 NONAME
+  _nextafter                    @975 NONAME
+  _nextafterf                   @976 NONAME
+  _nextafterl                   @977 NONAME
+  __signbit                     @978 NONAME
+  __signbitf                    @979 NONAME
+  __signbitl                    @980 NONAME
+
+  asctime                       @1000 NONAME
+  clock                         @1001 NONAME
+  ctime                         @1002 NONAME
+  difftime                      @1003 NONAME
+  _ftime                        @1004 NONAME
+  _gettimeofday                 @1005 NONAME
+  gmtime                        @1006 NONAME
+  localtime                     @1007 NONAME
+  mktime                        @1008 NONAME
+  strftime                      @1009 NONAME
+  time                          @1010 NONAME
+  _times                        @1011 NONAME
+  _tzset                        @1012 NONAME
+  _day                          @1013 NONAME
+  _mktime                       @1014 NONAME
+  _tzset_flag                   @1015 NONAME
+  _daylight                     @1016 NONAME
+  _timezone                     @1017 NONAME
+  _tzname                       @1018 NONAME
+  _strptime                     @1019 NONAME
+  _settimeofday                 @1020 NONAME
+
+  _memaccess                    @1104 NONAME
+; _os2_emxio                    @1105 NONAME ; see emxlibc2.def
+  _portaccess                   @1111 NONAME
+
+  _emxload_env                  @1160 NONAME
+  _emxload_this                 @1161 NONAME
+  _emxload_prog                 @1162 NONAME
+  _emxload_unload               @1163 NONAME
+  _emxload_connect              @1164 NONAME
+  _emxload_disconnect           @1165 NONAME
+  _emxload_stop                 @1166 NONAME
+  _emxload_list_start           @1167 NONAME
+  _emxload_list_get             @1168 NONAME
+
+  _fncmp                        @1200 NONAME
+  _fnlwr                        @1201 NONAME
+  _nls_init                     @1202 NONAME
+  _nls_init_flag                @1203 NONAME
+  _nls_strlwr                   @1204 NONAME
+  _nls_strupr                   @1205 NONAME
+  _rfnlwr                       @1206 NONAME
+  _sfnlwr                       @1207 NONAME
+  _nls_toupper_tab              @1208 NONAME
+  _nls_tolower_tab              @1209 NONAME
+  _fnlwr2                       @1210 NONAME
+
+  setlocale                     @1260 NONAME
+  localeconv                    @1261 NONAME
+  _localeconv                   @1262 NONAME
+
+  _mb_cur_max                   @1270 NONAME
+  mblen                         @1271 NONAME
+  mbstowcs                      @1272 NONAME
+  mbtowc                        @1273 NONAME
+  wcstombs                      @1274 NONAME
+  wctomb                        @1275 NONAME
+
+  _set_new_handler              @1300 NONAME
+  _lldiv                        @1301 NONAME
+  _ulldiv                       @1302 NONAME
+  __builtin_delete              @1303 NONAME
+  __builtin_new                 @1304 NONAME
+; __builtin_vec_delete          @1305 NONAME ; see emxlibc2.def
+; __builtin_vec_new             @1306 NONAME ; see emxlibc2.def
+  __cmpdi2                      @1307 NONAME
+  __divdi3                      @1308 NONAME
+  __divsi3                      @1309 NONAME
+  __fixdfsi                     @1310 NONAME
+  __fixunsdfdi                  @1311 NONAME
+  __fixunsdfsi                  @1312 NONAME
+; __main_08f                    @1313 NONAME ; see emxlibc2.def
+  __moddi3                      @1314 NONAME
+  __muldi3                      @1315 NONAME
+  __new_handler                 @1316 NONAME
+  __probe                       @1317 NONAME
+; __set_new_handler             @1318 NONAME ; see emxlibc2.def
+  __udivdi3                     @1319 NONAME
+  __udivsi3                     @1320 NONAME
+  __umoddi3                     @1321 NONAME
+  __fixunsxfdi                  @1322 NONAME
+; __main_08h                    @1323 NONAME ; see emxlibc2.def
+  __builtin_vec_delete          @1324 NONAME ; new version for GCC 2.6
+  __builtin_vec_new             @1325 NONAME ; new version for GCC 2.6
+  __fixunssfdi                  @1326 NONAME
+  __pure_virtual                @1327 NONAME
+  __ucmpdi2                     @1328 NONAME
+  __find_first_exception_table_match @1329 NONAME ; For backward compatibility
+  __unwind_function             @1330 NONAME ; For backward compatibility
+  __throw_type_match            @1331 NONAME
+  __register_exceptions         @1332 NONAME ; For backward compatibility
+  __bb_init_func                @1333 NONAME
+  __dummy                       @1334 NONAME
+  __dynamic_cast                @1335 NONAME
+  __is_pointer__FPv             @1336 NONAME
+  __rtti_array                  @1337 NONAME
+  __rtti_attr                   @1338 NONAME
+  __rtti_class                  @1339 NONAME
+  __rtti_func                   @1340 NONAME
+  __rtti_ptmd                   @1341 NONAME
+  __rtti_ptmf                   @1342 NONAME
+  __rtti_ptr                    @1343 NONAME
+  __rtti_si                     @1344 NONAME
+  __rtti_user                   @1345 NONAME
+  __tfb                         @1346 NONAME
+  __tfc                         @1347 NONAME
+  __tfd                         @1348 NONAME
+  __tff                         @1349 NONAME
+  __tfi                         @1350 NONAME
+  __tfl                         @1351 NONAME
+  __tfr                         @1352 NONAME
+  __tfs                         @1353 NONAME
+  __tfv                         @1354 NONAME
+  __tfw                         @1355 NONAME
+  __tfx                         @1356 NONAME
+  __tfUc                        @1357 NONAME
+  __tfUi                        @1358 NONAME
+  __tfUl                        @1359 NONAME
+  __tfUs                        @1360 NONAME
+  __tfUx                        @1361 NONAME
+  __throw_type_match_rtti       @1362 NONAME
+  __throw_bad_cast              @1363 NONAME
+  before__C9type_infoRC9type_info @1364 NONAME  ; type_info::before
+  name__C9type_info             @1365 NONAME    ; type_info::name
+  __eq__C9type_infoRC9type_info @1366 NONAME    ; type_info::operator==
+  __ne__C9type_infoRC9type_info @1367 NONAME    ; type_info::operator!=
+  terminate__Fv                 @1368 NONAME    ; terminate()
+  set_terminate__FPFv_v         @1369 NONAME    ; set_terminate(void (*)())
+  __eh_frame_init               @1370 NONAME
+  __eh_frame_term               @1371 NONAME
+  __eh_pc                       @1372 NONAME
+  __throw                       @1373 NONAME
+  __cp_exception_info           @1374 NONAME
+  __cp_pop_exception            @1375 NONAME
+  __cp_push_exception           @1376 NONAME
+  _$_9bad_alloc                 @1377 NONAME    ; bad_alloc::~bad_alloc()
+  _vt$9bad_alloc                @1378 NONAME    ; bad_alloc virtual table
+  __tf9bad_alloc                @1379 NONAME
+  what__C9bad_alloc             @1380 NONAME    ; bad_alloc::what() const
+  __nw__FUlPv                   @1381 NONAME    ; operator new(...)
+  __vn__FUlPv                   @1382 NONAME    ; operator new[](...)
+  nothrow                       @1383 NONAME
+  __nw__FUlRC9nothrow_t         @1384 NONAME    ; operator new(...)
+  __vn__FUlRC9nothrow_t         @1385 NONAME    ; operator new[](...)
+  __uncatch_exception           @1386 NONAME
+  __throw_bad_typeid            @1387 NONAME
+  what__C9exception             @1388 NONAME    ; exception::what() const
+  unexpected__Fv                @1389 NONAME    ; unexpected()
+  set_unexpected__FPFv_v        @1390 NONAME    ; set_unexpected(void (*)())
+  uncaught_exception__Fv        @1391 NONAME    ; uncaught_exception()
+  _vt$13bad_exception           @1392 NONAME    ; bad_exception virtual table
+  __tf13bad_exception           @1393 NONAME    ; bad_exception type_info func
+  __13bad_exception             @1394 NONAME    ; bad_exception()
+  _$_13bad_exception            @1395 NONAME    ; ~bad_exception()
+  _vt$9exception                @1396 NONAME    ; exception virtual table
+  __tf9exception                @1397 NONAME    ; exception type_info func
+  __9exception                  @1398 NONAME    ; exception()
+  _$_9exception                 @1399 NONAME    ; ~exception()
+; ...continued at ordinal 1600
+
+  __alarm                       @1400 NONAME
+  __cgets                       @1401 NONAME
+  __chdir                       @1402 NONAME
+  __chdrive                     @1403 NONAME
+  __chmod                       @1404 NONAME
+  __chsize                      @1405 NONAME
+  __clock                       @1406 NONAME
+  __close                       @1407 NONAME
+  __core                        @1408 NONAME
+  __dup                         @1409 NONAME
+  __dup2                        @1410 NONAME
+  __emx_version                 @1411 NONAME
+  __exit                        @1412 NONAME
+  __fcntl                       @1413 NONAME
+  __filesys                     @1414 NONAME
+  __findfirst                   @1415 NONAME
+  __findnext                    @1416 NONAME
+  __fork                        @1417 NONAME
+  __fstat                       @1418 NONAME
+  __fsync                       @1419 NONAME
+  __ftime                       @1420 NONAME
+  __ftruncate                   @1421 NONAME
+  __getcwd                      @1422 NONAME
+  __getdrive                    @1423 NONAME
+  __getpid                      @1424 NONAME
+  __getppid                     @1425 NONAME
+  __ioctl1                      @1426 NONAME
+  __ioctl2                      @1427 NONAME
+  __kill                        @1428 NONAME
+  __lseek                       @1429 NONAME
+  __memaccess                   @1430 NONAME
+  __memavail                    @1431 NONAME
+  __mkdir                       @1432 NONAME
+  __nls_memupr                  @1433 NONAME
+  __open                        @1434 NONAME
+  __os_version                  @1435 NONAME
+  __pipe                        @1436 NONAME
+  __portaccess                  @1437 NONAME
+  __ptrace                      @1438 NONAME
+  __raise                       @1439 NONAME
+  __read                        @1440 NONAME
+  __read_kbd                    @1441 NONAME
+  __remove                      @1442 NONAME
+  __rename                      @1443 NONAME
+  __rmdir                       @1444 NONAME
+  __sbrk                        @1445 NONAME
+  __scrsize                     @1446 NONAME
+  __select                      @1447 NONAME
+  __signal                      @1448 NONAME
+  __sleep                       @1449 NONAME
+  __spawnve                     @1450 NONAME
+  __stat                        @1451 NONAME
+  __swchar                      @1452 NONAME
+  __syserrno                    @1453 NONAME
+  __uflags                      @1454 NONAME
+  __ulimit                      @1455 NONAME
+  __umask                       @1456 NONAME
+; __unwind                      @1457 NONAME ; see emxlibc2.def
+  __utimes                      @1458 NONAME
+  __wait                        @1459 NONAME
+  __write                       @1460 NONAME
+  __newthread                   @1461 NONAME
+  __endthread                   @1462 NONAME
+  __waitpid                     @1463 NONAME
+  __sleep2                      @1464 NONAME
+  __unwind2                     @1465 NONAME
+  __pause                       @1466 NONAME
+  __execname                    @1467 NONAME
+  __initthread                  @1468 NONAME
+  __sigaction                   @1469 NONAME
+  __sigpending                  @1470 NONAME
+  __sigprocmask                 @1471 NONAME
+  __sigsuspend                  @1472 NONAME
+  __imphandle                   @1473 NONAME
+  __accept                      @1474 NONAME
+  __bind                        @1475 NONAME
+  __connect                     @1476 NONAME
+  __gethostbyaddr               @1477 NONAME
+  __gethostbyname               @1478 NONAME
+  __gethostid                   @1479 NONAME
+  __gethostname                 @1480 NONAME
+  __getnetbyaddr                @1481 NONAME
+  __getnetbyname                @1482 NONAME
+  __getpeername                 @1483 NONAME
+  __getprotobyname              @1484 NONAME
+  __getprotobynumber            @1485 NONAME
+  __getservbyname               @1486 NONAME
+  __getservbyport               @1487 NONAME
+  __getsockhandle               @1488 NONAME
+  __getsockname                 @1489 NONAME
+  __getsockopt                  @1490 NONAME
+  __listen                      @1491 NONAME
+  __recv                        @1492 NONAME
+  __recvfrom                    @1493 NONAME
+  __send                        @1494 NONAME
+  __sendto                      @1495 NONAME
+  __setsockopt                  @1496 NONAME
+  __shutdown                    @1497 NONAME
+  __socket                      @1498 NONAME
+  __brk                         @1499 NONAME
+  __impsockhandle               @1500 NONAME
+  __ttyname                     @1501 NONAME
+  __settime                     @1502 NONAME
+  __profil                      @1503 NONAME
+  __nls_ctype                   @1504 NONAME
+  __setsyserrno                 @1505 NONAME
+
+  __ti9exception                @1600 NONAME    ; exception type_info node
Index: trunk/src/emx/src/lib/cdll/emxlibc.sed
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibc.sed	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibc.sed	(revision 18)
@@ -0,0 +1,1 @@
+/For single-thread library/d
Index: trunk/src/emx/src/lib/cdll/emxlibc.tsf
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibc.tsf	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibc.tsf	(revision 18)
@@ -0,0 +1,38 @@
+;
+; emxlibc.tsf
+;
+MAXDATALENGTH=512
+
+TYPELIST
+  NAME=PRE,  ID=0x0001,
+  NAME=INT,  ID=0x0020,
+  NAME=API,  ID=0x0080,
+  NAME=POST, ID=0x8000
+
+GROUPLIST
+  NAME=STDIO,   ID=1
+  NAME=LOWIO,   ID=2
+  NAME=PROCESS, ID=3
+  NAME=SIGNAL,  ID=4
+  NAME=TIME,    ID=5
+  NAME=FNAME,   ID=6
+  NAME=MATH,    ID=7
+  NAME=MALLOC,  ID=8
+  NAME=STRING,  ID=9
+  NAME=SYSCALL, ID=10
+  NAME=EA,      ID=11
+  NAME=CONV,    ID=12
+  NAME=EMXLOAD, ID=13
+  NAME=PWD,     ID=14
+  NAME=DIR,     ID=15
+  NAME=CTYPE,   ID=16
+  NAME=TERMIOS, ID=17
+  NAME=LOCALE,  ID=18
+  NAME=GCC,     ID=19
+  NAME=SEM,     ID=20
+  NAME=ENV,     ID=21
+  NAME=NLS,     ID=22
+  NAME=INIT,    ID=23
+  NAME=OTHER,   ID=24
+  NAME=RTTI,    ID=25
+
Index: trunk/src/emx/src/lib/cdll/emxlibc.tss
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibc.tss	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibc.tss	(revision 18)
@@ -0,0 +1,905 @@
+;
+; emxlibc.tss
+;
+G STDIO
+T API
+v clearerr (p stream)
+i fclose (p stream)
+i feof (p stream)
+i ferror (p stream)
+i fflush (p stream)
+i fgetc (p stream)
+i fgetpos (p stream, p pos)
+i fgetpos_09b (p stream, p pos)
+p fgets (p buffer, i size, p stream)
+i fileno (p stream)
+p fopen (s fname, s mode)
+i fprintf (p stream, p format)
+i fputc (i char, p stream)
+i fputs (p string, p stream)
+i fread (p buffer, i size, i count, p stream)
+p freopen (s fname, s mode, p stream)
+i fscanf (p stream, p format)
+i fseek (p stream, i offset, i origin)
+i fsetpos (p stream, p pos)
+i fsetpos_09b (p stream, p pos)
+i ftell (p stream)
+i fwrite (p buffer, i size, i count, p stream)
+i getchar ()
+p gets (p buffer)
+v perror (p string)
+i printf (p format)
+i putchar (i char)
+i puts (p string)
+i remove (s fname)
+i rename (s oldfname, s newfname)
+v rewind (p stream)
+i scanf (p format)
+i setbuf (p stream, p buffer)
+i setvbuf (p stream, p buffer, i mode, i size)
+i sprintf (p buffer, p format)
+i sscanf (p buffer, p format)
+p tmpfile ()
+p tmpnam (p string)
+i ungetc (i char, p stream)
+i vfprintf (p stream, p format, p va_list)
+i vprintf (p format, p va_list)
+i vsprintf (p buffer, p format, p va_list)
+p fdopen (i handle, s mode)
+p cuserid (p buffer)
+i getw (p stream)
+i fcloseall ()
+i fgetchar ()
+i flushall ()
+i fputchar (i char)
+i pclose (p stream)
+p popen (p command, s mode)
+i putw (i word, p stream)
+i setbuffer (p stream, p buffer, i size)
+i snprintf (p buffer, i size, p format)
+p tempnam (p dir, p prefix)
+i vfscanf (p stream, p format, p va_list)
+i vscanf (p format, p va_list)
+i vsnprintf (p buffer, i size, p format, p va_list)
+i vsscanf (p buffer, p format, p va_list)
+p _fassign (p target_stream, p source_stream)
+i _fseek_hdr (p stream)
+p _fsetmode (p stream, s mode)
+p _fsopen (s fname, s mode, i shflag)
+i _getc_inline (p stream)
+p _mfclose (p stream)
+p _mfopen (p buffer, s mode, i size, i inc)
+i _putc_inline (i char, p stream)
+i _rmtmp ()
+
+T INT
+v _fbuf (p stream)
+p _fd_flags (i handle)
+p _fd_init (i handle)
+p _fd_lookahead (i handle)
+i _fill (p stream)
+i _flush (i char, p stream)
+p _fopen (p dst, s fname, s mode, i shflag, i lock)
+p _newstream ()
+
+G LOWIO
+T API
+i access (s fname, i mode)
+i chmod (s fname, i pmode)
+i chsize (i handle, i size)
+i close (i handle)
+i creat (s fname, i pmode)
+i dup (i handle)
+i dup2 (i handle1, i handle2)
+i eof (i handle)
+i fcntl (i handle, i request)
+i filelength (i handle)
+i flock (i handle, i operation)
+i fstat (i handle, p buffer)
+i fsync (i handle)
+i ftruncate(i handle, i size)
+i ioctl (i handle, i request)
+i isatty (i handle)
+i lseek (i handle, i offset, i origin)
+i mkstemp (p string)
+p mktemp (p string)
+i open (s fname, i oflag)
+i pipe (p two_handles)
+i read (i handle, p buffer, i size)
+i readv (i handle, p vector, i count)
+i select (i nfds, p readfds, p writefds, p exceptfds, p timeout)
+i setmode (i handle, i mode)
+i sopen (s fname, i oflag, i shflag)
+i stat (s path, p buffer)
+i tell (i handle)
+i truncate (s fname, i size)
+p ttyname (i handle)
+i umask (i pmode)
+i unlink (p fname)
+i utime (s path, p times)
+i utimes (s path, p tvp)
+i write (i handle, p buffer, i size)
+i writev (i handle, p vector, i count)
+i _crlf (p buffer, i size, p new_size)
+i _imphandle (i handle)
+i _isterm (i handle)
+i _seek_hdr (i handle)
+
+T INT
+i _vsopen (s fname, i oflag, i shflag)
+
+G PROCESS
+T API
+v abort ()
+i atexit (p function)
+i execl (s program, p arg0)
+i execle (s program, p arg0)
+i execlp (s program, p arg0)
+i execlpe (s program, p arg0)
+i execv (s program, p args)
+i execve (s program, p argv, p envp)
+i execvp (s program, p argv)
+i execvpe (s program, p argv)
+i exit (i termination_code)
+i fork ()
+i getpid ()
+i getppid ()
+i spawnl (i mode, s program, p arg0)
+i spawnle (i mode, s program, p arg0)
+i spawnlp (i mode, s program, p arg0)
+i spawnlpe (i mode, s program, p arg0)
+i spawnv (i mode, s program, p argv)
+i spawnve (i mode, s program, p argv, p envp)
+i spawnvp (i mode, s program, p argv)
+i spawnvpe (i mode, s program, p argv, p envp)
+i system (p command)
+i wait (p stat_loc)
+i waitpid (i pid, p stat_loc, i options)
+v _assert (p exp, s file, i line)
+i _exit (i termination_code)
+i _gettid ()
+p _threadid ()
+
+G TIME
+T API
+i alarm (i seconds)
+p asctime (p tm)
+p ctime (p time)
+i clock ()
+v difftime (i t1, i t0)
+v ftime (p ptr)
+i gettimeofday (p tp, p tzp)
+p gmtime (p time)
+p localtime (p time)
+i mktime (p tm)
+i sleep (i seconds)
+i settimeofday (p tp, p tzp)
+i strftime (p buffer, p format, p tm)
+p strptime (p buffer, p format, p tm)
+i time (p time)
+i times (p buffer)
+v tzset ()
+i _sleep2 (i millisec)
+
+T INT
+i _day (i year, i month, i day)
+i _mktime (p tm)
+
+G SIGNAL
+T API
+p signal (i signo, p handler)
+i raise (i signo)
+i kill (i pid, i signo)
+i pause ()
+i sigaction (i signo, p iact, p oact)
+i sigaddset (p set, i signo)
+i sigdelset (p set, i signo)
+i sigemptyset (p set)
+i sigfillset (p set)
+i sigismember (p set, i signo)
+i sigpending (p set)
+i sigprocmask (i how, p iset, p oset)
+i sigsuspend (p set)
+
+G FNAME
+T API
+i fnmatch (p pattern, p name, i flags)
+i _abspath (p dst, p src, i dst_size)
+v _defext (p path, p ext)
+i _fncmp (p fname1, p fname2)
+p _fnexplode (p mask)
+v _fnexplodefree (p list)
+i _fngetdrive (p path)
+i _fnisabs (p path)
+i _fnisrel (p path)
+v _fnlwr (p path)
+v _fnlwr2 (p path, p base)
+p _fnslashify (p path)
+i _fullpath (p dst, p src, i dst_size)
+p _getext (p path)
+p _getext2 (p path)
+p _getname (p path)
+v _makepath (p dst, p drive, p dir, p fname, p ext)
+v _remext (p path)
+v _rfnlwr ()
+v _sfnlwr (p path)
+v _splitpath (p src, p drive, p dir, p fname, p ext)
+
+G MATH
+T API
+v acos (q x)
+v asin (q x)
+v atan (q x)
+v atan2 (q y, q x)
+v ceil (q x)
+v cos (q x)
+v cosh (q x)
+v exp (q x)
+v fabs (q x)
+v floor (q x)
+v fmod (q x, q y)
+v frexp (q x, p exp_ptr)
+v ldexp (q x, i exp)
+v log (q x)
+v log10 (q x)
+v modf (q x, p int_ptr)
+v pow (q x, q y)
+v sin (q x)
+v sinh (q x)
+v sqrt (q x)
+v tan (q x)
+v tanh (q x)
+v cbrt (q x)
+v hypot (q x, q y)
+v rint (q x)
+v trunc (q x)
+q _copysign (q x, q y)
+i _copysignf (i x, i y)
+v _copysignl ()                 ; TODO
+q _nextafter (q x, q y)
+i _nextafterf (i x, i y)
+v _nextafterl ()                ; TODO
+
+i __fpclassify (q x)
+i __fpclassifyf (i x)
+i __fpclassifyl ()              ; TODO
+i __isfinite (q x)
+i __isfinitef (i x)
+i __isfinitel ()                ; TODO
+i __isnan (q x)
+i __isnanf (i x)
+i __isnanl ()                   ; TODO
+i __isnormal (q x)
+i __isnormalf (i x)
+i __isnormall ()                ; TODO
+i __signbit (q x)
+i __signbitf (i x)
+i __signbitl ()                 ; TODO
+
+v _acosl ()                     ; TODO
+v _asinl ()                     ; TODO
+v _atanl ()                     ; TODO
+v _atan2l ()                    ; TODO
+v _ceill ()                     ; TODO
+v _cosl ()                      ; TODO
+v _coshl ()                     ; TODO
+v _expl ()                      ; TODO
+v _fabsl ()                     ; TODO
+v _floorl ()                    ; TODO
+v _fmodl ()                     ; TODO
+v _frexpl ()                    ; TODO
+v _ldexpl ()                    ; TODO
+v _logl ()                      ; TODO
+v _log10l ()                    ; TODO
+v _modfl ()                     ; TODO
+v _powl ()                      ; TODO
+v _sinl ()                      ; TODO
+v _sinhl ()                     ; TODO
+v _sqrtl ()                     ; TODO
+v _tanl ()                      ; TODO
+v _tanhl ()                     ; TODO
+v _cbrtl ()                     ; TODO
+v _hypotl ()                    ; TODO
+v _rintl ()                     ; TODO
+v _truncl ()                    ; TODO
+
+i _clear87 ()
+i _control87 (i new_cw, i mask)
+v _fpreset ()
+i _fxam (q x)
+i _fxaml ()                     ; TODO
+i _status87 ()
+
+G INIT
+T INT
+i _CRT_init ()
+v _CRT_term ()
+i _DLL_InitTerm (i modhandle, i flag)
+v _cleanup ()
+v _entry1 ()
+v _entry2 ()
+v _startup ()
+v __ctordtorInit1 (p ptr)
+v __ctordtorTerm1 (p ptr)
+v __eh_frame_init (p ptr)
+v __eh_frame_term (p ptr)
+v __register_frame_info_table (p ptr, p obj)
+v __deregister_frame_info (p ptr)
+
+G SYSCALL
+T INT
+i __accept (i handle, p addr, p paddrlen)
+i __alarm (i seconds)
+i __bind (i handle, p addr, i addrlen)
+p __brk (p addr)
+v __cgets (p buffer)
+i __chdir (s path)
+i __chmod (s fname, i flag, i attr)
+i __chdrive (i drive)
+i __chsize (i handle, i size)
+q __clock ()
+i __close (i handle)
+i __connect (i handle, p addr, i addrlen)
+i __core (i handle)
+i __dup (i handle)
+i __dup2 (i handle1, i handle2)
+i __emx_version ()
+i __endthread (i tid)
+i __execname (p buffer, i size)
+i __exit (i termination_code)
+i __fcntl (i handle, i request, i arg)
+i __filesys (p drive, p name, i size)
+i __findfirst (p name, i attr, p buffer)
+i __findnext (p buffer)
+i __fork ()
+i __fstat (i handle, p buffer)
+i __fsync (i handle)
+v __ftime (p ptr)
+i __ftruncate (i handle, i size)
+i __getcwd (p buffer, i drive)
+i __getdrive ()
+i __gethostbyaddr (p addr, i len, i type, p dst)
+i __gethostbyname (p name, p dst)
+i __gethostid (p dst)
+i __gethostname (p name, i len)
+i __getnetbyname (p name, p dst)
+i __getnetbyaddr (i net, p dst)
+i __getpeername (i handle, p name, p pnamelen)
+i __getpid ()
+i __getppid ()
+i __getprotobyname (p name, p dst)
+i __getprotobynumber (i prot, p dst)
+i __getservbyname (p name, p proto, p dst)
+i __getservbyport (i port, p proto, p dst)
+i __getsockhandle (i handle)
+i __getsockname (i handle, p name, p pnamelen)
+i __getsockopt (i handle, i level, i optname, p optval, p poptlen)
+i __imphandle (i handle)
+i __impsockhandle (i handle, i flags)
+i __initthread (p preg)
+i __ioctl1 (i handle, i code)
+i __ioctl2 (i handle, i request, i arg)
+i __kill (i pid, i signo)
+i __listen (i handle, i backlog)
+i __lseek (i handle, i offset, i origin)
+p __memaccess (i first, i last, i flag)
+i __memavail ()
+i __mkdir (s path)
+i __newthread (i tid)
+v __nls_ctype (p buffer)
+v __nls_memupr (p buffer, i size)
+i __open (s fname, i flags, i size)
+i __os_version ()
+v __pause ()
+i __pipe (p two_handles, i pipe_size)
+i __portaccess (i first, i last)
+i __profil (p buffer)
+i __ptrace (i request, i pid, i addr, i data)
+i __raise (i signo)
+i __read (i handle, p buffer, i size)
+i __read_kbd (i echo, i wait, i sig)
+i __recv (i handle, p buf, i len, i flags)
+i __recvfrom (p args)
+i __remove (s path)
+i __rename (s old_name, s new_name)
+i __rmdir (s path)
+p __sbrk (i incr)
+v __scrsize (p dst)
+i __select (p args)
+i __send (i handle, p buffer, i len, i flags)
+i __sendto (p args)
+i __setsockopt (i handle, i level, i optname, p optval, i optlen)
+i __settime (p time)
+i __shutdown (i handle, i how)
+i __sigaction (i signo, p iact, p oact)
+i __signal (i signo, p handler)
+i __sigpending (p set)
+i __sigprocmask (i how, p iset, p oset)
+i __sigsuspend (p set)
+i __sleep (i seconds)
+i __sleep2 (i millisec)
+i __socket (i domain, i type, i protocol)
+i __spawnve (p new_proc)
+i __stat (s fname, p buffer)
+i __swchar (i flag, i new_char)
+i __setsyserrno (i code)
+i __syserrno ()
+i __uflags (i mask, i new_flags)
+i __ulimit (i cmd, i new_limit)
+i __umask (i pmode)
+v __unwind2 (p xcpt_reg_ptr)
+i __utimes (s path, p tvp)
+i __ttyname (i handle, p buffer, i size)
+i __wait (p stat_loc)
+i __waitpid (i pid, p stat_loc, i options)
+i __write (i handle, p buffer, i size)
+
+G MALLOC
+T API
+i brk (i addr)
+p calloc (i elements, i size)
+v free (p mem)
+p malloc (i size)
+p realloc (p mem, i size)
+p sbrk (i incr)
+p _expand (p mem, i size)
+i _heapchk ()
+i _heapmin ()
+i _heapset (i fill)
+i _heap_walk (p callback)
+p _mheap (p mem)
+i _msize (p mem)
+p _tcalloc (i elements, i size)
+v _tfree (p mem)
+i _theapmin ()
+p _tmalloc (i size)
+p _trealloc (p mem, i size)
+p _uaddmem (p heap, p memory, i size, i clean)
+p _ucalloc (p heap, i elements, i size)
+i _uclose (p heap)
+p _ucreate (p memory, i size, i clean, i type, p alloc_fun, p release_fun)
+p _ucreate2 (p memory, i size, i clean, i type, p alloc_fun, p release_fun, p expand_fun, p shrink_fun)
+p _udefault (p heap)
+i _udestroy (p heap)
+i _uheapchk (p heap)
+i _uheapmin (p heap)
+i _uheapset (p heap, i fill)
+i _uheap_type (p heap)
+i _uheap_walk (p heap, p callback)
+i _uheap_walk2 (p heap, p callback, p arg)
+p _umalloc (p heap, i size)
+i _uopen (p heap)
+i _ustats (p heap, p pstats)
+p _utcalloc (p heap, i elements, i size)
+p _utdefault (p heap)
+p _utmalloc (p heap, i size)
+
+G STRING
+T API
+i bcmp (p string1, p string2, i size)
+v bcopy (p src, p dst, i size)
+v bzero (p dst, i size)
+p index (p string, i char)
+p memccpy (p buffer1, p buffer2, i char, i size)
+p memchr (p buffer, i char, i size)
+i memcmp (p buffer1, p buffer2, i size)
+p memcpy (p dst, p src, i size)
+i memicmp (p buffer1, p buffer2, i size)
+p memmove (p dst, p src, i size)
+p memset (p buffer, i char, i size)
+p rindex (p string, i char)
+p strcat (p dst, p src)
+p strchr (p string, i char)
+i strcmp (p string1, p string2)
+i strcoll (p string1, p string2)
+p strcpy (p dst, p src)
+i strcspn (p string1, p string2)
+p strdup (p string)
+p strerror (i errno)
+i strlen (p string)
+p strncat (p dst, p src, i n)
+i stricmp (p string1, p string2)
+p strlwr (p string)
+i strncmp (p string1, p string2, i n)
+p strncpy (p dst, p src, i n)
+i strnicmp (p string1, p string2, i n)
+p strnset (p string, i char, i n)
+p strpbrk (p string1, p string2)
+p strrchr (p string, i char)
+p strrev (p string)
+v strset (p dst, i char)
+i strspn (p string1, p string2)
+p strstr (p string1, p string2)
+p strtok (p string1, p string2)
+p strupr (p string)
+i strxfrm (p string1, p string2, i n)
+i _memcount (p buffer, i char, i size)
+i _memdif (p buffer1, p buffer2, i size)
+p _memrchr (p buffer, i char, i size)
+v _memswap (p buffer1, p buffer2, i size)
+p _strncpy (p dst, p src, i size)
+
+G CTYPE
+T API
+i isalnum (i char)
+i isalpha (i char)
+i isascii (i char)
+i iscntrl (i char)
+i isdigit (i char)
+i isgraph (i char)
+i islower (i char)
+i isprint (i char)
+i ispunct (i char)
+i isspace (i char)
+i isupper (i char)
+i isxdigit (i char)
+i toascii (i char)
+i tolower (i char)
+i toupper (i char)
+i _tolower (i char)
+i _toupper (i char)
+
+G NLS
+T API
+v _nls_init ()
+p _nls_strlwr (p string)
+p _nls_strupr (p string)
+
+G CONV
+T API
+v atof (p string)
+i atoi (p string)
+i atol (p string)
+p gcvt (q x, i digits, p buffer)
+v strtod (p string, p end)
+i strtol (p string, p end, i radix)
+i strtoul (p string, p end, i radix)
+v _atofl (p string)
+q _atoll (p string)
+p _itoa (i x, p string, i radix)
+p _lltoa (q x, p string, i radix)
+p _ltoa (i x, p string, i radix)
+i _strtof (p string, p end)
+v _strtold (p string, p end)
+q _strtoll (p string, p end, i radix)
+q _strtoull (p string, p end, i radix)
+p _ulltoa (q x, p string, i radix)
+p _ultoa (i x, p string, i radix)
+
+G LOCALE
+T API
+p setlocale (i category, s locale)
+p localeconv ()
+i mblen (p string, i size)
+i mbstowcs (p dst, p src, i size)
+i mbtowc (p dst, p src, i size)
+i wcstombs (p dst, p src, i size)
+i wctomb (p dst, p src)
+
+T INT
+p _localeconv (i char_max)
+
+G PWD
+T API
+v endpwent ()
+i getegid ()
+i geteuid ()
+i getgid ()
+p getgrgid (i gid)
+p getgrnam (p name)
+i getgroups (i gidsetsize, p grouplist)
+p getlogin ()
+p getpass (p prompt)
+i getpgrp ()
+p getpwent ()
+p getpwnam (p name)
+p getpwuid (i uid)
+i getuid ()
+i setgid (i gid)
+i setpgid (i pid, i pgid)
+v setpwent ()
+i setsid ()
+i setuid (i uid)
+p _getpass1 (p prompt)
+p _getpass2 (p prompt, i kbd)
+
+G DIR
+T API
+i chdir (s path)
+i ftw (s path, p function, i depth)
+p getcwd (p buffer, i size)
+p getwd (p buffer)
+i glob (p pattern, i flags, p errfunc, p pglob)
+v globfree (p pglob)
+i mkdir (s path, i mode)
+p opendir (s name)
+i closedir (p dirp)
+p readdir (p dirp)
+v seekdir (p dirp, i off)
+i telldir (p dirp)
+v rewinddir (p dirp)
+i rmdir (s path)
+i _chdir2 (s path)
+i _chdrive (i drive)
+v _dt_free (p dt)
+p _dt_read (s dir, s mask, i flags)
+v _dt_sort (p dt, s spec)
+i _dt_split (s src, p dir, p mask)
+i _getcwd1 (p buffer, i drive)
+p _getcwd2 (p buffer, i size)
+i _getdrive ()
+v _wildcard (p argcp, p argvp)
+
+G TERMIOS
+T API
+i cfgetispeed (p ptermios)
+i cfgetospeed (p ptermios)
+i cfsetispeed (p ptermios, i speed)
+i cfsetospeed (p ptermios, i speed)
+i tcdrain (i handle)
+i tcflow (i handle)
+i tcflush (i handle)
+i tcgetattr (i handle, p ptermios)
+i tcgetpgrp (i handle)
+i tcsendbreak (i handle, i duration)
+i tcsetattr (i handle, i options, p ptermios)
+i tcsetpgrp (i handle, i pgrp)
+
+G EA
+T API
+v _ea_free (p ptr)
+i _ea_get (p dst, p path, i handle, s name)
+i _ea_put (p src, p path, i handle, s name)
+i _ea_remove (s path, i handle, s name)
+i _ead_add (p ead, s name, i flags, p value, i size)
+v _ead_clear (p ead)
+i _ead_copy (p dst, p src, i index)
+i _ead_count (p ead)
+p _ead_create ()
+i _ead_delete (p ead, i index)
+v _ead_destroy (p ead)
+i _ead_fea2list_size (p ead)
+p _ead_fea2list_to_fealist (p src)
+p _ead_fealist_to_fea2list (p src)
+i _ead_find (p ead, s name)
+p _ead_get_fea2list (p ead)
+i _ead_get_flags (p ead, i index)
+p _ead_get_name (p ead, i index)
+p _ead_get_value (p ead, i index)
+p _ead_name_len (p ead, i index)
+i _ead_read (p ead, p path, i handle, i flags)
+i _ead_replace (p ead, i index, i flags, p value, i size)
+v _ead_sort (p ead)
+i _ead_use_fea2list (p ead, p src)
+i _ead_value_size (p ead, i index)
+i _ead_write (p ead, p path, i handle, i flags)
+
+G EMXLOAD
+T API
+i _emxload_env (p envname)
+i _emxload_this (i seconds)
+i _emxload_prog (p name, i seconds)
+i _emxload_unload (p name, i wait_flag)
+i _emxload_list_start ()
+i _emxload_list_get (p buffer, i size, p pseconds)
+i _emxload_connect ()
+i _emxload_disconnect ()
+i _emxload_stop (i wait_flag)
+
+G SEM
+T API
+v _fmutex_checked_close (p sem)
+v _fmutex_checked_create (p sem, i flags)
+v _fmutex_checked_open (p sem)
+v _fmutex_checked_release (p sem)
+v _fmutex_checked_request (p sem, i flags)
+i _fmutex_create (p sem, i flags)
+i _fmutex_open (p sem)
+i _fmutex_close (p sem)
+v _fmutex_dummy (p sem)
+i _rmutex_checked_close (p sem)
+i _rmutex_checked_create (p sem, i flags)
+i _rmutex_checked_open (p sem)
+i _rmutex_close (p sem)
+i _rmutex_create (p sem, i flags)
+i _rmutex_dummy (p sem)
+i _rmutex_open (p sem)
+
+T INT
+i __fmutex_request_internal (p sem, i flags, i fs)
+i __fmutex_release_internal (p sem)
+v __smutex_request_internal (p sem)
+
+G GCC
+T API
+p set_new_handler (p handler)
+p set_terminate__FPFv_v (p func)
+p set_unexpected__FPFv_v (p func)
+v terminate__Fv ()
+v uncaught_exception__Fv ()     ; uncaught_exception()
+v unexpected__Fv ()             ; unexpected()
+v what__C9bad_alloc ()          ; TODO bad_alloc::what() const
+v what__C9exception ()          ; TODO exception::what() const
+v _$_13bad_exception()          ; TODO bad_exception::~bad_exception()
+v _$_9exception()               ; TODO exception::~exception()
+v __13bad_exception()           ; TODO bad_exception::bad_exception()
+v __nw__FUlPv ()                ; TODO operator new(...)
+v __nw__FUlRC9nothrow_t ()      ; TODO operator new(...)
+v __tf9bad_alloc()              ; TODO bad_alloc type info function
+v __tf13bad_exception()         ; TODO bad_exception type info function
+v __tf9exception()              ; TODO exception type info function
+v __vn__FUlPv ()                ; TODO operator new[](...)
+v __vn__FUlRC9nothrow_t ()      ; TODO operator new[](...)
+v __9exception()                ; TODO exception::exception()
+
+T INT
+i __cmpdi2 (q x, q y)
+p __cp_exception_info ()
+v __cp_pop_exception (p cp_eh_info)
+v __cp_push_exception (p value, p type, p cleanup)
+i __divsi3 (i x, i y)
+i __fixdfsi (q x)
+i __fixunsdfsi (q x)
+i __ucmpdi2 (q x, q y)
+i __udivsi3 (i x, i y)
+p __builtin_new (i size)
+p __builtin_vec_new (i size)
+p __find_first_exception_table_match (p pc)
+p __throw_type_match (p catch_type, p throw_type, p obj)
+q __divdi3 (q x, q y)
+q __fixunsdfdi (q x)
+q __fixunssfdi (i x)
+q __fixunsxfdi ()               ; TODO
+q __moddi3 (q x, q y)
+q __muldi3 (q x, q y)
+q __udivdi3 (q x, q y)
+q __umoddi3 (q x, q y)
+v __bb_init_func (p blocks)
+v __builtin_delete (p ptr)
+v __builtin_vec_delete (p ptr)
+v __probe (i n)
+v __pure_virtual ()
+v __register_exceptions (p table)
+v __throw ()
+v __uncatch_exception ()
+v __unwind_function (p ptr)
+
+G ENV
+T API
+p getenv (s name)
+i putenv (s string)
+i _path (p dst, s fname)
+v _searchenv (s name, s var, p path)
+
+G RTTI
+T INT
+v before__C9type_infoRC9type_info ()     ; TODO type_info::before
+v name__C9type_info ()                   ; TODO type_info::name
+p __dynamic_cast (p from, p to, i require_public, p address, p sub, p subptr)
+v __eq__C9type_infoRC9type_info ()       ; TODO type_info::operator==
+i __is_pointer__FPv (p p)
+v __ne__C9type_infoRC9type_info ()       ; TODO type_info::operator!=
+v __rtti_array (p addr, s name)
+v __rtti_attr (p addr, s name, i attrval, p ti)
+v __rtti_class (p addr, s name, p bl, i bn)
+v __rtti_func (p addr, s name)
+v __rtti_ptmd (p addr, s name)
+v __rtti_ptmf (p addr, s name)
+v __rtti_ptr (p addr, s name, p ti)
+v __rtti_si (p addr, s name, p ti)
+v __rtti_user (p addr, s name)
+v __throw_bad_cast ()
+v __throw_bad_typeid ()
+p __throw_type_match_rtti (p catch_type_r, p throw_type_r, p objptr)
+p __tfb ()
+p __tfc ()
+p __tfd ()
+p __tff ()
+p __tfi ()
+p __tfl ()
+p __tfr ()
+p __tfs ()
+p __tfv ()
+p __tfw ()
+p __tfx ()
+p __tfUc ()
+p __tfUi ()
+p __tfUl ()
+p __tfUs ()
+p __tfUx ()
+
+G OTHER
+T API
+i abs (i x)
+p bsearch (p key, p base, i num, i width, p compare)
+v div (i num, i den)            ; TODO
+v emx_revision (p name, i argc, p argv, p queuename, p retstr)
+i ffs (i x)
+i fpathconf (i handle, i name)
+i getopt (i argc, p argv, p opt_str)
+i getpagesize ()
+i labs (i x)
+v longjmp (p jmpbuf, i n)
+i pathconf (s path, i name)
+i ptrace (i request, i pid, i addr, i data)
+v qsort (p base, i num, i width, p compare)
+i rand ()
+i setjmp (p jmpbuf)
+v siglongjmp (p jmpbuf, i n)
+i sigsetjmp (p jmpbuf, i savemask)
+v srand (i seed)
+v swab (p src, p dst, i size)
+i sysconf (i name)
+i ulimit (i request)
+i uname (p name)
+i _core (i handle)
+v _envargs (p argcp, p argvp, s name)
+p _errno ()
+i _execname (p buffer, i size)
+i _filesys (p drive, p name, i size)
+p _getvol (i drive)
+i _int86 (i int_num, p inp_regs, p out_regs)
+v _lldiv (q num, q den)         ; TODO
+p _memaccess (i first, i last, i flag)
+i _portaccess (i first, i last)
+v _profil (p buff, i bufsiz, i offset, i scale)
+i _read_kbd (i echo, i wait, i sig)
+v _response (p argcp, p argvp)
+v _scrsize (p dst)
+i _setsyserrno (i code)
+p _splitargs (p string, p count)
+i _swchar ()
+i _syserrno ()
+i _uflags (i mask, i new_flags)
+v _uldiv (i num, i den)         ; TODO
+v _ulldiv (q num, q den)        ; TODO
+
+; Ignore the following exports (for emxtsf's -w1 option)
+I daylight
+I environ
+I ldiv()                ; identical to div()
+I nothrow
+I optarg
+I opterr
+I optind
+I optmode
+I optopt
+I optswchar
+I sys_errlist
+I sys_nerr
+I timezone
+I tzname
+I _HUGE_VAL
+I _LHUGE_VAL
+I _ctype
+I _emx_vcmp
+I _emx_env
+I _emx_rev
+I _emx_vprt
+I _files
+I _fmode_bin
+I _input()              ; TODO
+I _lookahead
+I _mb_cur_max
+I _nfiles
+I _nls_tolower_tab
+I _nls_toupper_tab
+I _nls_init_flag
+I _org_environ
+I _os2_bad
+I _osminor
+I _osmajor
+I _osmode
+I _output()             ; TODO
+I _pipe_size
+I _rmutex_fork()        ; TODO
+I _streamv
+I _tzset_flag
+I _vt$9bad_alloc        ; bad_alloc virtual table
+I _vt$13bad_exception   ; bad_exception virtual table
+I _vt$9exception        ; exception virtual table
+I _$_9bad_alloc         ; TODO bad_alloc::~bad_alloc()
+I __dummy
+I __eh_pc
+I __new_handler
+I __ti9exception        ; exception type_info node
Index: trunk/src/emx/src/lib/cdll/emxlibc2.def
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibc2.def	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibc2.def	(revision 18)
@@ -0,0 +1,45 @@
+;
+; emxlibc2.def
+;
+; These symbols are exported by emxlibc.dll but the import libraries
+; import them from emxio.dll or omit them entirely.  For linking, this
+; file is appended to emxlibc.def.
+;
+  mkdir_08e                     @731 NONAME ; obsolete, keep for compatibility
+  _dos_init                     @810 NONAME ; defined in emx2.a
+  _dos_syscall                  @811 NONAME ; defined in emx2.a
+  _entry1_08e                   @812 NONAME ; obsolete, keep for compatibility
+  _ctor_ptr                     @813 NONAME ; obsolete, keep for compatibility
+  _dtor_ptr                     @814 NONAME ; obsolete, keep for compatibility
+  _DLL_InitTerm_08f             @817 NONAME ; obsolete, keep for compatibility
+                                            ; (statically linked by import lib)
+  _CRT_init_08f                 @818 NONAME ; obsolete, keep for compatibility
+
+;
+; These functions are imported from emxio.dll now
+;
+  _inp8                         @1100 NONAME
+  _inp16                        @1101 NONAME
+  _inp32                        @1102 NONAME
+  _inps8                        @1103 NONAME
+  _outp8                        @1106 NONAME
+  _outp16                       @1107 NONAME
+  _outp32                       @1108 NONAME
+  _outps8                       @1109 NONAME
+  _outpt                        @1110 NONAME
+  _inps16                       @1112 NONAME
+  _inps32                       @1113 NONAME
+  _outps16                      @1114 NONAME
+  _outps32                      @1115 NONAME
+  _wait01                       @1116 NONAME
+  _wait10                       @1117 NONAME
+
+  _os2_emxio                    @1105 NONAME ; obsolete, keep for compatibility
+
+; __builtin_vec_delete          @1305 NONAME ; obsolete, never used?
+; __builtin_vec_new             @1306 NONAME ; obsolete, never used?
+  __main_08f                    @1313 NONAME ; obsolete, keep for compatibility
+; __set_new_handler             @1318 NONAME ; obsolete, never used?
+  __main_08h                    @1323 NONAME ; obsolete, keep for compatibility
+
+  __unwind                      @1457 NONAME ; obsolete, keep for compatibility
Index: trunk/src/emx/src/lib/cdll/emxlibc3.def
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibc3.def	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibc3.def	(revision 18)
@@ -0,0 +1,7 @@
+;
+; emxlibc3.def
+;
+; These symbols are exported by emxlibcm.dll and emxlibcs.dll but the
+; import libraries omit them entirely.  For linking, this file is appended
+; to emxlibc.def.
+;
Index: trunk/src/emx/src/lib/cdll/emxlibcm.sed
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibcm.sed	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibcm.sed	(revision 18)
@@ -0,0 +1,3 @@
+s/emxlibc/emxlibcm/
+s/EMXLIBC/EMXLIBCM/
+/For single-thread library/d
Index: trunk/src/emx/src/lib/cdll/emxlibcm.tsf
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibcm.tsf	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibcm.tsf	(revision 18)
@@ -0,0 +1,5 @@
+;
+; emxlibcm.tsf
+;
+MODNAME=\emx\dll\emxlibcm.dll
+MAJOR=249
Index: trunk/src/emx/src/lib/cdll/emxlibcm.tss
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibcm.tss	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibcm.tss	(revision 18)
@@ -0,0 +1,13 @@
+;
+; emxlibcm.tss
+;
+G PROCESS
+T API
+i _beginthread (p thread_function, p stack, i stack_size, p arg_list)
+v _endthread ()
+p _threadstore ()
+
+T INT
+p _thread ()
+
+I _errno_fun
Index: trunk/src/emx/src/lib/cdll/emxlibcs.sed
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibcs.sed	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibcs.sed	(revision 18)
@@ -0,0 +1,3 @@
+s/emxlibc/emxlibcs/
+s/EMXLIBC/EMXLIBCS/
+/For multithread library/d
Index: trunk/src/emx/src/lib/cdll/emxlibcs.tsf
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibcs.tsf	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibcs.tsf	(revision 18)
@@ -0,0 +1,5 @@
+;
+; emxlibcs.tsf
+;
+MODNAME=\emx\dll\emxlibcs.dll
+MAJOR=248
Index: trunk/src/emx/src/lib/cdll/emxlibcs.tss
===================================================================
--- trunk/src/emx/src/lib/cdll/emxlibcs.tss	(revision 18)
+++ trunk/src/emx/src/lib/cdll/emxlibcs.tss	(revision 18)
@@ -0,0 +1,4 @@
+;
+; emxlibcs.tss
+;
+I errno
Index: trunk/src/emx/src/lib/cdll/iodummy.s
===================================================================
--- trunk/src/emx/src/lib/cdll/iodummy.s	(revision 18)
+++ trunk/src/emx/src/lib/cdll/iodummy.s	(revision 18)
@@ -0,0 +1,39 @@
+/ iodummy.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+        .globl  __inp8
+        .globl  __inp16
+        .globl  __inp32
+        .globl  __inps8
+        .globl  __inps16
+        .globl  __inps32
+        .globl  __os2_emxio
+        .globl  __outp8
+        .globl  __outp16
+        .globl  __outp32
+        .globl  __outps8
+        .globl  __outps16
+        .globl  __outps32
+        .globl  __outpt
+        .globl  __wait01
+        .globl  __wait10
+
+        .text
+
+__inp8:
+__inp16:
+__inp32:
+__inps8:
+__inps16:
+__inps32:
+__os2_emxio:
+__outp8:
+__outp16:
+__outp32:
+__outps8:
+__outps16:
+__outps32:
+__outpt:
+__wait01:
+__wait10:
+        xorl    %eax, %eax
+        ret
Index: trunk/src/emx/src/lib/cdll/makefile
===================================================================
--- trunk/src/emx/src/lib/cdll/makefile	(revision 18)
+++ trunk/src/emx/src/lib/cdll/makefile	(revision 18)
@@ -0,0 +1,147 @@
+#
+# /emx/src/lib/cdll/makefile
+#
+# Build libraries: c_import
+# Build DLLs:      liblibcm.dll, emxlibcs.dll, emxlibc.dll
+#
+
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+.SOURCE.s: ..
+
+.PHONY: clean default dll-all dll-mt dll-st dll-fwd dll-fwd2 \
+        import import-st import-mt trace trace-mt trace-st trace-t
+
+DLL=\emx\dll\ #
+
+TARGET_DLL=$(DLL)$(DLLNAME).dll
+IMPORT_LIB=$(L)$(DIRNAME)\c_import
+
+ASMCMD = $(GCC) -DOMF -Zomf -c -x assembler-with-cpp
+CCCMD = $(GCC) -DEMX -Zomf -c
+
+.c.obj:
+	$(CCCMD) $<
+
+.s.obj:
+	$(ASMCMD) $<
+
+default: dll-all import-all
+
+dll-all: dll-mt dll-st dll-fwd
+
+dll-mt .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile $(PASSDOWN) DIRNAME=mt DLLNAME=emxlibcm dll
+
+dll-st .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile $(PASSDOWN) DIRNAME=st DLLNAME=emxlibcs dll
+
+dll-fwd .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile $(PASSDOWN) DIRNAME=dummy DLLNAME=dummy dll-fwd2
+
+dll-fwd2: $(DLL)emxlibc.dll
+
+dll: $(TARGET_DLL)
+
+import-all: import-mt import-st
+
+import-mt:
+	$(MAKE) DIRNAME=mt DLLNAME=emxlibcm import
+
+import-st:
+	$(MAKE) DIRNAME=st DLLNAME=emxlibcs import
+
+import: $(IMPORT_LIB).lib $(IMPORT_LIB).a
+
+trace: trace-st trace-mt
+
+trace-mt:
+	$(MAKE) DLLNAME=emxlibcm trace-t
+
+trace-st:
+	$(MAKE) DLLNAME=emxlibcs trace-t
+
+trace-t: $(MAP)$(DLLNAME).tdf
+
+clean:
+	-del $(CPU)\*.o $(DELOPT)
+	-del $(CPU)\*.obj $(DELOPT)
+	-del $(CPU)tmp.def $(DELOPT)
+	-del tmp.def $(DELOPT)
+	-del tmp.tsf $(DELOPT)
+	-del tmp.tss $(DELOPT)
+	-del trc00??.tff $(DELOPT)
+
+#
+# Create C runtime DLL
+#
+DLL_OBJS = $(L)dll0.obj revision.obj old_eh.obj old_io.obj old_nls.obj
+DLL_LIBS = $(L)gcc.lib $(L)$(DIRNAME)\c_dllrt.lib $(L)$(DIRNAME)\c.lib \
+           $(L)$(DIRNAME)\emx.lib $(L)emx2.lib $(L)os2.lib $(L)end.lib
+
+$(TARGET_DLL): $(DLL_OBJS) $(DLL_LIBS) \
+    ../emxlibc.def ../emxlibc3.def ../$(DLLNAME).sed
+	sed -f ../$(DLLNAME).sed ../emxlibc.def ../emxlibc3.def >tmp.def
+	link386 /nologo /noi /nod $(DLL_OBJS), $(DLLNAME).dll, \
+		$(MAP)$(DLLNAME) /map, $(DLL_LIBS), tmp;
+	del tmp.def
+	-emxload -qw
+	copy $(DLLNAME).dll $(TARGET_DLL)
+	del $(DLLNAME).dll
+
+revision.obj: revision.c
+old_io.obj: old_io.c $(I)stdlib.h
+old_nls.obj: old_io.c
+
+#
+# Create import libraries
+#
+$(IMPORT_LIB).a: $(IMPORT_LIB).lib
+	emximp -q -o $(IMPORT_LIB).a $(IMPORT_LIB).lib
+
+$(IMPORT_LIB).lib: emxlibc.def $(DLLNAME).sed emxio.def
+	sed -f $(DLLNAME).sed emxlibc.def >tmp.def
+	emximp -o $(IMPORT_LIB).lib tmp.def emxio.def
+	del tmp.def
+
+#
+# Create forwarder emxlibc.dll -> emxlibcm.dll
+#
+FWD_OBJS = $(L)dll0.obj revision.obj
+FWD_LIBS = $(L)c_static.lib $(L)mt\c_import.lib $(L)emx2.lib $(L)end.lib
+OLD_OBJS = oldcrt1.obj oldcrt3.obj oldcrtin.obj oldctor.obj olddllin.obj \
+           oldmain.obj oldmkdir.obj oldunwin.obj iodummy.obj
+
+$(DLL)emxlibc.dll: ../emxlibc.def ../emxlibc2.def ../emxlibc.sed \
+		$(FWD_LIBS) $(FWD_OBJS) $(OLD_OBJS)
+	sed -f ../emxlibc.sed ../emxlibc.def ../emxlibc2.def >tmp.def
+	link386 /nologo /noi /nod $(FWD_OBJS) $(OLD_OBJS), \
+		emxlibc.dll, nul, $(FWD_LIBS), tmp; | sed /L4085/d
+	del tmp.def
+	-emxload -qw
+	copy emxlibc.dll $(DLL)emxlibc.dll
+	del emxlibc.dll
+
+iodummy.obj: iodummy.s
+oldcrt1.obj: oldcrt1.s
+oldcrt3.obj: oldcrt3.s
+oldcrtin.obj: oldcrtin.c
+oldctor.obj: oldctor.c
+olddllin.obj: olddllin.c
+oldmain.obj: oldmain.c $(I)stdlib.h
+oldmkdir.obj: oldmkdir.c $(I)stdlib.h
+
+oldunwin.obj: ../oldunwin.s ../../emx_386/syscalls.h $(ASM386H)
+	$(ASMCMD) -I../../emx_386 ../oldunwin.s
+
+#
+# Create trace files (requires trcust.exe of os2pdp.zip)
+#
+$(MAP)$(DLLNAME).tdf: $(MAP)$(DLLNAME).map emxlibc.def \
+		emxlibc.tss $(DLLNAME).tss emxlibc.tsf $(DLLNAME).tsf
+	copy $(DLLNAME).tsf+emxlibc.tsf tmp.tsf
+	copy emxlibc.tss+$(DLLNAME).tss tmp.tss
+	emxtsf -d $(DLLNAME) -w1 tmp.tss $(MAP)$(DLLNAME).map emxlibc.def >>tmp.tsf
+	trcust tmp.tsf $(MAP)$(DLLNAME).tdf /m=$(MAP)$(DLLNAME).map
Index: trunk/src/emx/src/lib/cdll/old_eh.c
===================================================================
--- trunk/src/emx/src/lib/cdll/old_eh.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/old_eh.c	(revision 18)
@@ -0,0 +1,266 @@
+/* old_eh.c
+   Extracted from libgcc2.c and modified by Eberhard Mattes, Jul 1995 */
+
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+
+#include <stdlib.h>
+
+typedef struct {
+  void *start;
+  void *end;
+  void *exception_handler;
+} exception_table;
+
+struct exception_table_node {
+  exception_table *table;
+  void *start;
+  void *end;
+  struct exception_table_node *next;
+};
+
+static int except_table_pos;
+static void *except_pc;
+static struct exception_table_node *exception_table_list;
+
+static exception_table *
+find_exception_table (pc)
+     void* pc;
+{
+  register struct exception_table_node *table = exception_table_list;
+  for ( ; table != 0; table = table->next)
+    {
+      if (table->start <= pc && table->end > pc)
+	return table->table;
+    }
+  return 0;
+}
+
+/* this routine takes a pc, and the address of the exception handler associated
+   with the closest exception table handler entry associated with that PC,
+   or 0 if there are no table entries the PC fits in.  The algorithm works
+   something like this:
+
+    while(current_entry exists) {
+        if(current_entry.start < pc )
+            current_entry = next_entry;
+        else {
+            if(prev_entry.start <= pc && prev_entry.end > pc) {
+                save pointer to prev_entry;
+                return prev_entry.exception_handler;
+             }
+            else return 0;
+         }
+     }
+    return 0;
+
+   Assuming a correctly sorted table (ascending order) this routine should
+   return the tightest match...
+
+   In the advent of a tie, we have to give the last entry, as it represents
+   an inner block.
+ */
+
+
+void *
+__find_first_exception_table_match(pc)
+void *pc;
+{
+  exception_table *table = find_exception_table (pc);
+  int pos = 0;
+  int best = 0;
+  if (table == 0)
+    return (void*)0;
+#if 0
+  printf("find_first_exception_table_match(): pc = %x!\n",pc);
+#endif
+
+  except_pc = pc;
+
+#if 0
+  /* We can't do this yet, as we don't know that the table is sorted.  */
+  do {
+    ++pos;
+    if (table[pos].start > except_pc)
+      /* found the first table[pos].start > except_pc, so the previous
+	 entry better be the one we want! */
+      break;
+  } while(table[pos].exception_handler != (void*)-1);
+
+  --pos;
+  if (table[pos].start <= except_pc && table[pos].end > except_pc)
+    {
+      except_table_pos = pos;
+#if 0
+      printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
+#endif
+      return table[pos].exception_handler;
+    }
+#else
+  while (table[++pos].exception_handler != (void*)-1) {
+    if (table[pos].start <= except_pc && table[pos].end > except_pc)
+      {
+	/* This can apply.  Make sure it is better or as good as the previous
+	   best.  */
+	/* The best one ends first. */
+	if (best == 0 || (table[pos].end <= table[best].end
+			  /* The best one starts last.  */
+			  && table[pos].start >= table[best].start))
+	  best = pos;
+      }
+  }
+  if (best != 0)
+    return table[best].exception_handler;
+#endif
+
+#if 0
+  printf("find_first_eh_table_match(): else: returning NULL!\n");
+#endif
+  return (void*)0;
+}
+
+#ifndef EMX     /* Also defined in gcc/eh.c */
+void *
+__throw_type_match (void *catch_type, void *throw_type, void* obj)
+{
+#if 0
+ printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
+	catch_type, throw_type);
+#endif
+ if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
+   return obj;
+ return 0;
+}
+#endif
+
+void
+__register_exceptions (exception_table *table)
+{
+  struct exception_table_node *node;
+  exception_table *range = table + 1;
+
+  if (range->start == (void*)-1)
+    return;
+
+  node = (struct exception_table_node*)
+    malloc (sizeof (struct exception_table_node));
+  node->table = table;
+
+  /* This look can be optimized away either if the table
+     is sorted, or if we pass in extra parameters. */
+  node->start = range->start;
+  node->end = range->end;
+  for (range++ ; range->start != (void*)(-1); range++)
+    {
+      if (range->start < node->start)
+	node->start = range->start;
+      if (range->end > node->end)
+	node->end = range->end;
+    }
+
+  node->next = exception_table_list;
+  exception_table_list = node;
+}
+
+#if #machine(i386)
+void
+__unwind_function(void *ptr)
+{
+  asm("movl 8(%esp),%ecx");
+  /* Undo current frame */
+  asm("movl %ebp,%esp");
+  asm("popl %ebp");
+  /* like ret, but stay here */
+  asm("addl $4,%esp");
+  
+  /* Now, undo previous frame. */
+  /* This is a test routine, as we have to dynamically probe to find out
+     what to pop for certain, this is just a guess. */
+  asm("leal -16(%ebp),%esp");
+  asm("pop %ebx");
+  asm("pop %esi");
+  asm("pop %edi");
+  asm("movl %ebp,%esp");
+  asm("popl %ebp");
+
+  asm("movl %ecx,0(%esp)");
+  asm("ret");
+}
+#elif #machine(rs6000)
+__unwind_function(void *ptr)
+{
+  asm("mr 31,1");
+  asm("l 1,0(1)");
+  asm("l 31,-4(1)");
+  asm("# br");
+
+  asm("mr 31,1");
+  asm("l 1,0(1)");
+  /* use 31 as a scratch register to restore the link register. */
+  asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
+  asm("l 31,-4(1)");
+  asm("# br");
+  asm("mtctr 3;bctr # b 3");
+}
+#elif #machine(powerpc)
+__unwind_function(void *ptr)
+{
+  asm("mr 31,1");
+  asm("lwz 1,0(1)");
+  asm("lwz 31,-4(1)");
+  asm("# br");
+
+  asm("mr 31,1");
+  asm("lwz 1,0(1)");
+  /* use 31 as a scratch register to restore the link register. */
+  asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
+  asm("lwz 31,-4(1)");
+  asm("# br");
+  asm("mtctr 3;bctr # b 3");
+}
+#elif #machine(vax)
+__unwind_function(void *ptr)
+{
+  __label__ return_again;
+
+  /* Replace our frame's return address with the label below.
+     During execution, we will first return here instead of to
+     caller, then second return takes caller's frame off the stack.
+     Two returns matches two actual calls, so is less likely to
+     confuse debuggers.  `16' corresponds to RETURN_ADDRESS_OFFSET.  */
+  __asm ("movl %0,16(fp)" : : "p" (&& return_again));
+  return;
+
+ return_again:
+  return;
+}
+#else
+__unwind_function(void *ptr)
+{
+  abort ();
+}
+#endif /* powerpc */
Index: trunk/src/emx/src/lib/cdll/old_io.c
===================================================================
--- trunk/src/emx/src/lib/cdll/old_io.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/old_io.c	(revision 18)
@@ -0,0 +1,18 @@
+/* old_io.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdio.h>
+
+typedef long fpos_t_09b;
+
+int fgetpos_09b (FILE *stream, fpos_t_09b *pos)
+{
+  if ((*pos = ftell (stream)) == (long)EOF)
+    return EOF;
+  else
+    return 0;
+}
+
+int fsetpos_09b (FILE *stream, const fpos_t_09b *pos)
+{
+  return fseek (stream, *pos, SEEK_SET);
+}
Index: trunk/src/emx/src/lib/cdll/old_nls.c
===================================================================
--- trunk/src/emx/src/lib/cdll/old_nls.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/old_nls.c	(revision 18)
@@ -0,0 +1,3 @@
+/* old_nls.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+int _nls_init_flag = 1;
Index: trunk/src/emx/src/lib/cdll/oldcrt1.s
===================================================================
--- trunk/src/emx/src/lib/cdll/oldcrt1.s	(revision 18)
+++ trunk/src/emx/src/lib/cdll/oldcrt1.s	(revision 18)
@@ -0,0 +1,17 @@
+/ oldcrt1.s (emx+gcc) -- Copyright (c) 1990-1994 by Eberhard Mattes
+
+        .globl  __entry1_08e
+
+        .text
+
+__entry1_08e:
+        popl    L_ret
+        cld
+        call    __entry1
+        call    __entry2
+        call    __startup
+        jmp     *L_ret
+
+        .data
+
+L_ret:  .long   0
Index: trunk/src/emx/src/lib/cdll/oldcrt3.s
===================================================================
--- trunk/src/emx/src/lib/cdll/oldcrt3.s	(revision 18)
+++ trunk/src/emx/src/lib/cdll/oldcrt3.s	(revision 18)
@@ -0,0 +1,10 @@
+/ oldcrt3.s (emx+gcc) -- Copyright (c) 1990-1994 by Eberhard Mattes
+
+/ Keep these variables for compatibility with old applications
+        .globl  __ctor_ptr
+        .globl  __dtor_ptr
+
+        .data
+
+__ctor_ptr:     .long   0
+__dtor_ptr:     .long   0
Index: trunk/src/emx/src/lib/cdll/oldcrtin.c
===================================================================
--- trunk/src/emx/src/lib/cdll/oldcrtin.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/oldcrtin.c	(revision 18)
@@ -0,0 +1,18 @@
+/* oldcrtin.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+extern void _entry2 (void);
+extern void _startup (void);
+extern void __main (void);
+
+extern int __CTOR_LIST__, __DTOR_LIST__;
+extern int *_ctor_ptr, *_dtor_ptr;
+
+int _CRT_init_08f (void)
+{
+  _ctor_ptr = &__CTOR_LIST__;
+  _dtor_ptr = &__DTOR_LIST__;
+  _entry2 ();
+  _startup ();
+  __main ();
+  return 0;                     /* Success */
+}
Index: trunk/src/emx/src/lib/cdll/oldctor.c
===================================================================
--- trunk/src/emx/src/lib/cdll/oldctor.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/oldctor.c	(revision 18)
@@ -0,0 +1,15 @@
+/* oldctor.c (emx+gcc) -- Copyright (c) 1993-1994 by Eberhard Mattes */
+
+extern int __CTOR_LIST__;
+extern void __ctordtorInit1 (int *ptr);
+
+void __ctordtorInit (void)
+{
+  static int done;
+
+  if (!done)
+    {
+      done = 1;
+      __ctordtorInit1 (&__CTOR_LIST__);
+    }
+}
Index: trunk/src/emx/src/lib/cdll/olddllin.c
===================================================================
--- trunk/src/emx/src/lib/cdll/olddllin.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/olddllin.c	(revision 18)
@@ -0,0 +1,6 @@
+/* olddllin.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+unsigned long _DLL_InitTerm_08f (unsigned long mod_handle, unsigned long flag)
+{
+  return 1;
+}
Index: trunk/src/emx/src/lib/cdll/oldmain.c
===================================================================
--- trunk/src/emx/src/lib/cdll/oldmain.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/oldmain.c	(revision 18)
@@ -0,0 +1,46 @@
+/* oldmain.c (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes */
+/*                        Copyright (c) 1992-1994 by Kai Uwe Rommel */
+
+#include <stdlib.h>
+
+extern void __ctordtorInit (void);
+extern void __ctordtorTerm (void);
+
+/* Keep old code in the DLL for compatibility with old executables. */
+
+#define MAX_MODULES     64
+
+extern void __ctordtorInit1 (int *ptr);
+extern void __ctordtorTerm1 (int *ptr);
+extern int *_ctor_ptr;
+extern int *_dtor_ptr;
+
+static int *dtor_tab[MAX_MODULES];
+static int dtor_count = 0;
+
+static void call_dtor_lists (void)
+{
+  while (dtor_count > 0)
+    {
+      --dtor_count;
+      __ctordtorTerm1 (dtor_tab[dtor_count]);
+    }
+}
+
+void __main_08f (void)
+{
+  int *tmp;
+
+  tmp = _dtor_ptr;              /* Maybe a ctor calls DosLoadModule... */
+  __ctordtorInit1 (_ctor_ptr);
+  if (dtor_count == 0)
+    atexit (call_dtor_lists);
+  if (dtor_count < MAX_MODULES)
+    dtor_tab[dtor_count++] = tmp;
+}
+
+void __main_08h (void)
+{
+  __ctordtorInit ();
+  atexit (__ctordtorTerm);
+}
Index: trunk/src/emx/src/lib/cdll/oldmkdir.c
===================================================================
--- trunk/src/emx/src/lib/cdll/oldmkdir.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/oldmkdir.c	(revision 18)
@@ -0,0 +1,8 @@
+/* oldmkdir.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+int mkdir_08e (const char *name)
+{
+  return _mkdir (name, 0777);
+}
Index: trunk/src/emx/src/lib/cdll/oldunwin.s
===================================================================
--- trunk/src/emx/src/lib/cdll/oldunwin.s	(revision 18)
+++ trunk/src/emx/src/lib/cdll/oldunwin.s	(revision 18)
@@ -0,0 +1,15 @@
+/ oldunwin.s (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___unwind
+
+/ void __unwind (void)
+
+        ALIGN
+
+___unwind:
+        movb    $0x10, %al              /* unwind */
+        SYSCALL (0x7f)
+        EPILOGUE(__unwind)
Index: trunk/src/emx/src/lib/cdll/revision.c
===================================================================
--- trunk/src/emx/src/lib/cdll/revision.c	(revision 18)
+++ trunk/src/emx/src/lib/cdll/revision.c	(revision 18)
@@ -0,0 +1,17 @@
+/* revision.c (emx+gcc) -- Copyright (c) 1992-2001 by Eberhard Mattes */
+
+#include <string.h>
+#define INCL_REXXSAA
+#include <os2emx.h>
+
+static char const revision[] = "64";
+
+ULONG emx_revision (PCSZ name, LONG argc, const RXSTRING *argv,
+                    PCSZ queuename, PRXSTRING retstr)
+{
+  if (argc != 0)
+    return 1;
+  strcpy (retstr->strptr, revision);
+  retstr->strlength = strlen (revision);
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/386/biaddbb.s
===================================================================
--- trunk/src/emx/src/lib/conv/386/biaddbb.s	(revision 18)
+++ trunk/src/emx/src/lib/conv/386/biaddbb.s	(revision 18)
@@ -0,0 +1,115 @@
+/ biaddbb.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  __bi_add_bb
+
+#define n       0
+#define v       4
+
+/ int _bi_add_bb (_bi_bigint *dst, int dst_words,
+/                 const _bi_bigint *src1, const _bi_bigint *src2)
+
+#define dst             8(%ebp)
+#define dst_words       12(%ebp)
+#define src1            16(%ebp)
+#define src2            20(%ebp)
+
+        .text
+__bi_add_bb:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        movl    src1, %ebx
+        movl    src2, %esi
+        movl    n(%ebx), %ecx           /* ECX := src1->n */
+        movl    n(%esi), %edx           /* EDX := src2->n */
+        cmpl    %edx, %ecx              /* src1->n < src2->n ? */
+        jb      Lsetup                  /* yes -> skip */
+        xchgl   %ebx, %esi
+        xchgl   %edx, %ecx
+        ALIGN
+
+/* The longer number must fit in dst_words words. */
+
+Lsetup: cmpl    dst_words, %edx         /* ESI->n > dst_words? */
+        ja      Lcarry                  /* yes -> return 1 */
+        subl    %ecx, %edx
+
+/* Now, EBX is the shorter one of src1 and src2, ECX = EBX->n.  ESI is
+   the other one, EDX = ESI->n - EBX->n. */
+
+        movl    dst, %edi
+        movl    v(%ebx), %ebx           /* EBX := EBX->v */
+        movl    v(%esi), %esi           /* ESI := ESI->v */
+        movl    v(%edi), %edi           /* EDI := dst->v */
+        test    %ecx, %ecx              /* Clears carry! */
+        jz      Lend1                   /* ecx = 0 -> skip first loop */
+
+/* This loop adds words common to both src1 and src2. */
+
+        ALIGN
+L1:     movl    (%ebx), %eax
+        leal    4(%ebx), %ebx
+        adcl    (%esi), %eax
+        leal    4(%esi), %esi
+        movl    %eax, (%edi)
+        leal    4(%edi), %edi
+        dec     %ecx
+        jnz     L1
+
+/* Process the remaining words of the longer one. */
+
+        ALIGN
+Lend1:  decl    %edx                    /* EDX = 0? (keep carry!) */
+        js      Lend2                   /* yes -> skip second loop */
+        incl    %edx
+        ALIGN
+L2:     movl    (%esi), %eax
+        leal    4(%esi), %esi
+        adc     $0, %eax
+        movl    %eax, (%edi)
+        leal    4(%edi), %edi
+        decl    %edx
+        jnz     L2
+        ALIGN
+Lend2:  jnc     Ldone
+
+/* Carry from the most significant word.  Check dst_words. */
+
+        movl    %edi, %edx
+        movl    dst, %ebx
+        movl    v(%ebx), %eax
+        subl    %eax, %edx
+        shrl    $2, %edx
+        cmpl    dst_words, %edx
+        jae     Lcarry
+        movl    $1, (%edi)
+        incl    %edx
+        movl    %edx, n(%ebx)
+        xorl    %eax, %eax
+        jmp     Lreturn
+
+        ALIGN
+Lcarry: movl    $1, %eax
+        jmp     Lreturn
+
+/* No carry from most significant word.  Set dst->n. */
+
+        ALIGN
+Ldone:  movl    dst, %ebx
+        movl    v(%ebx), %eax
+        subl    %eax, %edi
+        shrl    $2, %edi
+        movl    %edi, n(%ebx)
+        xorl    %eax, %eax
+        ALIGN
+Lreturn:
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        leave
+        EPILOGUE(_bi_add_bb)
Index: trunk/src/emx/src/lib/conv/386/bidivbw.s
===================================================================
--- trunk/src/emx/src/lib/conv/386/bidivbw.s	(revision 18)
+++ trunk/src/emx/src/lib/conv/386/bidivbw.s	(revision 18)
@@ -0,0 +1,84 @@
+/ bidivbw.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  __bi_div_rem_bw
+
+#define n       0
+#define v       4
+
+/ int _bi_div_rem_bw (_bi_bigint *quot, int quot_words, _bi_word *rem,
+/                     const _bi_bigint *num, _bi_word den);
+
+#define quot            8(%ebp)
+#define quot_words      12(%ebp)
+#define rem             16(%ebp)
+#define num             20(%ebp)
+#define den             24(%ebp)
+
+        .text
+__bi_div_rem_bw:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        movl    quot, %edi              /* EDI := quot */
+        cmpl    $0, den                 /* Division by zero? */
+        je      Loverflow               /* Yes => return 1 */
+        movl    num, %esi               /* ESI := num */
+        movl    n(%esi), %ecx           /* ECX := num->n */
+        cmpl    quot_words, %ecx        /* num->n > quot_words? */
+        ja      Loverflow               /* Yes => return 1 */
+        testl   %ecx, %ecx              /* Is the numerator zero? */
+        jz      Lnum_zero               /* Yes => quotient is zero */
+
+/* See Donald Ervin Knuth, The Art of Computer Programming, Volume 2,
+   4.3.1, Exercise 16.  See also /emx/src/lib/gcc/386/ulldiv.s. */
+
+        movl    v(%esi), %esi
+        movl    v(%edi), %edi
+        leal    -4(%esi,%ecx,4), %esi   /* ESI := &num->v[num->n-1] */
+        leal    -4(%edi,%ecx,4), %edi   /* EDI := &quot->v[quot->n-1] */
+        xorl    %edx, %edx              /* r := 0 */
+        movl    den, %ebx               /* EBX := den */
+        ALIGN
+L1:     movl    (%esi), %eax
+        divl    %ebx                    /* r := (rb+num->v[j]) % den */
+        leal    -4(%esi), %esi          /* q[j] := (rb+num->v[j]) / den */
+        movl    %eax, (%edi)
+        leal    -4(%edi), %edi
+        decl    %ecx
+        jnz     L1
+
+        movl    rem, %ebx
+        movl    num, %esi
+        movl    quot, %edi
+        movl    %edx, (%ebx)            /* *rem := r */
+        movl    n(%esi), %ecx           /* ECX := num->n */
+        movl    v(%edi), %ebx
+        cmpl    $1, -4(%ebx,%ecx,4)     /* quot->v[num->n-1] != 0? */
+        sbbl    $0, %ecx                /* Yes => ECX := ECX-1 */
+        movl    %ecx, n(%edi)           /* quot->n := num->n or num->n-1 */
+        xorl    %eax, %eax
+        ALIGN
+Lreturn:
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        leave
+        EPILOGUE(_bi_div_rem_bw)
+
+        ALIGN
+Loverflow:
+        movl    $1, %eax
+        jmp     Lreturn
+
+        ALIGN
+Lnum_zero:
+        movl    rem, %ebx
+        movl    $0, (%ebx)
+        movl    $0, n(%edi)
+        xorl    %eax, %eax
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/conv/386/bidivhlp.s
===================================================================
--- trunk/src/emx/src/lib/conv/386/bidivhlp.s	(revision 18)
+++ trunk/src/emx/src/lib/conv/386/bidivhlp.s	(revision 18)
@@ -0,0 +1,153 @@
+/ bidivhlp.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  __bi_div_estimate
+        .globl  __bi_div_subtract
+        .globl  __bi_div_add_back
+
+        .text
+
+/* This function isn't exactly that time-critical, but it can be
+   written more elegantly in assembly language than in C. */
+
+/ _bi_word _bi_div_estimate (_bi_word *u, _bi_word v1, _bi_word v2)
+
+#define u               8(%ebp)
+#define v1              12(%ebp)
+#define v2              16(%ebp)
+
+        ALIGN
+__bi_div_estimate:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        pushl   %ebx
+        pushl   %edi
+        movl    u, %edi
+        movl    -4(%edi), %eax          /* EAX := u[-1] */
+        movl    0(%edi), %edx           /* EDX := u[0] */
+        cmpl    v1, %edx                /* u[0] == v1? */
+        je      Lmax                    /* Yes => use maximum quotient */
+        divl    v1
+
+/* EBX = q, EDX = r */
+
+Lcommon:movl    %edx, %ecx              /* Save ECX (r) */
+        movl    %eax, %ebx              /* Save EAX (q) */
+        mull    v2                      /* EDX:EAX := v2 * q */
+        ALIGN
+Ltest:  cmpl    %ecx, %edx
+        jb      Ldone
+        ja      Ldecr
+        cmpl    -8(%edi), %eax
+        jbe     Ldone
+        ALIGN
+Ldecr:  decl    %ebx                    /* q := q - 1 */
+        addl    v1, %ecx                /* Compute new r for new q */
+        jc      Ldone
+        subl    v2, %eax                /* EDX:EAX := v2 * q */
+        sbbl    $0, %edx
+        jmp     Ltest
+
+        ALIGN
+Ldone:  movl    %ebx, %eax
+Lreturn:popl    %edi
+        popl    %ebx
+        leave
+        EPILOGUE(_bi_div_estimate)
+
+        ALIGN
+Lmax:   movl    %edx, %ecx              /* EBX:ECX := EDX:EAX */
+        movl    %eax, %ebx
+        movl    $-1, %eax
+        mull    %ecx
+        subl    %ebx, %eax
+        sbbl    %ecx, %edx
+        movl    %eax, %edx
+        movl    $-1, %eax
+        jz      Lcommon
+        jmp     Lreturn                 /* r>=b, so the test is always false */
+
+#undef u
+#undef v1
+#undef v2
+
+/* This function is where _bi_div_bb() spends most of its time. */
+
+/ int _bi_div_subtract (_bi_word *u, const _bi_word *v, int n, _bi_word q)
+
+#define u               8(%ebp)
+#define v               12(%ebp)
+#define n               16(%ebp)
+#define q               20(%ebp)
+
+        ALIGN
+__bi_div_subtract:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        movl    u, %edi                 /* EDI := u */
+        movl    v, %esi                 /* ESI := v */
+        movl    n, %ecx                 /* ECX := n */
+        xorl    %ebx, %ebx              /* mul_carry := 0, sub_borrow := 0 */
+        ALIGN
+L1:     movl    (%esi), %eax
+        leal    4(%esi), %esi
+        mull    q
+        addl    %ebx, %eax
+        adcl    $0, %edx
+        movl    %edx, %ebx
+        subl    %eax, (%edi)
+        adcl    $0, %ebx
+        leal    4(%edi), %edi
+        decl    %ecx
+        jnz     L1
+        subl    %ebx, (%edi)
+        sbbl    %eax, %eax
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        leave
+        EPILOGUE(_bi_div_subtract)
+
+#undef u
+#undef v
+#undef n
+#undef q
+
+/* This function isn't exactly that time-critical, but it can be
+   written more elegantly in assembly language than in C. */
+
+/ int _bi_div_add_back (_bi_word *u, const _bi_word *v, int n)
+
+#define u               8(%ebp)
+#define v               12(%ebp)
+#define n               16(%ebp)
+
+        ALIGN
+__bi_div_add_back:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        pushl   %esi
+        pushl   %edi
+        movl    u, %edi                 /* EDI := u */
+        movl    v, %esi                 /* ESI := v */
+        movl    n, %ecx                 /* ECX := n */
+        incl    %ecx
+        clc
+        ALIGN
+L2:     movl    (%esi), %eax
+        leal    4(%esi), %esi
+        adcl    %eax, (%edi)
+        leal    4(%edi), %edi
+        decl    %ecx
+        jnz     L2
+        popl    %edi
+        popl    %esi
+        leave
+        EPILOGUE(_bi_div_add_back)
Index: trunk/src/emx/src/lib/conv/386/bimulbb.s
===================================================================
--- trunk/src/emx/src/lib/conv/386/bimulbb.s	(revision 18)
+++ trunk/src/emx/src/lib/conv/386/bimulbb.s	(revision 18)
@@ -0,0 +1,140 @@
+/ bimulbb.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  __bi_mul_bb
+
+#define n       0
+#define v       4
+
+/ int _bi_mul_bb (_bi_bigint *dst, int dst_words,
+/                 const _bi_bigint *src1, const _bi_bigint *src2)
+
+#define dst             8(%ebp)
+#define dst_words       12(%ebp)
+#define src1            16(%ebp)
+#define src2            20(%ebp)
+#define n1              -4(%ebp)
+#define n2              -8(%ebp)
+#define dn              -12(%ebp)
+#define v1              -16(%ebp)
+#define v2              -20(%ebp)
+#define dv              -24(%ebp)
+#define factor          -28(%ebp)
+
+        .text
+__bi_mul_bb:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        subl    $28, %esp
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        movl    dst, %edi
+        movl    src1, %esi              /* ESI := src1 */
+        movl    src2, %ebx              /* EBX := src2 */
+        movl    n(%esi), %ecx           /* ECX := src1->n */
+        movl    n(%ebx), %eax           /* EAX := src2->n */
+
+/* Set dst to zero if either src1 or src2 point to zero.  The code
+   below does not work if the word count of either factor is zero. */
+
+        testl   %ecx, %ecx              /* src1->n == 0? */
+        jz      Lzero
+        testl   %eax, %eax              /* src2->n == 0? */
+        jz      Lzero
+
+        movl    %ecx, n1                /* n1 := src1->n */
+        movl    %eax, n2                /* n2 := src2->n */
+        addl    %eax, %ecx
+        cmpl    dst_words, %ecx
+        ja      Loverflow
+
+        movl    v(%esi), %eax
+        movl    v(%ebx), %edx
+        movl    %eax, v1                /* v1 := src1->v */
+        movl    %edx, v2                /* v2 := src2->v */
+
+        movl    %ecx, dn                /* dn := src1->n + src2->n */
+        movl    v(%edi), %edi
+        xorl    %eax, %eax
+        movl    %edi, dv                /* dv := dst->v */
+        rep
+        stosl
+
+/* Outer loop, over words of src2. */
+
+        ALIGN
+L1:     movl    dv, %edi                /* EDI := &dst->v[i] */
+        movl    v1, %esi                /* ESI := &src1->v[0] */
+        movl    v2, %eax
+        movl    n1, %ecx
+        movl    (%eax), %edx
+        movl    %edx, factor            /* factor := src2->v[i] */
+        xorl    %ebx, %ebx              /* carry := 0 */
+
+/* Inner loop, over words of src1. */
+
+        ALIGN
+L2:     movl    (%esi), %eax
+        mull    factor
+        addl    $4, %esi
+        addl    %ebx, %eax
+        adcl    $0, %edx
+        addl    %eax, (%edi)
+        leal    4(%edi), %edi
+        adcl    $0, %edx
+        decl    %ecx
+        movl    %edx, %ebx
+        jnz     L2
+
+/* Handle carry (EBX). */
+
+        test    %ebx, %ebx
+        jz      Lnext
+        add     %ebx, (%edi)
+        leal    4(%edi), %edi
+
+/* Handle carry (CY). */
+
+        jnc     Lnext
+        ALIGN
+L3:     add     $1, (%edi)
+        leal    4(%edi), %edi
+        jc      L3
+
+/* End of outer loop. */
+
+        ALIGN
+Lnext:  addl    $4, v2
+        addl    $4, dv
+        decl    n2
+        jnz     L1
+
+/* Normalize product.  Note that dn is non-zero. */
+
+        movl    dst, %edi
+        movl    dn, %eax
+        movl    v(%edi), %esi
+        cmpl    $1, -4(%esi,%eax,4)
+        sbbl    $0, %eax                /* Decr EAX if dst->v[dn-1] == 0 */
+        movl    %eax, n(%edi)
+        ALIGN
+Ldone:  xorl    %eax, %eax
+        ALIGN
+Lreturn:
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        leave
+        EPILOGUE(_bi_mul_bb)
+
+        ALIGN
+Loverflow:
+        movl    $1, %eax
+        jmp     Lreturn
+
+        ALIGN
+Lzero:  movl    $0, n(%edi)
+        jmp     Ldone
Index: trunk/src/emx/src/lib/conv/386/bimulbw.s
===================================================================
--- trunk/src/emx/src/lib/conv/386/bimulbw.s	(revision 18)
+++ trunk/src/emx/src/lib/conv/386/bimulbw.s	(revision 18)
@@ -0,0 +1,83 @@
+/ bimulbw.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  __bi_mul_bw
+
+#define n       0
+#define v       4
+
+/ int _bi_mul_bw (_bi_bigint *dst, int dst_words,
+/                 const _bi_bigint *src, _bi_word factor)
+
+#define dst             8(%ebp)
+#define dst_words       12(%ebp)
+#define src             16(%ebp)
+#define factor          20(%ebp)
+
+        .text
+__bi_mul_bw:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        cmpl    $0, factor
+        je      Lzero
+        movl    src, %esi
+        movl    n(%esi), %ecx
+        cmpl    dst_words, %ecx
+        ja      Lcarry
+        testl   %ecx, %ecx
+        jz      Lzero
+        movl    dst, %edi
+        movl    %ecx, n(%edi)
+        movl    v(%edi), %edi
+        movl    v(%esi), %esi
+        xorl    %ebx, %ebx              /* EBX = carry */
+
+/* This loops processes all the words of src. */
+
+        ALIGN
+L1:     movl    (%esi), %eax
+        mull    factor
+        leal    4(%esi), %esi
+        addl    %ebx, %eax
+        adcl    $0, %edx
+        movl    %eax, (%edi)
+        movl    %edx, %ebx
+        leal    4(%edi), %edi
+        dec     %ecx
+        jnz     L1
+
+        test    %ebx, %ebx
+        jz      Ldone
+
+/* Carry from the most significant word.  Check dst_words. */
+
+        movl    dst, %edx
+        movl    n(%edx), %eax
+        cmpl    dst_words, %eax
+        jae     Lcarry
+        movl    %ebx, (%edi)
+        incl    n(%edx)
+        ALIGN
+Ldone:  xorl    %eax, %eax
+        ALIGN
+Lreturn:
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        leave
+        EPILOGUE(_bi_mul_bw)
+
+        ALIGN
+Lzero:  movl    dst, %edi
+        movl    $0, 0(%edi)
+        xorl    %eax, %eax
+        jmp     Lreturn
+
+        ALIGN
+Lcarry: movl    $1, %eax
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/conv/386/bisubmbw.s
===================================================================
--- trunk/src/emx/src/lib/conv/386/bisubmbw.s	(revision 18)
+++ trunk/src/emx/src/lib/conv/386/bisubmbw.s	(revision 18)
@@ -0,0 +1,149 @@
+/ bisubmbw.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  __bi_sub_mul_bw
+
+#define n       0
+#define v       4
+
+/ int _bi_sub_mul_bw (_bi_bigint *dst, const _bi_bigint *src, _bi_word factor)
+
+#define dst             8(%ebp)
+#define src             12(%ebp)
+#define factor          16(%ebp)
+#define dst_n_extra     -4(%ebp)
+
+        .text
+__bi_sub_mul_bw:
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        subl    $4, %esp
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        cmpl    $0, factor
+        je      Lnothing
+        movl    src, %esi
+        movl    n(%esi), %ecx
+        testl   %ecx, %ecx
+        jz      Lnothing
+        movl    dst, %edi
+        movl    n(%edi), %eax
+        subl    %ecx, %eax
+        jb      Lret_one
+        movl    %eax, dst_n_extra
+        movl    v(%edi), %edi
+        movl    v(%esi), %esi
+        xorl    %ebx, %ebx              /* EBX = mul_carry + sub_borrow */
+
+/* This loops processes all the words of src. */
+
+        ALIGN
+L1:     movl    (%esi), %eax
+        mull    factor
+        leal    4(%esi), %esi
+        addl    %ebx, %eax
+        adcl    $0, %edx
+        movl    %edx, %ebx
+        subl    %eax, (%edi)
+        adcl    $0, %ebx
+        leal    4(%edi), %edi
+        dec     %ecx
+        jnz     L1
+
+        movl    dst_n_extra, %ecx
+
+/* Process carry from the multiplication.  This needs to be done
+   only once, no loop. */
+
+        testl   %ebx, %ebx
+        jz      Lno_mul_carry
+        testl   %ecx, %ecx
+        jz      Lrestore                /* Overflow */
+        subl    %ebx, (%edi)
+        leal    4(%edi), %edi
+        sbbl    %ebx, %ebx              /* EBX non-zero iff borrow */
+        dec     %ecx
+        ALIGN
+Lno_mul_carry:
+
+/* Process borrow for the remaining words of dst. */
+
+        testl   %ebx, %ebx
+        jz      Lno_borrow
+        testl   %ecx, %ecx
+        jz      Lrestore
+        ALIGN
+L2:     subl    $1, (%edi)
+        decl    %ecx
+        leal    4(%edi), %edi
+        jnc     Lno_borrow
+        jnz     L2
+        jmp     Lrestore
+
+        ALIGN
+Lno_borrow:
+
+/* Normalize. */
+
+        movl    dst, %ebx
+        movl    n(%ebx), %ecx
+        ALIGN
+L3:     cmpl    $0, -4(%edi)
+        jnz     Ldone
+        subl    $4, %edi
+        dec     %ecx
+        jnz     L3
+        ALIGN
+Ldone:  movl    %ecx, n(%ebx)
+        xorl    %eax, %eax
+        ALIGN
+Lreturn:
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        leave
+        EPILOGUE(_bi_sub_mul_bw)
+
+/* The result would be negative.  Restore the original DST. */
+
+        ALIGN
+Lrestore:
+        movl    src, %esi
+        movl    dst, %edi
+        movl    n(%esi), %ecx
+        movl    v(%edi), %edi
+        movl    v(%esi), %esi
+        xorl    %ebx, %ebx
+        ALIGN
+L4:     movl    (%esi), %eax
+        mull    factor
+        leal    4(%esi), %esi
+        addl    %ebx, %eax
+        adcl    $0, %edx
+        movl    %edx, %ebx
+        addl    %eax, (%edi)
+        adcl    $0, %ebx
+        leal    4(%edi), %edi
+        dec     %ecx
+        jnz     L4
+
+        cmpl    $0, dst_n_extra
+        je      Lrestore_done
+        addl    %ebx, (%edi)
+        ALIGN
+Lrestore_done:
+        movl    $1, %eax
+        jmp     Lreturn
+
+        ALIGN
+Lnothing:
+        xorl    %eax, %eax
+        jmp     Lreturn
+
+        ALIGN
+Lret_one:
+        movl    $1, %eax
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/conv/386/smallcnv.s
===================================================================
--- trunk/src/emx/src/lib/conv/386/smallcnv.s	(revision 18)
+++ trunk/src/emx/src/lib/conv/386/smallcnv.s	(revision 18)
@@ -0,0 +1,7 @@
+/ smallcnv.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+        .stabs  "___atod", 11, 0, 0, 0
+        .stabs  "___small_atod", 1, 0, 0, 0
+
+        .stabs  "___dtoa", 11, 0, 0, 0
+        .stabs  "___small_dtoa", 1, 0, 0, 0
Index: trunk/src/emx/src/lib/conv/atod.c
===================================================================
--- trunk/src/emx/src/lib/conv/atod.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/atod.c	(revision 18)
@@ -0,0 +1,466 @@
+/* atod.c (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include <float.h>
+#include <locale.h>
+#include <errno.h>
+#include <assert.h>
+#include <emx/bigint.h>
+#include <emx/float.h>
+#include <emx/locale.h>
+
+#define BBITS           (LDBL_MAX_EXP + LDBL_MANT_DIG - LDBL_MAX_10_EXP \
+                         + (DECIMAL_DIG * 10)/3)
+#define BWORDS          (_BI_WORDS (BBITS) + 1)
+
+
+#define MAX1    (_BI_WORDMAX / 10)
+#define MAX2    (_BI_WORDMAX - 10 * MAX1)
+
+#define DOT     (unsigned char)_cur_lconv.decimal_point[0]
+
+const char * __atod (long double *p_result, const char *string,
+                     int min_exp, int max_exp, int bias,
+                     int mant_dig, int decimal_dig,
+                     int max_10_exp, int min_den_10_exp)
+{
+  const char *digits, *digits_end, *s, *end;
+  int e, k, i, cmp, int_digits, frac_digits, ov, pt, next, neg;
+  unsigned long long mant;
+  _bi_word w1, w2;
+  _BI_DECLARE (f, BWORDS);
+  _BI_DECLARE (t, BWORDS);      /* r, temporary */
+  _BI_DECLARE (x, BWORDS);      /* x and q */
+  _BI_DECLARE (uv, BWORDS);     /* u or v */
+  union
+  {
+    long double ld;
+    struct
+    {
+      unsigned long long mant;
+      unsigned short exp;
+    } x;
+  } z;
+
+#define INTEGER_BIT     (1ULL << (mant_dig - 1))
+
+  _BI_INIT (f);
+  _BI_INIT (t);
+  _BI_INIT (x);
+  _BI_INIT (uv);
+
+  s = string;
+  while (*s != 0 && isspace ((unsigned char)*s))
+    ++s;
+  neg = 0;
+  if (*s == '-')
+    {
+      ++s; neg = 1;
+    }
+  else if (*s == '+')
+    ++s;
+
+  if ((s[0] == 'i' || s[0] == 'I')
+      && (s[1] == 'n' || s[1] == 'N')
+      && (s[2] == 'f' || s[2] == 'F'))
+    {
+      s += 3;
+      if ((s[0] == 'i' || s[0] == 'I')
+          && (s[1] == 'n' || s[1] == 'N')
+          && (s[2] == 'i' || s[2] == 'I')
+          && (s[3] == 't' || s[3] == 'T')
+          && (s[4] == 'y' || s[4] == 'Y'))
+        s += 5;
+      *p_result = neg ? -INFINITY : INFINITY;
+      return s;
+    }
+  else if ((s[0] == 'n' || s[0] == 'N')
+           && (s[1] == 'a' || s[1] == 'A')
+           && (s[2] == 'n' || s[2] == 'N'))
+    {
+      s += 3;
+      end = s;
+      if (end[0] == '(')
+        {
+          ++end;
+          while (*end == '_' || (*end >= '0' && *end <= '9')
+                 || (*end >= 'a' && *end <= 'z')
+                 || (*end >= 'A' && *end <= 'Z'))
+            ++end;
+          if (*end == ')')
+            ++end;
+          else
+            end = s;
+        }
+      *p_result = NAN;
+      return end;
+    }
+
+  digits = s;
+  pt = 0; int_digits = frac_digits = 0;
+  while ((*s >= '0' && *s <= '9') || (*s == DOT && !pt))
+    {
+      if (*s++ == DOT)
+        pt = 1;
+      else if (pt)
+        ++frac_digits;
+      else
+        ++int_digits;
+    }
+  digits_end = s;
+
+  if (int_digits == 0 && frac_digits == 0)
+    {
+      /* Subject sequence is empty or does not have the expected
+         form. */
+
+      *p_result = 0.0;
+      return string;
+    }
+
+  /* Read exponent. */
+
+  e = 0; end = s;
+  if (*s == 'e' || *s == 'E')
+    {
+      char *exp_end, exp_neg;
+      long exp;
+      int saved_errno;
+
+      ++s; exp_neg = 0;
+      if (*s == '+')
+        ++s;
+      else if (*s == '-')
+        {
+          exp_neg = 1; ++s;
+        }
+      if (isdigit ((unsigned char)*s)) /* Note: strtol() skips whitespace! */
+        {
+          saved_errno = errno; errno = 0;
+          exp = strtol (s, &exp_end, 10);
+          if (errno == ERANGE)
+            {
+              /* If the exponent overflows, we need a *very* long
+                 mantissa to get a valid number.  Such a mantissa
+                 doesn't fit into memory. */
+
+              end = exp_end;
+              if (exp_neg)
+                goto underflow;
+              else
+                goto overflow;
+            }
+          else if (errno == 0 && exp_end != s)
+            {
+              end = exp_end;
+              e = exp_neg ? -exp : exp;
+            }
+          errno = saved_errno;
+        }
+    }
+
+  /* Adjust the exponent so that we can treat the sequence of digits
+     as integer (by ignoring the decimal point). */
+
+  e -= frac_digits;
+
+  /* Remove leading zeros to keep numbers small. */
+
+  while (digits < digits_end && (*digits == '0' || *digits == DOT))
+    ++digits;
+
+  /* Remove trailing zeros to keep numbers small. */
+
+  while (digits_end > digits
+         && (digits_end[-1] == '0' || digits_end[-1] == DOT))
+    {
+      if (digits_end[-1] != DOT)
+        ++e;
+      --digits_end;
+    }
+
+  /* Return 0.0 if the number is zero. */
+
+  if (digits == digits_end)
+    {
+      *p_result = neg ? -0.0 : 0.0;
+      return end;
+    }
+
+  /* Quick test of the exponent.  Note that the string may or may not
+     contain a decimal point. */
+
+  if (e + digits_end - digits - 2 > max_10_exp)
+    goto overflow;
+  if (e + digits_end - digits < min_den_10_exp)
+    goto underflow;
+
+  /* Build the integer. */
+
+  f.n = 0;                      /* f := 0 */
+  w1 = 0;                       /* Accumulates up to 9 digits */
+  w2 = 1;                       /* 10 ^ number_of_digits */
+  k = 0;                        /* Truncate after DECIMAL_DIG digits */
+  for (s = digits; s < digits_end; ++s)
+    if (*s != DOT)
+      {
+        if (k == decimal_dig)
+          ++e;
+        else
+          {
+            /* We have to check both W1 and W2 for overflow. */
+
+            if (w2 >= MAX1 || (w1 >= MAX1 && (w1 > MAX1 || *s - '0' > MAX2)))
+              {
+                /* Overflow of the accumulator.  Append the digits
+                   from W1 to F. */
+
+                ov = _bi_mul_bw (&f, BWORDS, &f, w2);
+                assert (!ov);
+                if (w1 != 0)
+                  {
+                    t.n = 1; t.v[0] = w1;
+                    ov = _bi_add_bb (&f, BWORDS, &f, &t);
+                    assert (!ov);
+                  }
+                w1 = 0; w2 = 1;
+              }
+            w1 = w1 * 10 + *s - '0';
+            w2 = w2 * 10;
+            ++k;
+          }
+      }
+
+  /* Check the exponent again, based on k -- now we don't have to cope
+     with the decimal point and get a better result. */
+
+  if (e + k - 1 > max_10_exp)
+    goto overflow;
+  if (e + k < min_den_10_exp)
+    goto underflow;
+
+  /* If there are digits accumulated in W1, append them to F. */
+
+  if (w2 != 1)
+    {
+      ov = _bi_mul_bw (&f, BWORDS, &f, w2);
+      assert (!ov);
+      t.n = 1; t.v[0] = w1;
+      ov = _bi_add_bb (&f, BWORDS, &f, &t);
+      assert (!ov);
+    }
+
+  /* Now, the number to convert is F*10^E.  The following code is
+     based on AlgorithmM of [1]. */
+
+  k = bias + mant_dig - 1;
+
+  /* We use powers of 5, not 10, to make the numbers smaller.  Adjust
+     K appropriately. */
+
+  k += e;
+
+  if (e < 0)
+    {
+      ov = _bi_pow5 (&uv, BWORDS, -e, 0, NULL);
+      assert (!ov);
+
+      /* Estimate the scaling factor. */
+
+      i = _bi_fls (&f) - _bi_fls (&uv);
+      if (k + i - mant_dig < 1)
+        i = mant_dig - k + 1;
+      k += i - mant_dig;
+      if (i < mant_dig)
+        {
+          ov = _bi_shl_b (&f, BWORDS, &f, mant_dig - i);
+          assert (!ov);
+        }
+      else if (i > mant_dig)
+        {
+          ov = _bi_shl_b (&uv, BWORDS, &uv,  i - mant_dig);
+          assert (!ov);
+        }
+
+      _bi_set_b (&t, BWORDS, &f);
+      ov = _bi_div_rem_bb (&t, BWORDS, &x, BWORDS, &uv); /* x:=r/v, r:=r%v */
+      assert (!ov);
+      i = _bi_fls (&x);
+
+      /* Our estimate for K is never too big, except for denormals. */
+
+      if (i < mant_dig)
+        {
+          --k;
+          assert (k == 0);
+        }
+
+      /* Sometimes, our estimate for K is too small. */
+
+      else if (i > mant_dig)
+        {
+          ++k;
+          if (k > max_exp - min_exp + 1)
+            goto overflow;
+          ov = _bi_shl_b (&uv, BWORDS, &uv, 1);
+          assert (!ov);
+          _bi_set_b (&t, BWORDS, &f);
+
+          /* We have to compute the quotient and remainder again. */
+
+          ov = _bi_div_rem_bb (&t, BWORDS, &x, BWORDS, &uv);
+          assert (!ov);
+
+          /* Our estimate can never be off by more than one, according
+             to Theorem 1. */
+
+          assert (_bi_fls (&x) == mant_dig);
+        }
+
+      /* r < v - r  is equivalent to 2r < v. */
+
+      ov = _bi_shl_b (&t, BWORDS, &t, 1);
+      assert (!ov);
+      cmp = _bi_cmp_bb (&t, &uv);
+    }
+  else
+    {
+      ov = _bi_pow5 (&t, BWORDS, e, 0, NULL);
+      assert (!ov);
+      ov = _bi_mul_bb (&uv, BWORDS, &f, &t);
+      assert (!ov);
+
+      /* v is a power of two, computing the scaling factor is
+         trivial. */
+
+      i = _bi_fls (&uv);
+      k += i - mant_dig;
+      if (i < mant_dig)
+        {
+          ov = _bi_shl_b (&uv, BWORDS, &uv, mant_dig - i);
+          assert (!ov);
+          i = 0;
+        }
+      else if (i > mant_dig)
+        i = i - mant_dig;
+      else
+        i = 0;
+
+      /* Compute x:=u/v and u:=u MOD v where v=2^i. */
+
+      ov = _bi_div_rem_pow2 (&uv, &x, BWORDS, i);
+      assert (!ov);
+
+      assert (x.n == 2);
+
+      /* r < v - r is equivalent to 2r < v.  Note that we have u=r and
+         v=2^i here. */
+
+      cmp = _bi_cmp_pow2 (&uv, i - 1);
+    }
+
+  if (k > max_exp - min_exp + 1)
+    goto overflow;
+
+  assert (x.n <= 2);            /* x.n can be < 2 for denormals */
+  if (x.n == 0)
+    mant = 0;
+  else if (x.n == 1)
+    mant = x.v[0];
+  else
+    mant = ((unsigned long long)x.v[1] << _BI_WORDSIZE) | x.v[0];
+
+  if (cmp < 0)
+    next = 0;
+  else if (cmp > 0)
+    next = 1;
+  else
+    next = x.v[0] & 1;
+  if (next)
+    {
+      if ((mant & ~INTEGER_BIT) == INTEGER_BIT - 1)
+        {
+          mant = INTEGER_BIT;
+          ++k;
+          if (k > max_exp - min_exp + 1)
+            goto overflow;
+        }
+      else
+        ++mant;
+    }
+
+  if (mant == 0)
+    goto underflow;
+
+  /* Build the floating point number from the sign, exponent, and
+     significant. */
+
+  switch (mant_dig)
+    {
+    case 24:
+      /* Clear the integer bit. */
+      mant &= ~(1ULL << (FLT_MANT_DIG - 1));
+      /* Insert the exponent. */
+      mant |= ((unsigned long long)k << (FLT_MANT_DIG - 1));
+      if (neg)
+        mant |= 0x80000000ULL;
+      *p_result = *(float *)&mant;
+      break;
+      
+    case 53:
+      /* Clear the integer bit. */
+      mant &= ~(1ULL << (DBL_MANT_DIG - 1));
+      /* Insert the exponent. */
+      mant |= ((unsigned long long)k << (DBL_MANT_DIG - 1));
+      if (neg)
+        mant |= 0x8000000000000000ULL;
+      *p_result = *(double *)&mant;
+      break;
+
+    case 64:
+      z.x.mant = mant;
+      z.x.exp = k;
+      if (neg)
+        z.x.exp |= 0x8000;
+      *p_result = z.ld;
+      break;
+    }
+  return end;
+
+overflow:
+  *p_result = neg ? -HUGE_VALL : HUGE_VALL;
+  errno = ERANGE;
+  return end;
+
+underflow:
+  *p_result = neg ? -0.0 : 0.0;
+  errno = ERANGE;
+  return end;
+}
+
+
+/* Theorem 1.  If u is a normalized m+n-bit number and v is a
+   normalized n-bit number, then 2^(m-1) <= [u/v] < 2^(m+1).
+
+   Proof: To get a lower bound for [u/v] consider the worst case
+   of u=1000... (u=2^(m+n-1)) and v=1111... (v=2^n - 1).
+
+     [u/v] >= [2^(m+n-1) / (2^n - 1)]
+           >= [2^(m+n-1) / 2^n]
+            = 2^(m-1)
+
+   To get an upper bound for [u/v] consider the worst case of
+   u=1111... (u=2^(m+n)-1) and v=1000... (v=2^(n-1)).
+
+     [u/v] <= [(2^(m+n) - 1) / 2^(n-1)]
+            = [2^(m+1) - 2^(1-n)]
+            < [2^(m+1)]
+            = 2^(m+1)                           qed. */
+
+/* References:
+
+   [1] William D. Clinger,
+       How to read floating point numbers accurately,
+       ACM SIGPLAN notices Volume 25 Number 6, June 1990. */
Index: trunk/src/emx/src/lib/conv/atof.c
===================================================================
--- trunk/src/emx/src/lib/conv/atof.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/atof.c	(revision 18)
@@ -0,0 +1,10 @@
+/* atof.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+double atof (const char *s)
+{
+  return strtod (s, NULL);
+}
Index: trunk/src/emx/src/lib/conv/atofl.c
===================================================================
--- trunk/src/emx/src/lib/conv/atofl.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/atofl.c	(revision 18)
@@ -0,0 +1,10 @@
+/* atofl.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+long double _atofl (const char *s)
+{
+  return _strtold (s, NULL);
+}
Index: trunk/src/emx/src/lib/conv/atoi.c
===================================================================
--- trunk/src/emx/src/lib/conv/atoi.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/atoi.c	(revision 18)
@@ -0,0 +1,24 @@
+/* atoi.c (emx+gcc) -- Copyright (c) 1990-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+int atoi (const char *string)
+{
+  int n;
+  char neg;
+  
+  n = 0; neg = 0;
+  while (*string == ' ' || *string == '\t') ++string;
+  if (*string == '+')
+    ++string;
+  else if (*string == '-')
+    {
+      ++string; neg = 1;
+    }
+  while (*string >= '0' && *string <= '9')
+    {
+      n = n * 10 + (*string - '0');
+      ++string;
+    }
+  return (neg ? -n : n);
+}
Index: trunk/src/emx/src/lib/conv/atol.c
===================================================================
--- trunk/src/emx/src/lib/conv/atol.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/atol.c	(revision 18)
@@ -0,0 +1,24 @@
+/* atol.c (emx+gcc) -- Copyright (c) 1990-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+long atol (const char *string)
+{
+  long n;
+  char neg;
+  
+  n = 0; neg = 0;
+  while (*string == ' ' || *string == '\t') ++string;
+  if (*string == '+')
+    ++string;
+  else if (*string == '-')
+    {
+      ++string; neg = 1;
+    }
+  while (*string >= '0' && *string <= '9')
+    {
+      n = n * 10 + (*string - '0');
+      ++string;
+    }
+  return (neg ? -n : n);
+}
Index: trunk/src/emx/src/lib/conv/atoll.c
===================================================================
--- trunk/src/emx/src/lib/conv/atoll.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/atoll.c	(revision 18)
@@ -0,0 +1,24 @@
+/* atoll.c (emx+gcc) -- Copyright (c) 1990-1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+long long _atoll (const char *string)
+{
+  long long n;
+  char neg;
+  
+  n = 0; neg = 0;
+  while (*string == ' ' || *string == '\t') ++string;
+  if (*string == '+')
+    ++string;
+  else if (*string == '-')
+    {
+      ++string; neg = 1;
+    }
+  while (*string >= '0' && *string <= '9')
+    {
+      n = n * 10 + (*string - '0');
+      ++string;
+    }
+  return (neg ? -n : n);
+}
Index: trunk/src/emx/src/lib/conv/bicmpbb.c
===================================================================
--- trunk/src/emx/src/lib/conv/bicmpbb.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bicmpbb.c	(revision 18)
@@ -0,0 +1,19 @@
+/* bicmpbb.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+int _bi_cmp_bb (const _bi_bigint *src1, const _bi_bigint *src2)
+{
+  int i;
+
+  if (src1->n > src2->n)
+    return 1;
+  else if (src1->n < src2->n)
+    return -1;
+  for (i = src1->n - 1; i >= 0; --i)
+    if (src1->v[i] > src2->v[i])
+      return 1;
+    else if (src1->v[i] < src2->v[i])
+      return -1;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bicmpp2.c
===================================================================
--- trunk/src/emx/src/lib/conv/bicmpp2.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bicmpp2.c	(revision 18)
@@ -0,0 +1,34 @@
+/* bicmpp2.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+/* SHIFT2 may be negative. */
+
+int _bi_cmp_pow2 (const _bi_bigint *src1, int shift2)
+{
+  int shift1, i, words, bits;
+
+  if (shift2 < 0)
+    {
+      /* 0 < src2 < 1 */
+      return src1->n == 0 ? -1 : 1;
+    }
+
+  shift1 = _bi_fls (src1) - 1;
+  if (shift1 < shift2)
+    return -1;
+  if (shift1 > shift2)
+    return 1;
+
+  words = (unsigned)shift2 / _BI_WORDSIZE;
+  bits = (unsigned)shift2 % _BI_WORDSIZE;
+
+  for (i = 0; i < words; ++i)
+    if (src1->v[i] != 0)
+      return 1;
+  if (bits == 0)
+    return 0;
+  if (src1->v[words] & (((_bi_word)1 << bits) - 1))
+    return 1;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bidivbb.c
===================================================================
--- trunk/src/emx/src/lib/conv/bidivbb.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bidivbb.c	(revision 18)
@@ -0,0 +1,114 @@
+/* bidivbb.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <assert.h>
+#include <sys/builtin.h>
+#include <emx/bigint.h>
+
+
+/* Helper functions defined in bidivhlp.c and bidivhlp.s. */
+
+_bi_word _bi_div_estimate (_bi_word *p, _bi_word v1, _bi_word v2);
+int _bi_div_subtract (_bi_word *u, const _bi_word *v, int n, _bi_word q);
+void _bi_div_add_back (_bi_word *u, const _bi_word *v, int n);
+
+
+/* Note: Up to one additional word may be needed for NUM_REM. */
+
+int _bi_div_rem_bb (_bi_bigint *num_rem, int num_rem_words,
+                    _bi_bigint *quot, int quot_words,
+                    const _bi_bigint *den)
+{
+  int nn, dn, shift, i, j, m, ov;
+  _bi_word q, v1, v2;
+  _bi_bigint tmp;
+
+  nn = num_rem->n;
+  dn = den->n;
+
+  if (dn == 0)
+    return 1;
+
+  if (nn + 1 > num_rem_words)
+    return 1;
+
+  if (nn < dn || (nn == dn && num_rem->v[nn-1] < den->v[nn-1]))
+    return _bi_set_w (quot, quot_words, 0);
+
+  if (dn == 1)
+    {
+      _bi_word rem;
+      if (_bi_div_rem_bw (quot, quot_words, &rem, num_rem, den->v[0]) != 0)
+        return 1;
+      return _bi_set_w (num_rem, num_rem_words, rem);
+    }
+
+/* See Donald Ervin Knuth, The Art of Computer Programming, Volume 2,
+   4.3.1, Algorithm D. */
+
+  m = nn - dn;
+  if (m + 1 > quot_words)
+    return 1;
+  quot->n = m + 1;
+
+  /* D1.  Normalize: shift left the numerator and the denominator to
+     make the most significant word of denominator >= _BI_WORDSIZE/2.
+     This won't change the quotient. */
+
+  shift = _BI_WORDSIZE - __fls (den->v[dn-1]);
+  if (shift != 0)
+    {
+
+      ov = _bi_shl_b (num_rem, num_rem_words, num_rem, shift);
+      assert (!ov);
+      tmp.n = dn;
+      tmp.v = alloca (dn * sizeof (_bi_word));
+      ov = _bi_shl_b (&tmp, dn, den, shift);
+      assert (!ov);
+      den = &tmp;
+    }
+
+  if (nn == num_rem->n)
+    num_rem->v[nn] = 0;
+
+  /* D2 and D7.  Loop over all words of NUM_DEN, starting at u(0), the
+     most significant word. */
+
+#define u(i)    num_rem->v[nn-(i)]
+#define v(i)    den->v[dn-(i)]
+
+  v1 = den->v[dn-1];
+  v2 = den->v[dn-2];
+  for (j = 0; j <= m; ++j)
+    {
+      /* D3.  Estimate the next quotient word. */
+
+      q = _bi_div_estimate (&u(j), v1, v2);
+
+      /* D4.  Multiply and subtract. */
+      /* D5.  Test remainder. */
+
+      if (_bi_div_subtract (&u(j+dn), &v(dn), dn, q))
+        {
+          /* D6.  Add back. */
+          q -= 1;
+          _bi_div_add_back (&u(j+dn), &v(dn), dn);
+        }
+      quot->v[m-j] = q;
+    }
+
+  /* D8.  Unnormalize. */
+
+  i = dn;
+  while (i > 0 && num_rem->v[i-1] == 0)
+    --i;
+  num_rem->n = i;
+  if (shift != 0)
+    _bi_shr_b (num_rem, num_rem_words, num_rem, shift);
+
+  /* Normalize QUOT. */
+
+  if (quot->v[quot->n-1] == 0)
+    quot->n -= 1;
+
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bidivp2.c
===================================================================
--- trunk/src/emx/src/lib/conv/bidivp2.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bidivp2.c	(revision 18)
@@ -0,0 +1,38 @@
+/* bidivp2.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <assert.h>
+#include <emx/bigint.h>
+
+int _bi_div_rem_pow2 (_bi_bigint *num_rem, _bi_bigint *quot, int quot_words,
+                      int shift)
+{
+  int shift_words, shift_bits, n;
+
+  assert (shift >= 0);
+  if (shift == 0)
+    {
+      if (_bi_set_b (quot, quot_words, num_rem) != 0)
+        return 1;
+      num_rem->n = 0;
+      return 0;
+    }
+
+  n = num_rem->n;
+  shift_words = (unsigned)shift / _BI_WORDSIZE;
+  shift_bits = (unsigned)shift % _BI_WORDSIZE;
+  if (n <= shift_words)
+    {
+      quot->n = 0;
+      return 0;
+    }
+
+  if (_bi_shr_b (quot, quot_words, num_rem, shift) != 0)
+    return 1;
+
+  n = shift_words + 1;
+  num_rem->v[n-1] &= ((_bi_word)1 << shift_bits) - 1;
+  while (n > 0 && num_rem->v[n-1] == 0)
+    --n;
+  num_rem->n = n;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bifls.c
===================================================================
--- trunk/src/emx/src/lib/conv/bifls.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bifls.c	(revision 18)
@@ -0,0 +1,13 @@
+/* bifls.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/builtin.h>
+#include <emx/bigint.h>
+
+int _bi_fls (const _bi_bigint *src)
+{
+  if (src->n == 0)
+    return 0;
+  else
+    return (src->n - 1) * _BI_WORDSIZE + __fls (src->v[src->n-1]);
+}
Index: trunk/src/emx/src/lib/conv/bihdivb.c
===================================================================
--- trunk/src/emx/src/lib/conv/bihdivb.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bihdivb.c	(revision 18)
@@ -0,0 +1,162 @@
+/* bihdivb.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <assert.h>
+#include <sys/builtin.h>
+#include <emx/bigint.h>
+
+/* Return NUM/DEN, replace NUM with NUM%DEN.  The quotient must not
+   exceed 1 << (_BI_WORDSIZE/2-1). */
+
+_bi_word _bi_hdiv_rem_b (_bi_bigint *num, const _bi_bigint *den)
+{
+  _bi_word q, nhi, dhi;
+  int shift, neg;
+
+  assert (den->n != 0);         /* DEN must be non-zero */
+  assert (den->v[den->n-1] != 0); /* DEN must be normalized */
+
+  /* The quotient is zero if NUM is zero or if NUM < DEN. */
+
+  if (num->n == 0 || num->n < den->n)
+    return 0;
+
+  assert (num->n <= den->n + 1); /* Overflow must not occur */
+  assert (num->v[num->n-1] != 0); /* NUM must be normalized */
+
+  /* Fetch the most significant words of both numbers. */
+
+  nhi = num->v[num->n-1];
+  dhi = den->v[den->n-1];
+
+  /* Use single-precision division if the numbers are single-precision
+     numbers. */
+
+  if (num->n == 1)              /* This implies den->n == 1, see above */
+    {
+      q = nhi / dhi;
+      neg = _bi_sub_mul_bw (num, den, q);
+      assert (!neg);
+      return q;
+    }
+
+  /* Now we know a bit more about the numbers; again, the quotient is
+     zero if NUM < DEN. */
+
+  if (num->n == den->n && nhi < dhi)
+    return 0;
+
+  /* No trivial cases left.  Compute an estimate for the quotient by
+     looking at the most significant bits.  Theorem 1 gives
+     relationships between the estimate and the quotient. */
+
+  /* Obtain the most significant _BI_WORDSIZE bits of NUM and scale DEN
+     appropriatly to keep the quotient unchanged.  This maximizes the
+     maximum possible quotient and increases the likelyhook of the
+     estimate being correct. */
+
+  shift = _BI_WORDSIZE - __fls (nhi);
+  if (shift == 0)
+    {
+      /* For num->n > den->n, the quotient would be too big. */
+      assert (num->n == den->n);
+    }
+  else
+    {
+      nhi = (nhi << shift) | (num->v[num->n-2] >> (_BI_WORDSIZE - shift));
+      if (den->n < num->n)
+        dhi >>= (_BI_WORDSIZE - shift);
+      else                      /* den->n >= num->n >= 2 */
+        dhi = (dhi << shift) | (den->v[den->n-2] >> (_BI_WORDSIZE - shift));
+    }
+
+  /* This assertion guarantees that DHI/NHI is either the quotient or
+     the quotient plus one.  The assertion can fail if the quotient is
+     bigger than supported (see theorem 2). */
+
+  assert (dhi >= 1 << (_BI_WORDSIZE/2-1));
+
+  /* Estimate the quotient by looking at the most significant
+     _BI_WORDSIZE bits of NHI. */
+
+  q = nhi / dhi;
+
+  /* If Q is zero, the quotient cannot be Q-1 and therefore we've got
+     the correct quotient. */
+
+  if (q == 0)
+    {
+      assert (_bi_cmp_bb (num, den) < 0);
+      return 0;
+    }
+
+  /* Q is exact if NHI/(DHI+1) = NHI/DHI.  Q is also exact if DHI is
+     the maximum value of a _bi_word and NHI is not the maximum value of
+     a _bi_word. */
+
+  if ((_bi_word)(dhi + 1) != 0 ? q == nhi / (dhi + 1) : (_bi_word)(nhi + 1) !=  0)
+    {
+      neg = _bi_sub_mul_bw (num, den, q);
+      assert (!neg);
+      assert (_bi_cmp_bb (num, den) < 0);
+      return q;
+    }
+
+  /* Theorem 2 guarantees that only two cases are left.  First try Q,
+     which is the correct quotient with extremely high probability. */
+
+  neg = _bi_sub_mul_bw (num, den, q);
+  if (neg)
+    {
+      /* The probability of hitting this case seems to be proportional
+         to 2^-_BI_WORDSIZE.  For _BI_WORDSIZE of 32, it's hardly ever
+         hit in practice if the quotient is <10.  This code has been
+         tested by reducing SHIFT to 7, which is the minimum value (by
+         theorem 2) for quotients up to 10. */
+
+      q -= 1;
+      neg = _bi_sub_mul_bw (num, den, q);
+      assert (!neg);
+    }
+  assert (_bi_cmp_bb (num, den) < 0);
+  return q;
+}
+
+/* Theorem 1: Given positive integers X, Y, and S.  Let x:=[X/S],
+   y:=[Y/S], y non-zero.  Then, [x/(y+1)] <= [X/Y] <= [x/y].
+
+   Proof: Suppose that X and Y are unknown.  For given x and y, a
+   lower bound for [X/Y] can be obtained by choosing the smallest X
+   and biggest Y for x and y, respectively:
+
+     [X/Y] >= [Xmin/Ymax] =  [(x*S+0) / (y*S+S-1)]
+                          =  [x*S / ((y+1)*S-1)]
+                          >= [x*S / ((y+1)*S]       (note that y >= 2, S >= 1)
+                          =  [x/(y+1)]
+
+   For given x and y, an upper bound for [X/Y] can be obtained by
+   choosing the biggest X and smallest Y for x and y, respectively:
+
+     [X/Y] <= [Xmax/Ymin] =  [(x*S+S-1) / (y*S+0)]
+                          =  [x/y + ((S-1)/S)/y]
+                          =  [[x/y] + x/y-[x/y] + ((S-1)/S)/y]
+                          =  [x/y] + [x/y-[x/y] + ((S-1)/S)/y]
+                          <= [x/y] + [(y-1)/y + ((S-1)/S)/y]
+                          =  [x/y] + [(y-1+(S-1)/S)/y]
+                          =  [x/y]                      qed.
+
+
+   Theorem 2: Let x and y be positive integers.  Then,
+
+     [x/y] - [x/(y+1)] <= 1
+
+   for x <= y^2+2y-1.
+
+   Proof:
+
+     [x/y] =  [x/y - x/(y+1) + x/(y+1)]
+           =  [(x*(y+1) - x*y)/(y*(y+1)) + x/(y+1)]
+           =  [x / (y*(y+1)) + x/(y+1)]
+           <= [(y*y+2*y-1) / (y*(y+1)) + x/(y+1)]   (for x <= y^2+2y-1)
+           =  [1 + (x+(1-1/y))/(y+1)]
+           =  1 + [x/(y+1)]                             qed. */
+
Index: trunk/src/emx/src/lib/conv/bipow5.c
===================================================================
--- trunk/src/emx/src/lib/conv/bipow5.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bipow5.c	(revision 18)
@@ -0,0 +1,117 @@
+/* bipow5.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/bigint.h>
+#include "bipow5.tab"
+
+
+int _bi_pow5 (_bi_bigint *dst, int dst_words,
+              int exp, int shift, const _bi_bigint *factor)
+{
+#ifdef TABLE1_SIZE
+  int f1;
+#endif
+  int f2, f3, ov;
+  _bi_bigint b2, b3, bt;
+  const _bi_bigint *p;
+
+  if (factor != NULL && factor->n == 0)
+    {
+      dst->n = 0;
+      return 0;
+    }
+
+#ifdef TABLE1_SIZE
+  f1 = exp % (TABLE1_SIZE + 1);
+  exp = exp / (TABLE1_SIZE + 1);
+#endif
+  f2 = exp % (TABLE2_SIZE + 1);
+  f3 = exp / (TABLE2_SIZE + 1);
+
+  p = NULL;
+  if (f3 != 0)
+    {
+      if (f3 > TABLE3_SIZE)
+        return 1;
+      b3.n = table3[f3] - table3[f3-1];
+      b3.v = (_bi_word *)table4 + table3[f3-1]; /* cast away const */
+      p = &b3;
+    }
+
+  if (f2 != 0)
+    {
+      b2.n = table2[f2] - table2[f2-1];
+      b2.v = (_bi_word *)table4 + table2[f2-1]; /* cast away const */
+      if (p == NULL)
+        p = &b2;
+      else
+        {
+          if (_bi_mul_bb (dst, dst_words, p, &b2) != 0)
+            return 1;
+          p = dst;
+        }
+    }
+
+  if (factor != NULL && (factor->n != 1 || factor->v[0] != 1))
+    {
+      if (p == NULL)
+        p = factor;
+      else
+        {
+          if (factor->n == 1)
+            ov = _bi_mul_bw (dst, dst_words, p, factor->v[0]);
+          else
+            {
+              if (p == dst)
+                {
+                  bt.v = alloca (dst->n * sizeof (_bi_word));
+                  _bi_set_b (&bt, dst->n, dst);
+                  p = &bt;
+                }
+              ov = _bi_mul_bb (dst, dst_words, p, factor);
+            }
+          if (ov != 0)
+            return ov;
+          p = dst;
+        }
+    }
+
+#ifdef TABLE1_SIZE
+  if (f1 != 0)
+    {
+      if (p == NULL)
+        {
+          if (shift != 0)
+            {
+              ov = _bi_shl_w (dst, dst_words, table1[f1-1], shift);
+              shift = 0;
+            }
+          else
+            ov = _bi_set_w (dst, dst_words, table1[f1-1]);
+        }
+      else
+        ov = _bi_mul_bw (dst, dst_words, p, table1[f1-1]);
+      if (ov != 0)
+        return 1;
+      p = dst;
+    }
+#endif
+
+  if (shift != 0)
+    {
+      if (p == NULL)
+        ov = _bi_shl_w (dst, dst_words, 1, shift);
+      else
+        ov = _bi_shl_b (dst, dst_words, p, shift);
+      if (ov != 0)
+        return 1;
+      p = dst;
+    }
+
+  if (p == NULL)
+    return _bi_set_w (dst, dst_words, 1);
+  else if (p != dst)
+    return _bi_set_b (dst, dst_words, p);
+  else
+    return 0;
+}
Index: trunk/src/emx/src/lib/conv/bisetb.c
===================================================================
--- trunk/src/emx/src/lib/conv/bisetb.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bisetb.c	(revision 18)
@@ -0,0 +1,13 @@
+/* bisetb.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <emx/bigint.h>
+
+int _bi_set_b (_bi_bigint *dst, int dst_words, const _bi_bigint *src)
+{
+  if (src->n > dst_words)
+    return 1;
+  dst->n = src->n;
+  memcpy (dst->v, src->v, src->n * sizeof (_bi_word));
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bisetd.c
===================================================================
--- trunk/src/emx/src/lib/conv/bisetd.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bisetd.c	(revision 18)
@@ -0,0 +1,25 @@
+/* bisetd.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+int _bi_set_d (_bi_bigint *dst, int dst_words, _bi_dword src)
+{
+  if (src == 0)
+    dst->n = 0;
+  else if (dst_words <= 0)
+    return 1;
+  else if (src >> _BI_WORDSIZE == 0)
+    {
+      dst->n = 1;
+      dst->v[0] = (_bi_word)src;
+    }
+  else if (dst_words <= 1)
+    return 1;
+  else
+    {
+      dst->n = 2;
+      dst->v[0] = (_bi_word)src;
+      dst->v[1] = (_bi_word)(src >> _BI_WORDSIZE);
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bisetw.c
===================================================================
--- trunk/src/emx/src/lib/conv/bisetw.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bisetw.c	(revision 18)
@@ -0,0 +1,17 @@
+/* bisetw.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+int _bi_set_w (_bi_bigint *dst, int dst_words, _bi_word src)
+{
+  if (src == 0)
+    dst->n = 0;
+  else if (dst_words <= 0)
+    return 1;
+  else
+    {
+      dst->n = 1;
+      dst->v[0] = src;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bishlb.c
===================================================================
--- trunk/src/emx/src/lib/conv/bishlb.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bishlb.c	(revision 18)
@@ -0,0 +1,47 @@
+/* bishlb.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+/* DST==SRC is allowed. */
+
+int _bi_shl_b (_bi_bigint *dst, int dst_words,
+               const _bi_bigint *src, int shift)
+{
+  int b, w, i, sn, dn;
+  _bi_word tmp;
+
+  sn = src->n;
+  if (sn == 0)
+    {
+      dst->n = 0;
+      return 0;
+    }
+  b = (unsigned)shift % _BI_WORDSIZE; /* Bit shift count */
+  w = (unsigned)shift / _BI_WORDSIZE; /* Word shift count */
+  dn = sn + w;
+  if (dn > dst_words)
+    return 1;
+  if (b == 0)
+    for (i = sn-1; i >= 0; --i)
+      dst->v[i+w] = src->v[i];
+  else
+    {
+      tmp = src->v[sn-1] >> (_BI_WORDSIZE - b);
+      if (tmp != 0)
+        {
+          if (dn + 1 > dst_words)
+            return 1;
+          dst->v[dn++] = tmp;
+        }
+      for (i = sn-1; i > 0; --i)
+        {
+          tmp = (src->v[i] << b) | (src->v[i-1] >> (_BI_WORDSIZE - b));
+          dst->v[i+w] = tmp;
+        }
+      dst->v[w] = src->v[0] << b;
+    }
+  for (i = 0; i < w; ++i)
+    dst->v[i] = 0;
+  dst->n = dn;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bishlw.c
===================================================================
--- trunk/src/emx/src/lib/conv/bishlw.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bishlw.c	(revision 18)
@@ -0,0 +1,33 @@
+/* bishlw.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+int _bi_shl_w (_bi_bigint *dst, int dst_words, _bi_word src, int shift)
+{
+  int b, w, dn;
+  _bi_dword tmp;
+  _bi_word carry;
+
+  if (src == 0)
+    {
+      dst->n = 0;
+      return 0;
+    }
+  b = (unsigned)shift % _BI_WORDSIZE; /* Bit shift count */
+  w = (unsigned)shift / _BI_WORDSIZE; /* Word shift count */
+  if (w + 1 > dst_words)
+    return 1;
+  for (dn = 0; dn < w; ++dn)
+    dst->v[dn] = 0;
+  tmp = (_bi_dword)src << b;
+  dst->v[dn++] = (_bi_word)tmp;
+  carry = tmp >> _BI_WORDSIZE;
+  if (carry)
+    {
+      if (dn + 1 > dst_words)
+        return 1;
+      dst->v[dn++] = carry;
+    }
+  dst->n = dn;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/bishrb.c
===================================================================
--- trunk/src/emx/src/lib/conv/bishrb.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/bishrb.c	(revision 18)
@@ -0,0 +1,39 @@
+/* bishrb.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+/* DST==SRC is allowed. */
+
+int _bi_shr_b (_bi_bigint *dst, int dst_words, const _bi_bigint *src,
+               int shift)
+{
+  int b, w, i, sn, dn;
+  _bi_word tmp;
+
+  b = (unsigned)shift % _BI_WORDSIZE; /* Bit shift count */
+  w = (unsigned)shift / _BI_WORDSIZE; /* Word shift count */
+  sn = src->n;
+  if (sn <= w)
+    {
+      dst->n = 0;
+      return 0;
+    }
+  dn = sn - w;
+  if (dn > dst_words)
+    return 1;
+  if (b == 0)
+    for (i = 0; i < sn; ++i)
+      dst->v[i] = src->v[i+w];
+  else
+    {
+      for (i = 0; i < dn - 1; ++i)
+        dst->v[i] = (src->v[i+w] >> b) | (src->v[i+w+1] << (_BI_WORDSIZE - b));
+      tmp = src->v[dn-1+w] >> b;
+      if (tmp != 0)
+        dst->v[dn-1] = tmp;
+      else
+        dn -= 1;
+    }
+  dst->n = dn;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/biwdivp2.c
===================================================================
--- trunk/src/emx/src/lib/conv/biwdivp2.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/biwdivp2.c	(revision 18)
@@ -0,0 +1,44 @@
+/* biwdivp2.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <assert.h>
+#include <emx/bigint.h>
+
+/* Return NUM/(1<<SHIFT), replace NUM with NUM%(1<<SHIFT).  The
+   quotient must fit in a _bi_word. */
+
+_bi_word _bi_wdiv_rem_pow2 (_bi_bigint *num, int shift)
+{
+  int shift_words, shift_bits, n;
+  _bi_word q;
+
+  assert (shift >= 1);
+
+  shift_words = (unsigned)shift / _BI_WORDSIZE + 1;
+  n = num->n;
+
+  /* The quotient is zero if NUM is zero or if NUM < (1<<SHIFT). */
+
+  if (n < shift_words)
+    return 0;
+
+  assert (n <= shift_words + 1); /* Overflow must not occur */
+  assert (num->v[n-1] != 0); /* NUM must be normalized */
+
+  shift_bits = (unsigned)shift % _BI_WORDSIZE;
+
+  if (n == shift_words)
+    q = num->v[n-1] >> shift_bits;
+  else /* n == shift_words + 1 */
+    {
+      assert (n >= 2);
+      assert (shift_bits != 0);
+      q = (((num->v[n-1] << (_BI_WORDSIZE - shift_bits))
+            | (num->v[n-2]) >> shift_bits));
+      n -= 1;                   /* Drop the most significant word */
+    }
+  num->v[n-1] &= ((_bi_word)1 << shift_bits) - 1;
+  while (n != 0 && num->v[n-1] == 0)
+    --n;
+  num->n = n;
+  return q;
+}
Index: trunk/src/emx/src/lib/conv/c/biaddbb.c
===================================================================
--- trunk/src/emx/src/lib/conv/c/biaddbb.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/c/biaddbb.c	(revision 18)
@@ -0,0 +1,46 @@
+/* biaddbb.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+/* DST==SRC1 or DST==SRC2 is allowed. */
+
+int _bi_add_bb (_bi_bigint *dst, int dst_words,
+                const _bi_bigint *src1, const _bi_bigint *src2)
+{
+  int i, n;
+  _bi_dword tmp;
+  _bi_word carry;
+  const _bi_bigint *s;
+
+  if (src1->n < src2->n)
+    {
+      n = src1->n; s = src2;
+    }
+  else
+    {
+      n = src2->n; s = src1;
+    }
+  if (s->n > dst_words)
+    return 1;
+  carry = 0;
+  for (i = 0; i < n; ++i)
+    {
+      tmp = (_bi_dword)src1->v[i] + src2->v[i] + carry;
+      dst->v[i] = (_bi_word)tmp;
+      carry = tmp >> _BI_WORDSIZE;
+    }
+  for (; i < s->n; ++i)
+    {
+      tmp = (_bi_dword)s->v[i] + carry;
+      dst->v[i] = (_bi_word)tmp;
+      carry = tmp >> _BI_WORDSIZE;
+    }
+  if (carry)
+    {
+      if (i + 1 > dst_words)
+        return 1;               /* TODO: restore DST? */
+      dst->v[i++] = carry;
+    }
+  dst->n = i;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/c/bidivbw.c
===================================================================
--- trunk/src/emx/src/lib/conv/c/bidivbw.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/c/bidivbw.c	(revision 18)
@@ -0,0 +1,42 @@
+/* bidivbw.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+/* QUOT==NUM is allowed. */
+
+int _bi_div_rem_bw (_bi_bigint *quot, int quot_words, _bi_word *rem,
+                    const _bi_bigint *num, _bi_word den)
+{
+  int j;
+  _bi_word r;
+  _bi_dword t;
+
+  if (den == 0)
+    return 1;
+
+  if (num->n > quot_words)
+    return 1;
+
+  if (num->n == 0)
+    {
+      *rem = 0;
+      quot->n = 0;
+      return 0;
+    }
+
+  /* TAOCP Vol. 2, 4.3.1, Exercise 16. */
+
+  r = 0;
+  for (j = num->n - 1; j >= 0; --j)
+    {
+      t = ((_bi_dword)r << _BI_WORDSIZE) + num->v[j];
+      quot->v[j] = t / den;
+      r = t % den;
+    }
+  *rem = r;
+  if (quot->v[num->n-1] != 0)
+    quot->n = num->n;
+  else
+    quot->n = num->n - 1;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/c/bidivhlp.c
===================================================================
--- trunk/src/emx/src/lib/conv/c/bidivhlp.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/c/bidivhlp.c	(revision 18)
@@ -0,0 +1,78 @@
+/* bidivhlp.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <emx/bigint.h>
+
+_bi_word _bi_div_estimate (_bi_word *u, _bi_word v1, _bi_word v2)
+{
+  _bi_word q, r;
+
+  assert (u[0] <= v1);
+  if (u[0] == v1)
+    {
+      _bi_dword rd;
+      q = (_bi_word)-1;
+      rd = ((_bi_dword)u[0] << _BI_WORDSIZE) + u[-1] - (_bi_dword)q * v1;
+      r = (_bi_word)rd;
+      if (r != rd)
+        return q;
+    }
+  else
+    {
+      _ulldiv_t qr;
+      qr = _ulldiv (((_bi_dword)u[0] << _BI_WORDSIZE) + u[-1], v1);
+      q = qr.quot;
+      r = qr.rem;
+    }
+
+  /* Eliminate most cases where Q is one too large, eliminate all
+     cases where Q is two too large. */
+
+  while ((_bi_dword)v2 * q > ((_bi_dword)r << _BI_WORDSIZE) + u[-2])
+    {
+      assert (q != 0);
+      q -= 1; r += v1;
+      if (r < v1)               /* Overflow */
+        break;
+    }
+  return q;
+}
+
+
+int _bi_div_subtract (_bi_word *u, const _bi_word *v, int n, _bi_word q)
+{
+  int i;
+  _bi_word sub_borrow, mul_carry;
+  _bi_sdword stmp;
+
+  mul_carry = 0; sub_borrow = 0;
+  for (i = 0; i < n; ++i)
+    {
+      stmp = (_bi_dword)*v++ * q + mul_carry;
+      mul_carry = stmp >> _BI_WORDSIZE;
+      stmp = (_bi_dword)*u - (_bi_word)stmp - sub_borrow;
+      *u++ = (_bi_word)stmp;
+      sub_borrow = stmp < 0;
+    }
+  stmp = (_bi_dword)*u - mul_carry - sub_borrow;
+  *u = (_bi_word)stmp;
+  return stmp < 0;
+}
+
+
+void _bi_div_add_back (_bi_word *u, const _bi_word *v, int n)
+{
+  int i;
+  _bi_word carry;
+  _bi_dword utmp;
+
+  carry = 0;
+  for (i = 0; i <= n; ++i)
+    {
+      utmp = (_bi_dword)*u + *v++ + carry;
+      *u++ = (_bi_word)utmp;
+      carry = utmp >> _BI_WORDSIZE;
+    }
+  assert (carry);
+}
Index: trunk/src/emx/src/lib/conv/c/bimulbb.c
===================================================================
--- trunk/src/emx/src/lib/conv/c/bimulbb.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/c/bimulbb.c	(revision 18)
@@ -0,0 +1,48 @@
+/* bimulbb.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <assert.h>
+#include <emx/bigint.h>
+
+int _bi_mul_bb (_bi_bigint *dst, int dst_words,
+                const _bi_bigint *src1, const _bi_bigint *src2)
+{
+  int i, j, dn;
+  _bi_dword tmp;
+  _bi_word carry, factor;
+
+  if (src1->n == 0 || src2->n == 0)
+    {
+      dst->n = 0;
+      return 0;
+    }
+  if (src1->n + src2->n > dst_words)
+    return 1;
+  dn = src1->n + src2->n;
+  for (i = 0; i < dn; ++i)
+    dst->v[i] = 0;
+  for (i = 0; i < src2->n; ++i)
+    {
+      factor = src2->v[i];
+      carry = 0;
+      for (j = 0; j < src1->n; ++j)
+        {
+          tmp = (_bi_dword)src1->v[j] * factor + dst->v[i+j] + carry;
+          dst->v[i+j] = (_bi_word)tmp;
+          carry = tmp >> _BI_WORDSIZE;
+        }
+      while (carry)
+        {
+          assert (i + j < dn);
+          tmp = (_bi_dword)dst->v[i+j] + carry;
+          dst->v[i+j] = (_bi_word)tmp;
+          carry = tmp >> _BI_WORDSIZE;
+          ++j;
+        }
+    }
+
+  if (dn > 0 && dst->v[dn-1] == 0)
+    --dn;
+  assert (dn != 0 && dst->v[dn-1] != 0);
+  dst->n = dn;
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/c/bimulbw.c
===================================================================
--- trunk/src/emx/src/lib/conv/c/bimulbw.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/c/bimulbw.c	(revision 18)
@@ -0,0 +1,34 @@
+/* bimulbw.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+/* DST==SRC is allowed. */
+
+int _bi_mul_bw (_bi_bigint *dst, int dst_words,
+                const _bi_bigint *src, _bi_word factor)
+{
+  int i;
+  _bi_dword tmp;
+  _bi_word carry;
+
+  if (factor == 0)
+    {
+      dst->n = 0;
+      return 0;
+    }
+  carry = 0;
+  for (i = 0; i < src->n; ++i)
+    {
+      tmp = (_bi_dword)src->v[i] * factor + carry;
+      dst->v[i] = (_bi_word)tmp;
+      carry = tmp >> _BI_WORDSIZE;
+    }
+  dst->n = src->n;
+  if (carry != 0)
+    {
+      if (dst->n >= dst_words)
+        return 1;
+      dst->v[dst->n++] = carry;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/c/bisubmbw.c
===================================================================
--- trunk/src/emx/src/lib/conv/c/bisubmbw.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/c/bisubmbw.c	(revision 18)
@@ -0,0 +1,77 @@
+/* bisubmbw.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/bigint.h>
+
+/* DST := DST - FACTOR * SRC; leave DST unchanged and return 1 if the
+   result would be negative. */
+
+int _bi_sub_mul_bw (_bi_bigint *dst, const _bi_bigint *src, _bi_word factor)
+{
+  int i, n;
+  _bi_word sub_borrow, mul_carry, add_carry;
+  _bi_sdword stmp;
+  _bi_dword utmp;
+
+  if (src->n > dst->n)
+    return 1;
+
+  if (src->n == 0 || factor == 0)
+    return 0;
+
+  n = src->n;
+  sub_borrow = 0; mul_carry = 0;
+  for (i = 0; i < n; ++i)
+    {
+      stmp = (_bi_dword)src->v[i] * factor + mul_carry;
+      mul_carry = stmp >> _BI_WORDSIZE;
+      stmp = (_bi_dword)dst->v[i] - (_bi_word)stmp - sub_borrow;
+      dst->v[i] = (_bi_word)stmp;
+      sub_borrow = stmp < 0;
+    }
+  n = dst->n;
+  if (mul_carry && i < n)
+    {
+      stmp = (_bi_dword)dst->v[i] - mul_carry - sub_borrow;
+      dst->v[i] = (_bi_word)stmp;
+      mul_carry = 0;
+      sub_borrow = stmp < 0;
+      ++i;
+    }
+  while (sub_borrow && i < n)
+    {
+      stmp = (_bi_dword)dst->v[i] - sub_borrow;
+      dst->v[i] = (_bi_word)stmp;
+      sub_borrow = stmp < 0;
+      ++i;
+    }
+  if (!mul_carry && !sub_borrow)
+    {
+      while (n != 0 && dst->v[n-1] == 0)
+        --n;
+      dst->n = n;
+      return 0;
+    }
+
+  /* The result would be negative.  Restore the original DST. */
+
+  add_carry = 0; mul_carry = 0;
+  n = src->n;
+  for (i = 0; i < n; ++i)
+    {
+      utmp = (_bi_dword)src->v[i] * factor + mul_carry;
+      mul_carry = utmp >> _BI_WORDSIZE;
+      utmp = (_bi_dword)dst->v[i] + (_bi_word)utmp + add_carry;
+      dst->v[i] = (_bi_word)utmp;
+      add_carry = utmp >> _BI_WORDSIZE;
+    }
+  n = dst->n;
+  if (i < n && (mul_carry || add_carry))
+    {
+      utmp = (_bi_dword)dst->v[i] + mul_carry + add_carry;
+      dst->v[i] = (_bi_word)utmp;
+      mul_carry = 0;
+      add_carry = utmp >> _BI_WORDSIZE;
+      ++i;
+    }
+  return 1;
+}
Index: trunk/src/emx/src/lib/conv/dtoa.c
===================================================================
--- trunk/src/emx/src/lib/conv/dtoa.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/dtoa.c	(revision 18)
@@ -0,0 +1,248 @@
+/* dtoa.c (emx+gcc) -- Copyright (c) 1996-1999 by Eberhard Mattes */
+
+#include <math.h>
+#include <float.h>
+#include <assert.h>
+#include <sys/builtin.h>
+#include <emx/float.h>
+#include <emx/bigint.h>
+
+#define BWORDS          _BI_WORDS (LDBL_MAX_EXP)
+#define BIAS            16383
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+struct long_double_bits
+{
+  _bi_dword mant;
+  unsigned short exp : 15;
+  unsigned short sign : 1;
+};
+
+
+static int estimate (int e)
+{
+  if (e < 0)
+    return (int)(e*0.3010299956639812);
+  else
+    return 1 + (int)(e*0.3010299956639811);
+}
+
+
+char *__dtoa (char *buffer, int *p_exp,
+              long double x, int ndigits, int fmt, int dig)
+{
+  const struct long_double_bits *bits;
+  _bi_dword f;
+  int e, k, r_n, s_n, m_n, i, cmp, digit;
+  int di, s_pow2, a, ov;
+  _BI_DECLARE (r, BWORDS);
+  _BI_DECLARE (s, BWORDS);
+  _BI_DECLARE (m, BWORDS);
+  _BI_DECLARE (tmp, BWORDS);
+
+  _BI_INIT (r); _BI_INIT (s); _BI_INIT (m); _BI_INIT (tmp);
+
+  bits = (const struct long_double_bits *)&x;
+  f = bits->mant;
+  e = bits->exp;
+
+  /* E is the exponent for the fraction F; now replace E with the
+     exponent for the integer F.  Compute an estimate for the scaling
+     factor.  See [1]. */
+
+  if (e != 0)                   /* normal */
+    {
+      e -= BIAS + LDBL_MANT_DIG - 1;
+      k = estimate (e + LDBL_MANT_DIG - 1);
+    }
+  else                          /* denormal */
+    {
+      e = 1 - (BIAS + LDBL_MANT_DIG - 1);
+      if (f >> 32 == 0)
+        k = estimate (e + __fls ((unsigned long)f) - 1);
+      else
+        k = estimate (e + __fls ((unsigned long)(f >> 32)) + 32 - 1);
+    }
+
+  /* Compute initial values (cf. table 1 of [1]). */
+
+  if (e >= 0)
+    {
+      if (f != 1ULL << (LDBL_MANT_DIG-1))
+        {
+          r_n = e + 1; s_n = 1; m_n = e;
+        }
+      else
+        {
+          r_n = e + 2; s_n = 2; m_n = e + 1;
+        }
+    }
+  else
+    {
+      if (e == LDBL_MIN_EXP - LDBL_MANT_DIG || f != 1ULL << (LDBL_MANT_DIG-1))
+        {
+          r_n = 1; s_n = 1 - e; m_n = 0;
+        }
+      else
+        {
+          r_n = 2; s_n = 2 - e; m_n = 1;
+        }
+    }
+
+  /* Now compute R, S, and M from K and the shift counts. */
+
+  if (k == 0)
+    {
+      ov = _bi_set_d (&tmp, BWORDS, f); assert (!ov);
+      ov = _bi_shl_b (&r, BWORDS, &tmp, r_n); assert (!ov);
+      ov = _bi_shl_w (&s, BWORDS, 1, s_n); assert (!ov);
+      s_pow2 = 1;
+      ov = _bi_shl_w (&m, BWORDS, 1, m_n); assert (!ov);
+    }
+  else if (k > 0)
+    {
+      s_n += k;                 /* 10^k = 2^k * 5^k */
+
+      /* Reduce powers of two.  Note that M is the smallest one of M,
+         R, and S.  This speed hack has been borrowed from Robert
+         G. Burger's C code. */
+
+      i = MIN (m_n, s_n);
+      r_n -= i; s_n -= i; m_n -= i;
+
+      ov = _bi_set_d (&tmp, BWORDS, f); assert (!ov);
+      ov = _bi_shl_b (&r, BWORDS, &tmp, r_n); assert (!ov);
+      ov = _bi_pow5 (&s, BWORDS, k, s_n, 0); assert (!ov);
+      s_pow2 = 0;
+      ov = _bi_shl_w (&m, BWORDS, 1, m_n); assert (!ov);
+    }
+  else                          /* k < 0 */
+    {
+      s_n += k;                 /* 10^k = 2^k * 5^k */
+
+      ov = _bi_set_d (&tmp, BWORDS, f); assert (!ov);
+      ov = _bi_pow5 (&r, BWORDS, -k, r_n, &tmp); assert (!ov);
+      ov = _bi_shl_w (&s, BWORDS, 1, s_n); assert (!ov);
+      s_pow2 = 1;
+      ov = _bi_pow5 (&m, BWORDS, -k, m_n, 0); assert (!ov);
+    }
+
+  /* Adjust the estimate, that is, multiply M and R by 10 if the
+     estimate is correct (it's frequently incorrect): Multiply M and R
+     by 10 (and decrement K) if R + M <= S. */
+
+  ov = _bi_add_bb (&tmp, BWORDS, &r, &m); assert (!ov);
+  cmp = _bi_cmp_bb (&tmp, &s);
+  if (cmp <= 0)
+    {
+      k -= 1;
+      ov = _bi_mul_bw (&r, BWORDS, &r, 10); assert (!ov);
+    }
+
+  /* Compute the maximum number of digits to generate. */
+
+  switch (fmt)
+    {
+    case DTOA_PRINTF_E:
+      a = ndigits + 1;
+      break;
+    case DTOA_PRINTF_F:
+      a = k + 1 + ndigits;
+      break;
+    case DTOA_PRINTF_G:
+    case DTOA_GCVT:
+      a = ndigits;
+      break;
+
+    default:
+      abort ();
+    }
+  if (a > DECIMAL_DIG)
+    a = DECIMAL_DIG;
+
+  /* Generate the digits.  We might need to use buffer[0] in case of
+     carry produced by rounding.  (Unlike the algorithms of [1] and
+     [2], this one does _not_ generate the digits left to right.) */
+
+  buffer[0] = '0'; di = 1;
+
+  if (a > 0)
+    {
+      for (;;)
+        {
+          /* Speed hack borrowed from Robert G. Burger's C code:
+             dividing by powers of two is faster than dividing by
+             arbitrary numbers.  */
+
+          if (s_pow2)
+            digit = _bi_wdiv_rem_pow2 (&r, s_n);
+          else
+            digit = _bi_hdiv_rem_b (&r, &s);
+          assert (digit < 10);
+
+          buffer[di++] = digit + '0';
+
+          if (--a <= 0)
+            break;
+
+          ov = _bi_mul_bw (&r, BWORDS, &r, 10); assert (!ov);
+        }
+
+      /* We've generated all the digits but might have to round up. */
+
+      ov = _bi_shl_b (&tmp, BWORDS, &r, 1); assert (!ov);
+      cmp = _bi_cmp_bb (&tmp, &s);
+      if (cmp > 0 || (cmp == 0 && ((buffer[di-1] - '0') & 1)))
+        while (++buffer[di-1] > '9')
+          --di;
+    }
+  else if (a == 0)
+    {
+      /* See above. */
+
+      if (s_pow2)
+        digit = _bi_wdiv_rem_pow2 (&r, s_n);
+      else
+        digit = _bi_hdiv_rem_b (&r, &s);
+      assert (digit < 10);
+
+      /* Round to nearest or even (note: zero is even, so we don't
+         round up if S/R is exactly five). */
+
+      if (digit > 5 || (digit == 5 && r.n != 0))
+        buffer[0] = '1';
+    }
+
+  while (di < DECIMAL_DIG + 1)  /* One extra for buffer[0] */
+    buffer[di++] = '0';
+  buffer[di] = 0;
+
+  if (buffer[0] != '0')
+    {
+      *p_exp = k + 1;
+      return buffer;
+    }
+  else
+    {
+      *p_exp = k;
+      return buffer + 1;
+    }
+}
+
+/* References:
+
+   [1] Robert G. Burger and R. Kent Dybvig,
+       Printing floating-point numbers quickly and accurately.
+       ACM SIGPLAN notices Volume 31 Number 5, May 1996.
+
+   [2] Guy L. Steele Jr. and Jon L. White,
+       How to print floating-point numbers accurately.
+       ACM SIGPLAN notices Volume 25 Number 6, June 1990.
+
+   (Not yet used:)
+
+   [3] David M. Gay,
+       Correctly rounded binary-decimal and decimal-binary conversions.
+       Numerical Analysis Manuscript 90-10, AT&T Bell Laboratories,
+       Murray Hill, New Jersey 07974, November 1990. */
Index: trunk/src/emx/src/lib/conv/gcvt.c
===================================================================
--- trunk/src/emx/src/lib/conv/gcvt.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/gcvt.c	(revision 18)
@@ -0,0 +1,124 @@
+/* gcvt.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <locale.h>
+#include <emx/float.h>
+#include <emx/locale.h>
+
+char *_gcvt (double x, int digits, char *buffer)
+{
+  char digstr[DECIMAL_DIG+2], *str, *dst;
+  const char *src;
+  int xp, i, fpclass, neg;
+
+  dst = buffer;
+
+  /* Handle trivial cases first.  The empty string is produced if
+     DIGITS is less than one. */
+
+  if (digits < 1)
+    {
+      *dst = 0;
+      return buffer;
+    }
+
+  /* Classify the number and get the sign bit. */
+
+  fpclass = fpclassify (x);
+  neg = signbit (x);
+  switch (fpclass)
+    {
+    case FP_ZERO:
+      /* "0" is produced if X is zero (the code below doesn't work if
+         X is zero). */
+      src = "0";
+      break;
+    case FP_NAN:
+      src = "NAN";
+      neg = 0;                  /* Don't print -NAN */
+      break;
+    case FP_INFINITE:
+      src = "INF";
+      break;
+    default:
+      src = NULL;
+      break;
+    }
+
+  /* Handle the sign bit. */
+
+  if (neg)
+    *dst++ = '-';
+
+  /* Handle special cases. */
+
+  if (src != NULL)
+    {
+      strcpy (dst, src);
+      return buffer;
+    }
+
+  /* Make the number positive. */
+
+  if (neg)
+    x = -x;
+
+  /* Compute a string of digits and an exponent for the number. */
+
+  str = __dtoa (digstr, &xp, x, digits, DTOA_GCVT, DBL_DIG);
+  __remove_zeros (str, 1);
+
+  /* Decide whether to use fixed or exponential format. */
+
+  if (xp < -1 || xp >= digits)
+    {
+      /* Exponential format: #.####e+## */
+
+      *dst++ = str[0];
+      if (str[1] != 0)
+        *dst++ = _cur_lconv.decimal_point[0];
+      for (src = str+1; *src != 0; ++src)
+        *dst++ = *src;
+      *dst++ = 'e';
+      if (xp < 0)
+        {
+          *dst++ = '-';
+          xp = -xp;
+        }
+      else
+        *dst++ = '+';
+
+      /* Use at least two digits for the exponent. */
+
+      if (xp < 10)
+        *dst++ = '0';
+      _itoa (xp, dst, 10);
+    }
+  else
+    {
+      /* Fixed format: ####.#### */
+
+      if (xp == -1)
+        *dst++ = '0';
+
+      /* Take digits from the string. */
+
+      for (i = 0; str[i] != 0; ++i)
+        {
+          if (i == xp + 1)
+            *dst++ = _cur_lconv.decimal_point[0];
+          *dst++ = str[i];
+        }
+
+      /* Append zeros until the exponent is correct. */
+
+      for (; i <= xp; ++i)
+        *dst++ = '0';
+
+      *dst = 0;
+    }
+  return buffer;
+}
Index: trunk/src/emx/src/lib/conv/itoa.c
===================================================================
--- trunk/src/emx/src/lib/conv/itoa.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/itoa.c	(revision 18)
@@ -0,0 +1,36 @@
+/* itoa.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+char *_itoa (int value, char *string, int radix)
+{
+  char *dst;
+  char digits[32];
+  unsigned x;
+  int i, n;
+  
+  dst = string;
+  if (radix < 2 || radix > 36)
+    {
+      *dst = 0;
+      return string;
+    }
+  if (radix == 10 && value < 0)
+    {
+      *dst++ = '-';
+      x = -value;
+    }
+  else
+    x = value;
+  i = 0;
+  do
+    {
+      n = x % radix;
+      digits[i++] = (n < 10 ? (char)n+'0' : (char)n-10+'a');
+      x /= radix;
+    } while (x != 0);
+  while (i > 0)
+    *dst++ = digits[--i];
+  *dst = 0;
+  return string;
+}
Index: trunk/src/emx/src/lib/conv/lltoa.c
===================================================================
--- trunk/src/emx/src/lib/conv/lltoa.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/lltoa.c	(revision 18)
@@ -0,0 +1,36 @@
+/* lltoa.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+char *_lltoa (long long value, char *string, int radix)
+{
+  char *dst;
+  char digits[64];
+  unsigned long long x;
+  int i, n;
+  
+  dst = string;
+  if (radix < 2 || radix > 36)
+    {
+      *dst = 0;
+      return string;
+    }
+  if (radix == 10 && value < 0)
+    {
+      *dst++ = '-';
+      x = -value;
+    }
+  else
+    x = value;
+  i = 0;
+  do
+    {
+      n = x % radix;
+      digits[i++] = (n < 10 ? (char)n+'0' : (char)n-10+'a');
+      x /= radix;
+    } while (x != 0);
+  while (i > 0)
+    *dst++ = digits[--i];
+  *dst = 0;
+  return string;
+}
Index: trunk/src/emx/src/lib/conv/ltoa.c
===================================================================
--- trunk/src/emx/src/lib/conv/ltoa.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/ltoa.c	(revision 18)
@@ -0,0 +1,36 @@
+/* ltoa.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+char *_ltoa (long value, char *string, int radix)
+{
+  char *dst;
+  char digits[32];
+  unsigned long x;
+  int i, n;
+  
+  dst = string;
+  if (radix < 2 || radix > 36)
+    {
+      *dst = 0;
+      return string;
+    }
+  if (radix == 10 && value < 0)
+    {
+      *dst++ = '-';
+      x = -value;
+    }
+  else
+    x = value;
+  i = 0;
+  do
+    {
+      n = x % radix;
+      digits[i++] = (n < 10 ? (char)n+'0' : (char)n-10+'a');
+      x /= radix;
+    } while (x != 0);
+  while (i > 0)
+    *dst++ = digits[--i];
+  *dst = 0;
+  return string;
+}
Index: trunk/src/emx/src/lib/conv/makefile
===================================================================
--- trunk/src/emx/src/lib/conv/makefile	(revision 18)
+++ trunk/src/emx/src/lib/conv/makefile	(revision 18)
@@ -0,0 +1,97 @@
+#
+# /emx/src/lib/conv/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+BIH=$(I)emx/bigint.h
+
+.IF $(LIBNAME)
+
+local: ;
+
+.ELSE
+
+local: bipow5.tab
+
+bipow5.tab: makepow5.exe
+	makepow5 -o bipow5.tab -s -m325 4951
+
+makepow5.exe: makepow5.c bisetw.c c/bimulbw.c $(BIH)
+	gcc -Wall -o makepow5.exe makepow5.c bisetw.c c/bimulbw.c
+
+.ENDIF
+
+atod.o: atod.c $(I)stdlib.h $(I)ctype.h $(I)math.h $(I)float.h \
+		$(I)locale.h $(ERRNO) $(I)assert.h $(BIH) $(I)emx/float.h \
+		$(I)emx/locale.h
+atof.o: atof.c $(I)math.h $(I)stdlib.h
+atofl.o: atofl.c $(I)stdlib.h
+atoi.o: atoi.c $(I)stdlib.h
+atol.o: atol.c $(I)stdlib.h
+atoll.o: atoll.c $(I)stdlib.h
+dtoa.o: dtoa.c $(I)math.h $(I)float.h $(I)assert.h \
+		$(BUILTIN) $(I)emx/float.h $(BIH)
+gcvt.o: gcvt.c $(I)stdlib.h $(I)string.h $(I)math.h $(I)float.h $(I)locale.h \
+		$(I)emx/float.h $(I)emx/locale.h
+itoa.o: itoa.c $(I)stdlib.h
+lltoa.o: lltoa.c $(I)stdlib.h
+ltoa.o: ltoa.c $(I)stdlib.h
+remzeros.o: remzeros.c $(I)string.h $(I)emx/float.h
+smalatod.o: smalatod.c $(I)stdlib.h $(I)math.h $(I)float.h $(I)locale.h \
+		$(I)ctype.h $(ERRNO) $(I)emx/float.h $(I)emx/locale.h
+smaldtoa.o: smaldtoa.c $(I)stdlib.h $(I)string.h $(I)math.h $(I)float.h \
+		$(I)emx/float.h
+strtod.o: strtod.c $(I)math.h $(I)float.h $(I)stdlib.h $(I)emx/float.h
+strtof.o: strtof.c $(I)math.h $(I)float.h $(I)stdlib.h $(I)emx/float.h
+strtol.o: strtol.c $(I)stdlib.h $(I)limits.h $(I)ctype.h $(ERRNO)
+strtold.o: strtold.c $(I)math.h $(I)float.h $(I)stdlib.h $(I)emx/float.h
+ulltoa.o: ulltoa.c $(I)stdlib.h
+ultoa.o: ultoa.c $(I)stdlib.h
+
+strtoul.o: ../strtol.c $(I)stdlib.h $(I)limits.h $(I)ctype.h $(ERRNO)
+	$(GCC) -c -DUNSIGNED -o strtoul.o ../strtol.c
+
+strtoll.o: ../strtol.c $(I)stdlib.h $(I)limits.h $(I)ctype.h $(ERRNO)
+	$(GCC) -c -DLONG_LONG -o strtoll.o ../strtol.c
+
+strtoull.o: ../strtol.c $(I)stdlib.h $(I)limits.h $(I)ctype.h $(ERRNO)
+	$(GCC) -c -DLONG_LONG -DUNSIGNED -o strtoull.o ../strtol.c
+
+bicmpbb.o: bicmpbb.c $(BIH)
+bicmpp2.o: bicmpp2.c $(BIH)
+bidivbb.o: bidivbb.c $(I)assert.h $(BUILTIN) $(BIH)
+bidivp2.o: bidivp2.c $(I)assert.h $(BIH)
+bifls.o: bifls.c $(I)string.h $(BUILTIN) $(BIH)
+bihdivb.o: bihdivb.c $(I)assert.h $(BIH)
+bipow5.o: bipow5.c $(I)stdlib.h $(I)assert.h $(BIH) ../bipow5.tab
+bisetb.o: bisetb.c $(I)string.h $(BIH)
+bisetd.o: bisetd.c $(BIH)
+bisetw.o: bisetw.c $(BIH)
+bishlb.o: bishlb.c $(BIH)
+bishlw.o: bishlw.c $(BIH)
+bishrb.o: bishrb.c $(BIH)
+biwdivp2.o: biwdivp2.c $(I)assert.h $(BIH)
+
+biaddbb.o: biaddbb.s $(ASM386H)
+bidivbw.o: bidivbw.s $(ASM386H)
+bidivhlp.o: bidivhlp.s $(ASM386H)
+bimulbb.o: bimulbb.s $(ASM386H)
+bimulbw.o: bimulbw.s $(ASM386H)
+bisubmbw.o: bisubmbw.s $(ASM386H)
+
+# biaddbb.o: biaddbb.c $(BIH)
+# bidivbw.o: bidivbw.c $(BIH)
+# bidivhlp.o: bidivhlp.c $(I)stdlib.h $(BIH)
+# bimulbb.o: bimulbb.c $(I)assert.h $(BIH)
+# bimulbw.o: bimulbw.c $(BIH)
+# bisubmbw.o: bisubmbw.c $(BIH)
+
+$(DSTLIB): atof.o atofl.o atoi.o atol.o atoll.o gcvt.o \
+    itoa.o lltoa.o ltoa.o remzeros.o \
+    strtod.o strtof.o strtol.o strtold.o strtoll.o strtoul.o strtoull.o \
+    ulltoa.o ultoa.o \
+    dtoa.o atod.o smaldtoa.o smalatod.o \
+    biaddbb.o bicmpbb.o bicmpp2.o bidivbb.o bidivbw.o bidivhlp.o \
+    bidivp2.o bifls.o bihdivb.o bimulbb.o bimulbw.o bipow5.o bisetb.o \
+    bisetd.o bisetw.o bishlb.o bishlw.o bishrb.o bisubmbw.o biwdivp2.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/conv/makepow5.c
===================================================================
--- trunk/src/emx/src/lib/conv/makepow5.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/makepow5.c	(revision 18)
@@ -0,0 +1,281 @@
+/* makepow5.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <emx/bigint.h>
+
+static const char *out_fname;
+static int single_prec;
+static int long_mul_threshold;
+static int max_exponent;
+static int short_factor;
+static int long_factor;
+
+struct power
+{
+  int n;
+  int i;
+};
+
+static struct power *powers;
+static _bi_word *words;
+static int words_used;
+static int words_alloc;
+
+
+static void usage (void)
+{
+  puts ("makepow5 -- Copyright (c) 1996 by Eberhard Mattes\n");
+  puts ("Usage:");
+  puts ("  makepow5 [-o <output_file>] [-s] [-m <threshold>] <max_exponent>");
+  exit (1);
+}
+
+
+static void out_of_memory (void)
+{
+  fprintf (stderr, "Out of memory\n");
+  exit (2);
+}
+
+
+static void compute_all_powers (void)
+{
+  int i, j, bw;
+  _bi_bigint b;
+
+  powers = malloc ((max_exponent + 1) * sizeof (_bi_bigint));
+  if (powers == NULL)
+    out_of_memory ();
+
+  words_used = 0; words_alloc = max_exponent;
+  words = malloc (words_alloc * sizeof (_bi_word));
+  if (words == NULL)
+    out_of_memory ();
+
+  bw = _BI_WORDS ((max_exponent + 1) * 3);
+  b.v = malloc (bw * sizeof (_bi_word));
+  if (b.v == NULL)
+    out_of_memory ();
+
+  if (_bi_set_w (&b, bw, 1) != 0)
+    abort ();
+  powers[0].n = b.n;
+  powers[0].i = words_used;
+  words[words_used++] = b.v[0];
+
+  fprintf (stderr, "Computing powers of 5...\n");
+  for (i = 1; i <= max_exponent; ++i)
+    {
+      if (_bi_mul_bw (&b, bw, &b, 5) != 0)
+        abort ();
+      if (words_used + b.n > words_alloc)
+        {
+          words_alloc *= 2;
+          words = realloc (words, words_alloc * sizeof (_bi_word));
+          if (words == NULL)
+            out_of_memory ();
+        }
+      powers[i].n = b.n;
+      powers[i].i = words_used;
+      for (j = 0; j < b.n; ++j)
+        words[words_used++] = b.v[j];
+    }
+
+  fprintf (stderr, "Table size: %d words\n", words_used);
+
+  if (single_prec)
+    {
+      unsigned long long x = 5;
+      short_factor = 1;
+      while (x == (_bi_word)x)
+        {
+          x *= 5;
+          ++short_factor;
+        }
+    }
+  else
+    short_factor = 1;
+}
+
+
+static void find_size (int factor, int *psize2, int *psize3)
+{
+  int i, size2, size3;
+
+  size2 = size3 = 0;
+  for (i = short_factor; i < factor; i += short_factor)
+    size2 += powers[i].n + 1;
+  for (i = factor; i <= max_exponent; i += factor)
+    size3 += powers[i].n + 1;
+  *psize2 = size2; *psize3 = size3;
+}
+
+
+static void optimize (void)
+{
+  int i, size2, size3, best_factor, best_size2, best_size3;
+
+  fprintf (stderr, "Optimizing...\n");
+  best_factor = short_factor * ((max_exponent + short_factor - 1)
+                                / short_factor);
+  find_size (best_factor, &best_size2, &best_size3);
+  for (i = short_factor * ((long_mul_threshold + short_factor - 1)
+                           / short_factor);
+       i < max_exponent; i += short_factor)
+    {
+      find_size (i, &size2, &size3);
+      if (size2 + size3 < best_size2 + best_size3)
+        {
+          best_factor = i; best_size2 = size2; best_size3 = size3;
+        }
+    }
+  long_factor = best_factor;
+  fprintf (stderr, "Table 1:     %4d entries, %4d words\n",
+           short_factor - 1, short_factor - 1);
+  fprintf (stderr, "Table 2 & 4: %4d entries, %4d words\n",
+           (best_factor - short_factor) / short_factor, best_size2);
+  fprintf (stderr, "Table 3 & 4: %4d entries, %4d words\n",
+           (max_exponent + 1) / best_factor, best_size3);
+  fprintf (stderr, "Total size:                %4d words\n",
+           best_size2 + best_size3 + short_factor);
+}
+
+
+static void write_output (void)
+{
+  FILE *f;
+  int i, j, index;
+  _bi_word s;
+
+  fprintf (stderr, "Writing output file...\n");
+  f = fopen (out_fname, "w");
+  if (f == NULL)
+    {
+      perror (out_fname);
+      exit (2);
+    }
+  fprintf (f, "/* %s */\n\n", out_fname);
+  fprintf (f, "/* This file has been generated with\n       makepow5 -o %s ",
+           out_fname);
+  if (single_prec != 0)
+    fprintf (f, "-s ");
+  if (long_mul_threshold != 0)
+    fprintf (f, "-m%d ", long_mul_threshold);
+  fprintf (f, "%d\n   Please do not edit this file! */\n\n", max_exponent);
+
+  if (short_factor != 1)
+    fprintf (f, "#define TABLE1_SIZE      %d\n", short_factor - 1);
+  fprintf (f, "#define TABLE2_SIZE      %d\n",
+           (long_factor - short_factor) / short_factor);
+  if (long_factor <= max_exponent)
+    fprintf (f, "#define TABLE3_SIZE      %d\n",
+             (max_exponent + 1) / long_factor);
+
+  fprintf (f, "\n");
+  if (short_factor != 1)
+    {
+      fprintf (f, "static const _bi_word table1[] =\n{\n");
+      s = 5;
+      for (i = 1; i < short_factor; ++i)
+        {
+          fprintf (f, "  %lu, /* 5^%d */\n", s, i);
+          s *= 5;
+        }
+      fprintf (f, "};\n\n");
+    }
+
+  fprintf (f, "static const int table2[] =\n{\n");
+
+  index = 0;
+  for (i = short_factor; i < long_factor; i += short_factor)
+    {
+      fprintf (f, "  %d, /* 5^%d */\n", index, i);
+      index += powers[i].n;
+    }
+  fprintf (f, "  %d\n", index);
+  fprintf (f, "};\n\n");
+
+  if (long_factor <= max_exponent)
+    {
+      fprintf (f, "static const int table3[] =\n{\n");
+      for (i = long_factor; i <= max_exponent; i += long_factor)
+        {
+          fprintf (f, "  %d, /* 5^%d */\n", index, i);
+          index += powers[i].n;
+        }
+      fprintf (f, "  %d\n", index);
+      fprintf (f, "};\n\n");
+    }
+
+  fprintf (f, "static const _bi_word table4[] =\n{\n");
+  for (i = short_factor; i < long_factor; i += short_factor)
+    {
+      fprintf (f, "/* 5^%d */\n", i);
+      for (j = 0; j < powers[i].n; ++j)
+        fprintf (f, "  0x%.8lx,\n", words[powers[i].i + j]);
+    }
+  if (long_factor <= max_exponent)
+    {
+      for (i = long_factor; i <= max_exponent; i += long_factor)
+        {
+          fprintf (f, "/* 5^%d */\n", i);
+          for (j = 0; j < powers[i].n; ++j)
+            fprintf (f, "  0x%.8lx,\n", words[powers[i].i + j]);
+        }
+    }
+  fprintf (f, "};\n");
+
+  if (fclose (f) != 0)
+    {
+      perror (out_fname);
+      remove (out_fname);
+    }
+}
+
+
+int main (int argc, char *argv[])
+{
+  int c;
+  char *end;
+
+  while ((c = getopt (argc, argv, "m:o:s")) != -1)
+    switch (c)
+      {
+      case 'm':
+        long_mul_threshold = strtol (optarg, &end, 10);
+        if (long_mul_threshold < 1 || *end != 0)
+          usage ();
+        break;
+
+      case 'o':
+        out_fname = optarg;
+        break;
+
+      case 's':
+        single_prec = 1;
+        break;
+
+      default:
+        usage ();
+      }
+
+  if (argc - optind != 1)
+    usage ();
+
+  max_exponent = strtol (argv[optind], &end, 10);
+  if (max_exponent < 1 || *end != 0)
+    usage ();
+
+  compute_all_powers ();
+  if (long_mul_threshold != 0)
+    optimize ();
+  else
+    long_factor = max_exponent + 1;
+
+  if (out_fname != NULL)
+    write_output ();
+
+  return 0;
+}
Index: trunk/src/emx/src/lib/conv/remzeros.c
===================================================================
--- trunk/src/emx/src/lib/conv/remzeros.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/remzeros.c	(revision 18)
@@ -0,0 +1,17 @@
+/* remzeros.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <emx/float.h>
+
+/* Remove trailing zeros from DIGITS for the "%g" format.  Keep at
+   least KEEP digits at the start of DIGITS. */
+
+void __remove_zeros (char *digits, int keep)
+{
+  int i;
+
+  i = strlen (digits) - 1;
+  while (i >= keep && digits[i] == '0')
+    --i;
+  digits[i+1] = 0;
+}
Index: trunk/src/emx/src/lib/conv/smalatod.c
===================================================================
--- trunk/src/emx/src/lib/conv/smalatod.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/smalatod.c	(revision 18)
@@ -0,0 +1,225 @@
+/* smalatod.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include <locale.h>
+#include <ctype.h>
+#include <errno.h>
+#include <emx/float.h>
+#include <emx/locale.h>
+
+
+const char * __small_atod (long double *p_result, const char *string,
+                           int min_exp, int max_exp, int bias,
+                           int mant_dig, int decimal_dig,
+                           int max_10_exp, int min_den_10_exp)
+{
+  const unsigned char *s, *end;
+  long double x, lim;
+  long scale;
+  char ok, dot, neg;
+  int fpclass;
+  union
+  {
+    long double ld;
+    struct
+    {
+      unsigned long long mant;
+      unsigned short exp;
+    } x;
+  } z;
+
+  s = end = string;
+
+  switch (mant_dig)
+    {
+    case 24:
+      lim = FLT_MAX / 10.0;
+      break;
+    case 53:
+      lim = DBL_MAX / 10.0;
+      break;
+    case 64:
+      lim = LDBL_MAX / 10.0L;
+      break;
+    default:
+      *p_result = NAN;
+      return string;
+    }
+
+  while (isspace (*s))
+    ++s;
+  neg = 0;
+  if (*s == '+')
+    ++s;
+  else if (*s == '-')
+    {
+      neg = 1; ++s;
+    }
+
+  if ((s[0] == 'i' || s[0] == 'I')
+      && (s[1] == 'n' || s[1] == 'N')
+      && (s[2] == 'f' || s[2] == 'F'))
+    {
+      s += 3;
+      if ((s[0] == 'i' || s[0] == 'I')
+          && (s[1] == 'n' || s[1] == 'N')
+          && (s[2] == 'i' || s[2] == 'I')
+          && (s[3] == 't' || s[3] == 'T')
+          && (s[4] == 'y' || s[4] == 'Y'))
+        s += 5;
+      *p_result = neg ? -INFINITY : INFINITY;
+      return s;
+    }
+  else if ((s[0] == 'n' || s[0] == 'N')
+           && (s[1] == 'a' || s[1] == 'A')
+           && (s[2] == 'n' || s[2] == 'N'))
+    {
+      s += 3;
+      end = s;
+      if (end[0] == '(')
+        {
+          ++end;
+          while (*end == '_' || (*end >= '0' && *end <= '9')
+                 || (*end >= 'a' && *end <= 'z')
+                 || (*end >= 'A' && *end <= 'Z'))
+            ++end;
+          if (*end == ')')
+            ++end;
+          else
+            end = s;
+        }
+      *p_result = NAN;
+      return end;
+    }
+
+  /* Scan the entire mantissa, updating SCALE. */
+
+  ok = dot = 0;
+  x = 0.0; scale = 0;
+  for (;;)
+    {
+      if (*s == (unsigned char)_cur_lconv.decimal_point[0] && !dot)
+        {
+          dot = 1;
+          ++s;
+        }
+      else if (isdigit (*s))
+        {
+          ok = 1;
+          if (x > lim)
+            ++scale;            /* Overflow */
+          else
+            x = x * 10.0L + (*s - '0');
+          ++s;
+          if (dot)
+            --scale;
+        }
+      else
+        break;
+    }
+
+  if (!ok)
+    {
+      *p_result = 0.0;
+      return string;
+    }
+
+  /* Scan the exponent. */
+
+  end = s;
+  if (*s == 'e' || *s == 'E')
+    {
+      char eneg;
+
+      ++s; eneg = 0;
+      if (*s == '+')
+        ++s;
+      else if (*s == '-')
+        {
+          eneg = 1; ++s;
+        }
+      if (isdigit (*s))         /* Note: strtol() skips whitespace! */
+        {
+          int saved_errno;
+          long exp;
+          const unsigned char *q;
+
+          saved_errno = errno; errno = 0;
+          exp = strtol (s, (char **)&q, 10);
+          if (errno == ERANGE)
+            {
+              /* If the exponent overflows, we need a *very* long
+                 mantissa to get a valid number.  Such a mantissa
+                 doesn't fit into memory. */
+
+              end = q;
+              if (eneg)
+                goto underflow;
+              else
+                goto overflow;
+            }
+          else if (errno == 0 && q != s)
+            {
+              end = q;
+
+              /* TODO: check for integer overflow */
+
+              if (eneg)
+                scale -= exp;
+              else
+                scale += exp;
+            }
+          errno = saved_errno;
+        }
+    }
+
+  /* Apply the scaling factor and the exponent.  Don't do this if X is
+     0.0 to be able to detect underflow. */
+
+  if (x == 0.0 || scale == 0)
+    z.ld = x;
+  else
+    z.ld = x * _powl (10.0L, (long double)scale);
+
+  switch (mant_dig)
+    {
+    case 24:
+      fpclass = __fpclassifyf ((float)z.ld);
+      break;
+    case 53:
+      fpclass = __fpclassify ((double)z.ld);
+      break;
+    case 64:
+      fpclass = __fpclassifyl (z.ld);
+      break;
+    default:
+      fpclass = FP_NAN;
+      break;
+    }
+
+  switch (fpclass)
+    {
+    case FP_ZERO:
+      if (x != 0.0)
+        errno = ERANGE;
+      break;
+    case FP_INFINITE:
+      errno = ERANGE;
+      break;
+    }
+
+  *p_result = neg ? -z.ld : z.ld;
+  return end;
+
+overflow:
+  *p_result = neg ? -HUGE_VALL : HUGE_VALL;
+  errno = ERANGE;
+  return end;
+
+underflow:
+  *p_result = neg ? -0.0 : 0.0;
+  errno = ERANGE;
+  return end;
+}
Index: trunk/src/emx/src/lib/conv/smaldtoa.c
===================================================================
--- trunk/src/emx/src/lib/conv/smaldtoa.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/smaldtoa.c	(revision 18)
@@ -0,0 +1,112 @@
+/* smalldtoa.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <emx/float.h>
+
+
+/* Convert a positive floating point number to a string of decimal
+   digits and an exponent.  The position of the decimal point is
+   assumed to be after the first digit.  Examples:
+
+   1234567890123456789 --> 1234567890123456789, xp = 18
+   123                 --> 1230000000000000000, xp =  2
+   12                  --> 1200000000000000000, xp =  1
+   1.2                 --> 1200000000000000000, xp =  0
+   0.12                --> 1200000000000000000, xp = -1
+
+   This function assumes that
+
+     LDBL_MANT_DIG <= 8 * sizeof (unsigned long long)
+
+   which is true for the extended real format (64-bit mantissa).
+   There are algorithms which are more precise, but they're more
+   complicated. */
+
+char *__small_dtoa (char *buffer, int *p_exp,
+                    long double x, int ndigits, int fmt, int dig)
+{
+  long double scaled;
+  unsigned long long intg;
+  int xp, len, a, i, next;
+
+  xp = (int)_floorl (_log10l (x));
+
+  if (LDBL_DIG - 1 - xp < LDBL_MAX_10_EXP)
+    {
+      /* This is the normal case. */
+
+      scaled = x * _powl (10.0, LDBL_DIG - 1 - xp);
+    }
+  else
+    {
+      /* Avoid overflow in _powl() for X near LDBL_MIN. */
+
+      scaled = (_powl (10.0, LDBL_DIG - 1 - xp - (LDBL_MAX_10_EXP - 1))
+                * (x * _powl (10.0, LDBL_MAX_10_EXP - 1)));
+    }
+
+  intg = (unsigned long long)scaled;
+  buffer[0] = '0';
+  _ulltoa (intg, buffer + 1, 10);
+
+  switch (fmt)
+    {
+    case DTOA_PRINTF_E:
+      a = ndigits + 1;
+      break;
+    case DTOA_PRINTF_F:
+      if (xp >= 0)
+        a = xp + 1 + ndigits;
+      else
+        a = ndigits;
+      break;
+    case DTOA_PRINTF_G:
+    case DTOA_GCVT:
+      a = ndigits;
+      break;
+    default:
+      abort ();
+    }
+  if (a > dig)
+    a = dig;
+
+  len = strlen (buffer + 1);
+  xp += len - LDBL_DIG;
+  if (len > a)
+    {
+      /* Round. */
+
+      next = 0;
+      if (buffer[a+1] > '5')
+        next = 1;
+      else if (buffer[a+1] == '5')
+        {
+          i = a + 2;
+          while (buffer[i] == '0')
+            ++i;
+          next = (buffer[i] != 0 || (buffer[a] & 1));
+        }
+      if (next)
+        while (++buffer[a] > '9')
+          --a;
+    }
+
+  i = a + 1;
+  while (i < DECIMAL_DIG + 1)
+    buffer[i++] = '0';
+  buffer[i] = 0;
+
+  if (buffer[0] != '0')
+    {
+      *p_exp = xp + 1;
+      return buffer;
+    }
+  else
+    {
+      *p_exp = xp;
+      return buffer + 1;
+    }
+}
Index: trunk/src/emx/src/lib/conv/strtod.c
===================================================================
--- trunk/src/emx/src/lib/conv/strtod.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/strtod.c	(revision 18)
@@ -0,0 +1,18 @@
+/* strtod.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include <emx/float.h>
+
+double strtod (const char *string, char **end_ptr)
+{
+  const char *end;
+  long double z;
+
+  end = __atod (&z, string, DBL_MIN_EXP, DBL_MAX_EXP, 1023,
+                DBL_MANT_DIG, DECIMAL_DIG, DBL_MAX_10_EXP, -324);
+  if (end_ptr != NULL)
+    *end_ptr = (char *)end;
+  return (double)z;
+}
Index: trunk/src/emx/src/lib/conv/strtof.c
===================================================================
--- trunk/src/emx/src/lib/conv/strtof.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/strtof.c	(revision 18)
@@ -0,0 +1,18 @@
+/* strtof.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include <emx/float.h>
+
+float _strtof (const char *string, char **end_ptr)
+{
+  const char *end;
+  long double z;
+
+  end = __atod (&z, string, FLT_MIN_EXP, FLT_MAX_EXP, 127,
+                FLT_MANT_DIG, DECIMAL_DIG, FLT_MAX_10_EXP, -45);
+  if (end_ptr != NULL)
+    *end_ptr = (char *)end;
+  return (float)z;
+}
Index: trunk/src/emx/src/lib/conv/strtol.c
===================================================================
--- trunk/src/emx/src/lib/conv/strtol.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/strtol.c	(revision 18)
@@ -0,0 +1,127 @@
+/* strtol.c (emx+gcc) -- Copyright (c) 1990-2001 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+
+#ifdef LONG_LONG
+#define UTYPE   unsigned long long
+#ifdef UNSIGNED
+#define NAME    _strtoull
+#define TYPE    unsigned long long
+#define MAX     ULLONG_MAX
+#else
+#define NAME    _strtoll
+#define TYPE    long long
+#define MAX     LLONG_MAX
+#define MIN     LLONG_MIN
+#endif
+#else
+#define UTYPE   unsigned long
+#ifdef UNSIGNED
+#define NAME    strtoul
+#define TYPE    unsigned long
+#define MAX     ULONG_MAX
+#else
+#define NAME    strtol
+#define TYPE    long
+#define MAX     LONG_MAX
+#define MIN     LONG_MIN
+#endif
+#endif
+
+TYPE NAME (const char *string, char **end_ptr, int radix)
+{
+  const unsigned char *s;
+  char neg, pfx;
+  TYPE result;
+
+  s = (const unsigned char *)string;
+  while (isspace (*s))
+    ++s;
+
+  neg = 0; pfx = 0;
+  if (*s == '-')
+    {
+      neg = 1; ++s;
+    }
+  else if (*s == '+')
+    ++s;
+
+  if ((radix == 0 || radix == 16) && s[0] == '0'
+      && (s[1] == 'x' || s[1] == 'X'))
+    {
+      radix = 16; s += 2; pfx = 1;
+    }
+  if (radix == 0)
+    radix = (s[0] == '0' ? 8 : 10);
+
+  result = 0;                   /* Keep the compiler happy */
+  if (radix >= 2 && radix <= 36)
+    {
+      UTYPE n, max1, max2, lim;
+      enum {no_number, ok, overflow} state;
+      unsigned char c;
+
+#ifdef UNSIGNED
+      lim = MAX;
+#else
+      lim = (neg ? -(UTYPE)MIN : MAX);
+#endif
+      max1 = lim / radix;
+      max2 = lim - max1 * radix;
+      n = 0; state = no_number;
+      for (;;)
+        {
+          c = *s;
+          if (c >= '0' && c <= '9')
+            c = c - '0';
+          else if (c >= 'A' && c <= 'Z')
+            c = c - 'A' + 10;
+          else if (c >= 'a' && c <= 'z')
+            c = c - 'a' + 10;
+          else
+            break;
+          if (c >= radix)
+            break;
+          if (n >= max1 && (n > max1 || (UTYPE)c > max2))
+            state = overflow;
+          if (state != overflow)
+            {
+              n = n * radix + (UTYPE)c;
+              state = ok;
+            }
+          ++s;
+        }
+      switch (state)
+        {
+        case no_number:
+          result = 0;
+          s = (const unsigned char *)string;
+          if (pfx)
+            ++s;                /* At least eat the 0 of "0x" */
+          /* Don't set errno!? */
+          break;
+        case ok:
+          result = (neg ? -n : n);
+          break;
+        case overflow:
+#ifdef UNSIGNED
+          result = MAX;
+#else
+          result = (neg ? MIN : MAX);
+#endif
+          errno = ERANGE;
+          break;
+        }
+    }
+  else
+    {
+      result = 0;
+      errno = EDOM;
+    }
+  if (end_ptr != NULL)
+    *end_ptr = (char *)s;
+  return result;
+}
Index: trunk/src/emx/src/lib/conv/strtold.c
===================================================================
--- trunk/src/emx/src/lib/conv/strtold.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/strtold.c	(revision 18)
@@ -0,0 +1,18 @@
+/* strtold.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include <emx/float.h>
+
+long double _strtold (const char *string, char **end_ptr)
+{
+  const char *end;
+  long double z;
+
+  end = __atod (&z, string, LDBL_MIN_EXP, LDBL_MAX_EXP, 16383,
+                LDBL_MANT_DIG, DECIMAL_DIG, LDBL_MAX_10_EXP, -4951);
+  if (end_ptr != NULL)
+    *end_ptr = (char *)end;
+  return z;
+}
Index: trunk/src/emx/src/lib/conv/ulltoa.c
===================================================================
--- trunk/src/emx/src/lib/conv/ulltoa.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/ulltoa.c	(revision 18)
@@ -0,0 +1,28 @@
+/* ulltoa.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+char *_ulltoa (unsigned long long value, char *string, int radix)
+{
+  char *dst;
+  char digits[64];
+  int i, n;
+  
+  dst = string;
+  if (radix < 2 || radix > 36)
+    {
+      *dst = 0;
+      return string;
+    }
+  i = 0;
+  do
+    {
+      n = value % radix;
+      digits[i++] = (n < 10 ? (char)n+'0' : (char)n-10+'a');
+      value /= radix;
+    } while (value != 0);
+  while (i > 0)
+    *dst++ = digits[--i];
+  *dst = 0;
+  return string;
+}
Index: trunk/src/emx/src/lib/conv/ultoa.c
===================================================================
--- trunk/src/emx/src/lib/conv/ultoa.c	(revision 18)
+++ trunk/src/emx/src/lib/conv/ultoa.c	(revision 18)
@@ -0,0 +1,28 @@
+/* ultoa.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+char *_ultoa (unsigned long value, char *string, int radix)
+{
+  char *dst;
+  char digits[32];
+  int i, n;
+  
+  dst = string;
+  if (radix < 2 || radix > 36)
+    {
+      *dst = 0;
+      return string;
+    }
+  i = 0;
+  do
+    {
+      n = value % radix;
+      digits[i++] = (n < 10 ? (char)n+'0' : (char)n-10+'a');
+      value /= radix;
+    } while (value != 0);
+  while (i > 0)
+    *dst++ = digits[--i];
+  *dst = 0;
+  return string;
+}
Index: trunk/src/emx/src/lib/emx_386/accept.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/accept.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/accept.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/accept.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___accept
+
+/ int __accept (int handle, struct sockaddr *addr, int *paddrlen)
+
+___accept:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* addr */
+        movl    4*4(%esp), %ecx         /* paddrlen */
+        movb    $0x41, %al              /* __accept */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__accept)
Index: trunk/src/emx/src/lib/emx_386/alarm.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/alarm.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/alarm.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/alarm.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___alarm
+
+/ unsigned __alarm (unsigned sec)
+
+        ALIGN
+
+___alarm:
+        movl    1*4(%esp), %edx
+        movb    $0x15, %al
+        SYSCALL (0x7f)
+        EPILOGUE (__alarm)
Index: trunk/src/emx/src/lib/emx_386/bind.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/bind.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/bind.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/bind.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___bind
+
+/ int __bind (int handle, struct sockaddr *addr, int addrlen)
+
+___bind:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* addr */
+        movl    4*4(%esp), %ecx         /* addrlen */
+        movb    $0x3d, %al              /* __bind */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__bind)
Index: trunk/src/emx/src/lib/emx_386/brk.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/brk.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/brk.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/brk.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___brk
+
+/ void *__brk (void *addr)
+
+        ALIGN
+
+___brk:
+        movl    1*4(%esp), %edx
+        movb    $1, %al
+        SYSCALL (0x7f)
+        cmpl    $-1, %eax
+        jne     1f
+        SET_ERRNO ($ENOMEM)
+        movl    $-1, %eax
+1:      EPILOGUE (__brk)
Index: trunk/src/emx/src/lib/emx_386/cgets.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/cgets.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/cgets.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/cgets.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___cgets
+
+/ void __cgets (char *buffer)
+
+        ALIGN
+
+___cgets:
+        movl    1*4(%esp), %edx
+        SYSCALL (0x0a)
+        EPILOGUE (__cgets)
Index: trunk/src/emx/src/lib/emx_386/chdir.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/chdir.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/chdir.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/chdir.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___chdir
+
+/ int __chdir (const char *name)
+
+        ALIGN
+
+___chdir:
+        movl    1*4(%esp), %edx
+        SYSCALL (0x3b)
+        SET_0
+        EPILOGUE (__chdir)
Index: trunk/src/emx/src/lib/emx_386/chdrive.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/chdrive.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/chdrive.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/chdrive.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___chdrive
+
+/ int __chdrive (char drive)
+
+        ALIGN
+
+___chdrive:
+        movb    1*4(%esp), %dl          /* drive */
+        cmpb    $0x61, %dl
+        jb      1f
+        subb    $0x20, %dl
+1:      subb    $0x41, %dl
+        SYSCALL (0x0e)
+        xorl    %eax, %eax
+        EPILOGUE (__chdrive)
Index: trunk/src/emx/src/lib/emx_386/chmod.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/chmod.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/chmod.s	(revision 18)
@@ -0,0 +1,23 @@
+/ emx_386/chmod.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___chmod
+
+/ int __chmod (char *name, int flag, int attr)
+
+        ALIGN
+
+___chmod:
+        movl    1*4(%esp), %edx         /* name */
+        movb    2*4(%esp), %al          /* flag */
+        movl    3*4(%esp), %ecx         /* attr */
+        SYSCALL (0x43)
+        jb      1f
+        movzwl  %cx, %eax
+        jmp     2f
+
+1:      SET_ERRNO (%eax)
+        movl    $-1, %eax
+2:      EPILOGUE (__chmod)
Index: trunk/src/emx/src/lib/emx_386/chsize.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/chsize.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/chsize.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/chsize.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___chsize
+
+/ int __chsize (int handle, long length)
+
+        ALIGN
+
+___chsize:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* length */
+        movb    $0x18, %al
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_0
+        EPILOGUE (__chsize)
Index: trunk/src/emx/src/lib/emx_386/clock.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/clock.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/clock.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/clock.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___clock
+
+/ long long __clock (void)
+
+        ALIGN
+
+___clock:
+        movb    $0x26, %al              /* __clock */
+        SYSCALL (0x7f)
+        EPILOGUE (__clock)
Index: trunk/src/emx/src/lib/emx_386/close.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/close.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/close.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/close.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___close
+
+/ __close (int handle)
+
+        ALIGN
+
+___close:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        SYSCALL (0x3e)
+        popl    %ebx
+        SET_0
+        EPILOGUE (__close)
Index: trunk/src/emx/src/lib/emx_386/connect.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/connect.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/connect.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/connect.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___connect
+
+/ int __connect (int handle, struct sockaddr *addr, int addrlen)
+
+___connect:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* addr */
+        movl    4*4(%esp), %ecx         /* addrlen */
+        movb    $0x42, %al              /* __connect */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__connect)
Index: trunk/src/emx/src/lib/emx_386/core.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/core.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/core.s	(revision 18)
@@ -0,0 +1,22 @@
+/ emx_386/core.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+/ WARNING: emx.dll depends on the stack frame of this function when
+/          dumping core
+        
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___core
+
+/ int __core (int handle)
+
+        ALIGN
+
+___core:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx
+        movb    $0x11, %al
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_0
+        EPILOGUE (__core)
Index: trunk/src/emx/src/lib/emx_386/dos.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/dos.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/dos.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/dosinit.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+/ In executables created with emxbind, the call to _dos_init will
+/ be fixed up at load time to _emx_init of emx.dll.  Under DOS,
+/ this dummy is called instead as there is no fixup.  This module
+/ must be linked statically to avoid having two fixups for the
+/ same location.
+        
+        .globl  __dos_init
+        .globl  __dos_syscall
+
+__dos_init:
+        ret     $4
+
+        .align  2, 0x90
+
+__dos_syscall:
+        int     $0x21
+        ret
Index: trunk/src/emx/src/lib/emx_386/dup.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/dup.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/dup.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/dup.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___dup
+
+/ int __dup (int handle)
+
+        ALIGN
+
+___dup:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        SYSCALL (0x45)
+        popl    %ebx
+        SET_EAX
+        EPILOGUE (__dup)
Index: trunk/src/emx/src/lib/emx_386/dup2.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/dup2.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/dup2.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/dup2.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___dup2
+
+/ int __dup2 (int handle1, int handle2)
+
+        ALIGN
+
+___dup2:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle1 */
+        movl    3*4(%esp), %ecx         /* handle2 */
+        SYSCALL (0x46)
+        popl    %ebx
+        SET_EAX
+        EPILOGUE (__dup2)
Index: trunk/src/emx/src/lib/emx_386/emx.imp
===================================================================
--- trunk/src/emx/src/lib/emx_386/emx.imp	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/emx.imp	(revision 18)
@@ -0,0 +1,9 @@
+;
+; emx.imp
+;
+_emx_init                       emx        1 R
+_emx_syscall                    emx        2 R
+_emx_16to32                     emx        3 1
+_emx_32to16                     emx        4 1
+_emx_thunk1                     emx        5 2
+_emx_exception                  emx        6 4
Index: trunk/src/emx/src/lib/emx_386/emx_ver.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/emx_ver.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/emx_ver.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/emx_ver.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___emx_version
+
+        ALIGN
+
+___emx_version:
+        pushl   %ebx
+        movb    $0x0a, %al
+        SYSCALL (0x7f)
+        movl    %ebx, %edx
+        popl    %ebx
+        EPILOGUE (__emx_version)
Index: trunk/src/emx/src/lib/emx_386/emxio.imp
===================================================================
--- trunk/src/emx/src/lib/emx_386/emxio.imp	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/emxio.imp	(revision 18)
@@ -0,0 +1,21 @@
+;
+; emxio.imp
+;
+_inp8                           emxio      1   1
+_outp8                          emxio      2   2
+_inp16                          emxio      3   1
+_outp16                         emxio      4   2
+_inp32                          emxio      5   1
+_outp32                         emxio      6   2
+_inps8                          emxio      7   3
+_outps8                         emxio      8   3
+_outpt                          emxio      9   1
+_inps16                         emxio      10  3
+_outps16                        emxio      11  3
+_inps32                         emxio      12  3
+_outps32                        emxio      13  3
+_wait01                         emxio      14  2
+_wait10                         emxio      15  2
+_wait0                          emxio      16  2
+_wait1                          emxio      17  2
+_outps8dac                      emxio      18  3
Index: trunk/src/emx/src/lib/emx_386/endthrea.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/endthrea.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/endthrea.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/endthrea.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___endthread
+
+/ int __endthread (int tid)
+
+        ALIGN
+
+___endthread:
+        movl    1*4(%esp), %edx         /* tid */
+        movb    $0x2d, %al              /* __endthread */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__endthread)
Index: trunk/src/emx/src/lib/emx_386/execname.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/execname.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/execname.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/execname.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___execname
+
+/ int __execname (char *dst, size_t size)
+
+___execname:
+        movl    1*4(%esp), %edx         /* dst */
+        movl    2*4(%esp), %ecx         /* size */
+        movb    $0x33, %al              /* execname */
+        SYSCALL (0x7f)
+        EPILOGUE (__execname)
Index: trunk/src/emx/src/lib/emx_386/exit.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/exit.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/exit.s	(revision 18)
@@ -0,0 +1,12 @@
+/ emx_386/exit.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___exit
+
+        ALIGN
+
+___exit:
+        SYSCALL (0x4c)
+L1:     jmp     L1
Index: trunk/src/emx/src/lib/emx_386/fcntl.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/fcntl.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/fcntl.s	(revision 18)
@@ -0,0 +1,21 @@
+/ emx_386/fcntl.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___fcntl
+
+/ int __fcntl (int handle, int request, int arg)
+
+        ALIGN
+
+___fcntl:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %ecx         /* request */
+        movl    4*4(%esp), %edx         /* arg */
+        movb    $0x19, %al              /* fcntl */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__fcntl)
Index: trunk/src/emx/src/lib/emx_386/filesys.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/filesys.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/filesys.s	(revision 18)
@@ -0,0 +1,21 @@
+/ emx_386/filesys.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___filesys
+
+/ int __filesys (const char *drive, char *name, size_t size)
+
+        ALIGN
+
+___filesys:
+        pushl   %edi
+        movl    2*4(%esp), %edx         /* drive */
+        movl    3*4(%esp), %edi         /* name */
+        movl    4*4(%esp), %ecx         /* size */
+        movb    $0x23, %al              /* __filesys */
+        SYSCALL (0x7f)
+        popl    %edi
+        SET_ERRNO_ECX
+        EPILOGUE (__filesys)
Index: trunk/src/emx/src/lib/emx_386/findfirs.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/findfirs.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/findfirs.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/findfirs.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___findfirst
+
+/ int __findfirst (const char *name, int attr, struct _find *fp)
+
+        ALIGN
+
+___findfirst:
+        pushl   %esi
+        movl    2*4(%esp), %edx
+        movl    3*4(%esp), %ecx
+        movl    4*4(%esp), %esi
+        SYSCALL (0x4e)
+        popl    %esi
+        SET_0
+        EPILOGUE (__findfirst)
Index: trunk/src/emx/src/lib/emx_386/findnext.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/findnext.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/findnext.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/findnext.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___findnext
+
+/ int __findnext (struct _find *fp)
+
+        ALIGN
+
+___findnext:
+        pushl   %esi
+        movl    2*4(%esp), %esi
+        SYSCALL (0x4f)
+        popl    %esi
+        SET_0
+        EPILOGUE (__findnext)
Index: trunk/src/emx/src/lib/emx_386/fork.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/fork.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/fork.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/fork.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___fork
+
+/ int __fork (void)
+
+        ALIGN
+
+___fork:
+        movb    $0x1c, %al              /* __fork */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__fork)
Index: trunk/src/emx/src/lib/emx_386/fstat.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/fstat.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/fstat.s	(revision 18)
@@ -0,0 +1,22 @@
+/ emx_386/fstat.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___fstat
+
+/ int __fstat (int handle, struct stat *buffer)
+
+        ALIGN
+
+___fstat:
+        pushl   %edi
+        pushl   %ebx
+        movl    3*4(%esp), %ebx         /* handle */
+        movl    4*4(%esp), %edi         /* buffer */
+        movb    $0x21, %al              /* __fstat */
+        SYSCALL (0x7f)
+        popl    %ebx
+        popl    %edi
+        SET_ERRNO_ECX
+        EPILOGUE (__fstat)
Index: trunk/src/emx/src/lib/emx_386/fsync.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/fsync.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/fsync.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/fsync.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___fsync
+
+/ int __fsync (int handle)
+
+        ALIGN
+
+___fsync:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movb    $0x1b, %al              /* __fsync */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__fsync)
Index: trunk/src/emx/src/lib/emx_386/ftime.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ftime.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ftime.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/ftime.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___ftime
+
+/ void __ftime (struct timeb *ptr)
+
+        ALIGN
+
+___ftime:
+        movl    1*4(%esp), %edx         /* ptr */
+        movb    $0x27, %al              /* __ftime */
+        SYSCALL (0x7f)
+        EPILOGUE (__ftime)
Index: trunk/src/emx/src/lib/emx_386/ftruncat.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ftruncat.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ftruncat.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/ftruncat.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___ftruncate
+
+/ int __ftruncate (int handle, long length)
+
+        ALIGN
+
+___ftruncate:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* length */
+        movb    $0x25, %al
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__ftruncate)
Index: trunk/src/emx/src/lib/emx_386/getcwd.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/getcwd.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/getcwd.s	(revision 18)
@@ -0,0 +1,22 @@
+/ emx_386/getcwd.s (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getcwd
+
+/ int __getcwd (char *buffer, char drive)
+
+        ALIGN
+
+___getcwd:
+        pushl   %esi
+        movl    2*4(%esp), %esi         /* buffer */
+        movb    3*4(%esp), %dl          /* drive */
+        cmpb    $0, %dl
+        je      1f
+        subb    $0x40, %dl
+1:      SYSCALL (0x47)
+        popl    %esi
+        SET_0
+        EPILOGUE (__getcwd)
Index: trunk/src/emx/src/lib/emx_386/getdrive.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/getdrive.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/getdrive.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/getdrive.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getdrive
+
+/ char __getdrive (void)
+
+        ALIGN
+
+___getdrive:
+        SYSCALL (0x19)
+        addb    $0x41, %al
+        movzbl  %al, %eax
+        EPILOGUE (__getdrive)
Index: trunk/src/emx/src/lib/emx_386/gethosti.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/gethosti.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/gethosti.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/gethosti.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___gethostid
+
+/ int __gethostid (int *dst)
+
+___gethostid:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* dst */
+        movb    $0x50, %al              /* __gethostid */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__gethostid)
Index: trunk/src/emx/src/lib/emx_386/gethostn.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/gethostn.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/gethostn.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/gethostn.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___gethostname
+
+/ int __gethostname (char *name, int len)
+
+___gethostname:
+        movl    1*4(%esp), %edx         /* name */
+        movl    2*4(%esp), %ecx         /* len */
+        movb    $0x4f, %al              /* __gethostname */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__gethostname)
Index: trunk/src/emx/src/lib/emx_386/getpeern.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/getpeern.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/getpeern.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/getpeern.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getpeername
+
+/ int __getpeername (int handle, struct sockaddr *name, int *pnamelen)
+
+___getpeername:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* name */
+        movl    4*4(%esp), %ecx         /* pnamelen */
+        movb    $0x46, %al              /* __getpeername */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__getpeername)
Index: trunk/src/emx/src/lib/emx_386/getpid.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/getpid.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/getpid.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/getpid.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getpid
+
+/ int __getpid (void)
+
+        ALIGN
+
+___getpid:
+        movb    $5, %al
+        SYSCALL (0x7f)
+        EPILOGUE (__getpid)
Index: trunk/src/emx/src/lib/emx_386/getppid.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/getppid.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/getppid.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/getppid.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getppid
+
+/ int __getppid (void)
+
+        ALIGN
+
+___getppid:
+        movb    $0x29, %al
+        SYSCALL (0x7f)
+        EPILOGUE (__getppid)
Index: trunk/src/emx/src/lib/emx_386/getsockh.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/getsockh.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/getsockh.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/getsockh.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getsockhandle
+
+/ int __getsockhandle (int handle)
+
+___getsockhandle:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movb    $0x3b, %al              /* __getsockhandle */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__getsockhandle)
Index: trunk/src/emx/src/lib/emx_386/getsockn.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/getsockn.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/getsockn.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/getsockn.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getsockname
+
+/ int __getsockname (int handle, struct sockaddr *name, int *pnamelen)
+
+___getsockname:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* name */
+        movl    4*4(%esp), %ecx         /* pnamelen */
+        movb    $0x45, %al              /* __getsockname */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__getsockname)
Index: trunk/src/emx/src/lib/emx_386/getsocko.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/getsocko.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/getsocko.s	(revision 18)
@@ -0,0 +1,26 @@
+/ emx_386/getsocko.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getsockopt
+
+/ int __getsockopt (int handle, int level, int optname, void *optval,
+/                   int *poptlen)
+
+___getsockopt:
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        movl    4*4(%esp), %ebx         /* handle */
+        movl    5*4(%esp), %edx         /* level */
+        movl    6*4(%esp), %ecx         /* optname */
+        movl    7*4(%esp), %esi         /* optval */
+        movl    8*4(%esp), %edi         /* poptlen */
+        movb    $0x43, %al              /* __getsockopt */
+        SYSCALL (0x7f)
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__getsockopt)
Index: trunk/src/emx/src/lib/emx_386/ghostbya.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ghostbya.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ghostbya.s	(revision 18)
@@ -0,0 +1,23 @@
+/ emx_386/ghostbya.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___gethostbyaddr
+
+/ int __gethostbyaddr (const char *addr, int len, int type,
+/                      struct hostent **dst)
+
+___gethostbyaddr:
+        pushl   %ebx
+        pushl   %esi
+        movl    3*4(%esp), %edx         /* addr */
+        movl    4*4(%esp), %ecx         /* len */
+        movl    5*4(%esp), %esi         /* type */
+        movl    6*4(%esp), %ebx         /* dst */
+        movb    $0x48, %al              /* __gethostbyaddr */
+        SYSCALL (0x7f)
+        popl    %esi
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__gethostbyaddr)
Index: trunk/src/emx/src/lib/emx_386/ghostbyn.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ghostbyn.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ghostbyn.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/ghostbyn.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___gethostbyname
+
+/ int __gethostbyname (const char *name, struct hostent **dst)
+
+___gethostbyname:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* name */
+        movl    3*4(%esp), %ebx         /* dst */
+        movb    $0x47, %al              /* __gethostbyname */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__gethostbyname)
Index: trunk/src/emx/src/lib/emx_386/gnetbyad.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/gnetbyad.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/gnetbyad.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/gnetbyad.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getnetbyaddr
+
+/ int __getnetbyaddr (long net, struct netent **dst)
+
+___getnetbyaddr:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* net */
+        movl    3*4(%esp), %ebx         /* dst */
+        movb    $0x4e, %al              /* __getnetbyaddr */
+        SYSCALL (0x7f)
+        popl    %ebx
+        EPILOGUE (__getnetbyaddr)
Index: trunk/src/emx/src/lib/emx_386/gnetbyna.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/gnetbyna.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/gnetbyna.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/gnetbyna.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getnetbyname
+
+/ int __getnetbyname (const char *name, struct netent **dst)
+
+___getnetbyname:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* name */
+        movl    3*4(%esp), %ebx         /* dst */
+        movb    $0x4d, %al              /* __getnetbyname */
+        SYSCALL (0x7f)
+        popl    %ebx
+        EPILOGUE (__getnetbyname)
Index: trunk/src/emx/src/lib/emx_386/gprotbna.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/gprotbna.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/gprotbna.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/gprotbna.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getprotobyname
+
+/ int __getprotobyname (const char *name, struct protoent **dst)
+
+___getprotobyname:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* name */
+        movl    3*4(%esp), %ebx         /* dst */
+        movb    $0x4b, %al              /* __getprotobyname */
+        SYSCALL (0x7f)
+        popl    %ebx
+        EPILOGUE (__getprotobyname)
Index: trunk/src/emx/src/lib/emx_386/gprotbnu.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/gprotbnu.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/gprotbnu.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/gprotbnu.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getprotobynumber
+
+/ int __getprotobynumber (int proto, struct protoent **dst)
+
+___getprotobynumber:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* number */
+        movl    3*4(%esp), %ebx         /* dst */
+        movb    $0x4c, %al              /* __getprotobynumber */
+        SYSCALL (0x7f)
+        popl    %ebx
+        EPILOGUE (__getprotobynumber)
Index: trunk/src/emx/src/lib/emx_386/gservbyn.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/gservbyn.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/gservbyn.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/gservbyn.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getservbyname
+
+/ int __getservbyname (const char *name, const char *proto,
+/                      struct servent **dst)
+
+___getservbyname:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* name */
+        movl    3*4(%esp), %ecx         /* proto */
+        movl    4*4(%esp), %ebx         /* dst */
+        movb    $0x49, %al              /* __getservbyname */
+        SYSCALL (0x7f)
+        popl    %ebx
+        EPILOGUE (__getservbyname)
Index: trunk/src/emx/src/lib/emx_386/gservbyp.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/gservbyp.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/gservbyp.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/gservbyp.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___getservbyport
+
+/ int __getservbyport (int port, const char *proto, struct servent **dst)
+
+___getservbyport:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* port */
+        movl    3*4(%esp), %ecx         /* proto */
+        movl    4*4(%esp), %ebx         /* dst */
+        movb    $0x4a, %al              /* __getservbyport */
+        SYSCALL (0x7f)
+        popl    %ebx
+        EPILOGUE (__getservbyport)
Index: trunk/src/emx/src/lib/emx_386/imphandl.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/imphandl.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/imphandl.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/imphandl.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___imphandle
+
+/ int __imphandle (int handle)
+
+___imphandle:
+        movl    1*4(%esp), %edx         /* handle */
+        movb    $0x39, %al              /* __imphandle */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__imphandle)
Index: trunk/src/emx/src/lib/emx_386/impsockh.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/impsockh.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/impsockh.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/impsockh.s (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___impsockhandle
+
+/ int __impsockhandle (int handle, int flags)
+
+___impsockhandle:
+        movl    1*4(%esp), %edx         /* handle */
+        movl    2*4(%esp), %ecx         /* flags */
+        movb    $0x54, %al              /* __impsockhandle */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__impsockhandle)
Index: trunk/src/emx/src/lib/emx_386/initthre.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/initthre.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/initthre.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/initthre.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___initthread
+
+/ int __initthread (void *preg)
+
+        ALIGN
+
+___initthread:
+        movl    1*4(%esp), %edx         /* preg */
+        movb    $0x34, %al              /* __initthread */
+        SYSCALL (0x7f)
+        EPILOGUE (__initthread)
Index: trunk/src/emx/src/lib/emx_386/ioctl1.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ioctl1.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ioctl1.s	(revision 18)
@@ -0,0 +1,24 @@
+/ emx_386/ioctl1.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___ioctl1
+
+/ __ioctl1 (int handle, int code)
+
+        ALIGN
+
+___ioctl1:
+        pushl   %ebx
+        movb    3*4(%esp), %al          /* code */
+        movl    2*4(%esp), %ebx         /* handle */
+        SYSCALL (0x44)
+        popl    %ebx
+        jb      Lerror
+        movzwl  %dx, %eax
+        jmp     Lreturn
+
+Lerror: SET_ERRNO (%eax)
+        movl    $-1, %eax
+Lreturn:EPILOGUE (__ioctl1)
Index: trunk/src/emx/src/lib/emx_386/ioctl2.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ioctl2.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ioctl2.s	(revision 18)
@@ -0,0 +1,21 @@
+/ emx_386/ioctl2.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___ioctl2
+
+/ int __ioctl2 (int handle, int request, void *arg)
+
+        ALIGN
+
+___ioctl2:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %ecx         /* request */
+        movl    4*4(%esp), %edx         /* arg */
+        movb    $0x14, %al              /* ioctl2 */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__ioctl2)
Index: trunk/src/emx/src/lib/emx_386/kill.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/kill.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/kill.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/kill.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___kill
+
+/ int __kill (int pid, int sig)
+
+___kill:
+        movl    1*4(%esp), %edx         /* pid */
+        movl    2*4(%esp), %ecx         /* sig */
+        movb    $0x0d, %al              /* kill */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__kill)
Index: trunk/src/emx/src/lib/emx_386/listen.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/listen.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/listen.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/listen.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___listen
+
+/ int __listen (int handle, int backlog)
+
+___listen:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* backlog */
+        movb    $0x3e, %al              /* __listen */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__listen)
Index: trunk/src/emx/src/lib/emx_386/lseek.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/lseek.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/lseek.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/lseek.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___lseek
+
+/ __lseek (int handle, long offset, int origin)
+
+        ALIGN
+
+___lseek:
+        pushl   %ebx
+        movb    4*4(%esp), %al          /* origin */
+        movl    3*4(%esp), %edx         /* offset */
+        movl    2*4(%esp), %ebx         /* handle */
+        SYSCALL (0x42)
+        popl    %ebx
+        SET_EAX
+        EPILOGUE (__lseek)
Index: trunk/src/emx/src/lib/emx_386/makefile
===================================================================
--- trunk/src/emx/src/lib/emx_386/makefile	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/makefile	(revision 18)
@@ -0,0 +1,170 @@
+#
+# /emx/src/lib/emx_386/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.PHONY: clean default dstlib emx emx2 emxio emxmt emxst
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+.SOURCE.s: ..
+
+LIBEMX2  = $(L)emx2.a
+LIBEMXIO = $(L)emxio.a
+
+DSTLIB=$(L)$(DIRNAME)\emx.a
+LIBC_CCFLAGS=-I..
+
+default:    emx
+
+emx .SEQUENTIAL: emx2 emxst emxmt emxio
+
+emx2: $(LIBEMX2)
+
+emxio: $(LIBEMXIO)
+
+emxmt .SETDIR=mt:
+	$(MAKE) -f ../makefile dstlib DIRNAME=mt MT_CCFLAGS=-Zmt
+
+emxst .SETDIR=st:
+	$(MAKE) -f ../makefile dstlib DIRNAME=st MT_CCFLAGS=
+
+dstlib: $(DSTLIB)
+
+clean:
+	-del *.o $(DELOPT)
+	-del mt\*.o $(DELOPT)
+	-del st\*.o $(DELOPT)
+
+accept.o: accept.s syscalls.h $(ASM386H)
+alarm.o: alarm.s syscalls.h $(ASM386H)
+bind.o: bind.s syscalls.h $(ASM386H)
+brk.o: brk.s syscalls.h $(ASM386H)
+cgets.o: cgets.s syscalls.h $(ASM386H)
+chdir.o: chdir.s syscalls.h $(ASM386H)
+chdrive.o: chdrive.s syscalls.h $(ASM386H)
+chmod.o: chmod.s syscalls.h $(ASM386H)
+chsize.o: chsize.s syscalls.h $(ASM386H)
+clock.o: clock.s syscalls.h $(ASM386H)
+close.o: close.s syscalls.h $(ASM386H)
+connect.o: connect.s syscalls.h $(ASM386H)
+core.o: core.s syscalls.h $(ASM386H)
+dos.o: dos.s
+dup.o: dup.s syscalls.h $(ASM386H)
+dup2.o: dup2.s syscalls.h $(ASM386H)
+emx_ver.o: emx_ver.s syscalls.h $(ASM386H)
+endthrea.o: endthrea.s syscalls.h $(ASM386H)
+execname.o: execname.s syscalls.h $(ASM386H)
+exit.o: exit.s syscalls.h $(ASM386H)
+fcntl.o: fcntl.s syscalls.h $(ASM386H)
+filesys.o: filesys.s syscalls.h $(ASM386H)
+findfirs.o: findfirs.s syscalls.h $(ASM386H)
+findnext.o: findnext.s syscalls.h $(ASM386H)
+fork.o: fork.s syscalls.h $(ASM386H)
+fstat.o: fstat.s syscalls.h $(ASM386H)
+fsync.o: fsync.s syscalls.h $(ASM386H)
+ftime.o: ftime.s syscalls.h $(ASM386H)
+ftruncat.o: ftruncat.s syscalls.h $(ASM386H)
+getcwd.o: getcwd.s syscalls.h $(ASM386H)
+getdrive.o: getdrive.s syscalls.h $(ASM386H)
+gethosti.o: gethosti.s syscalls.h $(ASM386H)
+gethostn.o: gethostn.s syscalls.h $(ASM386H)
+getpeern.o: getpeern.s syscalls.h $(ASM386H)
+getpid.o: getpid.s syscalls.h $(ASM386H)
+getppid.o: getppid.s syscalls.h $(ASM386H)
+getsockh.o: getsockh.s syscalls.h $(ASM386H)
+getsockn.o: getsockn.s syscalls.h $(ASM386H)
+getsocko.o: getsocko.s syscalls.h $(ASM386H)
+ghostbya.o: ghostbya.s syscalls.h $(ASM386H)
+ghostbyn.o: ghostbyn.s syscalls.h $(ASM386H)
+gnetbyad.o: gnetbyad.s syscalls.h $(ASM386H)
+gnetbyna.o: gnetbyna.s syscalls.h $(ASM386H)
+gprotbna.o: gprotbna.s syscalls.h $(ASM386H)
+gprotbnu.o: gprotbnu.s syscalls.h $(ASM386H)
+gservbyn.o: gservbyn.s syscalls.h $(ASM386H)
+gservbyp.o: gservbyp.s syscalls.h $(ASM386H)
+imphandl.o: imphandl.s syscalls.h $(ASM386H)
+impsockh.o: impsockh.s syscalls.h $(ASM386H)
+initthre.o: initthre.s syscalls.h $(ASM386H)
+ioctl1.o: ioctl1.s syscalls.h $(ASM386H)
+ioctl2.o: ioctl2.s syscalls.h $(ASM386H)
+kill.o: kill.s syscalls.h $(ASM386H)
+listen.o: listen.s syscalls.h $(ASM386H)
+lseek.o: lseek.s syscalls.h $(ASM386H)
+memacces.o: memacces.s syscalls.h $(ASM386H)
+memavail.o: memavail.s syscalls.h $(ASM386H)
+mkdir.o: mkdir.s syscalls.h $(ASM386H)
+newthrea.o: newthrea.s syscalls.h $(ASM386H)
+nls_memu.o: nls_memu.s syscalls.h $(ASM386H)
+nls_ctyp.o: nls_ctyp.s syscalls.h $(ASM386H)
+open.o: open.s syscalls.h $(ASM386H)
+os_ver.o: os_ver.s syscalls.h $(ASM386H)
+pause.o: pause.s syscalls.h $(ASM386H)
+pipe.o: pipe.s syscalls.h $(ASM386H)
+portacce.o: portacce.s syscalls.h $(ASM386H)
+profil.o: profil.s syscalls.h $(ASM386H)
+ptrace.o: ptrace.s syscalls.h $(ASM386H)
+raise.o: raise.s syscalls.h $(ASM386H)
+read.o: read.s syscalls.h $(ASM386H)
+read_kbd.o: read_kbd.s syscalls.h $(ASM386H)
+recv.o: recv.s syscalls.h $(ASM386H)
+recvfrom.o: recvfrom.s syscalls.h $(ASM386H)
+remove.o: remove.s syscalls.h $(ASM386H)
+rename.o: rename.s syscalls.h $(ASM386H)
+rmdir.o: rmdir.s syscalls.h $(ASM386H)
+sbrk.o: sbrk.s syscalls.h $(ASM386H)
+scrsize.o: scrsize.s syscalls.h $(ASM386H)
+select.o: select.s syscalls.h $(ASM386H)
+send.o: send.s syscalls.h $(ASM386H)
+sendto.o: sendto.s syscalls.h $(ASM386H)
+setsocko.o: setsocko.s syscalls.h $(ASM386H)
+setsyser.o: setsyser.s syscalls.h $(ASM386H)
+settime.o: settime.s syscalls.h $(ASM386H)
+shutdown.o: shutdown.s syscalls.h $(ASM386H)
+sigactio.o: sigactio.s syscalls.h $(ASM386H)
+signal.o: signal.s syscalls.h $(ASM386H)
+sigpendi.o: sigpendi.s syscalls.h $(ASM386H)
+sigprocm.o: sigprocm.s syscalls.h $(ASM386H)
+sigsuspe.o: sigsuspe.s syscalls.h $(ASM386H)
+sleep.o: sleep.s syscalls.h $(ASM386H)
+sleep2.o: sleep2.s syscalls.h $(ASM386H)
+socket.o: socket.s syscalls.h $(ASM386H)
+spawnve.o: spawnve.s syscalls.h $(ASM386H)
+stat.o: stat.s syscalls.h $(ASM386H)
+swchar.o: swchar.s syscalls.h $(ASM386H)
+syserrno.o: syserrno.s syscalls.h $(ASM386H)
+ttyname.o: ttyname.s syscalls.h $(ASM386H)
+uflags.o: uflags.s syscalls.h $(ASM386H)
+ulimit.o: ulimit.s syscalls.h $(ASM386H)
+umask.o: umask.s syscalls.h $(ASM386H)
+unwind.o: unwind.s syscalls.h $(ASM386H)
+utimes.o: utimes.s syscalls.h $(ASM386H)
+wait.o: wait.s syscalls.h $(ASM386H)
+waitpid.o: waitpid.s syscalls.h $(ASM386H)
+write.o: write.s syscalls.h $(ASM386H)
+
+
+$(DSTLIB): accept.o alarm.o bind.o brk.o cgets.o chdir.o chdrive.o \
+    chmod.o chsize.o clock.o close.o connect.o core.o dup.o dup2.o \
+    emx_ver.o endthrea.o execname.o exit.o fcntl.o filesys.o \
+    findfirs.o findnext.o fork.o fstat.o fsync.o ftime.o ftruncat.o \
+    getcwd.o getdrive.o gethosti.o gethostn.o getpeern.o getpid.o \
+    getppid.o getsockh.o getsockn.o getsocko.o ghostbya.o ghostbyn.o \
+    gnetbyad.o gnetbyna.o gprotbna.o gprotbnu.o gservbyn.o gservbyp.o \
+    imphandl.o impsockh.o initthre.o ioctl1.o ioctl2.o kill.o listen.o \
+    lseek.o memacces.o memavail.o mkdir.o newthrea.o nls_ctyp.o nls_memu.o \
+    open.o os_ver.o pause.o pipe.o portacce.o profil.o ptrace.o raise.o \
+    read.o read_kbd.o recv.o recvfrom.o remove.o rename.o rmdir.o sbrk.o \
+    scrsize.o select.o send.o sendto.o setsocko.o setsyser.o settime.o \
+    shutdown.o sigactio.o signal.o sigpendi.o sigprocm.o sigsuspe.o sleep.o \
+    sleep2.o socket.o spawnve.o stat.o swchar.o syserrno.o ttyname.o \
+    uflags.o ulimit.o umask.o unwind.o utimes.o wait.o waitpid.o write.o
+	-del $(DSTLIB)
+	$(AR) r $(DSTLIB) *.o
+
+$(LIBEMX2): emx.imp dos.o
+	emximp -o $(LIBEMX2) emx.imp
+	ar r $(LIBEMX2) dos.o
+
+$(LIBEMXIO): emxio.imp
+	emximp -o $(LIBEMXIO) emxio.imp
Index: trunk/src/emx/src/lib/emx_386/memacces.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/memacces.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/memacces.s	(revision 18)
@@ -0,0 +1,23 @@
+/ emx_386/memacces.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___memaccess
+
+/ void * __memaccess (unsigned first, unsigned last, int flag)
+
+        ALIGN
+
+___memaccess:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* first */
+        movl    3*4(%esp), %ecx         /* last */
+        movl    4*4(%esp), %edx         /* flag */
+        movb    $0x13, %al
+        SYSCALL (0x7f)
+        popl    %ebx
+        jnb     Lreturn
+        SET_ERRNO (%eax)
+        xorl    %eax, %eax              /* NULL */
+Lreturn:EPILOGUE (__memaccess)
Index: trunk/src/emx/src/lib/emx_386/memavail.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/memavail.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/memavail.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/memavail.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___memavail
+
+/ int __memavail (void)
+
+        ALIGN
+
+___memavail:
+        movb    $0x0b, %al
+        SYSCALL (0x7f)
+        EPILOGUE (__memavail)
Index: trunk/src/emx/src/lib/emx_386/mkdir.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/mkdir.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/mkdir.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/mkdir.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___mkdir
+
+/ int __mkdir (const char *name)
+
+        ALIGN
+
+___mkdir:
+        movl    1*4(%esp), %edx
+        SYSCALL (0x39)
+        SET_0
+        EPILOGUE (__mkdir)
Index: trunk/src/emx/src/lib/emx_386/newthrea.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/newthrea.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/newthrea.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/newthrea.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___newthread
+
+/ int __newthread (int tid)
+
+        ALIGN
+
+___newthread:
+        movl    1*4(%esp), %edx         /* tid */
+        movb    $0x2c, %al              /* __newthread */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__newthread)
Index: trunk/src/emx/src/lib/emx_386/nls_ctyp.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/nls_ctyp.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/nls_ctyp.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/nls_ctyp.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___nls_ctype
+
+/ int __nls_ctype (unsigned char *buf)
+
+        ALIGN
+
+___nls_ctype:
+        movl    1*4(%esp), %edx         /* buf */
+        movb    $0x5a, %al              /* __nls_ctype */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__nls_ctype)
Index: trunk/src/emx/src/lib/emx_386/nls_memu.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/nls_memu.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/nls_memu.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/nls_memu.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___nls_memupr
+
+/ void __nls_memupr (unsigned char *buf, size_t size)
+
+        ALIGN
+
+___nls_memupr:
+        movl    1*4(%esp), %edx         /* buf */
+        movl    2*4(%esp), %ecx         /* size */
+        movb    $0x2a, %al              /* __nls_memupr */
+        SYSCALL (0x7f)
+        EPILOGUE (__nls_memupr)
Index: trunk/src/emx/src/lib/emx_386/open.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/open.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/open.s	(revision 18)
@@ -0,0 +1,21 @@
+/ emx_386/open.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___open
+
+/ __open (char *path, int flags, unsigned long size)
+
+        ALIGN
+
+___open:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* path */
+        movl    3*4(%esp), %ecx         /* flags */
+        movl    4*4(%esp), %ebx         /* size */
+        movb    $0x2b, %al              /* __open */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__open)
Index: trunk/src/emx/src/lib/emx_386/os_ver.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/os_ver.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/os_ver.s	(revision 18)
@@ -0,0 +1,12 @@
+/ emx_386/os_ver.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___os_version
+
+        ALIGN
+
+___os_version:
+        SYSCALL (0x30)
+        EPILOGUE (__os_version)
Index: trunk/src/emx/src/lib/emx_386/pause.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/pause.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/pause.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/pause.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___pause
+
+/ void __pause (void)
+
+        ALIGN
+
+___pause:
+        movb    $0x32, %al              /* __pause */
+        SYSCALL (0x7f)
+        EPILOGUE (__pause)
Index: trunk/src/emx/src/lib/emx_386/pipe.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/pipe.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/pipe.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/pipe.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___pipe
+
+/ int __pipe (int *two_handles, int pipe_size)
+
+        ALIGN
+
+___pipe:
+        movl    1*4(%esp), %edx         /* two_handles */
+        movl    2*4(%esp), %ecx         /* pipe_size */
+        movb    $0x1a, %al              /* __pipe */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__pipe)
Index: trunk/src/emx/src/lib/emx_386/portacce.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/portacce.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/portacce.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/portacce.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___portaccess
+
+/ int __portaccess (unsigned first, unsigned last)
+
+        ALIGN
+
+___portaccess:
+        movl    1*4(%esp), %ecx         /* first */
+        movl    2*4(%esp), %edx         /* last */
+        movb    $0x12, %al
+        SYSCALL (0x7f)
+        SET_0
+        EPILOGUE (__portaccess)
Index: trunk/src/emx/src/lib/emx_386/profil.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/profil.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/profil.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/profil.s (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___profil
+
+/ int __profil (const struct _profil *p)
+
+        ALIGN
+
+___profil:
+        movl    1*4(%esp), %edx         /* p */
+        movb    $0x59, %al              /* __profil */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__profil)
Index: trunk/src/emx/src/lib/emx_386/ptrace.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ptrace.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ptrace.s	(revision 18)
@@ -0,0 +1,24 @@
+/ emx_386/ptrace.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___ptrace
+
+/ int __ptrace (int request, int pid, int addr, int data)
+
+        ALIGN
+
+___ptrace:
+        pushl   %ebx
+        pushl   %edi
+        movl    3*4(%esp), %ebx         /* request */
+        movl    4*4(%esp), %edi         /* pid */
+        movl    5*4(%esp), %edx         /* addr */
+        movl    6*4(%esp), %ecx         /* data */
+        movb    $8, %al                 /* ptrace */
+        SYSCALL (0x7f)
+        popl    %edi
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__ptrace)
Index: trunk/src/emx/src/lib/emx_386/raise.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/raise.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/raise.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/raise.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+/ WARNING: emx.dll depends on the stack frame of this function when
+/          dumping core
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___raise
+
+/ int __raise (int sig)
+
+        ALIGN
+
+___raise:
+        movl    1*4(%esp), %ecx         /* sig */
+        movb    $0x0e, %al              /* raise */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__raise)
Index: trunk/src/emx/src/lib/emx_386/read.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/read.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/read.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/read.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___read
+
+/ __read (int handle, void *buf, size_t nbyte)
+
+        ALIGN
+
+___read:
+        pushl   %ebx
+        movl    4*4(%esp), %ecx         /* nbyte */
+        movl    3*4(%esp), %edx         /* buf */
+        movl    2*4(%esp), %ebx         /* handle */
+        SYSCALL (0x3f)
+        popl    %ebx
+        SET_EAX
+        EPILOGUE (__read)
Index: trunk/src/emx/src/lib/emx_386/read_kbd.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/read_kbd.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/read_kbd.s	(revision 18)
@@ -0,0 +1,25 @@
+/ emx_386/read_kbd.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___read_kbd
+
+/ int __read_kbd (int echo, int wait, int sig)
+
+        ALIGN
+
+___read_kbd:
+        xorl    %edx, %edx
+        cmpl    $0, 1*4(%esp)           /* echo */
+        je      1f
+        orl     $1, %edx
+1:      cmpl    $0, 2*4(%esp)           /* wait */
+        je      2f
+        orl     $2, %edx
+2:      cmpl    $0, 3*4(%esp)           /* sig */
+        je      3f
+        orl     $4, %edx
+3:      movb    $0x2f, %al              /* __read_kbd */
+        SYSCALL (0x7f)
+        EPILOGUE (__read_kbd)
Index: trunk/src/emx/src/lib/emx_386/recv.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/recv.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/recv.s	(revision 18)
@@ -0,0 +1,22 @@
+/ emx_386/recv.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___recv
+
+/ int __recv (int handle, void *buf, int len, unsigned flags)
+
+___recv:
+        pushl   %ebx
+        pushl   %esi
+        movl    3*4(%esp), %ebx         /* handle */
+        movl    4*4(%esp), %edx         /* buf */
+        movl    5*4(%esp), %ecx         /* len */
+        movl    6*4(%esp), %esi         /* flags */
+        movb    $0x3f, %al              /* __recv */
+        SYSCALL (0x7f)
+        popl    %esi
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__recv)
Index: trunk/src/emx/src/lib/emx_386/recvfrom.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/recvfrom.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/recvfrom.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/recvfrom.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___recvfrom
+
+/ int __recvfrom (const struct _recvfrom *args)
+
+___recvfrom:
+        movl    1*4(%esp), %edx         /* args */
+        movb    $0x52, %al              /* __recvfrom */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__recvfrom)
Index: trunk/src/emx/src/lib/emx_386/remove.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/remove.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/remove.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/remove.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___remove
+
+/ int __remove (const char *name)
+
+        ALIGN
+
+___remove:
+        movl    1*4(%esp), %edx         /* name */
+        SYSCALL (0x41)
+        SET_0
+        EPILOGUE (__remove)
Index: trunk/src/emx/src/lib/emx_386/rename.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/rename.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/rename.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/rename.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___rename
+
+/ int __rename (const char *old_name, const char *new_name)
+
+        ALIGN
+
+___rename:
+        pushl   %edi
+        movl    2*4(%esp), %edx         /* old_name */
+        movl    3*4(%esp), %edi         /* new_name */
+        SYSCALL (0x56)
+        popl    %edi
+        SET_0
+        EPILOGUE (__rename)
Index: trunk/src/emx/src/lib/emx_386/rmdir.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/rmdir.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/rmdir.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/rmdir.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___rmdir
+
+/ int __rmdir (const char *name)
+
+        ALIGN
+
+___rmdir:
+        movl    1*4(%esp), %edx
+        SYSCALL (0x3a)
+        SET_0
+        EPILOGUE (__rmdir)
Index: trunk/src/emx/src/lib/emx_386/sbrk.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/sbrk.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/sbrk.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/sbrk.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___sbrk
+
+/ void *__sbrk (int incr)
+
+        ALIGN
+
+___sbrk:
+        movl    1*4(%esp), %edx
+        movb    $0, %al
+        SYSCALL (0x7f)
+        cmpl    $-1, %eax
+        jne     Lreturn
+        SET_ERRNO ($ENOMEM)
+        movl    $-1, %eax
+Lreturn:EPILOGUE (__sbrk)
Index: trunk/src/emx/src/lib/emx_386/scrsize.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/scrsize.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/scrsize.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/scrsize.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___scrsize
+
+/ void __scrsize (int *dst)
+
+        ALIGN
+
+___scrsize:
+        movl    1*4(%esp), %edx         /* dst */
+        movb    $0x1d, %al              /* __scrsize */
+        SYSCALL (0x7f)
+        EPILOGUE (__scrsize)
Index: trunk/src/emx/src/lib/emx_386/select.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/select.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/select.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/select.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___select
+
+/ void __select (struct _select *args)
+
+        ALIGN
+
+___select:
+        movl    1*4(%esp), %edx         /* args */
+        movb    $0x1e, %al              /* __select */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__select)
Index: trunk/src/emx/src/lib/emx_386/send.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/send.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/send.s	(revision 18)
@@ -0,0 +1,22 @@
+/ emx_386/send.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___send
+
+/ int __send (int handle, const void *buf, int len, unsigned flags)
+
+___send:
+        pushl   %ebx
+        pushl   %esi
+        movl    3*4(%esp), %ebx         /* handle */
+        movl    4*4(%esp), %edx         /* buf */
+        movl    5*4(%esp), %ecx         /* len */
+        movl    6*4(%esp), %esi         /* flags */
+        movb    $0x40, %al              /* __send */
+        SYSCALL (0x7f)
+        popl    %esi
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__send)
Index: trunk/src/emx/src/lib/emx_386/sendto.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/sendto.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/sendto.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/sendto.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___sendto
+
+/ int __sendto (const struct _sendto *args)
+
+___sendto:
+        movl    1*4(%esp), %edx         /* args */
+        movb    $0x53, %al              /* __sendto */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__sendto)
Index: trunk/src/emx/src/lib/emx_386/setsocko.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/setsocko.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/setsocko.s	(revision 18)
@@ -0,0 +1,26 @@
+/ emx_386/setsocko.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___setsockopt
+
+/ int __setsockopt (int handle, int level, int optname, const void *optval,
+/                   int optlen)
+
+___setsockopt:
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        movl    4*4(%esp), %ebx         /* handle */
+        movl    5*4(%esp), %edx         /* level */
+        movl    6*4(%esp), %ecx         /* optname */
+        movl    7*4(%esp), %esi         /* optval */
+        movl    8*4(%esp), %edi         /* optlen */
+        movb    $0x44, %al              /* __setsockopt */
+        SYSCALL (0x7f)
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__setsockopt)
Index: trunk/src/emx/src/lib/emx_386/setsyser.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/setsyser.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/setsyser.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/setsyser.s (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___setsyserrno
+
+/ int __setsyserrno (int errcode)
+
+        ALIGN
+
+___setsyserrno:
+        movl    1*4(%esp), %edx         /* errcode */
+        movb    $0x5b, %al              /* __setsyserrno */
+        SYSCALL (0x7f)
+        EPILOGUE (__setsyserrno)
Index: trunk/src/emx/src/lib/emx_386/settime.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/settime.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/settime.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/settime.s (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___settime
+
+/ int __settime (const struct timeval *tp)
+
+        ALIGN
+
+___settime:
+        movl    1*4(%esp), %edx         /* tp */
+        movb    $0x58, %al              /* __settime */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__settime)
Index: trunk/src/emx/src/lib/emx_386/shutdown.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/shutdown.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/shutdown.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/shutdown.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___shutdown
+
+/ int __shutdown (int handle, int how)
+
+___shutdown:
+        pushl   %ebx
+        movl    2*4(%esp), %ebx         /* handle */
+        movl    3*4(%esp), %edx         /* show */
+        movb    $0x51, %al              /* __shutdown */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__shutdown)
Index: trunk/src/emx/src/lib/emx_386/sigactio.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/sigactio.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/sigactio.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/sigactio.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___sigaction
+
+/ int __sigaction (int sig, const struct sigaction *iact,
+/                  struct sigaction *oact)
+
+___sigaction:
+        pushl   %ebx
+        movl    2*4(%esp), %ecx         /* sig */
+        movl    3*4(%esp), %edx         /* iact */
+        movl    4*4(%esp), %ebx         /* oact */
+        movb    $0x35, %al              /* __sigaction */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__sigaction)
Index: trunk/src/emx/src/lib/emx_386/signal.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/signal.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/signal.s	(revision 18)
@@ -0,0 +1,22 @@
+/ emx_386/signal.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+/ WARNING: emx.dll depends on the stack frame of this function when
+/          dumping core
+        
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___signal
+
+/ void (*__signal (int sig, void (*handler)()))(int sig)
+
+___signal:
+        movl    1*4(%esp), %ecx         /* sig */
+        movl    2*4(%esp), %edx         /* handler */
+        movb    $0x0c, %al              /* signal */
+        SYSCALL (0x7f)
+        cmpl    $-1, %eax               /* error? */
+        jne     Lreturn
+        SET_ERRNO ($EINVAL)
+        movl    $-1, %eax
+Lreturn:EPILOGUE (__signal)
Index: trunk/src/emx/src/lib/emx_386/sigpendi.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/sigpendi.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/sigpendi.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/sigpendi.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___sigpending
+
+/ int sigpending (sigset_t *set)
+
+___sigpending:
+        movl    1*4(%esp), %edx         /* set */
+        movb    $0x36, %al              /* __sigpending */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__sigpending)
Index: trunk/src/emx/src/lib/emx_386/sigprocm.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/sigprocm.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/sigprocm.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/sigprocm.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___sigprocmask
+
+/ int sigprocmask (int how, const sigset_t *iset, sigset_t *oset)
+
+___sigprocmask:
+        pushl   %ebx
+        movl    2*4(%esp), %ecx         /* how */
+        movl    3*4(%esp), %edx         /* iset */
+        movl    4*4(%esp), %ebx         /* oset */
+        movb    $0x37, %al              /* __sigprocmask */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__sigprocmask)
Index: trunk/src/emx/src/lib/emx_386/sigsuspe.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/sigsuspe.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/sigsuspe.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/sigsuspe.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___sigsuspend
+
+/ int sigsuspend (const sigset_t *mask)
+
+___sigsuspend:
+        movl    1*4(%esp), %edx         /* mask */
+        movb    $0x38, %al              /* __sigsuspend */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__sigsuspend)
Index: trunk/src/emx/src/lib/emx_386/sleep.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/sleep.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/sleep.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/sleep.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___sleep
+
+/ unsigned __sleep (unsigned sec)
+
+        ALIGN
+
+___sleep:
+        movl    1*4(%esp), %edx         /* sec */
+        movb    $0x17, %al              /* __sleep */
+        SYSCALL (0x7f)
+        EPILOGUE (__sleep)
Index: trunk/src/emx/src/lib/emx_386/sleep2.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/sleep2.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/sleep2.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/sleep2.s (emx+gcc) -- Copyright (c) 19931-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___sleep2
+
+/ unsigned __sleep2 (unsigned millisec)
+
+        ALIGN
+
+___sleep2:
+        movl    1*4(%esp), %edx         /* millisec */
+        movb    $0x30, %al              /* __sleep2 */
+        SYSCALL (0x7f)
+        EPILOGUE (__sleep2)
Index: trunk/src/emx/src/lib/emx_386/socket.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/socket.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/socket.s	(revision 18)
@@ -0,0 +1,19 @@
+/ emx_386/socket.s (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___socket
+
+/ int __socket (int domain, int type, int protocol)
+
+___socket:
+        pushl   %ebx
+        movl    2*4(%esp), %ecx         /* domain */
+        movl    3*4(%esp), %edx         /* type */
+        movl    4*4(%esp), %ebx         /* protocol */
+        movb    $0x3c, %al              /* __socket */
+        SYSCALL (0x7f)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__socket)
Index: trunk/src/emx/src/lib/emx_386/spawnve.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/spawnve.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/spawnve.s	(revision 18)
@@ -0,0 +1,21 @@
+/ emx_386/spawnve.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___spawnve
+
+/ int __spawnve (struct _new_proc *np)
+
+        ALIGN
+
+___spawnve:
+        movl    1*4(%esp), %edx
+        movw    %ds, %cx
+        movw    %cx, 12(%edx)           /* arg_sel */
+        movw    %cx, 14(%edx)           /* env_sel */
+        movw    %cx, 16(%edx)           /* fname_sel */
+        movb    $0x06, %al
+        SYSCALL (0x7f)
+        SET_EAX
+        EPILOGUE (__spawnve)
Index: trunk/src/emx/src/lib/emx_386/stat.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/stat.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/stat.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/stat.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___stat
+
+/ int __stat (const char *name, struct stat *buffer)
+
+        ALIGN
+
+___stat:
+        pushl   %edi
+        movl    2*4(%esp), %edx         /* name */
+        movl    3*4(%esp), %edi         /* buffer */
+        movb    $0x20, %al              /* __stat */
+        SYSCALL (0x7f)
+        popl    %edi
+        SET_ERRNO_ECX
+        EPILOGUE (__stat)
Index: trunk/src/emx/src/lib/emx_386/swchar.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/swchar.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/swchar.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/swchar.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___swchar
+
+/ int __swchar (int flag, int new)
+
+        ALIGN
+
+___swchar:
+        movb    1*4(%esp), %al          /* flag */
+        movb    2*4(%esp), %dl          /* new */
+        SYSCALL (0x37)
+        movzbl  %al, %eax
+        movb    %dl, %ah
+        EPILOGUE (__swchar)
Index: trunk/src/emx/src/lib/emx_386/syscalls.h
===================================================================
--- trunk/src/emx/src/lib/emx_386/syscalls.h	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/syscalls.h	(revision 18)
@@ -0,0 +1,90 @@
+/ emx_386/syscalls.h (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#define SYSCALL(x) movb $x,%ah;call ___syscall
+
+#define ENOMEM     12
+#define EINVAL     22
+
+#if !defined (__MT__)
+
+/* Return 0 if NC, set errno from EAX and return -1 if CY. */
+
+#define SET_0 \
+        jb      8f ;\
+        xorl    %eax, %eax ;\
+        jmp     9f ;\
+        ALIGN ;\
+8:      movl    %eax, _errno ;\
+        movl    $-1, %eax ;\
+        ALIGN ;\
+9:
+
+/* Return EAX if NC, set errno from EAX and return -1 if CY. */
+
+#define SET_EAX \
+        jnb     9f ;\
+        movl    %eax, _errno ;\
+        movl    $-1, %eax ;\
+        ALIGN ;\
+9:
+
+/* Set errno from ECX if non-zero. */
+
+#define SET_ERRNO_ECX \
+        jecxz   9f ;\
+        movl    %ecx, _errno ;\
+        ALIGN ;\
+9:
+
+/* Set errno from x (constant or any register) */
+
+#define SET_ERRNO(x) \
+        movl    x, _errno
+
+#else
+
+/* Return 0 if NC, set errno from EAX and return -1 if CY. */
+
+#define SET_0 \
+        jb      8f ;\
+        xorl    %eax, %eax ;\
+        jmp     9f ;\
+        ALIGN ;\
+8:      pushl   %eax ;\
+        call    __errno ;\
+        popl    (%eax) ;\
+        movl    $-1, %eax ;\
+        ALIGN ;\
+9:
+
+/* Return EAX if NC, set errno from EAX and return -1 if CY. */
+
+#define SET_EAX \
+        jnb     9f ;\
+        pushl   %eax ;\
+        call    __errno ;\
+        popl    (%eax) ;\
+        movl    $-1, %eax ;\
+        ALIGN ;\
+9:
+
+/* Set errno from ECX if non-zero. */
+
+#define SET_ERRNO_ECX \
+        jecxz   9f ;\
+        pushl   %eax ;\
+        pushl   %ecx ;\
+        call    __errno ;\
+        popl    (%eax) ;\
+        popl    %eax ;\
+        ALIGN ;\
+9:
+
+/* Set errno from x (constant or any register) */
+
+#define SET_ERRNO(x) \
+        pushl   x ;\
+        call    __errno ;\
+        popl    (%eax)
+
+#endif
Index: trunk/src/emx/src/lib/emx_386/syserrno.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/syserrno.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/syserrno.s	(revision 18)
@@ -0,0 +1,15 @@
+/ emx_386/syserrno.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___syserrno
+
+/ int __syserrno (void)
+
+        ALIGN
+
+___syserrno:
+        movb    $0x1f, %al              /* __syserrno */
+        SYSCALL (0x7f)
+        EPILOGUE (__syserrno)
Index: trunk/src/emx/src/lib/emx_386/ttyname.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ttyname.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ttyname.s	(revision 18)
@@ -0,0 +1,21 @@
+/ emx_386/ttyname.s (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___ttyname
+
+/ int __ttyname (int handle, char *buf, size_t buf_size)
+
+        ALIGN
+
+___ttyname:
+        pushl   %edi
+        movl    2*4(%esp), %edx         /* handle */
+        movl    3*4(%esp), %edi         /* buf */
+        movl    4*4(%esp), %ecx         /* buf_size */
+        movb    $0x57, %al              /* __ttyname */
+        SYSCALL (0x7f)
+        popl    %edi
+        SET_ERRNO_ECX
+        EPILOGUE (__ttyname)
Index: trunk/src/emx/src/lib/emx_386/uflags.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/uflags.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/uflags.s	(revision 18)
@@ -0,0 +1,17 @@
+/ emx_386/uflags.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___uflags
+
+/ int __uflags (int mask, int new)
+
+        ALIGN
+
+___uflags:
+        movl    1*4(%esp), %ecx         /* mask */
+        movl    2*4(%esp), %edx         /* new */
+        movb    $0x0f, %al              /* uflags */
+        SYSCALL (0x7f)
+        EPILOGUE (__uflags)
Index: trunk/src/emx/src/lib/emx_386/ulimit.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/ulimit.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/ulimit.s	(revision 18)
@@ -0,0 +1,18 @@
+/ emx_386/ulimit.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___ulimit
+
+/ long __ulimit (int cmd, long new_limit)
+
+        ALIGN
+
+___ulimit:
+        movb    $2, %al
+        movl    1*4(%esp), %ecx         /* cmd */
+        movl    2*4(%esp), %edx         /* new_limit */
+        SYSCALL (0x7f)
+        SET_ERRNO_ECX
+        EPILOGUE (__ulimit)
Index: trunk/src/emx/src/lib/emx_386/umask.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/umask.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/umask.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/umask.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___umask
+
+/ int __umask (int pmode)
+
+        ALIGN
+
+___umask:
+        movl    1*4(%esp), %edx         /* pmode */
+        movb    $0x28, %al              /* __umask */
+        SYSCALL (0x7f)
+        EPILOGUE (__umask)
Index: trunk/src/emx/src/lib/emx_386/unwind.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/unwind.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/unwind.s	(revision 18)
@@ -0,0 +1,16 @@
+/ emx_386/unwind.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___unwind2
+
+/ void __unwind2 (void *xcpt_reg_ptr)
+
+        ALIGN
+
+___unwind2:
+        movl    1*4(%esp), %edx         /* xcpt_reg_ptr */
+        movb    $0x31, %al              /* __unwind2 */
+        SYSCALL (0x7f)
+        EPILOGUE (__unwind2)
Index: trunk/src/emx/src/lib/emx_386/utimes.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/utimes.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/utimes.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/utimes.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___utimes
+
+/ int __utimes (const char *name, const struct timeval *tvp)
+
+        ALIGN
+
+___utimes:
+        pushl   %esi
+        movl    2*4(%esp), %edx         /* name */
+        movl    3*4(%esp), %esi         /* tvp */
+        movb    $0x24, %al              /* __utimes */
+        SYSCALL (0x7f)
+        popl    %esi
+        SET_ERRNO_ECX
+        EPILOGUE (__utimes)
Index: trunk/src/emx/src/lib/emx_386/wait.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/wait.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/wait.s	(revision 18)
@@ -0,0 +1,22 @@
+/ emx_386/wait.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___wait
+
+/ int __wait (int *status)
+/
+/ note: do not call with status == NULL!
+
+        ALIGN
+
+___wait:
+        pushl   %ebx
+        movb    $9, %al
+        SYSCALL (0x7f)
+        movl    2*4(%esp), %ebx
+        movl    %edx, (%ebx)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__wait)
Index: trunk/src/emx/src/lib/emx_386/waitpid.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/waitpid.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/waitpid.s	(revision 18)
@@ -0,0 +1,24 @@
+/ emx_386/waitpid.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___waitpid
+
+/ int __waitpid (int pid, int *status, int options)
+/
+/ note: do not call with status == NULL!
+
+        ALIGN
+
+___waitpid:
+        pushl   %ebx
+        movl    2*4(%esp), %edx         /* pid */
+        movl    4*4(%esp), %ecx         /* options */
+        movb    $0x2e, %al
+        SYSCALL (0x7f)
+        movl    3*4(%esp), %ebx         /* status */
+        movl    %edx, (%ebx)
+        popl    %ebx
+        SET_ERRNO_ECX
+        EPILOGUE (__waitpid)
Index: trunk/src/emx/src/lib/emx_386/write.s
===================================================================
--- trunk/src/emx/src/lib/emx_386/write.s	(revision 18)
+++ trunk/src/emx/src/lib/emx_386/write.s	(revision 18)
@@ -0,0 +1,20 @@
+/ emx_386/write.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+#include "syscalls.h"
+
+        .globl  ___write
+
+/ __write (int handle, void *buf, size_t nbyte)
+
+        ALIGN
+
+___write:
+        pushl   %ebx
+        movl    4*4(%esp), %ecx         /* nbyte */
+        movl    3*4(%esp), %edx         /* buf */
+        movl    2*4(%esp), %ebx         /* handle */
+        SYSCALL (0x40)
+        popl    %ebx
+        SET_EAX
+        EPILOGUE (__write)
Index: trunk/src/emx/src/lib/emxload/emxloadc.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloadc.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloadc.c	(revision 18)
@@ -0,0 +1,10 @@
+/* emxloadc.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/emxload.h>
+#include <emx/emxload.h>
+
+int _emxload_connect (void)
+{
+  return _emxload_request (_EMXLOAD_CONNECT, NULL, 0);
+}
Index: trunk/src/emx/src/lib/emxload/emxloadd.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloadd.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloadd.c	(revision 18)
@@ -0,0 +1,10 @@
+/* emxloadd.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/emxload.h>
+#include <emx/emxload.h>
+
+int _emxload_disconnect (void)
+{
+  return _emxload_request (_EMXLOAD_DISCONNECT, NULL, 0);
+}
Index: trunk/src/emx/src/lib/emxload/emxloade.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloade.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloade.c	(revision 18)
@@ -0,0 +1,21 @@
+/* emxloade.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/emxload.h>
+
+int _emxload_env (const char *envname)
+{
+  const char *p, *q;
+  long n;
+
+  p = getenv (envname);
+  if (p == NULL)
+    return -1;
+  errno = 0;
+  n = strtol (p, (char **)&q, 0);
+  if (errno != 0 || q == p || *q != 0 || n < 1)
+    return -1;
+  _emxload_this ((int)n * 60);
+  return 0;
+}
Index: trunk/src/emx/src/lib/emxload/emxloadl.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloadl.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloadl.c	(revision 18)
@@ -0,0 +1,39 @@
+/* emxloadl.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <os2emx.h>             /* Define FALSE */
+#include <emx/emxload.h>
+
+int _emxload_list_start (void)
+{
+  if (_osmode != OS2_MODE)
+    return -1;
+  if (_emxload_do_connect (FALSE) != 0)
+    return -1;
+  if (_emxload_do_request (_EMXLOAD_LIST, "", 0) != 0)
+    {
+      _emxload_do_disconnect (FALSE);
+      return -1;
+    }
+  return 0;
+}
+
+
+int _emxload_list_get (char *buf, size_t buf_size, int *pseconds)
+{
+  answer ans;
+
+  if (_osmode != OS2_MODE || buf_size == 0)
+    return -1;
+  if (_emxload_do_receive (&ans) != 0)
+    return -1;
+  if (ans.ans_code != 0)
+    {
+      _emxload_do_disconnect (FALSE);
+      return 1;
+    }
+  _strncpy (buf, ans.name, buf_size);
+  *pseconds = ans.seconds;
+  return 0;
+}
Index: trunk/src/emx/src/lib/emxload/emxloado.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloado.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloado.c	(revision 18)
@@ -0,0 +1,13 @@
+/* emxloado.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/emxload.h>
+#include <emx/emxload.h>
+
+int _emxload_stop (int wait_flag)
+{
+  int req_code;
+
+  req_code = (wait_flag ? _EMXLOAD_STOP_WAIT : _EMXLOAD_STOP);
+  return _emxload_request (req_code, NULL, 0);
+}
Index: trunk/src/emx/src/lib/emxload/emxloadp.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloadp.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloadp.c	(revision 18)
@@ -0,0 +1,21 @@
+/* emxloadp.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/emxload.h>
+#include <emx/emxload.h>
+
+int _emxload_prog (const char *name, int seconds)
+{
+  char buf1[MAXPATHLEN];
+  char buf2[MAXPATHLEN];
+
+  if (seconds != _EMXLOAD_INDEFINITE && seconds < 0)
+    return -1;
+  _strncpy (buf1, name, sizeof (buf1));
+  _defext (buf1, "exe");
+  if (_path (buf2, buf1) != 0 || _abspath (buf2, buf2, sizeof (buf2)) != 0)
+    return -1;
+  return _emxload_request (_EMXLOAD_LOAD, buf2, seconds);
+}
Index: trunk/src/emx/src/lib/emxload/emxloadr.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloadr.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloadr.c	(revision 18)
@@ -0,0 +1,188 @@
+/* emxloadr.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/emxload.h>
+#include <emx/emxload.h>
+#define INCL_DOSNMPIPES
+#define INCL_DOSPROCESS
+#define INCL_DOSERRORS
+#include <os2emx.h>
+
+
+static char const pipe_name[] = _EMXLOAD_PIPENAME;
+static HPIPE hpServer = 0;
+static int connect_level = 0;
+
+int _emxload_do_connect (int start)
+{
+  int i, ok;
+  ULONG rc, action;
+
+  if (connect_level <= 0)
+    {
+      ok = FALSE;
+      for (i = 0; i < 30; ++i)
+        {
+          rc = DosOpen (pipe_name, &hpServer, &action, 0, 0,
+                        OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+                        OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYREADWRITE
+                        | OPEN_ACCESS_READWRITE, NULL);
+          if (rc == 0)
+            {
+              ok = TRUE;
+              break;
+            }
+          else if (rc == ERROR_PIPE_BUSY)
+            rc = DosWaitNPipe (pipe_name, 1000L);
+          if (rc == ERROR_FILE_NOT_FOUND || rc == ERROR_PATH_NOT_FOUND)
+            {
+              if (!start)
+                return 0;
+              if (i == 0)
+                {
+                  CHAR objbuf[64];
+                  RESULTCODES res;
+
+                  /* Note: emxload will inherit the non-private file
+                     handles.  Therefore, emxload should close all the
+                     handles. */
+
+                  rc = DosExecPgm (objbuf, sizeof (objbuf), EXEC_BACKGROUND,
+                                   "emxload\0-server\0", NULL, &res,
+                                   "emxload.exe");
+                  if (rc != 0)
+                    return -1;
+                }
+              else
+                {
+                  /* Perhaps we should check here whether the server
+                     process is alive or not. */
+
+                  DosSleep (1000L);
+                }
+            }
+          else if (rc != 0 && rc != ERROR_PIPE_BUSY)
+            return -1;
+        }
+      if (!ok)
+        return -1;
+    }
+  ++connect_level;
+  return 0;
+}
+
+
+int _emxload_do_disconnect (int force)
+{
+  if (connect_level <= 0)
+    return -1;
+  --connect_level;
+  if (connect_level <= 0 || force)
+    {
+      connect_level = 0;
+      if (DosClose (hpServer) != 0)
+        return -1;
+    }
+  return 0;
+}
+
+
+int _emxload_do_request (int req_code, const char *name, int seconds)
+{
+  ULONG rc, cb;
+  int len;
+  request req;
+
+  if (connect_level <= 0)
+    return -1;
+  len = (name == NULL ? 0 : strlen (name));
+  if (name == NULL)
+    req.name[0] = 0;
+  else if (len >= sizeof (req.name))
+    return -1;
+  else
+    memcpy(req.name, name, len + 1);
+  req.req_code = req_code;
+  req.seconds = seconds;
+  rc = DosWrite (hpServer, &req, sizeof (req), &cb);
+  if (rc != 0)
+    {
+      rc = DosClose (hpServer);
+      connect_level = 0;
+      return -1;
+    }
+  return 0;
+}
+
+
+int _emxload_do_receive (answer *ans)
+{
+  ULONG rc, cb;
+
+  rc = DosRead (hpServer, ans, sizeof (answer), &cb);
+  if (rc != 0 || cb != sizeof (answer))
+    {
+      rc = DosClose (hpServer);
+      connect_level = 0;
+      return -1;
+    }
+  return 0;
+}
+
+
+int _emxload_do_wait (void)
+{
+  answer dummy;
+
+  return _emxload_do_receive (&dummy);
+}
+
+
+int _emxload_request (int req_code, const char *name, int seconds)
+{
+  int result;
+
+  if (_osmode != OS2_MODE)
+    return -1;
+  switch (req_code)
+    {
+    case _EMXLOAD_LOAD:
+      if (_emxload_do_connect (TRUE) != 0)
+        return -1;
+      result = _emxload_do_request (req_code, name, seconds);
+      if (_emxload_do_disconnect (FALSE) != 0)
+        result = -1;
+      return result;
+
+    case _EMXLOAD_UNLOAD:
+    case _EMXLOAD_UNLOAD_WAIT:
+      if (_emxload_do_connect (FALSE) != 0)
+        return 0;
+      result = _emxload_do_request (req_code, name, seconds);
+      if (req_code == _EMXLOAD_UNLOAD_WAIT && _emxload_do_wait () != 0)
+        result = -1;
+      if (_emxload_do_disconnect (FALSE) != 0)
+        result = -1;
+      return result;
+
+    case _EMXLOAD_CONNECT:
+      return _emxload_do_connect (TRUE);
+
+    case _EMXLOAD_STOP:
+    case _EMXLOAD_STOP_WAIT:
+      if (_emxload_do_connect (FALSE) != 0)
+        return -1;
+      result = _emxload_do_request (req_code, NULL, 0);
+      if (req_code == _EMXLOAD_STOP_WAIT && connect_level > 0)
+        _emxload_do_wait ();    /* Will always fail */
+      _emxload_do_disconnect (TRUE); /* DosClose may fail */
+      return result;
+
+    case _EMXLOAD_DISCONNECT:
+      return _emxload_do_disconnect (TRUE);
+
+    default:
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/emxload/emxloadt.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloadt.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloadt.c	(revision 18)
@@ -0,0 +1,14 @@
+/* emxloadt.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/emxload.h>
+
+int _emxload_this (int seconds)
+{
+  char name[MAXPATHLEN];
+
+  if (_execname (name, sizeof (name)) != 0)
+    return -1;
+  return _emxload_prog (name, seconds);
+}
Index: trunk/src/emx/src/lib/emxload/emxloadu.c
===================================================================
--- trunk/src/emx/src/lib/emxload/emxloadu.c	(revision 18)
+++ trunk/src/emx/src/lib/emxload/emxloadu.c	(revision 18)
@@ -0,0 +1,21 @@
+/* emxloadu.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/emxload.h>
+#include <emx/emxload.h>
+
+int _emxload_unload (const char *name, int wait_flag)
+{
+  char buf1[MAXPATHLEN];
+  char buf2[MAXPATHLEN];
+  int req_code;
+
+  _strncpy (buf1, name, sizeof (buf1));
+  _defext (buf1, "exe");
+  if (_path (buf2, buf1) != 0 || _abspath (buf2, buf2, sizeof (buf2)) != 0)
+    return -1;
+  req_code = (wait_flag ? _EMXLOAD_UNLOAD_WAIT : _EMXLOAD_UNLOAD);
+  return _emxload_request (req_code, buf2, 0);
+}
Index: trunk/src/emx/src/lib/emxload/makefile
===================================================================
--- trunk/src/emx/src/lib/emxload/makefile	(revision 18)
+++ trunk/src/emx/src/lib/emxload/makefile	(revision 18)
@@ -0,0 +1,25 @@
+#
+# /emx/src/lib/emxload/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+EMXLOAD=$(S)emxload.h
+
+emxloadc.o: emxloadc.c $(EMXLOAD) $(I)stdlib.h $(I)emx/emxload.h
+emxloadd.o: emxloadd.c $(EMXLOAD) $(I)stdlib.h $(I)emx/emxload.h
+emxloade.o: emxloade.c $(EMXLOAD) $(I)stdlib.h $(ERRNO)
+emxloadl.o: emxloadl.c $(EMXLOAD) $(I)stdlib.h $(I)string.h
+emxloado.o: emxloado.c $(EMXLOAD) $(I)stdlib.h $(I)emx/emxload.h
+emxloadp.o: emxloade.c $(EMXLOAD) $(I)stdlib.h $(I)string.h $(S)param.h \
+		$(I)emx/emxload.h
+emxloadr.o: emxloadr.c $(EMXLOAD) $(I)stdlib.h $(I)string.h $(I)process.h \
+		$(I)os2emx.h $(I)emx/emxload.h
+emxloadt.o: emxloadt.c $(EMXLOAD) $(I)stdlib.h $(S)param.h
+emxloadu.o: emxloadu.c $(EMXLOAD) $(I)stdlib.h $(I)string.h $(S)param.h \
+		$(I)emx/emxload.h
+
+$(DSTLIB): emxloadc.o emxloadd.o emxloade.o emxloadl.o emxloado.o \
+		emxloadp.o emxloadr.o emxloadt.o emxloadu.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/end/386/edata.asm
===================================================================
--- trunk/src/emx/src/lib/end/386/edata.asm	(revision 18)
+++ trunk/src/emx/src/lib/end/386/edata.asm	(revision 18)
@@ -0,0 +1,11 @@
+; edata.asm (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes
+
+                .386
+
+                PUBLIC  _edata
+
+________DATA    SEGMENT PUBLIC USE32 'DATA'
+_edata          LABEL BYTE
+________DATA    ENDS
+
+                END
Index: trunk/src/emx/src/lib/end/386/end.asm
===================================================================
--- trunk/src/emx/src/lib/end/386/end.asm	(revision 18)
+++ trunk/src/emx/src/lib/end/386/end.asm	(revision 18)
@@ -0,0 +1,16 @@
+; end.asm (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes
+
+                .386
+
+                PUBLIC  _end
+
+c_common        SEGMENT PUBLIC USE32 'BSS'
+c_common        ENDS
+
+________BSS     SEGMENT PUBLIC USE32 'BSS'
+_end            LABEL BYTE
+________BSS     ENDS
+
+DGROUP          GROUP   c_common, ________BSS
+
+                END
Index: trunk/src/emx/src/lib/end/386/etext.asm
===================================================================
--- trunk/src/emx/src/lib/end/386/etext.asm	(revision 18)
+++ trunk/src/emx/src/lib/end/386/etext.asm	(revision 18)
@@ -0,0 +1,11 @@
+; etext.asm (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes
+
+                .386
+
+                PUBLIC  _etext
+
+________TEXT    SEGMENT PUBLIC USE32 'CODE'
+_etext          LABEL BYTE
+________TEXT    ENDS
+
+                END
Index: trunk/src/emx/src/lib/end/386/weakzero.asm
===================================================================
--- trunk/src/emx/src/lib/end/386/weakzero.asm	(revision 18)
+++ trunk/src/emx/src/lib/end/386/weakzero.asm	(revision 18)
@@ -0,0 +1,10 @@
+; weakzero.asm (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes
+
+                .386
+
+                PUBLIC  WEAK$ZERO
+
+WEAK$ZERO       =       0
+
+                END
+
Index: trunk/src/emx/src/lib/end/makefile
===================================================================
--- trunk/src/emx/src/lib/end/makefile	(revision 18)
+++ trunk/src/emx/src/lib/end/makefile	(revision 18)
@@ -0,0 +1,34 @@
+#
+# /emx/src/lib/end/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.PHONY: clean default dstlib end
+
+#
+# Requires MASM 6.0
+#
+.asm.obj:
+	ml -c -nologo -Cp $<
+
+LIBEND=$(L)end.lib
+
+default:    end
+
+end .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(LIBEND)
+
+clean:
+	-del $(CPU)\*.obj $(DELOPT)
+
+edata.obj: edata.asm
+end.obj: end.asm
+etext.obj: etext.asm
+weakzero.obj: weakzero.asm
+
+OBJECTS=edata.obj end.obj etext.obj weakzero.obj
+
+$(LIBEND): $(OBJECTS)
+	emxomfar r $(LIBEND) $(OBJECTS)
Index: trunk/src/emx/src/lib/io/386/binmode.s
===================================================================
--- trunk/src/emx/src/lib/io/386/binmode.s	(revision 18)
+++ trunk/src/emx/src/lib/io/386/binmode.s	(revision 18)
@@ -0,0 +1,9 @@
+/ binmode.s (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes
+
+        .text
+
+L_setbinmode:
+        movl    $1, __fmode_bin
+        ret
+
+        .stabs  "___CTOR_LIST__", 23, 0, 0, L_setbinmode
Index: trunk/src/emx/src/lib/io/_crlf.c
===================================================================
--- trunk/src/emx/src/lib/io/_crlf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_crlf.c	(revision 18)
@@ -0,0 +1,40 @@
+/* _crlf.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <io.h>
+
+/* Do CR/LF -> LF conversion in the buffer BUF containing SIZE characters. */
+/* Store the number of resulting characters to *NEW_SIZE. This value does  */
+/* not include the final CR, if present. If the buffer ends with CR, 1 is  */
+/* returned, 0 otherwise.                                                  */
+
+int _crlf (char *buf, size_t size, size_t *new_size)
+{
+  size_t src, dst;
+  char *p;
+
+  p = memchr (buf, '\r', size); /* Avoid copying until CR reached */
+  if (p == NULL)                /* This is the trivial case */
+    {
+      *new_size = size;
+      return 0;
+    }
+  src = dst = p - buf;          /* Start copying here */
+  while (src < size)
+    {
+      if (buf[src] == '\r')     /* CR? */
+        {
+          ++src;                /* Skip the CR */
+          if (src >= size)      /* Is it the final char? */
+            {
+              *new_size = dst;  /* Yes -> don't include in new_size, */
+              return 1;         /*        notify caller              */
+            }
+          if (buf[src] != '\n') /* CR not followed by LF? */
+            --src;              /* Yes -> copy the CR */
+        }
+      buf[dst++] = buf[src++];  /* Copy a character */
+    }
+  *new_size = dst;
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/_fbuf.c
===================================================================
--- trunk/src/emx/src/lib/io/_fbuf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_fbuf.c	(revision 18)
@@ -0,0 +1,32 @@
+/* _fbuf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+/* Assign a buffer to a stream (which must not have a buffer) */
+
+void _fbuf (FILE *stream)
+{
+  if (stream->_flags & _IONBF)
+    stream->_buffer = NULL;
+  else
+    stream->_buffer = malloc (BUFSIZ);
+  if (stream->_buffer == NULL)
+    {
+      stream->_buf_size = 1;
+      stream->_buffer = &stream->_char_buf;
+      stream->_flags &= ~(_IOFBF|_IOLBF|_IOBUFMASK);
+      stream->_flags |= _IONBF|_IOBUFCHAR;
+    }
+  else
+    {
+      stream->_buf_size = BUFSIZ;
+      stream->_flags &= ~_IOBUFMASK;
+      stream->_flags |= _IOBUFLIB;
+    }
+  stream->_ptr = stream->_buffer;
+  stream->_rcount = 0;
+  stream->_wcount = 0;
+  stream->_ungetc_count = 0;
+}
Index: trunk/src/emx/src/lib/io/_fd.c
===================================================================
--- trunk/src/emx/src/lib/io/_fd.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_fd.c	(revision 18)
@@ -0,0 +1,68 @@
+/* _fd.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <emx/io.h>
+
+/* See app/iodata.c. */
+
+extern int _nfiles;
+extern int _files[];
+extern int _lookahead[];
+
+/* Return pointer to flags word for the file descriptor HANDLE.
+   Return NULL on error. */
+
+int *_fd_flags (int handle)
+{
+  struct fdvec *p;
+
+  if (handle < 0)
+    return NULL;
+
+  /* We want this case to be fast.  Note that _fdvec_head.n == _nfiles
+     and _fdvec_head.flags == _files! */
+
+  if (handle < _nfiles)
+    return &_files[handle];
+
+  handle -= _nfiles;
+  p = _fdvec_head.next;
+  while (p != NULL && handle >= p->n)
+    {
+      handle -= p->n;
+      p = p->next;
+    }
+  if (p == NULL)
+    return NULL;
+  return &p->flags[handle];
+}
+
+
+/* Return pointer to lookahead word for the file descriptor HANDLE.
+   Return NULL on error.
+
+   Note: select() does this inline. */
+
+int *_fd_lookahead (int handle)
+{
+  struct fdvec *p;
+
+  if (handle < 0)
+    return NULL;
+
+  /* We want this case to be fast.  Note that _fdvec_head.n == _nfiles
+     and _fdvec_head.lookahead == _lookahead! */
+
+  if (handle < _nfiles)
+    return &_lookahead[handle];
+
+  handle -= _nfiles;
+  p = _fdvec_head.next;
+  while (p != NULL && handle >= p->n)
+    {
+      handle -= p->n;
+      p = p->next;
+    }
+  if (p == NULL)
+    return NULL;
+  return &p->lookahead[handle];
+}
Index: trunk/src/emx/src/lib/io/_fdinit.c
===================================================================
--- trunk/src/emx/src/lib/io/_fdinit.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_fdinit.c	(revision 18)
@@ -0,0 +1,126 @@
+/* _fdinit.c (emx+gcc) -- Copyright (c) 1996-1997 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/io.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/startup.h>
+
+/* See app/iodata.c. */
+
+extern int _nfiles;
+extern int _files[];
+extern int _lookahead[];
+
+#if defined (__MT__)
+
+/* This semaphore protects a critical region in _fd_init(). */
+
+static _rmutex _fdinit_rmutex;
+
+
+/* Initialize the semaphore -- this function will be called by
+   _startup() via the __crtinit1__ set vector. */
+
+void _init1_fdinit (void)
+{
+  _rmutex_checked_create (&_fdinit_rmutex, 0);
+}
+
+_CRT_INIT1 (_init1_fdinit)
+
+#endif
+
+
+/* Return pointer to flags word for the new file descriptor HANDLE and
+   initialize lookahead.  Return NULL on error. */
+
+int *_fd_init (int handle)
+{
+  struct fdvec *p, *last;
+  int i, n;
+
+  if (handle < 0)
+    return NULL;
+
+  p = &_fdvec_head; last = NULL;
+  while (p != NULL && handle >= p->n)
+    {
+      handle -= p->n;
+      last = p;
+      p = p->next;
+    }
+  if (p == NULL)
+    {
+      n = handle + 1;
+      if (n < 32) n = 32;
+
+      p = malloc (sizeof (*p));
+      if (p == NULL)
+        return NULL;
+      p->flags = malloc (n * sizeof (int));
+      if (p->flags == NULL)
+        {
+          free (p);
+          return NULL;
+        }
+      p->lookahead = malloc (n * sizeof (int));
+      if (p->lookahead == NULL)
+        {
+          free (p->flags);
+          free (p);
+          return NULL;
+        }
+      for (i = 0; i < n; ++i)
+        {
+          p->flags[i] = 0;
+          p->lookahead[i] = -1;
+        }
+      p->n = n;
+      p->next = NULL;
+
+#if defined (__MT__)
+      /* Prevent other threads from updating last->next. */
+
+      _rmutex_checked_request (&_fdinit_rmutex, _FMR_IGNINT);
+
+      /* Now that we have locked other threads out of this critical
+         region, update last->next unless another thread has updated
+         last->next before this thread entered the critical region. */
+
+      if (last->next == NULL)
+        last->next = p;
+
+      /* End of critical region. From now on, last->next is non-NULL
+         and therefore won't be changed by other threads. */
+
+      _rmutex_checked_release (&_fdinit_rmutex);
+
+      /* If another thread updated last->next, back out and retry,
+         using the elements added by the other threads.  As we keep p
+         pointing to malloc()ed memory around the critical region,
+         other threads may not happen to use the same value of p. */
+
+      if (last->next != p)
+        {
+          /* Another thread did the work. */
+
+          free (p->flags);
+          free (p->lookahead);
+          free (p);
+
+          /* The other thread might have requested fewer new elements
+             than this thread, therefore we do not assign last->next
+             to p!  We start over, instead. */
+
+          return _fd_init (handle);
+        }
+#else
+      last->next = p;
+#endif
+    }
+
+  p->lookahead[handle] = -1;
+  return &p->flags[handle];
+}
Index: trunk/src/emx/src/lib/io/_fill.c
===================================================================
--- trunk/src/emx/src/lib/io/_fill.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_fill.c	(revision 18)
@@ -0,0 +1,103 @@
+/* _fill.c (emx+gcc) -- Copyright (c) 1990-2000 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+
+/* Note: _fill() now (as of emx 0.9a fix04) assumes that `rcount' has
+   been decremented prior to calling _fill().  See ungetc.c for
+   details. */
+
+int _fill (FILE *stream)
+{
+  /* Undo decrementing of `rcount'.  This wasn't required in earlier
+     versions as `rcount' was set but not examined by _fill().
+     Moreover, this fixes the bug of `rcount' being wrong if _fill()
+     fails. */
+
+  ++stream->_rcount;
+
+  /* Fail (without setting errno) for sscanf(). */
+
+  if ((stream->_flags & _IOSPECIAL) && stream->_flush == NULL)
+    return EOF;
+
+  /* Fail if the stream is not open. */
+
+  if (!(stream->_flags & _IOOPEN))
+    {
+      errno = EACCES;
+      return EOF;
+    }
+
+  /* Fail if the stream is in write mode. */
+
+  if (stream->_flags & _IOWRT)
+    {
+      stream->_flags |= _IOERR;
+      errno = EACCES;
+      return EOF;
+    }
+
+  if (stream->_ungetc_count != 0)
+    {
+      int c;
+
+      /* There are pushed-back characters.  Return the most recent one
+         and undo the effects of one ungetc() call. */
+
+      stream->_ungetc_count -= 1;
+      c = (unsigned char)stream->_buffer[stream->_ungetc_count];
+
+      if (stream->_ungetc_count == 0)
+        stream->_rcount = -stream->_rcount;
+
+      return c;
+    }
+
+  if (stream->_flags & _IOSPECIAL)
+    {
+      if (stream->_flush != NULL)
+        return stream->_flush (stream, _FLUSH_FILL);
+      errno = EACCES;
+      return EOF;
+    }
+
+  /* Switch to read mode. */
+
+  stream->_flags |= _IOREAD;
+  stream->_wcount = 0;
+  if (nbuf (stream))
+    _fbuf (stream);
+  else
+    stream->_ptr = stream->_buffer;
+
+  /* Fill the buffer. */
+
+  stream->_flags &= ~_IOUNGETC;
+  stream->_rcount = _stream_read (stream->_handle, stream->_buffer,
+                                  stream->_buf_size);
+  if (stream->_rcount < 0)
+    {
+      stream->_flags |= _IOERR;
+      stream->_rcount = 0;
+      return EOF;
+    }
+
+  /* Check for EOF. */
+
+  if (stream->_rcount == 0)
+    {
+      stream->_flags |= _IOEOF;
+      if (stream->_flags & _IORW)
+        stream->_flags &= ~(_IOREAD|_IOWRT);
+      return EOF;
+    }
+
+  /* Return the next character. */
+
+  --stream->_rcount;
+  return (unsigned char)*stream->_ptr++;
+}
Index: trunk/src/emx/src/lib/io/_flush.c
===================================================================
--- trunk/src/emx/src/lib/io/_flush.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_flush.c	(revision 18)
@@ -0,0 +1,43 @@
+/* _flush.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _flush (int c, FILE *stream)
+{
+  stream->_wcount = 0;          /* Undo decrement to avoid negative value */
+
+  /* Don't flag an error attempting to write beyond the end of the
+     string for snprintf() as we need the total number of characters
+     printed. */
+
+  if ((stream->_flags & _IOSPECIAL) && stream->_flush == NULL)
+    return (unsigned char)c;
+
+  /* Fail if the stream is not open or there is no function for
+     flushing the buffer. */
+
+  if (!(stream->_flags & _IOOPEN) || stream->_flush == NULL)
+    {
+      errno = EACCES;
+      return EOF;
+    }
+
+  /* Fail if the stream is in read mode. */
+
+  if (stream->_flags & _IOREAD)
+    {
+      stream->_flags |= _IOERR;
+      errno = EACCES;
+      return EOF;
+    }
+
+  /* Flush the buffer and put C into the buffer. */
+
+  if (stream->_flush (stream, (unsigned char)c) != 0)
+    return EOF;
+  return (unsigned char)c;
+}
Index: trunk/src/emx/src/lib/io/_flushst.c
===================================================================
--- trunk/src/emx/src/lib/io/_flushst.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_flushst.c	(revision 18)
@@ -0,0 +1,83 @@
+/* _flushst.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _flushstream (FILE *stream, int c)
+{
+  int n, w, fh;
+  char ch;
+
+  fh = stream->_handle;
+  if (c == _FLUSH_FILL)
+    {
+      /* Does not happen. */
+
+      errno = EACCES;
+      return EOF;
+    }
+  else
+    {
+      stream->_flags |= _IOWRT;       /* Switch to write mode */
+      stream->_rcount = 0;
+      stream->_flags &= ~_IOEOF;      /* Clear EOF flag, writing! */
+      stream->_wcount = 0;            /* Maybe negative at this point */
+      if (nbuf (stream))
+        _fbuf (stream);
+      if (bbuf (stream))
+        {
+          n = stream->_ptr - stream->_buffer;
+          if (n > 0)            /* n should never be < 0 */
+            {
+              /* Try to use a single write() call.  This can succeed
+                 only if _flush() is called before the buffer is
+                 full.  This can happen only when writing a '\n' to a
+                 line-buffered file, which is exactly the case where
+                 we want to do a single write(). */
+              if (n < stream->_buf_size)
+                {
+                  *stream->_ptr = (char)c;
+                  ++n;
+                  c = -1;       /* Don't write character separately */
+                }
+              w = _stream_write (fh, stream->_buffer, n);
+            }
+          else                  /* New or flushed buffer */
+            {
+              int *pflags = _fd_flags (fh);
+              w = 0;
+              if (pflags != NULL && (*pflags & O_APPEND))
+                _lseek (fh, 0L, SEEK_END);
+            }
+          stream->_ptr = stream->_buffer;
+          stream->_wcount = stream->_buf_size;
+          if (c == '\n' && (stream->_flags & _IOLBF))
+            {
+              ch = (char)c;
+              if (_stream_write (fh, &ch, 1) != 1)
+                ++n;            /* n != w */
+            }
+          else if (c >= 0)      /* -1: already written */
+            {
+              *stream->_ptr++ = (char)c;
+              --stream->_wcount;
+            }
+        }
+      else
+        {
+          n = 1;
+          ch = (char)c;
+          w = _stream_write (fh, &ch, 1);
+          stream->_wcount = 0;
+        }
+      if (n != w)
+        {
+          stream->_flags |= _IOERR;
+          return EOF;
+        }
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/_fopen.c
===================================================================
--- trunk/src/emx/src/lib/io/_fopen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_fopen.c	(revision 18)
@@ -0,0 +1,94 @@
+/* _fopen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+
+#define FALSE   0
+#define TRUE    1
+
+FILE *_fopen (FILE *dst, const char *fname, const char *mode, int shflag,
+              int lock)
+{
+  char ok, bt;
+  int omode;
+
+  switch (*mode)
+    {
+    case 'r':
+      dst->_flags = _IOREAD;
+      omode = O_RDONLY;
+      break;
+    case 'w':
+      dst->_flags = _IOWRT;
+      omode = O_WRONLY|O_CREAT|O_TRUNC;
+      break;
+    case 'a':
+      dst->_flags = _IOWRT;
+      omode = O_WRONLY|O_CREAT|O_APPEND;
+      break;
+    default:
+      errno = EINVAL;
+      _closestream (dst);
+      return NULL;
+    }
+  ++mode; ok = TRUE; bt = FALSE;
+  while (*mode != 0 && ok)
+    {
+      switch (*mode)
+        {
+        case 't':
+          if (bt)
+            ok = FALSE;
+          else
+            {
+              bt = TRUE;
+              omode |= O_TEXT;
+            }
+          break;
+        case 'b':
+          if (bt)
+            ok = FALSE;
+          else
+            {
+              bt = TRUE;
+              omode |= O_BINARY;
+            }
+          break;
+        case '+':
+          if (dst->_flags & _IORW)
+            ok = FALSE;
+          else
+            {
+              omode &= ~(O_RDONLY|O_WRONLY);
+              omode |= O_RDWR;
+              dst->_flags &= ~(_IOREAD|_IOWRT);
+              dst->_flags |= _IORW;
+            }
+          break;
+        default:
+          ok = FALSE; break;
+        }
+      if (ok) ++mode;
+    }
+  dst->_ptr = NULL;
+  dst->_buffer = NULL;
+  dst->_buf_size = 0;
+  dst->_rcount = 0;
+  dst->_wcount = 0;
+  dst->_tmpidx = 0;
+  dst->_ungetc_count = 0;
+  dst->_flags |= _IOOPEN | _IOBUFNONE;
+  dst->_flush = _flushstream;
+  if (_setmore (dst, lock) != 0)
+    return NULL;
+  dst->_handle = _sopen (fname, omode, shflag, 0644);
+  if (dst->_handle < 0)
+    {
+      _closestream (dst);
+      return NULL;
+    }
+  return dst;
+}
Index: trunk/src/emx/src/lib/io/_fseekhd.c
===================================================================
--- trunk/src/emx/src/lib/io/_fseekhd.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_fseekhd.c	(revision 18)
@@ -0,0 +1,47 @@
+/* _fseekhd.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <memory.h>
+#include <errno.h>
+
+int _fseek_hdr (FILE *stream)
+{
+  struct
+    {
+      char magic[2];
+      char fill1[6];
+      unsigned short hdr_size;
+    } exe_hdr;
+  struct
+    {
+      char sig[16];
+      char bound;
+      char fill1;
+      unsigned short hdr_loc_lo;      /* cannot use long, alignment! */
+      unsigned short hdr_loc_hi;
+    } patch;
+  long original_pos;
+  int saved_errno;
+
+  original_pos = ftell (stream);
+  if (fread (&exe_hdr, sizeof (exe_hdr), 1, stream) != 1)
+    goto failure;
+  if (memcmp (exe_hdr.magic, "MZ", 2) != 0)
+    return (fseek (stream, original_pos, SEEK_SET) == -1 ? -1 : 0);
+  if (fseek (stream, original_pos + 16 * exe_hdr.hdr_size, SEEK_SET) == -1)
+    goto failure;
+  if (fread (&patch, sizeof (patch), 1, stream) != 1)
+    goto failure;
+  if (memcmp (patch.sig, "emx", 3) != 0)
+    goto failure;
+  if (fseek (stream, original_pos + patch.hdr_loc_lo
+             + 65536L * patch.hdr_loc_hi, SEEK_SET) == -1)
+    goto failure;
+  return 0;
+
+failure:
+  saved_errno = errno;
+  fseek (stream, original_pos, SEEK_SET);
+  errno = saved_errno;
+  return -1;
+}
Index: trunk/src/emx/src/lib/io/_fsetmod.c
===================================================================
--- trunk/src/emx/src/lib/io/_fsetmod.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_fsetmod.c	(revision 18)
@@ -0,0 +1,24 @@
+/* _fsetmod.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+
+int _fsetmode (FILE *stream, const char *mode)
+{
+  int i;
+
+  if (*mode == 'b')
+    i = O_BINARY;
+  else if (*mode == 't')
+    i = O_TEXT;
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (_setmode (stream->_handle, i) == -1)
+    return -1;
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/_fsopen.c
===================================================================
--- trunk/src/emx/src/lib/io/_fsopen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_fsopen.c	(revision 18)
@@ -0,0 +1,14 @@
+/* _fsopen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <emx/io.h>
+
+FILE *_fsopen (const char *fname, const char *mode, int shflag)
+{
+  FILE *f;
+
+  f = _newstream ();
+  if (f != NULL)
+    f = _fopen (f, fname, mode, shflag, 1);
+  return f;
+}
Index: trunk/src/emx/src/lib/io/_imphand.c
===================================================================
--- trunk/src/emx/src/lib/io/_imphand.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_imphand.c	(revision 18)
@@ -0,0 +1,51 @@
+/* _imphand.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _fmode_bin;
+
+int _imphandle (int handle)
+{
+  int fd, rc, ht, *pflags;
+
+  if (handle < 0)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  fd = __imphandle (handle);
+  if (fd == -1)
+    return -1;
+  pflags = _fd_init (fd);
+  if (pflags == NULL)
+    {
+      /* `fd' has been relocated and is now out of range. */
+
+      __dup2 (fd, handle);
+      __close (fd);
+      errno = EBADF;
+      return -1;
+    }
+
+  *pflags = O_RDWR;             /* TODO */
+  if (_fmode_bin == 0)
+    *pflags |= O_TEXT;
+  rc = __ioctl1 (fd, 0);
+  if (rc != -1 && (rc & 0x80))
+    *pflags |= F_DEV;
+  rc = __ioctl2 (fd, FGETHTYPE, (int)&ht);
+  if (rc >= 0)
+    {
+      if (HT_ISDEV (ht))
+        *pflags |= F_DEV;
+      if (ht == HT_UPIPE || ht == HT_NPIPE)
+        *pflags |= F_PIPE;
+    }
+  return fd;
+}
Index: trunk/src/emx/src/lib/io/_input.c
===================================================================
--- trunk/src/emx/src/lib/io/_input.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_input.c	(revision 18)
@@ -0,0 +1,767 @@
+/* _input.c (emx+gcc) -- Copyright (c) 1990-2000 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <locale.h>
+#include <emx/locale.h>
+#include <emx/io.h>
+
+#define FALSE   0
+#define TRUE    1
+
+/* This structure holds the local variables of _input() which are
+   passed to the functions called by _input(). */
+
+typedef struct
+{
+  FILE *stream;                 /* Where input comes from */
+  int width;                    /* Field width or what's left over of it */
+  int chars;                    /* Number of characters read */
+  int volatile count;           /* Number of fields assigned */
+  char * volatile more;         /* Big buffer for %e format */
+  int collected;                /* Number of characters collected */
+  size_t more_size;             /* Size of the above */
+  char size;                    /* Size (0, 'h', 'l' or 'L') */
+  char width_given;             /* A field width has been given */
+  unsigned char ungetc_count;   /* stream's _ungetc_count prior to get0() */
+  enum
+    {
+      OK,                       /* Situation normal */
+      END_OF_FILE,              /* End of file (stop at next directive) */
+      MATCHING_FAILURE,         /* Matching failure (stop immediately) */
+      INPUT_FAILURE,            /* Input failure (stop immediately) */
+      OUT_OF_MEMORY             /* Out of memory (stop immediately) */
+    } status;
+} ilocal;
+
+
+/* Return the next input character.  Return EOF on input failure.
+   This is the only place where input is read from the stream or
+   whatever.  This function must return a value representable by an
+   `unsigned char', or EOF.  Otherwise, isdigit() etc. won't work. */
+
+static int get0 (ilocal *v)
+{
+  int c;
+
+  /* Save the stream's _ungetc_count; we need this to decide whether
+     to push back or leave unread the character if we don't eat it. */
+
+  v->ungetc_count = v->stream->_ungetc_count;
+
+  /* Read a character from the stream. */
+
+  c = _getc_inline (v->stream);
+  if (c == EOF)
+    {
+      v->status = END_OF_FILE;
+      return EOF;
+    }
+  ++v->chars;
+  return (unsigned char)c;
+}
+
+
+/* Return the next character of the current input field.  Return EOF
+   if the field width is exhausted or on input failure. */
+
+static int get (ilocal *v)
+{
+  if (v->width == 0)
+    return EOF;
+  --v->width;
+  return get0 (v);
+}
+
+
+/* Undo reading the previously read character.  Do not use ungetc()
+   unless it has been put into the stream with ungetc(). */
+
+static void make_unread (ilocal *v, int c)
+{
+  if (c != EOF)
+    {
+      if (v->ungetc_count != 0)
+        {
+          /* This case is simple: the character was put into the
+             stream with ungetc(), so we must also push it back with
+             ungetc(). */
+
+          _ungetc_nolock (c, v->stream);
+        }
+      else
+        {
+          /* Pretend that the character was not read.  Don't forget to
+             reset the EOF indicator! */
+
+          if (v->stream->_ptr == v->stream->_buffer)
+            abort ();
+          --v->stream->_ptr;
+          ++v->stream->_rcount;
+          v->stream->_flags &= ~_IOEOF;
+        }
+      --v->chars;
+    }
+}
+
+
+#define COLLECT(X) do { collect (v, (unsigned char *)buf, sizeof (buf), X); \
+                        if (v->status == OUT_OF_MEMORY) return; } while (0)
+
+static void collect (ilocal *v, unsigned char *buf, size_t buf_size,
+                     unsigned char c)
+{
+  if (v->more == NULL && v->collected < buf_size)
+    buf[v->collected] = c;
+  else
+    {
+      if (v->collected >= v->more_size)
+        {
+          v->more_size += 512;
+          v->more = realloc (v->more, v->more_size);
+          if (v->more == NULL)
+            {
+              v->status = OUT_OF_MEMORY;
+              return;
+            }
+          if (v->collected == buf_size)
+            memcpy (v->more, buf, buf_size);
+        }
+      v->more[v->collected] = c;
+    }
+  ++v->collected;
+}
+
+
+/* Skip leading whitespace of an input field and return the first
+   non-whitespace character.  Hitting EOF is treated as input failure.
+   Don't forget to check `v->status' after calling this function. */
+
+static int skip (ilocal *v)
+{
+  int c;
+
+  do
+    {
+      c = get0 (v);
+      if (c == EOF)
+        {
+          v->status = INPUT_FAILURE;
+          return EOF;
+        }
+    } while (isspace (c));
+
+  /* We have read one character of the field, therefore we have to
+     decrement `v->width'.  Note that `v->width' is never zero on
+     entry to skip(). */
+
+  --v->width;
+  return c;
+}
+
+
+static void inp_char (ilocal *v, unsigned char *dst)
+{
+  int c, ok;
+
+  if (v->status == END_OF_FILE)
+    {
+      v->status = INPUT_FAILURE;
+      return;
+    }
+  if (!v->width_given)
+    v->width = 1;
+  ok = FALSE;
+  while ((c = get (v)) != EOF)
+    {
+      ok = TRUE;
+      if (dst != NULL)
+        *dst++ = (unsigned char)c;
+    }
+  if (!ok)
+    v->status = INPUT_FAILURE;
+  else if (dst != NULL)
+    ++v->count;
+}
+
+
+static void inp_str (ilocal *v, unsigned char *dst)
+{
+  int c;
+
+  c = skip (v);
+  if (v->status != OK) return;
+  while (c != EOF && !isspace (c))
+    {
+      if (dst != NULL)
+        *dst++ = (unsigned char)c;
+      c = get (v);
+    }
+  if (dst != NULL)
+    {
+      *dst = 0;
+      ++v->count;
+    }
+  make_unread (v, c);
+}
+
+
+static void inp_set (ilocal *v, const char **pfmt, unsigned char *dst)
+{
+  char map[256], end, done;
+  unsigned char f;
+  const char *format;
+  int c, i, ok;
+
+  if (v->status == END_OF_FILE)
+    {
+      v->status = INPUT_FAILURE;
+      return;
+    }
+  format = *pfmt;
+  memset (map, 0, 256);
+  end = 0;
+  ++format;
+  if (*format == '^')
+    {
+      ++format; end = 1;
+    }
+  i = 0; done = 0;
+  do
+    {
+      f = (unsigned char)*format;
+      switch (f)
+        {
+        case 0:
+          *pfmt = format - 1;   /* Avoid skipping past 0 */
+          done = 1;
+          break;
+        case ']':
+          if (i > 0)
+            {
+              *pfmt = format;
+              done = 1;
+              break;
+            }
+          /* no break */
+        default:
+          if (format[1] == '-' && format[2] != 0 && format[2] != ']'
+              && f < (unsigned char)format[2])
+            {
+              memset (map+f, 1, (unsigned char)format[2] - f + 1);
+              format += 2;
+            }
+          else
+            map[f] = 1;
+          break;
+        }
+      ++format; ++i;
+    } while (!done);
+  ok = FALSE;
+  c = get (v);
+  while (c != EOF && map[c] != end)
+    {
+      ok = TRUE;
+      if (dst != NULL)
+        *dst++ = (unsigned char)c;
+      c = get (v);
+    }
+  if (!ok)
+    {
+      make_unread (v, c);
+      v->status = MATCHING_FAILURE;
+      return;
+    }
+  if (dst != NULL)
+    {
+      *dst = 0;
+      ++v->count;
+    }
+  make_unread (v, c);
+}
+
+
+static void inp_int_base (ilocal *v, void *dst, int base)
+{
+  char neg, ok;
+  unsigned long long n;
+  int c, digit;
+
+  c = skip (v);
+  if (v->status != OK) return;
+  neg = FALSE;
+  if (c == '+')
+    c = get (v);
+  else if (c == '-')
+    {
+      neg = TRUE;
+      c = get (v);
+    }
+
+  n = 0; ok = FALSE;
+
+  if (base == 0)
+    {
+      base = 10;
+      if (c == '0')
+        {
+          c = get (v);
+          if (c == 'x' || c == 'X')
+            {
+              base = 16;
+              c = get (v);
+            }
+          else
+            {
+              base = 8;
+              ok = TRUE; /* We've seen a digit! */
+            }
+        }
+    }
+  else if (base == 16 && c == '0')
+    {
+      c = get (v);
+      if (c == 'x' || c == 'X')
+        c = get (v);
+      else
+        ok = TRUE;          /* We've seen a digit! */
+    }
+
+  while (c != EOF)
+    {
+      if (isdigit (c))
+        digit = c - '0';
+      else if (isupper (c))
+        digit = c - 'A' + 10;
+      else if (islower (c))
+        digit = c - 'a' + 10;
+      else
+        break;
+      if (digit < 0 || digit >= base)
+        break;
+      ok = TRUE;
+      n = n * base + digit;
+      c = get (v);
+    }
+  if (!ok)
+    {
+      make_unread (v, c);
+      v->status = MATCHING_FAILURE;
+      return;
+    }
+  if (neg)
+    n = -n;
+  if (dst != NULL)
+    {
+      switch (v->size)
+        {
+        case 'L':
+          *(long long *)dst = n;
+          break;
+        case 'h':
+          *(short *)dst = n;
+          break;
+        default:
+          *(int *)dst = n;
+          break;
+        }
+      ++v->count;
+    }
+  make_unread (v, c);
+}
+
+
+static void inp_int (ilocal *v, unsigned char f, void *dst)
+{
+  switch (f)
+    {
+    case 'i':
+      inp_int_base (v, dst, 0);
+      break;
+
+    case 'd':
+      inp_int_base (v, dst, 10);
+      break;
+
+    case 'u':
+      inp_int_base (v, dst, 10);
+      break;
+
+    case 'o':
+      inp_int_base (v, dst, 8);
+      break;
+
+    case 'x':
+    case 'X':
+    case 'p':
+      inp_int_base (v, dst, 16);
+      break;
+
+    default:
+      abort ();
+    }
+}
+
+
+static void inp_float (ilocal *v, void *dst)
+{
+  int c;
+  const char *text;
+  char *p, *q;
+  char ok;
+  char buf[128];
+  long double lx;
+  double dx;
+  float fx;
+
+  v->collected = 0;
+  c = skip (v);
+  if (v->status != OK) return;
+  ok = FALSE;
+  if (c == '+' || c == '-')
+    {
+      COLLECT (c);
+      c = get (v);
+    }
+  if (c == 'i' || c == 'I')
+    text = "infinity";
+  else if (c == 'n' || c == 'N')
+    text = "nan";
+  else
+    text = NULL;
+
+  if (text != NULL)
+    {
+      int n = 0;
+      do
+        {
+          ++n;
+          COLLECT (c);
+          c = get (v);
+        } while (text[n] != 0 && tolower (c) == text[n]);
+      if (text[n] == 0 && text[0] == 'n' && c == '(')
+        {
+          do
+            {
+              COLLECT (c);
+              c = get (v);
+            } while (c == '_' || isalnum (c));
+          if (c == ')')
+            {
+              COLLECT (c);
+              c = get (v);
+            }
+          else
+            n = 0;              /* Matching failure */
+        }
+      if (!(text[n] == 0 || (text[0] == 'i' && n == 3)))
+        {
+          make_unread (v, c);
+          v->status = MATCHING_FAILURE;
+          return;
+        }
+    }
+  else
+    {
+      while (isdigit (c))
+        {
+          COLLECT (c);
+          ok = TRUE;
+          c = get (v);
+        }
+      if (c == (unsigned char)_cur_lconv.decimal_point[0])
+        {
+          COLLECT (c);
+          c = get (v);
+          while (isdigit (c))
+            {
+              COLLECT (c);
+              ok = TRUE;
+              c = get (v);
+            }
+        }
+      if (!ok)
+        {
+          make_unread (v, c);
+          v->status = MATCHING_FAILURE;
+          return;
+        }
+      
+      if (c == 'e' || c == 'E')
+        {
+          COLLECT (c);
+          c = get (v);
+          if (c == '+' || c == '-')
+            {
+              COLLECT (c);
+              c = get (v);
+            }
+          if (!isdigit (c))
+            {
+              make_unread (v, c);
+              v->status = MATCHING_FAILURE;
+              return;
+            }
+          while (isdigit (c))
+            {
+              COLLECT (c);
+              c = get (v);
+            }
+        }
+    }
+
+  make_unread (v, c);
+  COLLECT (0);
+
+  p = ((v->more != NULL) ? v->more : buf);
+  lx = 0.0; dx = 0.0; fx = 0.0;
+  switch (v->size)
+    {
+    case 'L':
+      lx = _strtold (p, &q); 
+      break;
+    case 'l':
+      dx = strtod (p, &q);
+      break;
+    default:
+      fx = _strtof (p, &q);
+      break;
+    }
+  if (q == buf || *q != 0) /* Ignore overflow! */
+    {
+      v->status = MATCHING_FAILURE;
+      return;
+    }
+  if (dst != NULL)
+    {
+      switch (v->size)
+        {
+        case 'L':
+          *(long double *)dst = lx;
+          break;
+        case 'l':
+          *(double *)dst = dx;
+          break;
+        default:
+          *(float *)dst = fx;
+          break;
+        }
+      ++v->count;
+    }
+}
+
+
+static int inp_main (ilocal *v, const char *format, char *arg_ptr)
+{
+  void *dst;
+  unsigned char f;
+  int c;
+  char assign;
+  int shift, mbi, mbn;
+
+  /* ISO 9899-1990, 7.9.6.2 "The format shall be a multibyte
+     character sequence, beginning and ending in its initial shift
+     state." */
+
+  shift = 0;
+
+  c = 0;
+  while ((f = *format) != 0)
+    {
+      if (isspace (f))
+        {
+          do
+            {
+              ++format; f = *format;
+            } while (isspace (f));
+          do
+            {
+              c = get0 (v);
+            } while (isspace (c));
+          make_unread (v, c);
+        }
+      else if (f != '%')
+        {
+          /* ISO 9899-1990, 7.9.6.2: "A directive that is an
+             ordinary multibyte character is executed by reading the
+             next characters of the stream.  If one of the characters
+             differs from one comprising the directive, the directive
+             fails, and the differing and subsequent characters remain
+             unread."
+
+             Avoid the overhead of calling mblen(). */
+
+          if (f <= 127 || _cur_mbyte.mode == _MB_8BITS)
+            mbn = 1;
+          else
+            {
+              mbn = _mbtowc (NULL, format, MB_LEN_MAX, &shift);
+              if (mbn < 1)
+                mbn = 1;        /* Treat an invalid character as is */
+            }
+          for (mbi = 0; mbi < mbn; ++mbi)
+            {
+              c = get0 (v);
+              if (c == EOF) return (v->count == 0 ? EOF : v->count);
+              if (c != (unsigned char)*format)
+                {
+                  /* ISO 9899 does not allow us to leave the entire
+                     multibyte character unread; only the non-matching
+                     byte will be left in the stream. */
+
+                  make_unread (v, c);
+                  return v->count;
+                }
+              ++format;
+            }
+        }
+      else
+        {
+          v->size = 0; v->width = INT_MAX; assign = TRUE; dst = NULL;
+          v->width_given = FALSE;
+          ++format;
+          if (*format == '*')
+            {
+              assign = FALSE;
+              ++format;
+            }
+          if (isdigit ((unsigned char)*format))
+            {
+              v->width = 0;
+              while (isdigit ((unsigned char)*format))
+                v->width = v->width * 10 + (*format++ - '0');
+
+              /* The behavior for a zero width is declared undefined
+                 by ISO 9899-1990.  In this implementation, a zero
+                 width is equivalent to no width being specified. */
+
+              if (v->width == 0)
+                v->width = INT_MAX;
+              else
+                v->width_given = TRUE;
+            }
+          if (*format == 'h' || *format == 'l' || *format == 'L')
+            v->size = *format++;
+          f = *format;
+          switch (f)
+            {
+            case 'c':
+              if (assign)
+                dst = va_arg (arg_ptr, char *);
+              inp_char (v, dst);
+              break;
+
+            case '[':
+              if (assign)
+                dst = va_arg (arg_ptr, char *);
+              inp_set (v, &format, dst);
+              break;
+
+            case 's':
+              if (assign)
+                dst = va_arg (arg_ptr, char *);
+              inp_str (v, dst);
+              break;
+
+            case 'f':
+            case 'e':
+            case 'E':
+            case 'g':
+            case 'G':
+              if (assign)
+                switch (v->size)
+                  {
+                  case 'L':
+                    dst = va_arg (arg_ptr, long double *);
+                    break;
+                  case 'l':
+                      dst = va_arg (arg_ptr, double *);
+                    break;
+                  default:
+                    dst = va_arg (arg_ptr, float *);
+                    break;
+                  }
+              inp_float (v, dst);
+              break;
+
+            case 'i':
+            case 'd':
+            case 'u':
+            case 'o':
+            case 'x':
+            case 'X':
+            case 'p':
+              if (assign)
+                switch (v->size)
+                  {
+                  case 'L':
+                    dst = va_arg (arg_ptr, long long *);
+                    break;
+                  case 'h':
+                    dst = va_arg (arg_ptr, short *);
+                    break;
+                  default:
+                    dst = va_arg (arg_ptr, int *);
+                    break;
+                  }
+              inp_int (v, f, dst);
+              break;
+
+            case 'n':
+              if (assign)
+                switch (v->size)
+                  {
+                  case 'L':
+                    *(va_arg (arg_ptr, long long *)) = v->chars;
+                    break;
+                  case 'h':
+                    *(va_arg (arg_ptr, short *)) = v->chars;
+                    break;
+                  default:
+                    *(va_arg (arg_ptr, int *)) = v->chars;
+                    break;
+                  }
+              break;
+
+            default:
+              if (f == 0)                 /* % at end of string */
+                return v->count;
+              c = get0 (v);
+              if (c != f)
+                return v->count;
+              break;
+            }
+          switch (v->status)
+            {
+            case INPUT_FAILURE:
+              return ((v->count == 0) ? EOF : v->count);
+            case MATCHING_FAILURE:
+            case OUT_OF_MEMORY:
+              return v->count;
+            default:
+              break;
+            }
+          ++format;
+        }
+    }
+  return v->count;
+}
+
+
+int _input (FILE *stream, const char *format, char *arg_ptr)
+{
+  ilocal v;
+  int rc;
+
+  v.stream = stream;
+  v.more = NULL; v.more_size = 0;
+  v.count = 0; v.chars = 0; v.status = OK;
+  rc = inp_main (&v, format, arg_ptr);
+  if (v.more != NULL)
+    free (v.more);
+  return rc;
+}
Index: trunk/src/emx/src/lib/io/_isterm.c
===================================================================
--- trunk/src/emx/src/lib/io/_isterm.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_isterm.c	(revision 18)
@@ -0,0 +1,16 @@
+/* _isterm.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <emx/syscalls.h>
+
+int _isterm (int handle)
+{
+  int j;
+
+  if (!_isatty (handle))
+    return 0;
+  j = __ioctl1 (handle, 0);
+  if (j < 0)
+    return 0;
+  return ((j & 0x03) ? 1 : 0);
+}
Index: trunk/src/emx/src/lib/io/_mfopen.c
===================================================================
--- trunk/src/emx/src/lib/io/_mfopen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_mfopen.c	(revision 18)
@@ -0,0 +1,110 @@
+/* _mfopen.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <emx/io.h>
+
+static int _mflush (FILE *stream, int c)
+{
+  int n;
+
+  if (c < 0)
+    return 0;
+  n = stream->_ptr - stream->_buffer;
+  if (n >= stream->_buf_size)
+    {
+      if (stream->_tmpidx == 0)
+        {
+          errno = ENOSPC;
+          return EOF;
+        }
+      if (stream->_tmpidx == -2)
+        {
+          if (stream->_buf_size == 0)
+            stream->_buf_size = 512;
+          else
+            stream->_buf_size *= 2;
+        }
+      else
+        stream->_buf_size += stream->_tmpidx;
+      stream->_buffer = realloc (stream->_buffer, stream->_buf_size);
+      if (stream->_buffer == NULL)
+        {
+          stream->_buf_size = 0;
+          stream->_wcount = 0;
+          errno = ENOMEM;
+          return EOF;
+        }
+    }
+  stream->_ptr = stream->_buffer + n;
+  *stream->_ptr++ = (char)c;
+  ++n;
+  stream->_wcount = stream->_buf_size - n;
+  return 0;
+}
+
+
+
+FILE *_mfopen (char *buf, const char *mode, size_t size, int inc)
+{
+  FILE *stream;
+  char *abuf = NULL;
+
+  if (mode[0] != 'w' || mode[1] != 'b' || mode[2] != 0)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  if ((buf == NULL && inc == 0) || (buf != NULL && (size == 0 || inc != 0)))
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  stream = _newstream ();
+  if (stream == NULL)
+    return NULL;
+  if (buf == NULL && size != 0)
+    {
+      buf = abuf = malloc (size);
+      if (buf == NULL)
+        {
+          errno = ENOMEM;
+          _closestream (stream);
+          return NULL;
+        }
+    }
+  stream->_buffer = buf;
+  stream->_ptr = buf;
+  stream->_rcount = 0;
+  stream->_wcount = size;
+  stream->_handle = -1;
+  stream->_flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOWRT;
+  stream->_buf_size = size;
+  stream->_flush = _mflush;
+  stream->_tmpidx = inc;
+  stream->_ungetc_count = 0;
+  if (_setmore (stream, 1) != 0)
+    {
+      if (abuf != NULL) free (abuf);
+      return NULL;
+    }
+  return stream;
+}
+
+
+char *_mfclose (FILE *stream)
+{
+  char *buf;
+
+  if ((stream->_flags & (_IOOPEN|_IOSPECIAL)) != (_IOOPEN|_IOSPECIAL)
+      || stream->_flush != _mflush)
+    return NULL;
+
+  /* Avoid a time window in which another thread allocates the stream
+     and sets _buffer! */
+
+  buf = stream->_buffer;
+  _closestream (stream);
+  return buf;
+}
Index: trunk/src/emx/src/lib/io/_newstre.c
===================================================================
--- trunk/src/emx/src/lib/io/_newstre.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_newstre.c	(revision 18)
@@ -0,0 +1,171 @@
+/* _newstre.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/io.h>
+
+#define INC     32
+
+FILE *_newstream (void)
+{
+  int i;
+  struct streamvec *sv, *last = NULL;
+
+  STREAMV_LOCK;
+  for (sv = &_streamvec_head; sv != NULL; sv = sv->next)
+    {
+      last = sv;
+      for (i = 0; i < sv->n; ++i)
+        if (!(sv->vec[i]._flags & (_IOOPEN|_IONEW)))
+          {
+            sv->vec[i]._flags = _IONEW;
+
+            /* Initialize new members to support dynamically linked
+               old executables with, say, -lvideo.  See also below. */
+
+            sv->vec[i]._more = 0;
+            sv->vec[i]._mbstate = 0;
+
+            STREAMV_UNLOCK;
+            return &sv->vec[i];
+          }
+    }
+
+  /* Enlarge our tables.  As the entries must not move, we add another
+     segment. */
+
+  sv = malloc (sizeof (*sv));
+  if (sv != NULL)
+    {
+      struct _FILE *fv;
+
+      fv = malloc (INC * sizeof (*fv));
+      if (fv == NULL)
+        free (sv);
+      else
+        {
+          for (i = 0; i < INC; ++i)
+            fv[i]._flags = 0;
+          sv->next = NULL;
+          sv->vec = fv;
+          sv->n = INC;
+
+          /* See above. */
+          fv[0]._flags = _IONEW;
+          fv[0]._more = 0;
+          fv[0]._mbstate = 0;
+
+          last->next = sv;      /* Done as last step, see fflush() */
+
+          STREAMV_UNLOCK;
+          return &fv[0];
+        }
+    }
+
+  STREAMV_UNLOCK;
+  return NULL;
+}
+
+#if defined (__MT__)
+
+int _setmore (FILE *stream, int lock)
+{
+  int i;
+  struct _file2 *p;
+  struct streamvec2 *sv2, *last = NULL;
+
+  stream->_mbstate = 0;
+  stream->_more = NULL;
+  if (lock)
+    STREAMV_LOCK;
+  p = NULL;
+  for (sv2 = &_streamvec2_head; sv2 != NULL; sv2 = sv2->next)
+    {
+      last = sv2;
+      for (i = 0; i < sv2->n; ++i)
+        if (sv2->vec[i].owner == NULL)
+          {
+            p = &sv2->vec[i];
+            goto super_break;
+          }
+    }
+super_break:
+  if (p == NULL)
+    {
+      sv2 = malloc (sizeof (*sv2));
+      if (sv2 != NULL)
+        {
+          struct _file2 *fv2;
+
+          fv2 = malloc (INC * sizeof (*fv2));
+          if (fv2 == NULL)
+            free (sv2);
+          else
+            {
+              for (i = 0; i < INC; ++i)
+                fv2[i].owner = NULL;
+              sv2->next = NULL;
+              sv2->vec = fv2;
+              sv2->n = INC;
+              last->next = sv2;
+              p = &sv2->vec[0];
+            }
+        }
+    }
+  if (p != NULL)
+    p->owner = stream;
+  if (lock)
+    STREAMV_UNLOCK;
+  if (p == NULL || _rmutex_create (&p->rsem, 0) != 0)
+    {
+      /* Note that stream->_more is NULL. */
+
+      _closestream (stream);
+      if (p != NULL)
+        p->owner = NULL;
+      return -1;
+    }
+  stream->_more = p;
+  return 0;
+}
+
+void _setdummymore (FILE *stream, struct _file2 *more)
+{
+  stream->_mbstate = 0;
+  stream->_more = more;
+  more->owner = stream;
+  _rmutex_dummy (&more->rsem);
+}
+
+#else
+
+int _setmore (FILE *stream, int lock)
+{
+  stream->_mbstate = 0;
+  stream->_more = NULL;
+  return 0;
+}
+
+void _setdummymore (FILE *stream, struct _file2 *more)
+{
+  stream->_mbstate = 0;
+  stream->_more = NULL;
+}
+
+#endif
+
+
+void _closestream (FILE *stream)
+{
+  if (stream->_more != NULL && stream->_more->owner == stream)
+    {
+#if defined (__MT__)
+      _rmutex_close (&stream->_more->rsem);
+#endif
+      stream->_more->owner = NULL;
+    }
+  stream->_flags = 0;
+}
Index: trunk/src/emx/src/lib/io/_output.c
===================================================================
--- trunk/src/emx/src/lib/io/_output.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_output.c	(revision 18)
@@ -0,0 +1,977 @@
+/* _output.c (emx+gcc) -- Copyright (c) 1990-2000 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <limits.h>
+#include <locale.h>
+#include <emx/io.h>
+#include <emx/float.h>
+#include <emx/locale.h>
+
+#define FALSE           0
+#define TRUE            1
+
+#define DEFAULT_PREC    6
+
+#define BEGIN do {
+#define END   } while (0)
+
+/* All functions in this module return -1 if an error ocurred while
+   writing the target file.  Otherwise, _output() returns the number
+   of characters written, all other functions return 0.
+
+   The CHECK macro is used to return -1 if the expression X evaluates
+   to a non-zero value.  This is used to pass up errors. */
+
+#define CHECK(X) BEGIN \
+                   if ((X) != 0) \
+                     return -1; \
+                 END
+
+/* Write the character C.  Note the return statement! */
+
+#define PUTC(V,C) BEGIN \
+                    if (_putc_inline (C, (V)->stream) == EOF) \
+                      return -1; \
+                    ++(V)->count; \
+                  END
+
+#define STRLEN(S) (((S) == NULL) ? 0 : strlen (S))
+
+/* This structure holds the local variables of _output() which are
+   passed to the various functions called by _output(). */
+
+typedef struct
+{
+  FILE *stream;                 /* Where output should go */
+  char minus;                   /* Non-zero if `-' flag present */
+  char plus;                    /* Non-zero if `+' flag present */
+  char blank;                   /* Non-zero if ` ' flag present */
+  char hash;                    /* Non-zero if `#' flag present */
+  char pad;                     /* Pad character (' ' or '0')  */
+  int width;                    /* Field width (or 0 if none specified) */
+  int prec;                     /* Precision (or -1 if none specified) */
+  int count;                    /* Number of characters printed */
+  int dig;                      /* DBL_DIG / LDBL_DIG for __small_dtoa() */
+} olocal;
+
+static char zdot[] = "0.";      /* "0." for the current locale */
+
+/* Print the first N characters of the string S. */
+
+static int out_str (olocal *v, const char *s, int n)
+{
+  if (n >= 16)
+    {
+      if (_fwrite_nolock (s, 1, n, v->stream) != n)
+        return -1;
+      v->count += n;
+    }
+  else
+    while (n > 0)
+      {
+        PUTC (v, *s);
+        ++s; --n;
+      }
+  return 0;
+}
+
+
+/* Note the return statement! */
+
+#define OUT_STR(V,S,N) BEGIN if (out_str (V, S, N) != 0) return -1; END
+
+
+/* Print the character C N times. */
+
+static int out_pad (olocal *v, char c, int n)
+{
+  char buf[256];
+
+  if (n > sizeof (buf))
+    {
+      int i;
+
+      /* Very big padding -- do 256 characters at a time. */
+      memset (buf, c, sizeof (buf));
+      while (n > 0)
+        {
+          i = sizeof (buf);
+          if (i > n)
+            i = n;
+          OUT_STR (v, buf, i);
+          n -= i;
+        }
+    }
+  else if (n >= 16)
+    {
+      memset (buf, c, n);
+      OUT_STR (v, buf, n);
+    }
+  else
+    while (n > 0)
+      {
+        PUTC (v, c);
+        --n;
+      }
+  return 0;
+}
+
+
+/* Note the return statement! */
+
+#define OUT_PAD(V,C,N) BEGIN if (out_pad (V, C, N) != 0) return -1; END
+
+
+/* Perform formatting for the "%c" and "%s" formats.  The meaning of
+   the '0' flag is not defined by ANSI for "%c" and "%s"; we always
+   use blanks for padding. */
+
+static int cvt_str (olocal *v, const char *str, int str_len)
+{
+  if (str == NULL)
+    {
+      /* Print "(null)" for the NULL pointer if the precision is big
+         enough or not specified. */
+
+      if (v->prec < 0 || v->prec >= 6)
+        str = "(null)";
+      else
+        str = "";
+    }
+
+  /* The precision, if specified, limits the number of characters to
+     be printed.  If the precision is specified, the array pointed to
+     by STR does not need to be null-terminated. */
+
+  if (str_len == -1)
+    {
+      if (v->prec >= 0)
+        {
+          const char *end = (const char *)memchr (str, 0, v->prec);
+          if (end != NULL)
+            str_len =  end - str;
+          else
+            str_len = v->prec;
+        }
+      else
+        str_len = strlen (str);
+    }
+  else if (v->prec >= 0 && v->prec < str_len)
+    str_len = v->prec;
+
+  /* Print the string, using blanks for padding. */
+
+  if (str_len < v->width && !v->minus)
+    OUT_PAD (v, ' ', v->width - str_len);
+  OUT_STR (v, str, str_len);
+  if (str_len < v->width && v->minus)
+    OUT_PAD (v, ' ', v->width - str_len);
+  return 0;
+}
+
+
+/* Print and pad a number (which has already been converted into
+   strings).  PFX is "0x" or "0X" for hexadecimal numbers, or NULL.
+   DOT is "0." for floating point numbers in [0.0,1.0) unless using
+   exponential format, the significant digits for large floating point
+   numbers in the "%f" format, "0", or NULL.  Insert LPAD0 zeros
+   between DOT and STR.  STR is the number.  Insert RPAD0 zeros
+   between STR and XPS.  XPS is the exponent (unless it is NULL).
+   IS_SIGNED is non-zero when printing a signed number. IS_NEG is
+   non-zero for negative numbers (the strings don't contain a
+   sign). */
+
+static int cvt_number (olocal *v, const char *pfx, const char *dot,
+                       const char *str, const char *xps,
+                       int lpad0, int rpad0, int is_signed, int is_neg)
+{
+  int sign, pfx_len, dot_len, str_len, xps_len, min_len, lpad1;
+
+  if (!is_signed)               /* No sign for %u, %o and %x */
+    sign = EOF;
+  else if (is_neg)
+    sign = '-';
+  else if (v->plus)             /* '+' overrides ' ' */
+    sign = '+';
+  else if (v->blank)
+    sign = ' ';
+  else
+    sign = EOF;
+
+  pfx_len = STRLEN (pfx);
+  dot_len = STRLEN (dot);
+  str_len = strlen (str);
+  xps_len = STRLEN (xps);
+
+  if (lpad0 < 0)
+    lpad0 = 0;
+  if (rpad0 < 0)
+    rpad0 = 0;
+  lpad1 = 0;
+
+  /* Compute the minimum length required for printing the number. */
+
+  min_len = lpad0 + pfx_len + dot_len + str_len + rpad0 + xps_len;
+  if (sign != EOF)
+    ++min_len;
+
+  /* If padding with zeros is requested, increase LPAD1 to pad the
+     number on the left with zeros.  Note that the `-' flag
+     (left-justify) turns off padding with zeros. */
+
+  if (v->pad == '0' && min_len < v->width)
+    {
+      lpad1 += v->width - min_len;
+      min_len = v->width;
+    }
+
+  /* If DOT is empty, we can combine LPAD0 into LPAD1. */
+
+  if (dot_len == 0)
+    {
+      lpad1 += lpad0;
+      lpad0 = 0;
+    }
+
+  /* Pad on the left with blanks. */
+
+  if (min_len < v->width && !v->minus)
+    OUT_PAD (v, ' ', v->width - min_len);
+
+  /* Print the number. */
+
+  if (sign != EOF)
+    PUTC (v, sign);
+  OUT_STR (v, pfx, pfx_len);
+  OUT_PAD (v, '0', lpad1);
+  OUT_STR (v, dot, dot_len);
+  OUT_PAD (v, '0', lpad0);
+  OUT_STR (v, str, str_len);
+  OUT_PAD (v, '0', rpad0);
+  OUT_STR (v, xps, xps_len);
+
+  /* Pad on the right with blanks. */
+
+  if (min_len < v->width && v->minus)
+    OUT_PAD (v, ' ', v->width - min_len);
+  return 0;
+}
+
+
+/* Print and pad an integer (which has already been converted into the
+   string STR).  PFX is "0x" or "0X" for hexadecimal numbers, or NULL.
+   ZERO is non-zero if the number is zero.  IS_NEG is non-zero if the
+   number is negative (the string STR doesn't contain a sign). */
+
+static int cvt_integer (olocal *v, const char *pfx, const char *str,
+                        int zero, int is_signed, int is_neg)
+{
+  int lpad0;
+
+  if (zero && v->prec == 0)     /* ANSI */
+    return 0;
+
+  if (v->prec >= 0)             /* Ignore `0' if `-' is given for an integer */
+    v->pad = ' ';
+
+  lpad0 = v->prec - strlen (str);
+  return cvt_number (v, pfx, NULL, str, NULL, lpad0, 0, is_signed, is_neg);
+}
+
+
+static int cvt_hex (olocal *v, char *str, char x, int zero)
+{
+  if (x == 'X')
+    _strupr (str);
+  return cvt_integer (v, ((!zero && v->hash) ? "0x" : NULL),
+                      str, zero, FALSE, FALSE);
+}
+
+
+static int cvt_hex_32 (olocal *v, unsigned n, char x)
+{
+  char buf[9];
+
+  _ltoa (n, buf, 16);
+  return cvt_hex (v, buf, x, n == 0);
+}
+
+
+static int cvt_hex_64 (olocal *v, unsigned long long n, char x)
+{
+  char buf[17];
+
+  _ulltoa (n, buf, 16);
+  return cvt_hex (v, buf, x, n == 0);
+}
+
+
+static int cvt_oct (olocal *v, const char *str, int zero)
+{
+  size_t len;
+
+  if (v->hash && str[0] != '0')
+    {
+      len = strlen (str);
+      if (v->prec <= (int)len)
+        v->prec = len + 1;
+    }
+  return cvt_integer (v, NULL, str, zero && !v->hash, FALSE, FALSE);
+}
+
+
+static int cvt_oct_32 (olocal *v, unsigned n)
+{
+  char buf[12];
+
+  _ltoa (n, buf, 8);
+  return cvt_oct (v, buf, n == 0);
+}
+
+
+static int cvt_oct_64 (olocal *v, unsigned long long n)
+{
+  char buf[23];
+
+  _ulltoa (n, buf, 8);
+  return cvt_oct (v, buf, n == 0);
+}
+
+
+static int cvt_dec_32 (olocal *v, unsigned n, int is_signed, int is_neg)
+{
+  char buf[11];
+
+  _ultoa (n, buf, 10);
+  return cvt_integer (v, NULL, buf, n == 0, is_signed, is_neg);
+}
+
+
+static int cvt_dec_64 (olocal *v, unsigned long long n, int is_signed,
+                       int is_neg)
+{
+  char buf[21];
+
+  _ulltoa (n, buf, 10);
+  return cvt_integer (v, NULL, buf, n == 0, is_signed, is_neg);
+}
+
+
+/* Print a floating point number (which has been turned into the digit
+   string DIGITS and the exponent XP) for the "%f" format.  If IS_NEG
+   is non-zero, the number is negative. */
+
+static int cvt_fixed_digits (olocal *v, char *digits, int xp, int is_neg,
+                             int is_auto)
+{
+  int lpad0, rpad0, len, frac;
+
+  /* We have to handle 9 cases (the examples are for DECIMAL_DIG=4):
+
+         | Fmt | Number    || digits | xp | pfx  |lpad0|rpad0| Output
+     ----+-----+-----------++--------+----+------+-----+-----+---------
+     (1) | .3f | 0.0001234 || "1234" | -4 | "0." | 0   | 3   | 0.000
+     (2) | .7f | 0.001234  || "1234" | -3 | "0." | 2   | 1   | 0.0012340
+     (3) | .3f | 0.001234  || "1234" | -3 | "0." | 2   | 0   | 0.001
+     (4) | .3f | 0.1234    || "1234" | -1 | "0." | 0   | 0   | 0.123
+     (5) | .3f | 1.234     || "1234" |  0 | N/A  | N/A | 0   | 1.234
+     (6) | .1f | 12.34     || "1234" |  1 | N/A  | N/A | 0   | 12.3
+     (7) | .3f | 123.4     || "1234" |  2 | N/A  | N/A | 2   | 123.400
+     (8) | .3f | 1234.0    || "1234" |  3 | N/A  | N/A | 3   | 1234.000
+     (9) | .3f | 123456.0  || "1235" |  5 |"1235"| 2   | 3   | 123500.000
+
+   */
+
+
+  if (xp < 0)
+    {
+      /* Cases (1) through (4).  We print "0." followed by
+
+           min (-xp - 1, v->prec)
+
+         zeros and the string of digit. */
+
+      lpad0 = -xp - 1;          /* This is for cases (2) through (3) */
+      if (v->prec < lpad0)
+        lpad0 = v->prec;        /* This is for case (1) */
+
+      /* Compute the number of zeros to append. */
+
+      rpad0 = v->prec - (lpad0 + DECIMAL_DIG); /* This is for case (2) */
+      if (rpad0 < 0)
+        rpad0 = 0;              /* This is for cases (1), (3) and (4) */
+
+      /* Truncate the string of digits according to the precision for
+         cases (1), (3) and (4). */
+
+      len = v->prec - lpad0;
+      if (len >= 0 && len < DECIMAL_DIG)
+        digits[len] = 0;
+
+      if (is_auto)
+        {
+          rpad0 = 0;
+          __remove_zeros (digits, 0);
+          if (digits[0] == 0)
+            lpad0 = 0;
+        }
+
+      return cvt_number (v, NULL, ((v->hash || digits[0] != 0 || lpad0 != 0)
+                                   ? zdot : "0"),
+                         digits, NULL, lpad0, rpad0, TRUE, is_neg);
+    }
+  else if (xp < DECIMAL_DIG)
+    {
+      /* Cases (5) through (8). */
+
+      /* Compute the number of zeros to append and truncate the string
+         of digits. */
+
+      frac = DECIMAL_DIG - xp - 1; /* Number of decimals (frac >= 0) */
+      rpad0 = v->prec - frac;   /* For cases (5), (7) and (8) */
+      if (rpad0 < 0)
+        {
+          /* Case (6) */
+          digits[DECIMAL_DIG + rpad0] = 0;
+          rpad0 = 0;
+        }
+
+      if (is_auto)
+        {
+          __remove_zeros (digits, xp + 1);
+          rpad0 = 0;
+        }
+
+      /* Insert the decimal point. */
+      if (v->hash || digits[xp + 1] != 0 || rpad0 != 0)
+        {
+          memmove (digits + xp + 2, digits + xp + 1, DECIMAL_DIG - xp);
+          digits[xp + 1] = zdot[1];
+        }
+      return cvt_number (v, NULL, NULL, digits, NULL, 0, rpad0, TRUE, is_neg);
+    }
+  else
+    {
+      /* Case (9). */
+
+      lpad0 = xp - DECIMAL_DIG + 1;
+      rpad0 = (is_auto ? 0 : v->prec);
+
+      return cvt_number (v, NULL, digits,
+                         ((v->hash || rpad0 != 0) ? zdot+1 : ""),
+                         NULL, lpad0, rpad0, TRUE, is_neg);
+    }
+}
+
+
+/* Print a floating point number (which has been turned into the digit
+   string DIGITS and the exponent XP) for the "%e" and "%g" formats.
+   If IS_NEG is non-zero, the number is negative.  XP_CHAR is 'e' or
+   'E'.  If IS_AUTO is non-zero, we should omit trailing zeros for the
+   "%g" format. */
+
+static int cvt_exp_digits (olocal *v, char *digits, int xp, int is_neg,
+                           char xp_char, int is_auto)
+{
+  int i, rpad0;
+  char xps_buf[10];
+
+  xps_buf[0] = xp_char;
+  xps_buf[1] = '+';
+  if (xp < 0)
+    {
+      xps_buf[1] = '-';
+      xp = -xp;
+    }
+  i = 2;
+  if (xp >= 1000)
+    xps_buf[i++] = (char)((xp / 1000) % 10) + '0';
+  if (xp >= 100)
+    xps_buf[i++] = (char)((xp / 100) % 10) + '0';
+  xps_buf[i++] = (char)((xp / 10) % 10) + '0';
+  xps_buf[i++] = (char)(xp % 10) + '0';
+  xps_buf[i] = 0;
+
+  /* Insert decimal point. */
+
+  if (v->prec == 0 && !v->hash)
+    {
+      digits[1] = 0;
+      rpad0 = 0;
+    }
+  else
+    {
+      memmove (digits + 2, digits + 1, DECIMAL_DIG);
+      digits[1] = zdot[1];
+      if (v->prec >= DECIMAL_DIG)
+        rpad0 = 1 + v->prec - DECIMAL_DIG;
+      else
+        {
+          rpad0 = 0;
+          digits[2 + v->prec] = 0;
+        }
+      if (is_auto)
+        {
+          __remove_zeros (digits, 2);
+          if (digits[2] == 0)
+            digits[1] = 0;
+          rpad0 = 0;
+        }
+    }
+  return cvt_number (v, NULL, NULL, digits, xps_buf, 0, rpad0, TRUE, is_neg);
+}
+
+
+/* Perform formatting for the "%f" format. */
+
+static int cvt_fixed (olocal *v, long double x, int is_neg)
+{
+
+  if (x == 0.0)
+    return cvt_number (v, NULL, NULL, ((v->hash || v->prec > 0) ? zdot : "0"),
+                       NULL, 0, v->prec, TRUE, is_neg);
+  else
+    {
+      char digits[DECIMAL_DIG+2], *p;
+      int xp;
+
+      p = __dtoa (digits, &xp, x, v->prec, DTOA_PRINTF_F, v->dig);
+      return cvt_fixed_digits (v, p, xp, is_neg, FALSE);
+    }
+}
+
+
+/* Perform formatting for the "%e" format.  XP_CHAR is 'e' or 'E'. */
+
+static int cvt_exp (olocal *v, long double x, int is_neg, char xp_char)
+{
+  if (x == 0.0)
+    {
+      static char xps_buf[] = "e+00";
+
+      xps_buf[0] = xp_char;
+      return cvt_number (v, NULL, NULL,
+                         ((v->hash || v->prec > 0) ? zdot : "0"),
+                         xps_buf, 0, v->prec, TRUE, is_neg);
+    }
+  else
+    {
+      char digits[DECIMAL_DIG+2], *p;
+      int xp;
+
+      p = __dtoa (digits, &xp, x, v->prec, DTOA_PRINTF_E, v->dig);
+      return cvt_exp_digits (v, p, xp, is_neg, xp_char, FALSE);
+    }
+}
+
+
+/* Perform formatting for the "%g" format.  XP_CHAR is 'e' or 'E'. */
+
+static int cvt_auto (olocal *v, long double x, int is_neg, char xp_char)
+{
+  /* A precision of zero is treated as a precision of 1.  Note that
+     the precision defines the number of significant digits, not the
+     number of decimals! */
+
+  if (v->prec == 0)
+    v->prec = 1;
+
+  /* 0.0 is treated specially as __dtoa() etc. cannot handle that
+     case. */
+
+  if (x == 0.0)
+    return cvt_number (v, NULL, NULL, (v->hash ? zdot : "0"), NULL,
+                       0, (v->hash ? v->prec - 1 : 0), TRUE, is_neg);
+  else
+    {
+      char digits[DECIMAL_DIG+2], *p;
+      int xp;
+
+      p = __dtoa (digits, &xp, x, v->prec, DTOA_PRINTF_G, v->dig);
+
+      /* If the exponent (of "%e" format) is less than -4 or greater
+         than or equal to the precision, use "%e" format.  Otherwise,
+         use "%f" format. */
+
+      if (xp < -4 || xp >= v->prec)
+        {
+          /* Adjust the precision to indicate the number of
+             decimals. */
+
+          v->prec -= 1;
+
+          /* Treat "%#g" like "%e" (except for the precision).  "%g"
+             (without `#') removes trailing zeros. */
+
+          return cvt_exp_digits (v, p, xp, is_neg, xp_char, !v->hash);
+        }
+      else
+        {
+          /* Compute the number of decimals from the exponent and the
+             precision.  We must not remove trailing zeros from the
+             integer part of the number! */
+
+          v->prec -= xp + 1;
+          if (v->prec < 0)
+            v->prec = 0;
+
+          return cvt_fixed_digits (v, p, xp, is_neg, !v->hash);
+        }
+    }
+}
+
+
+/* Print the floating point number X.  LIM is the number of
+   significant digits of X (depending on the type of X), FMT is the
+   format character from the format string. */
+
+static int cvt_float (olocal *v, long double x, char fmt)
+{
+  const char *s;
+  int is_neg, fpclass;
+
+  fpclass = fpclassify (x);
+  is_neg = signbit (x);
+  switch (fpclass)
+    {
+    case FP_NAN:
+      s = (fmt & 0x20) ? "nan" : "NAN";
+      is_neg = 0;               /* Don't print -NAN */
+      break;
+    case FP_INFINITE:
+      s = (fmt & 0x20) ? "inf" : "INF";
+      break;
+    default:
+      s = NULL;
+      break;
+    }
+
+  if (s != NULL)
+    {
+      v->pad = ' ';
+      return cvt_number (v, NULL, NULL, s, NULL, 0, 0, TRUE, is_neg);
+    }
+
+  if (v->prec < 0)
+    v->prec = DEFAULT_PREC;
+
+  if (is_neg)
+    x = -x;
+
+  switch (fmt)
+    {
+    case 'f':
+    case 'F':
+      return cvt_fixed (v, x, is_neg);
+
+    case 'g':
+      return cvt_auto (v, x, is_neg, 'e');
+
+    case 'G':
+      return cvt_auto (v, x, is_neg, 'E');
+
+    case 'e':
+      return cvt_exp (v, x, is_neg, 'e');
+
+    case 'E':
+      return cvt_exp (v, x, is_neg, 'E');
+
+    default:
+      abort ();
+    }
+}
+
+
+/* This is the working horse for printf() and friends. */
+
+int _output (FILE *stream, const char *format, char *arg_ptr)
+{
+  olocal v;
+  char size, cont;
+  unsigned char c;
+  int mbn, shift;
+
+  /* Initialize variables. */
+
+  v.stream = stream;
+  v.count = 0;
+  zdot[1] = _cur_lconv.decimal_point[0];
+
+  /* ANSI X3.159-1989, 4.9.6.1: "The format shall be a multibyte
+     character sequence, beginning and ending in its initial shift
+     state." */
+
+  shift = 0;
+
+  /* Interpret the string. */
+
+  while ((c = *format) != 0)
+    if (c != '%')
+      {
+        /* ANSI X3.159-1989, 4.9.6.1: "... ordinary multibyte
+           charcters (not %), which are copied unchanged to the output
+           stream..."
+
+           Avoid the overhead of calling mblen(). */
+
+        if (c <= 127 || _cur_mbyte.mode == _MB_8BITS)
+          {
+            PUTC (&v, c);
+            ++format;
+          }
+        else
+          {
+            mbn = _mbtowc (NULL, format, MB_LEN_MAX, &shift);
+            if (mbn < 1)
+              mbn = 1;          /* Output an invalid character as is */
+            while (mbn > 0)
+              {
+                PUTC (&v, *format);
+                ++format; --mbn;
+              }
+          }
+      }
+    else if (format[1] == '%')
+      {
+        /* ANSI X3.159-1989, 4.9.6.1: "The complete conversion
+           specification shall be %%." */
+
+        PUTC (&v, '%');
+        format += 2;
+      }
+    else
+      {
+        v.minus = v.plus = v.blank = v.hash = FALSE;
+        v.width = 0; v.prec = -1; size = 0; v.pad = ' ';
+        cont = TRUE;
+        do
+          {
+            ++format;
+            switch (*format)
+              {
+              case '-':
+                v.minus = TRUE;
+                break;
+              case '+':
+                v.plus = TRUE;
+                break;
+              case '0':
+                v.pad = '0';
+                break;
+              case ' ':
+                v.blank = TRUE;
+                break;
+              case '#':
+                v.hash = TRUE;
+                break;
+              default:
+                cont = FALSE;
+                break;
+              }
+          } while (cont);
+
+        /* `-' overrides `0' */
+
+        if (v.minus)
+          v.pad = ' ';
+
+        /* Field width */
+
+        if (*format == '*')
+          {
+            ++format;
+            v.width = va_arg (arg_ptr, int);
+            if (v.width < 0)
+              {
+                v.width = -v.width;
+                v.minus = TRUE;
+              }
+          }
+        else
+          while (*format >= '0' && *format <= '9')
+            {
+              v.width = v.width * 10 + (*format - '0');
+              ++format;
+            }
+
+        /* Precision */
+
+        if (*format == '.')
+          {
+            ++format;
+            if (*format == '*')
+              {
+                ++format;
+                v.prec = va_arg (arg_ptr, int);
+                if (v.prec < 0)
+                  v.prec = -1;  /* We don't need this */
+              }
+            else
+              {
+                v.prec = 0;
+                while (*format >= '0' && *format <= '9')
+                  {
+                    v.prec = v.prec * 10 + (*format - '0');
+                    ++format;
+                  }
+              }
+          }
+
+        /* Size */
+
+        if (*format == 'h' || *format == 'l' || *format == 'L')
+          {
+            size = *format++;
+            if (size == 'l' && *format == 'l')
+              {
+                size = 'L'; ++format;
+              }
+          }
+
+        /* Format */
+
+        switch (*format)
+          {
+          case 0:
+            return v.count;
+
+          case 'n':
+            if (size == 'L')
+              {
+                long long *ptr = va_arg (arg_ptr, long long *);
+                *ptr = v.count;
+              }
+            else if (size == 'h')
+              {
+                short *ptr = va_arg (arg_ptr, short *);
+                *ptr = v.count;
+              }
+            else
+              {
+                int *ptr = va_arg (arg_ptr, int *);
+                *ptr = v.count;
+              }
+            break;
+
+          case 'c':
+            {
+              char c;
+
+              c = (char)va_arg (arg_ptr, int);
+              v.prec = 1;
+              CHECK (cvt_str (&v, &c, 1));
+            }
+            break;
+
+          case 's':
+            CHECK (cvt_str (&v, va_arg (arg_ptr, const char *), -1));
+            break;
+
+          case 'd':
+          case 'i':
+            if (size == 'L')
+              {
+                long long n = va_arg (arg_ptr, long long);
+                if (n < 0)
+                  CHECK (cvt_dec_64 (&v, -n, TRUE, TRUE));
+                else
+                  CHECK (cvt_dec_64 (&v, n, TRUE, FALSE));
+              }
+            else
+              {
+                int n = va_arg (arg_ptr, int);
+                if (size == 'h')
+                  n = (short)n;
+                if (n < 0)
+                  CHECK (cvt_dec_32 (&v, -n, TRUE, TRUE));
+                else
+                  CHECK (cvt_dec_32 (&v, n, TRUE, FALSE));
+              }
+            break;
+
+          case 'u':
+            if (size == 'L')
+              CHECK (cvt_dec_64 (&v, va_arg (arg_ptr, unsigned long long),
+                                 FALSE, FALSE));
+            else
+              {
+                unsigned n = va_arg (arg_ptr, unsigned);
+                if (size == 'h')
+                  n = (unsigned short)n;
+                CHECK (cvt_dec_32 (&v, n, FALSE, FALSE));
+              }
+            break;
+
+          case 'p':
+            v.hash = TRUE;
+            CHECK (cvt_hex_32 (&v, va_arg (arg_ptr, unsigned), 'x'));
+            break;
+
+          case 'x':
+          case 'X':
+            if (size == 'L')
+              CHECK (cvt_hex_64 (&v, va_arg (arg_ptr, unsigned long long),
+                                 *format));
+            else
+              {
+                unsigned n = va_arg (arg_ptr, unsigned);
+                if (size == 'h')
+                  n = (unsigned short)n;
+                CHECK (cvt_hex_32 (&v, n, *format));
+              }
+            break;
+
+          case 'o':
+            if (size == 'L')
+              CHECK (cvt_oct_64 (&v, va_arg (arg_ptr, unsigned long long)));
+            else
+              {
+                unsigned n = va_arg (arg_ptr, unsigned);
+                if (size == 'h')
+                  n = (unsigned short)n;
+                CHECK (cvt_oct_32 (&v, n));
+              }
+            break;
+
+          case 'g':
+          case 'G':
+          case 'e':
+          case 'E':
+          case 'f':
+          case 'F':
+            if (size == 'L')
+              {
+                long double x = va_arg (arg_ptr, long double);
+                v.dig = LDBL_DIG;
+                CHECK (cvt_float (&v, x, *format));
+              }
+            else
+              {
+                double x = va_arg (arg_ptr, double);
+                v.dig = DBL_DIG;
+                CHECK (cvt_float (&v, x, *format));
+              }
+            break;
+
+          default:
+
+            /* ANSI X3.159-1989, 4.9.6.1: "If a conversion
+               specification is invalid, the behavior is undefined."
+
+               We print the last letter only. */
+
+            OUT_STR (&v, format, 1);
+            break;
+          }
+        ++format;
+      }
+
+  /* Return the number of characters printed. */
+
+  return v.count;
+}
Index: trunk/src/emx/src/lib/io/_rmtmp.c
===================================================================
--- trunk/src/emx/src/lib/io/_rmtmp.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_rmtmp.c	(revision 18)
@@ -0,0 +1,25 @@
+/* _rmtmp.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <emx/io.h>
+
+int _rmtmp (void)
+{
+  int i, n;
+  struct streamvec *sv;
+
+  /* Ignore locked streams to avoid deadlock on process
+     termination. */
+
+  n = 0;
+  for (sv = &_streamvec_head; sv != NULL; sv = sv->next)
+    for (i = 0; i < sv->n; ++i)
+      if ((sv->vec[i]._flags & _IOOPEN) && (sv->vec[i]._flags & _IOTMP)
+          && STREAM_UNLOCKED (&sv->vec[i])
+          && fclose (&sv->vec[i]) == 0)
+        ++n;
+  return n;
+}
Index: trunk/src/emx/src/lib/io/_seekhdr.c
===================================================================
--- trunk/src/emx/src/lib/io/_seekhdr.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_seekhdr.c	(revision 18)
@@ -0,0 +1,47 @@
+/* _seekhdr.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <memory.h>
+#include <io.h>
+#include <errno.h>
+
+int _seek_hdr (int handle)
+{
+  struct
+    {
+      char magic[2];
+      char fill1[6];
+      unsigned short hdr_size;
+    } exe_hdr;
+  struct
+    {
+      char sig[16];
+      char bound;
+      char fill1;
+      unsigned short hdr_loc_lo;      /* cannot use long, alignment! */
+      unsigned short hdr_loc_hi;
+    } patch;
+  long original_pos;
+  int saved_errno;
+
+  original_pos = _tell (handle);
+  if (_read (handle, &exe_hdr, sizeof (exe_hdr)) != sizeof (exe_hdr))
+    goto failure;
+  if (memcmp (exe_hdr.magic, "MZ", 2) != 0)
+    return (_lseek (handle, original_pos, SEEK_SET) == -1 ? -1 : 0);
+  if (_lseek (handle, original_pos + 16 * exe_hdr.hdr_size, SEEK_SET) == -1)
+    goto failure;
+  if (_read (handle, &patch, sizeof (patch)) != sizeof (patch))
+    goto failure;
+  if (memcmp (patch.sig, "emx", 3) != 0)
+    goto failure;
+  if (_lseek (handle, original_pos + patch.hdr_loc_lo
+              + 65536L * patch.hdr_loc_hi, SEEK_SET) == -1)
+    goto failure;
+  return 0;
+
+failure:
+  saved_errno = errno;
+  _lseek (handle, original_pos, SEEK_SET);
+  errno = saved_errno;
+  return -1;
+}
Index: trunk/src/emx/src/lib/io/_str_rd.c
===================================================================
--- trunk/src/emx/src/lib/io/_str_rd.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_str_rd.c	(revision 18)
@@ -0,0 +1,16 @@
+/* _str_rd.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _stream_read (int fd, void *buf, size_t nbyte)
+{
+  int r;
+
+  do
+    {
+      r = _read (fd, buf, nbyte);
+    } while (r == -1 && errno == EINTR);
+  return r;
+}
Index: trunk/src/emx/src/lib/io/_str_wr.c
===================================================================
--- trunk/src/emx/src/lib/io/_str_wr.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_str_wr.c	(revision 18)
@@ -0,0 +1,16 @@
+/* _str_wr.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _stream_write (int fd, const void *buf, size_t nbyte)
+{
+  int r;
+
+  do
+    {
+      r = _write (fd, buf, nbyte);
+    } while (r == -1 && errno == EINTR);
+  return r;
+}
Index: trunk/src/emx/src/lib/io/_tempnam.c
===================================================================
--- trunk/src/emx/src/lib/io/_tempnam.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_tempnam.c	(revision 18)
@@ -0,0 +1,104 @@
+/* _tempnam.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+/*                         Copyright (c) 1991-1993 by Kolja Elsaesser */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+#include "_tmp.h"
+
+
+/* Create absolute path name from src, copy it to dst and return 1 if
+   it's a directory. Note that this works also with a trailing backslash! */
+
+static int _isdir (char *dst, const char *src)
+{
+  int attr;
+
+  if (_fullpath (dst, src, MAXPATHLEN) != 0)
+    return 0;
+  attr = __chmod (dst, 0, 0);
+  return attr >= 0 && (attr & _A_SUBDIR);
+}
+
+
+char *_tempnam (const char *dir, const char *prefix)
+{
+  const char *tmpdir;
+  char *tmpname, *p, buf[MAXPATHLEN];
+  size_t len;
+  int saved_errno, idx_start;
+
+  saved_errno = errno;
+  if (strlen (prefix) > 5)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  tmpdir = NULL;
+  p = getenv ("TMP");
+  if (tmpdir == NULL && p != NULL && _isdir (buf, p))
+    tmpdir = buf;
+  if (tmpdir == NULL && dir != NULL && _isdir (buf, dir))
+    tmpdir = buf;
+  if (tmpdir == NULL)
+    tmpdir = P_tmpdir;
+  tmpname = malloc (strlen (tmpdir) + 1 + L_tmpnam);
+  if (tmpname == NULL)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+
+  len = strlen (tmpdir);
+  memcpy (tmpname, tmpdir, len);
+  if (len > 0 && !_trslash (tmpname, len, 0))
+    tmpname[len++] = '/';
+  p = tmpname + len;
+
+  TMPIDX_LOCK;
+  idx_start = _tmpidx;
+  for (;;)
+    {
+      if (_tmpidx == IDX_HI)
+        _tmpidx = IDX_LO;
+      else
+        ++_tmpidx;
+      if (_tmpidx == idx_start)
+        {
+          TMPIDX_UNLOCK;
+          free (tmpname);
+          errno = EINVAL;
+          return NULL;
+        }
+      _itoa (_tmpidx, p, 10);
+      strcat (p, ".tmp");
+      memmove (p, prefix, strlen (prefix));
+      errno = 0;
+      if (_access (tmpname, 0) != 0)
+        {
+          if (errno == ENOENT)
+            break;
+          TMPIDX_UNLOCK;
+          free (tmpname);
+          return NULL;
+        }
+    }
+  TMPIDX_UNLOCK;
+  errno = saved_errno;
+  if (_fullpath (buf, tmpname, sizeof (buf)) != 0)
+    {
+      free (tmpname);
+      errno = ENOENT;
+      return NULL;
+    }
+  free (tmpname);
+  p = _strdup (buf);
+  if (p == NULL)
+    errno = ENOMEM;
+  return p;
+}
Index: trunk/src/emx/src/lib/io/_tmp.c
===================================================================
--- trunk/src/emx/src/lib/io/_tmp.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_tmp.c	(revision 18)
@@ -0,0 +1,40 @@
+/* _tmp.c (emx+gcc) */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/startup.h>
+#include "_tmp.h"
+
+int _tmpidx = IDX_LO;
+
+
+#if defined (__MT__)
+
+/* This semaphore protects _tmpidx. */
+
+static _rmutex _tmpidx_rmutex;
+
+
+/* Initialize the semaphore -- this function will be called by
+   _startup() via the __crtinit1__ set vector. */
+
+void _init1_tmp (void)
+{
+  _rmutex_checked_create (&_tmpidx_rmutex, 0);
+}
+
+_CRT_INIT1 (_init1_tmp)
+
+
+void _tmpidx_lock (void)
+{
+  _rmutex_checked_request (&_tmpidx_rmutex, _FMR_IGNINT);
+}
+
+void _tmpidx_unlock (void)
+{
+  _rmutex_checked_release (&_tmpidx_rmutex);
+}
+
+#endif
Index: trunk/src/emx/src/lib/io/_tmp.h
===================================================================
--- trunk/src/emx/src/lib/io/_tmp.h	(revision 18)
+++ trunk/src/emx/src/lib/io/_tmp.h	(revision 18)
@@ -0,0 +1,23 @@
+/* _tmp.h (emx+gcc) */
+
+#define IDX_LO 10000000
+#define IDX_HI 99999999
+
+extern int _tmpidx;
+
+int _tmpidxnam (char *string);
+
+#if defined (__MT__)
+
+void _tmpidx_lock (void);
+void _tmpidx_unlock (void);
+
+#define TMPIDX_LOCK   _tmpidx_lock ()
+#define TMPIDX_UNLOCK _tmpidx_unlock ()
+
+#else
+
+#define TMPIDX_LOCK
+#define TMPIDX_UNLOCK
+
+#endif /* defined (__MT__) */
Index: trunk/src/emx/src/lib/io/_tmpbuf.c
===================================================================
--- trunk/src/emx/src/lib/io/_tmpbuf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_tmpbuf.c	(revision 18)
@@ -0,0 +1,30 @@
+/* _tmpbuf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <emx/io.h>
+
+/* Assign the temporary buffer BUF of size BUFSIZ to STREAM. */
+
+int _tmpbuf1 (FILE *stream, void *buf)
+{
+  stream->_ptr = stream->_buffer = (char *)buf;
+  stream->_wcount = BUFSIZ;
+  stream->_rcount = 0;
+  stream->_flags |= _IOWRT;
+  stream->_flags &= ~_IOBUFMASK;
+  stream->_flags |= _IOBUFTMP;
+  return 0;
+}
+
+int _endbuf1 (FILE *stream)
+{
+  int result;
+
+  result = _fflush_nolock (stream);
+  stream->_buf_size = 1;
+  stream->_ptr = stream->_buffer = &stream->_char_buf;
+  stream->_flags &= ~_IOBUFMASK;
+  stream->_flags |= _IOBUFCHAR;
+  stream->_rcount = stream->_wcount = 0;
+  return result;
+}
Index: trunk/src/emx/src/lib/io/_tmpidxn.c
===================================================================
--- trunk/src/emx/src/lib/io/_tmpidxn.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_tmpidxn.c	(revision 18)
@@ -0,0 +1,55 @@
+/* _tmpidxn.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+/*                         Copyright (c) 1991-1993 by Kolja Elsaesser */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include "_tmp.h"
+
+
+/* Returns _tmpidx if successful, -1 on error. */
+
+int _tmpidxnam (char *string)
+{
+  int saved_errno, idx_start, ret;
+  size_t len;
+
+  len = strlen (P_tmpdir);
+  memcpy (string, P_tmpdir, len);
+  if (len > 0 && !_trslash (string, len, 0))
+    string[len++] = '/';
+  saved_errno = errno;
+  TMPIDX_LOCK;
+  idx_start = _tmpidx;
+  for (;;)
+    {
+      if (_tmpidx >= IDX_HI)
+        _tmpidx = IDX_LO;
+      else
+        ++_tmpidx;
+      if (_tmpidx == idx_start)
+        {
+          errno = EINVAL;
+          ret = -1;
+          break;
+        }
+      _itoa (_tmpidx, string + len, 10);
+      strcat (string + len, ".tmp");
+      errno = 0;
+      if (_access (string, 0) != 0)
+        {
+          if (errno == ENOENT)
+            ret = _tmpidx;
+          else
+            ret = -1;
+          break;
+        }
+    }
+  TMPIDX_UNLOCK;
+  if (ret != -1)
+    errno = saved_errno;
+  return ret;
+}
Index: trunk/src/emx/src/lib/io/_trslash.c
===================================================================
--- trunk/src/emx/src/lib/io/_trslash.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_trslash.c	(revision 18)
@@ -0,0 +1,88 @@
+/* _trslash.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <sys/nls.h>
+#include <emx/io.h>
+
+/* Detect trailing slash or backslash for stat(), access(), and
+   _tmpidxnam().  If MODE is 0, the trailing (back)slash may be
+   preceded by an arbitrary character, including none.  Moreover, a
+   trailing colon is treated like a trailing slash.  If MODE is 1, the
+   trailing (back)slash must be preceded by a character which is not a
+   (back)slash or a colon.  Note that the string pointed to by NAME
+   need not be null-terminated! */
+
+/* Support only SBCS and DBCS for now. */
+
+int _trslash (const char *name, size_t len, int mode)
+{
+  size_t i;
+
+  switch (mode)
+    {
+    case 0:
+      if (len < 1 || (name[len-1] != '\\' && name[len-1] != '/'
+                      && name[len-1] != ':'))
+        return 0;
+      if (len == 1 && (name[0] == '\\' || name[0] == '/'))
+        return 1;
+      break;
+    case 1:
+      if (len < 2 || (name[len-1] != '\\' && name[len-1] != '/'))
+        return 0;
+      break;
+    default:
+      return 0;
+    }
+
+  /* The name seems to have a trailing (back)slash.  There are two
+     conditions which must _not_ hold:
+
+     (1) the (back)slash is the 2nd byte of a DBCS character
+     (2) the (back)slash is preceded by a SBCS (back)slash or a colon
+
+     Condition (2) does not matter if MODE is 0.
+
+          |         |     |     | return for MODE
+     Case | name(*) | (1) | (2) |   0   |   1
+     -----+---------+-----+-----+-------+-------
+     (a)  | ....//  | no  | yes |   1   |   0
+     (b)  | ....S/  | no  | no  |   1   |   1
+     (c)  | ...L2/  | no  | no  |   1   |   1
+     (d)  | ....L/  | yes | -   |   0   |   0
+
+     (*) S = SBCS character but not a (back)slash or colon
+         L = lead byte
+         2 = 2nd byte of DBCS char */
+
+  i = 0;
+  for (;;)
+    {
+      if (_nls_is_dbcs_lead ((unsigned char)name[i]))
+        {
+          if (i == len - 3)
+            {
+              /* Case (c) -- a DBCS character precedes the trailing
+                 (back)slash. */
+              return 1;
+            }
+          else if (i == len - 2)
+            {
+              /* Case (d) -- the last byte is the 2nd byte of a DBCS
+                 character and therefore is not a SBCS (back)slash. */
+              return 0;
+            }
+          else
+            i += 2;
+        }
+      else if (i == len - 2)
+        {
+          /* We hit the character preceding the trailing (back)slash;
+             this is either case (a) or (b).  Check for condition (2),
+             condition (1) does not apply. */
+          return (mode == 0
+                  || (name[i] != '\\' && name[i] != '/' && name[i] != ':'));
+        }
+      else
+        ++i;
+    }
+}
Index: trunk/src/emx/src/lib/io/_vsopen.c
===================================================================
--- trunk/src/emx/src/lib/io/_vsopen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/_vsopen.c	(revision 18)
@@ -0,0 +1,160 @@
+/* _vsopen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdarg.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+/* Bugs: O_TRUNC|O_RDONLY not implemented */
+/*       O_TEXT|O_WRONLY  does/can not overwrite Ctrl-Z */
+
+#define FALSE   0
+#define TRUE    1
+
+int _fmode_bin;                 /* Set non-zero to make binary mode default */
+
+#define SH_MASK           0x70
+
+/* This function may be called as follows (assuming that oflag does
+   not include O_CREAT nor O_SIZE):
+
+   _vsopen (name, oflag, shflag)
+   _vsopen (name, oflag | O_CREAT, shflag, pmode)
+   _vsopen (name, oflag | O_SIZE, shflag, size)
+   _vsopen (name, oflag | O_CREAT | O_SIZE, shflag, pmode, size) */
+
+int _vsopen (const char *name, int oflag, int shflag, va_list va)
+{
+  int handle, flags, *pflags, saved_errno;
+  int bits;
+  char dummy, ctrlz_kludge = FALSE;
+  unsigned long initial_size;
+
+  if ((oflag & O_ACCMODE) == O_RDONLY && (oflag & (O_TRUNC|O_CREAT)))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  bits = oflag & (O_ACCMODE|O_NDELAY|O_APPEND);
+  if (oflag & O_BINARY)
+    /* do nothing */;
+  else if (oflag & O_TEXT)
+    bits |= O_TEXT;
+  else if (_fmode_bin == 0)          /* neither O_TEXT nor O_BINARY given */
+    bits |= O_TEXT;
+
+  if ((bits & O_TEXT) && (oflag & O_APPEND) && (oflag & O_ACCMODE) == O_WRONLY)
+    {
+      /* The caller requests to open a text file for appending in
+         write-only.  To remove the Ctrl-Z (if there is any), we have
+         to temporarily open the file in read/write mode. */
+
+      flags = O_RDWR | (shflag & SH_MASK);
+      ctrlz_kludge = TRUE;
+    }
+  else
+    flags = (oflag & O_ACCMODE) | (shflag & SH_MASK);
+
+  if (oflag & O_CREAT)
+    {
+      int attr, pmode;
+
+      attr = 0;
+      pmode = va_arg (va, int);
+      if (!(pmode & S_IWRITE))
+        attr |= _A_RDONLY;
+      flags |= (attr << 8) | _SO_CREAT;
+      if (oflag & O_EXCL)
+        flags |= _SO_EXCL;
+    }
+
+  if (oflag & O_TRUNC)
+    flags |= _SO_TRUNC;
+
+  if (oflag & O_NOINHERIT)
+    flags |= _SO_NOINHERIT;
+
+  if (oflag & O_SYNC)
+    flags |= _SO_SYNC;
+
+  initial_size = 0;
+  if (oflag & O_SIZE)
+    {
+      initial_size = va_arg (va, unsigned long);
+      flags |= _SO_SIZE;
+    }
+    
+  saved_errno = errno;
+  handle = __open (name, flags, initial_size);
+  if (handle < 0 && ctrlz_kludge && errno == EACCES)
+    {
+      /* Perhaps read access is denied.  Try again. */
+      errno = saved_errno;
+      ctrlz_kludge = FALSE;
+      flags = (flags & ~O_ACCMODE) | (oflag & O_ACCMODE);
+      handle = __open (name, flags, initial_size);
+    }
+  if (handle < 0)
+    return -1;
+
+  if (__ioctl1 (handle, 0) & 0x80)
+    {
+      bits |= F_DEV;
+      oflag &= ~O_APPEND;
+    }
+
+  if (!(bits & F_DEV) && (bits & O_TEXT))
+    {
+      long size;
+
+      /* Remove the last character of the file if it is a Ctrl-Z.  Do
+         this even if O_SIZE is given as we don't know whether the
+         file existed before; removing a spurious Ctrl-Z due to O_SIZE
+         should be harmless. */
+
+      /* DEC Pathworks seems to treat the offset as unsigned number.
+         Therefore we do not use __lseek (handle, -1L, SEEK_END). */
+
+      size = __lseek (handle, 0L, SEEK_END);
+      if (size > 0 && __lseek (handle, size - 1, SEEK_SET) != -1L
+          && __read (handle, &dummy, 1) == 1 && dummy == 0x1a)
+        __ftruncate (handle, size - 1); /* Remove Ctrl-Z */
+      __lseek (handle, 0L, SEEK_SET);
+    }
+
+  if (ctrlz_kludge)
+    {
+      /* Reopen the handle in write-only mode. */
+
+      __close (handle);
+      flags = (flags & ~O_ACCMODE) | (oflag & O_ACCMODE);
+      flags &= ~_SO_EXCL;       /* Ignore O_EXCL */
+      handle = __open (name, flags, initial_size);
+      if (handle < 0)
+        return -1;
+    }
+
+  pflags = _fd_init (handle);
+  if (pflags == NULL)
+    {
+      __close (handle);
+      errno = EMFILE;
+      return -1;
+    }
+
+  *pflags = bits;
+
+  /* When opening a file for appending, move to the end of the file.
+     This is required for passing the handle to a child process. */
+
+  if (!(bits & F_DEV) && (bits & O_APPEND))
+    __lseek (handle, 0L, SEEK_END);
+  errno = saved_errno;
+
+  return handle;
+}
Index: trunk/src/emx/src/lib/io/access.c
===================================================================
--- trunk/src/emx/src/lib/io/access.c	(revision 18)
+++ trunk/src/emx/src/lib/io/access.c	(revision 18)
@@ -0,0 +1,60 @@
+/* access.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _access (const char *name, int mode)
+{
+  int a, slash;
+  size_t len;
+  char *tmp;
+
+  /* If there is a trailing slash or backslash, remove it and set
+     `slash' to true.  Make a local copy of the string to remove the
+     slash or backslash. */
+
+  len = strlen (name);
+  slash = _trslash (name, len, 1);
+  if (slash)
+    {
+      tmp = alloca (len);
+      memcpy (tmp, name, len - 1);
+      tmp[len-1] = 0;
+      name = tmp;
+    }
+
+  /* Query the attributes of the file or directory. */
+
+  a = __chmod (name, 0, 0);
+  if (a < 0)
+    return -1;
+
+  /* Fail if the name ends with a slash or backslash and is not a
+     directory. */
+
+  if (slash && !(a & _A_SUBDIR))
+    {
+      errno = ENOTDIR;
+      return -1;
+    }
+
+  /* Volume IDs are not accessible. */
+
+  if (a & _A_VOLID)
+    {
+      errno = ENOENT;
+      return -1;
+    }
+
+  /* When testing for write permission, check the read-only bit. */
+
+  if ((mode & 2) && (a & _A_RDONLY))
+    {
+      errno = EACCES;
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/chmod.c
===================================================================
--- trunk/src/emx/src/lib/io/chmod.c	(revision 18)
+++ trunk/src/emx/src/lib/io/chmod.c	(revision 18)
@@ -0,0 +1,23 @@
+/* chmod.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <emx/syscalls.h>
+
+int _chmod (const char *name, int pmode)
+{
+  int attr, rc;
+
+  attr = __chmod (name, 0, 0);           /* Get attributes */
+  if (attr < 0)
+    return -1;
+  if (pmode & S_IWRITE)
+    attr &= ~1;
+  else
+    attr |= 1;
+  rc = __chmod (name, 1, attr);
+  if (rc >= 0) rc = 0;
+  return rc;
+}
Index: trunk/src/emx/src/lib/io/chsize.c
===================================================================
--- trunk/src/emx/src/lib/io/chsize.c	(revision 18)
+++ trunk/src/emx/src/lib/io/chsize.c	(revision 18)
@@ -0,0 +1,47 @@
+/* chsize.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _chsize (int handle, long length)
+{
+  long n;
+  int i, j, *pflags;
+  char zeros[4096];
+
+  if ((pflags = _fd_flags (handle)) == NULL || (*pflags & F_DEV))
+    {
+      errno = EBADF;
+      return -1;
+    }
+  n = (long)__lseek (handle, 0L, SEEK_END);
+  if (n == -1L)
+    return -1;
+  if (__chsize (handle, length) != 0)
+    return -1;
+  if (n < length)
+    {
+      memset (zeros, 0, sizeof (zeros));
+      if (__lseek (handle, n, SEEK_SET) == -1)
+        return -1;
+      while (n < length)
+        {
+          i = length - n;
+          if (i > sizeof (zeros))
+            i = sizeof (zeros);
+          j = __write (handle, zeros, i);
+          if (j == -1)
+            return -1;
+          if (j == 0)
+            {
+              errno = ENOSPC;
+              return -1;
+            }
+          n += j;
+        }
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/clearerr.c
===================================================================
--- trunk/src/emx/src/lib/io/clearerr.c	(revision 18)
+++ trunk/src/emx/src/lib/io/clearerr.c	(revision 18)
@@ -0,0 +1,8 @@
+/* clearerr.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+
+void clearerr (FILE *stream)
+{
+  stream->_flags &= ~(_IOERR|_IOEOF);
+}
Index: trunk/src/emx/src/lib/io/close.c
===================================================================
--- trunk/src/emx/src/lib/io/close.c	(revision 18)
+++ trunk/src/emx/src/lib/io/close.c	(revision 18)
@@ -0,0 +1,16 @@
+/* close.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _close (int handle)
+{
+  if (_fd_flags (handle) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  return __close (handle);
+}
Index: trunk/src/emx/src/lib/io/creat.c
===================================================================
--- trunk/src/emx/src/lib/io/creat.c	(revision 18)
+++ trunk/src/emx/src/lib/io/creat.c	(revision 18)
@@ -0,0 +1,9 @@
+/* creat.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <io.h>
+#include <fcntl.h>
+
+int _creat (const char *name, int pmode)
+{
+  return _open (name, O_WRONLY|O_TRUNC|O_CREAT, pmode);
+}
Index: trunk/src/emx/src/lib/io/dup.c
===================================================================
--- trunk/src/emx/src/lib/io/dup.c	(revision 18)
+++ trunk/src/emx/src/lib/io/dup.c	(revision 18)
@@ -0,0 +1,31 @@
+/* dup.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _dup (int handle)
+{
+  int new, *pflags1, *pflags2, *pla1, *pla2;
+
+  if ((pflags1 = _fd_flags (handle)) == NULL
+      || (pla1 = _fd_lookahead (handle)) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  new = __dup (handle);
+  if (new < 0)
+    return new;
+  if ((pflags2 = _fd_init (new)) == NULL
+      || (pla2 = _fd_lookahead (new)) == NULL)
+    {
+      __close (new);
+      errno = EMFILE;
+      return -1;
+    }
+  *pflags2 = *pflags1;
+  *pla2 = *pla1;
+  return new;
+}
Index: trunk/src/emx/src/lib/io/dup2.c
===================================================================
--- trunk/src/emx/src/lib/io/dup2.c	(revision 18)
+++ trunk/src/emx/src/lib/io/dup2.c	(revision 18)
@@ -0,0 +1,36 @@
+/* dup2.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _dup2 (int handle1, int handle2)
+{
+  int *pflags1, *pflags2, *pla1, *pla2;
+
+  if ((pflags1 = _fd_flags (handle1)) == NULL
+      || (pla1 = _fd_lookahead (handle1)) == NULL
+      || handle2 < 0)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  /* TODO: Block signals */
+  if (__dup2 (handle1, handle2) < 0)
+    return -1;
+
+  if ((pflags2 = _fd_init (handle2)) == NULL
+      || (pla2 = _fd_lookahead (handle2)) == NULL)
+    {
+      /* TODO: Unfortunately, the original HANDLE2, if there was one,
+         is now closed. */
+      __close (handle2);
+      errno = EMFILE;
+      return -1;
+    }
+
+  *pflags2 = *pflags1;
+  *pla2 = *pla1;
+  return handle2;
+}
Index: trunk/src/emx/src/lib/io/ea.h
===================================================================
--- trunk/src/emx/src/lib/io/ea.h	(revision 18)
+++ trunk/src/emx/src/lib/io/ea.h	(revision 18)
@@ -0,0 +1,25 @@
+/* ea.h (emx+gcc) */
+
+struct _ead_data
+{
+  int count;                    /* Number of EAs */
+  int max_count;                /* Number of pointers allocated for INDEX */
+  int total_value_size;         /* Total size of values */
+  int total_name_len;           /* Total length of names w/o null characters */
+  size_t buffer_size;           /* Number of bytes allocated for BUFFER */
+  PFEA2LIST buffer;             /* Buffer holding FEA2LIST */
+  PFEA2 *index;                 /* Index for BUFFER */
+};
+
+void _ea_set_errno (ULONG rc);
+int _ea_write (const char *path, int handle, PFEA2LIST src);
+
+int _ead_make_index (struct _ead_data *ead, int new_count);
+int _ead_size_buffer (struct _ead_data *ead, int new_size);
+int _ead_enum (struct _ead_data *ead, const char *path, int handle,
+    int (*function)(struct _ead_data *ead, PDENA2 pdena, void *arg),
+    void *arg);
+
+#define _EA_ALIGN(i)     (((i) + 3) & -4)
+#define _EA_SIZE1(n, v)  _EA_ALIGN (sizeof (FEA2) + (n) + (v))
+#define _EA_SIZE2(p)     _EA_SIZE1 ((p)->cbName, (p)->cbValue)
Index: trunk/src/emx/src/lib/io/ead.c
===================================================================
--- trunk/src/emx/src/lib/io/ead.c	(revision 18)
+++ trunk/src/emx/src/lib/io/ead.c	(revision 18)
@@ -0,0 +1,173 @@
+/* ead.c (emx+gcc) -- Copyright (c) 1993-2000 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/ead.h>
+#include "ea.h"
+
+_ead _ead_create (void)
+{
+  _ead p;
+
+  p = malloc (sizeof (*p));
+  if (p == NULL)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+  p->count = 0;
+  p->max_count = 0;
+  p->total_value_size = 0;
+  p->total_name_len = 0;
+  p->buffer_size = 0;
+  p->index = NULL;
+  p->buffer = NULL;
+  return p;
+}
+
+
+void _ead_destroy (_ead ead)
+{
+  if (ead->buffer != NULL) free (ead->buffer);
+  if (ead->index != NULL) free (ead->index);
+  free (ead);
+}
+
+
+void _ead_clear (_ead ead)
+{
+  ead->count = 0;
+  ead->total_value_size = 0;
+  ead->total_name_len = 0;
+}
+
+
+int _ead_count (_ead ead)
+{
+  return ead->count;
+}
+
+
+int _ead_value_size (_ead ead, int index)
+{
+  if (index == 0)
+    return ead->total_value_size;
+  else if (index < 1 || index > ead->count)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  else
+    return ead->index[index-1]->cbValue;
+}
+
+
+int _ead_name_len (_ead ead, int index)
+{
+  if (index == 0)
+    return ead->total_name_len;
+  else if (index < 1 || index > ead->count)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  else
+    return ead->index[index-1]->cbName;
+}
+
+
+const char *_ead_get_name (_ead ead, int index)
+{
+  if (index < 1 || index > ead->count)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  else
+    return (const char *)ead->index[index-1]->szName;
+}
+
+
+const void *_ead_get_value (_ead ead, int index)
+{
+  if (index < 1 || index > ead->count)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  else
+    return ead->index[index-1]->szName + ead->index[index-1]->cbName + 1;
+}
+
+
+int _ead_get_flags (_ead ead, int index)
+{
+  if (index < 1 || index > ead->count)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  else
+    return ead->index[index-1]->fEA;
+}
+
+
+int _ead_find (_ead ead, const char *name)
+{
+  int i;
+
+  for (i = 0; i < ead->count; ++i)
+    if (strcmp (name, ead->index[i]->szName) == 0)
+      return i+1;
+  errno = ENOENT;
+  return -1;
+}
+
+
+int _ead_make_index (struct _ead_data *ead, int new_count)
+{
+  int i;
+  PFEA2 pfea;
+
+  if (new_count > ead->max_count)
+    {
+      ead->max_count = new_count;
+      ead->index = realloc (ead->index, ead->max_count * sizeof (*ead->index));
+      if (ead->index == NULL)
+        {
+          ead->max_count = 0;
+          ead->count = 0;
+          errno = ENOMEM;
+          return -1;
+        }
+    }
+  pfea = &ead->buffer->list[0];
+  for (i = 0; i < new_count; ++i)
+    {
+      ead->index[i] = (PFEA2)pfea;
+      pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset);
+    }
+  return 0;
+}
+
+
+int _ead_size_buffer (struct _ead_data *ead, int new_size)
+{
+  if (new_size > ead->buffer_size)
+    {
+      ead->buffer_size = new_size;
+      ead->buffer = realloc (ead->buffer, ead->buffer_size);
+      if (ead->buffer == NULL)
+        {
+          ead->buffer_size = 0;
+          ead->count = 0;
+          errno = ENOMEM;
+          return -1;
+        }
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/eadadd.c
===================================================================
--- trunk/src/emx/src/lib/io/eadadd.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eadadd.c	(revision 18)
@@ -0,0 +1,104 @@
+/* eadadd.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ead.h>
+#include "ea.h"
+
+int _ead_add (_ead ead, const char *name, int flags, const void *value,
+              int size)
+{
+  int i, len, new_size, offset;
+  PFEA2 dst, last;
+
+  i = _ead_find (ead, name);
+  if (i >= 1)
+    {
+      if (_ead_replace (ead, i, flags, value, size) < 0)
+        return -1;
+      return i;
+    }
+  len = strlen (name);
+  new_size = _EA_SIZE1 (len, size);
+  if (ead->count == 0)
+    offset = sizeof (ULONG);
+  else
+    {
+      offset = ead->buffer->cbList;
+      last = ead->index[ead->count - 1];
+      last->oNextEntryOffset = _EA_SIZE2 (last);
+    }
+  if (_ead_size_buffer (ead, offset + new_size) < 0)
+    return -1;
+  ead->buffer->cbList = offset + new_size;
+  dst = (PFEA2)((char *)ead->buffer + offset);
+  dst->oNextEntryOffset = 0;
+  dst->fEA = flags;
+  dst->cbName = len;
+  dst->cbValue = size;
+  memcpy (dst->szName, name, len + 1);
+  memcpy (dst->szName + len + 1, value, size);
+  if (_ead_make_index (ead, ead->count + 1) < 0)
+    return -1;
+  ++ead->count;
+  return ead->count;
+}
+
+
+int _ead_replace (_ead ead, int index, int flags, const void *value, int size)
+{
+  PFEA2 dst;
+  int old_size, new_size, offset;
+
+  if (index < 1 || index > ead->count)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  dst = ead->index[index-1];
+  new_size = _EA_SIZE1 (dst->cbName, size);
+  old_size = _EA_SIZE2 (dst);
+  offset = (char *)dst - (char *)ead->buffer;
+  dst = NULL;
+  if (new_size > old_size)
+    {
+      if (_ead_size_buffer (ead, ead->buffer_size - old_size + new_size) < 0)
+        return -1;
+    }
+  dst = (PFEA2)((char *)ead->buffer + offset);
+  if (new_size != old_size && index != ead->count)
+    memmove ((char *)dst + new_size, (char *)dst + old_size,
+             ead->buffer->cbList - (offset + old_size));
+  dst->fEA = flags;
+  dst->cbValue = size;
+  dst->oNextEntryOffset = (index == ead->count ? 0 : new_size);
+  ead->buffer->cbList += new_size - old_size;
+  memcpy (dst->szName + dst->cbName + 1, value, size);
+  return _ead_make_index (ead, ead->count);
+}
+
+
+int _ead_delete (_ead ead, int index)
+{
+  PFEA2 ptr;
+  int old_size;
+
+  if (index < 1 || index > ead->count)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  ptr = ead->index[index-1];
+  old_size = _EA_SIZE2 (ptr);
+  memmove (ptr, (char *)ptr + old_size,
+           ead->buffer->cbList - (((char *)ptr - (char *)ead->buffer)
+                                  + old_size));
+  ead->buffer->cbList -= old_size;
+  if (_ead_make_index (ead, ead->count - 1) < 0)
+    return -1;
+  --ead->count;
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/eadcopy.c
===================================================================
--- trunk/src/emx/src/lib/io/eadcopy.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eadcopy.c	(revision 18)
@@ -0,0 +1,38 @@
+/* eadcopy.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/ead.h>
+#include "ea.h"
+
+int _ead_copy (_ead dst_ead, _ead src_ead, int src_index)
+{
+  int i;
+  const FEA2 *s;
+
+  if (src_index == 0)
+    for (i = 1; i <= src_ead->count; ++i)
+      {
+        s = src_ead->index[i-1];
+        if (_ead_add (dst_ead, s->szName, s->fEA, s->szName + s->cbName + 1,
+                      s->cbValue) < 0)
+          return -1;
+      }
+  else if (src_index < 1 || src_index > src_ead->count)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  else
+    {
+      s = src_ead->index[src_index-1];
+      if (_ead_add (dst_ead, s->szName, s->fEA, s->szName + s->cbName + 1,
+                    s->cbValue) < 0)
+        return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/eadfea.c
===================================================================
--- trunk/src/emx/src/lib/io/eadfea.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eadfea.c	(revision 18)
@@ -0,0 +1,163 @@
+/* eadfea.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ead.h>
+#include "ea.h"
+
+int _ead_fea2list_size (_ead ead)
+{
+  if (ead->count == 0)
+    return 0;
+  else
+    return (int)ead->buffer->cbList;
+}
+
+
+const void *_ead_get_fea2list (_ead ead)
+{
+  if (ead->count == 0)
+    return NULL;
+  else
+    return (const void *)ead->buffer;
+}
+
+
+void *_ead_fea2list_to_fealist (const void *src)
+{
+  const FEA2LIST *s;
+  const FEA2 *ps;
+  PFEALIST d;
+  PFEA pd;
+  ULONG size, add;
+  char *q;
+
+  s = (const FEA2LIST *)src;
+  size = sizeof (ULONG);
+  if (s->cbList > sizeof (ULONG))
+    {
+      ps = &s->list[0];
+      for (;;)
+        {
+          add = sizeof (FEA) + 1 + ps->cbName + ps->cbValue;
+          size += add;
+          if (ps->oNextEntryOffset == 0)
+            break;
+          ps = (const FEA2 *)((char *)ps + ps->oNextEntryOffset);
+        }
+    }
+  d = malloc (size);
+  if (d == NULL)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+  d->cbList = size;
+  pd = &d->list[0];
+  if (s->cbList > sizeof (ULONG))
+    {
+      ps = &s->list[0];
+      for (;;)
+        {
+          pd->fEA = ps->fEA;
+          pd->cbName = ps->cbName;
+          pd->cbValue = ps->cbValue;
+          q = (char *)pd + sizeof (FEA);
+          memcpy (q, ps->szName, ps->cbName + 1);
+          q += ps->cbName + 1;
+          memcpy (q, ps->szName + ps->cbName + 1, ps->cbValue);
+          q += ps->cbValue;
+          pd = (PFEA)q;
+          if (ps->oNextEntryOffset == 0)
+            break;
+          ps = (const FEA2 *)((char *)ps + ps->oNextEntryOffset);
+        }
+    }
+  return d;
+}
+
+
+void *_ead_fealist_to_fea2list (const void *src)
+{
+  const FEALIST *s;
+  const FEA *ps;
+  PFEA2LIST d;
+  PFEA2 pd;
+  ULONG size, add, offset, *patch;
+  char *q;
+  const char *t;
+
+  s = (const FEALIST *)src;
+  size = sizeof (ULONG);
+  offset = sizeof (ULONG);
+  while (offset < s->cbList)
+    {
+      ps = (const FEA *)((char *)src + offset);
+      size += _EA_SIZE2 (ps);
+      offset += sizeof (FEA) + 1 + ps->cbName + ps->cbValue;
+    }
+  d = malloc (size);
+  if (d == NULL)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+  d->cbList = size;
+  pd = &d->list[0];
+  offset = sizeof (ULONG);
+  patch = NULL;
+  while (offset < s->cbList)
+    {
+      ps = (const FEA *)((char *)src + offset);
+      pd->fEA = ps->fEA;
+      pd->cbName = ps->cbName;
+      pd->cbValue = ps->cbValue;
+      t = (char *)src + offset + sizeof (FEA);
+      q = pd->szName;
+      memcpy (q, t, ps->cbName + 1);
+      t += ps->cbName + 1;
+      q += ps->cbName + 1;
+      memcpy (q, t, ps->cbValue);
+      add = _EA_SIZE2 (ps);
+      patch = &pd->oNextEntryOffset;
+      pd->oNextEntryOffset = add;
+      pd = (PFEA2)((char *)pd + add);
+      offset += sizeof (FEA) + 1 + ps->cbName + ps->cbValue;
+    }
+  if (patch != NULL)
+    *patch = 0;
+  return d;
+}
+
+
+int _ead_use_fea2list (_ead ead, const void *src)
+{
+  const FEA2LIST *s;
+  PFEA2 pfea;
+  int count;
+
+  s = src;
+  ead->count = 0;
+  if (_ead_size_buffer (ead, s->cbList) < 0)
+    return -1;
+  memcpy (ead->buffer, src, s->cbList);
+  count = 0;
+  if (s->cbList > sizeof (ULONG))
+    {
+      pfea = &ead->buffer->list[0];
+      for (;;)
+        {
+          ++count;
+          if (pfea->oNextEntryOffset == 0)
+            break;
+          pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset);
+        }
+    }
+  if (_ead_make_index (ead, count) < 0)
+    return -1;
+  ead->count = count;
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/eadread.c
===================================================================
--- trunk/src/emx/src/lib/io/eadread.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eadread.c	(revision 18)
@@ -0,0 +1,210 @@
+/* eadread.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/ead.h>
+#include "ea.h"
+
+struct gea_data
+{
+  int gea_alloc;
+  int gea_used;
+  int total_name_len;
+  int total_value_size;
+  int fea_size;
+  int count;
+  ULONG *patch;
+  PGEA2LIST gea_ptr;
+};
+
+
+static int _ead_make_gea (struct _ead_data *ead, PDENA2 pdena, void *arg)
+{
+  ULONG size;
+  PGEA2 pgea;
+  struct gea_data *p;
+
+  p = arg;
+  size = _EA_ALIGN (sizeof (GEA2) + pdena->cbName);
+  if (p->gea_used + size > p->gea_alloc)
+    {
+      p->gea_alloc += 512;             /* increment must be > size */
+      p->gea_ptr = realloc (p->gea_ptr, p->gea_alloc);
+      if (p->gea_ptr == NULL)
+        {
+          errno = ENOMEM;
+          return -1;
+        }
+    }
+  pgea = (PGEA2)((char *)p->gea_ptr + p->gea_used);
+  pgea->oNextEntryOffset = size;
+  pgea->cbName = pdena->cbName;
+  if (pdena->szName[pdena->cbName] != 0)
+    abort ();
+  memcpy (pgea->szName, pdena->szName, pdena->cbName + 1);
+  p->patch = &pgea->oNextEntryOffset;
+  p->gea_used += size;
+  size = _EA_SIZE2 (pdena);
+  p->fea_size += size;
+  p->total_name_len += pdena->cbName;
+  p->total_value_size += pdena->cbValue;
+  ++p->count;
+  return 0;
+}
+
+
+int _ead_read (_ead ead, const char *path, int handle, int flags)
+{
+  ULONG rc;
+  struct gea_data gd;
+  EAOP2 eaop;
+
+  _ead_clear (ead);
+  if (_osmode != OS2_MODE)
+    {
+      if (path != NULL)
+        {
+          if (_access (path, 0) != 0)
+            return -1;
+        }
+      else
+        {
+          if (_tell (handle) == -1)
+            return -1;
+        }
+      return 0;
+    }
+  gd.gea_alloc = sizeof (GEA2LIST);
+  gd.gea_ptr = malloc (gd.gea_alloc);
+  if (gd.gea_ptr == NULL)
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+  gd.gea_used = sizeof (eaop.fpGEA2List->cbList);
+  gd.fea_size = sizeof (eaop.fpFEA2List->cbList);
+  gd.total_name_len = 0;
+  gd.total_value_size = 0;
+  gd.count = 0;
+  gd.patch = NULL;
+  if (_ead_enum (ead, path, handle, _ead_make_gea, &gd) < 0)
+    {
+      if (gd.gea_ptr != NULL)
+        free (gd.gea_ptr);
+      return -1;
+    }
+  if (gd.count > 0)
+    {
+      *gd.patch = 0;
+      eaop.fpGEA2List = gd.gea_ptr; gd.gea_ptr = NULL;
+      eaop.fpGEA2List->cbList = gd.gea_used;
+      if (_ead_size_buffer (ead, gd.fea_size) < 0)
+        {
+          free (eaop.fpGEA2List);
+          return -1;
+        }
+      ead->buffer->cbList = gd.fea_size;
+      eaop.fpFEA2List = ead->buffer;
+      eaop.oError = 0;
+      if (path == NULL)
+        rc = DosQueryFileInfo (handle, FIL_QUERYEASFROMLIST, &eaop,
+                               sizeof (eaop));
+      else
+        rc = DosQueryPathInfo (path, FIL_QUERYEASFROMLIST, &eaop,
+                               sizeof (eaop));
+      if (rc != 0)
+        {
+          free (eaop.fpGEA2List);
+          _ea_set_errno (rc);
+          return -1;
+        }
+      free (eaop.fpGEA2List); eaop.fpGEA2List = NULL;
+    }
+  else if (gd.gea_ptr != NULL)
+    {
+      free (gd.gea_ptr); gd.gea_ptr = NULL;
+    }
+  if (gd.count != 0 && _ead_make_index (ead, gd.count) < 0)
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+  ead->count = gd.count;
+  ead->total_value_size = gd.total_value_size;
+  ead->total_name_len = gd.total_name_len;
+  return 0;
+}
+
+
+int _ead_enum (struct _ead_data *ead, const char *path, int handle,
+               int (*function)(struct _ead_data *ead, PDENA2 pdena, void *arg),
+               void *arg)
+{
+  void *dena_buf;
+  const void *fileref;
+  ULONG dena_buf_size, index, count, rc, reftype, hf, i;
+  PDENA2 pdena;
+  int expand_dena_buf;
+
+  if (path != NULL)
+    {
+      reftype = ENUMEA_REFTYPE_PATH;
+      fileref = path;
+    }
+  else
+    {
+      hf = handle;
+      reftype = ENUMEA_REFTYPE_FHANDLE;
+      fileref = &hf;
+    }
+  dena_buf_size = 0; dena_buf = NULL;
+  expand_dena_buf = 1; index = 1;
+  for (;;)
+    {
+      if (expand_dena_buf)
+        {
+          dena_buf_size += 0x20000; /* DosEnumAttribute is broken */
+          dena_buf = realloc (dena_buf, dena_buf_size);
+          if (dena_buf == NULL)
+            {
+              errno = ENOMEM;
+              return -1;
+            }
+        }
+      count = -1;
+      rc = DosEnumAttribute (reftype, fileref, index,
+                             dena_buf, dena_buf_size, &count,
+                             ENUMEA_LEVEL_NO_VALUE);
+      if (rc == ERROR_BUFFER_OVERFLOW)
+        expand_dena_buf = 1;
+      else if (rc != 0)
+        {
+          free (dena_buf);
+          _ea_set_errno (rc);
+          return -1;
+        }
+      else if (count == 0)
+        break;
+      else
+        {
+          expand_dena_buf = 0; pdena = dena_buf;
+          for (i = 0; i < count; ++i)
+            {
+              if (function (ead, pdena, arg) < 0)
+                {
+                  free (dena_buf);
+                  return -1;
+                }
+              pdena = (PDENA2)((char *)pdena + pdena->oNextEntryOffset);
+            }
+          index += count;
+        }
+    }
+  free (dena_buf);
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/eadsort.c
===================================================================
--- trunk/src/emx/src/lib/io/eadsort.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eadsort.c	(revision 18)
@@ -0,0 +1,21 @@
+/* eadsort.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ead.h>
+#include "ea.h"
+
+static int _ead_compare (const void *x1, const void *x2)
+{
+  return strcmp ((*((PFEA2 *)x1))->szName, ((*(PFEA2 *)x2))->szName);
+}
+
+
+void _ead_sort (_ead ead)
+{
+  if (ead->count >= 2)
+    qsort (ead->index, ead->count, sizeof (ead->index[0]), _ead_compare);
+}
Index: trunk/src/emx/src/lib/io/eadwrite.c
===================================================================
--- trunk/src/emx/src/lib/io/eadwrite.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eadwrite.c	(revision 18)
@@ -0,0 +1,84 @@
+/* eadwrite.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/ead.h>
+#include "ea.h"
+
+struct del_data
+{
+  int fea_alloc;
+  int fea_used;
+  ULONG *patch;
+  PFEA2LIST fea_ptr;
+};
+
+
+static int _ead_del (struct _ead_data *ead, PDENA2 pdena, void *arg)
+{
+  int add;
+  PFEA2 pfea;
+  struct del_data *p;
+
+  if (_ead_find (ead, pdena->szName) < 0)
+    {
+      p = arg;
+      add = _EA_SIZE1 (pdena->cbName, 0);
+      if (p->fea_used + add > p->fea_alloc)
+        {
+          p->fea_alloc += 512;          /* increment must be > add */
+          p->fea_ptr = realloc (p->fea_ptr, p->fea_alloc);
+          if (p->fea_ptr == NULL)
+            return -1;
+        }
+      pfea = (PFEA2)((char *)p->fea_ptr + p->fea_used);
+      pfea->oNextEntryOffset = add;
+      pfea->fEA = 0;
+      pfea->cbName = pdena->cbName;
+      pfea->cbValue = 0;        /* Delete! */
+      memcpy (pfea->szName, pdena->szName, pdena->cbName + 1);
+      p->patch = &pfea->oNextEntryOffset;
+      p->fea_used += add;
+    }
+  return 0;
+}
+
+
+int _ead_write (_ead ead, const char *path, int handle, int flags)
+{
+  if (_osmode != OS2_MODE)
+    return 0;
+  if (!(flags & _EAD_MERGE))
+    {
+      struct del_data dd;
+
+      dd.fea_used = sizeof (ULONG);
+      dd.fea_alloc = 0;
+      dd.fea_ptr = NULL;
+      dd.patch = NULL;
+      if (_ead_enum (ead, path, handle, _ead_del, &dd) < 0)
+        {
+          if (dd.fea_ptr != NULL)
+            free (dd.fea_ptr);
+          return -1;
+        }
+      if (dd.fea_ptr != NULL)
+        {
+          *dd.patch = 0;
+          dd.fea_ptr->cbList = dd.fea_used;
+          if (_ea_write (path, handle, dd.fea_ptr) < 0)
+            {
+              free (dd.fea_ptr);
+              return -1;
+            }
+          free (dd.fea_ptr);
+        }
+    }
+  if (ead->count != 0 && _ea_write (path, handle, ead->buffer) < 0)
+    return -1;
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/eaerrno.c
===================================================================
--- trunk/src/emx/src/lib/io/eaerrno.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eaerrno.c	(revision 18)
@@ -0,0 +1,34 @@
+/* eaerrno.c (emx+gcc) -- Copyright (c) 1993 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#include <os2.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "ea.h"
+
+void _ea_set_errno (ULONG rc)
+{
+  switch (rc)
+    {
+    case ERROR_FILE_NOT_FOUND:
+    case ERROR_PATH_NOT_FOUND:
+      errno = ENOENT;
+      break;
+    case ERROR_ACCESS_DENIED:
+      errno = EACCES;
+      break;
+    case ERROR_NOT_ENOUGH_MEMORY:
+      errno = ENOMEM;
+      break;
+    case ERROR_INVALID_HANDLE:
+      errno = EBADF;
+      break;
+    case ERROR_FILENAME_EXCED_RANGE:
+      errno = ENAMETOOLONG;
+      break;
+    default:
+      errno = EINVAL;
+      break;
+    }
+}
Index: trunk/src/emx/src/lib/io/eafree.c
===================================================================
--- trunk/src/emx/src/lib/io/eafree.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eafree.c	(revision 18)
@@ -0,0 +1,13 @@
+/* eafree.c (emx+gcc) -- Copyright (c) 1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/ea.h>
+
+void _ea_free (struct _ea *ptr)
+{
+  if (ptr->value != NULL)
+    {
+      free (ptr->value);
+      ptr->value = NULL;
+    }
+}
Index: trunk/src/emx/src/lib/io/eaget.c
===================================================================
--- trunk/src/emx/src/lib/io/eaget.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eaget.c	(revision 18)
@@ -0,0 +1,91 @@
+/* eaget.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/ea.h>
+#include "ea.h"
+
+int _ea_get (struct _ea *dst, const char *path, int handle,
+             const char *name)
+{
+  const void *fileref;
+  ULONG rc, reftype, hf;
+  EAOP2 eaop;
+  PGEA2LIST pgealist;
+  PFEA2LIST pfealist;
+  PGEA2 pgea;
+  PFEA2 pfea;
+  int len, size;
+
+  dst->flags = 0;
+  dst->size = 0;
+  dst->value = NULL;
+  if (_osmode != OS2_MODE)
+    {
+      if (path != NULL)
+        {
+          if (_access (path, 0) != 0)
+            return -1;
+        }
+      else
+        {
+          if (_tell (handle) == -1)
+            return -1;
+        }
+      return 0;
+    }
+  if (path != NULL)
+    {
+      reftype = ENUMEA_REFTYPE_PATH;
+      fileref = path;
+    }
+  else
+    {
+      hf = handle;
+      reftype = ENUMEA_REFTYPE_FHANDLE;
+      fileref = &hf;
+    }
+  len = strlen (name);
+  size = sizeof (GEA2LIST) + len;
+  pgealist = alloca (size);
+  pgealist->cbList = size;
+  pgea = &pgealist->list[0];
+  pgea->oNextEntryOffset = 0;
+  pgea->cbName = len;
+  memcpy (pgea->szName, name, len + 1);
+  size = sizeof (FEA2LIST) + 0x10000;
+  pfealist = alloca (size);
+  pfealist->cbList = size;
+  eaop.fpGEA2List = pgealist;
+  eaop.fpFEA2List = pfealist;
+  eaop.oError = 0;
+  if (path == NULL)
+    rc = DosQueryFileInfo (handle, FIL_QUERYEASFROMLIST, &eaop,
+                           sizeof (eaop));
+  else
+    rc = DosQueryPathInfo (path, FIL_QUERYEASFROMLIST, &eaop,
+                           sizeof (eaop));
+  if (rc != 0)
+    {
+      _ea_set_errno (rc);
+      return -1;
+    }
+  pfea = &pfealist->list[0];
+  if (pfea->cbValue != 0)
+    {
+      dst->value = malloc (pfea->cbValue);
+      if (dst->value == NULL)
+        {
+          errno = ENOMEM;
+          return -1;
+        }
+      memcpy (dst->value, pfea->szName + pfea->cbName + 1, pfea->cbValue);
+    }
+  dst->flags = pfea->fEA;
+  dst->size = pfea->cbValue;
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/eaput.c
===================================================================
--- trunk/src/emx/src/lib/io/eaput.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eaput.c	(revision 18)
@@ -0,0 +1,33 @@
+/* eaput.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/ea.h>
+#include "ea.h"
+
+int _ea_put (struct _ea *src, const char *path, int handle,
+             const char *name)
+{
+  PFEA2LIST pfealist;
+  PFEA2 pfea;
+  int len, size;
+
+  if (_osmode != OS2_MODE)
+    return 0;
+  len = strlen (name);
+  size = sizeof (FEA2LIST) + len + src->size;
+  pfealist = alloca (size);
+  pfealist->cbList = size;
+  pfea = &pfealist->list[0];
+  pfea->oNextEntryOffset = 0;
+  pfea->fEA = src->flags;
+  pfea->cbName = len;
+  pfea->cbValue = src->size;
+  memcpy (pfea->szName, name, len + 1);
+  memcpy (pfea->szName + len + 1, src->value, src->size);
+  return _ea_write (path, handle, pfealist);
+}
Index: trunk/src/emx/src/lib/io/earemove.c
===================================================================
--- trunk/src/emx/src/lib/io/earemove.c	(revision 18)
+++ trunk/src/emx/src/lib/io/earemove.c	(revision 18)
@@ -0,0 +1,14 @@
+/* earemove.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/ea.h>
+
+int _ea_remove (const char *path, int handle, const char *name)
+{
+  struct _ea ea;
+
+  ea.flags = 0;
+  ea.size = 0;
+  ea.value = NULL;
+  return _ea_put (&ea, path, handle, name);
+}
Index: trunk/src/emx/src/lib/io/eawrite.c
===================================================================
--- trunk/src/emx/src/lib/io/eawrite.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eawrite.c	(revision 18)
@@ -0,0 +1,26 @@
+/* eawrite.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#include <stdlib.h>
+#include "ea.h"
+
+int _ea_write (const char *path, int handle, PFEA2LIST src)
+{
+  ULONG rc;
+  EAOP2 eaop;
+
+  eaop.fpGEA2List = NULL;
+  eaop.fpFEA2List = src;
+  eaop.oError = 0;
+  if (path != NULL)
+    rc = DosSetPathInfo (path, 2, &eaop, sizeof (eaop), 0);
+  else
+    rc = DosSetFileInfo (handle, 2, &eaop, sizeof (eaop));
+  if (rc != 0)
+    {
+      _ea_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/eof.c
===================================================================
--- trunk/src/emx/src/lib/io/eof.c	(revision 18)
+++ trunk/src/emx/src/lib/io/eof.c	(revision 18)
@@ -0,0 +1,26 @@
+/* eof.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _eof (int handle)
+{
+  int *pflags;
+  long cur, len;
+
+  if ((pflags = _fd_flags (handle)) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (*pflags & F_EOF)          /* Ctrl-Z reached */
+    return 1;
+  cur = _tell (handle);
+  if (cur < 0)
+    return -1;
+  len = _filelength (handle);
+  if (len < 0)
+    return -1;
+  return cur == len;
+}
Index: trunk/src/emx/src/lib/io/fassign.c
===================================================================
--- trunk/src/emx/src/lib/io/fassign.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fassign.c	(revision 18)
@@ -0,0 +1,44 @@
+/* fassign.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/io.h>
+
+FILE *_fassign (FILE *target, FILE *source)
+{
+  /* Prevent other threads from reusing TARGET's slot while TARGET is
+     closed. */
+
+  STREAMV_LOCK;
+
+  if (!(source->_flags & _IOOPEN))
+    {
+      STREAMV_UNLOCK;
+      errno = EINVAL;
+      return NULL;
+    }
+
+  /* Do nothing if TARGET and SOURCE are the same stream. */
+
+  if (source == target)
+    {
+      STREAMV_UNLOCK;
+      return target;
+    }
+
+  /* Close TARGET, ignoring errors. */
+
+  fclose (target);
+
+  /* Assign the stream. */
+
+  *target = *source;
+  if (target->_more != NULL)
+    target->_more->owner = target;
+  source->_flags = 0;
+  STREAMV_UNLOCK;
+  return target;
+}
Index: trunk/src/emx/src/lib/io/fclose.c
===================================================================
--- trunk/src/emx/src/lib/io/fclose.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fclose.c	(revision 18)
@@ -0,0 +1,33 @@
+/* fclose.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <emx/io.h>
+
+int fclose (FILE *stream)
+{
+  int result;
+  char buf[L_tmpnam];
+
+  result = EOF;
+  if ((stream->_flags & _IOOPEN) && !(stream->_flags & _IOSPECIAL))
+    {
+      result = 0;
+      result = fflush (stream);
+      if (_close (stream->_handle) < 0)
+        result = EOF;
+      if (result == 0 && (stream->_flags & _IOTMP))
+        {
+          _itoa (stream->_tmpidx, buf, 10);
+          strcat (buf, ".tmp");
+          if (remove (buf) != 0)
+            result = EOF;
+        }
+      if ((stream->_flags & _IOBUFMASK) == _IOBUFLIB)
+        free (stream->_buffer);
+    }
+  _closestream (stream);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/fcloseal.c
===================================================================
--- trunk/src/emx/src/lib/io/fcloseal.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fcloseal.c	(revision 18)
@@ -0,0 +1,30 @@
+/* fcloseal.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <emx/io.h>
+
+int _fcloseall (void)
+{
+  int i, n, start;
+  char ok;
+  struct streamvec *sv;
+
+  n = 0; ok = 1;
+  for (sv = &_streamvec_head; sv != NULL; sv = sv->next)
+    {
+      if (sv->vec == _streamv)
+        start = 3;              /* Keep stdin, stdout, stderr */
+      else
+        start = 0;
+      for (i = start; i < sv->n; ++i)
+        if (sv->vec[i]._flags & _IOOPEN)
+          {
+            if (fclose (&sv->vec[i]) == 0)
+              ++n;
+            else
+              ok = 0;
+          }
+      start = 0;
+    }
+  return (ok ? n : EOF);
+}
Index: trunk/src/emx/src/lib/io/fcntl.c
===================================================================
--- trunk/src/emx/src/lib/io/fcntl.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fcntl.c	(revision 18)
@@ -0,0 +1,117 @@
+/* fcntl.c (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes */
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+#define FLAGS (O_APPEND | O_NDELAY)
+
+/* Replace some bits in an lvalue */
+
+#define SETBITS(dst,mask,newb) ((dst) = ((dst) & ~(mask)) | ((newb) & (mask)))
+
+
+/* Create a new file descriptor for HANDLE that is the lowest numbered
+   available file descriptor greater than or equal to HANDLE2. */
+
+static int dupfd (int handle, int handle2)
+{
+  int *handles;
+  int n, fd, e;
+
+  /* TODO: Use sysconf()? */
+
+  if (handle2 < 0 || handle2 >= _POSIX_OPEN_MAX)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  handles = alloca (handle2 * sizeof (int));
+  n = 0;
+  for (;;)
+    {
+      fd = _dup (handle);
+      if (fd < 0 || fd >= handle2)
+        break;
+      if (n >= handle2)
+        {
+          /* Avoid writing beyond the end of handles[] if dup()
+             happens not to work as advertised. */
+
+          _close (fd);
+          fd = -1; errno = EMFILE;
+          break;
+        }
+      handles[n++] = fd;
+    }
+  e = errno;
+  while (n > 0)
+    _close (handles[--n]);
+  errno = e;
+  return fd;
+}
+
+
+int _fcntl (int handle, int request, ...)
+{
+  va_list va;
+  int ht, arg, *pflags;
+
+  if ((pflags = _fd_flags (handle)) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  switch (request)
+    {
+    case F_GETFL:
+      /* Check for valid handle.  We don't call __fcntl() because
+         emx.exe does not implement F_GETFL (emx.dll and rsx.exe
+         do). */
+
+      if (__ioctl2 (handle, FGETHTYPE, (int)&ht) != 0)
+        return -1;
+      return *pflags & FLAGS;
+
+    case F_SETFL:
+      va_start (va, request);
+      arg = va_arg (va, int);
+      va_end (va);
+      if (arg & ~FLAGS)
+        break;
+      if (__fcntl (handle, request, arg) == -1)
+        return -1;
+      SETBITS (*pflags, FLAGS, arg);
+      return 0;
+
+    case F_GETFD:
+    case F_SETFD:
+      va_start (va, request);
+      arg = va_arg (va, int);
+      va_end (va);
+      return __fcntl (handle, request, arg);
+
+    case F_DUPFD:
+      va_start (va, request);
+      arg = va_arg (va, int);
+      va_end (va);
+      if (arg < 0)
+        {
+          errno = EINVAL;
+          return -1;
+        }
+      return dupfd (handle, arg);
+
+    case F_GETOSFD:
+      return __fcntl (handle, request, 0);
+    }
+
+  errno = EINVAL;
+  return -1;
+}
Index: trunk/src/emx/src/lib/io/fdopen.c
===================================================================
--- trunk/src/emx/src/lib/io/fdopen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fdopen.c	(revision 18)
@@ -0,0 +1,92 @@
+/* fdopen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+
+#define FALSE   0
+#define TRUE    1
+
+/* Bug: doesn't check for compatible modes (O_ACCMODE) */
+
+FILE *_fdopen (int handle, const char *mode)
+{
+  char ok, bt;
+  FILE *dst;
+  int omode;
+
+  if (_fd_flags (handle) == NULL)
+    {
+      errno = EBADF;
+      return NULL;
+    }
+  dst = _newstream ();
+  switch (*mode)
+    {
+    case 'r':
+      dst->_flags = _IOREAD;
+      break;
+    case 'w':
+      dst->_flags = _IOWRT;
+      break;
+    case 'a':
+      dst->_flags = _IOWRT;
+      break;
+    default:
+      _closestream (dst);
+      return NULL;
+    }
+  ++mode; ok = TRUE; bt = FALSE; omode = 0;
+  while (*mode != 0 && ok)
+    {
+      switch (*mode)
+        {
+        case 't':
+          if (bt)
+            ok = FALSE;
+          else
+            {
+              bt = TRUE;
+              omode = O_TEXT;
+            }
+          break;
+        case 'b':
+          if (bt)
+            ok = FALSE;
+          else
+            {
+              bt = TRUE;
+              omode = O_BINARY;
+            }
+          break;
+        case '+':
+          if (dst->_flags & _IORW)
+            ok = FALSE;
+          else
+            {
+              dst->_flags &= ~(_IOREAD|_IOWRT);
+              dst->_flags |= _IORW;
+            }
+          break;
+        default:
+          ok = FALSE; break;
+        }
+      if (ok) ++mode;
+    }
+  if (bt)
+    _setmode (handle, omode);
+  dst->_handle = handle;
+  dst->_ptr = NULL;
+  dst->_buffer = NULL;
+  dst->_buf_size = 0;
+  dst->_rcount = 0;
+  dst->_wcount = 0;
+  dst->_flags |= _IOOPEN | _IOBUFNONE;
+  dst->_flush = _flushstream;
+  dst->_ungetc_count = 0;
+  if (_setmore (dst, 1) != 0)
+    return NULL;
+  return dst;
+}
Index: trunk/src/emx/src/lib/io/feof.c
===================================================================
--- trunk/src/emx/src/lib/io/feof.c	(revision 18)
+++ trunk/src/emx/src/lib/io/feof.c	(revision 18)
@@ -0,0 +1,8 @@
+/* feof.c (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int feof (FILE *s)
+{
+  return (s->_flags & _IOEOF ? 1 : 0);
+}
Index: trunk/src/emx/src/lib/io/ferror.c
===================================================================
--- trunk/src/emx/src/lib/io/ferror.c	(revision 18)
+++ trunk/src/emx/src/lib/io/ferror.c	(revision 18)
@@ -0,0 +1,8 @@
+/* ferror.c (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int ferror (FILE *s)
+{
+  return (s->_flags & _IOERR ? 1 : 0);
+}
Index: trunk/src/emx/src/lib/io/fflush.c
===================================================================
--- trunk/src/emx/src/lib/io/fflush.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fflush.c	(revision 18)
@@ -0,0 +1,86 @@
+/* fflush.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <emx/io.h>
+
+int _fflush_nolock (FILE *stream)
+{
+  int result, n, ft, saved_errno;
+  long pos;
+
+  result = 0;
+  if (stream->_flags & _IOSPECIAL)
+    {
+      if (stream->_flush != NULL)
+        result = stream->_flush (stream, _FLUSH_FLUSH);
+      stream->_ungetc_count = 0; /* Undo ungetc() */
+      stream->_flags &= ~_IOUNGETC;
+      return result;
+    }
+  if ((stream->_flags & _IOWRT) && bbuf (stream))
+    {
+      n = stream->_ptr - stream->_buffer;
+      if (n > 0 && _stream_write (stream->_handle, stream->_buffer, n) <= 0)
+        {
+          stream->_flags |= _IOERR;
+          result = EOF;
+        }
+    }
+
+  /* Undo ungetc() now, before calling ftell(). */
+
+  if (stream->_ungetc_count != 0)
+    {
+      stream->_rcount = -stream->_rcount;
+      stream->_ungetc_count = 0;
+    }
+  stream->_flags &= ~_IOUNGETC;
+
+  saved_errno = errno;
+  if ((stream->_flags & _IOREAD) && bbuf (stream) &&
+      _ioctl (stream->_handle, FGETHTYPE, &ft) >= 0 && ft == HT_FILE)
+    {
+      /* ISO 9899-1990, 7.9.5.2: "The fflush function returns EOF if a
+         write error occurs, otherwise zero." */
+      pos = _ftell_nolock (stream);
+      if (pos != -1L)
+        _lseek (stream->_handle, pos, SEEK_SET);
+    }
+  errno = saved_errno;
+  stream->_ptr = stream->_buffer;
+  stream->_rcount = 0;
+  stream->_wcount = 0;
+  if ((stream->_flags & (_IORW|_IOWRT)) == (_IORW|_IOWRT))
+    stream->_flags &= ~_IOWRT;
+  return result;
+}
+
+
+int fflush (FILE *stream)
+{
+  int result, n;
+  struct streamvec *sv;
+
+  result = 0;
+  if (stream == NULL)
+    {
+      for (sv = &_streamvec_head; sv != NULL; sv = sv->next)
+        for (n = 0; n < sv->n; ++n)
+          if ((sv->vec[n]._flags & (_IOOPEN|_IOWRT)) == (_IOOPEN|_IOWRT))
+            if (fflush (&sv->vec[n]) != 0)
+              result = EOF;
+      return result;
+    }
+
+  STREAM_LOCK (stream);
+  result = _fflush_nolock (stream);
+  STREAM_UNLOCK (stream);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/fgetc.c
===================================================================
--- trunk/src/emx/src/lib/io/fgetc.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fgetc.c	(revision 18)
@@ -0,0 +1,18 @@
+/* fgetc.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+int fgetc (FILE *stream)
+{
+  int r;
+
+  STREAM_LOCK (stream);
+  r = _getc_inline (stream);
+  STREAM_UNLOCK (stream);
+  return r;
+}
Index: trunk/src/emx/src/lib/io/fgetchar.c
===================================================================
--- trunk/src/emx/src/lib/io/fgetchar.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fgetchar.c	(revision 18)
@@ -0,0 +1,8 @@
+/* fgetchar.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int _fgetchar (void)
+{
+  return getchar ();
+}
Index: trunk/src/emx/src/lib/io/fgetpos.c
===================================================================
--- trunk/src/emx/src/lib/io/fgetpos.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fgetpos.c	(revision 18)
@@ -0,0 +1,16 @@
+/* fgetpos.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int fgetpos (FILE *stream, fpos_t *pos)
+{
+  long n;
+
+  if ((n = ftell (stream)) == (long)EOF)
+    return EOF;
+  pos->_pos = n;
+  pos->_reserved1 = 0;
+  pos->_mbstate = stream->_mbstate;
+  pos->_reserved2 = 0;
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/fgets.c
===================================================================
--- trunk/src/emx/src/lib/io/fgets.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fgets.c	(revision 18)
@@ -0,0 +1,48 @@
+/* fgets.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+char *fgets (char *buffer, int n, FILE *stream)
+{
+  int c;
+  char *dst;
+
+  if (n <= 0)
+    return NULL;
+  dst = buffer;
+
+  STREAM_LOCK (stream);
+  while (n > 1)
+    {
+      c = _getc_inline (stream);
+      if (c == EOF)
+        {
+          /* ISO/IEC 9899:1990, 7.9.7.2: "If end-of-file is
+             encountered and no characters have been read into the
+             array, the contents of the array remain unchanged and a
+             null pointer is returned.  If a read error occurs during
+             the operation, the array contents are indeterminate and a
+             null pointer is returned." */
+
+          if (dst == buffer || ferror (stream))
+            {
+              STREAM_UNLOCK (stream);
+              return NULL;
+            }
+          else
+            break;              /* EOF after reading at least one char */
+        }
+      *dst++ = (char)c;
+      if (c == '\n')
+        break;
+      --n;
+    }
+  STREAM_UNLOCK (stream);
+  *dst = 0;
+  return buffer;
+}
Index: trunk/src/emx/src/lib/io/fileleng.c
===================================================================
--- trunk/src/emx/src/lib/io/fileleng.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fileleng.c	(revision 18)
@@ -0,0 +1,16 @@
+/* fileleng.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <emx/syscalls.h>
+
+long _filelength (int handle)
+{
+  long cur, n;
+
+  cur = (long)__lseek (handle, 0L, SEEK_CUR);
+  if (cur == -1L)
+    return -1;
+  n = (long)__lseek (handle, 0L, SEEK_END);
+  __lseek (handle, cur, SEEK_SET);
+  return n;
+}
Index: trunk/src/emx/src/lib/io/fileno.c
===================================================================
--- trunk/src/emx/src/lib/io/fileno.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fileno.c	(revision 18)
@@ -0,0 +1,8 @@
+/* fileno.c (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int fileno (FILE *s)
+{
+  return s->_handle;
+}
Index: trunk/src/emx/src/lib/io/flock.c
===================================================================
--- trunk/src/emx/src/lib/io/flock.c	(revision 18)
+++ trunk/src/emx/src/lib/io/flock.c	(revision 18)
@@ -0,0 +1,16 @@
+/* flock.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <sys/file.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _flock (int handle, int operation)
+{
+  if (_fd_flags (handle) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  /*...this is a dummy function...*/
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/flushall.c
===================================================================
--- trunk/src/emx/src/lib/io/flushall.c	(revision 18)
+++ trunk/src/emx/src/lib/io/flushall.c	(revision 18)
@@ -0,0 +1,27 @@
+/* flushall.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <emx/io.h>
+
+int _flushall (void)
+{
+  int i, n;
+  struct streamvec *sv;
+
+  /* Ignore locked streams to avoid deadlock on process
+     termination. */
+
+  n = 0;
+  for (sv = &_streamvec_head; sv != NULL; sv = sv->next)
+    for (i = 0; i < sv->n; ++i)
+      if ((sv->vec[i]._flags & _IOOPEN) && STREAM_LOCK_NOWAIT (&sv->vec[i]))
+        {
+          ++n;
+          _fflush_nolock (&sv->vec[i]);
+          STREAM_UNLOCK (&sv->vec[i]);
+        }
+  return n;
+}
Index: trunk/src/emx/src/lib/io/fopen.c
===================================================================
--- trunk/src/emx/src/lib/io/fopen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fopen.c	(revision 18)
@@ -0,0 +1,15 @@
+/* fopen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <share.h>
+#include <emx/io.h>
+
+FILE *fopen (const char *fname, const char *mode)
+{
+  FILE *f;
+
+  f = _newstream ();
+  if (f != NULL)
+    f = _fopen (f, fname, mode, SH_DENYNO, 1);
+  return f;
+}
Index: trunk/src/emx/src/lib/io/fprintf.c
===================================================================
--- trunk/src/emx/src/lib/io/fprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fprintf.c	(revision 18)
@@ -0,0 +1,28 @@
+/* fprintf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <emx/io.h>
+
+int fprintf (FILE *stream, const char *format, ...)
+{
+  va_list arg_ptr;
+  int result;
+  void *tb;
+
+  va_start (arg_ptr, format);
+  STREAM_LOCK (stream);
+  if (nbuf (stream))
+    _fbuf (stream);
+  _tmpbuf (stream, tb);
+  result = _output (stream, format, arg_ptr);
+  if (_endbuf (stream) != 0)
+    result = -1;
+  STREAM_UNLOCK (stream);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/fputc.c
===================================================================
--- trunk/src/emx/src/lib/io/fputc.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fputc.c	(revision 18)
@@ -0,0 +1,18 @@
+/* fputc.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+int fputc (int c, FILE *stream)
+{
+  int r;
+
+  STREAM_LOCK (stream);
+  r = _putc_inline (c, stream);
+  STREAM_UNLOCK (stream);
+  return r;
+}
Index: trunk/src/emx/src/lib/io/fputchar.c
===================================================================
--- trunk/src/emx/src/lib/io/fputchar.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fputchar.c	(revision 18)
@@ -0,0 +1,8 @@
+/* fputchar.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int _fputchar (int c)
+{
+  return putchar (c);
+}
Index: trunk/src/emx/src/lib/io/fputs.c
===================================================================
--- trunk/src/emx/src/lib/io/fputs.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fputs.c	(revision 18)
@@ -0,0 +1,12 @@
+/* fputs.c (emx+gcc) -- Copyright (c) 1990-1993 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <string.h>
+
+int fputs (const char *string, FILE *stream)
+{
+  int len;
+
+  len = strlen (string);
+  return (len == 0 || fwrite (string, len, 1, stream) == 1 ? 0 : EOF);
+}
Index: trunk/src/emx/src/lib/io/fread.c
===================================================================
--- trunk/src/emx/src/lib/io/fread.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fread.c	(revision 18)
@@ -0,0 +1,125 @@
+/* fread.c (emx+gcc) -- Copyright (c) 1990-1999 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+size_t fread (void *buffer, size_t size, size_t count, FILE *stream)
+{
+  size_t total, left, n;
+  int r;   /* signed! */
+  char *dst;
+  int fh, c;
+
+  if (size == 0 || count == 0)
+    return 0;
+  total = size * count;
+  if (total / count != size)
+    {
+      errno = ERANGE;
+      return 0;
+    }
+
+  STREAM_LOCK (stream);
+  if (nbuf (stream))
+    _fbuf (stream);
+  left = total;
+  dst = buffer;
+  fh = stream->_handle;
+  stream->_flags |= _IOREAD;
+  if (bbuf (stream))
+    while (left != 0)
+      {
+        if (stream->_rcount > 0)
+          {
+            n = min ((size_t)stream->_rcount, left);
+            memcpy (dst, stream->_ptr, n);
+            stream->_ptr += n;
+            stream->_rcount -= n;
+            dst += n;
+            left -= n;
+          }
+        else if (left > BUFSIZ && stream->_ungetc_count == 0)
+          {
+            n = (left / BUFSIZ) * BUFSIZ;      /* Number of buffers */
+            r = _stream_read (fh, dst, n);
+            if (r < 0)
+              {
+                stream->_flags |= _IOERR;
+                break;
+              }
+            if (r == 0)
+              {
+                stream->_ptr = stream->_buffer;
+                stream->_flags |= _IOEOF;
+                if (stream->_flags & _IORW)
+                  stream->_flags &= ~(_IOREAD|_IOWRT);
+                break;
+              }
+            left -= r;
+            dst += r;
+          }
+        else
+          {
+            --stream->_rcount;
+            c = _fill (stream);
+            if (c == EOF)
+              break;
+            *dst++ = (char)c;
+            --left;
+          }
+      }
+  else
+    {
+      if (stream->_rcount > 0)
+        {
+          n = min ((size_t)stream->_rcount, left);
+          memcpy (dst, stream->_ptr, n);
+          stream->_ptr += n;
+          stream->_rcount -= n;
+          dst += n;
+          left -= n;
+        }
+      while (left != 0)
+        {
+          if (stream->_ungetc_count != 0)
+            {
+              --stream->_rcount;
+              c = _fill (stream);
+              if (c == EOF)
+                break;
+              *dst++ = (char)c;
+              --left;
+            }
+          else
+            {
+              r = _stream_read (fh, dst, left);
+              if (r < 0)
+                {
+                  stream->_flags |= _IOERR;
+                  break;
+                }
+              if (r == 0)
+                {
+                  stream->_ptr = stream->_buffer;
+                  stream->_flags |= _IOEOF;
+                  if (stream->_flags & _IORW)
+                    stream->_flags &= ~(_IOREAD|_IOWRT);
+                  break;
+                }
+              dst += r;
+              left -= r;
+            }
+        }
+    }
+  STREAM_UNLOCK (stream);
+  return (total - left) / size;
+}
Index: trunk/src/emx/src/lib/io/freopen.c
===================================================================
--- trunk/src/emx/src/lib/io/freopen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/freopen.c	(revision 18)
@@ -0,0 +1,20 @@
+/* freopen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <share.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/io.h>
+
+FILE *freopen (const char *fname, const char *mode, FILE *stream)
+{
+  FILE *result;
+
+  STREAMV_LOCK;
+  if (stream->_flags & _IOOPEN)
+    fclose (stream);
+  result = _fopen (stream, fname, mode, SH_DENYNO, 0);
+  STREAMV_UNLOCK;
+  return result;
+}
Index: trunk/src/emx/src/lib/io/fscanf.c
===================================================================
--- trunk/src/emx/src/lib/io/fscanf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fscanf.c	(revision 18)
@@ -0,0 +1,22 @@
+/* fscanf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <emx/io.h>
+
+int fscanf (FILE *stream, const char *format, ...)
+{
+  va_list arg_ptr;
+  int result;
+
+  va_start (arg_ptr, format);
+  STREAM_LOCK (stream);
+  result = _input (stream, format, arg_ptr);
+  STREAM_UNLOCK (stream);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/fseek.c
===================================================================
--- trunk/src/emx/src/lib/io/fseek.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fseek.c	(revision 18)
@@ -0,0 +1,188 @@
+/* fseek.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _fseek_nolock (FILE *stream, long offset, int origin)
+{
+  long cur_pos;
+  int fflush_result, *pflags;
+
+  if (!(stream->_flags & _IOOPEN) || origin < 0 || origin > 2
+      || (stream->_flags & _IOSPECIAL))
+    {
+      errno = EINVAL;
+      return EOF;
+    }
+
+  cur_pos = -1;                 /* Not yet computed */
+
+  /* fflush() is not required if all of the following conditions are met:
+     - the stream is a read-only file
+     - the buffer has not been modified by ungetc()
+     - the stream is buffered
+     - there are no pushed-back characters
+     - the new position is within buffer */
+
+  if ((stream->_flags & (_IORW|_IOREAD|_IOWRT|_IOUNGETC)) == _IOREAD
+      && bbuf (stream) && stream->_ungetc_count == 0)
+    {
+      long file_pos, end_pos, buf_pos;
+      int text_mode, n;
+
+      file_pos = _tell (stream->_handle);
+      if (file_pos == -1) return EOF;
+      cur_pos = _ftell_nolock (stream);
+      if (origin == SEEK_CUR)
+        {
+          offset += cur_pos;
+          origin = SEEK_SET;
+        }
+      else if (origin == SEEK_END)
+        {
+          end_pos = _lseek (stream->_handle, 0L, SEEK_END);
+          _lseek (stream->_handle, file_pos, SEEK_SET);
+          if (end_pos == -1)
+            return EOF;
+          offset += end_pos;
+          origin = SEEK_SET;
+        }
+      text_mode = ((pflags = _fd_flags (stream->_handle)) != NULL
+                   && (*pflags & F_CRLF));
+      n = stream->_ptr - stream->_buffer;
+      if (text_mode)
+        {
+          /* Use lower bound on the buffer position for a quick check
+             if the new position can at all be inside the buffer.  The
+             lower bound is the exact buffer position if all
+             characters in the buffer are newline characters. */
+
+          buf_pos = cur_pos - 2 * n;
+        }
+      else
+        buf_pos = cur_pos - n;
+
+      if (offset >= buf_pos && offset < file_pos)
+        {
+          if (text_mode)
+            {
+              const char *p;
+
+              /* Compute exact buffer position.  This is only required
+                 if the new position is smaller than the current
+                 position. */
+
+              if (offset >= cur_pos)
+                buf_pos = cur_pos; /* Wrong value doesn't matter */
+              else
+                {
+                  p = stream->_ptr;
+                  buf_pos = cur_pos - n;
+                  while (n > 0)
+                    {
+                      if (*--p == '\n')
+                        --buf_pos;
+                      --n;
+                    }
+                }
+
+              if (offset >= buf_pos)
+                {
+                  long tmp_pos;
+
+                  /* The new position is within the buffer.  Adjust
+                     the new position for newline characters.  If
+                     offset >= cur_pos, we can start at the current
+                     position. */
+
+                  if (offset >= cur_pos)
+                    {
+                      /* Optimization. */
+
+                      p = stream->_ptr;
+                      tmp_pos = cur_pos;
+                    }
+                  else
+                    {
+                      p = stream->_buffer;
+                      tmp_pos = buf_pos;
+                    }
+                  while (tmp_pos < offset)
+                    {
+                      if (*p == '\n')
+                        {
+                          ++tmp_pos;
+                          if (tmp_pos >= offset)
+                            break;
+                        }
+                      ++p; ++tmp_pos;
+                    }
+                  stream->_rcount -= p - stream->_ptr;
+                  stream->_ptr = (char *)p;
+                  stream->_flags &= ~_IOEOF;
+                  return 0;
+                }
+            }
+          else if (offset >= buf_pos)
+            {
+              stream->_ptr = stream->_buffer + (offset - buf_pos);
+              stream->_rcount = file_pos - offset;
+              stream->_flags &= ~_IOEOF;
+              return 0;
+            }
+        }
+    }
+
+#if 1
+  /* Get file position indicator before undoing any effects of
+     ungetc().  ANSI X3.159-1989 is not precise on this. */
+
+  if (origin == SEEK_CUR && cur_pos == -1)
+    cur_pos = _ftell_nolock (stream);
+#endif
+
+  fflush_result = _fflush_nolock (stream);
+  stream->_flags &= ~_IOEOF;
+  if (stream->_flags & _IORW)
+    stream->_flags &= ~(_IOREAD|_IOWRT);
+
+  if (origin == SEEK_CUR)
+    {
+      if (cur_pos == -1)
+        cur_pos = _ftell_nolock (stream);
+      if (cur_pos == -1)
+        {
+          /* "fseek (f, 0L, SEEK_CUR)" should not fail for
+             non-seekable files as it is required for switching from
+             read mode to write mode. */
+
+          if (offset == 0 && (stream->_flags & _IORW))
+            return fflush_result;
+          return EOF;
+        }
+      offset += cur_pos;
+      origin = SEEK_SET;
+    }
+
+  if (_lseek (stream->_handle, offset, origin) == -1)
+    return EOF;
+  else
+    return fflush_result;
+}
+
+
+int fseek (FILE *stream, long offset, int origin)
+{
+  int result;
+
+  STREAM_LOCK (stream);
+  result = _fseek_nolock (stream, offset, origin);
+  STREAM_UNLOCK (stream);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/fsetpos.c
===================================================================
--- trunk/src/emx/src/lib/io/fsetpos.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fsetpos.c	(revision 18)
@@ -0,0 +1,11 @@
+/* fsetpos.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int fsetpos (FILE *stream, const fpos_t *pos)
+{
+  if (fseek (stream, pos->_pos, SEEK_SET) != 0)
+    return -1;
+  stream->_mbstate = pos->_mbstate;
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/fstat.c
===================================================================
--- trunk/src/emx/src/lib/io/fstat.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fstat.c	(revision 18)
@@ -0,0 +1,23 @@
+/* fstat.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <time.h>
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+int _fstat (int handle, struct stat *buffer)
+{
+  int rc;
+
+  rc = __fstat (handle, buffer);
+  if (rc == 0)
+    {
+      if (!_tzset_flag) _tzset ();
+      _loc2gmt (&buffer->st_atime, -1);
+      _loc2gmt (&buffer->st_mtime, -1);
+      _loc2gmt (&buffer->st_ctime, -1);
+    }
+  return rc;
+}
Index: trunk/src/emx/src/lib/io/fsync.c
===================================================================
--- trunk/src/emx/src/lib/io/fsync.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fsync.c	(revision 18)
@@ -0,0 +1,9 @@
+/* fsync.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <emx/syscalls.h>
+
+int _fsync (int handle)
+{
+  return __fsync (handle);
+}
Index: trunk/src/emx/src/lib/io/ftell.c
===================================================================
--- trunk/src/emx/src/lib/io/ftell.c	(revision 18)
+++ trunk/src/emx/src/lib/io/ftell.c	(revision 18)
@@ -0,0 +1,108 @@
+/* ftell.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <io.h>
+#include <fcntl.h>
+#include <emx/io.h>
+
+long _ftell_nolock (FILE *stream)
+{
+  long pos;
+  int *pflags;
+
+  if (stream->_flags & _IOSPECIAL)
+    pos = 0;
+  else
+    {
+      pos = _tell (stream->_handle);
+      if (pos == -1)
+        return -1;
+    }
+  if (stream->_flags & _IOWRT)
+    {
+      if (bbuf (stream))
+        {
+          pos += stream->_ptr - stream->_buffer;
+          if (!(stream->_flags & _IOSPECIAL)
+              && (pflags = _fd_flags (stream->_handle)) != NULL
+              && (*pflags & O_TEXT))
+            {
+              const char *p;
+              int n;
+
+              /* In text mode, newlines are translated to CR/LF pairs.
+                 Adjust the position to take account of this. */
+
+              n = stream->_ptr - stream->_buffer;
+              p = stream->_buffer;
+              while (n > 0)
+                {
+                  if (*p ++ == '\n')
+                    ++pos;
+                  --n;
+                }
+            }
+        }
+    }
+  else if (stream->_flags & _IOREAD)
+    {
+      /* Subtract the number of unprocessed buffered characters from
+         the file position of the end of the buffer to get the current
+         position. */
+
+      if (!(stream->_flags & _IOSPECIAL)
+          && stream->_ungetc_count == 0
+          && (pflags = _fd_flags (stream->_handle)) != NULL
+          && (*pflags & F_CRLF))
+        {
+          const char *p;
+          int n;
+
+          /* There has been at least one CR/LF to newline translation.
+             Assume that all newlines in the buffer have been
+             translated from a CR/LF pair each. */
+
+          p = stream->_ptr;
+          n = stream->_rcount;
+          pos -= n;
+          while (n > 0)
+            {
+              if (*p++ == '\n')
+                --pos;
+              --n;
+            }
+        }
+      else if (stream->_ungetc_count != 0)
+        {
+          /* There are characters pushed back by ungetc().  For binary
+             streams, each successful ungetc() decrements the file position
+             indicator.  Treat text mode like binary mode as the file
+             position indicator is undefined in text mode after
+             calling ungetc(). */
+
+          pos = pos + stream->_rcount - stream->_ungetc_count;
+        }
+      else
+        {
+          /* Binary mode. */
+
+          pos -= stream->_rcount;
+        }
+    }
+  return pos;
+}
+
+
+long ftell (FILE *stream)
+{
+  long r;
+
+  STREAM_LOCK (stream);
+  r = _ftell_nolock (stream);
+  STREAM_UNLOCK (stream);
+  return r;
+}
Index: trunk/src/emx/src/lib/io/ftruncat.c
===================================================================
--- trunk/src/emx/src/lib/io/ftruncat.c	(revision 18)
+++ trunk/src/emx/src/lib/io/ftruncat.c	(revision 18)
@@ -0,0 +1,18 @@
+/* ftruncat.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _ftruncate (int handle, long length)
+{
+  int *pflags;
+
+  if ((pflags = _fd_flags (handle)) == NULL || (*pflags & F_DEV))
+    {
+      errno = EBADF;
+      return -1;
+    }
+  return __ftruncate (handle, length);
+}
Index: trunk/src/emx/src/lib/io/fwrite.c
===================================================================
--- trunk/src/emx/src/lib/io/fwrite.c	(revision 18)
+++ trunk/src/emx/src/lib/io/fwrite.c	(revision 18)
@@ -0,0 +1,169 @@
+/* fwrite.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+
+
+static size_t fwrite_internal (const char *src, size_t left, FILE *stream)
+{
+  size_t n;
+  int w;   /* signed! */
+  int fh;
+
+  fh = stream->_handle;
+  if (stream->_flags & _IOSPECIAL)
+    {
+      while (left != 0)
+        {
+          n = stream->_wcount;
+          if (n == 0)
+            {
+              if (_flush (*src++, stream) == EOF)
+                {
+                  stream->_flags |= _IOERR;
+                  return left;
+                }
+              --left;
+            }
+          else
+            {
+              if (left < n)
+                n = left;
+              memcpy (stream->_ptr, src, n);
+              stream->_ptr += n; stream->_wcount -= n;
+              src += n; left -= n;
+            }
+        }
+    }
+  else if (bbuf (stream))
+    {
+      if (stream->_wcount == 0 && stream->_ptr == stream->_buffer)
+        stream->_wcount = stream->_buf_size;
+      while (left != 0)
+        {
+          if (left <= stream->_wcount)
+            {
+              memcpy (stream->_ptr, src, left);
+              stream->_ptr += left;
+              stream->_wcount -= left;
+              src += left;
+              left = 0;
+            }
+          else if (stream->_ptr != stream->_buffer) /* Buffer non-empty */
+            {
+              n = stream->_ptr - stream->_buffer;
+              stream->_ptr = stream->_buffer;
+              while (n != 0)
+                {
+                  w = _stream_write (fh, stream->_ptr, n);
+                  if (w <= 0)
+                    {
+                      stream->_flags |= _IOERR;
+                      return left;
+                    }
+                  n -= w; stream->_ptr += w;
+                }
+              stream->_ptr = stream->_buffer;
+              stream->_wcount = stream->_buf_size;
+            }
+          else
+            {
+              w = _stream_write (fh, src, left);
+              if (w <= 0)
+                {
+                  stream->_flags |= _IOERR;
+                  return left;
+                }
+              src += w;
+              left -= w;
+            }
+        }
+    }
+  else
+    while (left != 0)
+      {
+        w = _stream_write (fh, src, left);
+        if (w <= 0)
+          {
+            stream->_flags |= _IOERR;
+            return left;
+          }
+        src += w;
+        left -= w;
+      }
+  return left;
+}
+
+
+size_t _fwrite_nolock (const void *buffer, size_t size, size_t count,
+                       FILE *stream)
+{
+  size_t total, left, n;
+  const char *src, *newline;
+
+  if (stream->_flags & _IOREAD)    /* File in read mode? */
+    {
+      stream->_flags |= _IOERR;
+      errno = EACCES;
+      return 0;
+    }
+  if (count == 0)
+    return 0;
+  if (size == 0)
+    return count;
+  total = size * count;
+  if (total / count != size)
+    {
+      errno = ERANGE;
+      return 0;
+    }
+
+  if (nbuf (stream))
+    _fbuf (stream);
+  src = buffer;
+  stream->_flags |= _IOWRT;
+
+  if (stream->_flags & _IOLBF)
+    {
+      newline = _memrchr (src, '\n', total);
+      if (newline == NULL)
+        left = fwrite_internal (src, total, stream);
+      else
+        {
+          n = (size_t)(newline - src) + 1;
+          left = fwrite_internal (src, n, stream) + total - n;
+          if (left == total - n)
+            {
+              /* Note that the return value will be inaccurate if
+                 _fflush_nolock() fails, but that's also true for
+                 _IOFBF. */
+
+              if (_fflush_nolock (stream) != 0)
+                left = total;
+              else if (left != 0)
+                left = fwrite_internal (src + n, left, stream);
+            }
+        }
+    }
+  else
+    left = fwrite_internal (src, total, stream);
+  return (total - left) / size;
+}
+
+
+size_t fwrite (const void *buffer, size_t size, size_t count, FILE *stream)
+{
+  size_t r;
+
+  STREAM_LOCK (stream);
+  r = _fwrite_nolock (buffer, size, count, stream);
+  STREAM_UNLOCK (stream);
+  return r;
+}
Index: trunk/src/emx/src/lib/io/getc.c
===================================================================
--- trunk/src/emx/src/lib/io/getc.c	(revision 18)
+++ trunk/src/emx/src/lib/io/getc.c	(revision 18)
@@ -0,0 +1,10 @@
+/* getc.c (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int _getc_inline (FILE *s)
+{
+  return (--s->_rcount >= 0
+          ? (unsigned char)*s->_ptr++
+          : _fill (s));
+}
Index: trunk/src/emx/src/lib/io/getchar.c
===================================================================
--- trunk/src/emx/src/lib/io/getchar.c	(revision 18)
+++ trunk/src/emx/src/lib/io/getchar.c	(revision 18)
@@ -0,0 +1,8 @@
+/* getchar.c (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int getchar (void)
+{
+  return getc (stdin);
+}
Index: trunk/src/emx/src/lib/io/gets.c
===================================================================
--- trunk/src/emx/src/lib/io/gets.c	(revision 18)
+++ trunk/src/emx/src/lib/io/gets.c	(revision 18)
@@ -0,0 +1,38 @@
+/* gets.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+char *gets (char *buffer)
+{
+  int c;
+  char *dst;
+
+  dst = buffer;
+  STREAM_LOCK (stdin);
+  for (;;)
+    {
+      c = _getc_inline (stdin);
+      if (c == EOF)
+        {
+          if (dst == buffer)
+            {
+              *dst = 0;
+              STREAM_UNLOCK (stdin);
+              return NULL;
+            }
+          else
+            break;
+        }
+      if (c == '\n')
+        break;
+      *dst++ = (char)c;
+    }
+  STREAM_UNLOCK (stdin);
+  *dst = 0;
+  return buffer;
+}
Index: trunk/src/emx/src/lib/io/getw.c
===================================================================
--- trunk/src/emx/src/lib/io/getw.c	(revision 18)
+++ trunk/src/emx/src/lib/io/getw.c	(revision 18)
@@ -0,0 +1,10 @@
+/* getw.c (emx+gcc) -- Copyright (c) 1992-1995 by Kai Uwe Rommel */
+
+#include <stdio.h>
+
+int _getw (FILE *stream)
+{
+  int x;
+
+  return (fread (&x, sizeof (x), 1, stream) == 1 ? x : EOF);
+}
Index: trunk/src/emx/src/lib/io/ioctl.c
===================================================================
--- trunk/src/emx/src/lib/io/ioctl.c	(revision 18)
+++ trunk/src/emx/src/lib/io/ioctl.c	(revision 18)
@@ -0,0 +1,76 @@
+/* ioctl.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/termio.h>
+#include <sys/ioctl.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+/* Including the socket header files would be overkill. */
+
+#define FIONBIO         0x667e
+
+int _ioctl (int handle, int request, ...)
+{
+  va_list va;
+  int rc, saved_errno, arg, *int_ptr, *pflags, *pla;
+  const struct termio *tp;
+
+  if ((pflags = _fd_flags (handle)) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  saved_errno = errno; errno = 0;
+  va_start (va, request);
+  arg = va_arg (va, int);
+  va_end (va);
+  rc = __ioctl2 (handle, request, arg);
+  if (rc >= 0 && errno == 0)
+    switch (request)
+      {
+      case TCSETAF:
+      case TCSETAW:
+      case TCSETA:
+        va_start (va, request);
+        tp = va_arg (va, const struct termio *);
+        va_end (va);
+        if (tp->c_lflag & IDEFAULT)
+          *pflags &= ~F_TERMIO;
+        else
+          *pflags |= F_TERMIO;
+        break;
+
+      case _TCSANOW:
+      case _TCSADRAIN:
+      case _TCSAFLUSH:
+        *pflags |= F_TERMIO;
+        break;
+
+      case FIONREAD:
+        if ((pla = _fd_lookahead (handle)) != NULL && *pla >= 0)
+          {
+            va_start (va, request);
+            int_ptr = va_arg (va, int *);
+            va_end (va);
+            ++(*int_ptr);
+          }
+        break;
+
+      case FIONBIO:
+        va_start (va, request);
+        int_ptr = va_arg (va, int *);
+        va_end (va);
+        if (*int_ptr)
+          *pflags |= O_NDELAY;
+        else
+          *pflags &= ~O_NDELAY;
+        break;
+      }
+  if (errno == 0)
+    errno = saved_errno;
+  return rc;
+}
Index: trunk/src/emx/src/lib/io/isatty.c
===================================================================
--- trunk/src/emx/src/lib/io/isatty.c	(revision 18)
+++ trunk/src/emx/src/lib/io/isatty.c	(revision 18)
@@ -0,0 +1,18 @@
+/* isatty.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _isatty (int handle)
+{
+  int *pflags;
+
+  if ((pflags = _fd_flags (handle)) == NULL)
+    {
+      errno = EBADF;
+      return 0;
+    }
+  else
+    return ((*pflags & F_DEV) ? 1 : 0);
+}
Index: trunk/src/emx/src/lib/io/lseek.c
===================================================================
--- trunk/src/emx/src/lib/io/lseek.c	(revision 18)
+++ trunk/src/emx/src/lib/io/lseek.c	(revision 18)
@@ -0,0 +1,50 @@
+/* lseek.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+long _lseek (int handle, long offset, int origin)
+{
+  int *pflags, *pla;
+  long n, cur;
+
+  if ((pflags = _fd_flags (handle)) == NULL
+      || (pla = _fd_lookahead (handle)) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (origin == SEEK_CUR && (*pla >= 0 || (*pflags & F_EOF)))
+    --offset;
+  if (offset < 0)
+    {
+      /* DOS doesn't return an error for seek before beginning of file */
+      if (origin == SEEK_SET)
+        {
+          errno = EINVAL;
+          return -1;
+        }
+      cur = (long)__lseek (handle, 0L, SEEK_CUR);
+      if (cur == -1L)
+        return -1;
+      n = (long)__lseek (handle, 0L, origin);
+      if (n + offset < 0)
+        {
+          __lseek (handle, cur, SEEK_SET);
+          errno = EINVAL;
+          return -1;
+        }
+      offset += n; origin = SEEK_SET;
+    }
+  n = (long)__lseek (handle, offset, origin);
+  if (n == -1L)
+    return -1;
+  else
+    {
+      *pflags &= ~F_EOF;        /* Clear Ctrl-Z flag */
+      *pla = -1;                /* Clear lookahead */
+      return n;
+    }
+}
Index: trunk/src/emx/src/lib/io/makefile
===================================================================
--- trunk/src/emx/src/lib/io/makefile	(revision 18)
+++ trunk/src/emx/src/lib/io/makefile	(revision 18)
@@ -0,0 +1,209 @@
+#
+# /emx/src/lib/io/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+_fbuf.o: _fbuf.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h
+_fill.o: _fill.c $(I)stdio.h $(I)io.h $(ERRNO) $(FCNTL) $(I)emx/io.h
+_flush.o: _flush.c $(I)stdio.h $(I)io.h $(ERRNO) $(FCNTL) $(I)emx/io.h
+_flushst.o: _flushst.c $(I)stdio.h $(I)io.h $(ERRNO) $(FCNTL) $(I)emx/io.h
+_fopen.o: _fopen.c $(I)stdio.h $(I)io.h $(FCNTL) $(ERRNO) $(I)emx/io.h
+_input.o: _input.c $(I)stdio.h $(I)stdlib.h $(I)stdarg.h $(I)string.h \
+		$(I)ctype.h $(I)limits.h $(I)locale.h $(I)emx/locale.h \
+		$(I)emx/io.h
+_newstre.o: _newstre.c $(I)stdio.h $(I)emx/io.h $(RMUTEX)
+_output.o: _output.c $(I)stdio.h $(I)stdlib.h $(I)stdarg.h $(I)string.h \
+		$(I)math.h $(I)float.h $(I)limits.h $(I)locale.h \
+		$(I)emx/io.h $(I)emx/float.h $(I)emx/locale.h
+_rmtmp.o: _rmtmp.c $(I)stdio.h $(I)emx/io.h $(RMUTEX)
+_str_rd.o: _str_rd.c $(I)unistd.h $(ERRNO) $(I)emx/io.h
+_str_wr.o: _str_wr.c $(I)unistd.h $(ERRNO) $(I)emx/io.h
+_tmpbuf.o: _tmpbuf.c $(I)stdio.h $(I)emx/io.h
+_tmp.o: _tmp.c _tmp.h $(RMUTEX) $(I)emx/startup.h
+_tmpidxn.o: _tmpidxn.c $(I)stdio.h $(I)stdlib.h $(I)string.h $(I)io.h \
+		$(ERRNO) $(I)emx/io.h _tmp.h
+_trslash.o: _trslash.c $(I)sys/nls.h $(I)emx/io.h
+clearerr.o: clearerr.c $(I)stdio.h
+fclose.o: fclose.c $(I)stdio.h $(I)stdlib.h $(I)io.h $(I)string.h $(I)emx/io.h
+feof.o: feof.c $(I)stdio.h
+ferror.o: ferror.c $(I)stdio.h
+fflush.o: fflush.c $(I)stdio.h $(I)stdlib.h $(I)io.h $(FCNTL) $(I)sys/ioctl.h \
+		$(I)emx/io.h $(RMUTEX)
+fgetc.o: fgetc.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h $(RMUTEX)
+fgetpos.o: fgetpos.c $(I)stdio.h
+fgets.o: fgets.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h $(RMUTEX)
+fileno.o: fileno.c $(I)stdio.h
+fopen.o: fopen.c $(I)stdio.h $(I)share.h $(I)emx/io.h
+fprintf.o: fprintf.c $(I)stdio.h $(I)stdlib.h $(I)stdarg.h $(I)emx/io.h \
+		$(RMUTEX)
+fputc.o: fputc.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h $(RMUTEX)
+fputs.o: fputs.c $(I)stdio.h $(I)string.h
+fread.o: fread.c $(I)stdio.h $(I)stdlib.h $(I)string.h $(I)io.h $(ERRNO) \
+		$(I)emx/io.h $(RMUTEX)
+freopen.o: freopen.c $(I)stdio.h $(I)share.h $(I)emx/io.h
+fscanf.o: fscanf.c $(I)stdio.h $(I)stdlib.h $(I)stdarg.h $(I)emx/io.h \
+		$(RMUTEX)
+fseek.o: fseek.c $(I)stdio.h $(I)stdlib.h $(I)io.h $(ERRNO) $(I)emx/io.h \
+		$(RMUTEX)
+fsetpos.o: fsetpos.c $(I)stdio.h
+ftell.o: ftell.c $(I)stdio.h $(I)stdlib.h $(I)io.h $(FCNTL) $(I)emx/io.h \
+		$(RMUTEX)
+fwrite.o: fwrite.c $(I)stdio.h $(I)stdlib.h $(I)io.h $(ERRNO) $(I)string.h \
+		$(I)emx/io.h $(RMUTEX)
+getc.o: getc.c $(I)stdio.h
+getchar.o: getchar.c $(I)stdio.h
+gets.o: gets.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h $(RMUTEX)
+printf.o: printf.c $(I)stdio.h $(I)stdlib.h $(I)stdarg.h $(I)emx/io.h \
+		$(RMUTEX)
+putc.o: putc.c $(I)stdio.h
+putchar.o: putchar.c $(I)stdio.h
+puts.o: puts.c $(I)stdio.h $(I)stdlib.h $(I)string.h $(I)emx/io.h $(RMUTEX)
+remove.o: remove.c $(I)emx/syscalls.h $(I)io.h $(ERRNO)
+rename.o: rename.c $(I)stdio.h $(I)emx/syscalls.h $(ERRNO)
+rewind.o: rewind.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h $(RMUTEX)
+scanf.o: scanf.c $(I)stdio.h $(I)stdarg.h $(I)emx/io.h
+setbuf.o: setbuf.c $(I)stdio.h
+setvbuf.o: setvbuf.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h $(RMUTEX)
+sprintf.o: sprintf.c $(I)stdio.h $(I)stdarg.h $(I)limits.h $(I)emx/io.h
+sscanf.o: sscanf.c $(I)stdio.h $(I)stdarg.h $(I)limits.h $(I)emx/io.h
+tmpfile.o: tmpfile.c $(I)stdio.h $(I)stdlib.h $(ERRNO) $(FCNTL) $(I)io.h \
+		$(I)string.h $(I)sys/param.h $(I)emx/io.h _tmp.h
+tmpnam.o: tmpnam.c $(I)stdio.h $(I)emx/thread.h _tmp.h
+ungetc.o: ungetc.c $(I)stdio.h $(I)stdlib.h $(I)limits.h $(ERRNO) $(S)ioctl.h \
+		$(I)emx/io.h $(RMUTEX)
+vfprintf.o: vfprintf.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h $(RMUTEX)
+vfscanf.o: vfscanf.c $(I)stdio.h $(I)stdlib.h $(I)stdarg.h $(I)emx/io.h \
+		$(RMUTEX)
+vprintf.o: vprintf.c $(I)stdio.h $(I)stdlib.h $(I)emx/io.h $(RMUTEX)
+vscanf.o: vscanf.c $(I)stdio.h $(I)stdlib.h $(I)stdarg.h $(I)emx/io.h \
+		$(RMUTEX)
+vsprintf.o: vsprintf.c $(I)stdio.h $(I)limits.h $(I)emx/io.h
+vsscanf.o: vsscanf.c $(I)stdio.h $(I)stdarg.h $(I)limits.h $(I)emx/io.h
+
+
+_crlf.o: _crlf.c $(I)io.h $(I)string.h
+_fd.o: _fd.c $(I)emx/io.h
+_fdinit.o: _fdinit.c $(I)stdlib.h $(I)emx/io.h $(RMUTEX) $(I)emx/startup.h
+_fseekhd.o: _fseekhd.c $(I)stdio.h $(I)memory.h $(ERRNO)
+_fsetmod.o: _fsetmod.c $(I)stdio.h $(I)io.h $(ERRNO) $(FCNTL)
+_fsopen.o: _fsopen.c $(I)stdio.h $(I)emx/io.h
+_imphand.o: _imphand.c $(I)emx/syscalls.h $(I)io.h $(FCNTL) $(ERRNO) \
+		$(S)ioctl.h $(I)emx/io.h
+_isterm.o: _isterm.c $(I)io.h $(I)emx/syscalls.h
+_mfopen.o: _mfopen.c $(I)stdio.h $(I)stdlib.h $(ERRNO) $(I)emx/io.h
+_seekhdr.o: _seekhdr.c $(I)io.h $(I)memory.h $(ERRNO)
+_tempnam.o: _tempnam.c $(I)stdio.h $(I)emx/syscalls.h $(I)stdlib.h $(ERRNO) \
+		$(I)io.h $(I)string.h $(I)sys/param.h $(I)emx/io.h _tmp.h
+_vsopen.o: _vsopen.c $(I)emx/syscalls.h $(I)io.h $(I)stdarg.h $(ERRNO) \
+		$(FCNTL) $(I)sys/types.h $(I)sys/stat.h $(I)emx/io.h
+
+access.o: access.c $(I)emx/syscalls.h $(I)string.h $(I)io.h $(ERRNO) \
+		$(I)emx/io.h
+chmod.o: chmod.c $(I)io.h $(I)sys/types.h $(I)sys/stat.h $(I)emx/syscalls.h \
+		$(ERRNO)
+chsize.o: chsize.c $(I)io.h $(I)emx/syscalls.h $(ERRNO) $(I)string.h \
+		$(I)emx/io.h
+close.o: close.c $(I)emx/syscalls.h $(I)io.h $(ERRNO) $(I)emx/io.h
+creat.o: creat.c $(I)io.h $(FCNTL)
+dup.o: dup.c $(I)io.h $(I)emx/syscalls.h $(ERRNO) $(I)emx/io.h
+dup2.o: dup2.c $(I)io.h $(I)emx/syscalls.h $(ERRNO) $(I)emx/io.h
+eof.o: eof.c $(I)io.h $(ERRNO) $(I)emx/io.h
+fassign.o: fassign.c $(I)stdio.h $(ERRNO) $(I)emx/io.h $(RMUTEX)
+fcloseal.o: fcloseal.c $(I)stdio.h $(I)emx/io.h
+fcntl.o: fcntl.c $(I)emx/syscalls.h $(I)unistd.h $(I)io.h $(FCNTL) $(ERRNO) \
+		$(S)ioctl.h $(I)limits.h $(I)emx/io.h $(I)stdarg.h
+fdopen.o: fdopen.c $(I)stdio.h $(FCNTL) $(ERRNO) $(I)io.h $(I)emx/io.h
+fgetchar.o: fgetchar.c $(I)stdio.h
+fileleng.o: fileleng.c $(I)io.h $(I)emx/syscalls.h
+flock.o: flock.c $(I)sys/file.h $(S)fcntl.h $(ERRNO) $(I)emx/io.h
+flushall.o: flushall.c $(I)stdio.h $(I)emx/io.h $(RMUTEX)
+fputchar.o: fputchar.c $(I)stdio.h
+fstat.o: fstat.c $(I)io.h $(I)emx/syscalls.h $(I)sys/types.h $(I)sys/stat.h \
+		$(I)time.h $(I)emx/time.h $(I)emx/io.h
+fsync.o: fsync.c $(I)io.h $(I)emx/syscalls.h
+ftruncat.o: ftruncat.c $(I)io.h $(I)emx/syscalls.h $(ERRNO) $(I)emx/io.h
+getw.o: getw.c $(I)stdio.h
+ioctl.o: ioctl.c $(I)emx/syscalls.h $(I)io.h $(I)stdlib.h $(I)sys/termio.h \
+		$(I)sys/ioctl.h $(ERRNO) $(I)stdarg.h $(I)emx/io.h
+isatty.o: isatty.c $(I)emx/syscalls.h $(I)io.h $(ERRNO)
+lseek.o: lseek.c $(I)emx/syscalls.h $(I)io.h $(ERRNO) $(I)emx/io.h
+mkstemp.o: mkstemp.c $(I)io.h $(I)string.h $(PROCESS) $(ERRNO) $(FCNTL)
+mktemp.o: mktemp.c $(I)io.h $(I)string.h $(PROCESS) $(ERRNO)
+open.o: open.c $(I)io.h $(I)stdarg.h $(I)share.h $(I)emx/io.h
+pclose.o: pclose.c $(I)io.h $(PROCESS) $(ERRNO) $(I)emx/io.h
+pipe.o: pipe.c $(I)io.h $(ERRNO) $(FCNTL) $(I)emx/syscalls.h $(I)emx/io.h
+popen.o: popen.c $(I)emx/syscalls.h $(I)stdio.h $(I)stdlib.h $(I)string.h \
+		$(PROCESS) $(I)io.h $(I)unistd.h $(FCNTL) $(ERRNO)
+putw.o: putw.c $(I)stdio.h
+read.o: read.c $(I)emx/syscalls.h $(I)io.h $(ERRNO) $(I)string.h $(FCNTL) \
+		$(I)emx/io.h $(BUILTIN)
+readv.o: readv.c $(I)stdlib.h $(I)string.h $(I)unistd.h $(I)io.h $(ERRNO) \
+		$(I)sys/types.h $(I)sys/uio.h
+select.o: select.c $(I)io.h $(I)sys/types.h $(I)sys/time.h $(I)emx/syscalls.h \
+		$(I)stdlib.h $(I)memory.h $(I)emx/io.h
+setbuffe.o: setbuffe.c $(I)stdio.h
+setmode.o: setmode.c $(I)io.h $(FCNTL) $(ERRNO) $(I)emx/io.h
+snprintf.o: snprintf.c $(I)stdio.h $(I)stdarg.h $(I)limits.h $(I)emx/io.h
+sopen.o: sopen.c $(I)io.h $(I)stdarg.h $(I)emx/io.h
+stat.o: stat.c $(I)io.h $(I)sys/types.h $(I)sys/stat.h $(I)time.h \
+               $(I)stdlib.h $(ERRNO) $(I)string.h $(I)emx/time.h
+tell.o: tell.c $(I)io.h $(I)emx/syscalls.h $(ERRNO) $(I)emx/io.h
+truncate.o: truncate.c $(I)io.h $(FCNTL)
+ttyname.o: ttyname.c $(I)unistd.h $(I)emx/syscalls.h $(I)emx/thread.h
+umask.o: umask.c $(I)emx/syscalls.h $(I)stdlib.h
+unlink.o: unlink.c $(I)io.h $(I)emx/syscalls.h
+utime.o: utime.c $(I)time.h $(I)sys/time.h $(I)sys/utime.h $(I)emx/syscalls.h \
+		$(I)emx/time.h
+utimes.o: utimes.c $(I)time.h $(I)sys/time.h $(I)emx/syscalls.h $(I)emx/time.h
+vsnprint.o: vsnprint.c $(I)stdio.h $(I)limits.h $(I)emx/io.h
+write.o: write.c $(I)emx/syscalls.h $(I)io.h $(ERRNO) $(I)string.h $(FCNTL) \
+		$(SIGNAL) $(I)emx/io.h
+writev.o: writev.c $(I)stdlib.h $(I)string.h $(I)unistd.h $(I)io.h $(ERRNO) \
+		$(I)sys/types.h $(I)sys/uio.h
+
+
+ead.o: ead.c $(I)sys/ead.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+eadadd.o: eadadd.c $(I)sys/ead.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+eadcopy.o: eadcopy.c $(I)sys/ead.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+eadfea.o: eadfea.c $(I)sys/ead.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+eadread.o: eadread.c $(I)sys/ead.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+eadsort.o: eadsort.c $(I)sys/ead.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+eadwrite.o: eadwrite.c $(I)sys/ead.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+eaerrno.o: eaerrno.c $(ERRNO) $(I)os2.h $(I)stdlib.h ea.h
+eafree.o: eafree.c $(I)sys/ea.h $(I)stdlib.h
+eaget.o: eaget.c $(I)sys/ea.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+eaput.o: eaput.c $(I)sys/ea.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+    $(I)io.h ea.h
+earemove.o: earemove.c $(I)sys/ea.h $(I)stdlib.h
+eawrite.o: eawrite.c ea.h $(I)stdlib.h
+
+
+$(DSTLIB): _crlf.o _fbuf.o _fd.o _fdinit.o _fill.o _flush.o _flushst.o \
+    _fopen.o _fseekhd.o _fsetmod.o _fsopen.o _imphand.o _input.o _isterm.o \
+    _mfopen.o _newstre.o _output.o _rmtmp.o _seekhdr.o _str_rd.o _str_wr.o \
+    _tempnam.o _tmp.o _tmpbuf.o _tmpidxn.o _trslash.o _vsopen.o \
+    access.o chmod.o chsize.o close.o creat.o clearerr.o dup.o dup2.o ead.o \
+    eadadd.o eadcopy.o eadfea.o eadread.o eadsort.o eadwrite.o eaerrno.o \
+    eafree.o eaget.o eaput.o earemove.o eawrite.o eof.o fassign.o fclose.o \
+    fcloseal.o fcntl.o fdopen.o feof.o ferror.o fflush.o fgetc.o fgetchar.o \
+    fgetpos.o fgets.o fileleng.o fileno.o flock.o flushall.o fopen.o \
+    fprintf.o fputc.o fputchar.o fputs.o fread.o freopen.o fscanf.o fseek.o \
+    fsetpos.o fstat.o fsync.o ftell.o ftruncat.o fwrite.o getc.o getchar.o \
+    gets.o getw.o ioctl.o isatty.o lseek.o mkstemp.o mktemp.o open.o pclose.o \
+    pipe.o popen.o printf.o putc.o putchar.o puts.o putw.o \
+    read.o readv.o remove.o rename.o rewind.o scanf.o select.o setbuf.o \
+    setbuffe.o setmode.o setvbuf.o snprintf.o sopen.o sprintf.o sscanf.o \
+    stat.o tell.o tmpfile.o tmpnam.o truncate.o ttyname.o umask.o ungetc.o \
+    unlink.o utime.o utimes.o vfprintf.o vfscanf.o vprintf.o vscanf.o \
+    vsnprint.o vsprintf.o vsscanf.o write.o writev.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/io/mkstemp.c
===================================================================
--- trunk/src/emx/src/lib/io/mkstemp.c	(revision 18)
+++ trunk/src/emx/src/lib/io/mkstemp.c	(revision 18)
@@ -0,0 +1,36 @@
+/* mkstemp.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <process.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+
+int _mkstemp (char *string)
+{
+  int fd, pid, n;
+  char *s;
+
+  pid = _getpid ();
+  s = strchr (string, 0);
+  n = 0;
+  while (s != string && s[-1] == 'X')
+    {
+      --s; ++n;
+      *s = (char)(pid % 10) + '0';
+      pid /= 10;
+    }
+  if (n < 2)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  *s = 'a';
+  for (;;)
+    {
+      fd = _open (string, O_RDWR | O_CREAT | O_EXCL, 0600);
+      if (fd >= 0 || errno != EEXIST || *s == 'z')
+        return fd;
+      ++*s;
+    }
+}
Index: trunk/src/emx/src/lib/io/mktemp.c
===================================================================
--- trunk/src/emx/src/lib/io/mktemp.c	(revision 18)
+++ trunk/src/emx/src/lib/io/mktemp.c	(revision 18)
@@ -0,0 +1,40 @@
+/* mktemp.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <process.h>
+#include <io.h>
+#include <errno.h>
+
+char *_mktemp (char *string)
+{
+  int pid, n, saved_errno;
+  char *s;
+
+  pid = _getpid ();
+  s = strchr (string, 0);
+  n = 0;
+  while (s != string && s[-1] == 'X')
+    {
+      --s; ++n;
+      *s = (char)(pid % 10) + '0';
+      pid /= 10;
+    }
+  if (n < 2)
+    return NULL;
+  *s = 'a'; saved_errno = errno;
+  for (;;)
+    {
+      errno = 0;
+      if (_access (string, 0) != 0 && errno == ENOENT)
+        {
+          errno = saved_errno;
+          return string;
+        }
+      if (*s == 'z')
+        {
+          errno = saved_errno;
+          return NULL;
+        }
+      ++*s;
+    }
+}
Index: trunk/src/emx/src/lib/io/open.c
===================================================================
--- trunk/src/emx/src/lib/io/open.c	(revision 18)
+++ trunk/src/emx/src/lib/io/open.c	(revision 18)
@@ -0,0 +1,17 @@
+/* open.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdarg.h>
+#include <io.h>
+#include <share.h>
+#include <emx/io.h>
+
+int _open (const char *name, int oflag, ...)
+{
+  va_list va;
+  int h;
+
+  va_start (va, oflag);
+  h = _vsopen (name, oflag, SH_DENYNO, va);
+  va_end (va);
+  return h;
+}
Index: trunk/src/emx/src/lib/io/pclose.c
===================================================================
--- trunk/src/emx/src/lib/io/pclose.c	(revision 18)
+++ trunk/src/emx/src/lib/io/pclose.c	(revision 18)
@@ -0,0 +1,25 @@
+/* pclose.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <process.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _pclose (FILE *stream)
+{
+  int rc, write_mode;
+
+  if (!(stream->_flags & _IOOPEN))
+    {
+      errno = EBADF;
+      return -1;
+    }
+  write_mode = (stream->_flags & _IOWRT);
+  if (write_mode && fclose (stream) != 0)
+    return -1;
+  if (_waitpid (stream->_pid, &rc, 0) == -1)
+    return -1;
+  if (!write_mode && fclose (stream) != 0 && errno != EBADF)
+    return -1;
+  return rc;
+}
Index: trunk/src/emx/src/lib/io/pipe.c
===================================================================
--- trunk/src/emx/src/lib/io/pipe.c	(revision 18)
+++ trunk/src/emx/src/lib/io/pipe.c	(revision 18)
@@ -0,0 +1,38 @@
+/* pipe.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _fmode_bin;
+int _pipe_size;
+
+int _pipe (int *two_handles)
+{
+  int *pflags1, *pflags2;
+
+  if (__pipe (two_handles, (_pipe_size != 0 ? _pipe_size : 8192)) != 0)
+    return -1;
+  pflags1 = _fd_init (two_handles[0]);
+  if (pflags1 == NULL)
+    pflags2 = NULL;
+  else
+    pflags2 = _fd_init (two_handles[1]);
+  if (pflags2 == NULL)
+    {
+      __close (two_handles[0]);
+      __close (two_handles[1]);
+      errno = EMFILE;
+      return -1;
+    }
+  *pflags1 = O_RDONLY | F_PIPE;
+  *pflags2 = O_WRONLY | F_PIPE;
+  if (_fmode_bin == 0)
+    {
+      *pflags1 |= O_TEXT;
+      *pflags2 |= O_TEXT;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/popen.c
===================================================================
--- trunk/src/emx/src/lib/io/popen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/popen.c	(revision 18)
@@ -0,0 +1,113 @@
+/* popen.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <unistd.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static void restore (int org_handle, int org_private, int handle)
+{
+  int saved_errno;
+
+  saved_errno = errno;
+  _dup2 (org_handle, handle);
+  _close (org_handle);
+  _fcntl (handle, F_SETFD, org_private);
+  errno = saved_errno;
+}
+
+static FILE *make_pipe (int pipe_local, int pipe_remote, int handle,
+                        const char *command, const char *mode)
+{
+  int i, org_handle, org_private;
+  FILE *f;
+  const char *sh, *base, *opt;
+
+  _fcntl (pipe_local, F_SETFD, 1);
+  org_private = _fcntl (handle, F_GETFD, 0);
+  if (org_private == -1)
+    return NULL;
+  org_handle = _dup (handle);
+  if (org_handle == -1)
+    return NULL;
+  _fcntl (org_handle, F_SETFD, 1);
+  i = _dup2 (pipe_remote, handle);
+  if (i != handle)
+    {
+      restore (org_handle, org_private, handle);
+      errno = EBADF;
+      return NULL;
+    }
+  if (_close (pipe_remote) == -1)
+    {
+      restore (org_handle, org_private, handle);
+      return NULL;
+    }
+  f = _fdopen (pipe_local, mode);
+  if (f == NULL)
+    {
+      restore (org_handle, org_private, handle);
+      return NULL;
+    }
+  sh = getenv ("EMXSHELL");
+  if (sh == NULL)
+    sh = getenv ("COMSPEC");
+  if (sh == NULL)
+    {
+      fclose (f);
+      restore (org_handle, org_private, handle);
+      errno = ENOENT;
+      return NULL;
+    }
+  base = _getname (sh);
+  if (_stricmp (base, "cmd.exe") == 0 || _stricmp (base, "4os2.exe") == 0)
+    opt = "/c";
+  else
+    opt = "-c";
+  i = _spawnlp (P_NOWAIT, sh, sh, opt, command, (char *)0);
+  if (i == -1)
+    {
+      fclose (f);
+      f = NULL;
+    }
+  else
+    f->_pid = i;
+  restore (org_handle, org_private, handle);
+  return f;
+}
+
+
+FILE *_popen (const char *command, const char *mode)
+{
+  int ph[2];
+  FILE *stream;
+  int saved_errno;
+
+  if (mode[0] != 'r' && mode[0] != 'w')
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  if (_pipe (ph) == -1)
+    return NULL;
+  if (_fcntl (ph[0], F_SETFD, 1) == -1)
+    return NULL;
+  if (_fcntl (ph[1], F_SETFD, 1) == -1)
+    return NULL;
+  if (mode[0] == 'r')
+    stream = make_pipe (ph[0], ph[1], STDOUT_FILENO, command, mode);
+  else
+    stream = make_pipe (ph[1], ph[0], STDIN_FILENO, command, mode);
+  if (stream == NULL)
+    {
+      saved_errno = errno;
+      _close (ph[0]);
+      _close (ph[1]);
+      errno = saved_errno;
+    }
+  return stream;
+}
Index: trunk/src/emx/src/lib/io/printf.c
===================================================================
--- trunk/src/emx/src/lib/io/printf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/printf.c	(revision 18)
@@ -0,0 +1,28 @@
+/* printf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <emx/io.h>
+
+int printf (const char *format, ...)
+{
+  va_list arg_ptr;
+  int result;
+  void *tb;
+
+  va_start (arg_ptr, format);
+  STREAM_LOCK (stdout);
+  if (nbuf (stdout))
+    _fbuf (stdout);
+  _tmpbuf (stdout, tb);
+  result = _output (stdout, format, arg_ptr);
+  if (_endbuf (stdout) != 0)
+    result = -1;
+  STREAM_UNLOCK (stdout);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/putc.c
===================================================================
--- trunk/src/emx/src/lib/io/putc.c	(revision 18)
+++ trunk/src/emx/src/lib/io/putc.c	(revision 18)
@@ -0,0 +1,10 @@
+/* putc.c (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int _putc_inline (int c, FILE *s)
+{
+  return (--s->_wcount >= 0 && (c != '\n' || !(s->_flags & _IOLBF))
+          ? (unsigned char)(*s->_ptr++ = (char)c)
+          : _flush (c, s));
+}
Index: trunk/src/emx/src/lib/io/putchar.c
===================================================================
--- trunk/src/emx/src/lib/io/putchar.c	(revision 18)
+++ trunk/src/emx/src/lib/io/putchar.c	(revision 18)
@@ -0,0 +1,8 @@
+/* putchar.c (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int putchar (int c)
+{
+  return putc (c, stdout);
+}
Index: trunk/src/emx/src/lib/io/puts.c
===================================================================
--- trunk/src/emx/src/lib/io/puts.c	(revision 18)
+++ trunk/src/emx/src/lib/io/puts.c	(revision 18)
@@ -0,0 +1,29 @@
+/* puts.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <emx/io.h>
+
+int puts (const char *string)
+{
+  int result, len;
+  void *tb;
+
+  len = strlen (string);
+  STREAM_LOCK (stdout);
+  if (nbuf (stdout))
+    _fbuf (stdout);
+  _tmpbuf (stdout, tb);
+  if (len == 0 || _fwrite_nolock (string, len, 1, stdout) == 1)
+    result = _putc_inline ('\n', stdout);
+  else
+    result = EOF;
+  if (_endbuf (stdout) != 0)
+    result = EOF;
+  STREAM_UNLOCK (stdout);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/putw.c
===================================================================
--- trunk/src/emx/src/lib/io/putw.c	(revision 18)
+++ trunk/src/emx/src/lib/io/putw.c	(revision 18)
@@ -0,0 +1,8 @@
+/* putw.c (emx+gcc) -- Copyright (c) 1992-1995 by Kai Uwe Rommel */
+
+#include <stdio.h>
+
+int _putw (int x, FILE *stream)
+{
+  return (fwrite (&x, sizeof (x), 1, stream) == 1 ? x : EOF);
+}
Index: trunk/src/emx/src/lib/io/read.c
===================================================================
--- trunk/src/emx/src/lib/io/read.c	(revision 18)
+++ trunk/src/emx/src/lib/io/read.c	(revision 18)
@@ -0,0 +1,114 @@
+/* read.c (emx+gcc) -- Copyright (c) 1990-1999 by Eberhard Mattes */
+
+#include <string.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/builtin.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+/* Read NBYTE characters, use lookahead, if available. This is simple
+   unless O_NDELAY is in effect. */
+
+static int read_lookahead (int handle, void *buf, size_t nbyte, int *pla)
+{
+  int i, n, la, saved_errno;
+  char *dst;
+
+  i = 0; dst = buf; saved_errno = errno;
+  if (nbyte > 0 && (la = __lxchg (pla, -1)) != -1)
+    {
+      *dst = (char)la;
+      ++i; --nbyte;
+    }
+  n = __read (handle, dst+i, nbyte);
+  if (n == -1)
+    {
+      if (errno == EAGAIN && i > 0)           /* lookahead and O_NDELAY */
+        {
+          errno = saved_errno;                /* hide EAGAIN */
+          return i;                           /* and be successful */
+        }
+      return -1;
+    }
+  return i + n;
+}
+
+
+int _read (int handle, void *buf, size_t nbyte)
+{
+  int n, *pflags, *pla;
+  size_t j, k;
+  char *dst, c;
+
+  if ((pflags = _fd_flags (handle)) == NULL
+      || (pla = _fd_lookahead (handle)) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  *pflags &= ~F_CRLF;           /* No CR/LF pair translated to newline */
+  if (nbyte > 0 && (*pflags & F_EOF))
+    return 0;
+  dst = buf;
+  n = read_lookahead (handle, dst, nbyte, pla);
+  if (n == -1)
+    return -1;
+  if ((*pflags & O_TEXT) && !(*pflags & F_TERMIO) && n > 0)
+    {
+      /* special processing for text mode */
+      if (!(*pflags & (F_PIPE|F_SOCKET|F_DEV)) && dst[n-1] == 0x1a &&
+          _eof (handle))
+        {
+          /* remove last Ctrl-Z in text files */
+          --n;
+          *pflags |= F_EOF;
+          if (n == 0)
+            return 0;
+        }
+      if (n == 1 && dst[0] == '\r')
+        {
+          /* This is the tricky case as we are not allowed to
+             decrement n by one as 0 indicates end of file. We have to
+             use look ahead. */
+
+          int saved_errno = errno;
+          j = read_lookahead (handle, &c, 1, pla); /* look ahead */
+          if (j == -1 && errno == EAGAIN)
+            {
+              *pla = '\r';
+              return -1;
+            }
+          errno = saved_errno;                /* hide error */
+          if (j == 1 && c == '\n')            /* CR/LF ? */
+            {
+              dst[0] = '\n';                  /* yes -> replace with LF */
+              *pflags |= F_CRLF;
+            }
+          else
+            *pla = (unsigned char)c;          /* no -> save the 2nd char */
+        }
+      else
+        {
+          /* Translate each CR/LF pair to a newline character.  Set
+             F_CRLF if at lest one such translation has been
+             performed.  Set the file's look-ahead to CR if the buffer
+             ends with CR. */
+
+          if (_crlf (dst, n, &k))
+            {
+              /* Buffer ends with CR: Set look ahead and adjust `n'
+                 for F_CRLF logic. */
+
+              *pla = '\r';
+              --n;
+            }
+          if (k != n)
+            *pflags |= F_CRLF;
+          n = k;
+        }
+    }
+  return n;
+}
Index: trunk/src/emx/src/lib/io/readv.c
===================================================================
--- trunk/src/emx/src/lib/io/readv.c	(revision 18)
+++ trunk/src/emx/src/lib/io/readv.c	(revision 18)
@@ -0,0 +1,60 @@
+/* readv.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+int _readv (int handle, const struct iovec *iov, int iovcnt)
+{
+  int i, n;
+  size_t total, len;
+  char *buf, *mp, *p;
+
+  if (iovcnt <= 0 || iovcnt > 16)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  total = 0;
+  for (i = 0; i < iovcnt; ++i)
+    {
+      if (iov[i].iov_len < 0)
+        {
+          errno = EINVAL;
+          return -1;
+        }
+      total += iov[i].iov_len;
+    }
+
+  mp = NULL;
+  if (total <= 0x100000)
+    buf = alloca (total);
+  else
+    buf = mp = malloc (total);
+  if (buf == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  n = _read (handle, buf, total);
+  if (n > 0)
+    {
+      total = (size_t)n; n = 0; p = buf;
+      for (i = 0; total > 0 && i < iovcnt; ++i)
+        {
+          len = (size_t)iov[i].iov_len;
+          if (len > total) len = total;
+          memcpy (iov[i].iov_base, p, len);
+          p += len; total -= len; n += len;
+        }
+    }
+  if (mp != NULL)
+    free (mp);
+  return n;
+}
Index: trunk/src/emx/src/lib/io/remove.c
===================================================================
--- trunk/src/emx/src/lib/io/remove.c	(revision 18)
+++ trunk/src/emx/src/lib/io/remove.c	(revision 18)
@@ -0,0 +1,10 @@
+/* remove.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+int remove (const char *name)
+{
+  return __remove (name);
+}
Index: trunk/src/emx/src/lib/io/rename.c
===================================================================
--- trunk/src/emx/src/lib/io/rename.c	(revision 18)
+++ trunk/src/emx/src/lib/io/rename.c	(revision 18)
@@ -0,0 +1,10 @@
+/* rename.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+int rename (const char *old_name, const char *new_name)
+{
+  return __rename (old_name, new_name);
+}
Index: trunk/src/emx/src/lib/io/rewind.c
===================================================================
--- trunk/src/emx/src/lib/io/rewind.c	(revision 18)
+++ trunk/src/emx/src/lib/io/rewind.c	(revision 18)
@@ -0,0 +1,17 @@
+/* rewind.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+void rewind (FILE *stream)
+{
+  STREAM_LOCK (stream);
+  _fflush_nolock (stream);
+  _fseek_nolock (stream, 0L, SEEK_SET);
+  stream->_flags &= ~_IOERR;
+  STREAM_UNLOCK (stream);
+}
Index: trunk/src/emx/src/lib/io/scanf.c
===================================================================
--- trunk/src/emx/src/lib/io/scanf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/scanf.c	(revision 18)
@@ -0,0 +1,22 @@
+/* scanf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <emx/io.h>
+
+int scanf (const char *format, ...)
+{
+  va_list arg_ptr;
+  int result;
+
+  va_start (arg_ptr, format);
+  STREAM_LOCK (stdin);
+  result = _input (stdin, format, arg_ptr);
+  STREAM_UNLOCK (stdin);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/select.c
===================================================================
--- trunk/src/emx/src/lib/io/select.c	(revision 18)
+++ trunk/src/emx/src/lib/io/select.c	(revision 18)
@@ -0,0 +1,72 @@
+/* select.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <memory.h>
+#include <io.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+int _select (int nfds, fd_set *readfds, fd_set *writefds,
+             fd_set *exceptfds, struct timeval *timeout)
+{
+  struct _select args;
+
+  args.nfds = nfds;
+  args.readfds = readfds;
+  args.writefds = writefds;
+  args.exceptfds = exceptfds;
+  args.timeout = timeout;
+  if (readfds != NULL)
+    {
+      fd_set *tmp;
+      struct timeval tv;
+      int i, j, k, n, nb, nw, rc;
+      struct fdvec *pv;
+
+      nw = (nfds + 31) / 32;
+      if (nw < 256 / 32)
+        nw = 256 / 32;
+      nb = nw * 4;
+      tmp = alloca (nb);
+      memset (tmp, 0, nb);
+      j = 0; n = 0; pv = &_fdvec_head;
+      while (n < nfds && pv != NULL)
+        {
+          k = nfds - n;
+          if (pv->n < k) k = pv->n;
+          for (i = 0; i < k; ++i, ++n)
+            if (pv->lookahead[i] >= 0 && FD_ISSET (n, readfds))
+              {
+                FD_SET (n, tmp); /* handles ready due to look ahead */
+                ++j;
+              }
+          pv = pv->next;
+        }
+      if (j != 0)                /* there are handles with active look ahead */
+        {
+          tv.tv_sec = 0; tv.tv_usec = 0;      /* immediately return */
+          args.timeout = &tv;
+          rc = __select (&args);
+          if (rc == 0)          /* no handles ready -> use look ahead */
+            {
+              memcpy (readfds, tmp, nb);
+              rc = j;
+            }
+          else if (rc > 0)      /* merge */
+            for (i = 0; i < n; ++i)
+              if (FD_ISSET (i, tmp) && !FD_ISSET (i, readfds))
+                {
+                  FD_SET (i, readfds);
+                  if (!((writefds != NULL && FD_ISSET (i, writefds))
+                        || (exceptfds != NULL && FD_ISSET (i, exceptfds))))
+                    ++rc;
+                }
+          return rc;
+        }
+    }
+  return __select (&args);
+}
Index: trunk/src/emx/src/lib/io/setbuf.c
===================================================================
--- trunk/src/emx/src/lib/io/setbuf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/setbuf.c	(revision 18)
@@ -0,0 +1,8 @@
+/* setbuf.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int setbuf (FILE *stream, char *buffer)
+{
+  return setvbuf (stream, buffer, (buffer != NULL ? _IOFBF : _IONBF), BUFSIZ);
+}
Index: trunk/src/emx/src/lib/io/setbuffe.c
===================================================================
--- trunk/src/emx/src/lib/io/setbuffe.c	(revision 18)
+++ trunk/src/emx/src/lib/io/setbuffe.c	(revision 18)
@@ -0,0 +1,8 @@
+/* setbuffe.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+
+int _setbuffer (FILE *stream, char *buffer, size_t size)
+{
+  return setvbuf (stream, buffer, (buffer != NULL ? _IOFBF : _IONBF), size);
+}
Index: trunk/src/emx/src/lib/io/setmode.c
===================================================================
--- trunk/src/emx/src/lib/io/setmode.c	(revision 18)
+++ trunk/src/emx/src/lib/io/setmode.c	(revision 18)
@@ -0,0 +1,28 @@
+/* setmode.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+
+int _setmode (int handle, int mode)
+{
+  int old_mode, *pflags;
+
+  if ((pflags = _fd_flags (handle)) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  old_mode = ((*pflags & O_TEXT) ? O_TEXT : O_BINARY);
+  if (mode == O_BINARY)
+    *pflags &= ~O_TEXT;
+  else if (mode == O_TEXT)
+    *pflags |= O_TEXT;
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return old_mode;
+}
Index: trunk/src/emx/src/lib/io/setvbuf.c
===================================================================
--- trunk/src/emx/src/lib/io/setvbuf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/setvbuf.c	(revision 18)
@@ -0,0 +1,63 @@
+/* setvbuf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+int setvbuf (FILE *stream, char *buffer, int mode, size_t size)
+{
+  if (!(stream->_flags & _IOOPEN)
+      || (mode != _IONBF && mode != _IOFBF && mode != _IOLBF))
+    return EOF;
+
+  STREAM_LOCK (stream);
+  _fflush_nolock (stream);
+  if ((stream->_flags & _IOBUFMASK) == _IOBUFLIB)
+    free (stream->_buffer);
+  stream->_flags &= ~(_IOBUFMASK|_IOLBF|_IOFBF|_IONBF);
+
+  if (mode == _IONBF)
+    {
+      stream->_buf_size = 1;
+      stream->_buffer = &stream->_char_buf;
+      stream->_flags |= _IONBF|_IOBUFCHAR;
+    }
+  else if (buffer != NULL && size >= 1 && size <= 0x400000)
+    {
+      /* ANSI X3.159-1989, 4.9.5.6: "If buf is not a null pointer, the
+         array it points to may be used instead of a buffer allocated
+         by the setvbuf function."
+
+         We use that array unless SIZE is invalid. */
+
+      stream->_buf_size = size;
+      stream->_buffer = buffer;
+      stream->_flags |= mode|_IOBUFUSER;
+    }
+  else
+    {
+      /* ANSI X3.159-1989 doesn't assign any meaning to SIZE in this
+         case.  We use SIZE as size of the buffer to allocate; if SIZE
+         is invalid, use BUFSIZ instead. */
+
+      if (size < 1 || size > 0x400000)
+        size = BUFSIZ;
+      buffer = malloc (size);
+      if (buffer == NULL)
+        {
+          STREAM_UNLOCK (stream);
+          return EOF;
+        }
+      stream->_buf_size = size;
+      stream->_buffer = buffer;
+      stream->_flags |= mode|_IOBUFLIB;
+    }
+  stream->_ptr = stream->_buffer;
+  stream->_rcount = 0;
+  stream->_wcount = 0;
+  STREAM_UNLOCK (stream);
+  return 0;
+}
Index: trunk/src/emx/src/lib/io/snprintf.c
===================================================================
--- trunk/src/emx/src/lib/io/snprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/snprintf.c	(revision 18)
@@ -0,0 +1,33 @@
+/* snprintf.c (emx+gcc) -- Copyright (c) 1995-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <emx/io.h>
+
+int _snprintf (char *buffer, size_t n, const char *format, ...)
+{
+  va_list arg_ptr;
+  FILE trick;
+  struct _file2 trick2;
+  int result;
+
+  if (n > INT_MAX)
+    return EOF;
+  va_start (arg_ptr, format);
+  trick._buffer = buffer;
+  trick._ptr = buffer;
+  trick._rcount = 0;
+  trick._wcount = n != 0 ? (int)n - 1 : 0;
+  trick._handle = -1;
+  trick._flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOWRT;
+  trick._buf_size = (int)n;
+  trick._flush = NULL;
+  trick._ungetc_count = 0;
+  _setdummymore (&trick, &trick2);
+  result = _output (&trick, format, arg_ptr);
+  if (n != 0)
+    *trick._ptr = 0;
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/sopen.c
===================================================================
--- trunk/src/emx/src/lib/io/sopen.c	(revision 18)
+++ trunk/src/emx/src/lib/io/sopen.c	(revision 18)
@@ -0,0 +1,16 @@
+/* sopen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdarg.h>
+#include <io.h>
+#include <emx/io.h>
+
+int _sopen (const char *name, int oflag, int shflag, ...)
+{
+  va_list va;
+  int h;
+
+  va_start (va, shflag);
+  h = _vsopen (name, oflag, shflag, va);
+  va_end (va);
+  return h;
+}
Index: trunk/src/emx/src/lib/io/sprintf.c
===================================================================
--- trunk/src/emx/src/lib/io/sprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/sprintf.c	(revision 18)
@@ -0,0 +1,30 @@
+/* sprintf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <emx/io.h>
+
+int sprintf (char *buffer, const char *format, ...)
+{
+  va_list arg_ptr;
+  FILE trick;
+  struct _file2 trick2;
+  int result;
+
+  va_start (arg_ptr, format);
+  trick._buffer = buffer;
+  trick._ptr = buffer;
+  trick._rcount = 0;
+  trick._wcount = INT_MAX;
+  trick._handle = -1;
+  trick._flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOWRT;
+  trick._buf_size = INT_MAX;
+  trick._flush = NULL;
+  trick._ungetc_count = 0;
+  _setdummymore (&trick, &trick2);
+  result = _output (&trick, format, arg_ptr);
+  putc (0, &trick);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/sscanf.c
===================================================================
--- trunk/src/emx/src/lib/io/sscanf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/sscanf.c	(revision 18)
@@ -0,0 +1,29 @@
+/* sscanf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <emx/io.h>
+
+int sscanf (const char *buffer, const char *format, ...)
+{
+  va_list arg_ptr;
+  FILE trick;
+  struct _file2 trick2;
+  int result;
+
+  va_start (arg_ptr, format);
+  trick._buffer = (char *)buffer;               /* const -> non-const */
+  trick._ptr = (char *)buffer;                  /* const -> non-const */
+  trick._rcount = strlen (buffer);
+  trick._wcount = 0;
+  trick._handle = -1;
+  trick._flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOREAD;
+  trick._buf_size = INT_MAX;
+  trick._flush = NULL;
+  trick._ungetc_count = 0;
+  _setdummymore (&trick, &trick2);
+  result = _input (&trick, format, arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/stat.c
===================================================================
--- trunk/src/emx/src/lib/io/stat.c	(revision 18)
+++ trunk/src/emx/src/lib/io/stat.c	(revision 18)
@@ -0,0 +1,57 @@
+/* stat.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <emx/io.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+int _stat (const char *name, struct stat *buffer)
+{
+  int rc, slash;
+  size_t len;
+  char *tmp;
+
+  /* If there is a trailing slash or backslash, remove it and set
+     `slash' to true.  Make a local copy of the string to remove the
+     slash or backslash. */
+
+  len = strlen (name);
+  slash = _trslash (name, len, 1);
+  if (slash)
+    {
+      tmp = alloca (len);
+      memcpy (tmp, name, len - 1);
+      tmp[len-1] = 0;
+      name = tmp;
+    }
+  rc = __stat (name, buffer);
+  if (rc == 0)
+    {
+      if (slash && ((buffer->st_mode & S_IFMT) != S_IFDIR))
+        {
+          errno = ENOTDIR;
+          return -1;
+        }
+      if (!_tzset_flag) _tzset ();
+      _loc2gmt (&buffer->st_atime, -1);
+      _loc2gmt (&buffer->st_mtime, -1);
+      _loc2gmt (&buffer->st_ctime, -1);
+      if ((buffer->st_mode & S_IFMT) == S_IFREG)
+        {
+          tmp = _getext (name);
+          if (tmp != NULL &&
+              (_stricmp (tmp, ".exe") == 0 ||
+               _stricmp (tmp, ".com") == 0 ||
+               _stricmp (tmp, ".cmd") == 0 ||
+               _stricmp (tmp, ".bat") == 0))
+            buffer->st_mode |= (S_IEXEC >> 6) * 0111;
+        }
+    }
+  return rc;
+}
Index: trunk/src/emx/src/lib/io/tell.c
===================================================================
--- trunk/src/emx/src/lib/io/tell.c	(revision 18)
+++ trunk/src/emx/src/lib/io/tell.c	(revision 18)
@@ -0,0 +1,25 @@
+/* tell.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+long _tell (int handle)
+{
+  int *pflags, *pla;
+  long n;
+
+  if ((pflags = _fd_flags (handle)) == NULL
+      || (pla = _fd_lookahead (handle)) == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  n = (long)__lseek (handle, 0L, SEEK_CUR);
+  if (n == -1)
+    return n;
+  if (*pla >= 0 || (*pflags & F_EOF))
+    --n;
+  return n;
+}
Index: trunk/src/emx/src/lib/io/tmpfile.c
===================================================================
--- trunk/src/emx/src/lib/io/tmpfile.c	(revision 18)
+++ trunk/src/emx/src/lib/io/tmpfile.c	(revision 18)
@@ -0,0 +1,36 @@
+/* tmpfile.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+/*                        Copyright (c) 1991-1993 by Kolja Elsaesser */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <emx/io.h>
+#include "_tmp.h"
+
+
+FILE *tmpfile (void)
+{
+  char name[L_tmpnam];
+  int idx, fd;
+  FILE *f;
+
+  do
+    {
+      idx = _tmpidxnam (name);
+      if (idx == -1)
+        return NULL;
+      fd = _open (name, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0644);
+    } while (fd == -1 && errno == EEXIST);
+  if (fd == -1)
+    return NULL;
+  f = _fdopen (fd, "w+b");
+  if (f == NULL)
+    return NULL;
+  f->_tmpidx = idx;
+  f->_flags |= _IOTMP;
+  return f;
+}
Index: trunk/src/emx/src/lib/io/tmpnam.c
===================================================================
--- trunk/src/emx/src/lib/io/tmpnam.c	(revision 18)
+++ trunk/src/emx/src/lib/io/tmpnam.c	(revision 18)
@@ -0,0 +1,23 @@
+/* tmpnam.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+/*                       Copyright (c) 1991-1993 by Kolja Elsaesser */
+
+#include <stdio.h>
+#include <emx/thread.h>
+#include "_tmp.h"
+
+
+char *tmpnam (char *string)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#define tnbuf (tp->_th_tmpnam_buf)
+#else
+  static char tnbuf[L_tmpnam];
+#endif
+
+  if (string == NULL) string = tnbuf;
+  if (_tmpidxnam (string) >= 0)
+    return string;
+  else
+    return NULL;
+}
Index: trunk/src/emx/src/lib/io/truncate.c
===================================================================
--- trunk/src/emx/src/lib/io/truncate.c	(revision 18)
+++ trunk/src/emx/src/lib/io/truncate.c	(revision 18)
@@ -0,0 +1,16 @@
+/* truncate.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <io.h>
+#include <fcntl.h>
+
+int _truncate (char *name, long length)
+{
+  int handle, result;
+
+  handle = _open (name, O_RDWR);
+  if (handle == -1)
+    return -1;
+  result = _ftruncate (handle, length);
+  _close (handle);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/ttyname.c
===================================================================
--- trunk/src/emx/src/lib/io/ttyname.c	(revision 18)
+++ trunk/src/emx/src/lib/io/ttyname.c	(revision 18)
@@ -0,0 +1,20 @@
+/* ttyname.c (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <emx/syscalls.h>
+#include <emx/thread.h>
+
+char *_ttyname (int handle)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#define buf (tp->_th_ttyname)
+#else
+  static char buf[32];
+#endif
+
+  if (__ttyname (handle, buf, sizeof (buf)) == 0)
+    return buf;
+  else
+    return NULL;
+}
Index: trunk/src/emx/src/lib/io/umask.c
===================================================================
--- trunk/src/emx/src/lib/io/umask.c	(revision 18)
+++ trunk/src/emx/src/lib/io/umask.c	(revision 18)
@@ -0,0 +1,9 @@
+/* umask.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+int _umask (int pmode)
+{
+  return __umask (pmode);
+}
Index: trunk/src/emx/src/lib/io/ungetc.c
===================================================================
--- trunk/src/emx/src/lib/io/ungetc.c	(revision 18)
+++ trunk/src/emx/src/lib/io/ungetc.c	(revision 18)
@@ -0,0 +1,160 @@
+/* ungetc.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <emx/io.h>
+
+/* The implementation of ungetc() has been changed in emx 0.9a fix04
+   to fix bugs.  The new implementation adds the `_ungetc_count' field
+   to `struct _FILE'.  Unfortunately, the new implementation must
+   still work with the old getc().  Otherwise, old programs using the
+   new dynamic library, and old modules (compiled with the inline
+   getc() of the old stdio.h) linked with the new static library would
+   break.
+
+   As `_ungetc_count' must be adjusted for every evaluation of getc()
+   while there are pushed-back characters, getc() must call _fill() if
+   there are pushed-back characters.  Checking `_ungetc_count' is not
+   an option for the reasons given above.  The only way to make the
+   old getc() call _fill() is making `rcount' less than 1.
+
+   If we just set `rcount' to, say, 0, if there are pushed-back
+   characters, we have to refill the buffer after all pushed-back
+   characters have been read, as the original `rcount' is no longer
+   available (and we don't have space in the structure for saving the
+   old value).  That is, the buffer will be flushed after ungetc().
+   That's too inefficient.
+
+   Therefore, we encode the number of characters available for reading
+   in the stream buffer as negative number in the `rcount' field while
+   there are pushed-back characters.  We use the GET_RCOUNT macro to
+   retrieve the number of characters available for reading.
+
+   This design also works for executables built with the new stdio.h
+   and linked with the old library (this should happen only when
+   linking dynamically) as getc() has not been changed at all.
+
+   Programs which directly use `rcount' will break. */
+
+
+int _ungetc_nolock (int c, FILE *stream)
+{
+  if (!(stream->_flags & _IOOPEN) || c == EOF)
+    return EOF;
+  if ((stream->_flags & _IOSPECIAL) && stream->_flush == NULL)
+    {
+      /* ungetc() on a string is used only by sscanf(), and this does
+         an ungetc() of the recently read character, so we don't have
+         to write it to the (read-only!) string. */
+
+      --stream->_ptr;
+      ++stream->_rcount;
+      stream->_flags &= ~_IOEOF;
+      return (unsigned char)c;
+    }
+
+  /* Fail if the stream is in write mode. */
+
+  if (stream->_flags & _IOWRT)
+    {
+      stream->_flags |= _IOERR;
+      errno = EACCES;
+      return EOF;
+    }
+
+  /* Switch to read mode.  Note that _fbuf() zeros `rcount' and
+     `_ungetc_count'.  We call it now to simplify things. */
+
+  stream->_flags |= _IOREAD;
+  stream->_wcount = 0;
+  if (nbuf (stream))
+    _fbuf (stream);
+
+  /* Check `_ungetc_count' for overflow. */
+
+  if (stream->_ungetc_count == UCHAR_MAX)
+    return EOF;
+
+  /* Check for buffer overflow. */
+
+  if (stream->_ungetc_count >= stream->_buf_size)
+    return EOF;
+
+  /* Push back the character by overwriting a character in the stream
+     buffer before `ptr'.  There is always at least one character
+     available: The only case where `ptr' equals `buffer' and there is
+     data in the buffer is created fseek().  If fseek() has succeeded,
+     the underlying file must be a disk file, therefore we can safely
+     flush the buffer to make space.  This ensures one character of
+     pushback. */
+
+  if (stream->_rcount != 0
+      && stream->_ptr - stream->_buffer < stream->_ungetc_count + 1)
+    {
+      int ft, uc;
+
+      /* If there are not enough characters available before `ptr',
+         we'll flush the buffer to make space.  However, we must be
+         able to reread after undoing ungetc() to avoid data loss.
+         Therefore, fail now if we have to flush the buffer and there
+         is data in the buffer and the underlying file is not a disk
+         file.  (This can happen only if at least one character is
+         currently pushed back, see above.) */
+
+      if ((stream->_flags & _IOSPECIAL)
+          || _ioctl (stream->_handle, FGETHTYPE, &ft) < 0
+          || ft != HT_FILE)
+        return EOF;
+      
+      /* OK, we can flush the stream buffer.  We flush the buffer
+         completely and don't attempt to keep some data (that would be
+         difficult w.r.t. newlines in text mode).  Note that fflush()
+         does not modify the EOF indicator and the error indicator. */
+
+      uc = stream->_ungetc_count;
+      if (_fflush_nolock (stream) != 0)
+        return EOF;
+      stream->_ungetc_count = uc;
+    }
+
+  /* Now there is enough space available.  We insert the characters
+     beginning at the low end of the buffer to avoid various special
+     cases related to the value of `ptr'. */
+
+  stream->_buffer[stream->_ungetc_count] = (char)c;
+
+  /* Set a flag indicating that we have modified the buffer. */
+
+  stream->_flags |= _IOUNGETC;
+
+  /* Let `getc()' call _fill(), and save the value of `rcount'.
+     Increment the `_ungetc_count' field which contains the number of
+     characters pushed back. */
+
+  if (stream->_ungetc_count == 0)
+    stream->_rcount = -stream->_rcount;
+  stream->_ungetc_count += 1;
+
+  /* Clear any EOF condition. */
+
+  stream->_flags &= ~_IOEOF;
+
+  return (unsigned char)c;
+}
+
+
+int ungetc (int c, FILE *stream)
+{
+  int result;
+
+  STREAM_LOCK (stream);
+  result = _ungetc_nolock (c, stream);
+  STREAM_UNLOCK (stream);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/unlink.c
===================================================================
--- trunk/src/emx/src/lib/io/unlink.c	(revision 18)
+++ trunk/src/emx/src/lib/io/unlink.c	(revision 18)
@@ -0,0 +1,9 @@
+/* unlink.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <io.h>
+#include <emx/syscalls.h>
+
+int _unlink (const char *name)
+{
+  return __remove (name);       /* There are no links */
+}
Index: trunk/src/emx/src/lib/io/utime.c
===================================================================
--- trunk/src/emx/src/lib/io/utime.c	(revision 18)
+++ trunk/src/emx/src/lib/io/utime.c	(revision 18)
@@ -0,0 +1,30 @@
+/* utime.c (emx+gcc) -- Copyright (c) 1990-2000 by Eberhard Mattes */
+
+#include <time.h>
+#include <sys/time.h>
+#include <sys/utime.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+int _utime (const char *name, const struct utimbuf *times)
+{
+  struct timeval tv[2];
+  time_t tmp;
+
+  if (times == NULL)
+    {
+      tv[0].tv_sec = tv[1].tv_sec = time (NULL);
+      tv[0].tv_usec = tv[1].tv_usec = 0;
+    }
+  else
+    {
+      tv[0].tv_sec = times->actime;
+      tv[0].tv_usec = 0;
+      tv[1].tv_sec = times->modtime;
+      tv[1].tv_usec = 0;
+    }
+  if (!_tzset_flag) _tzset ();
+  tmp = tv[0].tv_sec; _gmt2loc (&tmp); tv[0].tv_sec = tmp;
+  tmp = tv[1].tv_sec; _gmt2loc (&tmp); tv[1].tv_sec = tmp;
+  return __utimes (name, tv);
+}
Index: trunk/src/emx/src/lib/io/utimes.c
===================================================================
--- trunk/src/emx/src/lib/io/utimes.c	(revision 18)
+++ trunk/src/emx/src/lib/io/utimes.c	(revision 18)
@@ -0,0 +1,27 @@
+/* utimes.c (emx+gcc) -- Copyright (c) 1990-2000 by Eberhard Mattes */
+
+#include <time.h>
+#include <sys/time.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+int _utimes (const char *name, const struct timeval *tvp)
+{
+  struct timeval tv[2];
+  time_t tmp;
+
+  if (tvp == NULL)
+    {
+      tv[0].tv_sec = tv[1].tv_sec = time (NULL);
+      tv[0].tv_usec = tv[1].tv_usec = 0;
+    }
+  else
+    {
+      tv[0] = tvp[0];
+      tv[1] = tvp[1];
+    }
+  if (!_tzset_flag) _tzset ();
+  tmp = tv[0].tv_sec; _gmt2loc (&tmp); tv[0].tv_sec = tmp;
+  tmp = tv[1].tv_sec; _gmt2loc (&tmp); tv[1].tv_sec = tmp;
+  return __utimes (name, tv);
+}
Index: trunk/src/emx/src/lib/io/vfprintf.c
===================================================================
--- trunk/src/emx/src/lib/io/vfprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/vfprintf.c	(revision 18)
@@ -0,0 +1,24 @@
+/* vfprintf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+int vfprintf (FILE *stream, const char *format, va_list arg_ptr)
+{
+  int result;
+  void *tb;
+
+  STREAM_LOCK (stream);
+  if (nbuf (stream))
+    _fbuf (stream);
+  _tmpbuf (stream, tb);
+  result = _output (stream, format, arg_ptr);
+  if (_endbuf (stream) != 0)
+    result = -1;
+  STREAM_UNLOCK (stream);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/vfscanf.c
===================================================================
--- trunk/src/emx/src/lib/io/vfscanf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/vfscanf.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vfscanf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <emx/io.h>
+
+int vfscanf (FILE *stream, const char *format, va_list arg_ptr)
+{
+  int r;
+
+  STREAM_LOCK (stream);
+  r = _input (stream, format, arg_ptr);
+  STREAM_UNLOCK (stream);
+  return r;
+}
Index: trunk/src/emx/src/lib/io/vprintf.c
===================================================================
--- trunk/src/emx/src/lib/io/vprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/vprintf.c	(revision 18)
@@ -0,0 +1,24 @@
+/* vprintf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <emx/io.h>
+
+int vprintf (const char *format, va_list arg_ptr)
+{
+  int result;
+  void *tb;
+
+  STREAM_LOCK (stdout);
+  if (nbuf (stdout))
+    _fbuf (stdout);
+  _tmpbuf (stdout, tb);
+  result = _output (stdout, format, arg_ptr);
+  if (_endbuf (stdout) != 0)
+    result = -1;
+  STREAM_UNLOCK (stdout);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/vscanf.c
===================================================================
--- trunk/src/emx/src/lib/io/vscanf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/vscanf.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vscanf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <emx/io.h>
+
+int vscanf (const char *format, va_list arg_ptr)
+{
+  int r;
+
+  STREAM_LOCK (stdin);
+  r = _input (stdin, format, arg_ptr);
+  STREAM_UNLOCK (stdin);
+  return r;
+}
Index: trunk/src/emx/src/lib/io/vsnprint.c
===================================================================
--- trunk/src/emx/src/lib/io/vsnprint.c	(revision 18)
+++ trunk/src/emx/src/lib/io/vsnprint.c	(revision 18)
@@ -0,0 +1,29 @@
+/* vsnprintf.c (emx+gcc) -- Copyright (c) 1995-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <limits.h>
+#include <emx/io.h>
+
+int _vsnprintf (char *buffer, size_t n, const char *format, va_list arg_ptr)
+{
+  FILE trick;
+  struct _file2 trick2;
+  int result;
+
+  if (n > INT_MAX)
+    return EOF;
+  trick._buffer = buffer;
+  trick._ptr = buffer;
+  trick._rcount = 0;
+  trick._wcount = n != 0 ? (int)n - 1 : 0;
+  trick._handle = -1;
+  trick._flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOWRT;
+  trick._buf_size = (int)n;
+  trick._flush = NULL;
+  trick._ungetc_count = 0;
+  _setdummymore (&trick, &trick2);
+  result = _output (&trick, format, arg_ptr);
+  if (n != 0)
+    *trick._ptr = 0;
+  return result;
+}
Index: trunk/src/emx/src/lib/io/vsprintf.c
===================================================================
--- trunk/src/emx/src/lib/io/vsprintf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/vsprintf.c	(revision 18)
@@ -0,0 +1,26 @@
+/* vsprintf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <limits.h>
+#include <emx/io.h>
+
+int vsprintf (char *buffer, const char *format, va_list arg_ptr)
+{
+  FILE trick;
+  struct _file2 trick2;
+  int result;
+
+  trick._buffer = buffer;
+  trick._ptr = buffer;
+  trick._rcount = 0;
+  trick._wcount = INT_MAX;
+  trick._handle = -1;
+  trick._flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOWRT;
+  trick._buf_size = INT_MAX;
+  trick._flush = NULL;
+  trick._ungetc_count = 0;
+  _setdummymore (&trick, &trick2);
+  result = _output (&trick, format, arg_ptr);
+  putc (0, &trick);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/vsscanf.c
===================================================================
--- trunk/src/emx/src/lib/io/vsscanf.c	(revision 18)
+++ trunk/src/emx/src/lib/io/vsscanf.c	(revision 18)
@@ -0,0 +1,26 @@
+/* vsscanf.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <emx/io.h>
+
+int vsscanf (const char *buffer, const char *format, va_list arg_ptr)
+{
+  FILE trick;
+  struct _file2 trick2;
+  int result;
+
+  trick._buffer = (char *)buffer;             /* const -> non-const */
+  trick._ptr = (char *)buffer;                /* const -> non-const */
+  trick._rcount = strlen (buffer);
+  trick._wcount = 0;
+  trick._handle = -1;
+  trick._flags = _IOOPEN|_IOSPECIAL|_IOBUFUSER|_IOREAD;
+  trick._buf_size = INT_MAX;
+  trick._flush = NULL;
+  trick._ungetc_count = 0;
+  _setdummymore (&trick, &trick2);
+  result = _input (&trick, format, arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/io/write.c
===================================================================
--- trunk/src/emx/src/lib/io/write.c	(revision 18)
+++ trunk/src/emx/src/lib/io/write.c	(revision 18)
@@ -0,0 +1,195 @@
+/* write.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <signal.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+#define CTRL_Z 0x1a
+
+#define BEGIN do {
+#define END   } while (0)
+
+/* Write the current buffer, for write_text(). */
+
+#define WRTBUF                                                  \
+  BEGIN                                                         \
+    n = __write (handle, buf, buf_cnt);                         \
+    if (n < 0) return -1;                                       \
+    out_cnt += n;                                               \
+    if (n != buf_cnt) goto partial;                             \
+    buf_cnt = 0; lf_cnt_1 = lf_cnt; buf_pos = i;                \
+  END
+
+/* Write to a text-mode file.  Partial writes are possible.  `buf' is
+   big enough for supporting atomic writes for
+
+        NBYTE <= PIPE_SIZE = 512
+
+   and any contents of the buffer pointed to by SRC (the worst case is
+   all newlines).  Return the number of characters (of SRC) written.
+   Return -1 on error. */
+
+static int write_text (int handle, const char *src, size_t nbyte, int *pflags)
+{
+  int out_cnt, lf_cnt, lf_cnt_1, buf_cnt, n;
+  size_t i, buf_pos;
+  char buf[2*512];
+  char splitp;
+
+  out_cnt = lf_cnt = lf_cnt_1 = buf_cnt = 0;
+  buf_pos = 0; i = 0;
+  if (*pflags & F_WRCRPEND)
+    {
+      if (*src == '\n')
+        {
+          /* Handle the first newline specially: Don't prepend a '\r'
+             character. */
+
+          buf[buf_cnt++] = src[i++];
+        }
+      else
+        {
+          /* This is the case where our algorithm fails: The
+             application does not try to continue writing with a
+             newline.  There will be an unexpected '\r' left in the
+             pipe. */
+
+          *pflags &= ~F_WRCRPEND;
+        }
+    }
+  while (i < nbyte)
+    {
+      if (src[i] == '\n')
+        {
+          /* Don't split '\r' and '\n' between two __write() calls as
+             we cannot remove the '\r' from a pipe in case the second
+             __write() fails. */
+
+         if (buf_cnt >= sizeof (buf) - 1) WRTBUF;
+          buf[buf_cnt++] = '\r';
+          ++lf_cnt;
+        }
+      if (buf_cnt >= sizeof (buf)) WRTBUF;
+      buf[buf_cnt++] = src[i++];
+    }
+  if (buf_cnt != 0) WRTBUF;
+  *pflags &= ~F_WRCRPEND;
+  return out_cnt - lf_cnt;
+
+partial:
+
+  /* Not all bytes have been written. */
+
+  if (n == 0)
+    return out_cnt - lf_cnt_1;
+
+  /* Adjust the return value for newline conversion: Add to `lf_cnt_1'
+     the number of '\r' characters written.
+
+     If the '\r', but not the '\n', of an expanded newline has been
+     written, processing depends on the handle type.  For files, we
+     remove the '\r' by changing the size of the file.  For pipes (and
+     devices), we exclude the newline from the count and set a flag to
+     let the next write() omit the '\r' if the first character to be
+     written is a newline. */
+
+  buf_cnt = 0; splitp = 0;
+  for (i = buf_pos; buf_cnt < n; ++i)
+    {
+      /* Check for '\r' in `buf' to handle the case of an initial '\n'
+         with suppressed '\r'. */
+
+      if (src[i] == '\n' && buf[buf_cnt] == '\r')
+        {
+          ++buf_cnt;
+          if (buf_cnt == n)
+            splitp = 1;
+          if (buf_cnt <= n)
+            ++lf_cnt_1;
+        }
+      ++buf_cnt;
+    }
+
+  if (splitp)
+    {
+      if (*pflags & (F_DEV|F_SOCKET|F_PIPE))
+        *pflags |= F_WRCRPEND;
+      else
+        {
+          long pos;
+          int saved_errno;
+
+          saved_errno = errno;
+          pos = __lseek (handle, -1L, SEEK_CUR);
+          if (pos != -1)
+            __ftruncate (handle, pos);
+          errno = saved_errno;
+        }
+    }
+  else
+    *pflags &= ~F_WRCRPEND;
+  return out_cnt - lf_cnt_1;
+}
+
+
+int _write (int handle, const void *buf, size_t nbyte)
+{
+  int n, *pflags;
+  const char *src;
+
+  if ((pflags = _fd_flags (handle)) == NULL)
+    {
+      errno = EBADF; return -1;
+    }
+  if ((*pflags & (F_DEV|F_SOCKET|F_PIPE|O_APPEND)) == O_APPEND)
+    __lseek (handle, 0L, SEEK_END);
+  if (nbyte == 0)                 /* Avoid truncation of file */
+    return 0;
+  src = buf;
+  if ((*pflags & O_TEXT) && ((*pflags & F_WRCRPEND)
+                             || memchr (src, '\n', nbyte) != NULL))
+    n = write_text (handle, src, nbyte, pflags);
+  else
+    n = __write (handle, src, nbyte);
+
+  if (n < 0)
+    {
+      if (errno == EPIPE)
+        {
+          __raise (SIGPIPE);
+          errno = EPIPE;
+        }
+      return -1;
+    }
+  if (n == 0)
+    {
+      /* Ctrl-Z cannot be written to certain devices (printer) unless
+         they have been switched to binary mode.  Don't return an
+         error if writing failed due to a Ctrl-Z at the start of the
+         data to be written. */
+
+      if ((*pflags & F_DEV) && *src == CTRL_Z)
+        return 0;
+
+      /* For devices and pipes with O_NONBLOCK set, set errno to
+         EAGAIN. */
+
+      if ((*pflags & (F_DEV|F_SOCKET|F_PIPE))
+          && (*pflags & O_NONBLOCK))
+        {
+          errno = EAGAIN;
+          return -1;
+        }
+
+      /* Set errno to ENOSPC in all remaining cases (disk full while
+         writing to a disk file). */
+
+      errno = ENOSPC;
+      return -1;
+    }
+  return n;
+}
Index: trunk/src/emx/src/lib/io/writev.c
===================================================================
--- trunk/src/emx/src/lib/io/writev.c	(revision 18)
+++ trunk/src/emx/src/lib/io/writev.c	(revision 18)
@@ -0,0 +1,57 @@
+/* writev.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+int _writev (int handle, const struct iovec *iov, int iovcnt)
+{
+  int i, n;
+  size_t total, len;
+  char *buf, *mp, *p;
+
+  if (iovcnt <= 0 || iovcnt > 16)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  total = 0;
+  for (i = 0; i < iovcnt; ++i)
+    {
+      if (iov[i].iov_len < 0)
+        {
+          errno = EINVAL;
+          return -1;
+        }
+      total += iov[i].iov_len;
+    }
+
+  mp = NULL;
+  if (total <= 0x100000)
+    buf = alloca (total);
+  else
+    buf = mp = malloc (total);
+  if (buf == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  p = buf;
+  for (i = 0; i < iovcnt; ++i)
+    {
+      len = iov[i].iov_len;
+      memcpy (p, iov[i].iov_base, len);
+      p += len;
+    }
+
+  n = _write (handle, buf, total);
+  if (mp != NULL)
+    free (mp);
+  return n;
+}
Index: trunk/src/emx/src/lib/lib0.mak
===================================================================
--- trunk/src/emx/src/lib/lib0.mak	(revision 18)
+++ trunk/src/emx/src/lib/lib0.mak	(revision 18)
@@ -0,0 +1,36 @@
+#
+# /emx/src/lib/lib0.mak
+#
+GCC=gcc -O2 -Wall -mprobe -fstack-check -mepilogue -DNDEBUG $(LIBC_CCFLAGS) $(MT_CCFLAGS)
+AR=ar
+I=/emx/include/
+S=/emx/include/sys/
+L=\emx\lib\ #
+MAP=\emx\etc\ #
+FCNTL=$(I)fcntl.h $(S)fcntl.h
+PROCESS=$(I)process.h $(S)process.h
+SIGNAL=$(I)signal.h $(S)signal.h
+ERRNO=$(I)errno.h $(S)errno.h
+BUILTIN=$(S)builtin.h $(I)$(CPU)/builtin.h
+FMUTEX=$(BUILTIN) $(S)fmutex.h
+RMUTEX=$(FMUTEX) $(S)rmutex.h
+LIBCDLL=/emx/src/lib/cdll/
+ASM386H=$(I)emx/asm386.h
+
+PASSDOWN=CPU=$(CPU) DELOPT=$(DELOPT)
+
+.SUFFIXES: .c .imp .o .obj .s
+
+.IF $(OMF)
+.c.obj:
+	$(GCC) -c -Zomf $<
+
+.s.obj:
+	$(GCC) -c -Zomf -x assembler-with-cpp -I. -I../$(CPU) $<
+.ELSE
+.c.o:
+	$(GCC) -c $<
+
+.s.o:
+	$(GCC) -c -x assembler-with-cpp -I. -I../$(CPU) $<
+.END
Index: trunk/src/emx/src/lib/libc.mak
===================================================================
--- trunk/src/emx/src/lib/libc.mak	(revision 18)
+++ trunk/src/emx/src/lib/libc.mak	(revision 18)
@@ -0,0 +1,5 @@
+#
+# /emx/src/lib/libc.mak
+#
+LIBBASE=c
+.INCLUDE: /emx/src/lib/libc0.mak
Index: trunk/src/emx/src/lib/libc0.mak
===================================================================
--- trunk/src/emx/src/lib/libc0.mak	(revision 18)
+++ trunk/src/emx/src/lib/libc0.mak	(revision 18)
@@ -0,0 +1,51 @@
+#
+# /emx/src/lib/libc0.mak
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.IF $(OMF)
+DSTLIB=/emx/lib/$(LIBNAME).lib
+.ELSE
+DSTLIB=/emx/lib/$(LIBNAME).a
+.END
+LIBC_CCFLAGS=-I.. $(MORE_LIBC_CCFLAGS)
+
+.PHONY: default clean lib-st lib-st-p lib-mt dstlib local \
+        lib-st-2 lib-st-p-2 lib-mt-2
+
+.SOURCE.c: ../$(CPU)
+.SOURCE.h: ../$(CPU)
+.SOURCE.s: ../$(CPU)
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+.SOURCE.s: ..
+
+default: lib-st lib-mt lib-st-p
+
+lib-st: local lib-st-2
+lib-st-p: local lib-st-p-2
+lib-mt: local lib-mt-2
+
+lib-st-2 .SETDIR=st_$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN) LIBNAME=st/$(LIBBASE) MT_CCFLAGS=
+
+lib-st-p-2 .SETDIR=st_p_$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN) LIBNAME=st/$(LIBBASE)_p MT_CCFLAGS=-pg
+
+lib-mt-2 .SETDIR=mt_$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN) LIBNAME=mt/$(LIBBASE) MT_CCFLAGS=-Zmt
+
+dstlib: $(DSTLIB)
+
+.IF $(OMF)
+clean:
+	-del st_$(CPU)\*.obj $(DELOPT)
+	-del mt_$(CPU)\*.obj $(DELOPT)
+	-del st_p_$(CPU)\*.obj $(DELOPT)
+.ELSE
+clean:
+	-del st_$(CPU)\*.o $(DELOPT)
+	-del mt_$(CPU)\*.o $(DELOPT)
+	-del st_p_$(CPU)\*.o $(DELOPT)
+.END
Index: trunk/src/emx/src/lib/locale/curlcfti.c
===================================================================
--- trunk/src/emx/src/lib/locale/curlcfti.c	(revision 18)
+++ trunk/src/emx/src/lib/locale/curlcfti.c	(revision 18)
@@ -0,0 +1,17 @@
+/* curlcfti.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/locale.h>
+
+struct _lcf_time _cur_lcf_time =
+{
+  {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"},
+  {"January", "February", "March", "April", "May", "June",
+   "July", "August", "September", "October", "November", "December"},
+  {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
+  {"Sunday", "Monday", "Tuesday", "Wednesday",
+   "Thursday", "Friday", "Saturday"},
+  "%a %b %d %H:%M:%S %Y", "%m/%d/%y", "%H:%M:%S",
+  "AM", "PM"
+};
Index: trunk/src/emx/src/lib/locale/curlconv.c
===================================================================
--- trunk/src/emx/src/lib/locale/curlconv.c	(revision 18)
+++ trunk/src/emx/src/lib/locale/curlconv.c	(revision 18)
@@ -0,0 +1,13 @@
+/* curlconv.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <locale.h>
+#include <emx/locale.h>
+
+struct lconv _cur_lconv =
+{
+  ".", "", "", "", "", "", "", "", "", "",
+  CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
+  CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX
+};
Index: trunk/src/emx/src/lib/locale/localeco.c
===================================================================
--- trunk/src/emx/src/lib/locale/localeco.c	(revision 18)
+++ trunk/src/emx/src/lib/locale/localeco.c	(revision 18)
@@ -0,0 +1,65 @@
+/* localeco.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <locale.h>
+#include <emx/locale.h>
+
+/* Assume that all the library modules are compiled with the same
+   signedness of char. */
+
+#define CONVERT(F) tmp.F = (_cur_lconv.F == CHAR_MAX \
+                           ? (char)char_max : _cur_lconv.F)
+
+
+/* TODO: This is not yet thread-safe. */
+
+static char grouping[64];
+static int gi;
+
+static void convert_grouping (char **dst, char **src, int char_max)
+{
+  const char *s;
+
+  s = *src;
+  while (*s != 0 && *s != CHAR_MAX)
+    ++s;
+  if (*s == CHAR_MAX)
+    {
+      *dst = grouping + gi;
+      for (s = *src; *s != CHAR_MAX; ++s)
+        grouping[gi++] = *s;
+      grouping[gi++] = (char)char_max;
+    }
+}
+    
+
+struct lconv *_localeconv (int char_max)
+{
+  static struct lconv tmp;
+
+  tmp = _cur_lconv;
+  CONVERT (int_frac_digits);
+  CONVERT (frac_digits);
+  CONVERT (p_cs_precedes);
+  CONVERT (p_sep_by_space);
+  CONVERT (n_cs_precedes);
+  CONVERT (n_sep_by_space);
+  CONVERT (p_sign_posn);
+  CONVERT (n_sign_posn);
+
+  if (char_max != CHAR_MAX)
+    {
+      gi = 0;
+      convert_grouping (&tmp.grouping, &_cur_lconv.grouping, char_max);
+      convert_grouping (&tmp.mon_grouping, &_cur_lconv.mon_grouping, char_max);
+    }
+
+  return &tmp;
+}
+
+
+struct lconv *(localeconv) (void)
+{
+  return _localeconv (127);
+}
Index: trunk/src/emx/src/lib/locale/locales.c
===================================================================
--- trunk/src/emx/src/lib/locale/locales.c	(revision 18)
+++ trunk/src/emx/src/lib/locale/locales.c	(revision 18)
@@ -0,0 +1,235 @@
+/* locales.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <locale.h>
+#include <emx/locale.h>
+
+/* ---------------------------------- C ---------------------------------- */
+
+static const struct lc_collate c_collate = {0};
+static const struct lc_ctype c_ctype = {0};
+static const struct lc_monetary c_monetary =
+{
+  "", "", "", "", "", "", "",
+  CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
+  CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX
+};
+static const struct lc_numeric c_numeric = {".", "", ""};
+static const struct lc_time c_time =
+{
+  "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec",
+  "January\0February\0March\0April\0May\0June\0"
+    "July\0August\0September\0October\0November\0December",
+  "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat",
+  "Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday",
+  "%a %b %d %H:%M:%S %Y", "%m/%d/%y", "%H:%M:%S",
+  "AM", "PM"
+};
+
+/* --------------------------------- FRAN -------------------------------- */
+
+#define fran_collate c_collate
+#define fran_ctype   c_ctype
+static const struct lc_monetary fran_monetary =
+{
+  "FRF ", "F", ",", ".", "\3", "", "-",
+  2, 2, 0, 1, 0, 1, 1, 1
+};
+static const struct lc_numeric fran_numeric = {",", " ", "\3"};
+static const struct lc_time fran_time =
+{
+  "jan\0fev\0mar\0avr\0mai\0jun\0jui\0aou\0sep\0oct\0nov\0dec",
+  "janvier\0f\\'evrier\0mars\0avril\0mai\0juin\0"
+    "juillet\0ao\\^ut\0septembre\0octobre\0novembre\0d\\'ecembre",
+  "Dim\0Lun\0Mar\0Mer\0Jeu\0Ven\0Sam",
+  "Dimanche\0Lundi\0Mardi\0Mercredi\0Jeudi\0Vendredi\0Samedi",
+  "%d-%m-%y %H.%M.%S", "%d.%m.%y", "%H.%M.%S",
+  "", ""
+};
+
+/* --------------------------------- GERM -------------------------------- */
+
+#define germ_collate c_collate
+#define germ_ctype   c_ctype
+static const struct lc_monetary germ_monetary =
+{
+  "DEM ", "DM", ",", ".", "\3", "", "-",
+  2, 2, 1, 0, 1, 0, 1, 1
+};
+static const struct lc_numeric germ_numeric = {",", ".", "\3"};
+static const struct lc_time germ_time =
+{
+  "Jan\0Feb\0Mrz\0Apr\0Mai\0Jun\0Jul\0Aug\0Sep\0Okt\0Nov\0Dez",
+  "Januar\0Februar\0M\\\"arz\0April\0Mai\0Juni\0"
+    "Juli\0August\0September\0Oktober\0November\0Dezember",
+  "So\0Mo\0Di\0Mi\0Do\0Fr\0Sa",
+  "Sonntag\0Montag\0Dienstag\0Mittwoch\0Donnerstag\0Freitag\0Samstag",
+  "%A, %d. %B %Y %H.%M.%S", "%d.%m.%Y", "%H.%M.%S",
+  "", ""
+};
+
+/* --------------------------------- ITAL -------------------------------- */
+
+#define ital_collate c_collate
+#define ital_ctype   c_ctype
+static const struct lc_monetary ital_monetary =
+{
+  "ITL. ", "L.", "", ".", "\3", "", "-",
+  0, 0, 1, 1, 1, 1, 1, 1
+};
+#define ital_numeric germ_numeric
+static const struct lc_time ital_time =
+{
+  "GEN\0FEB\0MAR\0APR\0MAG\0GIU\0LUG\0AGO\0SET\0OTT\0NOV\0DIC",
+  "gennaio\0febbraio\0marzo\0aprile\0maggio\0giugno\0"
+    "luglio\0agosto\0settembre\0ottobre\0novembre\0dicembre",
+  "DOM\0LUN\0MAR\0MER\0GIO\0VEN\0SAB",
+  "dom\\'enica\0luned\\`i\0marted\\`i\0mercoled\\`i\0"
+    "gioved\\`i\0venerd\\`i\0s\\`abato",
+  "%d/%m/%Y %H:%M:%S", "%d/%m/%y", "%H:%M:%S",
+  "", ""
+};
+
+/* --------------------------------- NETH -------------------------------- */
+
+#if 0
+
+#define neth_collate c_collate
+#define neth_ctype   c_ctype
+static const struct lc_monetary neth_monetary =
+{
+  "NLG ", "F", ",", ".", "\3", "", "-",
+  2, 2, 1, 1, 1, 1, 1, 4
+};
+#define neth_numeric germ_numeric
+#define neth_time    c_time
+
+#endif
+
+/* --------------------------------- NORW -------------------------------- */
+
+#if 0
+
+#define norw_collate c_collate
+#define norw_ctype   c_ctype
+static const struct lc_monetary norw_monetary =
+{
+  "NOK ", "kr", ",", ".", "\3", "", "-",
+  2, 2, 1, 0, 1, 0, 1, 2
+};
+#define norw_numeric germ_numeric
+#define norw_time    c_time
+
+#endif
+
+/* --------------------------------- SPAI -------------------------------- */
+
+#define spai_collate c_collate
+#define spai_ctype   c_ctype
+static const struct lc_monetary spai_monetary =
+{
+  "ESP ", "Pts", "", ".", "\3", "", "-",
+  0, 0, 1, 1, 1, 1, 1, 1
+};
+#define spai_numeric germ_numeric
+static const struct lc_time spai_time =
+{
+  "ENE\0FEB\0MAR\0ABR\0MAY\0JUN\0JUL\0AGO\0SEP\0OCT\0NOV\0DIC",
+  "Enero\0Febrero\0Marzo\0Abril\0Mayo\0Junio\0"
+    "Julio\0Agosto\0Septiembre\0Octubre\0Noviembre\0Diciembre",
+  "DOM\0LUN\0MAR\0MIE\0JUE\0VIE\0SAB",
+  "Domingo\0Lunes\0Martes\0Miercoles\0Jueves\0Viernes\0Sabado",
+  "%d %B %Y %H:%M:%S", "%d/%m/%y", "%H:%M:%S",
+  "", ""
+};
+
+/* --------------------------------- UK ---------------------------------- */
+
+#define uk_collate c_collate
+#define uk_ctype   c_ctype
+static const struct lc_monetary uk_monetary =
+{
+  "GBP ", "$", ".", ",", "\3", "", "-",
+  2, 2, 1, 0, 1, 0, 1, 1
+};
+#define uk_numeric usa_numeric
+static const struct lc_time uk_time =
+{
+  "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec",
+  "January\0February\0March\0April\0May\0June\0"
+    "July\0August\0September\0October\0November\0December",
+  "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat",
+  "Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday",
+  "%d/%m/%y %H:%M:%S", "%d/%m/%y", "%H:%M:%S",
+  "", ""
+};
+
+/* --------------------------------- USA --------------------------------- */
+
+#define usa_collate c_collate
+#define usa_ctype   c_ctype
+static const struct lc_monetary usa_monetary =
+{
+  "AMD ", "$", ".", ",", "\3", "", "-",
+  2, 2, 1, 0, 1, 0, 1, 1
+};
+static const struct lc_numeric usa_numeric = {".", ",", "\3"};
+#define usa_time    c_time
+
+/* -------------------------------- en_us -------------------------------- */
+
+#define en_us_collate c_collate
+#define en_us_ctype   c_ctype
+static const struct lc_monetary en_us_monetary =
+{
+  "USD ", "$", ".", ",", "\3", "", "-",
+  2, 2, 1, 0, 1, 0, 2, 2
+};
+#define en_us_numeric usa_numeric
+#define en_us_time    c_time
+
+/* -------------------------------- en_gb -------------------------------- */
+
+#define en_gb_collate c_collate
+#define en_gb_ctype   c_ctype
+static const struct lc_monetary en_gb_monetary =
+{
+  "GBP ", "", ".", ",", "\3", "+", "-",
+  2, 2, 1, 0, 1, 0, 1, 1
+};
+#define en_gb_numeric usa_numeric
+#define en_gb_time    c_time
+
+/* ----------------------------------------------------------------------- */
+
+/* The type casts are used for removing constness. */
+
+#define DATA(NAME,PFX) \
+  { \
+     NAME, \
+     (struct lc_collate *)&PFX##_collate, \
+     (struct lc_ctype *)&PFX##_ctype, \
+     (struct lc_monetary *)&PFX##_monetary, \
+     (struct lc_numeric *)&PFX##_numeric, \
+     (struct lc_time *)&PFX##_time \
+   }
+
+const struct lc_data _lc_table[] =
+{
+  DATA ("C", c),
+  DATA ("FRAN", fran),
+  DATA ("GERM", germ),
+  DATA ("ITAL", ital),
+#if 0
+  DATA ("NETH", neth),
+  DATA ("NORW", norw),
+#endif
+  DATA ("SPAI", spai),
+  DATA ("UK", uk),
+  DATA ("USA", usa),
+  DATA ("de_de", germ),
+  DATA ("en_us", en_us),
+  DATA ("en_gb", en_gb),
+  {NULL, NULL, NULL, NULL, NULL, NULL}
+};
Index: trunk/src/emx/src/lib/locale/makefile
===================================================================
--- trunk/src/emx/src/lib/locale/makefile	(revision 18)
+++ trunk/src/emx/src/lib/locale/makefile	(revision 18)
@@ -0,0 +1,15 @@
+#
+# /emx/src/lib/locale/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+curlcfti.o: curlcfti.c $(I)stdlib.h $(I)emx/locale.h
+curlconv.o: curlconv.c $(I)stdlib.h $(I)locale.h $(I)limits.h $(I)emx/locale.h
+localeco.o: localeco.c $(I)stdlib.h $(I)locale.h $(I)emx/locale.h
+locales.o:  locales.c $(I)stdlib.h $(I)locale.h $(I)limits.h $(I)emx/locale.h
+setlocal.o: setlocal.c $(I)stdlib.h $(I)locale.h $(I)string.h $(I)emx/locale.h
+
+$(DSTLIB): curlcfti.o curlconv.o localeco.o locales.o setlocal.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/locale/setlocal.c
===================================================================
--- trunk/src/emx/src/lib/locale/setlocal.c	(revision 18)
+++ trunk/src/emx/src/lib/locale/setlocal.c	(revision 18)
@@ -0,0 +1,420 @@
+/* setlocal.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <string.h>
+#include <emx/locale.h>
+
+static char *lcn_collate  = "C";
+static char *lcn_ctype    = "C";
+static char *lcn_monetary = "C";
+static char *lcn_numeric  = "C";
+static char *lcn_time     = "C";
+
+/* Store strings for strftime() here.  We cannot directly used the
+   strings provided in the locales table entry because we have to
+   translate accented character for the current code page. */
+
+static char time_buf[320];
+static int time_buf_ptr;
+
+/* Table are used for translating accented characters (specified in
+   TeX notation) to the current code page.  This is an entry of such a
+   table.  `inp' is the base character and `out' is the translated
+   character.  The last entry of a table has inp == 0. */
+
+struct accent
+{
+  unsigned char inp;
+  unsigned char out;
+};
+
+/* This structure describes a code page.  It holds pointers to the
+   accent translation tables. */
+
+struct codepage
+{
+  struct accent *acute;
+  struct accent *grave;
+  struct accent *circumflex;
+  struct accent *dieresis;
+};
+
+
+/* This table translates acute accents to code page 850. */
+
+static struct accent cp850_acute[] =
+{
+  {'e', 130},
+  {0, 0}
+};
+
+/* This table translates grave accents to code page 850. */
+
+static struct accent cp850_grave[] =
+{
+  {'a', 133},
+  {'i', 141},
+  {0, 0}
+};
+
+/* This table translates circumflex accents to code page 850. */
+
+static struct accent cp850_circumflex[] =
+{
+  {'u', 150},
+  {0, 0}
+};
+
+/* This table translates umlaut accents to code page 850. */
+
+static struct accent cp850_dieresis[] =
+{
+  {'a', 132},
+  {0, 0}
+};
+
+
+/* This is the description of code page 850. */
+
+static struct codepage cp_850 =
+{
+  cp850_acute,
+  cp850_grave,
+  cp850_circumflex,
+  cp850_dieresis
+};
+
+
+/* The current code page. */
+
+static struct codepage *cur_cp = &cp_850;
+
+
+/* Add the character C to the end of `time_buf' and update
+   `time_buf_ptr'.  If there is no space left, nothing is done. */
+
+#define TIME_BUF_CHAR(C) \
+  (time_buf_ptr < sizeof (time_buf) \
+    ? (void)(time_buf[time_buf_ptr++] = (C)) : (void)0)
+
+
+/* Translate an accented character and put the result into `time_buf'.
+   P is the translation table, C is the base character.  Return true
+   if the translation is successful. */
+
+static int time_buf_accent (const struct accent *p, unsigned char c)
+{
+  if (p == NULL)
+    return 0;
+  while (p->inp != 0)
+    {
+      if (p->inp == c)
+        {
+          TIME_BUF_CHAR (p->out);
+          return 1;
+        }
+      ++p;
+    }
+  return 0;
+}
+
+
+/* Translate a string according to the current code page and put it
+   into `time_buf'.  Return a pointer to the start of the string in
+   `time_buf'.  If there is not enough space left in `time_buf',
+   return a pointer to the string "?". */
+
+static char *set_time_buf (const char *s)
+{
+  unsigned char c;
+  char *result;
+
+  result = time_buf + time_buf_ptr;
+  while ((c = *s++) != 0)
+    if (c == '\\')
+      switch ((c = *s))
+        {
+        case 0:
+          break;
+        case '\\':
+          ++s;
+          TIME_BUF_CHAR ('\\');
+          break;
+        case '\'':
+          ++s;
+          if (*s != 0)
+            {
+              c = *s++;
+              if (!time_buf_accent (cur_cp->acute, c))
+                TIME_BUF_CHAR (c);
+            }
+          break;
+        case '`':
+          ++s;
+          if (*s != 0)
+            {
+              c = *s++;
+              if (!time_buf_accent (cur_cp->grave, c))
+                TIME_BUF_CHAR (c);
+            }
+          break;
+        case '^':
+          ++s;
+          if (*s != 0)
+            {
+              c = *s++;
+              if (!time_buf_accent (cur_cp->circumflex, c))
+                TIME_BUF_CHAR (c);
+            }
+          break;
+        case '"':
+          ++s;
+          if (*s != 0)
+            {
+              c = *s++;
+              if (!time_buf_accent (cur_cp->dieresis, c))
+                {
+                  TIME_BUF_CHAR (c);
+                  if (c == 'a' || c == 'o' || c == 'u'
+                      || c == 'A' || c == 'E' || c == 'U')
+                    TIME_BUF_CHAR ('e');
+                }
+            }
+          break;
+        default:
+          ++s;
+          TIME_BUF_CHAR ('?');
+          break;
+          }
+    else
+      TIME_BUF_CHAR (c);
+  if (time_buf_ptr < sizeof (time_buf))
+    time_buf[time_buf_ptr++] = 0;
+  else
+    result = "?";
+  return result;
+}
+
+
+/* Translate COUNT strings according to the current code page and put
+   them into `time_buf'.  Put pointers to the strings in `time_buf'
+   into the array pointed to by DST.  SRC points to the source
+   strings, separated by null characters. */
+
+static void time_buf_array (char **dst, const char *src, int count)
+{
+  int i;
+
+  for (i = 0; i < count; ++i)
+    {
+      dst[i] = set_time_buf (src);
+      src = strchr (src, 0) + 1;
+    }
+}
+
+
+/* Find LOCALE in the table of locales.  If no matching entry is
+   found, return NULL.  Otherwise return a pointer to the table
+   entry. */
+
+static const struct lc_data *findloc (const char *locale)
+{
+  const struct lc_data *dp;
+
+  for (dp = _lc_table; dp->name != NULL; ++dp)
+    if (_stricmp (dp->name, locale) == 0)
+      return dp;
+  return NULL;
+}
+
+
+/* Update the data associated with category CATEGORY for locale
+   LOCALE.  LOCALE specifies a single locale.  Return the name of the
+   locale or NULL. */
+
+static char *setloc1 (int category, const char *locale)
+{
+  const struct lc_data *dp;
+
+  dp = findloc (locale);
+  if (dp == NULL)
+    return NULL;
+  if (category == LC_COLLATE || category == LC_ALL)
+    {
+      lcn_collate = dp->name;
+    }
+  if (category == LC_CTYPE || category == LC_ALL)
+    {
+      lcn_ctype = dp->name;
+      /* Set _mb_cur_max and _cur_mbyte. */
+    }
+  if (category == LC_MONETARY || category == LC_ALL)
+    {
+      lcn_monetary = dp->name;
+      _cur_lconv.int_curr_symbol   = dp->monetary->int_curr_symbol;
+      _cur_lconv.currency_symbol   = dp->monetary->currency_symbol;
+      _cur_lconv.mon_decimal_point = dp->monetary->mon_decimal_point;
+      _cur_lconv.mon_thousands_sep = dp->monetary->mon_thousands_sep;
+      _cur_lconv.mon_grouping      = dp->monetary->mon_grouping;
+      _cur_lconv.positive_sign     = dp->monetary->positive_sign;
+      _cur_lconv.negative_sign     = dp->monetary->negative_sign;
+      _cur_lconv.int_frac_digits   = dp->monetary->int_frac_digits;
+      _cur_lconv.frac_digits       = dp->monetary->frac_digits;
+      _cur_lconv.p_cs_precedes     = dp->monetary->p_cs_precedes;
+      _cur_lconv.p_sep_by_space    = dp->monetary->p_sep_by_space;
+      _cur_lconv.n_cs_precedes     = dp->monetary->n_cs_precedes;
+      _cur_lconv.n_sep_by_space    = dp->monetary->n_sep_by_space;
+      _cur_lconv.p_sign_posn       = dp->monetary->p_sign_posn;
+      _cur_lconv.n_sign_posn       = dp->monetary->n_sign_posn;
+    }
+  if (category == LC_NUMERIC || category == LC_ALL)
+    {
+      lcn_numeric = dp->name;
+      _cur_lconv.decimal_point = dp->numeric->decimal_point;
+      _cur_lconv.thousands_sep = dp->numeric->thousands_sep;
+      _cur_lconv.grouping      = dp->numeric->grouping;
+    }
+  if (category == LC_TIME || category == LC_ALL)
+    {
+      lcn_time = dp->name;
+      time_buf_ptr = 0;
+      time_buf_array (_cur_lcf_time.months1, dp->time->months1, 12);
+      time_buf_array (_cur_lcf_time.months2, dp->time->months2, 12);
+      time_buf_array (_cur_lcf_time.wdays1, dp->time->wdays1, 7);
+      time_buf_array (_cur_lcf_time.wdays2, dp->time->wdays2, 7);
+      _cur_lcf_time.date_time_fmt = set_time_buf (dp->time->date_time_fmt);
+      _cur_lcf_time.date_fmt = set_time_buf (dp->time->date_fmt);
+      _cur_lcf_time.time_fmt = set_time_buf (dp->time->time_fmt);
+      _cur_lcf_time.am = set_time_buf (dp->time->am);
+      _cur_lcf_time.pm = set_time_buf (dp->time->pm);
+
+    }
+  return dp->name;
+}
+
+
+char *setlocale (int category, const char *locale)
+{
+  static char buf[64];
+  char *pn;
+  const char *s1, *s2;
+  int store, i, len;
+  static const int cat[5] = 
+    {LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME};
+
+  /* Check CATEGORY (fail if it's invalid) and set `pn' to the current
+     locale associated with CATEGORY (or to NULL if CATEGORY is
+     LC_ALL). */
+
+  switch (category)
+    {
+    case LC_ALL:
+      pn = NULL;
+      break;
+    case LC_COLLATE:
+      pn = lcn_collate;
+      break;
+    case LC_CTYPE:
+      pn = lcn_ctype;
+      break;
+    case LC_MONETARY:
+      pn = lcn_monetary;
+      break;
+    case LC_NUMERIC:
+      pn = lcn_numeric;
+      break;
+    case LC_TIME:
+      pn = lcn_time;
+      break;
+    default:
+      return NULL;
+    }
+
+  /* If LOCALE is NULL, return the current locale. */
+
+  if (locale == NULL)
+    {
+      /* `pn' is non-NULL for all categories but LC_ALL. */
+
+      if (pn != NULL)
+        return pn;
+
+      /* If the locales for all the categories are identical, return
+         that locale. */
+
+      if (_stricmp (lcn_collate, lcn_ctype) == 0
+          && _stricmp (lcn_collate, lcn_monetary) == 0
+          && _stricmp (lcn_collate, lcn_numeric) == 0
+          && _stricmp (lcn_collate, lcn_time) == 0)
+        return lcn_collate;
+
+      /* Create a comma-separated list of locales for all the
+         categories. */
+
+      strcpy (buf, lcn_collate); strcat (buf, ",");
+      strcat (buf, lcn_ctype); strcat (buf, ",");
+      strcat (buf, lcn_monetary); strcat (buf, ",");
+      strcat (buf, lcn_numeric); strcat (buf, ",");
+      strcat (buf, lcn_time);
+      return buf;
+    }
+
+  /* The default locale is taken from the LANG environment variable. */
+
+  if (*locale == 0)
+    {
+      locale = getenv ("LANG");
+      if (locale == NULL || *locale == 0)
+        locale = "C";
+    }
+
+  /* LOCALE is treated specially if it contains commas and CATEGORY is
+     LC_ALL.  Otherwise, it simply contains the name of the locale. */
+
+  if (category != LC_ALL || strchr (locale, ',') == NULL)
+    return setloc1 (category, locale);
+
+  /* We have to copy LOCALE to `buf' for keeping the return value in
+     case the caller changes LOCALE. */
+
+  if (strlen (locale) >= sizeof (buf))
+    return NULL;
+
+  /* Make two passes: The first pass checks whether LOCALE is
+     correctly formatted and contains valid locales, the second pass
+     sets the data for all the categories. */
+
+  for (store = 0; store < 2; ++store)
+    {
+
+      /* Loop over 5 comma-separated locales in LOCALE. */
+
+      s1 = locale;
+      for (i = 0; i < 5; ++i)
+        {
+          s2 = strchr (s1, ',');
+          if (i == 4)
+            {
+              if (s2 != NULL)
+                return NULL;
+              s2 = strchr (s1, 0);
+            }
+          else
+            {
+              if (s2 == NULL)
+                return NULL;
+            }
+          len = s2 - s1;
+          memcpy (buf, s1, len);
+          buf[len] = 0;
+          if (store)
+            setloc1 (cat[i], buf);
+          else if (findloc (buf) == NULL)
+            return NULL;
+          s1 = s2 + 1;
+        }
+    }
+  strcpy (buf, locale);
+  return buf;
+}
Index: trunk/src/emx/src/lib/make.cmd
===================================================================
--- trunk/src/emx/src/lib/make.cmd	(revision 18)
+++ trunk/src/emx/src/lib/make.cmd	(revision 18)
@@ -0,0 +1,6 @@
+@echo off
+setlocal
+set switchar=-
+set gccopt=-pipe %gccopt%
+(dmake %1 %2 %3 %4 %5 %6 %7 %8 %9 2>&1) | tee out
+endlocal
Index: trunk/src/emx/src/lib/makefile
===================================================================
--- trunk/src/emx/src/lib/makefile	(revision 18)
+++ trunk/src/emx/src/lib/makefile	(revision 18)
@@ -0,0 +1,547 @@
+#
+# /emx/src/lib/makefile
+#
+# This makefile has been designed for dmake 3.8.
+#
+# Don't forget to SET SWITCHAR=-
+#
+# Targets:
+#
+# mkdir         Create directories
+# c-st          Single-thread common C library:      st/c.a
+# c-st-p        Ditto, for profiling:                st/c_p.a
+# c-mt          Multithread common C library:        mt/c.a
+# c_alias       Aliases                              c_alias.{a,lib}
+# c_static      Static modules                       c_static.{a,lib}
+# c_app-st      Single-thread application C library: st/c_app.a
+# c_app-st-p    Ditto, for profiling:                st/c_app_p.a
+# c_app-mt      Multithread application C library:   mt/c_app.a
+# c_dllrt-st    Single-thread DLL C library:         st/c_dllrt.a
+# c_dllrt-mt    Multithread DLL C library:           mt/c_dllrt.a
+# c_dllso-st    Single-thread DLL C library (-Zso):  st/c_dllso.lib
+# c_dllso-mt    Multithread DLL C library (-Zso):    mt/c_dllso.lib
+# c_import-st   Single-thread import library:        st/c_import.{a,lib}
+# c_import-mt   Multithread import library:          mt/c_import.{a,lib}
+# c_dllnrt      DLL without runtime environment:     c_dllnrt.lib
+# libgcc        GCC helper functions:                gcc.a
+# libgcc-p	Ditto, with profiling:		     gcc_p.a
+# socket        Socket library:                      socket.a
+# graph         Graphics library:                    graph.a
+# video         Video library:                       video.a
+# moddef        moddef library:                      moddef.a
+# omflib        omflib library:                      omflib.a
+# tmalloc       tmalloc wrapper library:             tmalloc.a
+# malloc1-st	Old single-thread malloc library:    st/malloc1.a
+# malloc1-mt	Old multithread malloc library:	     mt/malloc1.a
+# end		etext/edata/end library for LINK386: end.lib
+# os2           OS/2 API import library:             os2.a
+# os2-p         Ditto, for profiling:                os2_p.a
+# dll-fwd       Create forwarder DLL                 emxlibc.dll
+# dll-mt        Create multithread C runtime DLL     emxlibcm.dll
+# dll-st        Create single-thread C runtime DLL   emxlibcs.dll
+# sys           System call emulation library:       st/sys.lib mt/sys.lib
+# o-crt         Startup modules (.o)                 crt0.o dll0.o ...
+# o-crt-bsd     Ditto, BSD stuff                     gcrt0.o
+# o-opt         Optional object files (.o)           binmode.o sigbsd.o ...
+# obj-crt       Startup modules (.obj)               crt0.obj dll0.obj ...
+# obj-opt       Optional object files (.obj)         binmode.obj sigbsd.obj ...
+# emxwrap       emxwrap.dll, wrap.a, and wrap.lib
+# all-dos       All libraries and object files for DOS
+# all-os2       Ditto, plus libraries, object files, and DLLs for OS/2
+# all-dos-bsd   Like all-dos, plus BSD stuff
+# all-os2-bsd   Like all-os2, plus BSD stuff
+# omf           Build .lib and .obj files from .a and .o files
+# trace		Build .tdf and .tff files	     emxlibc?.tdf trc00??.tff
+# clean         Remove files created in the build process
+# cleanall      Remove target files and files created in the build process
+#
+##############################################################################
+
+.IF $(CPU)
+.ELSE
+CPU=386
+.ENDIF
+
+##############################################################################
+
+GCC=gcc -O2 -Wall -mprobe -fstack-check
+ASM=gcc -c -Wall -x assembler-with-cpp
+AR=ar
+I=/emx/include/
+S=$(I)sys/
+E=$(S)emx.h
+L=\emx\lib\ #
+DLL=\emx\dll\ #
+
+##############################################################################
+
+PASSDOWN=CPU=$(CPU) DELOPT=$(DELOPT)
+
+##############################################################################
+
+.SUFFIXES: .a .lib
+
+.a.lib:
+	emxomf -sl $<
+
+.PHONY: all-dos all-os2 all-bsd all-dos-bsd all-os2-bsd clean cleanall \
+        default emx_386 libgcc libgcc-p c_static c_alias \
+        c-st c-st-p c-mt c_app-st c_app-st-p c_app-mt c_dllrt-st c_dllrt-mt \
+        c_dllso-st c_dllso-mt c_import-st c_import-mt c_dllnrt \
+        socket tmalloc end graph os2_386 os2_386-p sys video moddef \
+	omflib emxwrap trace \
+        malloc1-st malloc1-mt mkdir mkdir-cpu \
+        omf dll-int o-crt o-crt-bsd o-opt obj-crt obj-opt recurse os2 os2-p \
+        rec-all rec-c rec-app rec-conv rec-ctype rec-emx_386 \
+        rec-emxload rec-gcc rec-graph rec-io rec-cdll rec-malloc rec-math \
+        rec-misc rec-moddef rec-nls rec-os2_386 rec-process rec-socket \
+        rec-startup rec-str rec-sys rec-termios rec-time rec-tmalloc \
+        rec-video rec-locale rec-mbyte rec-omflib rec-end rec-malloc1
+
+
+
+##############################################################################
+
+default .SEQUENTIAL: all-os2-bsd trace
+
+os2: os2_$(CPU)
+
+os2-p: os2_$(CPU)-p
+
+all-dos .SEQUENTIAL: o-crt o-opt c-st c_alias c_app-st libgcc os2_$(CPU) \
+    emx_$(CPU) graph video moddef omflib $(L)g.a $(L)m.a c-st-p \
+    c_app-st-p libgcc-p os2_$(CPU)-p malloc1-st
+
+all-os2 .SEQUENTIAL: all-dos c-mt c_app-mt c_dllrt-st c_dllrt-mt \
+    c_dllso-st c_dllso-mt c_import-st c_import-mt c_dllnrt \
+    sys end dll-int emxwrap socket tmalloc malloc1-mt omf
+
+all-dos-bsd .SEQUENTIAL: all-dos o-crt-bsd
+
+all-os2-bsd .SEQUENTIAL: all-os2 o-crt-bsd
+
+omf .SEQUENTIAL: obj-crt obj-opt \
+        $(L)gcc.lib $(L)g.lib $(L)m.lib $(L)c_alias.lib \
+        $(L)st\c.lib $(L)st\c_app.lib $(L)st\c_dllrt.lib $(L)st\emx.lib \
+        $(L)mt\c.lib $(L)mt\c_app.lib $(L)mt\c_dllrt.lib $(L)mt\emx.lib \
+        $(L)os2.lib $(L)emx2.lib $(L)emxio.lib $(L)graph.lib $(L)video.lib \
+        $(L)moddef.lib $(L)tmalloc.lib $(L)omflib.lib $(L)c_static.lib \
+        $(L)socket.lib $(L)st\malloc1.lib $(L)mt\malloc1.lib
+
+o-crt .SETDIR=startup:
+	$(MAKE) o-crt $(PASSDOWN)
+
+o-crt-bsd .SETDIR=startup:
+	$(MAKE) o-crt-bsd $(PASSDOWN)
+
+obj-crt .SETDIR=startup:
+	$(MAKE) obj-crt $(PASSDOWN)
+
+o-opt: $(L)binmode.o $(L)sigsysv.o $(L)sigbsd.o $(L)smallcnv.o
+
+obj-opt: $(L)binmode.obj $(L)sigsysv.obj $(L)sigbsd.obj $(L)smallcnv.obj
+
+clean:
+	$(MAKE) recurse RDIR=all RTARGET=clean $(PASSDOWN)
+
+cleanall .IGNORE: clean
+	del $(L)*.o $(DELOPT)
+	del $(L)*.obj $(DELOPT)
+	del $(L)*.lib $(DELOPT)
+	del $(L)*.a $(DELOPT)
+	del $(L)mt\*.a $(DELOPT)
+	del $(L)mt\*.lib $(DELOPT)
+	del $(L)st\*.a $(DELOPT)
+	del $(L)st\*.lib $(DELOPT)
+
+##############################################################################
+
+recurse: rec-$(RDIR)
+
+RECURSE=$(RTARGET) $(PASSDOWN)
+
+rec-all .SEQUENTIAL: rec-c rec-os2_$(CPU) rec-gcc rec-emx_$(CPU) rec-sys \
+                     rec-alias rec-app rec-cdll rec-dllrt rec-dllso \
+                     rec-dllnrt rec-moddef rec-omflib rec-graph rec-video \
+                     rec-socket rec-static rec-tmalloc rec-end rec-malloc1
+
+rec-c .SEQUENTIAL: rec-conv rec-ctype rec-emxload rec-io \
+                   rec-locale rec-malloc rec-math rec-mbyte rec-misc \
+                   rec-nls rec-process rec-startup rec-str rec-termios \
+                   rec-time
+
+rec-alias .SETDIR=alias:
+	$(MAKE) $(RECURSE)
+
+rec-app .SETDIR=app:
+	$(MAKE) $(RECURSE)
+
+rec-cdll .SETDIR=cdll:
+	$(MAKE) $(RECURSE)
+
+rec-conv .SETDIR=conv:
+	$(MAKE) $(RECURSE)
+
+rec-ctype .SETDIR=ctype:
+	$(MAKE) $(RECURSE)
+
+rec-dllnrt .SETDIR=dllnrt:
+	$(MAKE) $(RECURSE)
+
+rec-dllrt .SETDIR=dllrt:
+	$(MAKE) $(RECURSE)
+
+rec-dllso .SETDIR=dllso:
+	$(MAKE) $(RECURSE)
+
+rec-emx_$(CPU) .SETDIR=emx_$(CPU):
+	$(MAKE) $(RECURSE)
+
+rec-emxload .SETDIR=emxload:
+	$(MAKE) $(RECURSE)
+
+rec-end .SETDIR=end:
+	$(MAKE) $(RECURSE)
+
+rec-gcc .SETDIR=gcc:
+	$(MAKE) $(RECURSE)
+
+rec-graph .SETDIR=graph:
+	$(MAKE) $(RECURSE)
+
+rec-io .SETDIR=io:
+	$(MAKE) $(RECURSE)
+
+rec-locale .SETDIR=locale:
+	$(MAKE) $(RECURSE)
+
+rec-malloc .SETDIR=malloc:
+	$(MAKE) $(RECURSE)
+
+rec-malloc1 .SETDIR=malloc1:
+	$(MAKE) $(RECURSE)
+
+rec-math .SETDIR=math:
+	$(MAKE) $(RECURSE)
+
+rec-mbyte .SETDIR=mbyte:
+	$(MAKE) $(RECURSE)
+
+rec-moddef .SETDIR=moddef:
+	$(MAKE) $(RECURSE)
+
+rec-static .SETDIR=static:
+	$(MAKE) $(RECURSE)
+
+rec-tmalloc .SETDIR=tmalloc:
+	$(MAKE) $(RECURSE)
+
+rec-omflib .SETDIR=omflib:
+	$(MAKE) $(RECURSE)
+
+rec-misc .SETDIR=misc:
+	$(MAKE) $(RECURSE)
+
+rec-nls .SETDIR=nls:
+	$(MAKE) $(RECURSE)
+
+rec-os2_$(CPU) .SETDIR=os2_$(CPU):
+	$(MAKE) $(RECURSE)
+
+rec-process .SETDIR=process:
+	$(MAKE) $(RECURSE)
+
+rec-socket .SETDIR=socket:
+	$(MAKE) $(RECURSE)
+
+rec-startup .SETDIR=startup:
+	$(MAKE) $(RECURSE)
+
+rec-str .SETDIR=str:
+	$(MAKE) $(RECURSE)
+
+rec-sys .SETDIR=sys:
+	$(MAKE) $(RECURSE)
+
+rec-termios .SETDIR=termios:
+	$(MAKE) $(RECURSE)
+
+rec-time .SETDIR=time:
+	$(MAKE) $(RECURSE)
+
+rec-video .SETDIR=video:
+	$(MAKE) $(RECURSE)
+
+##############################################################################
+
+$(L)binmode.o: io/$(CPU)/binmode.s
+	$(ASM) -o $(L)binmode.o io/$(CPU)/binmode.s
+
+$(L)sigsysv.o: process/sigsysv.c $(S)uflags.h
+	$(GCC) -c -o $(L)sigsysv.o process/sigsysv.c
+
+$(L)sigbsd.o: process/sigbsd.c $(S)uflags.h
+	$(GCC) -c -o $(L)sigbsd.o process/sigbsd.c
+
+$(L)smallcnv.o: conv/$(CPU)/smallcnv.s
+	$(ASM) -o $(L)smallcnv.o conv/$(CPU)/smallcnv.s
+
+$(L)binmode.obj: $(L)binmode.o
+	emxomf -sl $(L)binmode.o
+
+$(L)sigbsd.obj: $(L)sigbsd.o
+	emxomf -sl $(L)sigbsd.o
+
+$(L)sigsysv.obj: $(L)sigsysv.o
+	emxomf -sl $(L)sigsysv.o
+
+$(L)smallcnv.obj: $(L)smallcnv.o
+	emxomf -sl $(L)smallcnv.o
+
+$(L)crt0.obj: obj-crt
+$(L)mcrt0.obj: obj-crt
+$(L)dll0.obj: obj-crt
+$(L)res0.obj: obj-crt
+
+##############################################################################
+
+c-st:
+	$(MAKE) recurse RDIR=c RTARGET=lib-st $(PASSDOWN)
+
+c-st-p:
+	$(MAKE) recurse RDIR=c RTARGET=lib-st-p $(PASSDOWN)
+
+c-mt:
+	$(MAKE) recurse RDIR=c RTARGET=lib-mt $(PASSDOWN)
+
+c_alias:
+	$(MAKE) recurse RDIR=alias RTARGET=alias $(PASSDOWN)
+
+c_app-st $(L)st\c_app.a:
+	$(MAKE) recurse RDIR=app RTARGET=lib-st $(PASSDOWN)
+
+c_app-st-p $(L)st\c_app_p.a:
+	$(MAKE) recurse RDIR=app RTARGET=lib-st-p $(PASSDOWN)
+
+c_app-mt $(L)mt\c_app.a:
+	$(MAKE) recurse RDIR=app RTARGET=lib-mt $(PASSDOWN)
+
+c_dllrt-st:
+	$(MAKE) recurse RDIR=dllrt RTARGET=lib-st $(PASSDOWN)
+
+c_dllrt-mt:
+	$(MAKE) recurse RDIR=dllrt RTARGET=lib-mt $(PASSDOWN)
+
+c_dllso-st:
+	$(MAKE) recurse RDIR=dllso RTARGET=lib-st $(PASSDOWN)
+
+c_dllso-mt:
+	$(MAKE) recurse RDIR=dllso RTARGET=lib-mt $(PASSDOWN)
+
+c_import-st: c_static
+	$(MAKE) recurse RDIR=cdll RTARGET=import-st $(PASSDOWN)
+
+c_import-mt: c_static
+	$(MAKE) recurse RDIR=cdll RTARGET=import-mt $(PASSDOWN)
+
+c_dllnrt:
+	$(MAKE) recurse RDIR=dllnrt RTARGET=dllnrt $(PASSDOWN)
+
+c_static:
+	$(MAKE) recurse RDIR=static RTARGET=static $(PASSDOWN)
+
+
+##############################################################################
+
+libgcc .SETDIR=gcc:
+	$(MAKE) libgcc $(PASSDOWN)
+
+libgcc-p .SETDIR=gcc:
+	$(MAKE) libgcc-p $(PASSDOWN)
+
+os2_$(CPU) .SETDIR=os2_$(CPU):
+	$(MAKE) os2 $(PASSDOWN)
+
+os2_$(CPU)-p .SETDIR=os2_$(CPU):
+	$(MAKE) os2-p $(PASSDOWN)
+
+emx_$(CPU) .SETDIR=emx_$(CPU):
+	$(MAKE) emx $(PASSDOWN)
+
+sys .SETDIR=sys:
+	$(MAKE) sys $(PASSDOWN)
+
+graph .SETDIR=graph:
+	$(MAKE) graph $(PASSDOWN)
+
+video .SETDIR=video:
+	$(MAKE) video $(PASSDOWN)
+
+moddef .SETDIR=moddef:
+	$(MAKE) moddef $(PASSDOWN)
+
+tmalloc .SETDIR=tmalloc:
+	$(MAKE) tmalloc $(PASSDOWN)
+
+omflib .SETDIR=omflib:
+	$(MAKE) omflib $(PASSDOWN)
+
+socket .SETDIR=socket:
+	$(MAKE) socket $(PASSDOWN)
+
+end .SETDIR=end:
+	$(MAKE) end $(PASSDOWN)
+
+malloc1-st $(L)st\malloc1.a:
+	$(MAKE) recurse RDIR=malloc1 RTARGET=lib-st $(PASSDOWN)
+
+malloc1-mt $(L)mt\malloc1.a:
+	$(MAKE) recurse RDIR=malloc1 RTARGET=lib-mt $(PASSDOWN)
+
+
+##############################################################################
+
+$(L)g.a:
+	$(AR) rs $(L)g.a
+
+$(L)m.a:
+	$(AR) rs $(L)m.a
+
+##############################################################################
+
+$(L)gcc.lib: $(L)gcc.a
+$(L)st\c.lib: $(L)st\c.a
+$(L)mt\c.lib: $(L)mt\c.a
+$(L)st\c_app.lib: $(L)st\c_app.a
+$(L)mt\c_app.lib: $(L)mt\c_app.a
+$(L)st\c_dllrt.lib: $(L)st\c_dllrt.a
+$(L)mt\c_dllrt.lib: $(L)mt\c_dllrt.a
+$(L)st\emx.lib: $(L)st\emx.a
+$(L)mt\emx.lib: $(L)mt\emx.a
+$(L)st\malloc1.lib: $(L)st\malloc1.a
+$(L)mt\malloc1.lib: $(L)mt\malloc1.a
+$(L)c_alias.lib: $(L)c_alias.a
+$(L)c_static.lib: $(L)c_static.a
+$(L)emx2.lib: $(L)emx2.a
+$(L)emxio.lib: $(L)emxio.a
+$(L)graph.lib: $(L)graph.a
+$(L)video.lib: $(L)video.a
+$(L)moddef.lib: $(L)moddef.a
+$(L)tmalloc.lib: $(L)tmalloc.a
+$(L)omflib.lib: $(L)omflib.a
+$(L)socket.lib: $(L)socket.a
+$(L)os2.lib: $(L)os2.a
+$(L)g.lib: $(L)g.a
+$(L)m.lib: $(L)m.a
+
+##############################################################################
+
+dll-int .SEQUENTIAL: $(L)gcc.lib $(L)os2.lib $(L)dll0.obj \
+    $(L)res0.obj $(L)emx2.lib $(L)c_static.lib $(L)end.lib \
+    $(L)st\c.lib $(L)st\c_dllrt.lib $(L)st\emx.lib \
+    $(L)mt\c.lib $(L)mt\c_dllrt.lib $(L)mt\emx.lib
+	$(MAKE) recurse RDIR=cdll RTARGET=dll-all $(PASSDOWN)
+
+dll-st .SEQUENTIAL: libgcc c-st c_dllrt-st emx_$(CPU) os2_$(CPU) dll-st-int
+
+dll-st-int .SEQUENTIAL: $(L)gcc.lib $(L)emx2.lib $(L)os2.lib $(L)dll0.obj \
+    $(L)st\c.lib $(L)st\c_dllrt.lib $(L)st\emx.lib
+	$(MAKE) recurse RDIR=cdll RTARGET=dll-st $(PASSDOWN)
+
+dll-mt .SEQUENTIAL: libgcc c-mt c_dllrt-mt emx_$(CPU) os2_$(CPU) dll-mt-int
+
+dll-mt-int .SEQUENTIAL: $(L)gcc.lib $(L)emx2.lib $(L)os2.lib $(L)dll0.obj \
+    $(L)mt\c.lib $(L)mt\c_dllrt.lib $(L)mt\emx.lib
+	$(MAKE) recurse RDIR=cdll RTARGET=dll-mt $(PASSDOWN)
+
+dll-fwd .SEQUENTIAL: c_import-mt emx_$(CPU) $(L)c_static.lib dll-fwd-int
+
+dll-fwd-int: $(L)dll0.obj $(L)emx2.lib
+	$(MAKE) recurse RDIR=cdll RTARGET=dll-fwd $(PASSDOWN)
+
+emxwrap .SEQUENTIAL: $(L)res0.obj emxwrap-int
+
+emxwrap-int .SETDIR=os2_$(CPU):
+	$(MAKE) emxwrap $(PASSDOWN)
+
+#
+# Requires trcust.exe of os2pdp.zip
+#
+trace:
+	$(MAKE) recurse RDIR=cdll RTARGET=trace $(PASSDOWN)
+
+##############################################################################
+
+mkdir .IGNORE:
+	mkdir alias\$(CPU)
+	mkdir app\mt_$(CPU)
+	mkdir app\st_$(CPU)
+	mkdir app\st_p_$(CPU)
+	mkdir cdll\$(CPU)
+	mkdir conv\mt_$(CPU)
+	mkdir conv\st_$(CPU)
+	mkdir conv\st_p_$(CPU)
+	mkdir ctype\mt_$(CPU)
+	mkdir ctype\st_$(CPU)
+	mkdir ctype\st_p_$(CPU)
+	mkdir dllnrt\$(CPU)
+	mkdir dllrt\mt_$(CPU)
+	mkdir dllrt\st_$(CPU)
+	mkdir dllso\mt_$(CPU)
+	mkdir dllso\st_$(CPU)
+	mkdir emx_$(CPU)\mt
+	mkdir emx_$(CPU)\st
+	mkdir emxload\mt_$(CPU)
+	mkdir emxload\st_$(CPU)
+	mkdir emxload\st_p_$(CPU)
+	mkdir gcc\st_$(CPU)
+	mkdir gcc\st_p_$(CPU)
+	mkdir graph\$(CPU)
+	mkdir io\mt_$(CPU)
+	mkdir io\st_$(CPU)
+	mkdir io\st_p_$(CPU)
+	mkdir locale\mt_$(CPU)
+	mkdir locale\st_$(CPU)
+	mkdir locale\st_p_$(CPU)
+	mkdir malloc\mt_$(CPU)
+	mkdir malloc\st_$(CPU)
+	mkdir malloc\st_p_$(CPU)
+	mkdir malloc1\mt_$(CPU)
+	mkdir malloc1\st_$(CPU)
+	mkdir math\mt_$(CPU)
+	mkdir math\st_$(CPU)
+	mkdir math\st_p_$(CPU)
+	mkdir mbyte\mt_$(CPU)
+	mkdir mbyte\st_$(CPU)
+	mkdir mbyte\st_p_$(CPU)
+	mkdir misc\mt_$(CPU)
+	mkdir misc\st_$(CPU)
+	mkdir misc\st_p_$(CPU)
+	mkdir moddef\$(CPU)
+	mkdir nls\mt_$(CPU)
+	mkdir nls\st_$(CPU)
+	mkdir nls\st_p_$(CPU)
+	mkdir omflib\$(CPU)
+	mkdir os2_$(CPU)\st
+	mkdir os2_$(CPU)\st_p
+	mkdir process\mt_$(CPU)
+	mkdir process\st_$(CPU)
+	mkdir process\st_p_$(CPU)
+	mkdir socket\$(CPU)
+	mkdir startup\mt_$(CPU)
+	mkdir startup\st_$(CPU)
+	mkdir startup\st_p_$(CPU)
+	mkdir static\$(CPU)
+	mkdir str\mt_$(CPU)
+	mkdir str\st_$(CPU)
+	mkdir str\st_p_$(CPU)
+	mkdir sys\mt_$(CPU)
+	mkdir sys\st_$(CPU)
+	mkdir termios\mt_$(CPU)
+	mkdir termios\st_$(CPU)
+	mkdir termios\st_p_$(CPU)
+	mkdir time\mt_$(CPU)
+	mkdir time\st_$(CPU)
+	mkdir time\st_p_$(CPU)
+	mkdir tmalloc\$(CPU)
+	mkdir video\$(CPU)
Index: trunk/src/emx/src/lib/malloc/calloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/calloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/calloc.c	(revision 18)
@@ -0,0 +1,19 @@
+/* calloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+void *calloc (size_t count, size_t size)
+{
+  _UM_MT_DECL
+
+  if (_UM_DEFAULT_REGULAR_HEAP == NULL)
+    _um_init_default_regular_heap ();
+  return _ucalloc (_UM_DEFAULT_REGULAR_HEAP, count, size);
+}
Index: trunk/src/emx/src/lib/malloc/defalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/defalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/defalloc.c	(revision 18)
@@ -0,0 +1,76 @@
+/* defalloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <ulimit.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void *_um_default_alloc (Heap_t h, size_t *size, int *clean)
+{
+  void *p;
+  size_t n;
+  int saved_errno;
+  long rest;
+
+  /* Round to the next multiple of 64K. */
+
+  n = (*size + 0xffff) & ~0xffff;
+
+  /* If there aren't enough bytes left in the current heap object, add
+     the rest of the current heap object to the heap.  _heap_expand()
+     will call us again.  Save errno in case UL_OBJREST isn't
+     implemented.  Let's hope that no other thread calls sbrk() while
+     we do all this work.  (Due to locking of the heap, this can only
+     happen by a direct call to sbrk().) */
+
+  saved_errno = errno;
+  rest = _ulimit (UL_OBJREST, 0); /* The 2nd arg isn't required */
+  errno = saved_errno;
+  if (rest != -1 && rest != 0 && n > (size_t)rest)
+    {
+      if (*size <= (size_t)rest)
+        {
+          /* We can allocate enough memory if we don't round the size.
+             So don't round.  Note that this usually does not happen
+             as the increment is rounded to a multiple of 64K (see
+             above) and the break value is usually a multiple of 64K.
+             The break value is usually a multiple of 64K because
+             _INITIAL_DEFAULT_HEAP_SIZE is a multiple of 64K and the
+             increment is rounded to a multiple of 64K (see above).
+             However, someone else might call sbrk() with an increment
+             which is not a multiple of 64K. */
+
+          n = *size;
+        }
+      else
+        {
+          /* sbrk() will start a new heap object if non-contiguous
+             memory allocation is implemented.  Add the rest of the
+             current heap object to the heap and postpone the
+             requested memory allocation to the next call. */
+
+          p = _sbrk ((int)rest);
+          if (p == (void *)-1)
+            return NULL;
+          *size = (size_t)rest; *clean = !_BLOCK_CLEAN;
+          return p;
+        }
+    }
+
+  /* Allocate memory. */
+
+  p = _sbrk (n);
+  if (p == (void *)-1)
+    {
+      n = *size;
+      p = _sbrk (n);
+      if (p == (void *)-1)
+        return NULL;
+    }
+  *size = n; *clean = !_BLOCK_CLEAN;
+  return p;
+}
Index: trunk/src/emx/src/lib/malloc/defexpan.c
===================================================================
--- trunk/src/emx/src/lib/malloc/defexpan.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/defexpan.c	(revision 18)
@@ -0,0 +1,35 @@
+/* defexpan.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+int _um_default_expand (Heap_t h, void *base, size_t old_size,
+                        size_t *new_size, int *clean)
+{
+  void *p;
+  size_t n;
+
+  if (_UM_ADD (base, old_size) != _sbrk (0))
+    return 0;
+  n = (*new_size - old_size + 0xffff) & ~0xffff;
+  p = _sbrk (n);
+  if (p == (void *)-1)
+    {
+      n = *new_size - old_size;
+      p = _sbrk (n);
+      if (p == (void *)-1)
+        return 0;
+    }
+  if (p != _UM_ADD (base, old_size))
+    {
+      _sbrk (-n);
+      return 0;
+    }
+  *new_size = old_size + n; *clean = !_BLOCK_CLEAN;
+  return 1;
+}
Index: trunk/src/emx/src/lib/malloc/defrelea.c
===================================================================
--- trunk/src/emx/src/lib/malloc/defrelea.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/defrelea.c	(revision 18)
@@ -0,0 +1,18 @@
+/* defrelea.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void _um_default_release (Heap_t h, void *memory, size_t size)
+{
+  void *cur;
+
+  cur = _sbrk (0);
+  if (_UM_ADD (memory, size) == cur)
+    _sbrk (-size);
+}
Index: trunk/src/emx/src/lib/malloc/defshrin.c
===================================================================
--- trunk/src/emx/src/lib/malloc/defshrin.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/defshrin.c	(revision 18)
@@ -0,0 +1,20 @@
+/* defshrink.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void _um_default_shrink (Heap_t h, void *memory, size_t old_size,
+                         size_t *new_size)
+{
+  void *cur;
+
+  cur = _sbrk (0);
+  if (_UM_ADD (memory, old_size) != cur
+      || _sbrk ((int)(*new_size - old_size)) == (void *)-1)
+    *new_size = old_size;
+}
Index: trunk/src/emx/src/lib/malloc/expand.c
===================================================================
--- trunk/src/emx/src/lib/malloc/expand.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/expand.c	(revision 18)
@@ -0,0 +1,14 @@
+/* expand.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void *_expand (void *block, size_t new_size)
+{
+  return _um_realloc (block, new_size, 4, _UMFI_NOMOVE);
+}
Index: trunk/src/emx/src/lib/malloc/free.c
===================================================================
--- trunk/src/emx/src/lib/malloc/free.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/free.c	(revision 18)
@@ -0,0 +1,14 @@
+/* free.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void free (void *block)
+{
+  _um_free_maybe_lock (block, 1);
+}
Index: trunk/src/emx/src/lib/malloc/heapchk.c
===================================================================
--- trunk/src/emx/src/lib/malloc/heapchk.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/heapchk.c	(revision 18)
@@ -0,0 +1,45 @@
+/* heapchk.c (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+int _heapchk (void)
+{
+  _UM_MT_DECL
+  int rc1, rc2;
+
+  /* Initialize the heap pointers, in case _heapchk() is called by a
+     new thread before malloc(). */
+
+  if (_UM_DEFAULT_REGULAR_HEAP == NULL)
+    _um_init_default_regular_heap ();
+  if (_UM_DEFAULT_TILED_HEAP == NULL)
+    _um_init_default_tiled_heap ();
+
+  /* First check the regular heap. */
+
+  rc1 = _uheapchk (_UM_DEFAULT_REGULAR_HEAP);
+  if (rc1 != _HEAPOK && rc1 != _HEAPEMPTY)
+    return rc1;
+
+  /* If there's no tiled heap or if it's identical to the regular
+     heap, return the regular heap's status. */
+
+  if (_UM_DEFAULT_REGULAR_HEAP == _UM_DEFAULT_TILED_HEAP
+      || _UM_DEFAULT_TILED_HEAP == NULL)
+    return rc1;
+
+  /* Check the tiled heap.  Do not return _HEAPEMPTY if any of the two
+     heaps is non-empty. */
+
+  rc2 = _uheapchk (_UM_DEFAULT_TILED_HEAP);
+  if (rc2 == _HEAPEMPTY)
+    return rc1;
+  return rc2;
+}
Index: trunk/src/emx/src/lib/malloc/heapmin.c
===================================================================
--- trunk/src/emx/src/lib/malloc/heapmin.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/heapmin.c	(revision 18)
@@ -0,0 +1,19 @@
+/* heapmin.c (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+int _heapmin (void)
+{
+  _UM_MT_DECL
+
+  if (_UM_DEFAULT_REGULAR_HEAP == NULL)
+    _um_init_default_regular_heap ();
+  return _uheapmin (_UM_DEFAULT_REGULAR_HEAP);
+}
Index: trunk/src/emx/src/lib/malloc/heapset.c
===================================================================
--- trunk/src/emx/src/lib/malloc/heapset.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/heapset.c	(revision 18)
@@ -0,0 +1,45 @@
+/* heapset.c (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+int _heapset (unsigned fill)
+{
+  _UM_MT_DECL
+  int rc1, rc2;
+
+  /* Initialize the heap pointers, in case _heapset() is called by a
+     new thread before malloc(). */
+
+  if (_UM_DEFAULT_REGULAR_HEAP == NULL)
+    _um_init_default_regular_heap ();
+  if (_UM_DEFAULT_TILED_HEAP == NULL)
+    _um_init_default_tiled_heap ();
+
+  /* First fill the regular heap. */
+
+  rc1 = _uheapset (_UM_DEFAULT_REGULAR_HEAP, fill);
+  if (rc1 != _HEAPOK && rc1 != _HEAPEMPTY)
+    return rc1;
+
+  /* If there's no tiled heap or if it's identical to the regular
+     heap, return the regular heap's status. */
+
+  if (_UM_DEFAULT_REGULAR_HEAP == _UM_DEFAULT_TILED_HEAP
+      || _UM_DEFAULT_TILED_HEAP == NULL)
+    return rc1;
+
+  /* Fill the tiled heap.  Do not return _HEAPEMPTY if any of the two
+     heaps is non-empty. */
+
+  rc2 = _uheapset (_UM_DEFAULT_TILED_HEAP, fill);
+  if (rc2 == _HEAPEMPTY)
+    return rc1;
+  return rc2;
+}
Index: trunk/src/emx/src/lib/malloc/heapwalk.c
===================================================================
--- trunk/src/emx/src/lib/malloc/heapwalk.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/heapwalk.c	(revision 18)
@@ -0,0 +1,41 @@
+/* heapwalk.c (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+int _heap_walk (_um_callback1 *callback)
+{
+  _UM_MT_DECL
+  int rc;
+
+  /* Initialize the heap pointers, in case _heap_walk() is called by a
+     new thread before malloc(). */
+
+  if (_UM_DEFAULT_REGULAR_HEAP == NULL)
+    _um_init_default_regular_heap ();
+  if (_UM_DEFAULT_TILED_HEAP == NULL)
+    _um_init_default_tiled_heap ();
+
+  /* First walk through the regular heap. */
+
+  rc = _uheap_walk (_UM_DEFAULT_REGULAR_HEAP, callback);
+  if (rc != 0)
+    return rc;
+
+  /* If there's no tiled heap or if it's identical to the regular
+     heap, return the regular heap's status. */
+
+  if (_UM_DEFAULT_REGULAR_HEAP == _UM_DEFAULT_TILED_HEAP
+      || _UM_DEFAULT_TILED_HEAP == NULL)
+    return rc;
+
+  /* Walk through the tiled heap. */
+
+  return _uheap_walk (_UM_DEFAULT_TILED_HEAP, callback);
+}
Index: trunk/src/emx/src/lib/malloc/iaddmem.c
===================================================================
--- trunk/src/emx/src/lib/malloc/iaddmem.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/iaddmem.c	(revision 18)
@@ -0,0 +1,157 @@
+/* iaddmem.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+Heap_t _um_seg_addmem (Heap_t h, struct _um_seg *seg, void *memory,
+                       size_t size)
+{
+  struct _um_lump *lump;
+  size_t asize, osize;
+
+  assert (_UM_ADD (seg->mem, seg->size) == memory);
+
+  /* Expand the segment SEG by adding free space at the end.  First,
+     compute the new number of bytes available at START.  Drop the
+     partial page at the end, if there is any. */
+
+  asize = (char *)seg->mem + seg->size + size - (char *)seg->start;
+  asize &= ~(_UM_PAGE_SIZE-1);
+
+  /* Compute the old size of the segment's pages. */
+
+  osize = (char *)seg->end - (char *)seg->start;
+
+  /* Incorporate the new memory as free space into the heap if it adds
+     at least one page. */
+
+  if (asize > osize)
+    {
+      lump = _UM_PREV_LUMP ((struct _um_lump *)seg->end);
+      if (_UM_LUMP_STATUS (lump) == _UMS_FREE)
+        {
+          /* Coalesce the last free lump of the segment with the new
+             memory.  This is done here instead of relying on
+             _um_lump_coalesce_free() because the segment is not in a
+             consistent state. */
+
+          _um_lump_unlink_heap (h, lump);
+          _um_lump_set_size (lump, (_UM_ROUND_LUMP (lump->size) + asize - osize
+                                    - _UM_LUMP_OVERHEAD));
+          _um_lump_link_heap (h, lump);
+        }
+      else
+        {
+          /* The last lump of the segment is used.  Add a free lump at
+             the end of the segment.  Don't attempt to coalesce
+             because the segment is not in a consistent state. */
+
+          _um_lump_make_free (h, (struct _um_lump *)_UM_ADD (seg->start,
+                                                             osize),
+                              seg, asize - osize);
+        }
+
+      /* Adjust the segment control structure. */
+
+      seg->end = _UM_ADD (seg->start, asize);
+      /* TODO: zero_limit */
+    }
+
+  /* Update SIZE anyway.  This avoids calling _um_seg_addmem() over
+     and over from _um_lump_expand_seg(). */
+
+  seg->size += size;
+  return h;
+}
+
+
+Heap_t _um_seg_setmem (Heap_t h, struct _um_seg *seg, void *memory,
+                       size_t size, int clean)
+{
+  char *start, *mem_end;
+  unsigned long diff;
+  size_t asize;
+
+  seg->size = size;
+  seg->mem = memory;
+
+  /* Align START+_UM_LUMP_HEADER_SIZE on a _UM_PAGE_SIZE boundary. */
+
+  start = _UM_ADD (seg, sizeof (struct _um_seg));
+  diff = _UM_ALIGN_DIFF (start + _UM_LUMP_HEADER_SIZE, _UM_PAGE_SIZE);
+  start += diff;
+  assert (_UM_IS_ALIGNED (start + _UM_LUMP_HEADER_SIZE, _UM_PAGE_SIZE));
+
+  /* Compute the number of bytes available at START.  Drop the partial
+     page at the end, if there is any. */
+
+  mem_end = (char *)_UM_ADD (seg->mem, seg->size);
+  if (start > mem_end)
+    return NULL;
+  asize = mem_end - start;
+  asize &= ~(_UM_PAGE_SIZE-1);
+  if (asize == 0)
+    return NULL;
+
+  seg->start = (void *)start;
+  seg->end = (void *)(start + asize);
+  seg->zero_limit = clean ? seg->start : seg->end;
+
+  _um_lump_make_free (h, (struct _um_lump *)start, seg, asize);
+  return h;
+}
+
+
+Heap_t _um_addmem_nolock (Heap_t h, void *memory, size_t size, int clean)
+{
+  struct _um_seg *seg;
+  unsigned long diff;
+
+  /* First check if an existing segment is to be expanded
+     contiguously.  This is very important in order to avoid splitting
+     the heap into a lot of segments if sbrk() is used by
+     alloc_fun(). */
+
+  for (seg = h->seg_head; seg != NULL; seg = seg->next)
+    if (_UM_ADD (seg->mem, seg->size) == memory)
+      break;
+
+  if (seg != NULL)
+    return _um_seg_addmem (h, seg, memory, size);
+
+  /* _UM_PARENT_ALIGN is the minimum alignment.  Add one to be able to
+     allocate at least a one-byte block.  Add another page for
+     alignment (well, mis-alignment) of the pages. */
+
+  if (size < (sizeof (struct _um_seg) + _UM_ROUND_LUMP (_UM_PARENT_ALIGN)
+              + _UM_PAGE_SIZE))
+    return NULL;
+
+  /* Align SEG to make the low bits of the address available for
+     _UMF_MASK. */
+
+  diff = _UM_ALIGN_DIFF (memory, _UM_PARENT_ALIGN);
+  seg = (struct _um_seg *)_UM_ADD (memory, diff);
+  assert (((unsigned long)seg & _UMF_MASK) == 0);
+
+  /* Create a segment. */
+
+  if (_um_seg_setmem (h, seg, memory, size, clean) != h)
+    return NULL;
+
+  /* Add the segment to the heap. */
+
+  seg->parent_heap = h;
+  seg->next = h->seg_head;
+  h->seg_head = seg;
+  h->n_segments += 1;
+
+  seg->magic = _UM_MAGIC_SEG;
+  return h;
+}
Index: trunk/src/emx/src/lib/malloc/ialloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/ialloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/ialloc.c	(revision 18)
@@ -0,0 +1,369 @@
+/* ialloc.c (emx+gcc) -- Copyright (c) 1996-1999 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+/* ALIGN must be a power of two. */
+
+void *_um_crumb_alloc (struct _um_crateset *crateset, size_t size,
+                       size_t align, unsigned flags)
+{
+  void *result;
+  struct _um_crumb *crumb;
+  struct _um_crate *crate;
+
+  crumb = crateset->crumb_head;
+  while (crumb != NULL)
+    {
+      crate = _PTR_FROM_UMINT (crumb->x.free.parent_crate, struct _um_crate);
+
+      assert (_UM_CRUMB_STATUS (crumb) == _UMS_FREE);
+      assert (crate->magic == _UM_MAGIC_CRATE);
+      assert (crate->parent_crateset == crateset);
+      assert (crate->used < crate->max);
+
+      result = _UM_BLOCK_FROM_CRUMB (crumb);
+      if (_UM_IS_ALIGNED (result, align)
+          && (!(flags & _UMFI_TILED) || _UM_TILE_OK (result, size)))
+        {
+          _um_crumb_unlink (crateset, crumb);
+          crate->used += 1;
+          _UM_CRUMB_SET_STATUS (crumb, _UMS_USER);
+          crumb->x.used.size = size;
+          if (flags & _UMFI_ZERO)
+            memset (result, 0, size);
+          return result;
+        }
+
+      /* Move to the next crumb of the list. */
+
+      crumb = crumb->x.free.next;
+    }
+
+  /* No (suitable) free crumb found in the free list.  Allocate from
+     the most recently allocated crate. The most recently allocated
+     crate is at the head of the list (ie, it's pointed to by
+     crateset->crate_head).  The most recently allocated crate is the
+     only one which has crate->init < crate->max. */
+
+  crate = crateset->crate_head;
+  if (crate == NULL || crate->init >= crate->max)
+    return NULL;
+
+  crumb = _UM_CRUMB_BY_INDEX (crate, crate->init);
+  result = _UM_BLOCK_FROM_CRUMB (crumb);
+  if (_UM_IS_ALIGNED (result, align)
+      && (!(flags & _UMFI_TILED) || _UM_TILE_OK (result, size)))
+    {
+      assert (_UM_IS_ALIGNED (crate, _UM_PARENT_ALIGN));
+      crumb->x.used.parent_crate = _UMINT_FROM_PTR (crate) | _UMS_USER;
+      crumb->x.used.size = size;
+      crate->init += 1;
+      crate->used += 1;
+      if (flags & _UMFI_ZERO)    /* TODO: Not always required */
+        memset (result, 0, size);
+      return result;
+    }
+
+  /* Well, we could try the next crumb.  However, it's simpler to
+     allocate a lump. */
+
+  return NULL;
+}
+
+
+/* Attempt to allocate a lump without expanding the heap. */
+
+static void *_um_lump_alloc_noexpand (Heap_t h, size_t size, size_t align,
+                                      unsigned flags)
+{
+  int bucket_number;
+  struct _um_lump *olump, *ulump, *slack;
+  size_t rsize, osize, diff;
+  void *block;
+  struct _um_seg *seg;
+
+  /* Set RSIZE to the rounded size of the lump. */
+
+  rsize = _UM_ROUND_LUMP (size);
+  if (rsize >= _UM_MAX_SIZE)
+    return NULL;
+
+  /* Find the smallest bucket for that lump size (`small' with respect
+     to the size of the lumps, not to the number of the free lumps in
+     that bucket).  There can't be a suitable free lump in any smaller
+     bucket. */
+
+  bucket_number = _um_find_bucket (rsize);
+
+  /* Try all the lumps of the smallest bucket.  If this fails, try the
+     next bigger bucket, and so on. */
+
+  while (bucket_number < _UM_BUCKETS)
+    {
+      /* Examine all lumps of the current bucket. */
+
+      for (olump = h->buckets[bucket_number].head;
+           olump != NULL; olump = olump->x.free.next)
+        {
+          assert (_UM_LUMP_STATUS (olump) == _UMS_FREE);
+
+          /* Compute the rounded size of the current lump; try the
+             next lump if it's too small. */
+
+          osize = _UM_ROUND_LUMP (olump->size);
+          if (osize < rsize)
+            continue;
+
+          /* Reject this lump if it's not big enough to obtain the
+             requested alignment. */
+
+          block = _UM_BLOCK_FROM_LUMP (olump);
+          diff = _UM_ALIGN_DIFF (block, align);
+          assert (diff % _UM_PAGE_SIZE == 0);
+          if (osize < diff + rsize)
+            continue;
+
+          /* Align the block as requested.  This may leave a free lump
+             of DIFF bytes preceding the block. */
+
+          block = _UM_ADD (block, diff);
+          assert (_UM_IS_ALIGNED (block, align));
+
+          /* If tiling is requested, realign the block again if
+             required.  Reject this lump if it's not big enough to
+             obtain proper alignment for tiling or if its address is
+             too high for tiling.  Update DIFF and BLOCK. */
+
+          if (flags & _UMFI_TILED)
+            {
+              if (!_UM_TILE_TILED (block, size))
+                continue;
+              if (!_UM_TILE_ALIGNED (block, size))
+                {
+                  diff += _UM_ALIGN_DIFF (block, 0x10000);
+                  if (osize < diff + rsize)
+                    continue;
+                  block = _UM_ADD (_UM_BLOCK_FROM_LUMP (olump), diff);
+                  if (!_UM_TILE_TILED (block, size))
+                    continue;
+                }
+              assert (_UM_TILE_OK (block, size));
+            }
+    
+          /* Remove the lump from the free list. */
+
+          _um_lump_unlink_bucket (&h->buckets[bucket_number], olump);
+
+          /* Initialize the lump.  ULUMP points to the aligned
+             lump. */
+
+          seg = _PTR_FROM_UMINT (olump->parent_seg, struct _um_seg);
+          ulump = _UM_ADD (olump, diff);
+          assert (_UM_IS_ALIGNED (seg, _UM_PARENT_ALIGN));
+          ulump->parent_seg = _UMINT_FROM_PTR (seg) | _UMS_USER;
+          if (flags & _UMFI_CRATE)
+            _UM_LUMP_SET_STATUS (ulump, _UMS_CRATE);
+          _um_lump_set_size (ulump, size);
+
+          /* If the lump is bigger than required, add the slack to the
+             appropriate free list.  There's no need to coalesce with
+             other free blocks as the slack is part of a (previously)
+             free lump which cannot have neighboring fre lumps. */
+
+          if (osize > diff + rsize)
+            {
+              assert ((osize - rsize) % _UM_PAGE_SIZE == 0);
+              slack = (struct _um_lump *)_UM_ADD (olump, diff + rsize);
+              _um_lump_make_free (h, slack, seg, osize - (diff + rsize));
+            }
+
+          /* If padding was inserted before the block for alignment
+             and/or tiling, add the padding to the free list.  There's
+             no need to coalesce with other free blocks as the slack
+             is part of a (previously) free lump which cannot have
+             neighboring fre lumps. */
+
+          if (diff > 0)
+            {
+              assert (diff % _UM_PAGE_SIZE == 0);
+              _um_lump_make_free (h, olump, seg, diff);
+            }
+
+          if (flags & _UMFI_ZERO) /* TODO: Not always required */
+            memset (block, 0, size);
+
+          return block;
+        }
+      ++bucket_number;
+    }
+
+  /* All suitable buckets searched, in vain.  Fail. */
+
+  return NULL;
+}
+
+
+/* Call ALLOC_FUN to add SIZE bytes to the heap.  Return -1 on error,
+   0 if ALLOC_FUN allocated less than SIZE bytes, or 1 if ALLOC_FUN
+   allocated SIZE bytes or more. */
+
+static int _um_heap_expand2 (Heap_t h, size_t size)
+{
+  void *memory;
+  size_t mem_size, shrink_size;
+  int clean;
+
+  mem_size = size; clean = !_BLOCK_CLEAN;
+  memory = h->alloc_fun (h, &mem_size, &clean);
+  if (memory == NULL)
+    return -1;
+
+  if (_um_addmem_nolock (h, memory, mem_size, clean) != h)
+    {
+      /* _um_addmem_nolock() failed -- give back the memory. */
+
+      if (h->release_fun != NULL)
+        h->release_fun (h, memory, mem_size);
+      else if (h->shrink_fun != NULL)
+        {
+          shrink_size = 0;
+          h->shrink_fun (h, memory, mem_size, &shrink_size);
+        }
+      return -1;
+    }
+
+  return mem_size < size ? 0 : 1;
+}
+
+
+/* Attempt to expand the heap to enable allocation of a lump of SIZE
+   bytes.  Return true iff successful. */
+
+static int _um_heap_expand (Heap_t h, size_t size)
+{
+  size_t rsize, add_size;
+  int r;
+
+  /* Can't expand a fixed-size heap, ie, a heap which doesn't have an
+     ALLOC_FUN. */
+
+  if (h->alloc_fun == NULL)
+    return 0;
+
+  rsize = _UM_ROUND_LUMP (size);
+  if (rsize >= _UM_MAX_SIZE)
+    return 0;
+  add_size = rsize + _HEAP_MIN_SIZE;
+
+  r = _um_heap_expand2 (h, add_size);
+  if (r == 0)
+    {
+      /* ALLOC_FUN may allocate less memory than requested to avoid
+         wasting the rest of a heap object.  Therefore we call
+         ALLOC_FUN again if it did not allocate enough memory.  Note
+         that we have to request the same amount of memory as in the
+         first attempt!  Otherwise the ADD_SIZE bytes might be split
+         in two heap objects. */
+
+      r = _um_heap_expand2 (h, add_size);
+    }
+  return r > 0;
+}
+
+
+/* Allocate a lump, possibly expanding the heap to satisfy the
+   allocation request. */
+
+void *_um_lump_alloc (Heap_t h, size_t size, size_t align, unsigned flags)
+{
+  void *block;
+
+  if (_UM_ROUND_LUMP (size) < size)
+    return NULL;                /* Overflow */
+  block = _um_lump_alloc_noexpand (h, size, align, flags);
+  if (block != NULL)
+    return block;
+  if (!_um_heap_expand (h, size))
+    return NULL;
+
+  /* This should succeed -- note that the heap is locked.  Failure
+     indicates an internal error or heap corruption. */
+
+  return _um_lump_alloc_noexpand (h, size, align, flags);
+}
+
+
+static void *_um_crateset_alloc (Heap_t h, struct _um_crateset *crateset,
+                                 size_t size, size_t align, unsigned flags)
+{
+  struct _um_crate *crate;
+  size_t crate_size;
+  void *block;
+  int n;
+
+  block = _um_crumb_alloc (crateset, size, align, flags);
+  if (block != NULL)
+    return block;
+
+  /* Don't add a new crate if allocation failed due to alignment
+     requirements. */
+
+  if (crateset->crumb_head == NULL &&
+      (crateset->crate_head == NULL
+       || crateset->crate_head->init >= crateset->crate_head->max))
+    {
+      n = _UM_MAX_CRATE_SIZE / (crateset->crumb_size + _UM_CRUMB_OVERHEAD);
+      crate_size = (sizeof (struct _um_crate)
+                    + n * (crateset->crumb_size + _UM_CRUMB_OVERHEAD));
+      crate = _um_lump_alloc (h, crate_size, _UM_PARENT_ALIGN, _UMFI_CRATE);
+      if (crate != NULL)
+        {
+          crate->magic = _UM_MAGIC_CRATE;
+          crate->parent_crateset = crateset;
+          crate->parent_heap = h;
+          crate->crumb_size = crateset->crumb_size;
+          crate->max = n;
+          crate->init = 0;
+          crate->used = 0;
+          crate->next = crateset->crate_head;
+          crateset->crate_head = crate;
+
+          /* Update the heap's number of crates and maximum number of
+             crumbs. */
+
+          h->n_crates += 1;
+          h->max_crumbs += n;
+
+          /* Try again to allocate a crumb. */
+
+          return _um_crumb_alloc (crateset, size, align, flags);
+        }
+    }
+  return NULL;
+}
+
+
+void *_um_alloc_no_lock (Heap_t h, size_t size, size_t align, unsigned flags)
+{
+  int i;
+  void *block;
+
+  if (h->n_cratesets > 0 && size <= h->cratesets[h->n_cratesets-1].crumb_size)
+    {
+      i = 0;
+      while (size > h->cratesets[i].crumb_size)
+        ++i;
+      block = _um_crateset_alloc (h, &h->cratesets[i], size, align, flags);
+      if (block != NULL)
+        return block;
+    }
+  return _um_lump_alloc (h, size, align, flags);
+}
Index: trunk/src/emx/src/lib/malloc/ifree.c
===================================================================
--- trunk/src/emx/src/lib/malloc/ifree.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/ifree.c	(revision 18)
@@ -0,0 +1,139 @@
+/* ifree.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+static void _um_crate_free (struct _um_crateset *crateset,
+                            struct _um_crate *crate)
+{
+  struct _um_crumb *crumb;
+  struct _um_crate **patch;
+  int i;
+
+  /* Update the heap's number of crates and maximum number of
+     crumbs. */
+
+  crate->parent_heap->n_crates -= 1;
+  crate->parent_heap->max_crumbs -= crate->max;
+
+  /* Remove all the initialized crumbs of the crate from the free list. */
+
+  for (i = 0; i < crate->init; ++i)
+    {
+      crumb = _UM_CRUMB_BY_INDEX (crate, i);
+      assert (_UM_CRUMB_STATUS (crumb) == _UMS_FREE);
+      assert (_PTR_FROM_UMINT (crumb->x.free.parent_crate, struct _um_crate) == crate);
+      _um_crumb_unlink (crateset, crumb);
+    }
+
+  /* Remove the crate from the list of crates. */
+
+  for (patch = &crateset->crate_head; *patch != NULL; patch = &(*patch)->next)
+    if (*patch == crate)
+      break;
+  if (*patch == NULL)
+    abort ();
+  *patch = crate->next;
+
+  /* Deallocate the crate. */
+
+  _um_free_maybe_lock (crate, 0);
+}
+
+
+void _um_crumb_free_maybe_lock (struct _um_crate *crate,
+                                struct _um_crumb *crumb, int lock)
+{
+  struct _um_crateset *crateset;
+
+  crateset = crate->parent_crateset;
+  if (lock)
+    _um_heap_lock (crate->parent_heap);
+
+  assert (_UM_CRUMB_STATUS (crumb) != _UMS_FREE);
+  assert (crateset->crumb_size == crate->crumb_size);
+  assert (crumb->x.used.size <= crate->crumb_size);
+  assert (crate->used != 0);
+
+  /* Insert the crumb at the head of the crateset's free list. */
+
+  crumb->x.free.next = crateset->crumb_head;
+  crumb->x.free.prev = NULL;
+  if (crateset->crumb_head == NULL)
+    crateset->crumb_tail = crumb;
+  else
+    crateset->crumb_head->x.free.prev = crumb;
+  crateset->crumb_head = crumb;
+
+  /* Mark the crumb as free. */
+
+  _UM_CRUMB_SET_STATUS (crumb, _UMS_FREE);
+
+  /* Set the crumb's size to the maximum value.  This is used by
+     _uheapset(). */
+
+  /* Adjust the crate. */
+
+  crate->used -= 1;
+  if (crate->used == 0)
+    {
+      /* The crate is no longer used.  Remove all its initialized
+         crumbs from the free list and deallocate the crate. */
+
+      _um_crate_free (crateset, crate);
+    }
+
+  if (lock)
+    _um_heap_unlock (crate->parent_heap);
+}
+
+
+void _um_lump_free_maybe_lock (struct _um_seg *seg, struct _um_lump *lump,
+                               int lock)
+{
+  Heap_t h;
+
+  h = seg->parent_heap;
+  if (lock)
+    _um_heap_lock (h);
+
+  assert (_UM_LUMP_STATUS (lump) != _UMS_FREE);
+  _um_lump_coalesce_free (h, lump, seg, _UM_ROUND_LUMP (lump->size));
+
+  if (lock)
+    _um_heap_unlock (h);
+}
+
+
+void _um_free_maybe_lock (void *block, int lock)
+{
+  struct _um_hdr *hdr;
+  _umagic *parent;
+
+  if (block == NULL)
+    return;
+
+  hdr = _HDR_FROM_BLOCK (block);
+  if (_UM_HDR_STATUS (hdr) == _UMS_FREE)
+    abort ();
+  parent = _PTR_FROM_UMINT (hdr->parent, _umagic);
+  switch (*parent)
+    {
+    case _UM_MAGIC_CRATE:
+      _um_crumb_free_maybe_lock ((struct _um_crate *)parent,
+                                 _UM_CRUMB_FROM_BLOCK (block), lock);
+      break;
+    case _UM_MAGIC_SEG:
+      _um_lump_free_maybe_lock ((struct _um_seg *)parent,
+                                _UM_LUMP_FROM_BLOCK (block), lock);
+      break;
+    default:
+      abort ();
+    }
+}
Index: trunk/src/emx/src/lib/malloc/imisc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/imisc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/imisc.c	(revision 18)
@@ -0,0 +1,163 @@
+/* imisc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+/* Leave FLS undefined if __fls() is not available.  __fls() is
+   similar to ffs(), but finds the last (most significant) bit. */
+
+#define FLS(x)          __fls(x)
+
+
+int _um_find_bucket (size_t rsize)
+{
+  int bucket;
+
+#ifdef FLS
+  bucket = FLS (rsize) - 1 - _UM_MIN_BUCKET;
+  if (bucket < 0)
+    bucket = 0;
+  else if (bucket >= _UM_BUCKETS)
+    return _UM_BUCKETS - 1;
+  assert (_UM_BUCKET_SIZE (bucket) <= rsize);
+  assert (_UM_BUCKET_SIZE (bucket+1) > rsize);
+  return bucket;
+#else
+  for (bucket = _UM_BUCKETS - 1; bucket >= 0; --bucket)
+    if (_UM_BUCKET_SIZE (bucket) <= rsize)
+      return bucket;
+  abort ();                     /* RSIZE is probably not rounded! */
+#endif
+}
+
+
+static __inline__ void _um_lump_link_bucket (struct _um_bucket *bucket,
+                                             struct _um_lump *lump)
+{
+  lump->x.free.prev = NULL;
+  if (bucket->head != NULL)
+    bucket->head->x.free.prev = lump;
+  else
+    bucket->tail = lump;
+  lump->x.free.next = bucket->head;
+  bucket->head = lump;
+}
+
+
+void _um_lump_unlink_bucket (struct _um_bucket *bucket, struct _um_lump *lump)
+{
+  if (lump->x.free.prev == NULL)
+    bucket->head = lump->x.free.next;
+  else
+    lump->x.free.prev->x.free.next = lump->x.free.next;
+  if (lump->x.free.next == NULL)
+    bucket->tail = lump->x.free.prev;
+  else
+    lump->x.free.next->x.free.prev = lump->x.free.prev;
+}
+
+
+void _um_lump_unlink_heap (Heap_t h, struct _um_lump *lump)
+{
+  size_t rsize;
+  int bucket;
+
+  rsize = _UM_ROUND_LUMP (lump->size);
+  bucket = _um_find_bucket (rsize);
+  _um_lump_unlink_bucket (&h->buckets[bucket], lump);
+}
+
+
+void _um_lump_link_heap (Heap_t h, struct _um_lump *lump)
+{
+  size_t rsize;
+  int bucket_number;
+
+  rsize = _UM_ROUND_LUMP (lump->size);
+  bucket_number = _um_find_bucket (rsize);
+  _um_lump_link_bucket (&h->buckets[bucket_number], lump);
+}
+
+
+/* Turn uninitialized memory into a free lump.  RSIZE is the rounded
+   total size, including `struct _um_lump' and the size word at the
+   end.  This function does not coalesce the new lump with neighboring
+   free lumps, therefore the segment need not be in a consistent
+   state. */
+
+void _um_lump_make_free (Heap_t h, struct _um_lump *lump,
+                         struct _um_seg *seg, size_t rsize)
+{
+  int bucket_number;
+
+  assert (_UM_IS_ALIGNED (seg, _UM_PARENT_ALIGN));
+  assert (rsize % _UM_PAGE_SIZE == 0);
+  lump->parent_seg = _UMINT_FROM_PTR (seg) | _UMS_FREE;
+  _um_lump_set_size (lump, rsize - _UM_LUMP_OVERHEAD);
+
+  bucket_number = _um_find_bucket (rsize);
+  _um_lump_link_bucket (&h->buckets[bucket_number], lump);
+}
+
+
+/* Turn uninitialized memory into a free lump.  RSIZE is the rounded
+   total size, including `struct _um_lump' and the size word at the
+   end.  This function attempts to coalesce the new lump with
+   neighboring free lumps.  Note that the segment must be in a
+   consistent state (except for the free lump to be created). */
+
+void _um_lump_coalesce_free (Heap_t h, struct _um_lump *lump,
+                             struct _um_seg *seg, size_t rsize)
+{
+  assert (_UM_IS_ALIGNED (seg, _UM_PARENT_ALIGN));
+  assert (rsize % _UM_PAGE_SIZE == 0);
+  lump->parent_seg = _UMINT_FROM_PTR (seg) | _UMS_FREE;
+  _um_lump_set_size (lump, rsize - _UM_LUMP_OVERHEAD);
+
+  /* Coalesce with preceding free lump, if possible. */
+
+  if (!_UM_FIRST_LUMP (seg, lump))
+    {
+      struct _um_lump *prev = _UM_PREV_LUMP (lump);
+      if (_UM_LUMP_STATUS (prev) == _UMS_FREE)
+        {
+          _um_lump_unlink_heap (h, prev);
+          assert (_UM_IS_ALIGNED (seg, _UM_PARENT_ALIGN));
+          prev->parent_seg = _UMINT_FROM_PTR (seg) | _UMS_FREE;
+
+          /* It's important to round at least one of the sizes,
+             otherwise the sum might become too short. */
+
+          _um_lump_set_size (prev, (_UM_ROUND_LUMP (lump->size)
+                                    + _UM_ROUND_LUMP (prev->size)
+                                    - _UM_LUMP_OVERHEAD));
+          lump = prev;
+        }
+    }
+
+  /* Coalesce with succeeding free lump, if possible. */
+
+  if (!_UM_LAST_LUMP (seg, lump))
+    {
+      struct _um_lump *next = _UM_NEXT_LUMP (lump);
+      if (_UM_LUMP_STATUS (next) == _UMS_FREE)
+        {
+          _um_lump_unlink_heap (h, next);
+
+          /* It's important to round at least one of the sizes,
+             otherwise the sum might become too short. */
+
+          _um_lump_set_size (lump, (_UM_ROUND_LUMP (lump->size)
+                                    + _UM_ROUND_LUMP (next->size)
+                                    - _UM_LUMP_OVERHEAD));
+        }
+    }
+
+  _um_lump_link_heap (h, lump);
+}
Index: trunk/src/emx/src/lib/malloc/initr.c
===================================================================
--- trunk/src/emx/src/lib/malloc/initr.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/initr.c	(revision 18)
@@ -0,0 +1,55 @@
+/* initr.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <sys/smutex.h>
+#include <sys/uflags.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+/* This is the default regular heap. */
+
+Heap_t _um_regular_heap;
+
+
+void _um_init_default_regular_heap (void)
+{
+  _UM_MT_DECL
+  void *memory;
+  Heap_t h;
+  static _smutex lock;
+
+  _smutex_request (&lock);
+
+  /* Create the regular heap if it hasn't been created by another
+     thread between the check of _UM_DEFAULT_REGULAR_HEAP by our
+     caller and obtaining the semaphore. */
+
+  if (_UM_DEFAULT_REGULAR_HEAP == NULL)
+    {
+      if (_um_regular_heap == NULL)
+        {
+          _uflags (_UF_SBRK_MODEL, _UF_SBRK_ARBITRARY);
+          memory = _sbrk (_INITIAL_DEFAULT_HEAP_SIZE);
+          if (memory == (void *)-1)
+            abort ();
+          h = _ucreate2 (memory, _INITIAL_DEFAULT_HEAP_SIZE,
+                         !_BLOCK_CLEAN, _HEAP_REGULAR,
+                         _um_default_alloc, _um_default_release,
+                         _um_default_expand, _um_default_shrink);
+          if (h == NULL)
+            abort ();
+          if (_uopen (h) != 0)
+            abort ();
+          _um_regular_heap = h;
+        }
+
+      _UM_DEFAULT_REGULAR_HEAP = _um_regular_heap;
+    }
+
+  _smutex_release (&lock);
+}
Index: trunk/src/emx/src/lib/malloc/initt.c
===================================================================
--- trunk/src/emx/src/lib/malloc/initt.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/initt.c	(revision 18)
@@ -0,0 +1,56 @@
+/* initt.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <sys/smutex.h>
+#include <sys/uflags.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+/* This is the default tiled heap. */
+
+Heap_t _um_tiled_heap = NULL;
+
+
+/* This is an attempt at provoking a linker error if malloc() has been
+   replaced and -ltmalloc has been forgotten.  By referencing the
+   _emx_tmalloc_magic() function, we force in the module compiled from
+   malloc.c.  That will hopefully conflict with the replacement
+   malloc().  Note that the symbol must actually be used; we do this
+   by calling the function. */
+
+extern void _emx_tmalloc_magic (void);
+
+
+void _um_init_default_tiled_heap (void)
+{
+  _UM_MT_DECL
+  static _smutex lock;
+
+  _smutex_request (&lock);
+
+  /* Create the tiled heap if it hasn't been created by another thread
+     between the check of _UM_DEFAULT_TILED_HEAP by our caller and
+     obtaining the semaphore. */
+
+  if (_UM_DEFAULT_TILED_HEAP == NULL)
+    {
+      if (_um_tiled_heap == NULL)
+        {
+          /* Use the regular heap also as tiled heap. */
+
+          _emx_tmalloc_magic ();
+          _um_init_default_regular_heap ();
+          _um_tiled_heap = _um_regular_heap;
+        }
+
+
+      _UM_DEFAULT_TILED_HEAP = _um_tiled_heap;
+    }
+
+  _smutex_release (&lock);
+}
Index: trunk/src/emx/src/lib/malloc/irealloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/irealloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/irealloc.c	(revision 18)
@@ -0,0 +1,326 @@
+/* irealloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+static void *_um_crumb_expand (struct _um_crate *crate,
+                               struct _um_crumb *crumb, size_t new_size)
+{
+  if (new_size > crate->crumb_size)
+    return NULL;
+  crumb->x.used.size = new_size;
+  return _UM_BLOCK_FROM_CRUMB (crumb);
+}
+
+static void *_um_crumb_realloc (struct _um_crate *crate,
+                                struct _um_crumb *crumb,
+                                size_t new_size, size_t align, unsigned flags)
+{
+  void *r;
+  Heap_t h;
+
+  /* No locking required for _um_crumb_expand()! */
+  r = _um_crumb_expand (crate, crumb, new_size);
+  if (r != NULL || (flags & _UMFI_NOMOVE))
+    return r;
+
+  h = crate->parent_heap;
+  _um_heap_lock (h);
+  if (h->type & _HEAP_TILED)
+    flags |= _UMFI_TILED;
+  r = _um_alloc_no_lock (h, new_size, align, flags);
+  if (r != NULL)
+    {
+      memcpy (r, _UM_BLOCK_FROM_CRUMB (crumb), crumb->x.used.size);
+      _um_crumb_free_maybe_lock (crate, crumb, 0);
+    }
+  _um_heap_unlock (h);
+  return r;
+}
+
+/* Try to expand the segment for the lump LUMP.  LUMP is either the
+   last lump of the segment or is followed by a free lump which is the
+   last lump of the segment. */
+
+static int _um_lump_expand_seg (Heap_t h, struct _um_seg *seg,
+                                struct _um_lump *lump, size_t new_size,
+                                size_t align, unsigned flags)
+{
+  size_t rsize, nsize, expanded_size;
+  int clean;
+
+  /* We don't attempt to expand the segment if there's no EXPAND_FUN.
+     This avoids calling ALLOC_FUN just to find out that it didn't
+     allocate contiguous memory. */
+
+  if (h->expand_fun == NULL)
+    return 0;
+
+  /* We try expanding the segment only for the segment which is at the
+     head of the segment list, ie, for the most recently allocated
+     segment.  This assumes that memory is allocated in a bottom-up
+     fashion a la sbrk(). */
+
+  if (seg != h->seg_head)
+    return 0;
+
+  /* Find out how much memory we need. */
+
+  rsize = _UM_ROUND_LUMP (new_size);
+  nsize = (char *)_UM_ADD (lump, rsize) - (char *)seg->mem;
+  assert (nsize > seg->size);
+
+  /* Attempt to expand the segment by calling EXPAND_FUN. */
+
+  expanded_size = nsize; clean = !_BLOCK_CLEAN;
+  if (!h->expand_fun (h, seg->mem, seg->size, &expanded_size, &clean)
+      || expanded_size <= seg->size)
+    return 0;
+
+  /* Add the new memory to the segment. */
+
+  if (_um_seg_addmem (h, seg, _UM_ADD (seg->mem, seg->size),
+                      expanded_size - seg->size) != h)
+    {
+      /* We should shrink the segment here.  However, _seg_addmem()
+         currently always returns h. */
+
+      return 0;
+    }
+
+  /* Fail if the new size is too small. */
+
+  if (expanded_size < nsize)
+    return 0;
+
+  return 1;
+}
+
+
+/* Try to expand a lump without expanding the segment.  LUMP must not
+   be the last lump of the segment. */
+
+static void *_um_lump_expand_up2 (Heap_t h, struct _um_seg *seg,
+                                  struct _um_lump *lump, struct _um_lump *next,
+                                  size_t new_size, size_t align,
+                                  unsigned flags)
+{
+  struct _um_lump *slack;
+  size_t rsize, osize;
+  void *block;
+
+  rsize = _UM_ROUND_LUMP (new_size);
+  osize = _UM_ROUND_LUMP (lump->size) + _UM_ROUND_LUMP (next->size);
+  if (osize < rsize)
+    return NULL;
+
+  /* TODO: attempt to move the block to satisfy alignment/tiling.
+     Don't forget to update the computation of the new size in
+     _um_lump_expand_seg()! */
+
+  block = _UM_BLOCK_FROM_LUMP (lump);
+  if (!_UM_IS_ALIGNED (block, align))
+    return NULL;
+  if ((flags & _UMFI_TILED) && !_UM_TILE_OK (block, new_size))
+    return NULL;
+
+  _um_lump_unlink_heap (seg->parent_heap, next);
+  _um_lump_set_size (lump, new_size);
+
+  /* If the new lump is bigger than required, add the slack to the
+     appropriate free list.  As the lump wasn't free, it might have a
+     neighboring free lump, so try to coalesce free lumps. */
+
+  if (osize > rsize)
+    {
+      assert ((osize - rsize) % _UM_PAGE_SIZE == 0);
+      slack = (struct _um_lump *)_UM_ADD (lump, rsize);
+      _um_lump_coalesce_free (seg->parent_heap, slack, seg, osize - rsize);
+    }
+  return block;
+}
+
+
+static void *_um_lump_expand_up (Heap_t h, struct _um_seg *seg,
+                                 struct _um_lump *lump, size_t new_size,
+                                 size_t align, unsigned flags)
+{
+  struct _um_lump *next;
+  void *block;
+
+  if (!_UM_LAST_LUMP (seg, lump))
+    {
+      next = _UM_NEXT_LUMP (lump);
+      if (_UM_LUMP_STATUS (next) != _UMS_FREE)
+        return NULL;
+      block =  _um_lump_expand_up2 (h, seg, lump, next, new_size,
+                                    align, flags);
+      if (block != NULL)
+        return block;
+      if (!_UM_LAST_LUMP (seg, next))
+        return NULL;
+    }
+
+  /* Now, LUMP is either the last lump of the segment or followed by
+     the last lump of the segment, which is a free lump. */
+
+  /* TODO: Support realignment in _um_lump_expand_up2() and remove these
+     checks. */
+
+  block = _UM_BLOCK_FROM_LUMP (lump);
+  if (!_UM_IS_ALIGNED (block, align))
+    return NULL;
+  if ((flags & _UMFI_TILED) && !_UM_TILE_OK (block, new_size))
+    return NULL;
+
+  /* Attempt to expand the segment. */
+
+  if (!_um_lump_expand_seg (h, seg, lump, new_size, align, flags))
+    return NULL;
+
+  /* If _um_lump_expand_seg() succeeds, it has in fact enlarged the
+     segment, either by adding a free lump or by extending the free
+     lump following LUMP; the segment must be large enough now. */
+
+  assert (!_UM_LAST_LUMP (seg, lump));
+  next = _UM_NEXT_LUMP (lump);
+  assert (_UM_LAST_LUMP (seg, next));
+  assert (_UM_LUMP_STATUS (next) == _UMS_FREE);
+  block = _um_lump_expand_up2 (h, seg, lump, next, new_size, align, flags);
+  assert (block != NULL);
+  return block;
+}
+
+
+static void *_um_lump_expand_down (struct _um_seg *seg,
+                                   struct _um_lump *lump, size_t new_size,
+                                   size_t align, unsigned flags)
+{
+  struct _um_lump *prev, *slack;
+  size_t rsize, osize;
+  void *block;
+
+  if (_UM_FIRST_LUMP (seg, lump))
+    return NULL;
+  prev = _UM_PREV_LUMP (lump);
+  if (_UM_LUMP_STATUS (prev) != _UMS_FREE)
+    return NULL;
+  rsize = _UM_ROUND_LUMP (new_size);
+  osize = _UM_ROUND_LUMP (lump->size) + _UM_ROUND_LUMP (prev->size);
+  if (osize < rsize)
+    return NULL;
+
+  /* TODO: attempt to move the block to satisfy alignment/tiling. */
+
+  block = _UM_BLOCK_FROM_LUMP (prev);
+  if (!_UM_IS_ALIGNED (block, align))
+    return NULL;
+  if ((flags & _UMFI_TILED) && !_UM_TILE_OK (block, new_size))
+    return NULL;
+
+  _um_lump_unlink_heap (seg->parent_heap, prev);
+  prev->parent_seg = lump->parent_seg; /* Copy flag bits */
+  memmove (block, _UM_BLOCK_FROM_LUMP (lump), lump->size);
+  _um_lump_set_size (prev, new_size);
+
+  /* If the new lump is bigger than required, add the slack to the
+     appropriate free list.  As the lump wasn't free, it might have a
+     neighboring free lump, so try to coalesce free lumps. */
+
+  if (osize > rsize)
+    {
+      assert ((osize - rsize) % _UM_PAGE_SIZE == 0);
+      slack = (struct _um_lump *)_UM_ADD (prev, rsize);
+      _um_lump_coalesce_free (seg->parent_heap, slack, seg, osize - rsize);
+    }
+  return block;
+}
+
+
+static void *_um_lump_realloc (struct _um_seg *seg, struct _um_lump *lump,
+                               size_t new_size, size_t align, unsigned flags)
+{
+  void *r;
+  Heap_t h;
+  size_t osize, rsize;
+  struct _um_lump *slack;
+
+  h = seg->parent_heap;
+  _um_heap_lock (h);
+  if (h->type & _HEAP_TILED)
+    flags |= _UMFI_TILED;
+  osize = _UM_ROUND_LUMP (lump->size);
+  rsize = _UM_ROUND_LUMP (new_size);
+  r = _UM_BLOCK_FROM_LUMP (lump);
+  if (rsize < osize)
+    {
+      /* TODO: Use crateset? */
+      _um_lump_set_size (lump, new_size);
+      assert ((osize - rsize) % _UM_PAGE_SIZE == 0);
+      slack = (struct _um_lump *)_UM_ADD (lump, rsize);
+      _um_lump_coalesce_free (h, slack, seg, osize - rsize);
+    }
+  else if (rsize > osize)
+    {
+      r = _um_lump_expand_up (h, seg, lump, new_size, align, flags);
+      if (flags & _UMFI_NOMOVE)
+        return r;
+      if (r == NULL)
+        r = _um_lump_expand_down (seg, lump, new_size, align, flags);
+      if (r == NULL)
+        {
+          r = _um_lump_alloc (h, new_size, align, flags);
+          if (r != NULL)
+            {
+              memcpy (r, _UM_BLOCK_FROM_LUMP (lump), lump->size);
+              _um_lump_free_maybe_lock (seg, lump, 0);
+            }
+        }
+    }
+  else if (lump->size != new_size)
+    _um_lump_set_size (lump, new_size);
+
+  _um_heap_unlock (h);
+  return r;
+}
+
+
+void *_um_realloc (void *block, size_t new_size, size_t align, unsigned flags)
+{
+  struct _um_hdr *hdr;
+  _umagic *parent;
+
+  if (block == NULL)
+    return NULL;
+  if (new_size == 0)
+    {
+      _um_free_maybe_lock (block, 1);
+      return NULL;
+    }
+
+  hdr = _HDR_FROM_BLOCK (block);
+  if (_UM_HDR_STATUS (hdr) == _UMS_FREE)
+    abort ();
+  parent = _PTR_FROM_UMINT (hdr->parent, _umagic);
+  switch (*parent)
+    {
+    case _UM_MAGIC_CRATE:
+      return _um_crumb_realloc ((struct _um_crate *)parent,
+                                _UM_CRUMB_FROM_BLOCK (block), new_size,
+                                align, flags);
+      break;
+    case _UM_MAGIC_SEG:
+      return _um_lump_realloc ((struct _um_seg *)parent,
+                               _UM_LUMP_FROM_BLOCK (block), new_size,
+                               align, flags);
+    default:
+      abort ();
+    }
+}
Index: trunk/src/emx/src/lib/malloc/iwalk.c
===================================================================
--- trunk/src/emx/src/lib/malloc/iwalk.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/iwalk.c	(revision 18)
@@ -0,0 +1,172 @@
+/* iwalk.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+#ifndef NDEBUG
+int _um_walk_error (int x)
+{
+  return x;
+}
+#endif
+
+static int _um_crate_walk (struct _um_crate *crate, size_t size, Heap_t h,
+                           _um_callback2 *callback, void *arg)
+{
+  int i, j, ret;
+  struct _um_crate *crate2;
+  struct _um_crumb *crumb;
+  size_t n, used;
+
+  if (crate->magic != _UM_MAGIC_CRATE || crate->parent_heap != h)
+    return _UM_WALK_ERROR (_HEAPBADBEGIN);
+  h->scratch1 += 1;             /* Count crates */
+  for (i = 0; i < h->n_cratesets; ++i)
+    if (h->cratesets[i].crumb_size == crate->crumb_size)
+      break;
+  if (i >= h->n_cratesets)
+    return _UM_WALK_ERROR (_HEAPBADBEGIN);
+  j = 0;
+  for (crate2 = h->cratesets[i].crate_head;
+       crate2 != NULL && crate2->magic == _UM_MAGIC_CRATE;
+       crate2 = crate2->next)
+    {
+      if (++j > h->n_crates)    /* Avoid infinite loop */
+        return _UM_WALK_ERROR (_HEAPBADEND);
+      if (crate2 == crate)
+        break;
+    }
+  if (crate2 != crate)
+    return _UM_WALK_ERROR (_HEAPBADBEGIN);
+  if (crate->used > crate->max || crate->init > crate->max)
+    return _UM_WALK_ERROR (_HEAPBADBEGIN);
+  n = (sizeof (struct _um_crate)
+       + crate->max * (crate->crumb_size + _UM_CRUMB_OVERHEAD));
+  if (n != size)
+    return _UM_WALK_ERROR (_HEAPBADBEGIN);
+
+  used = 0;
+  for (i = 0; i < crate->init; ++i)
+    {
+      crumb = _UM_CRUMB_BY_INDEX (crate, i);
+      if (_UM_CRUMB_STATUS (crumb) == _UMS_FREE)
+        ret = callback (h, crumb, crate->crumb_size,
+                        _FREEENTRY, _HEAPOK, NULL, 0, arg);
+      else
+        {
+          ret = callback (h, crumb, crumb->x.used.size,
+                          _USEDENTRY, _HEAPOK, NULL, 0, arg);
+          ++used;
+        }
+      if (ret != 0)
+        return _UM_WALK_ERROR (ret);
+    }
+  if (used != crate->used)
+    return _UM_WALK_ERROR (_HEAPBADEND);
+
+#if 0
+  /* Don't forget to update _check_crateset() if you enable this
+     code. */
+  for (i = crate->init; i < crate->max; ++i)
+    {
+      crumb = _UM_CRUMB_BY_INDEX (crate, i);
+      ret = callback (h, crumb, crate->crumb_size, _FREEENTRY, _HEAPOK,
+                      NULL, 0, arg);
+      if (ret != 0)
+        return _UM_WALK_ERROR (ret);
+    }
+#endif
+  return _HEAPOK;
+}
+
+
+static int _um_seg_walk (struct _um_seg *seg, Heap_t h, 
+                         _um_callback2 *callback, void *arg)
+{
+  int ret;
+  struct _um_lump *lump, *next;
+  char *start;
+
+  if (seg->magic != _UM_MAGIC_SEG || seg->parent_heap != h)
+    return _UM_WALK_ERROR (_HEAPBADBEGIN);
+
+  start = _UM_ADD (seg, sizeof (struct _um_seg));
+  start += _UM_ALIGN_DIFF (start + _UM_LUMP_HEADER_SIZE, _UM_PAGE_SIZE);
+  if (seg->start != (void *)start
+      || (((_umint)seg->end - (_umint)seg->start)
+          > seg->size - ((char *)seg->start - (char *)seg->mem))
+      || ((_umint)seg->end - (_umint)seg->start) % _UM_PAGE_SIZE != 0
+      || (_umint)seg->zero_limit < (_umint)seg->start
+      || (_umint)seg->zero_limit > (_umint)seg->end
+      || (((_umint)seg->zero_limit - (_umint)seg->start)
+          % _UM_PAGE_SIZE) != 0)
+    return _UM_WALK_ERROR (_HEAPBADBEGIN);
+
+  /* TDOO: Check seg->mem */
+
+  lump = (struct _um_lump *)seg->start;
+  ret = _HEAPOK;
+  while ((unsigned long)lump < (unsigned long)seg->end)
+    {
+      if (_PTR_FROM_UMINT (lump->parent_seg, struct _um_seg) != seg)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      next = _UM_NEXT_LUMP (lump);
+      if ((_umint)next < (_umint)seg->start
+          || (_umint)next > (_umint)seg->end)
+        return _UM_WALK_ERROR (_HEAPBADEND);
+      if (lump->size != ((_umint *)next)[-1])
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+
+      /* Check for two adjacent free lumps -- that must not happen. */
+
+      if (_UM_LUMP_STATUS (lump) == _UMS_FREE
+          && !_UM_LAST_LUMP (seg, lump)
+          && _UM_LUMP_STATUS (next) == _UMS_FREE)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+
+      if (_UM_LUMP_STATUS (lump) == _UMS_CRATE)
+        ret = _um_crate_walk ((struct _um_crate *)_UM_BLOCK_FROM_LUMP (lump),
+                              lump->size, h, callback, arg);
+      else
+        ret = callback (h, _UM_BLOCK_FROM_LUMP (lump),
+                        lump->size, (_UM_LUMP_STATUS (lump) == _UMS_FREE
+                                     ? _FREEENTRY : _USEDENTRY),
+                        _HEAPOK, NULL, 0, arg);
+      if (ret != _HEAPOK)
+        return _UM_WALK_ERROR (ret);
+      lump = next;
+    }
+  if ((void *)lump != seg->end)
+    return _UM_WALK_ERROR (_HEAPBADEND);
+  return _HEAPOK;
+}
+
+  
+int _um_walk_no_lock (Heap_t h, _um_callback2 *callback, void *arg)
+
+{
+  int ret, initial_count, i;
+  struct _um_seg *seg;
+
+  ret = _HEAPEMPTY; initial_count = 0; i = 0; h->scratch1 = 0;
+  for (seg = h->seg_head; seg != NULL; seg = seg->next)
+    {
+      if (++i > h->n_segments)  /* Avoid infinite loop */
+        return _UM_WALK_ERROR (_HEAPBADEND);
+      if (seg == h->initial_seg)
+        ++initial_count;
+      ret = _um_seg_walk (seg, h, callback, arg);
+      if (ret != _HEAPOK)
+        return ret;
+    }
+  if (i != h->n_segments)
+    return _UM_WALK_ERROR (_HEAPBADEND);
+  if (initial_count != 1)
+    return _UM_WALK_ERROR (_HEAPBADBEGIN);
+  return ret;
+}
Index: trunk/src/emx/src/lib/malloc/makefile
===================================================================
--- trunk/src/emx/src/lib/malloc/makefile	(revision 18)
+++ trunk/src/emx/src/lib/malloc/makefile	(revision 18)
@@ -0,0 +1,100 @@
+#
+# /emx/src/lib/malloc/makefile
+#
+.IF $(SO)
+
+AR=ar
+DSTLIB=malloc2.a
+GCC=gcc $(SO) -Wall
+I=/emx/include/
+S=/emx/include/sys/
+E=$(S)emx.h
+BUILTIN=$(S)builtin.h $(I)386/builtin.h
+
+.c.o:
+	$(GCC) -c $<
+
+default: $(DSTLIB)
+
+.ELSE
+
+.INCLUDE: /emx/src/lib/libc.mak
+
+.ENDIF
+
+H=$(I)stdlib.h $(I)umalloc.h $(I)stddef.h \
+	$(BUILTIN) $(S)fmutex.h $(S)rmutex.h $(I)emx/umalloc.h \
+
+OBJS=calloc.o defalloc.o defexpan.o defrelea.o defshrin.o expand.o \
+     free.o heapchk.o heapmin.o heapset.o heapwalk.o \
+     iaddmem.o ialloc.o ifree.o imisc.o initr.o initt.o irealloc.o iwalk.o \
+     malloc.o mheap.o msize.o realloc.o \
+     tcalloc.o tfree.o theapmin.o tmalloc.o trealloc.o \
+     uaddmem.o ucalloc.o uclose.o ucreate.o ucreate2.o udefault.o \
+     udestroy.o uheapchk.o uheapmin.o uheapset.o umalloc.o uopen.o \
+     ustats.o utcalloc.o utdefaul.o utmalloc.o \
+     utype.o uwalk.o uwalk2.o
+
+local: ;
+
+calloc.o: calloc.c $(H) $(I)emx/thread.h
+defalloc.o: defalloc.c $(H) $(I)ulimit.h
+defexpan.o: defexpan.c $(H)
+defrelea.o: defrelea.c $(H)
+defshrin.o: defshrin.c $(H)
+expand.o: expand.c $(H)
+free.o: free.c $(H)
+heapchk.o: heapchk.c $(H) $(I)emx/thread.h
+heapmin.o: heapmin.c $(H) $(I)emx/thread.h
+heapset.o: heapset.c $(H) $(I)emx/thread.h
+iaddmem.o: iaddmem.c $(H)
+ialloc.o: ialloc.c $(H)
+ifree.o: ifree.c $(H)
+imisc.o: imisc.c $(H)
+initr.o: initr.c $(H) $(S)smutex.h $(S)uflags.h $(I)emx/thread.h
+initt.o: initt.c $(H) $(S)smutex.h $(S)uflags.h $(I)emx/thread.h
+irealloc.o: irealloc.c $(H) $(I)string.h
+malloc.o: malloc.c $(H) $(I)emx/thread.h
+mheap.o: mheap.c $(H)
+msize.o: msize.c $(H)
+realloc.o: realloc.c $(H)
+tcalloc.o: tcalloc.c $(H) $(I)emx/thread.h
+tfree.o: tfree.c $(H)
+theapmin.o: theapmin.c $(H) $(I)emx/thread.h
+tmalloc.o: tmalloc.c $(H) $(I)emx/thread.h
+trealloc.o: trealloc.c $(H) $(I)emx/thread.h
+uaddmem.o: uaddmem.c $(H)
+ucalloc.o: ucalloc.c $(H)
+uclose.o: uclose.c $(H)
+ucreate.o: ucreate.c $(H)
+ucreate2.o: ucreate2.c $(H)
+udefault.o: udefault.c $(H) $(I)emx/thread.h
+udestroy.o: udestroy.c $(H)
+uheapchk.o: uheapchk.c $(H)
+uheapmin.o: uheapmin.c $(H)
+uheapset.o: uheapset.c $(H) $(I)string.h
+umalloc.o: umalloc.c $(H)
+uopen.o: uopen.c $(H)
+ustats.o: ustats.c $(H)
+utcalloc.o: utcalloc.c $(H)
+utdefaul.o: utdefaul.c $(H) $(I)emx/thread.h
+utmalloc.o: utmalloc.c $(H)
+utype.o: utype.c $(H)
+
+# The following modules contain functions which take a pointer to
+# a function as argument
+
+heapwalk.o: heapwalk.c $(H) $(I)emx/thread.h
+	$(GCC) -fexceptions -c ../heapwalk.c
+
+iwalk.o: iwalk.c $(H)
+	$(GCC) -fexceptions -c ../iwalk.c
+
+uwalk.o: uwalk.c $(H)
+	$(GCC) -fexceptions -c ../uwalk.c
+
+uwalk2.o: uwalk2.c $(H)
+	$(GCC) -fexceptions -c ../uwalk2.c
+
+$(DSTLIB): $(OBJS)
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/malloc/malloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/malloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/malloc.c	(revision 18)
@@ -0,0 +1,25 @@
+/* malloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+void *malloc (size_t size)
+{
+  _UM_MT_DECL
+
+  if (_UM_DEFAULT_REGULAR_HEAP == NULL)
+    _um_init_default_regular_heap ();
+  return _umalloc (_UM_DEFAULT_REGULAR_HEAP, size);
+}
+
+/* See initt.c */
+
+void _emx_tmalloc_magic (void)
+{
+}
Index: trunk/src/emx/src/lib/malloc/mheap.c
===================================================================
--- trunk/src/emx/src/lib/malloc/mheap.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/mheap.c	(revision 18)
@@ -0,0 +1,32 @@
+/* mheap.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+Heap_t _mheap (const void *block)
+{
+  struct _um_hdr *hdr;
+  _umagic *parent;
+
+  if (block == NULL)
+    return NULL;
+
+  hdr = _HDR_FROM_BLOCK (block);
+  if (_UM_HDR_STATUS (hdr) == _UMS_FREE)
+    return NULL;
+  parent = _PTR_FROM_UMINT (hdr->parent, _umagic);
+  switch (*parent)
+    {
+    case _UM_MAGIC_CRATE:
+      return ((struct _um_crate *)parent)->parent_heap;
+    case _UM_MAGIC_SEG:
+      return ((struct _um_seg *)parent)->parent_heap;
+    default:
+      return NULL;
+    }
+}
Index: trunk/src/emx/src/lib/malloc/msize.c
===================================================================
--- trunk/src/emx/src/lib/malloc/msize.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/msize.c	(revision 18)
@@ -0,0 +1,16 @@
+/* msize.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+size_t _msize (const void *block)
+{
+  if (block == NULL)
+    return 0;
+  return _HDR_FROM_BLOCK (block)->size;
+}
Index: trunk/src/emx/src/lib/malloc/realloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/realloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/realloc.c	(revision 18)
@@ -0,0 +1,17 @@
+/* realloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void *realloc (void *block, size_t new_size)
+{
+  if (block == NULL)
+    return malloc (new_size);
+  else
+    return _um_realloc (block, new_size, 4, 0);
+}
Index: trunk/src/emx/src/lib/malloc/tcalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/tcalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/tcalloc.c	(revision 18)
@@ -0,0 +1,19 @@
+/* tcalloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+void *_tcalloc (size_t count, size_t size)
+{
+  _UM_MT_DECL
+
+  if (_UM_DEFAULT_TILED_HEAP == NULL)
+    _um_init_default_tiled_heap ();
+  return _utcalloc (_UM_DEFAULT_TILED_HEAP, count, size);
+}
Index: trunk/src/emx/src/lib/malloc/tfree.c
===================================================================
--- trunk/src/emx/src/lib/malloc/tfree.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/tfree.c	(revision 18)
@@ -0,0 +1,14 @@
+/* tfree.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void _tfree (void *block)
+{
+  _um_free_maybe_lock (block, 1);
+}
Index: trunk/src/emx/src/lib/malloc/theapmin.c
===================================================================
--- trunk/src/emx/src/lib/malloc/theapmin.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/theapmin.c	(revision 18)
@@ -0,0 +1,19 @@
+/* theapmin.c (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+int _theapmin (void)
+{
+  _UM_MT_DECL
+
+  if (_UM_DEFAULT_TILED_HEAP == NULL)
+    _um_init_default_tiled_heap ();
+  return _uheapmin (_UM_DEFAULT_TILED_HEAP);
+}
Index: trunk/src/emx/src/lib/malloc/tmalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/tmalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/tmalloc.c	(revision 18)
@@ -0,0 +1,19 @@
+/* tmalloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+void *_tmalloc (size_t size)
+{
+  _UM_MT_DECL
+
+  if (_UM_DEFAULT_TILED_HEAP == NULL)
+    _um_init_default_tiled_heap ();
+  return _utmalloc (_UM_DEFAULT_TILED_HEAP, size);
+}
Index: trunk/src/emx/src/lib/malloc/trealloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/trealloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/trealloc.c	(revision 18)
@@ -0,0 +1,22 @@
+/* trealloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+void *_trealloc (void *block, size_t new_size)
+{
+  _UM_MT_DECL
+
+  if (_UM_DEFAULT_TILED_HEAP == NULL)
+    _um_init_default_tiled_heap ();
+  if (block == NULL)
+    return _tmalloc (new_size);
+  else
+    return _um_realloc (block, new_size, 4, _UMFI_TILED);
+}
Index: trunk/src/emx/src/lib/malloc/uaddmem.c
===================================================================
--- trunk/src/emx/src/lib/malloc/uaddmem.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/uaddmem.c	(revision 18)
@@ -0,0 +1,19 @@
+/* uaddmem.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+Heap_t _uaddmem (Heap_t h, void *memory, size_t size, int clean)
+{
+  Heap_t r;
+
+  _um_heap_lock (h);
+  r = _um_addmem_nolock (h, memory, size, clean);
+  _um_heap_unlock (h);
+  return r;
+}
Index: trunk/src/emx/src/lib/malloc/ucalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/ucalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/ucalloc.c	(revision 18)
@@ -0,0 +1,35 @@
+/* ucalloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+/* TODO: _BLOCK_CLEAN */
+
+void *_ucalloc (Heap_t h, size_t count, size_t size)
+{
+  size_t bytes;
+  void *block;
+  unsigned flags;
+
+  assert (h->magic == _UM_MAGIC_HEAP);
+  if (h->magic != _UM_MAGIC_HEAP)
+    return NULL;
+
+  bytes = count * size;
+  if (size != 0 && bytes / size != count) /* Check for overflow */
+    return NULL;
+
+  _um_heap_lock (h);
+  flags = _UMFI_ZERO;
+  if (h->type & _HEAP_TILED)
+    flags |= _UMFI_TILED;
+  block = _um_alloc_no_lock (h, bytes, 4, flags);
+  _um_heap_unlock (h);
+  return block;
+}
Index: trunk/src/emx/src/lib/malloc/uclose.c
===================================================================
--- trunk/src/emx/src/lib/malloc/uclose.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/uclose.c	(revision 18)
@@ -0,0 +1,20 @@
+/* uclose.c (emx+gcc) -- Copyright (c) 1996-1997 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+int _uclose (Heap_t h)
+{
+  if (h->magic != _UM_MAGIC_HEAP
+      || h == _um_regular_heap || h == _um_tiled_heap)
+    return -1;
+#if defined (__MT__)
+  _rmutex_close (&h->rsem);
+#endif
+  return 0;
+}
Index: trunk/src/emx/src/lib/malloc/ucreate.c
===================================================================
--- trunk/src/emx/src/lib/malloc/ucreate.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/ucreate.c	(revision 18)
@@ -0,0 +1,17 @@
+/* ucreate.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+Heap_t _ucreate (void *memory, size_t size, int clean, unsigned type,
+                 void *(*alloc_fun)(Heap_t, size_t *, int *),
+                 void (*release_fun)(Heap_t, void *, size_t))
+{
+  return _ucreate2 (memory, size, clean, type,
+                    alloc_fun, release_fun, NULL, NULL);
+}
Index: trunk/src/emx/src/lib/malloc/ucreate2.c
===================================================================
--- trunk/src/emx/src/lib/malloc/ucreate2.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/ucreate2.c	(revision 18)
@@ -0,0 +1,99 @@
+/* ucreate2.c (emx+gcc) -- Copyright (c) 1996-1997 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+Heap_t _ucreate2 (void *memory, size_t size, int clean, unsigned type,
+                  void *(*alloc_fun)(Heap_t, size_t *, int *),
+                  void (*release_fun)(Heap_t, void *, size_t),
+                  int (*expand_fun)(Heap_t, void *, size_t, size_t *, int *),
+                  void (*shrink_fun)(Heap_t, void *, size_t, size_t *))
+{
+  struct _uheap *h;
+  int i;
+  unsigned long diff;
+  unsigned t;
+
+  /* Check the TYPE argument.  It must not contain any bits but
+     _HEAP_REGULAR, _HEAP_TILED, and _HEAP_SHARED.  Exactly one of
+     _HEAP_REGULAR and _HEAP_TILED must be set. */
+
+  if (type & ~(_HEAP_REGULAR|_HEAP_TILED|_HEAP_SHARED))
+    return NULL;
+  t = type & (_HEAP_REGULAR|_HEAP_TILED);
+  if (t != _HEAP_REGULAR && t != _HEAP_TILED)
+      return NULL;
+
+  /* Check the SIZE argument. */
+
+  if (size < _HEAP_MIN_SIZE || size > _HEAP_MIN_SIZE + _UM_MAX_SIZE)
+    return NULL;
+
+  /* Compute DIFF, the number of bytes to insert at MEMORY to align H
+     properly. */
+
+  diff = _UM_ALIGN_DIFF (memory, 4);
+  memory = _UM_ADD (memory, diff);
+  size -= diff;
+  if (size < _HEAP_MIN_SIZE)
+    return NULL;
+
+  /* Initialize the strcuture. */
+
+  h = (struct _uheap *)memory;
+  h->magic = 0;                 /* Will be set properly below */
+  h->type = type;
+  h->alloc_fun = alloc_fun;
+  h->expand_fun = expand_fun;
+  h->release_fun = release_fun;
+  h->shrink_fun = shrink_fun;
+  h->seg_head = NULL;
+  h->n_segments = 0;
+  h->n_crates = 0;
+  h->max_crumbs = 0;
+  for (i = 0; i < _UM_BUCKETS; ++i)
+    {
+      h->buckets[i].head = NULL;
+      h->buckets[i].tail = NULL;
+    }
+  h->n_cratesets = 5;
+  for (i = 0; i < h->n_cratesets; ++i)
+    {
+      h->cratesets[i].crate_head = NULL;
+      h->cratesets[i].crumb_head = NULL;
+      h->cratesets[i].crumb_tail = NULL;
+    }
+  h->cratesets[0].crumb_size = 4;
+  h->cratesets[1].crumb_size = 8;
+  h->cratesets[2].crumb_size = 12;
+  h->cratesets[3].crumb_size = 16;
+  h->cratesets[4].crumb_size = 20;
+
+  /* Initialize the mutex semaphore. */
+
+#if defined (__MT__)
+  if (_rmutex_create (&h->rsem, (type & _HEAP_SHARED) ? _FMC_SHARED : 0) != 0)
+    return NULL;
+#endif
+
+  /* The heap has been created, except for the initial segment. */
+
+  h->magic = _UM_MAGIC_HEAP;
+
+  /* Add the initial segment to the heap. */
+
+  if (_um_addmem_nolock (h, _UM_ADD (h, sizeof (struct _uheap)),
+                         size - sizeof (struct _uheap), clean) == NULL)
+    {
+      h->magic = 0;
+      return NULL;
+    }
+  h->initial_seg = h->seg_head;
+  h->initial_seg_size = h->initial_seg->size;
+  return h;
+}
Index: trunk/src/emx/src/lib/malloc/udefault.c
===================================================================
--- trunk/src/emx/src/lib/malloc/udefault.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/udefault.c	(revision 18)
@@ -0,0 +1,43 @@
+/* udefault.c (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+Heap_t _udefault (Heap_t h)
+{
+  _UM_MT_DECL
+  Heap_t old;
+
+  /* At program start and for new threads, _UM_DEFAULT_REGULAR_HEAP is
+     NULL.  This means that _um_init_default_regular_heap() should be
+     called to initialize _UM_DEFAULT_REGULAR_HEAP.  We want
+     _udefault() to return a pointer to the heap, but we don't want
+     _udefault() to create the heap as it might be replaced by the
+     heap pointed to by H anyway.
+
+     The following code makes _udefault() return the correct value for
+     new threads if the heap already exists.  If the heap does not
+     exist, NULL will be returned.
+
+     Note that assigning _um_regular_heap to _UM_DEFAULT_REGULAR_HEAP
+     (instead of OLD) would create a time window unless protected by
+     the mutex semaphore used by _um_init_default_regular_heap()! */
+
+  old = _UM_DEFAULT_REGULAR_HEAP;
+  if (old == NULL)
+    old = _um_regular_heap;     /* ...which might be NULL, see above */
+
+  if (h != NULL)
+    {
+      if (h->magic != _UM_MAGIC_HEAP)
+        return NULL;
+      _UM_DEFAULT_REGULAR_HEAP = h;
+    }
+  return old;
+}
Index: trunk/src/emx/src/lib/malloc/udestroy.c
===================================================================
--- trunk/src/emx/src/lib/malloc/udestroy.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/udestroy.c	(revision 18)
@@ -0,0 +1,94 @@
+/* udestroy.c (emx+gcc) -- Copyright (c) 1996-1997 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+int _udestroy (Heap_t h, int force)
+{
+  struct _um_seg *seg, *next;
+  struct _um_lump *lump;
+  size_t shrink_size;
+
+  if (h->magic != _UM_MAGIC_HEAP
+      || h == _um_regular_heap || h == _um_tiled_heap)
+    return -1;
+
+  _um_heap_lock (h);
+  if (!force)
+    {
+      /* Check if all blocks have been freed.  As a crate is freed as
+         soon as all its crumbs are freed, we have to check for lumps
+         only.  If each segment contains just one free lump, no blocks
+         are used. */
+
+      for (seg = h->seg_head; seg != NULL; seg = seg->next)
+        {
+          lump = (struct _um_lump *)seg->start;
+          if (_UM_LUMP_STATUS (lump) != _UMS_FREE
+              || !_UM_LAST_LUMP (seg, lump))
+            {
+              /* At least one lump is used.  Return. */
+
+              _um_heap_unlock (h);
+              return 0;
+            }
+        }
+    }
+  
+  h->magic = 0;
+  _um_heap_unlock (h);
+
+  /* Deallocate all the segments but the initial segment.  The
+     segments are deallocated in LIFO manner to support sbrk(). */
+
+  if (h->release_fun != NULL || h->shrink_fun != NULL)
+    for (seg = h->seg_head; seg != NULL; seg = next)
+      {
+        next = seg->next;
+        if (seg != h->initial_seg)
+          {
+            if (h->release_fun != NULL)
+              h->release_fun (h, seg->mem, seg->size);
+            else if (h->shrink_fun != NULL)
+              {
+                shrink_size = 0;
+                h->shrink_fun (h, seg->mem, seg->size, &shrink_size);
+              }
+          }
+      }
+  h->seg_head = h->initial_seg;
+
+  /* Deallocate memory contiguously added to the initial segment. */
+
+  if (h->initial_seg->size != h->initial_seg_size)
+    {
+      seg = h->initial_seg;
+      assert (seg->size > h->initial_seg_size);
+      if (h->release_fun != NULL)
+        h->release_fun (h, _UM_ADD (seg->mem, h->initial_seg_size),
+                        seg->size - h->initial_seg_size);
+      else if (h->shrink_fun != NULL)
+        {
+          shrink_size = 0;
+          h->shrink_fun (h, _UM_ADD (seg->mem, h->initial_seg_size),
+                         seg->size - h->initial_seg_size, &shrink_size);
+        }
+    }
+
+  /* The semaphore is closed both by _uclose() and by _udestroy().
+     This is required because _ucreate() sets the open count to 1 and
+     n calls to _uopen() increment the open count to 1+n.  Then, n
+     calls to _uclose() decrement the open count to 1 and _udestroy()
+     decrements the open count to 0, destroying the semaphore. */
+
+#if defined (__MT__)
+  _rmutex_close (&h->rsem);
+#endif
+  return 0;
+}
Index: trunk/src/emx/src/lib/malloc/uheapchk.c
===================================================================
--- trunk/src/emx/src/lib/malloc/uheapchk.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/uheapchk.c	(revision 18)
@@ -0,0 +1,161 @@
+/* uheapchk.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+struct _um_check
+{
+  unsigned free;
+  unsigned crates;
+};
+
+static int _walk_check (Heap_t h, const void *obj, size_t size, int flag,
+                        int status, const char *fname, size_t lineno,
+                        void *arg)
+{
+  struct _um_check *check = (struct _um_check *)arg;
+
+  if (status == _HEAPOK)
+    {
+      if (flag == _USEDENTRY && (h->type & _HEAP_TILED)
+          && !_UM_TILE_OK (obj, size))
+        return _HEAPBADNODE;
+      if (flag == _FREEENTRY)
+        check->free += 1;
+    }
+  return status;
+}
+
+
+static int _check_bucket (Heap_t h, int bucket_num, struct _um_check *check)
+{
+  struct _um_lump *lump, *prev_lump;
+  struct _um_seg *seg;
+  size_t min_size, max_size, rsize, i;
+
+  min_size = _UM_BUCKET_SIZE (bucket_num);
+  max_size = bucket_num == _UM_BUCKETS - 1 ? _UM_MAX_SIZE : min_size * 2 - 1;
+
+  prev_lump = NULL; i = 0;
+  for (lump = h->buckets[bucket_num].head;
+       lump != NULL; lump = lump->x.free.next)
+    {
+      if (++i > h->scratch1)    /* Avoid infinite loop */
+        return _UM_WALK_ERROR (_HEAPBADEND);
+      if (_UM_LUMP_STATUS (lump) != _UMS_FREE)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      seg = _PTR_FROM_UMINT (lump->parent_seg, struct _um_seg);
+      if (seg->magic != _UM_MAGIC_SEG)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      if (seg->parent_heap != h)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      if (lump->x.free.prev != prev_lump)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      rsize = _UM_ROUND_LUMP (lump->size);
+      if (rsize < min_size || rsize > max_size)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      check->free += 1;
+      prev_lump = lump;
+    }
+  if (h->buckets[bucket_num].tail != prev_lump)
+    return _UM_WALK_ERROR (_HEAPBADNODE);
+  return _HEAPOK;
+}
+
+
+static int _check_crateset (Heap_t h, int set_num, struct _um_check *check)
+{
+  struct _um_crateset *crateset;
+  struct _um_crumb *crumb, *prev_crumb;
+  struct _um_crate *crate;
+  size_t i;
+
+  crateset = &h->cratesets[set_num];
+  prev_crumb = NULL; i = 0;
+  for (crumb = crateset->crumb_head; crumb != NULL; crumb = crumb->x.free.next)
+    {
+      if (++i > h->max_crumbs)  /* Avoid infinite loop */
+        return _UM_WALK_ERROR (_HEAPBADEND);
+      if (_UM_CRUMB_STATUS (crumb) != _UMS_FREE)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      crate = _PTR_FROM_UMINT (crumb->x.free.parent_crate, struct _um_crate);
+      if (crate->magic != _UM_MAGIC_CRATE)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      if (crate->parent_crateset != crateset)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      if (crumb->x.free.prev != prev_crumb)
+        return _UM_WALK_ERROR (_HEAPBADNODE);
+      check->free += 1;
+      prev_crumb = crumb;
+    }
+  if (crateset->crumb_tail != prev_crumb)
+    return _UM_WALK_ERROR (_HEAPBADNODE);
+
+  i = 0;
+  for (crate = crateset->crate_head; crate != NULL; crate = crate->next)
+    {
+      if (++i > h->n_crates)
+        return _UM_WALK_ERROR (_HEAPBADEND);
+    }
+  check->crates += i;
+
+  /* Only the head of the crate list may have INIT < MAX. */
+
+  if (crateset->crate_head != NULL)
+    {
+      for (crate = crateset->crate_head->next;
+           crate != NULL; crate = crate->next)
+        if (crate->init < crate->max)
+          return _UM_WALK_ERROR (_HEAPBADNODE);
+    }
+
+  return _HEAPOK;
+}
+
+
+int _uheapchk (Heap_t h)
+{
+  int ret, i;
+  struct _um_check pass1, pass2;
+
+  if (h == NULL)
+    return _HEAPEMPTY;
+  if (h->magic != _UM_MAGIC_HEAP)
+    return _HEAPBADBEGIN;
+
+  _um_heap_lock (h);
+  pass1.free = 0; pass1.crates = 0;
+  pass2.free = 0; pass2.crates = 0;
+  ret = _um_walk_no_lock (h, _walk_check, &pass1);
+  pass1.crates = h->scratch1;
+
+  if (ret == _HEAPOK)
+    for (i = 0; i < _UM_BUCKETS; ++i)
+      {
+        h->scratch1 = pass1.free;
+        ret = _check_bucket (h, i, &pass2);
+        if (ret != _HEAPOK)
+          break;
+      }
+
+  if (ret == _HEAPOK)
+    for (i = 0; i < h->n_cratesets; ++i)
+      {
+        ret = _check_crateset (h, i, &pass2);
+        if (ret != _HEAPOK)
+          break;
+      }
+
+  if (pass1.free != pass2.free)
+    ret = _UM_WALK_ERROR (_HEAPBADNODE);
+  if (pass1.crates != h->n_crates || pass2.crates != h->n_crates)
+    ret = _UM_WALK_ERROR (_HEAPBADEND);
+
+  _um_heap_unlock (h);
+  return ret;
+}
Index: trunk/src/emx/src/lib/malloc/uheapmin.c
===================================================================
--- trunk/src/emx/src/lib/malloc/uheapmin.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/uheapmin.c	(revision 18)
@@ -0,0 +1,142 @@
+/* uheapmin.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+int _uheapmin (Heap_t h)
+{
+  struct _um_seg *seg, *next, **patch;
+  struct _um_lump *lump;
+  char *mem_end;
+  size_t shrink_size, new_size, asize, fsize, min_size;
+  char remove;
+
+  if (h->magic != _UM_MAGIC_HEAP)
+    return -1;
+  if (h->release_fun == NULL && h->shrink_fun == NULL)
+    return 0;
+
+  _um_heap_lock (h);
+
+  /* Examine all segments, releasing segments which don't contain any
+     used lumps, shrinking segments which have a free lump at the end.
+     Exactly those segments which contain one free lump don't contain
+     any used lumps.  Examine the segments in LIFO manner to support
+     sbrk(). */
+
+  patch = &h->seg_head;
+  for (seg = h->seg_head; seg != NULL; seg = next)
+    {
+      next = seg->next;
+      remove = 0;
+      lump = (struct _um_lump *)seg->start;
+      if (seg != h->initial_seg
+          && _UM_LUMP_STATUS (lump) == _UMS_FREE && _UM_LAST_LUMP (seg, lump))
+        {
+          /* This segment is unused and is not the initial segment.
+             First try SHRINK_FUN because SHRINK_FUN returns status,
+             so we can keep the segment if SHRINK_FUN fails.  For
+             RELEASE_FUN, we have to assume successful deallocation of
+             the segment. */
+
+          if (h->shrink_fun != NULL)
+            {
+              _um_lump_unlink_heap (h, lump);
+              shrink_size = 0;
+              h->shrink_fun (h, seg->mem, seg->size, &shrink_size);
+              if (shrink_size == 0)
+                remove = 1;
+              else if (shrink_size <= seg->size)
+                {
+                  if (_um_seg_setmem (h, seg, seg->mem, shrink_size,
+                                      !_BLOCK_CLEAN) != h)
+                    {
+                      memset (seg->mem, 0, shrink_size);
+                      remove = 1;
+                    }
+                }
+              else
+                abort ();
+            }
+          else
+            {
+              _um_lump_unlink_heap (h, lump);
+              h->release_fun (h, seg->mem, seg->size);
+              remove = 1;
+            }
+        }
+
+      if (remove)
+        {
+          *patch = next;
+          h->n_segments -= 1;
+        }
+      else
+        patch = &seg->next;
+    }
+
+  /* Shrink the most recently allocated segment, if possible.  Don't
+     make the initial segment smaller than its initial size. */
+
+  seg = h->seg_head;
+  if (h->shrink_fun != NULL)
+    {
+      lump = _UM_PREV_LUMP ((struct _um_lump *)seg->end);
+      if (_UM_LUMP_STATUS (lump) == _UMS_FREE)
+        {
+          min_size = seg == h->initial_seg ? h->initial_seg_size : 0;
+          new_size = (char *)lump - (char *)seg->mem;
+          if (new_size < min_size)
+            new_size = min_size;
+
+          /* Don't shrink the segment by less than one page. */
+
+          if (new_size + _UM_PAGE_SIZE < seg->size)
+            {
+              _um_lump_unlink_heap (h, lump);
+              shrink_size = new_size - min_size;
+              h->shrink_fun (h, _UM_ADD (seg->mem, min_size),
+                             seg->size - min_size, &shrink_size);
+              assert (shrink_size <= seg->size - min_size);
+              assert (shrink_size >= new_size - min_size);
+              seg->size = shrink_size + min_size;
+
+              /* Compute the number of bytes available at seg->start.
+                 Drop the partial page at the end, if there is any. */
+
+              mem_end = (char *)_UM_ADD (seg->mem, seg->size);
+              asize = mem_end - (char *)seg->start;
+              asize &= ~(_UM_PAGE_SIZE-1);
+              assert (asize > 0);
+
+              /* Set the new segment end. */
+
+              seg->end = _UM_ADD (seg->start, asize);
+              seg->zero_limit = seg->end;
+
+              /* If there's free space at the end (this happens only
+                 if the SHRINK_FUN didn't deallocate all the excess
+                 memory, or for the initial segment), make a new free
+                 lump. */
+
+              if ((void *)lump != seg->end)
+                {
+                  assert ((void *)lump < seg->end);
+                  fsize = (char *)seg->end - (char *)lump;
+                  assert (fsize % _UM_PAGE_SIZE == 0);
+                  _um_lump_make_free (h, lump, seg, fsize);
+                }
+            }
+        }
+    }
+
+  _um_heap_unlock (h);
+  return 0;
+}
Index: trunk/src/emx/src/lib/malloc/uheapset.c
===================================================================
--- trunk/src/emx/src/lib/malloc/uheapset.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/uheapset.c	(revision 18)
@@ -0,0 +1,35 @@
+/* uheapset.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+static int _um_walk_set (Heap_t h, const void *obj, size_t size, int flag,
+                         int status, const char *fname, size_t lineno,
+                         void *arg)
+{
+  if (flag == _FREEENTRY && status == _HEAPOK)
+    {
+      /* Cast away `const'. */
+      memset ((void *)obj, (int)arg, size);
+    }
+  return status;
+}
+
+
+int _uheapset (Heap_t h, unsigned fill)
+{
+  struct _um_seg *seg;
+
+  if (h == NULL)
+    return _HEAPEMPTY;
+  if (fill != 0)
+    for (seg = h->seg_head; seg != NULL; seg = seg->next)
+      seg->zero_limit = seg->end;
+  return _uheap_walk2 (h, _um_walk_set, (void *)fill);
+}
Index: trunk/src/emx/src/lib/malloc/umalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/umalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/umalloc.c	(revision 18)
@@ -0,0 +1,27 @@
+/* umalloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void *_umalloc (Heap_t h, size_t size)
+{
+  void *block;
+  unsigned flags;
+
+  assert (h->magic == _UM_MAGIC_HEAP);
+  if (h->magic != _UM_MAGIC_HEAP)
+    return NULL;
+  _um_heap_lock (h);
+  flags = 0;
+  if (h->type & _HEAP_TILED)
+    flags |= _UMFI_TILED;
+  block = _um_alloc_no_lock (h, size, 4, flags);
+  _um_heap_unlock (h);
+  return block;
+}
Index: trunk/src/emx/src/lib/malloc/uopen.c
===================================================================
--- trunk/src/emx/src/lib/malloc/uopen.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/uopen.c	(revision 18)
@@ -0,0 +1,21 @@
+/* uopen.c (emx+gcc) -- Copyright (c) 1996-1997 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+int _uopen (Heap_t h)
+{
+  if (h->magic != _UM_MAGIC_HEAP
+      || h == _um_regular_heap || h == _um_tiled_heap)
+    return -1;
+#if defined (__MT__)
+  if (_rmutex_open (&h->rsem) != 0)
+    return -1;
+#endif
+  return 0;
+}
Index: trunk/src/emx/src/lib/malloc/ustats.c
===================================================================
--- trunk/src/emx/src/lib/malloc/ustats.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/ustats.c	(revision 18)
@@ -0,0 +1,64 @@
+/* ustats.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+static int _walk_stats (Heap_t h, const void *obj, size_t size, int flag,
+                        int status, const char *fname, size_t lineno,
+                        void *arg)
+{
+  _HEAPSTATS *stats;
+
+  stats = (_HEAPSTATS *)arg;
+  if (status != _HEAPOK)
+    return status;
+  if (flag == _USEDENTRY)
+    stats->_used += size;
+  else if (size > stats->_max_free)
+    stats->_max_free = size;
+  return status;
+}
+
+
+
+int _ustats (Heap_t h, _HEAPSTATS *stats)
+{
+  struct _um_seg *seg;
+  int ret;
+
+  stats->_provided = 0;
+  stats->_used = 0;
+  stats->_tiled = 0;
+  stats->_shared = 0;
+  stats->_max_free = 0;
+  stats->_segments = h->n_segments;
+  stats->_crates = h->n_crates;
+  stats->_reserved1 = 0;
+  stats->_reserved2 = 0;
+  stats->_reserved3 = 0;
+  stats->_reserved4 = 0;
+  stats->_reserved5 = 0;
+  stats->_reserved6 = 0;
+  stats->_reserved7 = 0;
+  stats->_reserved8 = 0;
+  stats->_reserved9 = 0;
+
+  if (h == NULL)                /* Uninitialized _um_runtime_heap! */
+    return 0;
+
+  _um_heap_lock (h);
+  if (h->type & _HEAP_TILED) stats->_tiled = 1;
+  if (h->type & _HEAP_SHARED) stats->_shared = 1;
+
+  for (seg = h->seg_head; seg != NULL; seg = seg->next)
+    stats->_provided += (char *)seg->end - (char *)seg->start;
+  ret = _um_walk_no_lock (h, _walk_stats, (void *)stats);
+
+  _um_heap_unlock (h);
+  return ret;
+}
Index: trunk/src/emx/src/lib/malloc/utcalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/utcalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/utcalloc.c	(revision 18)
@@ -0,0 +1,29 @@
+/* utcalloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void *_utcalloc (Heap_t h, size_t count, size_t size)
+{
+  size_t bytes;
+  void *block;
+
+  assert (h->magic == _UM_MAGIC_HEAP);
+  if (h->magic != _UM_MAGIC_HEAP)
+    return NULL;
+
+  bytes = count * size;
+  if (size != 0 && bytes / size != count) /* Check for overflow */
+    return NULL;
+
+  _um_heap_lock (h);
+  block = _um_alloc_no_lock (h, bytes, 4, _UMFI_ZERO | _UMFI_TILED);
+  _um_heap_unlock (h);
+  return block;
+}
Index: trunk/src/emx/src/lib/malloc/utdefaul.c
===================================================================
--- trunk/src/emx/src/lib/malloc/utdefaul.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/utdefaul.c	(revision 18)
@@ -0,0 +1,30 @@
+/* utdefaul.c (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+#include <emx/thread.h>
+
+Heap_t _utdefault (Heap_t h)
+{
+  _UM_MT_DECL
+  Heap_t old;
+
+  /* The same comment as in _udefault() applies here. */
+
+  old = _UM_DEFAULT_TILED_HEAP;
+  if (old == NULL)
+    old = _um_tiled_heap;       /* ...which might be NULL */
+
+  if (h != NULL)
+    {
+      if (h->magic != _UM_MAGIC_HEAP)
+        return NULL;
+      _UM_DEFAULT_TILED_HEAP = h;
+    }
+  return old;
+}
Index: trunk/src/emx/src/lib/malloc/utmalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/utmalloc.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/utmalloc.c	(revision 18)
@@ -0,0 +1,23 @@
+/* utmalloc.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+void *_utmalloc (Heap_t h, size_t size)
+{
+  void *block;
+
+  assert (h->magic == _UM_MAGIC_HEAP);
+  if (h->magic != _UM_MAGIC_HEAP)
+    return NULL;
+  _um_heap_lock (h);
+  block = _um_alloc_no_lock (h, size, 4, _UMFI_TILED);
+  _um_heap_unlock (h);
+  return block;
+}
Index: trunk/src/emx/src/lib/malloc/utype.c
===================================================================
--- trunk/src/emx/src/lib/malloc/utype.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/utype.c	(revision 18)
@@ -0,0 +1,14 @@
+/* utype.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+unsigned _uheap_type (Heap_t h)
+{
+  return h->type;
+}
Index: trunk/src/emx/src/lib/malloc/uwalk.c
===================================================================
--- trunk/src/emx/src/lib/malloc/uwalk.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/uwalk.c	(revision 18)
@@ -0,0 +1,22 @@
+/* uwalk.c (emx+gcc) -- Copyright (c) 1996-2000 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+static int _um_walk_walk1 (Heap_t h, const void *obj, size_t size, int flag,
+                           int status, const char *fname, size_t lineno,
+                           void *arg)
+{
+  return (*(_um_callback1 **)arg)(obj, size, flag, status, fname, lineno);
+}
+
+
+int _uheap_walk (Heap_t h, _um_callback1 *callback)
+{
+  return _uheap_walk2 (h, _um_walk_walk1, &callback);
+}
Index: trunk/src/emx/src/lib/malloc/uwalk2.c
===================================================================
--- trunk/src/emx/src/lib/malloc/uwalk2.c	(revision 18)
+++ trunk/src/emx/src/lib/malloc/uwalk2.c	(revision 18)
@@ -0,0 +1,21 @@
+/* uwalk2.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <umalloc.h>
+#include <sys/builtin.h>        /* For <sys/fmutex.h> */
+#include <sys/fmutex.h>         /* For <sys/rmutex.h> */
+#include <sys/rmutex.h>
+#include <emx/umalloc.h>
+
+int _uheap_walk2 (Heap_t h, _um_callback2 *callback, void *arg)
+{
+  int ret;
+
+  if (h == NULL || h->magic != _UM_MAGIC_HEAP)
+    return _HEAPBADBEGIN;
+  _um_heap_lock (h);
+  ret = _um_walk_no_lock (h, callback, arg);
+  _um_heap_unlock (h);
+  return ret;
+}
Index: trunk/src/emx/src/lib/math/386/acos.s
===================================================================
--- trunk/src/emx/src/lib/math/386/acos.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/acos.s	(revision 18)
@@ -0,0 +1,34 @@
+/ acos.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(acos)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double acos (double x)
+
+/ acos(x) = atan2 (sqrt (1-x*x), x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fld     %st
+        fmulp
+        fsubrl  __const_ONE
+        fsqrt
+        FLD     x                       /* x */
+        fpatan
+        _xam
+        j_nan   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($EDOM)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/asin.s
===================================================================
--- trunk/src/emx/src/lib/math/386/asin.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/asin.s	(revision 18)
@@ -0,0 +1,36 @@
+/ asin.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(asin)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double asin (double x)
+
+/ asin(x) = atan (x / sqrt (1-x*x))
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fld     %st
+        fld     %st
+        fmulp
+        fsubrl  __const_ONE
+        fsqrt
+        fdivrp
+        fldl    __const_ONE
+        fpatan
+        _xam
+        j_nan   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($EDOM)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/atan.s
===================================================================
--- trunk/src/emx/src/lib/math/386/atan.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/atan.s	(revision 18)
@@ -0,0 +1,22 @@
+/ atan.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(atan)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double atan (double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fldl    __const_ONE
+        fpatan
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/atan2.s
===================================================================
--- trunk/src/emx/src/lib/math/386/atan2.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/atan2.s	(revision 18)
@@ -0,0 +1,27 @@
+/ atan2.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(atan2)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double atan2 (double y, double x)
+
+#define y        4(%esp)
+#if defined (LONG_DOUBLE)
+#define x       16(%esp)
+#else
+#define x       12(%esp)
+#endif
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     y                       /* y */
+        FLD     x                       /* x */
+        fpatan
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/ceil.s
===================================================================
--- trunk/src/emx/src/lib/math/386/ceil.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/ceil.s	(revision 18)
@@ -0,0 +1,33 @@
+/ ceil.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(ceil)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double ceil (double x)
+
+#define cw1       0(%esp)
+#define cw2       2(%esp)
+/define ret_addr  4(%esp)
+#define x         8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp
+        fstcww  cw1
+        movw    cw1, %ax
+        andw    $0xf3ff, %ax
+        orw     $0x0800, %ax            /* round up towards +inf */
+        movw    %ax, cw2
+        fldcww  cw2
+        FLD     x                       /* x */
+        frndint
+        fldcww  cw1
+        addl    $4, %esp
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/clear.s
===================================================================
--- trunk/src/emx/src/lib/math/386/clear.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/clear.s	(revision 18)
@@ -0,0 +1,18 @@
+/ clear.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  LABEL(_clear87)
+
+        .text
+
+        ALIGN
+
+/ unsigned _clear87 (void)
+
+LABEL(_clear87):
+        PROFILE_NOFRAME
+        xor     %eax, %eax              /* Clear upper 16 bits */
+        fstsww  %ax
+        fclex
+        EPILOGUE(_clear87)
Index: trunk/src/emx/src/lib/math/386/consts.s
===================================================================
--- trunk/src/emx/src/lib/math/386/consts.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/consts.s	(revision 18)
@@ -0,0 +1,20 @@
+/ consts.s (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes
+
+        .globl  __const_NAN
+        .globl  __const_ONE
+        .globl  __const_ZERO
+        .globl  __const_TWO
+        .globl  __const_HALF
+        .globl  __const_M_ONE
+        .globl  __HUGE_VAL
+        .globl  __LHUGE_VAL
+
+__const_NAN:    .long   0xffffffff, 0x7fffffff
+__const_ONE:    .long   0x00000000, 0x3ff00000
+__const_ZERO:   .long   0x00000000, 0x00000000
+__const_TWO:    .long   0x00000000, 0x40000000
+__const_HALF:   .long   0x00000000, 0x3fe00000
+__const_M_ONE:  .long   0x00000000, 0xbff00000
+
+__HUGE_VAL:     .long   0x00000000, 0x7ff00000
+__LHUGE_VAL:    .long   0x00000000, 0x80000000, 0x00007fff
Index: trunk/src/emx/src/lib/math/386/control.s
===================================================================
--- trunk/src/emx/src/lib/math/386/control.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/control.s	(revision 18)
@@ -0,0 +1,35 @@
+/ control.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  LABEL(_control87)
+
+        .text
+
+        ALIGN
+
+/ unsigned _control87 (unsigned new, unsigned mask)
+
+#define cw_old          0(%esp)
+#define cw_new          2(%esp)
+/define ret_addr        4(%esp)
+#define new             8(%esp)
+#define mask            12(%esp)
+
+LABEL(_control87):
+        PROFILE_NOFRAME
+        pushl   %ecx                    /* Dummy (for control word) */
+        fstcww  cw_old                  /* Store control word into memory */
+        movl    mask, %ecx              /* Get mask */
+        jecxz   1f                      /* Do not set cw => done */
+        movl    new, %edx               /* Get new bits */
+        andl    %ecx, %edx              /* Mask new bits by mask bits */
+        notl    %ecx
+        movl    cw_old, %eax            /* Get old cw */
+        andl    %ecx, %eax              /* Apply mask to old cw */
+        orl     %edx, %eax              /* Insert new bits */
+        movw    %ax, cw_new             /* Put new cw into memory */
+        fldcww  cw_new                  /* Load control word */
+1:      popl    %eax                    /* Return old cw in lower 16 bits */
+        movzwl  %ax, %eax               /* Clear upper 16 bits */
+        EPILOGUE(_control87)
Index: trunk/src/emx/src/lib/math/386/copysig.s
===================================================================
--- trunk/src/emx/src/lib/math/386/copysig.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/copysig.s	(revision 18)
@@ -0,0 +1,61 @@
+/ copysig.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX2(copysign)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+#if defined (LONG_DOUBLE)
+
+/ long double copysignl (long double x, long double y)
+
+#define x(i)    4+i(%esp)
+#define y(i)    16+i(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movb    y(9), %al
+        andb    $0x7f, x(9)
+        andb    $0x80, %al
+        orb     %al, x(9)
+        fldt    x(0)
+        EPILOGUE(FUNC)
+
+#elif defined (FLOAT)
+
+/ float copysignf (float x, float y)
+
+#define x(i)    4+i(%esp)
+#define y(i)    8+i(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movb    y(3), %al
+        andb    $0x7f, x(3)
+        andb    $0x80, %al
+        orb     %al, x(3)
+        flds    x(0)
+        EPILOGUE(FUNC)
+
+#else
+
+/ double copysign (double x, double y)
+
+#define x(i)    4+i(%esp)
+#define y(i)    12+i(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movb    y(7), %al
+        andb    $0x7f, x(7)
+        andb    $0x80, %al
+        orb     %al, x(7)
+        fldl    x(0)
+        EPILOGUE(FUNC)
+
+#endif
Index: trunk/src/emx/src/lib/math/386/cos.s
===================================================================
--- trunk/src/emx/src/lib/math/386/cos.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/cos.s	(revision 18)
@@ -0,0 +1,30 @@
+/ cos.s (emx+gcc) -- Copyright (c) 1992-1993 by Steffen Haecker
+/                    Modified 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(cos)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double cos (double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fcos                            /* cos(x) */
+        fstsww  %ax
+        testb   $0x04, %ah                              
+        jnz     Llarge                  /* C2 != 0 ? */
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Llarge: fldl    __const_ONE             /* cos(large):=1 */
+        fstp    %st(1)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/cosh.s
===================================================================
--- trunk/src/emx/src/lib/math/386/cosh.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/cosh.s	(revision 18)
@@ -0,0 +1,54 @@
+/ cosh.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(cosh)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double cosh (double x)
+
+#define cw1      0(%esp)
+#define cw2      2(%esp)
+/define ret_addr 4(%esp)
+#define x        8(%esp)
+
+/ cosh(x) = 0.5 * (exp(x) + exp(-x)) = 0.5 * (exp(x) + 1/exp(-x))
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp                /* space for control words */
+        FLD     x                       /* x */
+        fldl2e                          /* log2 (e) */
+        fmulp                           /* y := x * log2 (e) */
+        fstcww  cw1
+        movw    cw1, %ax
+        andw    $0xf3ff, %ax
+        orw     $0x0400, %ax            /* round down towards -inf */
+        movw    %ax, cw2
+        fldcww  cw2      
+        fld     %st                     /* y, y */
+        frndint                         /* int (y), y */
+        fldcww  cw1
+        fxch    %st(1)                  /* y, int (y) */
+        fsub    %st(1), %st             /* frac (y), int (y) */
+        f2xm1                           /* 2^frac (y) - 1, int (y) */
+        faddl   __const_ONE             /* 2^frac (y), int (y) */
+        fscale                          /* 2^frac (y) * 2^int (y), int (y) */
+        fst     %st(1)                  /* exp(x), exp(x) */
+        fdivrl  __const_ONE             /* exp(-x), exp(x) */
+        faddp                           /* exp(x) + exp(-x) */
+        fmull   __const_HALF            /* 0.5 * (exp(x) + exp(-x)) */
+        CONV(x)                         /* convert to double */
+        addl    $4, %esp                /* Remove control words */
+        _xam
+        j_inf   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($ERANGE)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/exp.s
===================================================================
--- trunk/src/emx/src/lib/math/386/exp.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/exp.s	(revision 18)
@@ -0,0 +1,61 @@
+/ exp.s (emx+gcc) -- Copyright (c) 1991-2000 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(exp)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double exp (double x)
+
+#define cw1      0(%esp)
+#define cw2      2(%esp)
+/define ret_addr 4(%esp)
+#define x        8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp                /* space for control words */
+        FLD     x                       /* x */
+        fxam
+        fstsww %ax
+        andb    $0x47, %ah
+        cmpb    $5, %ah
+        je      Lreturn                 /* x = +INF => return x */
+        cmpb    $7, %ah
+        je      Lminf                   /* x = -INF => return 0 */
+        fldl2e                          /* log2 (e) */
+        fmulp                           /* y := x * log2 (e) */
+        fstcww  cw1
+        movw    cw1, %ax
+        andw    $0xf3ff, %ax
+        orw     $0x0400, %ax            /* round down towards -inf */
+        movw    %ax, cw2
+        fldcww  cw2      
+        fld     %st                     /* y, y */
+        frndint                         /* int (y), y */
+        fldcww  cw1
+        fxch    %st(1)                  /* y, int (y) */
+        fsub    %st(1), %st             /* frac (y), int (y) */
+        f2xm1                           /* 2^frac (y) - 1, int (y) */
+        faddl   __const_ONE             /* 2^frac (y), int (y) */
+        fscale                          /* 2^frac (y) * 2^int (y), int (y) */
+        fstp    %st(1)                  /* 2^frac (y) * 2^int (y) */
+        CONV(x)                         /* convert to double */
+        _xam
+        j_inf   Lerror
+Lreturn:addl    $4, %esp                /* Remove control words */
+        EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($ERANGE)
+        jmp     Lreturn
+
+        ALIGN
+Lminf:  fstp    %st(0)                  /* Pop x */
+        fldl    __const_ZERO            /* Return +0 */
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/fabs.s
===================================================================
--- trunk/src/emx/src/lib/math/386/fabs.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/fabs.s	(revision 18)
@@ -0,0 +1,21 @@
+/ fabs.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(fabs)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double fabs (double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fabs
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/floor.s
===================================================================
--- trunk/src/emx/src/lib/math/386/floor.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/floor.s	(revision 18)
@@ -0,0 +1,33 @@
+/ floor.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(floor)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double floor (double x)
+
+#define cw1       0(%esp)
+#define cw2       2(%esp)
+/define ret_addr  4(%esp)
+#define x         8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp
+        fstcww  cw1
+        movw    cw1, %ax
+        andw    $0xf3ff, %ax
+        orw     $0x0400, %ax            /* round down towards -inf */
+        movw    %ax, cw2
+        fldcww  cw2
+        FLD     x                       /* x */
+        frndint
+        fldcww  cw1
+        addl    $4, %esp
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/fmod.s
===================================================================
--- trunk/src/emx/src/lib/math/386/fmod.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/fmod.s	(revision 18)
@@ -0,0 +1,38 @@
+/ fmod.s (emx+gcc) -- Copyright (c) 1992-1993 by Steffen Haecker
+/                     Modified 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(fmod)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double fmod (double x, double y)
+
+/define ret_addr  0(%esp)
+#define x         4(%esp)
+#if defined (LONG_DOUBLE)
+#define y        16(%esp)
+#else
+#define y        12(%esp)
+#endif
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     y                       /* y */
+        ftst
+        fstsww  %ax
+        andw    $0x4100, %ax
+        xorb    $0x40, %ah
+        jz      2f                      /* y = 0 ? */
+        FLD     x                       /* x */
+1:      fprem
+        fstsww  %ax
+        andb    $0x04, %ah
+        jnz     1b                      /* C2 != 0 ? */
+        fstp    %st(1)
+2:      EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/fpclass.s
===================================================================
--- trunk/src/emx/src/lib/math/386/fpclass.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/fpclass.s	(revision 18)
@@ -0,0 +1,116 @@
+/ fpclass.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX3(__fpclassify)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+#if defined (LONG_DOUBLE)
+
+/ int __fpclassifyl (long double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        fldt    x
+        fxam
+        fstsww  %ax
+        fstp    %st(0)
+        movb    %ah, %al
+        andl    $0x47, %eax
+        movb    Ltable(%eax), %al
+        EPILOGUE(FUNC)
+
+Ltable: .byte   FP_NAN          /* +unnormal, not supported by 387 */
+        .byte   FP_NAN          /* -unnormal, not supported by 387 */
+        .byte   FP_NAN          /* +NaN */
+        .byte   FP_NAN          /* -NaN */
+        .byte   FP_NORMAL       /* +normal */
+        .byte   FP_INFINITE     /* +infinity */
+        .byte   FP_NORMAL       /* -normal */
+        .byte   FP_INFINITE     /* -infinity */
+        .byte   FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN
+        .byte   FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN
+        .byte   FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN
+        .byte   FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN
+        .byte   FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN
+        .byte   FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN
+        .byte   FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN, FP_NAN
+        .byte   FP_ZERO         /* +zero */
+        .byte   FP_NAN          /* empty */
+        .byte   FP_ZERO         /* -zero */
+        .byte   FP_NAN          /* empty */
+        .byte   FP_SUBNORMAL    /* +denormal */
+        .byte   FP_NAN          /* empty, not supported by 387 */
+        .byte   FP_SUBNORMAL    /* -denormal */
+        .byte   FP_NAN          /* empty, not supported by 387 */
+
+#elif defined (FLOAT)
+
+/ int __fpclassifyf (float x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    x, %edx
+        movl    $FP_ZERO, %eax          /* Clear upper 24 bits */
+        andl    $0x7fffffff, %edx
+        jz      Lreturn
+        movb    $FP_SUBNORMAL, %al
+        cmpl    $0x00800000, %edx
+        jb      Lreturn
+        movb    $FP_NORMAL, %al
+        cmpl    $0x7f800000, %edx
+        jb      Lreturn
+        movb    $FP_INFINITE, %al
+        je      Lreturn
+        movb    $FP_NAN, %al
+        ALIGN
+Lreturn:
+        EPILOGUE(FUNC)
+
+#else
+
+/ int __fpclassify (double x)
+
+#define x0      4(%esp)
+#define x4      8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    x4, %edx
+        movl    $FP_NORMAL, %eax                /* Clear upper 24 bits */
+        andl    $0x7ff00000, %edx
+        jz      Lexp0
+        cmpl    $0x7ff00000, %edx
+        je      Lexpmax
+        ALIGN
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lexp0:  movb    $FP_SUBNORMAL, %al
+        testl   $0x000fffff, x4
+        jnz     Lreturn
+        cmpl    $0, x0
+        jne     Lreturn
+        movb    $FP_ZERO, %al
+        jmp     Lreturn
+
+        ALIGN
+Lexpmax:testl   $0x000fffff, x4
+        jnz     Lnan
+        movb    $FP_INFINITE, %al
+        cmpl    $0, x0
+        je      Lreturn
+        ALIGN
+Lnan:   movb    $FP_NAN, %al
+        jmp     Lreturn
+
+#endif
Index: trunk/src/emx/src/lib/math/386/fpreset.s
===================================================================
--- trunk/src/emx/src/lib/math/386/fpreset.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/fpreset.s	(revision 18)
@@ -0,0 +1,16 @@
+/ fpreset.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  LABEL(_fpreset)
+
+        .text
+
+        ALIGN
+
+/ void _fpreset (void)
+
+LABEL(_fpreset):
+        PROFILE_NOFRAME
+        finit
+        EPILOGUE(_fpreset)
Index: trunk/src/emx/src/lib/math/386/frexp.s
===================================================================
--- trunk/src/emx/src/lib/math/386/frexp.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/frexp.s	(revision 18)
@@ -0,0 +1,40 @@
+/ frexp.s (emx+gcc) -- Copyright (c) 1992-1993 by Steffen Haecker
+/                      Modified 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(frexp)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double frexp (double x, int *exp_ptr)
+
+#define x       4(%esp)
+#if defined (LONG_DOUBLE)
+#define exp_ptr 16(%esp)
+#else
+#define exp_ptr 12(%esp)
+#endif
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    exp_ptr, %edx
+        movl    $0, (%edx)
+        fldl    __const_M_ONE           /* -1 */
+        FLD     x                       /* x */
+        ftst
+        fstsww  %ax
+        andw    $0x4100, %ax
+        xorb    $0x40, %ah
+        jz      1f                      /* x = 0 ? */
+        fxtract
+        fxch    %st(1)
+        fistpl  (%edx)
+        fscale
+        incl    (%edx)
+1:      fstp    %st(1)
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/fxam.s
===================================================================
--- trunk/src/emx/src/lib/math/386/fxam.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/fxam.s	(revision 18)
@@ -0,0 +1,31 @@
+/ fxam.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX2(fxam)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ int _fxam (double x)
+/ int _fxaml (long double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fxam
+        fstsww  %ax
+        fstp    %st(0)
+        movl    %eax, %edx
+        shrl    $8, %eax
+        andl    $7, %eax
+        test    $0x4000, %edx
+        jz      Lreturn
+        orl     $8, %eax
+Lreturn:
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/hypot.s
===================================================================
--- trunk/src/emx/src/lib/math/386/hypot.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/hypot.s	(revision 18)
@@ -0,0 +1,44 @@
+/ hypot.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+/ As the arguments are double and the computation is done in extended
+/ format, an iterative method or scaling is not required to avoid overflow.
+/ However, such an algorithm should perhaps be used for _hypotl().
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX2(hypot)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double _hypot (double x, double y)
+
+#define x        4(%esp)
+#if defined (LONG_DOUBLE)
+#define y       16(%esp)
+#else
+#define y       12(%esp)
+#endif
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fld     %st                     /* x, x */
+        fmulp                           /* x*x */
+        FLD     y                       /* y, x*x */
+        fld     %st                     /* y, y, x*x */
+        fmulp                           /* y*y, x*x */
+        faddp                           /* y*y + x*x */
+        fsqrt                           /* hypot (x, y) */
+        CONV(x)                         /* convert to double */
+        _xam
+        j_inf   Lerror
+Lreturn:
+        EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($ERANGE)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/isfin.s
===================================================================
--- trunk/src/emx/src/lib/math/386/isfin.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/isfin.s	(revision 18)
@@ -0,0 +1,85 @@
+/ isfin.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX3(__isfinite)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+#if defined (LONG_DOUBLE)
+
+/ int __isfinitel (long double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        fldt    x
+        fxam
+        fstsww  %ax
+        fstp    %st(0)
+        movb    %ah, %al
+        andl    $0x47, %eax
+        movb    Ltable(%eax), %al
+        EPILOGUE(FUNC)
+
+Ltable: .byte   0               /* +unnormal, not supported by 387 */
+        .byte   0               /* -unnormal, not supported by 387 */
+        .byte   0               /* +NaN */
+        .byte   0               /* -NaN */
+        .byte   1               /* +normal */
+        .byte   0               /* +infinity */
+        .byte   1               /* -normal */
+        .byte   0               /* -infinity */
+        .byte   0, 0, 0, 0, 0, 0, 0, 0
+        .byte   0, 0, 0, 0, 0, 0, 0, 0
+        .byte   0, 0, 0, 0, 0, 0, 0, 0
+        .byte   0, 0, 0, 0, 0, 0, 0, 0
+        .byte   0, 0, 0, 0, 0, 0, 0, 0
+        .byte   0, 0, 0, 0, 0, 0, 0, 0
+        .byte   0, 0, 0, 0, 0, 0, 0, 0
+        .byte   1               /* +zero */
+        .byte   0          /* empty */
+        .byte   1               /* -zero */
+        .byte   0          /* empty */
+        .byte   1               /* +denormal */
+        .byte   0          /* empty, not supported by 387 */
+        .byte   1               /* -denormal */
+        .byte   0          /* empty, not supported by 387 */
+
+#elif defined (FLOAT)
+
+/ int __isfinitef (float x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    x, %edx
+        xorl    %eax, %eax
+        andl    $0x7fffffff, %edx
+        cmpl    $0x7f800000, %edx
+        setb    %al
+        EPILOGUE(FUNC)
+
+#else
+
+/ int __isfinite (double x)
+
+#define x0      4(%esp)
+#define x4      8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    x4, %edx
+        xorl    %eax, %eax
+        andl    $0x7ff00000, %edx
+        cmpl    $0x7ff00000, %edx
+        setne   %al
+        EPILOGUE(FUNC)
+
+#endif
Index: trunk/src/emx/src/lib/math/386/isnan.s
===================================================================
--- trunk/src/emx/src/lib/math/386/isnan.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/isnan.s	(revision 18)
@@ -0,0 +1,92 @@
+/ isnan.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX3(__isnan)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+#if defined (LONG_DOUBLE)
+
+/ int __isnanl (long double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        fldt    x
+        fxam
+        fstsww  %ax
+        fstp    %st(0)
+        movb    %ah, %al
+        andl    $0x47, %eax
+        movb    Ltable(%eax), %al
+        EPILOGUE(FUNC)
+
+Ltable: .byte   1               /* +unnormal, not supported by 387 */
+        .byte   1               /* -unnormal, not supported by 387 */
+        .byte   1               /* +NaN */
+        .byte   1               /* -NaN */
+        .byte   0               /* +normal */
+        .byte   0               /* +infinity */
+        .byte   0               /* -normal */
+        .byte   0               /* -infinity */
+        .byte   1, 1, 1, 1, 1, 1, 1, 1
+        .byte   1, 1, 1, 1, 1, 1, 1, 1
+        .byte   1, 1, 1, 1, 1, 1, 1, 1
+        .byte   1, 1, 1, 1, 1, 1, 1, 1
+        .byte   1, 1, 1, 1, 1, 1, 1, 1
+        .byte   1, 1, 1, 1, 1, 1, 1, 1
+        .byte   1, 1, 1, 1, 1, 1, 1, 1
+        .byte   0               /* +zero */
+        .byte   1               /* empty */
+        .byte   0               /* -zero */
+        .byte   1               /* empty */
+        .byte   0               /* +denormal */
+        .byte   1               /* empty, not supported by 387 */
+        .byte   0               /* -denormal */
+        .byte   1               /* empty, not supported by 387 */
+
+#elif defined (FLOAT)
+
+/ int __isnanf (float x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    x, %edx
+        xorl    %eax, %eax
+        andl    $0x7fffffff, %edx
+        cmpl    $0x7f800000, %edx
+        seta    %al
+        EPILOGUE(FUNC)
+
+#else
+
+/ int __isnan (double x)
+
+#define x0      4(%esp)
+#define x4      8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    x4, %edx
+        xorl    %eax, %eax
+        andl    $0x7fffffff, %edx
+        cmpl    $0x7ff00000, %edx
+        je      Linf
+        seta    %al
+        ALIGN
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Linf:   cmpl    $0, x0
+        setne   %al
+        jmp     Lreturn
+
+#endif
Index: trunk/src/emx/src/lib/math/386/isnorm.s
===================================================================
--- trunk/src/emx/src/lib/math/386/isnorm.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/isnorm.s	(revision 18)
@@ -0,0 +1,64 @@
+/ isnorm.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX3(__isnormal)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+#if defined (LONG_DOUBLE)
+
+/ int __isnormall (long double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        fldt    x
+        fxam
+        fstsww  %ax
+        fstp    %st(0)
+        movb    %ah, %al
+        andl    $0x45, %eax
+        cmpb    $0x04, %al
+        sete    %al
+        EPILOGUE(FUNC)
+
+#elif defined (FLOAT)
+
+/ int __isnormalf (float x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    x, %edx
+        xorl    %eax, %eax
+        andl    $0x7fffffff, %edx
+        subl    $0x00800000, %edx
+        cmpl    $0x7f000000, %edx
+        setb    %al
+        EPILOGUE(FUNC)
+
+#else
+
+/ int __isnormal (double x)
+
+#define x0      4(%esp)
+#define x4      8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        movl    x4, %edx
+        xorl    %eax, %eax
+        andl    $0x7ff00000, %edx
+        subl    $0x00100000, %edx
+        cmpl    $0x7fe00000, %edx
+        setb    %al
+        EPILOGUE(FUNC)
+
+#endif
Index: trunk/src/emx/src/lib/math/386/ldexp.s
===================================================================
--- trunk/src/emx/src/lib/math/386/ldexp.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/ldexp.s	(revision 18)
@@ -0,0 +1,35 @@
+/ ldexp.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(ldexp)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double ldexp (double x, int exp)
+
+#define x        4(%esp)
+#if defined (LONG_DOUBLE)
+#define exp     16(%esp)
+#else
+#define exp     12(%esp)
+#endif
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        fildl   exp                     /* exp */
+        FLD     x                       /* x */
+        fscale
+        fstp    %st(1)
+        CONV(x)                         /* convert to double */
+        _xam
+        j_inf   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($ERANGE)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/log.s
===================================================================
--- trunk/src/emx/src/lib/math/386/log.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/log.s	(revision 18)
@@ -0,0 +1,36 @@
+/ log.s (emx+gcc) -- Copyright (c) 1991-2000 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(log)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double log (double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fxam
+        fstsww %ax
+        andb    $0x47, %ah
+        cmpb    $5, %ah
+        je      Lreturn                 /* x = +INF => return x */
+        fldl2e
+        fdivrl  __const_ONE
+        fxch    %st(1)
+        fyl2x
+        _xam
+        j_nan   Lerror
+        j_inf   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($EDOM)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/log10.s
===================================================================
--- trunk/src/emx/src/lib/math/386/log10.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/log10.s	(revision 18)
@@ -0,0 +1,36 @@
+/ log10.s (emx+gcc) -- Copyright (c) 1991-2000 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(log10)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double log10 (double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fxam
+        fstsww %ax
+        andb    $0x47, %ah
+        cmpb    $5, %ah
+        je      Lreturn                 /* x = +INF => return x */
+        fldl2t
+        fdivrl  __const_ONE
+        fxch    %st(1)
+        fyl2x
+        _xam
+        j_nan   Lerror
+        j_inf   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($EDOM)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/modf.s
===================================================================
--- trunk/src/emx/src/lib/math/386/modf.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/modf.s	(revision 18)
@@ -0,0 +1,46 @@
+/ modf.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(modf)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double modf (double x, double *intptr)
+
+#define cw1       0(%esp)
+#define cw2       2(%esp)
+/define ret_addr  4(%esp)
+#define x         8(%esp)
+#if defined (LONG_DOUBLE)
+#define intptr   20(%esp)
+#else
+#define intptr   16(%esp)
+#endif
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp
+        fstcww  cw1
+        movw    cw1, %ax
+        orw     $0x0c00, %ax            /* chop mode */
+        movw    %ax, cw2
+        movl    intptr, %eax
+        fldcww  cw2
+        FLD     x                       /* x */
+        fld     %st
+        frndint
+#if defined (LONG_DOUBLE)
+        fld     %st                     /* there is no fstt, use fstpt */
+        fstpt   (%eax)
+#else
+        fstl    (%eax)
+#endif
+        fldcww  cw1
+        fsubrp
+        addl    $4, %esp
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/nextaft.s
===================================================================
--- trunk/src/emx/src/lib/math/386/nextaft.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/nextaft.s	(revision 18)
@@ -0,0 +1,323 @@
+/ nextaft.s (emx+gcc) -- Copyright (c) 1996-1998 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX2(nextafter)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+#if defined (LONG_DOUBLE)
+
+/ long double nextafterl (long double x, long double y)
+
+#define x(i)    4+i(%esp)
+#define y(i)    16+i(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        fldt    x(0)
+        fldt    y(0)
+        fucompp
+        fstsww  %ax
+        testb   $0x04, %ah
+        jnz     Lunordered              /* Unordered (at least one NaN) */
+        testb   $0x40, %ah
+        jnz     Leq                     /* x==y */
+        movb    x(9), %al
+        shrb    $7, %al                 /* signbit(x) -> bit 0 of %al */
+        xorb    %ah, %al                /* Note: bit 0 of %ah is 1 iff x>y */
+        testb   $0x01, %al
+        movw    x(8), %ax               /* Fetch exponent */
+        jnz     Ldown                   /* Decrement mantissa */
+
+/* Increment mantissa. */
+
+Lup:    andl    $0x7fff, %eax           /* Clear sign bit */
+        cmpl    $0x7fff, %eax           /* Infinity? */
+        je      Lreturn_x               /* Yes => return x */
+        addl    $1, x(0)                /* Increment lower word */
+        adcl    $0, x(4)                /* Propagate carry into upper word */
+        jc      Lup_of                  /* Overflow */
+        testl   %eax, %eax              /* Denormal? */
+        jnz     Lreturn_x               /* No => return x */
+        testb   $0x80, x(7)             /* Pseudo-denormal? */
+        jz      Lreturn_x_exception     /* No => return x, raise exceptions */
+        incw    x(8)                    /* Turn it into a normal */
+        jmp     Lreturn_x
+
+/* Return x and raise appropriate exceptions (inexact and
+   underflow/overflow). */
+
+        ALIGN
+Lreturn_x_exception:
+        fldt    x(0)
+        fstl    y(0)                    /* This raises the exceptions */
+        jmp     Lreturn                 /* (we store as 64-bit number!) */
+
+/* Mantissa overflow.  Increment exponent. */
+
+        ALIGN
+Lup_of: cmpl    $0x7ffe, %eax           /* Exponent overflow? */
+        je      Lup_make_inf            /* Yes => return infinity */
+        movb    $0x80, x(7)             /* Set mantissa to 100...000 */
+        incw    x(8)                    /* Increment exponent */
+        jmp     Lreturn_x               /* Return x */
+
+/* x is LDBL_MAX, raise overflow and inexact exceptions,
+   return infinity. */
+
+        ALIGN
+Lup_make_inf:
+        movl    $0xffffffff, x(0)       /* Restore mantissa of x */
+        movl    $0xffffffff, x(4)
+        fldt    x(0)                    /* Compute x+x */
+        fadd    %st
+        jmp     Lreturn
+
+/* Decrement mantissa. */
+
+        ALIGN
+Ldown:  andl    $0x7fff, %eax           /* Clear sign bit */
+        cmpl    $0x7fff, %eax           /* Infinity? */
+        je      Ldown_is_inf            /* Yes => return biggest normal */
+        subl    $1, x(0)                /* Decrement lower word */
+        sbbl    $0, x(4)                /* Propagate carry into upper word */
+        jc      Ldown_uf0               /* Underflow (integer bit was 0) */
+        jo      Ldown_uf1               /* Underflow (integer bit was 1) */
+        test    %eax, %eax              /* Is the exponent zero? */
+        jnz     Lreturn_x               /* No => return x */
+        jmp     Lreturn_x_exception     /* Yes => maybe raise exceptions */
+
+/* Underflow (mantissa was 100...000 and is now 011...111).  Decrement
+   the exponent.  Return the biggest denormal if the exponent becomes 0. */
+
+        ALIGN
+Ldown_uf1:
+        decw    x(8)                    /* Decrement exponent */
+        cmp     $1, %eax                /* Exponent now zero? */
+        je      Lreturn_x_exception     /* Yes => return x (mantissa OK) */
+
+/* It's still a normal.  Set the mantissa to 111...111. */
+
+        orb     $0x80, x(7)
+        jmp     Lreturn_x
+
+/* Underflow (mantissa was 000...000 and is now 111...111.  Return
+   the smallest denormal with y's sign. */
+
+        ALIGN
+Ldown_uf0:
+        movl    $1, y(0)
+        movl    $0, y(4)
+        andw    $0x8000, y(8)
+        fldt    y(0)
+        fstl    y(0)                    /* This raises the exceptions */
+        jmp     Lreturn
+
+/* x is infinite.  Return the biggest normal with x's sign. */
+
+        ALIGN
+Ldown_is_inf:
+        movl    $0xffffffff, x(0)
+        movl    $0xffffffff, x(4)
+        andw    $0x8000, x(8)
+        orw     $0x7ffe, x(8)
+        jmp     Lreturn_x
+
+/* Unordered: return one of the NaNs. */
+
+        ALIGN
+Lunordered:
+        fldt    x(0)
+        _xam
+        j_nan   Lreturn                 /* x is a Nan => return x */
+        fstp    %st(0)                  /* Remove x */
+
+/* Fall through to return y */
+
+/* x==y: return y. */
+
+        ALIGN
+Leq:    fldt    y(0)
+        jmp     Lreturn
+
+        ALIGN
+Lreturn_x:
+        fldt    x(0)
+
+        ALIGN
+Lreturn:
+        EPILOGUE(FUNC)
+
+#elif defined (FLOAT)
+
+/ float nextafterf (float x, float y)
+
+#define x       4(%esp)
+#define y       8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        flds    x
+        flds    y
+        fucompp
+        fstsww  %ax
+        testb   $0x04, %ah
+        jnz     Lunordered              /* Unordered (at least one NaN) */
+        testb   $0x40, %ah
+        jnz     Leq                     /* x==y */
+        movl    x, %edx
+        shrl    $31, %edx               /* signbit(x) -> bit 0 of %dl */
+        xorb    %ah, %dl                /* Note: bit 0 of %ah is 1 iff x>y */
+        testb   $0x01, %dl
+        movl    $1, %ecx                /* Increment */
+        jz      Lcommon
+        movl    $-1, %ecx               /* TODO: Do this without jump */
+        ALIGN
+Lcommon:movl    x, %eax
+        andl    $0x7fffffff, %eax       /* Clear sign bit */
+        jz      Lx_zero                 /* x = 0.0 => smallest denormal */
+        addl    %ecx, x
+        movl    x, %edx
+        andl    $0x7fffffff, %edx
+        jz      Lreturn_x               /* 0.0 => no underflow */
+        cmpl    $0x7f800000, %edx
+        je      Loverflow
+        cmpl    $0x00800000, %edx
+        jb      Lunderflow
+        ALIGN
+Lreturn_x:
+        flds    x
+        ALIGN
+Lreturn:
+        EPILOGUE(FUNC)
+
+        ALIGN
+Lx_zero:
+        movl    y, %eax
+        andl    $0x80000000, %eax       /* Extract sign bit of y */
+        orl     $0x00000001, %eax       /* Smallest denormal */
+        movl    %eax, x
+        ALIGN
+Lunderflow:
+        fldl    Lsmall
+        fstps   y
+        jmp     Lreturn_x
+
+        ALIGN
+Loverflow:
+        fldl    Lbig
+        fstps   y                       /* Raise overflow and inexact */
+        jmp     Lreturn_x
+
+        ALIGN
+Lunordered:
+        movl    x, %eax
+        andl    $0x7fffffff, %eax
+        cmpl    $0x7f800000, %eax
+        ja      Lreturn_x               /* x is a NaN => return x */
+
+/* Fall through to return y (which is a NaN) */
+
+        ALIGN
+Leq:    flds    y
+        jmp     Lreturn
+
+Lsmall: .long   0x00000001, 0x00000000
+Lbig:   .long   0xffffffff, 0x7fefffff
+
+#else
+
+/ double nextafter (double x, double y)
+
+#define x(i)    4+i(%esp)
+#define y(i)    12+i(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        fldl    x(0)
+        fldl    y(0)
+        fucompp
+        fstsww  %ax
+        testb   $0x04, %ah
+        jnz     Lunordered              /* Unordered (at least one NaN) */
+        testb   $0x40, %ah
+        jnz     Leq                     /* x==y */
+
+        movb    x(7), %dl
+        shrb    $7, %dl                 /* signbit(x) -> bit 0 of %dl */
+        xorb    %ah, %dl                /* Note: bit 0 of %ah is 1 iff x>y */
+
+        movl    x(4), %eax
+        andl    $0x7fffffff, %eax       /* Clear sign bit */
+        orl     x(0), %eax              /* x == 0.0? */
+        jz      Lx_zero                 /* Yes => smallest denormal */
+        testb   $0x01, %dl
+        jnz     Ldec
+        addl    $1, x(0)
+        adcl    $0, x(4)
+        ALIGN
+Lcommon:movl    x(4), %eax
+        andl    $0x7fffffff, %eax       /* Clear sign bit */
+        orl     x(0), %eax
+        jz      Lreturn_x               /* 0.0 => no underflow */
+        movl    x(4), %eax
+        andl    $0x7ff00000, %eax       /* Extract exponent */
+        cmpl    $0x7ff00000, %eax
+        je      Loverflow
+        cmpl    $0x00100000, %eax
+        jb      Lunderflow
+        ALIGN
+Lreturn_x:
+        fldl    x(0)
+        ALIGN
+Lreturn:
+        EPILOGUE(FUNC)
+
+        ALIGN
+Ldec:   subl    $1, x(0)
+        sbbl    $0, x(4)
+        jmp     Lcommon
+
+        ALIGN
+Lx_zero:
+        andl    $0x80000000, y(4)       /* Keep sign bit of y */
+        movl    $0x00000001, y(0)       /* Smallest denormal */
+        fldl    Lsmall
+        fstps   x(0)
+        fldl    y(0)
+        jmp     Lreturn
+
+        ALIGN
+Lunderflow:
+        fldl    Lsmall
+        fstps   y(0)
+        jmp     Lreturn_x
+
+        ALIGN
+Loverflow:
+        fldl    Lbig
+        fstps   y(0)                    /* Raise overflow and inexact */
+        jmp     Lreturn_x
+
+        ALIGN
+Lunordered:
+        movl    x(4), %eax
+        andl    $0x7fffffff, %eax
+        cmpl    $0x7ff80000, %eax
+        jae     Lreturn_x               /* x is a NaN => return x */
+
+/* Fall through to return y (which is a NaN) */
+
+        ALIGN
+Leq:    fldl    y(0)
+        jmp     Lreturn
+
+Lsmall: .long   0x00000001, 0x00000000
+Lbig:   .long   0xffffffff, 0x7fefffff
+
+#endif
Index: trunk/src/emx/src/lib/math/386/pow.s
===================================================================
--- trunk/src/emx/src/lib/math/386/pow.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/pow.s	(revision 18)
@@ -0,0 +1,318 @@
+/ pow.s (emx+gcc) -- Copyright (c) 1991-1993 by Kolja Elsaesser
+/                    Modified 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(pow)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double pow (double x, double y)
+
+#define cw_user       -4(%ebp)
+#define cw_chop       -2(%ebp)
+/define saved_ebp      0(%ebp)
+/define ret_addr       4(%ebp)
+#define x              8(%ebp)
+#if defined (LONG_DOUBLE)
+#define y             20(%ebp)
+#else
+#define y             16(%ebp)
+#endif
+
+LABEL(FUNC):
+        pushl   %ebp
+        movl    %esp, %ebp
+        PROFILE_FRAME
+        subl    $4, %esp
+        pushf                           /* Save flags */
+        fstcww  cw_user
+        movw    cw_user, %ax
+        orw     $0x0c00, %ax            /* Chop by truncating toward 0 */
+        movw    %ax, cw_chop
+        FLD     y
+        fxam
+        fstsww %ax
+        movb    %ah, %al
+        andb    $0x47, %al
+        cmpb    $5, %al
+        je      Ly_pinf                 /* y = +INF */
+        cmpb    $7, %al
+        je      Ly_minf                 /* y = -INF */
+        andb    $0x45, %al
+        cmpb    $1, %al
+        je      Ly_nan                  /* y = NAN */
+        cmpb    $0x40, %al
+        je      Ly_zero                 /* y = 0 */
+        movb    %ah, %cl                /* cl := fxam(y) */
+
+/ -INF < y < 0 or 0 < y < INF.  Check x.
+
+        FLD     x
+        fxam
+        fstsww  %ax
+        movb    %ah, %al
+        andb    $0x47, %al
+        cmpb    $5, %al
+        je      Lx_pinf                 /* x = +INF */
+        cmpb    $7, %al
+        je      Lx_minf                 /* x = -INF */
+        andb    $0x45, %al
+        cmpb    $1, %al
+        je      Lx_nan                  /* x = NAN */
+        cmpb    $0x40, %al
+        je      Lx_zero                 /* x = 0 */
+        test    $2, %ah
+        jnz     Lx_neg                  /* x < 0 */
+
+/ x > 0, y non-zero and finite
+
+Lx_pos: call    Lpower
+        jmp     Ldone
+
+/ x > 0, y non-zero and finite, overflow of y*log(x)
+        ALIGN
+Lx_pos_ov:
+        FLD     x
+        fcomps  Lone
+        fnstsww %ax
+        sahf
+        ja      Ldone
+        fchs
+        jmp     Ldone
+
+/ x = 0, y non-zero and finite
+
+        ALIGN
+Lx_zero:testb   $2, %cl
+        jnz     Lx_zero_y_neg
+
+/ x = 0, y > 0
+
+        fxch    %st(1)                  /* st(0) := y, st(1) := x */
+        call    Lis_odd_int
+        fstp    %st(0)                  /* Pop y */
+        cmpl    $1, %eax                /* Odd integer? */
+        je      Ldone                   /* Yes: return x (+0 or -0) */
+        fstp    %st(0)                  /* Pop x */
+        fldl    __const_ZERO            /* No: return +0 */
+        jmp     Ldone
+
+/ x = 0, y < 0
+Lx_zero_y_neg:
+        movb    %ah, %ch                /* ch := fxam(x) */
+        fxch    %st(1)                  /* st(0) := y, st(1) := x */
+        call    Lis_odd_int
+        fstp    %st(0)                  /* Pop y */
+        cmpl    $1, %eax                /* Odd integer? */
+        je      L1                      /* Yes: return 1/x (divide by zero) */
+        fstp    %st(0)                  /* Pop x */
+        fldl    __const_ZERO
+L1:     fdivrs  Lone
+        jmp     Ldone
+
+/ x = +INF, y non-zero and finite 
+        ALIGN
+Lx_pinf:fstp    %st(1)                  /* pop x, st(0):=x */
+        testb   $2, %cl                 /* y > 0? */
+        jz      Ldone                   /* Yes: return x = +INF */
+        fstp    %st(0)                  /* Pop x */
+        fldl    __const_ZERO            /* Return +0 */
+        jmp     Ldone
+
+/ x = -INF, y non-zero and finite 
+        ALIGN
+Lx_minf:testb   $2, %cl                 /* y < 0? */
+        jnz     Lx_minf_y_neg           /* Yes -> return +0 or -0 */
+        fxch    %st(1)                  /* st(0) := y, st(1) := x */
+        call    Lis_odd_int
+        fstp    %st(0)                  /* Pop y */
+        cmpl    $1, %eax                /* Is y an odd integer? */
+        je      Ldone                   /* Yes: return x = -INF */
+        fchs                            /* No: return -x = +INF */
+        jmp     Ldone
+
+/ x = +INF, y < 0 and finite
+        ALIGN
+Lx_minf_y_neg:
+        fstp    %st(0)                  /* Pop x */
+        call    Lis_odd_int
+        fstp    %st(0)                  /* Pop y */
+        fldl    __const_ZERO
+        cmpl    $1, %eax                /* Is y an odd integer? */
+        jne     Ldone                   /* No: return +0 */
+        fchs                            /* Yes: return -0 */
+        jmp     Ldone
+
+/ x = NAN, y non-zero and finite
+        ALIGN
+Lx_nan: fstp    %st(1)
+        jmp     Ldone
+
+/ y = 0
+        ALIGN
+Ly_zero:
+        fstp    %st(0)
+        flds    Lone
+        jmp     Ldone
+
+/ x < 0, y non-zero and finite
+        ALIGN
+Lx_neg: fxch    %st(1)                  /* st(0) := y, st(1) := x */
+        call    Lis_odd_int
+        cmp     $0, %eax                /* Is y an integer? */
+        je      Lx_neg_invalid          /* No -> return NAN */
+        fxch    %st(1)                  /* st(0) := x, st(1) := y */
+        fchs                            /* st(0) := -x */
+        movl    %eax, %ecx              /* Remember whether y is odd or not */
+        call    Lpower
+/ Change sign if y is odd
+        cmpl    $1, %ecx
+        jne     Ldone
+        fchs
+        jmp     Ldone
+
+/ x < 0, y not an integer
+        ALIGN
+Lx_neg_invalid:
+        fstp    %st(0)                  /* Pop y */
+        fstp    %st(0)                  /* Pop x */
+        jmp     Linvalid
+
+        ALIGN
+Ly_nan:                                 /* pow(x,NAN) = NAN */
+Ldone:  CONV(x)                         /* convert to double */
+        popf
+        leave
+        _xam
+        j_inf   Lerange
+        j_nan   Ledom
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerange:SET_ERRNO_CONST($ERANGE)
+        jmp     Lreturn
+
+        ALIGN
+Ledom:  SET_ERRNO_CONST($EDOM)
+        jmp     Lreturn
+
+/ pow(x,+INF)
+        ALIGN
+Ly_pinf:fstp    %st(0)
+        FLD     x
+        _xam
+        j_nan   Ldone
+        fabs
+        fcoms   Lone
+        fnstsww %ax
+        fstp    %st(0)
+        sahf
+        jz      Linvalid
+        ja      Lret_pinf
+Lret_zero:
+        fldl    __const_ZERO
+        jmp     Ldone
+
+/ pow(x,-INF)
+        ALIGN
+Ly_minf:fstp    %st(0)                  /* Pop y */
+        FLD     x
+        _xam
+        j_nan   Ldone
+        fabs
+        fcoms   Lone
+        fnstsww %ax
+        fstp    %st(0)                  /* Pop x */
+        sahf
+        jz      Linvalid
+        ja      Lret_zero
+Lret_pinf:
+        fldl    __HUGE_VAL
+        jmp     Ldone
+
+        ALIGN
+Linvalid:
+        fldl    __const_ZERO
+        fdivl   __const_ZERO
+        jmp     Ldone
+
+
+/ Check if x (in st(0)) is an odd integer
+/ Returns:
+/	0       x is not an integer
+/       1       x is an odd integer
+/       2       x is an even integer (or too big to be odd)
+/ x is not removed from the stack
+        ALIGN
+Lis_odd_int:
+        fld     %st                     /* st(0)=x, st(1)=x */
+        fldcww  cw_chop
+        frndint                         /* st(0)=int(x), st(1)=x */
+        fldcww  cw_user
+        fcom    %st(1)
+        fnstsww %ax
+        sahf
+        jnz     Lnot_int                /* x not an integer */
+        fmuls   Lhalf                   /* st(0)=x/2, st(1)=x */
+        fldcww  cw_chop
+        frndint
+        fldcww  cw_user
+        fmuls   Ltwo                    /* st(0)=2*(x/2), st(1)=x */
+        fcomp   %st(1)
+        fnstsww %ax
+        sahf
+        jnz     Lodd
+        movl    $2, %eax
+        ret
+
+        ALIGN
+Lodd:   movl    $1, %eax
+        ret
+
+        ALIGN
+Lnot_int:
+        fstp    %st(0)                  /* pop int(x) */
+        movl    $0, %eax
+        ret
+
+/ Compute st(0) ^ st(1)
+/ Note:  References x!
+
+        ALIGN
+Lpower:
+        fyl2x                           /* st(1) * log(st(0)) */
+        _xam
+        j_inf   Lpower_overflow
+        fld     %st
+        fldcww  cw_chop
+        frndint
+        fldcww  cw_user
+        fsubr   %st, %st(1)
+        fxch    %st(1)
+        f2xm1
+        fadds   Lone    /* TODO: to avoid overflow, scale 1.0, add later */
+        fscale
+        fstp    %st(1)                  /* Remove the scaling factor */
+        ret
+
+        ALIGN
+Lpower_overflow:
+        fabs
+        FLD     x
+        fabs
+        fcomps  Lone
+        fnstsww %ax
+        sahf
+        ja      Lpower_ret
+        fdivrs  Lone
+Lpower_ret:
+        ret
+
+Lhalf:  .long 0x3f000000
+Lone:   .long 0x3f800000
+Ltwo:   .long 0x40000000
Index: trunk/src/emx/src/lib/math/386/rint.s
===================================================================
--- trunk/src/emx/src/lib/math/386/rint.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/rint.s	(revision 18)
@@ -0,0 +1,32 @@
+/ rint.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX2(rint)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double _rint (double x)
+
+#define cw1       0(%esp)
+#define cw2       2(%esp)
+/define ret_addr  4(%esp)
+#define x         8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp
+        fstcww  cw1
+        movw    cw1, %ax
+        andw    $0xf3ff, %ax            /* round to nearest or even */
+        movw    %ax, cw2
+        fldcww  cw2
+        FLD     x                       /* x */
+        frndint
+        fldcww  cw1
+        addl    $4, %esp
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/386/signbit.s
===================================================================
--- trunk/src/emx/src/lib/math/386/signbit.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/signbit.s	(revision 18)
@@ -0,0 +1,55 @@
+/ signbit.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX3(__signbit)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+#if defined (LONG_DOUBLE)
+
+/ int __signbitl (long double x)
+
+#define x0      4(%esp)
+#define x9      13(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        xorl    %eax, %eax
+        testb   $0x80, x9
+        setnz   %al
+        EPILOGUE(FUNC)
+
+#elif defined (FLOAT)
+
+/ int __signbitf (float x)
+
+#define x0      4(%esp)
+#define x3      7(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        xorl    %eax, %eax
+        testb   $0x80, x3
+        setnz   %al
+        EPILOGUE(FUNC)
+
+#else
+
+/ int __signbit (double x)
+
+#define x0      4(%esp)
+#define x7      11(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        xorl    %eax, %eax
+        testb   $0x80, x7
+        setnz   %al
+        EPILOGUE(FUNC)
+
+#endif
Index: trunk/src/emx/src/lib/math/386/sin.s
===================================================================
--- trunk/src/emx/src/lib/math/386/sin.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/sin.s	(revision 18)
@@ -0,0 +1,30 @@
+/ sin.s (emx+gcc) -- Copyright (c) 1992-1993 by Steffen Haecker
+/                    Modified 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(sin)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double sin (double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fsin                            /* sin(x) */
+        fstsww  %ax
+        testb   $0x04, %ah                              
+        jnz     Llarge                  /* C2 != 0 ? */
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Llarge: fldl    __const_ZERO            /* sin(large):=0 */
+        fstp    %st(1)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/sinh.s
===================================================================
--- trunk/src/emx/src/lib/math/386/sinh.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/sinh.s	(revision 18)
@@ -0,0 +1,54 @@
+/ sinh.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(sinh)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double sinh (double x)
+
+#define cw1      0(%esp)
+#define cw2      2(%esp)
+/define ret_addr 4(%esp)
+#define x        8(%esp)
+
+/ sinh(x) = 0.5 * (exp(x) - exp(-x)) = 0.5 * (exp(x) - 1/exp(x))
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp                /* space for control words */
+        FLD     x                       /* x */
+        fldl2e                          /* log2 (e) */
+        fmulp                           /* y := x * log2 (e) */
+        fstcww  cw1
+        movw    cw1, %ax
+        andw    $0xf3ff, %ax
+        orw     $0x0400, %ax            /* round down towards -inf */
+        movw    %ax, cw2
+        fldcww  cw2      
+        fld     %st                     /* y, y */
+        frndint                         /* int (y), y */
+        fldcww  cw1
+        fxch    %st(1)                  /* y, int (y) */
+        fsub    %st(1), %st             /* frac (y), int (y) */
+        f2xm1                           /* 2^frac (y) - 1, int (y) */
+        faddl   __const_ONE             /* 2^frac (y), int (y) */
+        fscale                          /* 2^frac (y) * 2^int (y), int (y) */
+        fst     %st(1)                  /* exp(x), exp(x) */
+        fdivrl  __const_ONE             /* exp(-x), exp(x) */
+        fsubrp                          /* exp(x) - exp(-x) */
+        fmull   __const_HALF            /* 0.5 * (exp(x) - exp(-x)) */
+        CONV(x)                         /* convert to double */
+        addl    $4, %esp                /* Remove control words */
+        _xam
+        j_inf   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($ERANGE)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/sqrt.s
===================================================================
--- trunk/src/emx/src/lib/math/386/sqrt.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/sqrt.s	(revision 18)
@@ -0,0 +1,27 @@
+/ sqrt.s (emx+gcc) -- Copyright (c) 1991-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(sqrt)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double sqrt (double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fsqrt
+        _xam
+        j_nan   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($EDOM)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/status.s
===================================================================
--- trunk/src/emx/src/lib/math/386/status.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/status.s	(revision 18)
@@ -0,0 +1,17 @@
+/ status.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  LABEL(_status87)
+
+        .text
+
+        ALIGN
+
+/ unsigned _status87 (void)
+
+LABEL(_status87):
+        PROFILE_NOFRAME
+        xor     %eax, %eax              /* Clear upper 16 bits */
+        fstsww  %ax
+        EPILOGUE(_status87)
Index: trunk/src/emx/src/lib/math/386/tan.s
===================================================================
--- trunk/src/emx/src/lib/math/386/tan.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/tan.s	(revision 18)
@@ -0,0 +1,39 @@
+/ tan.s (emx+gcc) -- Copyright (c) 1992-1993 by Steffen Haecker
+/                    Modified 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(tan)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double tan (double x)
+
+#define x       4(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        FLD     x                       /* x */
+        fptan
+
+/* Note: fptan is followed by fstsww, avoiding a bug in the 486. */
+
+        fstsww  %ax
+        testb   $0x04, %ah
+        jnz     Llarge                  /* C2 != 0 ? */
+
+/* This used to be fdivrp.  However, on the 387, as opposed to the 8087,
+   st(0) is always 1 after fptan. */
+
+        fstp    %st(0)
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Llarge: fldl    __const_ZERO            /* tan(large):=0 */
+        fstp    %st(1)
+        fstp    %st(1)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/tanh.s
===================================================================
--- trunk/src/emx/src/lib/math/386/tanh.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/tanh.s	(revision 18)
@@ -0,0 +1,57 @@
+/ tanh.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX1(tanh)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double tanh (double x)
+
+#define cw1      0(%esp)
+#define cw2      2(%esp)
+/define ret_addr 4(%esp)
+#define x        8(%esp)
+
+/ tanh(x) = (t-1.0) / (t+1.0) with t = exp (2.0 * x)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp                /* space for control words */
+        FLD     x                       /* x */
+        fmull   __const_TWO             /* 2x */
+        fldl2e                          /* log2 (e) */
+        fmulp                           /* y := 2x * log2 (e) */
+        fstcww  cw1
+        movw    cw1, %ax
+        andw    $0xf3ff, %ax
+        orw     $0x0400, %ax            /* round down towards -inf */
+        movw    %ax, cw2
+        fldcww  cw2      
+        fld     %st                     /* y, y */
+        frndint                         /* int (y), y */
+        fldcww  cw1
+        fxch    %st(1)                  /* y, int (y) */
+        fsub    %st(1), %st             /* frac (y), int (y) */
+        f2xm1                           /* 2^frac (y) - 1, int (y) */
+        faddl   __const_ONE             /* 2^frac (y), int (y) */
+        fscale                          /* 2^frac (y) * 2^int (y), int (y) */
+        fstp    %st(1)                  /* 2^frac (y) * 2^int (y) */
+        fld     %st                     /* t, t */
+        faddl   __const_ONE             /* t+1, t */
+        fxch    %st(1)                  /* t, t+1 */
+        fsubl   __const_ONE             /* t-1, t+1 */
+        fdivp                           /* (t-1)/(t+1) */
+        CONV(x)                         /* convert to double */
+        addl    $4, %esp                /* Remove control words */
+        _xam
+        j_inf   Lerror
+Lreturn:EPILOGUE(FUNC)
+
+        ALIGN
+Lerror: SET_ERRNO_CONST($ERANGE)
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/math/386/trunc.s
===================================================================
--- trunk/src/emx/src/lib/math/386/trunc.s	(revision 18)
+++ trunk/src/emx/src/lib/math/386/trunc.s	(revision 18)
@@ -0,0 +1,33 @@
+/ trunc.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#define FUNC    MATHSUFFIX2(trunc)
+
+        .globl  LABEL(FUNC)
+
+        .text
+
+        ALIGN
+
+/ double _trunc (double x)
+
+#define cw1       0(%esp)
+#define cw2       2(%esp)
+/define ret_addr  4(%esp)
+#define x         8(%esp)
+
+LABEL(FUNC):
+        PROFILE_NOFRAME
+        subl    $4, %esp
+        fstcww  cw1
+        movw    cw1, %ax
+        andw    $0xf3ff, %ax
+        orw     $0x0c00, %ax            /* chop by truncating toward 0 */
+        movw    %ax, cw2
+        fldcww  cw2
+        FLD     x                       /* x */
+        frndint
+        fldcww  cw1
+        addl    $4, %esp
+        EPILOGUE(FUNC)
Index: trunk/src/emx/src/lib/math/cbrt.c
===================================================================
--- trunk/src/emx/src/lib/math/cbrt.c	(revision 18)
+++ trunk/src/emx/src/lib/math/cbrt.c	(revision 18)
@@ -0,0 +1,11 @@
+/* cbrt.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <math.h>
+
+double _cbrt (double x)
+{
+  if (x >= 0)
+    return pow (x, 1.0 / 3.0);
+  else
+    return -pow (-x, 1.0 / 3.0);
+}
Index: trunk/src/emx/src/lib/math/cbrtl.c
===================================================================
--- trunk/src/emx/src/lib/math/cbrtl.c	(revision 18)
+++ trunk/src/emx/src/lib/math/cbrtl.c	(revision 18)
@@ -0,0 +1,11 @@
+/* cbrtl.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <math.h>
+
+long double _cbrtl (long double x)
+{
+  if (x >= 0)
+    return _powl (x, 1.0 / 3.0);
+  else
+    return -_powl (-x, 1.0 / 3.0);
+}
Index: trunk/src/emx/src/lib/math/makefile
===================================================================
--- trunk/src/emx/src/lib/math/makefile	(revision 18)
+++ trunk/src/emx/src/lib/math/makefile	(revision 18)
@@ -0,0 +1,121 @@
+#
+# /emx/src/lib/math/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+%l.o: %.s
+	$(GCC) -DLONG_DOUBLE -c -x assembler-with-cpp -o $@ $<
+
+%f.o: %.s
+	$(GCC) -DFLOAT -c -x assembler-with-cpp -o $@ $<
+
+copysig.o: copysig.s $(ASM386H)
+copysigf.o: copysig.s $(ASM386H)
+copysigl.o: copysig.s $(ASM386H)
+
+fpclass.o: fpclass.s $(ASM386H)
+fpclassf.o: fpclass.s $(ASM386H)
+fpclassl.o: fpclass.s $(ASM386H)
+
+isfin.o: isfin.s $(ASM386H)
+isfinf.o: isfin.s $(ASM386H)
+isfinl.o: isfin.s $(ASM386H)
+
+isnan.o: isnan.s $(ASM386H)
+isnanf.o: isnan.s $(ASM386H)
+isnanl.o: isnan.s $(ASM386H)
+
+isnorm.o: isnorm.s $(ASM386H)
+isnormf.o: isnorm.s $(ASM386H)
+isnorml.o: isnorm.s $(ASM386H)
+
+nextaft.o: nextaft.s $(ASM386H)
+nextaftf.o: nextaft.s $(ASM386H)
+nextaftl.o: nextaft.s $(ASM386H)
+
+signbit.o: signbit.s $(ASM386H)
+signbitf.o: signbit.s $(ASM386H)
+signbitl.o: signbit.s $(ASM386H)
+
+acos.o: acos.s $(ASM386H)
+asin.o: asin.s $(ASM386H)
+atan.o: atan.s $(ASM386H)
+atan2.o: atan2.s $(ASM386H)
+cbrt.o: cbrt.c $(I)math.h
+ceil.o: ceil.s $(ASM386H)
+clear.o: clear.s $(ASM386H)
+consts.o: consts.s
+control.o: control.s $(ASM386H)
+cos.o: cos.s $(ASM386H)
+cosh.o: cosh.s $(ASM386H)
+exp.o: exp.s $(ASM386H)
+fabs.o: fabs.s $(ASM386H)
+floor.o: floor.s $(ASM386H)
+fmod.o: fmod.s $(ASM386H)
+fpreset.o: fpreset.s $(ASM386H)
+frexp.o: frexp.s $(ASM386H)
+fxam.o: fxam.s $(ASM386H)
+hypot.o: hypot.s $(ASM386H)
+ldexp.o: ldexp.s $(ASM386H)
+log.o: log.s $(ASM386H)
+log10.o: log10.s $(ASM386H)
+modf.o: modf.s $(ASM386H)
+pow.o: pow.s $(ASM386H)
+rint.o: rint.s $(ASM386H)
+sin.o: sin.s $(ASM386H)
+sinh.o: sinh.s $(ASM386H)
+sqrt.o: sqrt.s $(ASM386H)
+status.o: status.s $(ASM386H)
+tan.o: tan.s $(ASM386H)
+tanh.o: tanh.s $(ASM386H)
+trunc.o: trunc.s $(ASM386H)
+
+acosl.o: acos.s $(ASM386H)
+asinl.o: asin.s $(ASM386H)
+atanl.o: atan.s $(ASM386H)
+atan2l.o: atan2.s $(ASM386H)
+cbrtl.o: cbrtl.c $(I)math.h
+cosl.o: cos.s $(ASM386H)
+coshl.o: cosh.s $(ASM386H)
+expl.o: exp.s $(ASM386H)
+fabsl.o: fabs.s $(ASM386H)
+floorl.o: floor.s $(ASM386H)
+fmodl.o: fmod.s $(ASM386H)
+frexpl.o: frexp.s $(ASM386H)
+fxaml.o: fxam.s $(ASM386H)
+hypotl.o: hypot.s $(ASM386H)
+ldexpl.o: ldexp.s $(ASM386H)
+logl.o: log.s $(ASM386H)
+log10l.o: log10.s $(ASM386H)
+modfl.o: modf.s $(ASM386H)
+powl.o: pow.s $(ASM386H)
+rintl.o: rint.s $(ASM386H)
+sinl.o: sin.s $(ASM386H)
+sinhl.o: sinh.s $(ASM386H)
+sqrtl.o: sqrt.s $(ASM386H)
+tanl.o: tan.s $(ASM386H)
+tanhl.o: tanh.s $(ASM386H)
+truncl.o: trunc.s $(ASM386H)
+
+# `ceill' ends with two `l's -- we have to handle that specially
+ceill.o: ../$(CPU)/ceil.s $(ASM386H)
+	$(GCC) -DLONG_DOUBLE -c -x assembler-with-cpp -o ceill.o ../$(CPU)/ceil.s
+
+$(DSTLIB): copysig.o copysigf.o copysigl.o \
+    fpclass.o fpclassf.o fpclassl.o \
+    isfin.o isfinf.o isfinl.o \
+    isnan.o isnanf.o isnanl.o \
+    isnorm.o isnormf.o isnorml.o \
+    nextaft.o nextaftf.o nextaftl.o \
+    signbit.o signbitf.o signbitl.o \
+    acos.o asin.o atan.o atan2.o cbrt.o ceil.o clear.o consts.o \
+    control.o cos.o cosh.o exp.o fabs.o floor.o fmod.o \
+    fpreset.o frexp.o fxam.o hypot.o ldexp.o log.o log10.o modf.o pow.o \
+    rint.o sin.o sinh.o sqrt.o status.o tan.o tanh.o trunc.o \
+    acosl.o asinl.o atanl.o atan2l.o cbrtl.o ceill.o \
+    cosl.o coshl.o expl.o fabsl.o floorl.o fmodl.o frexpl.o \
+    fxaml.o hypotl.o ldexpl.o logl.o log10l.o modfl.o powl.o rintl.o sinl.o \
+    sinhl.o sqrtl.o tanl.o tanhl.o truncl.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/mbyte/_mbtowc.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/_mbtowc.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/_mbtowc.c	(revision 18)
@@ -0,0 +1,96 @@
+/* _mbtowc.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/nls.h>
+#include <emx/locale.h>
+
+int _mbtowc (wchar_t *pwc, const char *s, size_t n, int *pshift)
+{
+  unsigned char c;
+
+  /* ANSI X3.159-1989, 4.10.7.2: "If s is not a null pointer, the
+     mbtowc function either returns 0 (if s points to the null
+     character)" */
+
+  c = *s;
+  if (c == 0)
+    return 0;
+  if (n == 0)
+    return -1;
+  switch (_cur_mbyte.mode)
+    {
+    case _MB_8BITS:
+      if (pwc != NULL)
+        *pwc = c;
+      return 1;
+  
+    case _MB_DBCS:
+      if (_nls_is_dbcs_lead (c))
+        {
+          if (n >= 2 && s[1] != 0)
+            {
+              if (pwc != NULL)
+                *pwc = (c << 8) | (unsigned char)s[1];
+              return 2;
+            }
+        }
+      else
+        {
+          if (pwc != NULL)
+            *pwc = c;
+          return 1;
+        }
+      break;
+      
+    case _MB_UTF_2:         /* UTF-2 */
+      if (c <= 0x7f)
+        {
+          if (pwc != NULL)
+            *pwc = c;
+          return 1;
+        }
+      else
+        {
+          int i, n;
+          unsigned long x, m;
+
+          if ((c & 0xe0) == 0xc0)
+            {
+              n = 1; x = c & 0x1f; m = 0x80;
+            }
+          else if ((c & 0xf0) == 0xe0)
+            {
+              n = 2; x = c & 0x0f; m = 0x800;
+            }
+          else if ((c & 0xf8) == 0xf0)
+            {
+              n = 3; x = c & 0x07; m = 0x10000;
+            }
+          else if ((c & 0xfc) == 0xf8)
+            {
+              n = 4; x = c & 0x03; m = 0x200000;
+            }
+          else if ((c & 0xfe) == 0xfc)
+            {
+              n = 5; x = c & 0x01; m = 0x4000000;
+            }
+          else
+            return -1;
+          ++s;
+          for (i = 0; i < n; ++i)
+            {
+              if ((*s & 0xc0) != 0x80)
+                return -1;
+              x = (x << 6) | (*s & 0x3f);
+              ++s;
+            }
+          if (x < m)
+            return -1;
+          if (pwc != NULL)
+            *pwc = (wchar_t)x;
+          return n + 1;
+        }
+      break;
+    }
+  return -1;
+}
Index: trunk/src/emx/src/lib/mbyte/_wctomb.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/_wctomb.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/_wctomb.c	(revision 18)
@@ -0,0 +1,84 @@
+/* _wctomb.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/nls.h>
+#include <emx/locale.h>
+
+int _wctomb (char *s, wchar_t wchar, size_t n, int *pshift)
+{
+  wchar_t lead;
+
+  if (n == 0)
+    return -1;
+
+  if (wchar == 0)
+    {
+      *s = 0;
+      return 1;
+    }
+
+  switch (_cur_mbyte.mode)
+    {
+    case _MB_8BITS:
+      if (wchar <= 255)         /* wchar_t is unsigned */
+        {
+          *s = (char)wchar;
+          return 1;
+        }
+      break;
+
+    case _MB_DBCS:
+      if (wchar <= 255 && !_nls_is_dbcs_lead (wchar)) /* wchar_t is unsigned */
+        {
+          *s = (char)wchar;
+          return 1;
+        }
+      lead = wchar >> 8; wchar &= 0xff;
+      if (_nls_is_dbcs_lead (lead) && wchar != 0 && n >= 2)
+        {
+          *s++ = lead;
+          *s++ = (char)wchar;
+          return 2;
+        }
+      break;
+
+    case _MB_UTF_2:             /* UTF-2 */
+      if (wchar <= 0x7f)
+        {
+          *s = (char)wchar;
+          return 1;
+        }
+      else
+        {
+          /* wchar_t has (only) 16 bits, therefore there are only two
+             cases. */
+
+          if (wchar <= 0x7ff && n >= 2)
+            {
+              *s++ = (char)((wchar >> 6) | 0xc0);
+              *s = (char)(((wchar >> 0) & 0x3f) | 0x80);
+              return 2;
+            }
+          else if (n >= 3)
+            {
+              *s++ = (char)((wchar >> 12) | 0xe0);
+              *s++ = (char)(((wchar >> 6) & 0x3f) | 0x80);
+              *s = (char)(((wchar >> 0) & 0x3f) | 0x80);
+              return 3;
+            }
+        }
+
+    case _MB_SHIFT:
+
+      /* ANSI X3.159-1989, 4.10.7.3: "If the value of wchar is zero,
+         the wctomb function is left in the initial shift state." */
+
+      if (wchar == 0)
+        *pshift = 0;
+
+      /* Not yet implemented */
+
+      break;
+    }
+  return -1;
+}
Index: trunk/src/emx/src/lib/mbyte/makefile
===================================================================
--- trunk/src/emx/src/lib/mbyte/makefile	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/makefile	(revision 18)
@@ -0,0 +1,20 @@
+#
+# /emx/src/lib/mbyte/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+mbcurmax.o: mbcurmax.c $(I)stdlib.h
+mblen.o: mblen.c $(I)stdlib.h $(I)emx/thread.h $(I)emx/locale.h
+mbstowcs.o: mbstowcs.c $(I)stdlib.h $(I)limits.h $(I)emx/locale.h
+mbtowc.o: mbtowc.c $(I)stdlib.h $(I)emx/thread.h $(I)emx/locale.h
+mbyte.o: mbyte.c $(I)stdlib.h $(I)emx/locale.h
+wcstombs.o: wcstombs.c $(I)stdlib.h $(I)emx/locale.h
+wctomb.o: wctomb.c $(I)stdlib.h $(I)limits.h $(I)emx/thread.h $(I)emx/locale.h
+_mbtowc.o: _mbtowc.c $(I)emx/locale.h $(I)sys/nls.h
+_wctomb.o: _wctomb.c $(I)emx/locale.h $(I)sys/nls.h
+
+$(DSTLIB): mbcurmax.o mblen.o mbstowcs.o mbtowc.o mbyte.o \
+    wcstombs.o wctomb.o _mbtowc.o _wctomb.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/mbyte/mbcurmax.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/mbcurmax.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/mbcurmax.c	(revision 18)
@@ -0,0 +1,5 @@
+/* mbcurmax.c (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+int _mb_cur_max = 1;
Index: trunk/src/emx/src/lib/mbyte/mblen.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/mblen.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/mblen.c	(revision 18)
@@ -0,0 +1,31 @@
+/* mblen.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/thread.h>
+#include <emx/locale.h>
+
+#if defined (__MT__)
+#define shift tp->_th_mblen_shift
+#else
+static int shift = 0;
+#endif
+
+
+int mblen (const char *s, size_t n)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#endif
+
+  if (s == NULL)
+    {
+      if (_cur_mbyte.mode == _MB_SHIFT)
+        {
+          shift = 0;
+          return 1;             /* State dependency */
+        }
+      else
+        return 0;               /* No state dependency */
+    }
+  return _mbtowc (NULL, s, n, &shift);
+}
Index: trunk/src/emx/src/lib/mbyte/mbstowcs.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/mbstowcs.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/mbstowcs.c	(revision 18)
@@ -0,0 +1,38 @@
+/* mbstowcs.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <emx/locale.h>
+
+
+size_t mbstowcs (wchar_t *pwcs, const char *s, size_t n)
+{
+  int shift, i;
+  size_t result;
+
+  shift = 0; result = 0;
+  switch (_cur_mbyte.mode)
+    {
+    case _MB_8BITS:
+      while (*s != 0 && n != 0)
+        {
+          pwcs[result++] = (unsigned char)*s++;
+          --n;
+        }
+      break;
+
+    default:
+      while (*s != 0 && n != 0)
+        {
+          i = _mbtowc (pwcs + result, s, MB_LEN_MAX, &shift);
+          if (i < 1)
+            return (size_t)-1;
+          s += i; ++result; --n;
+        }
+      break;
+    }
+
+  if (n != 0)
+    pwcs[result] = 0;
+  return result;
+}
Index: trunk/src/emx/src/lib/mbyte/mbtowc.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/mbtowc.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/mbtowc.c	(revision 18)
@@ -0,0 +1,31 @@
+/* mbtowc.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/thread.h>
+#include <emx/locale.h>
+
+#if defined (__MT__)
+#define shift tp->_th_mbtowc_shift
+#else
+static int shift = 0;
+#endif
+
+
+int mbtowc (wchar_t *pwc, const char *s, size_t n)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#endif
+
+  if (s == NULL)
+    {
+      if (_cur_mbyte.mode == _MB_SHIFT)
+        {
+          shift = 0;
+          return 1;             /* State dependency */
+        }
+      else
+        return 0;               /* No state dependency */
+    }
+  return _mbtowc (pwc, s, n, &shift);
+}
Index: trunk/src/emx/src/lib/mbyte/mbyte.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/mbyte.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/mbyte.c	(revision 18)
@@ -0,0 +1,9 @@
+/* mbyte.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/locale.h>
+
+struct _mbyte _cur_mbyte =
+{
+  _MB_8BITS
+};
Index: trunk/src/emx/src/lib/mbyte/wcstombs.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/wcstombs.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/wcstombs.c	(revision 18)
@@ -0,0 +1,45 @@
+/* wcstombs.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <emx/locale.h>
+
+size_t wcstombs (char *s, const wchar_t *pwcs, size_t n)
+{
+  size_t result;
+  wchar_t wc;
+  int shift, i;
+
+  shift = 0; result = 0;
+  switch (_cur_mbyte.mode)
+    {
+    case _MB_8BITS:
+      while (n != 0 && *pwcs != 0)
+        {
+          wc = *pwcs++;
+          if (wc > 255)         /* wchar_t is unsigned */
+            return (size_t)-1;
+          s[result++] = (char)wc;
+          --n;
+        }
+      break;
+
+    default:
+      while (n != 0 && *pwcs != 0)
+        {
+          i = _wctomb (s + result, *pwcs++, n, &shift);
+          if (i < 1)
+            return (size_t)-1;
+          result += i; n -= i;
+        }
+      break;
+    }
+
+  /* ANSI X3.159-1989, 4.10.8.2: "Otherwise, the wcstombs function
+     returns the number of bytes modified, not including a terminating
+     null character, if any." */
+
+  if (n != 0)
+    s[result] = 0;
+  return result;
+}
Index: trunk/src/emx/src/lib/mbyte/wctomb.c
===================================================================
--- trunk/src/emx/src/lib/mbyte/wctomb.c	(revision 18)
+++ trunk/src/emx/src/lib/mbyte/wctomb.c	(revision 18)
@@ -0,0 +1,31 @@
+/* wctomb.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <emx/thread.h>
+#include <emx/locale.h>
+
+#if defined (__MT__)
+#define shift (tp->_th_wctomb_shift)
+#else
+static int shift = 0;
+#endif
+
+int wctomb (char *s, wchar_t wchar)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#endif
+
+  if (s == NULL)
+    {
+      if (_cur_mbyte.mode == _MB_SHIFT)
+        {
+          shift = 0;
+          return 1;             /* State dependency */
+        }
+      else
+        return 0;               /* No state dependency */
+    }
+  return _wctomb (s, wchar, MB_LEN_MAX, &shift);
+}
Index: trunk/src/emx/src/lib/misc/386/div.s
===================================================================
--- trunk/src/emx/src/lib/misc/386/div.s	(revision 18)
+++ trunk/src/emx/src/lib/misc/386/div.s	(revision 18)
@@ -0,0 +1,19 @@
+/ div.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _div, _ldiv
+
+        .text
+        ALIGN
+
+/ div_t div (int num, int den)
+/ ldiv_t ldiv (long num, long den)
+
+_ldiv:
+_div:
+        PROFILE_NOFRAME
+        movl    1*4(%esp), %eax         /* num */
+        cltd                            /* sign extension */
+        idivl   2*4(%esp)               /* den */
+        EPILOGUE(div)
Index: trunk/src/emx/src/lib/misc/386/int86.s
===================================================================
--- trunk/src/emx/src/lib/misc/386/int86.s	(revision 18)
+++ trunk/src/emx/src/lib/misc/386/int86.s	(revision 18)
@@ -0,0 +1,46 @@
+/ int86.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __int86
+
+        .text
+        ALIGN
+
+/ int _int86 (int int_num, union REGS *inp_regs, union REGS *out_regs)
+
+__int86:
+        PROFILE_NOFRAME
+        pushl   %ebp
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+        movl    $0xc3c300cd, %eax       /* int 0; ret; ret */
+        movb    5*4(%esp), %ah          /* int_num */
+        pushl   %eax                    /* Push code */
+        pushl   %esp                    /* Push address of code */
+        movl    8*4(%esp), %ebx         /* inp_regs */
+        movl    0*4(%ebx), %eax
+        movl    2*4(%ebx), %ecx
+        movl    3*4(%ebx), %edx
+        movl    4*4(%ebx), %esi
+        movl    5*4(%ebx), %edi
+        movl    1*4(%ebx), %ebx
+        call    (%esp)                  /* "call %esp" is undefined */
+        movl    %ebx, 1*4(%esp)
+        movl    9*4(%esp), %ebx         /* out_regs */
+        movl    %eax, 0*4(%ebx)
+        popl    %eax                    /* Remove address of code */
+        popl    1*4(%ebx)               /* %ebx */
+        movl    %ecx, 2*4(%ebx)
+        movl    %edx, 3*4(%ebx)
+        movl    %esi, 4*4(%ebx)
+        movl    %edi, 5*4(%ebx)
+        pushf
+        popl    6*4(%ebx)
+        movl    0*4(%ebx), %eax         /* Return %eax */
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        popl    %ebp
+        EPILOGUE(_int86)
Index: trunk/src/emx/src/lib/misc/386/setjmp.s
===================================================================
--- trunk/src/emx/src/lib/misc/386/setjmp.s	(revision 18)
+++ trunk/src/emx/src/lib/misc/386/setjmp.s	(revision 18)
@@ -0,0 +1,64 @@
+/ setjmp.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _setjmp, _longjmp
+
+        .text
+        ALIGN
+
+#define J_EBX  0
+#define J_ESI  4
+#define J_EDI  8
+#define J_ESP 12
+#define J_EBP 16
+#define J_EIP 20
+#define J_XCP 24
+
+/ Words at offsets 28..44 are reserved
+
+/ int setjmp (jmp_buf here)
+
+_setjmp:
+        PROFILE_NOFRAME
+        movl    1*4(%esp), %edx         /* here */
+        movl    %ebx, J_EBX(%edx)
+        movl    %esi, J_ESI(%edx)
+        movl    %edi, J_EDI(%edx)
+        movl    %ebp, J_EBP(%edx)
+        movl    %esp, J_ESP(%edx)
+        movl    0*4(%esp), %eax         /* return address */
+        movl    %eax, J_EIP(%edx)
+        cmpb    $0, __osmode            /* OS/2? */
+        je      1f                      /* No -> skip */
+        fs
+        movl    0, %eax                 /* Exception handler */
+        movl    %eax, J_XCP(%edx)
+1:      xorl    %eax, %eax
+        EPILOGUE(setjmp)
+
+        ALIGN
+
+/ void longjmp (jmp_buf there, int n)
+
+_longjmp:
+        PROFILE_NOFRAME
+        cmpb    $0, __osmode            /* OS/2? */
+        je      2f                      /* No -> skip */
+        movl    1*4(%esp), %eax         /* there */
+        pushl   J_XCP(%eax)
+        call    ___unwind2              /* unwind signal handlers */
+        addl    $4, %esp
+2:      movl    1*4(%esp), %edx         /* there */
+        movl    2*4(%esp), %eax         /* n */
+        testl   %eax, %eax
+        jne     3f
+        incl    %eax
+3:      movl    J_EBX(%edx), %ebx
+        movl    J_ESI(%edx), %esi
+        movl    J_EDI(%edx), %edi
+        movl    J_EBP(%edx), %ebp
+        movl    J_ESP(%edx), %esp
+        movl    J_EIP(%edx), %edx
+        movl    %edx, 0*4(%esp)         /* return address */
+        EPILOGUE(longjmp)               /* well, ... */
Index: trunk/src/emx/src/lib/misc/386/sigsetjm.s
===================================================================
--- trunk/src/emx/src/lib/misc/386/sigsetjm.s	(revision 18)
+++ trunk/src/emx/src/lib/misc/386/sigsetjm.s	(revision 18)
@@ -0,0 +1,85 @@
+/ sigsetjm.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __sigsetjmp, __siglongjmp
+
+        .text
+        ALIGN
+
+#define J_EBX  0
+#define J_ESI  4
+#define J_EDI  8
+#define J_ESP 12
+#define J_EBP 16
+#define J_EIP 20
+#define J_XCP 24
+#define J_SAVE 48
+#define J_MASK 52
+
+/ Words at offsets 28..44 are reserved
+
+/ int _sigsetjmp (sigjmp_buf here, int savemask)
+
+__sigsetjmp:
+        PROFILE_NOFRAME
+        movl    1*4(%esp), %edx         /* here */
+        movl    %ebx, J_EBX(%edx)
+        movl    %esi, J_ESI(%edx)
+        movl    %edi, J_EDI(%edx)
+        movl    %ebp, J_EBP(%edx)
+        movl    %esp, J_ESP(%edx)
+        movl    0*4(%esp), %eax         /* return address */
+        movl    %eax, J_EIP(%edx)
+        cmpb    $0, __osmode            /* OS/2? */
+        je      1f                      /* No -> skip */
+        fs
+        movl    0, %eax                 /* Exception handler */
+        movl    %eax, J_XCP(%edx)
+1:      movl    2*4(%esp), %eax         /* savemask */
+        movl    %eax, J_SAVE(%edx)
+        testl   %eax, %eax
+        je      2f
+        leal    J_MASK(%edx), %eax
+        pushl   %eax                    /* oset */
+        pushl   $0                      /* iset */
+        pushl   $3                      /* how: SIG_SETMASK */
+        call    __sigprocmask
+        addl    $12, %esp
+2:      xorl    %eax, %eax
+        EPILOGUE(_sigsetjmp)
+
+        ALIGN
+
+/ void _siglongjmp (sigjmp_buf there, int n)
+
+__siglongjmp:
+        PROFILE_NOFRAME
+        movl    1*4(%esp), %eax         /* there */
+        cmpl    $0, J_SAVE(%eax)
+        je      1f
+        leal    J_MASK(%eax), %eax
+        pushl   $0                      /* oset */
+        pushl   %eax                    /* iset */
+        pushl   $3                      /* how: SIG_SETMASK */
+        call    __sigprocmask
+        addl    $12, %esp
+1:      cmpb    $0, __osmode            /* OS/2? */
+        je      2f                      /* No -> skip */
+        movl    1*4(%esp), %eax         /* there */
+        pushl   J_XCP(%eax)
+        call    ___unwind2              /* unwind signal handlers */
+        addl    $4, %esp
+2:      movl    1*4(%esp), %edx         /* there */
+        movl    2*4(%esp), %eax         /* n */
+        testl   %eax, %eax
+        jne     3f
+        incl    %eax
+3:      movl    J_EBX(%edx), %ebx
+        movl    J_ESI(%edx), %esi
+        movl    J_EDI(%edx), %edi
+        movl    J_EBP(%edx), %ebp
+        movl    J_ESP(%edx), %esp
+        movl    J_EIP(%edx), %edx
+        movl    %edx, 0*4(%esp)         /* return address */
+        EPILOGUE(_siglongjmp)           /* well, ... */
Index: trunk/src/emx/src/lib/misc/386/uldiv.s
===================================================================
--- trunk/src/emx/src/lib/misc/386/uldiv.s	(revision 18)
+++ trunk/src/emx/src/lib/misc/386/uldiv.s	(revision 18)
@@ -0,0 +1,17 @@
+/ uldiv.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __uldiv
+
+        .text
+        ALIGN
+
+/ _uldiv_t _uldiv (long num, long den)
+
+__uldiv:
+        PROFILE_NOFRAME
+        movl    1*4(%esp), %eax         /* num */
+        xorl    %edx, %edx              /* zero extension */
+        divl    2*4(%esp)               /* den */
+        EPILOGUE(_uldiv)
Index: trunk/src/emx/src/lib/misc/abort.c
===================================================================
--- trunk/src/emx/src/lib/misc/abort.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/abort.c	(revision 18)
@@ -0,0 +1,54 @@
+/* abort.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <signal.h>
+#include <emx/startup.h>
+
+static sig_atomic_t abort_flag = 0;
+
+void abort (void)
+{
+  sigset_t set;
+  struct sigaction act;
+
+  /* Special handling if there's a signal-catching function installed
+     and SIGABRT is not blocked: do not yet call _cleanup(). */
+
+  if (_sigaction (SIGABRT, NULL, &act) == 0
+      && act.sa_handler != SIG_IGN && act.sa_handler != SIG_DFL
+      && _sigemptyset (&set) == 0
+      && _sigprocmask (SIG_SETMASK, NULL, &set) == 0
+      && _sigismember (&set, SIGABRT) == 0)
+    {
+      /* Raise SIGABRT.  Note that this is not guaranteed to terminate
+         the process. */
+
+      raise (SIGABRT);
+    }
+
+  /* Install SIG_DFL for SIGABRT. */
+
+  act.sa_handler = SIG_DFL;
+  _sigemptyset (&act.sa_mask);
+  act.sa_flags = 0;
+  _sigaction (SIGABRT, &act, NULL);
+
+  /* Clean up the C library only once. */
+
+  if (abort_flag++ == 0)
+    _cleanup ();
+
+  /* Unblock SIGABRT. */
+
+  _sigemptyset (&set);
+  _sigaddset (&set, SIGABRT);
+  _sigprocmask (SIG_UNBLOCK, &set, NULL);
+
+  /* Raise SIGABRT again. */
+
+  raise (SIGABRT);
+
+  /* This should not get reached. */
+
+  _exit (3);
+}
Index: trunk/src/emx/src/lib/misc/abs.c
===================================================================
--- trunk/src/emx/src/lib/misc/abs.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/abs.c	(revision 18)
@@ -0,0 +1,6 @@
+/* abs.c (emx+gcc) -- Copyright (c) 1992-1993 by Eberhard Mattes */
+
+int abs (int n)
+{
+  return (n < 0 ? -n : n);
+}
Index: trunk/src/emx/src/lib/misc/abspath.c
===================================================================
--- trunk/src/emx/src/lib/misc/abspath.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/abspath.c	(revision 18)
@@ -0,0 +1,124 @@
+/* abspath.c (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <alloca.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/nls.h>
+#include <emx/syscalls.h>
+
+#define FALSE   0
+#define TRUE    1
+#define IS_PATH_DELIM(c) ((c)=='\\' || (c)=='/')
+
+int _abspath (char *dst, const char *src, int size)
+{
+  char drive, dir[MAXPATHLEN+1], src_drive, *s, *p;
+  int i, j, rel, server, trail;
+
+  s = alloca (strlen (src) + 1);
+  strcpy (s, src);
+  src_drive = _fngetdrive (s);
+  if (src_drive == 0)
+    drive = _getdrive ();
+  else
+    {
+      drive = src_drive;
+      s += 2;
+    }
+  dir[0] = 0; rel = FALSE; server = FALSE; trail = FALSE;
+  if (IS_PATH_DELIM (*s))
+    {
+      ++s;
+      if (IS_PATH_DELIM (*s))
+        {
+          ++s; server = TRUE;
+        }
+    }
+  else if (__getcwd (dir, drive) == 0)
+    _fnslashify (dir);
+  else
+    {
+      dir[0] = 0;
+      rel = TRUE;
+    }
+  while (*s != 0)
+    {
+      if (s[0] == '.' && (IS_PATH_DELIM (s[1]) || s[1] == 0))
+        ++s;
+      else if (s[0] == '.' && s[1] == '.' && (IS_PATH_DELIM (s[2]) || 
+                                              s[2] == 0))
+        {
+          s += 2;
+          if (*dir == 0)
+            strcpy (dir, "..");
+          else
+            {
+              p = _getname (dir);
+              if (p == dir)
+                p[0] = 0;
+              else
+                p[-1] = 0;
+            }
+        }
+      else
+        {
+          i = strlen (dir);
+          if (i < sizeof (dir) - 1)
+            dir[i++] = '/';
+          while (*s != 0)
+            {
+              if (_nls_is_dbcs_lead ((unsigned char)*s) && s[1] != 0)
+                {
+                  if (i < sizeof (dir) - 2)
+                    {
+                      dir[i++] = s[0];
+                      dir[i++] = s[1];
+                    }
+                  s += 2;
+                }
+              else if (IS_PATH_DELIM (*s))
+                break;
+              else
+                {
+                  if (i < sizeof (dir) - 1)
+                    dir[i++] = *s;
+                  ++s;
+                }
+            }
+          dir[i] = 0;
+        }
+      if (*s != 0)
+        {
+          ++s;
+          if (*s == 0)
+            trail = 1;
+        }
+    }
+  i = 0;
+  if (i+1 < size && (src_drive != 0 || !server))
+    {
+      dst[i++] = drive;
+      dst[i++] = ':';
+    }
+  if (i < size && server && src_drive == 0)
+    dst[i++] = '/';
+  if (i < size && !rel && dir[0] != '/')
+    dst[i++] = '/';
+  j = 0;
+  if (rel && dir[j] == '/')
+    ++j;
+  while (i < size && dir[j] != 0)
+    dst[i++] = dir[j++];
+  if (trail && i < size && (i == 0 || dst[i-1] != '/'))
+    dst[i++] = '/';
+  if (i >= size)
+    {
+      dir[size-1] = 0;
+      errno = ERANGE;
+      return -1;
+    }
+  dst[i] = 0;
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/alarm.c
===================================================================
--- trunk/src/emx/src/lib/misc/alarm.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/alarm.c	(revision 18)
@@ -0,0 +1,9 @@
+/* alarm.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+unsigned _alarm (unsigned sec)
+{
+  return __alarm (sec);
+}
Index: trunk/src/emx/src/lib/misc/assert.c
===================================================================
--- trunk/src/emx/src/lib/misc/assert.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/assert.c	(revision 18)
@@ -0,0 +1,15 @@
+/* assert.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#undef NDEBUG
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void _assert (const char *string, const char *fname, unsigned int line)
+{
+  fprintf (stderr, "Assertion failed: %s, file %s, line %u\n",
+           string, fname, line);
+  fflush (stderr);
+  abort ();
+}
Index: trunk/src/emx/src/lib/misc/atexit.c
===================================================================
--- trunk/src/emx/src/lib/misc/atexit.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/atexit.c	(revision 18)
@@ -0,0 +1,12 @@
+/* atexit.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/startup.h>
+
+int atexit (void (*func)(void))
+{
+  if (_atexit_n >= sizeof (_atexit_v) / sizeof (_atexit_v[0]))
+    return -1;
+  _atexit_v[_atexit_n++] = func;
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/brk.c
===================================================================
--- trunk/src/emx/src/lib/misc/brk.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/brk.c	(revision 18)
@@ -0,0 +1,9 @@
+/* brk.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+void *_brk (void *addr)
+{
+  return __brk (addr);
+}
Index: trunk/src/emx/src/lib/misc/bsearch.c
===================================================================
--- trunk/src/emx/src/lib/misc/bsearch.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/bsearch.c	(revision 18)
@@ -0,0 +1,27 @@
+/* bsearch.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+void *bsearch (const void *key, const void *base, size_t num, size_t width,
+               int (*compare)(const void *key, const void *element))
+{
+  int left, right, median, sign;
+  const void *element;
+
+  if (width <= 0)
+    return NULL;
+  left = 1; right = num;
+  while (left <= right)
+    {
+      median = (left + right) / 2;
+      element = (void *)((char *)base + (median-1)*width);
+      sign = compare (key, element);
+      if (sign == 0)
+        return (void *)element;
+      if (sign > 0)
+        left = median + 1;
+      else
+        right = median - 1;
+    }
+  return NULL;
+}
Index: trunk/src/emx/src/lib/misc/chdir.c
===================================================================
--- trunk/src/emx/src/lib/misc/chdir.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/chdir.c	(revision 18)
@@ -0,0 +1,22 @@
+/* chdir.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _chdir (const char *name)
+{
+  size_t len;
+  char *tmp;
+
+  len = strlen (name);
+  if (_trslash (name, len, 1))
+    {
+      tmp = alloca (len);
+      memcpy (tmp, name, len - 1);
+      tmp[len-1] = 0;
+      name = tmp;
+    }
+  return __chdir (name);
+}
Index: trunk/src/emx/src/lib/misc/chdir2.c
===================================================================
--- trunk/src/emx/src/lib/misc/chdir2.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/chdir2.c	(revision 18)
@@ -0,0 +1,40 @@
+/* chdir2.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _chdir2 (const char *name)
+{
+  char old_drive, new_drive, *tmp;
+  size_t len;
+  int saved_errno;
+
+  len = strlen (name);
+  if (_trslash (name, len, 1))
+    {
+      tmp = alloca (len);
+      memcpy (tmp, name, len - 1);
+      tmp[len-1] = 0;
+      name = tmp;
+    }
+  old_drive = _getdrive ();
+  new_drive = _fngetdrive (name);
+  if (new_drive != 0)
+    {
+      if (_chdrive (new_drive) != 0)
+        return -1;
+      if (name[2] == 0)         /* Change drive only */
+        return 0;
+    }
+  if (__chdir (name) == 0)
+    return 0;
+  else
+    {
+      saved_errno = errno;
+      _chdrive (old_drive);
+      errno = saved_errno;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/misc/chdrive.c
===================================================================
--- trunk/src/emx/src/lib/misc/chdrive.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/chdrive.c	(revision 18)
@@ -0,0 +1,9 @@
+/* chdrive.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+int _chdrive (char drive)
+{
+  return __chdrive (drive);
+}
Index: trunk/src/emx/src/lib/misc/core.c
===================================================================
--- trunk/src/emx/src/lib/misc/core.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/core.c	(revision 18)
@@ -0,0 +1,9 @@
+/* core.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+int _core (int handle)
+{
+  return __core (handle);
+}
Index: trunk/src/emx/src/lib/misc/cuserid.c
===================================================================
--- trunk/src/emx/src/lib/misc/cuserid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/cuserid.c	(revision 18)
@@ -0,0 +1,21 @@
+/* cuserid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *_cuserid (char *buffer)
+{
+  static char tmp_name[L_cuserid];
+  const char *name;
+
+  name = getenv ("LOGNAME");
+  if (name == NULL)
+    name = getenv ("USER");
+  if (name == NULL)
+    name = "root";
+  if (buffer == NULL)
+    buffer = tmp_name;
+  _strncpy (buffer, name, L_cuserid);
+  return buffer;
+}
Index: trunk/src/emx/src/lib/misc/defext.c
===================================================================
--- trunk/src/emx/src/lib/misc/defext.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/defext.c	(revision 18)
@@ -0,0 +1,52 @@
+/* defext.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/nls.h>
+
+/* Note that _nls_is_dbcs_lead() returns false for all characters if
+   _nls_init() has not been called.  In consequence, this function
+   works properly for SBCS strings even if _nls_init() has not been
+   called. */
+
+/* Note: This function is used by emx.dll. */
+
+#define FALSE   0
+#define TRUE    1
+
+void _defext (char *dst, const char *ext)
+{
+  int dot, sep;
+
+  dot = FALSE; sep = TRUE;
+  while (*dst != 0)
+    if (_nls_is_dbcs_lead ((unsigned char)*dst))
+      {
+        if (dst[1] == 0)        /* Invalid DBCS character */
+          return;
+        dst += 2;
+        sep = FALSE;
+      }
+    else
+      switch (*dst++)
+        {
+        case '.':
+          dot = TRUE;
+          sep = FALSE;
+          break;
+        case ':':
+        case '/':
+        case '\\':
+          dot = FALSE;
+          sep = TRUE;
+          break;
+        default:
+          sep = FALSE;
+          break;
+        }
+  if (!dot && !sep)
+    {
+      *dst++ = '.';
+      strcpy (dst, ext);
+    }
+}
Index: trunk/src/emx/src/lib/misc/dirent.c
===================================================================
--- trunk/src/emx/src/lib/misc/dirent.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/dirent.c	(revision 18)
@@ -0,0 +1,205 @@
+/* dirent.c (emx+gcc) */
+
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+struct _dircontents
+{
+  char *                _d_entry;
+  long                  _d_size;
+  unsigned short        _d_attr;
+  unsigned short        _d_time;
+  unsigned short        _d_date;
+  struct _dircontents * _d_next;
+};
+
+struct _dirdesc
+{
+  int                   dd_id;
+  long                  dd_loc;
+  struct _dircontents * dd_contents;
+  struct _dircontents * dd_cp;
+  struct dirent         dd_dirent;
+};
+
+
+static int _readdir_ino = 31415926;
+
+static void free_dircontents (struct _dircontents *dp);
+static char *getdirent (const char *dir, struct _find *pfind,
+    const char *base);
+
+int _closedir (DIR *dirp)
+{
+  free_dircontents (dirp->dd_contents);
+  free (dirp);
+  return 0;
+}
+
+
+struct dirent *_readdir (DIR *dirp)
+{
+  if (dirp->dd_cp == NULL)
+    return NULL;
+  strcpy (dirp->dd_dirent.d_name, dirp->dd_cp->_d_entry);
+  dirp->dd_dirent.d_namlen = strlen (dirp->dd_dirent.d_name);
+  dirp->dd_dirent.d_reclen = dirp->dd_dirent.d_namlen;
+  dirp->dd_dirent.d_ino = _readdir_ino++;
+  if (_readdir_ino == 0)
+    _readdir_ino = 1;
+  dirp->dd_dirent.d_size = dirp->dd_cp->_d_size;
+  dirp->dd_dirent.d_attr = dirp->dd_cp->_d_attr;
+  dirp->dd_dirent.d_time = dirp->dd_cp->_d_time;
+  dirp->dd_dirent.d_date = dirp->dd_cp->_d_date;
+  dirp->dd_cp = dirp->dd_cp->_d_next;
+  ++dirp->dd_loc;
+  return &dirp->dd_dirent;
+}
+
+
+void _seekdir (DIR *dirp, long off)
+{
+  long i;
+  struct _dircontents *dp;
+  
+  if (off >= 0)
+    {
+      i = 0;
+      for (dp = dirp->dd_contents; i < off && dp != NULL; dp = dp->_d_next)
+        ++i;
+      dirp->dd_loc = i;
+      dirp->dd_cp = dp;
+    }
+  else
+    errno = EINVAL;
+}
+
+
+void _rewinddir (DIR *dirp)
+{
+  _seekdir (dirp, 0L);
+}
+
+
+long _telldir (DIR *dirp)
+{
+  return dirp->dd_loc;
+}
+
+
+DIR *_opendir (const char *name)
+{
+  struct stat statb;
+  struct _find find;
+  DIR *dirp;
+  char *s;
+  struct _dircontents *dp;
+  char nbuf[MAXPATHLEN+1];
+  int len;
+  
+  len = strlen (name);
+  memcpy (nbuf, name, len + 1);
+  s = nbuf + len;
+  if (_trslash (nbuf, len, 0))
+    {
+      nbuf[len++] = '.';        /* s now points to '.' */
+      nbuf[len] = 0;
+    }
+  if (_stat (nbuf, &statb) < 0)
+    return NULL;
+  if ((statb.st_mode & S_IFMT) != S_IFDIR)
+    {
+      errno = ENOTDIR;
+      return NULL;
+    }
+  dirp = malloc (sizeof (DIR));
+  if (dirp == NULL)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+  if (*s == 0)
+    *s++ = '\\';
+  strcpy (s, "*.*");
+  dirp->dd_loc = 0;
+  dirp->dd_contents = NULL;
+  dirp->dd_cp = NULL;
+  s = getdirent (nbuf, &find, name);
+  if (s == NULL)
+    {
+      errno = ENOMEM;
+      return dirp;
+    }
+  do
+    {
+      dp = malloc (sizeof (struct _dircontents));
+      if (dp == NULL)
+        {
+          free_dircontents (dirp->dd_contents);
+          errno = ENOMEM;
+          return NULL;
+        }
+      dp->_d_entry = malloc (strlen (s) + 1);
+      if (dp->_d_entry == NULL)
+        {
+          free (dp);
+          free_dircontents (dirp->dd_contents);
+          errno = ENOMEM;
+          return NULL;
+        }
+      if (dirp->dd_contents != NULL)
+        dirp->dd_cp->_d_next = dp;
+      else
+        dirp->dd_contents = dp;
+      dirp->dd_cp = dp;
+      strcpy (dp->_d_entry, s);
+      dp->_d_next = NULL;
+      dp->_d_size = ((unsigned long)find.size_hi << 16) + find.size_lo;
+      dp->_d_attr = find.attr;
+      dp->_d_time = find.time;
+      dp->_d_date = find.date;
+      s = getdirent (NULL, &find, name);
+    } while (s != NULL);
+  dirp->dd_cp = dirp->dd_contents;
+  return dirp;
+}
+
+
+static void free_dircontents (struct _dircontents *dp)
+{
+  struct _dircontents *odp;
+
+  while (dp != NULL)
+    {
+      if (dp->_d_entry != NULL)
+        free(dp->_d_entry);
+      odp = dp;
+      dp = dp->_d_next;
+      free (odp);
+    }
+}
+
+
+static char *getdirent (const char *dir, struct _find *pfind, const char *base)
+{
+  int rc;
+
+  if (dir != NULL)
+    rc = __findfirst (dir, A_DIR|A_HIDDEN|A_SYSTEM, pfind);
+  else
+    rc = __findnext (pfind);
+  if (rc == 0)
+    {
+      _fnlwr2 (pfind->name, base);
+      return pfind->name;
+    }
+  else
+    return NULL;
+}
Index: trunk/src/emx/src/lib/misc/dtread.c
===================================================================
--- trunk/src/emx/src/lib/misc/dtread.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/dtread.c	(revision 18)
@@ -0,0 +1,201 @@
+/* dtread.c (emx+gcc) -- Copyright (c) 1987-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/dirent.h>
+#include <sys/dirtree.h>
+#include <emx/io.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+
+static void _dt_free_recurse (struct _dt_node *dn)
+{
+  struct _dt_node *next;
+
+  while (dn != NULL)
+    {
+      next = dn->next;
+      if (dn->name != NULL)
+        free (dn->name);
+      if (dn->sub != NULL)
+        _dt_free_recurse (dn->sub);
+      free (dn);
+      dn = next;
+    }
+}
+
+
+void _dt_free (struct _dt_tree *dt)
+{
+  if (dt->strings != NULL)
+    {
+      free (dt->strings);
+      dt->strings = NULL;
+    }
+  _dt_free_recurse (dt->tree);
+  free (dt);
+}
+
+
+struct _dt_rdata
+{
+  struct _find find;
+  char path[MAXPATHLEN+1];
+  const char *dir;
+  const char *mask;
+  unsigned flags;
+  int attr, dir_pass;
+};
+
+
+static int _dt_match (struct _dt_rdata *dp)
+{
+  if ((dp->flags & _DT_NOCPDIR) && (strcmp (dp->find.name, ".") == 0 ||
+                                    strcmp (dp->find.name, "..") == 0))
+    return 0;
+  return 1;
+}
+
+
+static struct _dt_node *_dt_add (struct _dt_rdata *dp)
+{
+  struct _dt_node *new;
+  struct tm tm;
+
+  new = malloc (sizeof (*new));
+  if (new == NULL)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+  new->next = NULL;
+  new->sub = NULL;
+  new->name = _strdup (dp->find.name);
+  if (new->name == NULL)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+  _fnlwr2 (new->name, dp->dir);
+  new->size = dp->find.size_lo + ((long)dp->find.size_hi << 16);
+  new->user = 0;
+  new->attr = dp->find.attr;
+  tm.tm_sec = (dp->find.time & 0x1f) * 2;
+  tm.tm_min = (dp->find.time >> 5) & 0x3f;
+  tm.tm_hour = (dp->find.time >> 11) & 0x1f;
+  tm.tm_mday = dp->find.date & 0x1f;
+  tm.tm_mon = ((dp->find.date >> 5) & 0x0f) - 1;
+  tm.tm_year = ((dp->find.date >> 9) & 0x7f) + 1980 - 1900;
+  tm.tm_isdst = -1;             /* unknown */
+  new->mtime = _mktime (&tm);
+  _loc2gmt (&new->mtime, -1);
+  return new;
+}
+
+
+static int _dt_read_recurse (struct _dt_rdata *dp, struct _dt_node **dst,
+                             int path_len)
+{
+  struct _dt_node *new, **add;
+  int r, len2;
+
+  *dst = NULL;
+  add = dst;
+  strcpy (dp->path + path_len, dp->mask);
+  r = __findfirst (dp->path, dp->attr, &dp->find);
+  while (r == 0)
+    {
+      if (!(dp->dir_pass && (dp->find.attr & A_DIR)) && _dt_match (dp))
+        {
+          new = _dt_add (dp);
+          if (new == NULL)
+            return -1;
+          *add = new;
+          add = &new->next;
+        }
+      r = __findnext (&dp->find);
+    }
+  if (errno != ENOENT)
+    return -1;
+  if (dp->dir_pass)
+    {
+      strcpy (dp->path + path_len, "*.*");
+      r = __findfirst (dp->path, A_DIR|A_HIDDEN|A_SYSTEM, &dp->find);
+      while (r == 0)
+        {
+          if ((dp->find.attr & A_DIR) && _dt_match (dp))
+            {
+              new = _dt_add (dp);
+              if (new == NULL)
+                return -1;
+              *add = new;
+              add = &new->next;
+            }
+          r = __findnext (&dp->find);
+        }
+      if (errno != ENOENT)
+        return -1;
+    }
+  if (dp->flags & _DT_TREE)
+    for (new = *dst; new != NULL; new = new->next)
+      if ((new->attr & A_DIR) && strcmp (new->name, ".") != 0
+          && strcmp (new->name, "..") != 0)
+        {
+          len2 = strlen (new->name);
+          strcpy (dp->path + path_len, new->name);
+          dp->path[path_len+len2] = '/';
+          if (_dt_read_recurse (dp, &new->sub, path_len+len2+1) < 0)
+            return -1;
+        }
+  return 0;
+}
+
+
+struct _dt_tree *_dt_read (const char *dir, const char *mask,
+                           unsigned flags)
+{
+  struct _dt_tree *p;
+  struct _dt_rdata data;
+  int len, saved_errno;
+
+  if (!_tzset_flag) _tzset ();
+  data.dir = dir;
+  data.mask = mask;
+  data.flags = flags;
+  data.dir_pass = 1;
+  if (strcmp (mask, "*.*") == 0
+      || (_osmode == OS2_MODE && strcmp (mask, "*") == 0))
+    data.dir_pass = 0;
+  data.attr = A_HIDDEN | A_SYSTEM;
+  if (!data.dir_pass)
+    data.attr |= A_DIR;
+  len = strlen (dir);
+  if (len >= sizeof (data.path))
+    {
+      errno = ENAMETOOLONG;
+      return NULL;
+    }
+  memcpy (data.path, dir, len);
+  if (len > 0 && !_trslash (data.path, len, 0))
+    data.path[len++] = '/';
+  p = malloc (sizeof (*p));
+  if (p == NULL)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+  p->strings = NULL;
+  saved_errno = errno;
+  if (_dt_read_recurse (&data, &p->tree, len) != 0)
+    {
+      _dt_free (p);
+      return NULL;
+    }
+  errno = saved_errno;
+  return p;
+}
Index: trunk/src/emx/src/lib/misc/dtsort.c
===================================================================
--- trunk/src/emx/src/lib/misc/dtsort.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/dtsort.c	(revision 18)
@@ -0,0 +1,192 @@
+/* dtsort.c (emx+gcc) -- Copyright (c) 1987-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/dirent.h>
+#include <sys/dirtree.h>
+#include <sys/nls.h>
+
+
+static struct
+{
+  struct _dt_node **buf;
+  int buf_alloc;
+  const char *spec;
+} _dt_sort_data;
+
+
+static int _dt_compare_size (const struct _dt_node *n1,
+                             const struct _dt_node *n2)
+{
+  if (n1->size < n2->size)
+    return -1;
+  else if (n1->size > n2->size)
+    return 1;
+  else
+    return 0;
+}
+
+
+
+static int _dt_compare_time (const struct _dt_node *n1,
+                             const struct _dt_node *n2)
+{
+  if (n1->mtime < n2->mtime)
+    return -1;
+  else if (n1->mtime > n2->mtime)
+    return 1;
+  else
+    return 0;
+}
+
+
+static int _dt_compare_file (const struct _dt_node *n1,
+                             const struct _dt_node *n2)
+{
+  int a1, a2;
+
+  a1 = n1->attr & A_DIR;
+  a2 = n2->attr & A_DIR;
+  if (a1 < a2)
+    return 1;
+  else if (a1 > a2)
+    return -1;
+  else
+    return 0;
+}
+
+
+static int _dt_compare_ext (const struct _dt_node *n1,
+                            const struct _dt_node *n2)
+{
+  const char *ext1, *ext2;
+  int d;
+
+  ext1 = _getext (n1->name);
+  ext2 = _getext (n2->name);
+  if (ext1 == NULL && ext2 == NULL)
+    return 0;
+  if (ext1 == NULL && ext2 != NULL)
+    return -1;
+  if (ext2 == NULL && ext1 != NULL)
+    return 1;
+  d = _fncmp (ext1, ext2);
+  if (d == 0)
+    d = strcmp (ext1, ext2);
+  return d;
+}
+
+
+static int _dt_compare_name (const struct _dt_node *n1,
+                             const struct _dt_node *n2)
+{
+  int d;
+
+  d = _fncmp (n1->name, n2->name);
+  if (d == 0)
+    d = strcmp (n1->name, n2->name);
+  return d;
+}
+
+
+static int _dt_sort_compare (const void *x1, const void *x2)
+{
+  const struct _dt_node *n1, *n2;
+  const char *p;
+  int result;
+
+  n1 = *(const struct _dt_node **)x1;
+  n2 = *(const struct _dt_node **)x2;
+  for (p = _dt_sort_data.spec; *p != 0; ++p)
+    {
+      switch (*p)
+        {
+        case 'n':
+          result = _dt_compare_name (n1, n2);
+          break;
+        case 'N':
+          result = _dt_compare_name (n2, n1);
+          break;
+        case 'e':
+          result = _dt_compare_ext (n1, n2);
+          break;
+        case 'E':
+          result = _dt_compare_ext (n2, n1);
+          break;
+        case 't':
+          result = _dt_compare_time (n1, n2);
+          break;
+        case 'T':
+          result = _dt_compare_time (n2, n1);
+          break;
+        case 's':
+          result = _dt_compare_size (n1, n2);
+          break;
+        case 'S':
+          result = _dt_compare_size (n2, n1);
+          break;
+        case 'f':
+          result = _dt_compare_file (n1, n2);
+          break;
+        case 'F':
+          result = _dt_compare_file (n2, n1);
+          break;
+        default:
+          result = 0;
+          break;
+        }
+      if (result != 0)
+        return result;
+    }
+  return 0;
+}
+
+
+static void _dt_sort_recurse (struct _dt_node **tree)
+{
+  int i, n;
+  struct _dt_node *p, **add;
+
+  n = 0;
+  for (p = *tree; p != NULL; p = p->next)
+    ++n;
+  if (n > _dt_sort_data.buf_alloc)
+    {
+      _dt_sort_data.buf_alloc = n;
+      _dt_sort_data.buf = realloc (_dt_sort_data.buf,
+                                   n * sizeof (*_dt_sort_data.buf));
+      if (_dt_sort_data.buf == NULL)
+        return;
+    }
+  if (n >= 2)
+    {
+      n = 0;
+      for (p = *tree; p != NULL; p = p->next)
+        _dt_sort_data.buf[n++] = p;
+      qsort (_dt_sort_data.buf, n, sizeof (*_dt_sort_data.buf),
+             _dt_sort_compare);
+      add = tree; *tree = NULL;
+      for (i = 0; i < n; ++i)
+        {
+          p = _dt_sort_data.buf[i];
+          p->next = NULL;
+          *add = p;
+          add = &p->next;
+        }
+    }
+  for (p = *tree; p != NULL; p = p->next)
+    if (p->sub != NULL)
+      _dt_sort_recurse (&p->sub);
+}
+
+
+void _dt_sort (struct _dt_tree *dt, const char *spec)
+{
+  _dt_sort_data.buf = NULL;
+  _dt_sort_data.buf_alloc = 0;
+  _dt_sort_data.spec = spec;
+  _dt_sort_recurse (&dt->tree);
+  if (_dt_sort_data.buf != NULL)
+    free (_dt_sort_data.buf);
+}
Index: trunk/src/emx/src/lib/misc/dtsplit.c
===================================================================
--- trunk/src/emx/src/lib/misc/dtsplit.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/dtsplit.c	(revision 18)
@@ -0,0 +1,91 @@
+/* dtsplit.c (emx+gcc) -- Copyright (c) 1987-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/dirtree.h>
+#include <emx/io.h>
+
+
+int _dt_split (const char *src, char *dir, char *mask)
+{
+  unsigned char drive;
+  char *p;
+  char old_dir[MAXPATHLEN+1];
+  char path_buf[MAXPATHLEN+1];
+  char mask_buf[MAXPATHLEN+1];
+  int saved_errno;
+  size_t len;
+
+  drive = _fngetdrive (src);
+  if (drive != 0)
+    {
+      src += 2;
+      if (*src == 0)
+        src = ".";
+    }
+  else
+    drive = _getdrive ();
+  path_buf[0] = drive;
+  path_buf[1] = ':';
+  if (strlen (src) >= sizeof (path_buf) - 2)
+    {
+      errno = ENAMETOOLONG;
+      return -1;
+    }
+  strcpy (path_buf + 2, src);
+  strcpy (mask_buf, "*.*");
+  old_dir[0] = drive;
+  old_dir[1] = ':';
+  if (_getcwd1 (old_dir+2, drive) != 0)
+    return -1;
+  saved_errno = errno;
+  if (_chdir (path_buf) != 0)
+    {
+      errno = saved_errno;
+      p = _getname (path_buf + 2);
+      if (p == path_buf + 2)
+        {
+          strcpy (mask_buf, path_buf+2);
+          path_buf[2] = '.';
+          path_buf[3] = 0;
+        }
+      else
+        {
+          if (*p != 0)
+            strcpy (mask_buf, p);
+          if (p == path_buf + 3)
+            path_buf[3] = 0;    /* Root directory */
+          else
+            p[-1] = 0;          /* Remove last name */
+        }
+      if (_chdir (path_buf) != 0)
+        return -1;
+    }
+  if (strcmp (mask_buf, "..") == 0)
+    {
+      _chdir (old_dir);
+      errno = EINVAL;
+      return -1;
+    }
+  if (_getcwd1 (path_buf+2, drive) != 0)
+    {
+      saved_errno = errno;
+      _chdir (old_dir);
+      errno = saved_errno;
+      return -1;
+    }
+  if (path_buf[3] != 0)
+    {
+      len = strlen (path_buf);
+      if (_trslash (path_buf, len, 0))
+        path_buf[len-1] = 0;
+    }
+  _chdir (old_dir);
+  if (dir != NULL)
+    strcpy (dir, path_buf);
+  if (mask != NULL)
+    strcpy (mask, mask_buf);
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/envargs.c
===================================================================
--- trunk/src/emx/src/lib/misc/envargs.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/envargs.c	(revision 18)
@@ -0,0 +1,43 @@
+/* envargs.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <emx/startup.h>
+
+void _envargs (int *argcp, char ***argvp, const char *name)
+{
+  char *str, *p, **args, **argv, **new_argv;
+  int argc, i, n, len;
+
+  str = getenv (name);
+  if (str == NULL || *str == 0)
+    return;
+  str = _strdup (str);
+  if (str == NULL)
+    return;
+  args = _splitargs (str, &n);
+  if (args == NULL || n == 0)
+    return;
+  argc = *argcp; argv = *argvp;
+  new_argv = malloc ((argc + n + 1) * sizeof (char *));
+  if (new_argv == NULL)
+    return;
+  new_argv[0] = argv[0];
+  for (i = 0; i < n; ++i)
+    {
+      len = strlen (args[i]);
+      p = malloc (len + 2);
+      if (p == NULL)
+        return;
+      p[0] = _ARG_NONZERO|_ARG_ENV;
+      memcpy (p + 1, args[i], len + 1);
+      new_argv[1+i] = p + 1;
+    }
+  for (i = 1; i < argc; ++i)
+    new_argv[n+i] = argv[i];
+  new_argv[n+argc] = NULL;
+  free (str);
+  free (args);
+  *argcp = argc + n;
+  *argvp = new_argv;
+}
Index: trunk/src/emx/src/lib/misc/execname.c
===================================================================
--- trunk/src/emx/src/lib/misc/execname.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/execname.c	(revision 18)
@@ -0,0 +1,9 @@
+/* execname.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+int _execname (char *dst, size_t size)
+{
+  return __execname (dst, size);
+}
Index: trunk/src/emx/src/lib/misc/filesys.c
===================================================================
--- trunk/src/emx/src/lib/misc/filesys.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/filesys.c	(revision 18)
@@ -0,0 +1,9 @@
+/* filesys.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+int _filesys (const char *drive, char *name, size_t size)
+{
+  return __filesys (drive, name, size);
+}
Index: trunk/src/emx/src/lib/misc/fnexplod.c
===================================================================
--- trunk/src/emx/src/lib/misc/fnexplod.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/fnexplod.c	(revision 18)
@@ -0,0 +1,80 @@
+/* fnexplod.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <emx/syscalls.h>
+
+
+char **_fnexplode (const char *mask)
+{
+  char **list, **tmp, *p, *q;
+  int a, n, i;
+  struct _find find;
+  struct stat st;
+  char name[MAXNAMLEN];
+
+  /* Avoid expanding a directory to all the files and directories it
+     contains. */
+
+  if (_stat (mask, &st) == 0 && S_ISDIR (st.st_mode))
+    return NULL;
+
+  _strncpy (name, mask, sizeof (name));
+  p = _getname (name);
+  list = NULL; n = 0; a = 0;
+  if (__findfirst (mask, 0x10, &find) != 0)
+    return NULL;
+  do
+    {
+      if (strcmp (find.name, ".") != 0 &&
+          strcmp (find.name, "..") != 0)
+        {
+          if (n + 1 >= a)
+            {
+              a += 32;
+              tmp = realloc (list, a * sizeof (char **));
+              if (tmp == NULL)
+                {
+                  errno = ENOMEM;
+                  goto failure;
+                }
+              list = tmp;
+            }
+          strcpy (p, find.name);
+          _fnlwr2 (name, name);
+          q = _strdup (name);
+          if (q == NULL)
+            {
+              errno = ENOMEM;
+              goto failure;
+            }
+          list[n++] = q;
+        }
+    } while (__findnext (&find) == 0);
+  if (list != NULL)
+    list[n] = NULL;
+  return list;
+
+failure:            
+  if (list != NULL)
+    {
+      for (i = 0; i < n; ++i)
+        free (list[i]);
+      free (list);
+    }
+  return NULL;
+}
+
+
+void _fnexplodefree (char **list)
+{
+  int i;
+
+  for (i = 0; list[i] != NULL; ++i)
+    free (list[i]);
+  free (list);
+}
Index: trunk/src/emx/src/lib/misc/fngetdrv.c
===================================================================
--- trunk/src/emx/src/lib/misc/fngetdrv.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/fngetdrv.c	(revision 18)
@@ -0,0 +1,16 @@
+/* fngetdrv.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+char _fngetdrive (const char *src)
+{
+  /* As we check the first character we can't hit by accident a DBCS
+     character having ':' as second byte. */
+
+  if (src[0] >= 'A' && src[0] <= 'Z' && src[1] == ':')
+    return src[0];
+  else if (src[0] >= 'a' && src[0] <= 'z' && src[1] == ':')
+    return src[0]-'a'+'A';
+  else
+    return 0;
+}
Index: trunk/src/emx/src/lib/misc/fnisabs.c
===================================================================
--- trunk/src/emx/src/lib/misc/fnisabs.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/fnisabs.c	(revision 18)
@@ -0,0 +1,11 @@
+/* fnisabs.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <ctype.h>
+
+int _fnisabs (const char *name)
+{
+  if (isalpha ((unsigned char)name[0]) && name[1] == ':')
+    name += 2;
+  return name[0] == '/' || name[0] == '\\';
+}
Index: trunk/src/emx/src/lib/misc/fnisrel.c
===================================================================
--- trunk/src/emx/src/lib/misc/fnisrel.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/fnisrel.c	(revision 18)
@@ -0,0 +1,10 @@
+/* fnisrel.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <ctype.h>
+
+int _fnisrel (const char *name)
+{
+  return !(*name == '/' || *name == '\\'
+           || (isalpha ((unsigned char)name[0]) && name[1] == ':'));
+}
Index: trunk/src/emx/src/lib/misc/fnmatch.c
===================================================================
--- trunk/src/emx/src/lib/misc/fnmatch.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/fnmatch.c	(revision 18)
@@ -0,0 +1,597 @@
+/* fnmatch.c (emx+gcc) -- Copyright (c) 1994-1998 by Eberhard Mattes */
+
+#include <string.h>
+#include <ctype.h>
+#include <fnmatch.h>
+#include <sys/nls.h>
+
+/* In OS/2 and DOS styles, both / and \ separate components of a path.
+   This macro returns true iff C is a separator. */
+
+#define IS_OS2_COMP_SEP(C)  ((C) == '/' || (C) == '\\')
+
+
+/* This macro returns true if C is at the end of a component of a
+   path. */
+
+#define IS_OS2_COMP_END(C)  ((C) == 0 || IS_OS2_COMP_SEP (C))
+
+
+/* Return a pointer to the next component of the path SRC, for OS/2
+   and DOS styles.  When the end of the string is reached, a pointer
+   to the terminating null character is returned. */
+
+static const unsigned char *skip_comp_os2 (const unsigned char *src)
+{
+  /* Skip characters until hitting a separator or the end of the
+     string. */
+
+  while (!IS_OS2_COMP_END (*src))
+    if (_nls_is_dbcs_lead (*src) && src[1] != 0)
+      src += 2;
+    else
+      ++src;
+
+  /* Skip the separator if we hit a separator. */
+
+  if (*src != 0)
+    ++src;
+  return src;
+}
+
+
+/* Return true iff the path P contains a colon. */
+
+static int has_colon (const unsigned char *p)
+{
+  while (*p != 0)
+    if (*p == ':')
+      return 1;
+    else if (_nls_is_dbcs_lead (p[0]) && p[1] != 0)
+      p += 2;
+    else
+      ++p;
+  return 0;
+}
+
+
+/* Compare a single component (directory name or file name) of the
+   paths, for OS/2 and DOS styles.  MASK and NAME point into a
+   component of the wildcard and the name to be checked, respectively.
+   Comparing stops at the next separator.  The FLAGS argument is the
+   same as that of fnmatch().  HAS_DOT is true if a dot is in the
+   current component of NAME.  The number of dots is not restricted,
+   even in DOS style.  Return _FNM_MATCH iff MASK and NAME match.
+   Note that this function is recursive. */
+
+static int match_comp_os2 (const unsigned char *mask,
+                           const unsigned char *name,
+                           unsigned flags, int has_dot)
+{
+  int rc;
+
+  for (;;)
+    if (_nls_is_dbcs_lead (*mask) && mask[1] != 0)
+      {
+        /* DBCS characters match themselves. */
+
+        if (mask[0] != name[0] || mask[1] != name[1])
+          return FNM_NOMATCH;
+        mask += 2; name += 2;
+      }
+    else
+      switch (*mask)
+        {
+        case 0:
+
+          /* There must be no extra characters at the end of NAME when
+             reaching the end of MASK unless _FNM_PATHPREFIX is set:
+             in that case, NAME may point to a separator. */
+
+          if (*name == 0)
+            return _FNM_MATCH;
+          if ((flags & _FNM_PATHPREFIX) && IS_OS2_COMP_SEP (*name))
+            return _FNM_MATCH;
+          return FNM_NOMATCH;
+
+        case '/':
+        case '\\':
+
+          /* Separators match separators. */
+
+          if (IS_OS2_COMP_SEP (*name))
+            return _FNM_MATCH;
+
+          /* If _FNM_PATHPREFIX is set, a trailing separator in MASK
+             is ignored at the end of NAME. */
+
+          if ((flags & _FNM_PATHPREFIX) && mask[1] == 0 && *name == 0)
+            return _FNM_MATCH;
+
+          /* Stop comparing at the separator. */
+
+          return FNM_NOMATCH;
+
+        case '?':
+
+          /* A question mark matches one character.  It does not match
+             a dot.  At the end of the component (and before a dot),
+             it also matches zero characters. */
+
+          if (*name != '.' && !IS_OS2_COMP_END (*name))
+            {
+              if (_nls_is_dbcs_lead (name[0]) && name[1] != 0)
+                name += 2;
+              else
+                ++name;
+            }
+          ++mask;
+          break;
+
+        case '*':
+
+          /* An asterisk matches zero or more characters.  In DOS
+             mode, dots are not matched. */
+
+          do
+            {
+              ++mask;
+            } while (*mask == '*');
+          for (;;)
+            {
+              rc = match_comp_os2 (mask, name, flags, has_dot);
+              if (rc != FNM_NOMATCH)
+                return rc;
+              if (IS_OS2_COMP_END (*name))
+                return FNM_NOMATCH;
+              if (*name == '.' && (flags & _FNM_STYLE_MASK) == _FNM_DOS)
+                return FNM_NOMATCH;
+              if (_nls_is_dbcs_lead (name[0]) && name[1] != 0)
+                name += 2;
+              else
+                ++name;
+            }
+
+        case '.':
+
+          /* A dot matches a dot.  It also matches the implicit dot at
+             the end of a dot-less NAME. */
+
+          ++mask;
+          if (*name == '.')
+            ++name;
+          else if (has_dot || !IS_OS2_COMP_END (*name))
+            return FNM_NOMATCH;
+          break;
+
+        default:
+
+          /* All other characters match themselves. */
+
+          if (flags & _FNM_IGNORECASE)
+            {
+              if (_nls_tolower (*mask) != _nls_tolower (*name))
+                return FNM_NOMATCH;
+            }
+          else
+            {
+              if (*mask != *name)
+                return FNM_NOMATCH;
+            }
+          ++mask; ++name;
+          break;
+        }
+}
+
+
+/* Compare a single component (directory name or file name) of the
+   paths, for all styles which need component-by-component matching.
+   MASK and NAME point to the start of a component of the wildcard and
+   the name to be checked, respectively.  Comparing stops at the next
+   separator.  The FLAGS argument is the same as that of fnmatch().
+   Return _FNM_MATCH iff MASK and NAME match. */
+
+static int match_comp (const unsigned char *mask, const unsigned char *name,
+                       unsigned flags)
+{
+  const unsigned char *s;
+
+  switch (flags & _FNM_STYLE_MASK)
+    {
+    case _FNM_OS2:
+    case _FNM_DOS:
+
+      /* For OS/2 and DOS styles, we add an implicit dot at the end of
+         the component if the component doesn't include a dot. */
+
+      s = name;
+      while (!IS_OS2_COMP_END (*s) && *s != '.')
+        if (_nls_is_dbcs_lead (s[0]) && s[1] != 0)
+          s += 2;
+        else
+          ++s;
+      return match_comp_os2 (mask, name, flags, *s == '.');
+
+    default:
+      return _FNM_ERR;
+    }
+}
+
+
+
+/* In Unix styles, / separates components of a path.  This macro
+   returns true iff C is a separator. */
+
+#define IS_UNIX_COMP_SEP(C)  ((C) == '/')
+
+
+/* This macro returns true if C is at the end of a component of a
+   path. */
+
+#define IS_UNIX_COMP_END(C)  ((C) == 0 || IS_UNIX_COMP_SEP (C))
+
+
+/* Match complete paths for Unix styles.  The FLAGS argument is the
+   same as that of fnmatch().  COMP points to the start of the current
+   component in NAME.  Return _FNM_MATCH iff MASK and NAME match.  The
+   backslash character is used for escaping ? and * unless
+   FNM_NOESCAPE is set. */
+
+static int match_unix (const unsigned char *mask, const unsigned char *name,
+                       unsigned flags, const unsigned char *comp)
+{
+  unsigned char c1, c2;
+  char invert, matched;
+  const unsigned char *start;
+  int rc;
+
+  for (;;)
+    if (_nls_is_dbcs_lead (*mask))
+      {
+        /* DBCS characters match themselves. */
+
+        if (mask[0] != name[0] || mask[1] != name[1])
+          return FNM_NOMATCH;
+        mask += 2; name += 2;
+      }
+    else
+      switch (*mask)
+        {
+        case 0:
+
+          /* There must be no extra characters at the end of NAME when
+             reaching the end of MASK unless _FNM_PATHPREFIX is set:
+             in that case, NAME may point to a separator. */
+
+          if (*name == 0)
+            return _FNM_MATCH;
+          if ((flags & _FNM_PATHPREFIX) && IS_UNIX_COMP_SEP (*name))
+            return _FNM_MATCH;
+          return FNM_NOMATCH;
+
+        case '?':
+
+          /* A question mark matches one character.  It does not match
+             the component separator if FNM_PATHNAME is set.  It does
+             not match a dot at the start of a component if FNM_PERIOD
+             is set. */
+
+          if (*name == 0)
+            return FNM_NOMATCH;
+          if ((flags & FNM_PATHNAME) && IS_UNIX_COMP_SEP (*name))
+            return FNM_NOMATCH;
+          if (*name == '.' && (flags & FNM_PERIOD) && name == comp)
+            return FNM_NOMATCH;
+          ++mask;
+          if (_nls_is_dbcs_lead (name[0]) && name[1] != 0)
+            name += 2;
+          else
+            ++name;
+          break;
+
+        case '*':
+
+          /* An asterisk matches zero or more characters.  It does not
+             match the component separator if FNM_PATHNAME is set.  It
+             does not match a dot at the start of a component if
+             FNM_PERIOD is set. */
+
+          if (*name == '.' && (flags & FNM_PERIOD) && name == comp)
+            return FNM_NOMATCH;
+          do
+            {
+              ++mask;
+            } while (*mask == '*');
+          for (;;)
+            {
+              rc = match_unix (mask, name, flags, comp);
+              if (rc != FNM_NOMATCH)
+                return rc;
+              if (*name == 0)
+                return FNM_NOMATCH;
+              if ((flags & FNM_PATHNAME) && IS_UNIX_COMP_SEP (*name))
+                return FNM_NOMATCH;
+              if (_nls_is_dbcs_lead (name[0]) && name[1] != 0)
+                name += 2;
+              else
+                ++name;
+            }
+
+        case '/':
+
+          /* Separators match only separators.  If _FNM_PATHPREFIX is
+             set, a trailing separator in MASK is ignored at the end
+             of NAME. */
+
+          if (!(IS_UNIX_COMP_SEP (*name)
+                || ((flags & _FNM_PATHPREFIX) && *name == 0
+                    && (mask[1] == 0
+                        || (!(flags & FNM_NOESCAPE) && mask[1] == '\\'
+                            && mask[2] == 0)))))
+            return FNM_NOMATCH;
+
+          ++mask;
+          if (*name != 0) ++name;
+
+          /* This is the beginning of a new component if FNM_PATHNAME
+             is set. */
+
+          if (flags & FNM_PATHNAME)
+            comp = name;
+          break;
+
+        case '[':
+
+          /* A set of characters.  Always case-sensitive. */
+
+          if (*name == 0)
+            return FNM_NOMATCH;
+          if ((flags & FNM_PATHNAME) && IS_UNIX_COMP_SEP (*name))
+            return FNM_NOMATCH;
+          if (*name == '.' && (flags & FNM_PERIOD) && name == comp)
+            return FNM_NOMATCH;
+
+          invert = 0; matched = 0;
+          ++mask;
+
+          /* If the first character is a ! or ^, the set matches all
+             characters not listed in the set. */
+
+          if (*mask == '!' || *mask == '^')
+            {
+              ++mask; invert = 1;
+            }
+          else if (_nls_is_dbcs_lead (*name))
+            {
+              /* DBCS characters can only match inverted sets. */
+
+              return FNM_NOMATCH;
+            }
+
+          /* Loop over all the characters of the set.  The loop ends
+             if the end of the string is reached or if a ] is
+             encountered unless it directly follows the initial [ or
+             [-. */
+
+          start = mask;
+          while (!(*mask == 0 || (*mask == ']' && mask != start)))
+            {
+              /* Get the next character which is optionally preceded
+                 by a backslash. */
+
+              c1 = *mask++;
+              if (_nls_is_dbcs_lead (c1))
+                return _FNM_ERR; /* DBCS characters not supported in sets */
+              if (!(flags & FNM_NOESCAPE) && c1 == '\\')
+                {
+                  if (*mask == 0)
+                    break;
+                  c1 = *mask++;
+                }
+
+              /* Ranges of characters are written as a-z.  Don't
+                 forget to check for the end of the string and to
+                 handle the backslash.  If the character after - is a
+                 ], it isn't a range. */
+
+              if (*mask == '-' && mask[1] != ']')
+                {
+                  ++mask;       /* Skip the - character */
+                  if (!(flags & FNM_NOESCAPE) && *mask == '\\')
+                    ++mask;
+                  if (*mask == 0)
+                    break;
+                  c2 = *mask++;
+                  if (_nls_is_dbcs_lead (c2))
+                    return _FNM_ERR; /* DBCS chars not supported in sets */
+                }
+              else
+                c2 = c1;
+
+              /* Now check whether this character or range matches NAME. */
+
+              if (c1 <= *name && *name <= c2)
+                matched = 1;
+            }
+
+          /* If the end of the string is reached before a ] is found,
+             back up to the [ and compare it to NAME. */
+
+          if (*mask == 0)
+            {
+              if (*name != '[')
+                return FNM_NOMATCH;
+              ++name;
+              mask = start;
+              if (invert)
+                --mask;
+            }
+          else
+            {
+              if (invert)
+                matched = !matched;
+              if (!matched)
+                return FNM_NOMATCH;
+              ++mask;           /* Skip the ] character */
+              if (*name != 0)
+                {
+                  if (_nls_is_dbcs_lead (name[0]) && name[1] != 0)
+                    name += 2;
+                  else
+                    ++name;
+                }
+            }
+          break;
+
+        case '\\':
+          ++mask;
+          if (flags & FNM_NOESCAPE)
+            {
+              if (*name != '\\')
+                return FNM_NOMATCH;
+              ++name;
+            }
+          else if (*mask == '*' || *mask == '?')
+            {
+              if (*mask != *name)
+                return FNM_NOMATCH;
+              ++mask; ++name;
+            }
+          break;
+
+        default:
+
+          /* All other characters match themselves. */
+
+          if (flags & _FNM_IGNORECASE)
+            {
+              if (_nls_tolower (*mask) != _nls_tolower (*name))
+                return FNM_NOMATCH;
+            }
+          else
+            {
+              if (*mask != *name)
+                return FNM_NOMATCH;
+            }
+          ++mask; ++name;
+          break;
+        }
+}
+
+
+/* Check whether the path name NAME matches the wildcard MASK.  Return
+   0 (_FNM_MATCH) if it matches, _FNM_NOMATCH if it doesn't.  Return
+   _FNM_ERR on error. The operation of this function is controlled by
+   FLAGS.  This is an internal function, with unsigned arguments. */
+
+
+static int _fnmatch_unsigned (const unsigned char *mask,
+                              const unsigned char *name,
+                              unsigned flags)
+{
+  int m_drive, n_drive, rc;
+
+  /* Match and skip the drive name if present. */
+
+  m_drive = ((isalpha (mask[0]) && mask[1] == ':') ? mask[0] : -1);
+  n_drive = ((isalpha (name[0]) && name[1] == ':') ? name[0] : -1);
+
+  if (m_drive != n_drive)
+    {
+      if (m_drive == -1 || n_drive == -1)
+        return FNM_NOMATCH;
+      if (!(flags & _FNM_IGNORECASE))
+        return FNM_NOMATCH;
+      if (_nls_tolower (m_drive) != _nls_tolower (n_drive))
+        return FNM_NOMATCH;
+    }
+
+  if (m_drive != -1) mask += 2;
+  if (n_drive != -1) name += 2;
+
+  /* Colons are not allowed in path names, except for the drive name,
+     which was skipped above. */
+
+  if (has_colon (mask) || has_colon (name))
+    return _FNM_ERR;
+
+  /* The name "\\server\path" should not be matched by mask
+     "\*\server\path".  Ditto for /. */
+
+  switch (flags & _FNM_STYLE_MASK)
+    {
+    case _FNM_OS2:
+    case _FNM_DOS:
+
+      if (IS_OS2_COMP_SEP (name[0]) && IS_OS2_COMP_SEP (name[1]))
+        {
+          if (!(IS_OS2_COMP_SEP (mask[0]) && IS_OS2_COMP_SEP (mask[1])))
+            return FNM_NOMATCH;
+          name += 2;
+          mask += 2;
+        }
+      break;
+
+    case _FNM_POSIX:
+
+      if (name[0] == '/' && name[1] == '/')
+        {
+          int i;
+
+          name += 2;
+          for (i = 0; i < 2; ++i)
+            if (mask[0] == '/')
+              ++mask;
+            else if (mask[0] == '\\' && mask[1] == '/')
+              mask += 2;
+            else
+              return FNM_NOMATCH;
+        }
+
+      /* In Unix styles, treating ? and * w.r.t. components is simple.
+         No need to do matching component by component. */
+
+      return match_unix (mask, name, flags, name);
+    }
+
+  /* Now compare all the components of the path name, one by one.
+     Note that the path separator must not be enclosed in brackets. */
+
+  while (*mask != 0 || *name != 0)
+    {
+
+      /* If _FNM_PATHPREFIX is set, the names match if the end of MASK
+         is reached even if there are components left in NAME. */
+
+      if (*mask == 0 && (flags & _FNM_PATHPREFIX))
+        return _FNM_MATCH;
+
+      /* Compare a single component of the path name. */
+
+      rc = match_comp (mask, name, flags);
+      if (rc != _FNM_MATCH)
+        return rc;
+
+      /* Skip to the next component or to the end of the path name. */
+
+      mask = skip_comp_os2 (mask);
+      name = skip_comp_os2 (name);
+    }
+
+  /* If we reached the ends of both strings, the names match. */
+
+  if (*mask == 0 && *name == 0)
+    return _FNM_MATCH;
+
+  /* The names do not match. */
+
+  return FNM_NOMATCH;
+}
+
+
+/* This is the public entrypoint, with signed arguments. */
+
+int _fnmatch (const char *mask, const char *name, int flags)
+{
+  return _fnmatch_unsigned (mask, name, flags);
+}
Index: trunk/src/emx/src/lib/misc/fnslashi.c
===================================================================
--- trunk/src/emx/src/lib/misc/fnslashi.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/fnslashi.c	(revision 18)
@@ -0,0 +1,19 @@
+/* fnslashi.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/nls.h>
+
+char *_fnslashify (char *name)
+{
+  char *p;
+
+  p = name;
+  while (*p != 0)
+    if (_nls_is_dbcs_lead ((unsigned char)*p) && p[1] != 0)
+      p += 2;
+    else if (*p == '\\')
+      *p++ = '/';
+    else
+      ++p;
+  return name;
+}
Index: trunk/src/emx/src/lib/misc/fpathcon.c
===================================================================
--- trunk/src/emx/src/lib/misc/fpathcon.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/fpathcon.c	(revision 18)
@@ -0,0 +1,44 @@
+/* fpathcon.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+/* Return the POSIX.1  minimum values, for now. */
+
+long _fpathconf (int handle, int name)
+{
+  switch (name)
+    {
+    case _PC_LINK_MAX:
+      return _POSIX_LINK_MAX;
+
+    case _PC_MAX_CANON:
+      return _POSIX_MAX_CANON;
+
+    case _PC_MAX_INPUT:
+      return _POSIX_MAX_INPUT;
+
+    case _PC_NAME_MAX:
+      return _POSIX_NAME_MAX;
+
+    case _PC_PATH_MAX:
+      return _POSIX_PATH_MAX;
+
+    case _PC_PIPE_BUF:
+      return _POSIX_PIPE_BUF;
+
+    case _PC_CHOWN_RESTRICTED:
+      return 1;
+
+    case _PC_NO_TRUNC:
+      return 1;                 /* TODO */
+
+    case _PC_VDISABLE:
+      return 0;
+
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/misc/ftw.c
===================================================================
--- trunk/src/emx/src/lib/misc/ftw.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/ftw.c	(revision 18)
@@ -0,0 +1,94 @@
+/* ftw.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <ftw.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <emx/io.h>
+
+static int ftw_recurse (int (*fn)(const char *name,
+                                  const struct stat *stat_ptr,
+                                  int flag),
+                        char *name_buf, int index)
+{
+  int rc, flag, len;
+  struct stat st;
+  DIR *dir;
+  struct dirent *ent;
+
+  dir = _opendir (name_buf);
+  if (dir == NULL)
+    return -1;
+  if (index < 1 || !_trslash (name_buf, index, 0))
+    name_buf[index++] = '/';
+  rc = 0;
+  for (;;)
+    {
+      ent = _readdir (dir);     /* emx version never fails */
+      if (ent == NULL)
+        break;
+      len = strlen (ent->d_name);
+      if (index + len >= MAXPATHLEN)
+        {
+          errno = ENAMETOOLONG;
+          rc = -1;
+          break;
+        }
+      strcpy (name_buf + index, ent->d_name);
+      if (_stat (name_buf, &st) != 0)
+        flag = FTW_NS;
+      else if ((st.st_mode & S_IFMT) == S_IFDIR)
+        flag = FTW_D;
+      else
+        flag = FTW_F;
+      if (flag != FTW_D || (strcmp (ent->d_name, ".") != 0 &&
+                            strcmp (ent->d_name, "..") != 0))
+        {
+          rc = fn (name_buf, &st, flag);
+          if (rc != 0)
+            break;
+          if (flag == FTW_D)
+            {
+              rc = ftw_recurse (fn, name_buf, index + len);
+              if (rc != 0)
+                break;
+            }
+        }
+    }
+  _closedir (dir);
+  return rc;
+}
+
+
+int _ftw (const char *path,
+          int (*fn)(const char *name, const struct stat *stat_ptr, int flag),
+          int depth)
+{
+  struct stat st;
+  char name_buf[MAXPATHLEN+1];
+  int rc, len;
+
+  len = strlen (path);
+  if (len >= MAXPATHLEN)
+    {
+      errno = ENAMETOOLONG;
+      return -1;
+    }
+  if (_stat (path, &st) != 0)
+    return -1;
+  if ((st.st_mode & S_IFMT) != S_IFDIR)
+    {
+      errno = ENOTDIR;
+      return -1;
+    }
+  strcpy (name_buf, path);
+  rc = fn (name_buf, &st, FTW_D);
+  if (rc != 0)
+    return rc;
+  return ftw_recurse (fn, name_buf, len);
+}
Index: trunk/src/emx/src/lib/misc/fullpath.c
===================================================================
--- trunk/src/emx/src/lib/misc/fullpath.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/fullpath.c	(revision 18)
@@ -0,0 +1,77 @@
+/* fullpath.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <emx/syscalls.h>
+#include <emx/io.h>
+
+int _fullpath (char *dst, const char *src, int size)
+{
+  char drive, cwd1[MAXPATHLEN+1], cwd2[MAXPATHLEN+1];
+  char *temp, c;
+  int i, j, k, add_file;
+
+  drive = _fngetdrive (src);
+  if (drive == 0)
+    drive = _getdrive ();
+  else
+    src += 2;
+  i = strlen (src);
+  temp = (char *)alloca (i+2+1);
+  temp[0] = drive; temp[1] = ':';
+  strcpy (temp+2, src);
+  cwd1[0] = cwd2[0] = drive;
+  cwd1[1] = cwd2[1] = ':';
+  cwd1[2] = cwd2[2] = '/';
+  if (__getcwd (cwd1+3, drive) != 0)
+    goto failure;
+  add_file = 0; k = 0;
+  if (_chdir (temp) != 0)
+    {
+      k = _getname (temp) - temp;
+      if (k == 3)
+        {
+          c = temp[k]; temp[k] = 0;
+          if (_chdir (temp) != 0)
+            goto failure;
+          temp[k] = c;
+        }
+      else if (k > 3)
+        {
+          temp[k-1] = 0;
+          if (_chdir (temp) != 0)
+            goto failure;
+        }
+      add_file = 1;
+    }
+  j = __getcwd (cwd2+3, drive);
+  if (_chdir (cwd1) != 0 || j != 0)
+    goto failure;
+  if (strlen (cwd2)+1 > size)
+    {
+      errno = ERANGE;
+      goto failure;
+    }
+  strcpy (dst, cwd2);
+  if (add_file && temp[k] != 0)
+    {
+      j = strlen (dst);
+      if (j+1+strlen (temp+k)+1 > size)
+        {
+          errno = ERANGE;
+          goto failure;
+        }
+      if (!_trslash (dst, j, 0))
+        dst[j++] = '/';
+      strcpy (dst+j, temp+k);
+    }
+  _fnslashify (dst);
+  return 0;
+
+failure:
+  dst[0] = 0;
+  return -1;
+}
Index: trunk/src/emx/src/lib/misc/getcwd.c
===================================================================
--- trunk/src/emx/src/lib/misc/getcwd.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getcwd.c	(revision 18)
@@ -0,0 +1,45 @@
+/* getcwd.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <emx/syscalls.h>
+
+char *_getcwd (char *buffer, size_t size)
+{
+  char tmp[MAXPATHLEN+1];
+  size_t len;
+
+  if (buffer != NULL && size == 0)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  if (__getcwd (tmp, 0) < 0)
+    return NULL;
+  len = strlen (tmp) + 2;
+  if (buffer != NULL)
+    {
+      if (len > size)
+        {
+          errno = ERANGE;
+          return NULL;
+        }
+    }
+  else
+    {
+      if (len > size)
+        size = len;
+      buffer = malloc (size);
+      if (buffer == NULL)
+        {
+          errno = ENOMEM;
+          return NULL;
+        }
+    }
+  _fnslashify (tmp);
+  buffer[0] = '/';
+  strcpy (buffer+1, tmp);
+  return buffer;
+}
Index: trunk/src/emx/src/lib/misc/getcwd1.c
===================================================================
--- trunk/src/emx/src/lib/misc/getcwd1.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getcwd1.c	(revision 18)
@@ -0,0 +1,13 @@
+/* getcwd1.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+int _getcwd1 (char *buffer, char drive)
+{
+  if (__getcwd (buffer+1, drive) < 0)
+    return -1;
+  _fnslashify (buffer+1);
+  buffer[0] = '/';
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/getcwd2.c
===================================================================
--- trunk/src/emx/src/lib/misc/getcwd2.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getcwd2.c	(revision 18)
@@ -0,0 +1,47 @@
+/* getcwd2.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <emx/syscalls.h>
+
+char *_getcwd2 (char *buffer, int size)
+{
+  char tmp[MAXPATHLEN+1];
+  int len;
+
+  if (buffer != NULL && size <= 0)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  if (__getcwd (tmp, 0) < 0)
+    return NULL;
+  len = strlen (tmp) + 4;
+  if (buffer != NULL)
+    {
+      if (len > size)
+        {
+          errno = ERANGE;
+          return NULL;
+        }
+    }
+  else
+    {
+      if (len > size)
+        size = len;
+      buffer = malloc (size);
+      if (buffer == NULL)
+        {
+          errno = ENOMEM;
+          return NULL;
+        }
+    }
+  _fnslashify (tmp);
+  buffer[0] = _getdrive();
+  buffer[1] = ':';
+  buffer[2] = '/';
+  strcpy (buffer+3, tmp);
+  return buffer;
+}
Index: trunk/src/emx/src/lib/misc/getdrive.c
===================================================================
--- trunk/src/emx/src/lib/misc/getdrive.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getdrive.c	(revision 18)
@@ -0,0 +1,9 @@
+/* getdrive.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+char _getdrive (void)
+{
+  return __getdrive ();
+}
Index: trunk/src/emx/src/lib/misc/getegid.c
===================================================================
--- trunk/src/emx/src/lib/misc/getegid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getegid.c	(revision 18)
@@ -0,0 +1,9 @@
+/* getegid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+gid_t _getegid (void)
+{
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/geteuid.c
===================================================================
--- trunk/src/emx/src/lib/misc/geteuid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/geteuid.c	(revision 18)
@@ -0,0 +1,9 @@
+/* geteuid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+uid_t _geteuid (void)
+{
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/getext.c
===================================================================
--- trunk/src/emx/src/lib/misc/getext.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getext.c	(revision 18)
@@ -0,0 +1,48 @@
+/* getext.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/nls.h>
+
+/* Note that _nls_is_dbcs_lead() returns false for all characters if
+   _nls_init() has not been called.  In consequence, this function
+   works properly for SBCS strings even if _nls_init() has not been
+   called. */
+
+#define FALSE   0
+#define TRUE    1
+
+char *_getext (const char *path)
+{
+  int sep;
+  const char *dotp;
+
+  sep = TRUE; dotp = NULL;
+  while (*path != 0)
+    if (_nls_is_dbcs_lead ((unsigned char)*path))
+      {
+        if (path[1] == 0)       /* Invalid DBCS character */
+          break;
+        path += 2;
+        sep = FALSE;
+      }
+    else
+      switch (*path++)
+        {
+        case '.':
+          /* Note that PATH has been incremented. */
+          dotp = (sep ? NULL : path - 1);
+          sep = FALSE;
+          break;
+        case ':':
+        case '/':
+        case '\\':
+          dotp = NULL;
+          sep = TRUE;
+          break;
+        default:
+          sep = FALSE;
+          break;
+        }
+  return (char *)dotp;
+}
Index: trunk/src/emx/src/lib/misc/getext2.c
===================================================================
--- trunk/src/emx/src/lib/misc/getext2.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getext2.c	(revision 18)
@@ -0,0 +1,12 @@
+/* getext2.c (emx+gcc) -- Copyright (c) 1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+
+char *_getext2 (const char *path)
+{
+  char *p;
+
+  p = _getext (path);
+  return (p != NULL ? p : "");
+}
Index: trunk/src/emx/src/lib/misc/getgid.c
===================================================================
--- trunk/src/emx/src/lib/misc/getgid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getgid.c	(revision 18)
@@ -0,0 +1,9 @@
+/* getgid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+gid_t _getgid (void)
+{
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/getgrgid.c
===================================================================
--- trunk/src/emx/src/lib/misc/getgrgid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getgrgid.c	(revision 18)
@@ -0,0 +1,19 @@
+/* getgrgid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/types.h>
+#include <grp.h>
+
+/* Dummy function */
+
+struct group *_getgrgid (gid_t gid)
+{
+  static struct group tmp_grp;
+  static char *tmp_members;
+
+  tmp_members = NULL;
+  tmp_grp.gr_name = "root";
+  tmp_grp.gr_gid = gid;
+  tmp_grp.gr_mem = &tmp_members;
+  return &tmp_grp;
+}
Index: trunk/src/emx/src/lib/misc/getgrnam.c
===================================================================
--- trunk/src/emx/src/lib/misc/getgrnam.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getgrnam.c	(revision 18)
@@ -0,0 +1,21 @@
+/* getgrnam.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <sys/types.h>
+#include <grp.h>
+
+/* Dummy function */
+
+struct group *_getgrnam (const char *name)
+{
+  static struct group tmp_grp;
+  static char *tmp_members;
+  static char tmp_name[9];
+
+  _strncpy (tmp_name, name, sizeof (tmp_name));
+  tmp_members = NULL;
+  tmp_grp.gr_name = tmp_name;
+  tmp_grp.gr_gid = 0;
+  tmp_grp.gr_mem = &tmp_members;
+  return &tmp_grp;
+}
Index: trunk/src/emx/src/lib/misc/getgroup.c
===================================================================
--- trunk/src/emx/src/lib/misc/getgroup.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getgroup.c	(revision 18)
@@ -0,0 +1,9 @@
+/* getgroup.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+int _getgroups (int gidsetsize, gid_t grouplist [])
+{
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/getlogin.c
===================================================================
--- trunk/src/emx/src/lib/misc/getlogin.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getlogin.c	(revision 18)
@@ -0,0 +1,20 @@
+/* getlogin.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+char *_getlogin (void)
+{
+  static char tmp_name[L_cuserid];
+  const char *name;
+
+  name = getenv ("LOGNAME");
+  if (name == NULL)
+    name = getenv ("USER");
+  if (name == NULL)
+    name = "root";
+  _strncpy (tmp_name, name, sizeof (tmp_name));
+  return tmp_name;
+}
Index: trunk/src/emx/src/lib/misc/getname.c
===================================================================
--- trunk/src/emx/src/lib/misc/getname.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getname.c	(revision 18)
@@ -0,0 +1,36 @@
+/* getname.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/nls.h>
+
+/* Note that _nls_is_dbcs_lead() returns false for all characters if
+   _nls_init() has not been called.  In consequence, this function
+   works properly for SBCS strings even if _nls_init() has not been
+   called. */
+
+/* Note: This function is used by emx.dll. */
+
+char *_getname (const char *path)
+{
+  const char *p;
+
+  p = path;
+  while (*path != 0)
+    if (_nls_is_dbcs_lead ((unsigned char)*path))
+      {
+        if (path[1] == 0)       /* Invalid DBCS character */
+          break;
+        path += 2;
+      }
+    else
+      switch (*path++)
+        {
+        case ':':
+        case '/':
+        case '\\':
+          p = path;             /* Note that PATH has been incremented */
+          break;
+        }
+  return (char *)p;
+}
Index: trunk/src/emx/src/lib/misc/getopt.c
===================================================================
--- trunk/src/emx/src/lib/misc/getopt.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getopt.c	(revision 18)
@@ -0,0 +1,161 @@
+/* getopt.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+char *_optarg          = NULL;
+int _optind            = 1;              /* Default: first call             */
+int _opterr            = 1;              /* Default: error messages enabled */
+char *_optswchar       = "-";            /* Default: '-' starts options     */
+enum _optmode _optmode = GETOPT_UNIX;
+int _optopt;
+
+static char * next_opt;             /* Next character in cluster of options */
+
+static char done;
+static char sw_char;
+static char init;
+
+static char ** options;            /* List of entries which are options     */
+static char ** non_options;        /* List of entries which are not options */
+static int options_count;
+static int non_options_count;
+
+#define BEGIN do {
+#define END   } while (0)
+
+#define PUT(dst) BEGIN \
+                  if (_optmode == GETOPT_ANY) \
+                    dst[dst##_count++] = argv[_optind]; \
+                 END
+
+/* Note: `argv' is not const as GETOPT_ANY reorders argv[]. */
+
+int _getopt (int argc, char * argv[], const char *opt_str)
+{
+  char c, *q;
+  int i, j;
+
+  if (!init || _optind == 0)
+    {
+      if (_optind == 0) _optind = 1;
+      done = 0; init = 1;
+      next_opt = "";
+      if (_optmode == GETOPT_ANY)
+        {
+          options = (char **)malloc (argc * sizeof (char *));
+          non_options = (char **)malloc (argc * sizeof (char *));
+          if (options == NULL || non_options == NULL)
+            {
+              fprintf (stderr, "out of memory in getopt()\n");
+              exit (255);
+            }
+          options_count = 0; non_options_count = 0;
+        }
+    }
+  if (done)
+    return -1;
+restart:
+  _optarg = NULL;
+  if (*next_opt == 0)
+    {
+      if (_optind >= argc)
+        {
+          if (_optmode == GETOPT_ANY)
+            {
+              j = 1;
+              for (i = 0; i < options_count; ++i)
+                argv[j++] = options[i];
+              for (i = 0; i < non_options_count; ++i)
+                argv[j++] = non_options[i];
+              _optind = options_count+1;
+              free (options); free (non_options);
+            }
+          done = 1;
+          return -1;
+        }
+      else if (!strchr (_optswchar, argv[_optind][0]) || argv[_optind][1] == 0)
+        {
+          if (_optmode == GETOPT_UNIX)
+            {
+              done = 1;
+              return -1;
+            }
+          PUT (non_options);
+          _optarg = argv[_optind++];
+          if (_optmode == GETOPT_ANY)
+            goto restart;
+          /* _optmode==GETOPT_KEEP */
+          return 0;
+        }
+      else if (argv[_optind][0] == argv[_optind][1] && argv[_optind][2] == 0)
+        {
+          if (_optmode == GETOPT_ANY)
+            {
+              j = 1;
+              for (i = 0; i < options_count; ++i)
+                argv[j++] = options[i];
+              argv[j++] = argv[_optind];
+              for (i = 0; i < non_options_count; ++i)
+                argv[j++] = non_options[i];
+              for (i = _optind+1; i < argc; ++i)
+                argv[j++] = argv[i];
+              _optind = options_count+2;
+              free (options); free (non_options);
+            }
+          ++_optind;
+          done = 1;
+          return -1;
+        }
+      else
+        {
+          PUT (options);
+          sw_char = argv[_optind][0];
+          next_opt = argv[_optind]+1;
+        }
+    }
+  c = *next_opt++;
+  if (*next_opt == 0)  /* Move to next argument if end of argument reached */
+    ++_optind;
+  if (c == ':' || (q = strchr (opt_str, c)) == NULL)
+    {
+      if (_opterr && opt_str[0] != ':')
+        {
+          if (c < ' ' || c >= 127)
+            fprintf (stderr, "%s: invalid option; character code=0x%.2x\n",
+                     argv[0], c);
+          else
+            fprintf (stderr, "%s: invalid option `%c%c'\n",
+                     argv[0], sw_char, c);
+        }
+      _optopt = c;
+      return '?';
+    }
+  if (q[1] == ':')
+    {
+      if (*next_opt != 0)         /* Argument given */
+        {
+          _optarg = next_opt;
+          next_opt = "";
+          ++_optind;
+        }
+      else if (q[2] == ':')
+        _optarg = NULL;           /* Optional argument missing */
+      else if (_optind >= argc)
+        {                         /* Required argument missing */
+          if (_opterr && opt_str[0] != ':')
+            fprintf (stderr, "%s: no argument for `%c%c' option\n",
+                     argv[0], sw_char, c);
+          _optopt = c;
+          return (opt_str[0] == ':' ? ':' : '?');
+        }
+      else
+        {
+          PUT (options);
+          _optarg = argv[_optind++];
+        }
+    }
+  return c;
+}
Index: trunk/src/emx/src/lib/misc/getpages.c
===================================================================
--- trunk/src/emx/src/lib/misc/getpages.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getpages.c	(revision 18)
@@ -0,0 +1,8 @@
+/* getpages.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+int _getpagesize (void)
+{
+  return 4096;
+}
Index: trunk/src/emx/src/lib/misc/getpass.c
===================================================================
--- trunk/src/emx/src/lib/misc/getpass.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getpass.c	(revision 18)
@@ -0,0 +1,8 @@
+/* getpass.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+
+char *_getpass (const char *prompt)
+{
+  return _getpass2 (prompt, 1);
+}
Index: trunk/src/emx/src/lib/misc/getpass1.c
===================================================================
--- trunk/src/emx/src/lib/misc/getpass1.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getpass1.c	(revision 18)
@@ -0,0 +1,12 @@
+/* getpass1.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+char *_getpass1 (const char *prompt)
+{
+  int ht, kbd;
+
+  kbd = (_ioctl (0, FGETHTYPE, &ht) == 0 && ht == HT_DEV_CON);
+  return _getpass2 (prompt, kbd);
+}
Index: trunk/src/emx/src/lib/misc/getpass2.c
===================================================================
--- trunk/src/emx/src/lib/misc/getpass2.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getpass2.c	(revision 18)
@@ -0,0 +1,36 @@
+/* getpass2.c (emx+gcc) -- Copyright (c) 1993-1994 by Kai Uwe Rommel */
+/*                         Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <conio.h>
+#include <unistd.h>
+#include <pwd.h>
+
+char *_getpass2 (const char *prompt, int kbd)
+{
+  static char pbuf[_PASSWORD_LEN+1];
+  int c, i;
+
+  fputs (prompt, stderr);
+  fflush (stderr);
+  i = 0;
+  for (;;)
+    {
+      c = (kbd ? getch () : fgetc (stdin));
+      if (c == '\r' || c == '\n')
+        break;
+      if (c == '\b' || c == 127)
+        {
+          if (i > 0) --i;
+        }
+      else if (c == 0x15 || c == 0x1b)
+        i = 0;
+      else if (i < sizeof (pbuf)-1)
+        pbuf[i++] = (char)c;
+    }
+  pbuf[i] = 0;
+  fputs ("\r\n", stderr);
+  fflush (stderr);
+  return pbuf;
+}
Index: trunk/src/emx/src/lib/misc/getpgrp.c
===================================================================
--- trunk/src/emx/src/lib/misc/getpgrp.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getpgrp.c	(revision 18)
@@ -0,0 +1,10 @@
+/* getpgrp.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <process.h>
+#include <sys/types.h>
+
+pid_t _getpgrp (void)
+{
+  return _getpid ();
+}
Index: trunk/src/emx/src/lib/misc/getpwnam.c
===================================================================
--- trunk/src/emx/src/lib/misc/getpwnam.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getpwnam.c	(revision 18)
@@ -0,0 +1,19 @@
+/* getpwnam.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <pwd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <emx/pwd.h>
+
+/* Dummy function */
+
+struct passwd *_getpwnam (const char *name)
+{
+  if (name == NULL)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  return _getpw (0, name);
+}
Index: trunk/src/emx/src/lib/misc/getpwuid.c
===================================================================
--- trunk/src/emx/src/lib/misc/getpwuid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getpwuid.c	(revision 18)
@@ -0,0 +1,13 @@
+/* getpwuid.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <emx/pwd.h>
+
+/* Dummy function */
+
+struct passwd *_getpwuid (uid_t uid)
+{
+  return _getpw (uid, NULL);
+}
Index: trunk/src/emx/src/lib/misc/getuid.c
===================================================================
--- trunk/src/emx/src/lib/misc/getuid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getuid.c	(revision 18)
@@ -0,0 +1,9 @@
+/* getuid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <sys/types.h>
+
+uid_t _getuid (void)
+{
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/getvol.c
===================================================================
--- trunk/src/emx/src/lib/misc/getvol.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getvol.c	(revision 18)
@@ -0,0 +1,51 @@
+/* getvol.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <emx/thread.h>
+#include <emx/syscalls.h>
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#include <os2emx.h>
+
+char *_getvol (char drive)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread();
+#define result (tp->_th_vollabel)
+#else
+  static char result[12];
+#endif
+
+  if (drive == 0)
+    drive = _getdrive ();
+  if (drive >= 'a' && drive <= 'z')
+    drive += 'A' - 'a';
+  if (!(drive >= 'A' && drive <= 'Z'))
+    return NULL;
+
+  if (_osmode == OS2_MODE)
+    {
+      ULONG rc;
+      FSINFO fsinfo;
+
+      memset (&fsinfo, 0, sizeof (fsinfo));
+      rc = DosQueryFSInfo (drive - 'A' + 1, FSIL_VOLSER, &fsinfo,
+                           sizeof (fsinfo));
+      if (rc != 0)
+        return NULL;
+      strcpy (result, fsinfo.vol.szVolLabel);
+    }
+  else
+    {
+      static struct _find find;
+      char mask[7];
+
+      mask[0] = drive;
+      strcpy (mask + 1, ":\\*.*");
+      if (__findfirst (mask, _A_VOLID, &find) != 0)
+        return NULL;
+      strcpy (result, find.name);
+    }
+  return result;
+}
Index: trunk/src/emx/src/lib/misc/getwd.c
===================================================================
--- trunk/src/emx/src/lib/misc/getwd.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/getwd.c	(revision 18)
@@ -0,0 +1,24 @@
+/* getwd.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <emx/syscalls.h>
+
+char *_getwd (char *buffer)
+{
+  if (buffer == NULL)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  if (__getcwd (buffer+1, 0) < 0)
+    {
+      _strncpy (buffer, strerror (errno), MAXPATHLEN);
+      return NULL;
+    }
+  _fnslashify (buffer+1);
+  buffer[0] = '/';
+  return buffer;
+}
Index: trunk/src/emx/src/lib/misc/glob.c
===================================================================
--- trunk/src/emx/src/lib/misc/glob.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/glob.c	(revision 18)
@@ -0,0 +1,238 @@
+/* glob.c (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fnmatch.h>
+#include <glob.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+
+struct globi
+{
+  glob_t *pglob;
+  size_t index;
+  int (*errfun)(const char *, int);
+};
+
+
+void _globfree (glob_t *pglob)
+{
+  size_t i, j;
+
+  if (pglob->gl_pathv != NULL)
+    {
+      j = (pglob->gl_flags & GLOB_DOOFFS) ? pglob->gl_offs : 0;
+      for (i = 0; i < pglob->gl_pathc; ++i)
+        free (pglob->gl_pathv[i + j]);
+      free (pglob->gl_pathv);
+      pglob->gl_pathv = NULL;
+    }
+  pglob->gl_pathc = 0;
+  pglob->gl_offs = 0;
+  pglob->gl_flags = 0;
+}
+
+
+static int glob_add (struct globi *pg, const char *s0)
+{
+  char *s;
+
+  if (s0 == NULL)
+    s = NULL;
+  else
+    {
+      s = _strdup (s0);
+      if (s == NULL)
+        goto nospace;
+    }
+  if (pg->index >= pg->pglob->gl_alloc)
+    {
+      char **v;
+
+      pg->pglob->gl_alloc += 16;
+      v = realloc (pg->pglob->gl_pathv, pg->pglob->gl_alloc * sizeof (char *));
+      if (v == NULL)
+        goto nospace;
+      pg->pglob->gl_pathv = v;
+    }
+  pg->pglob->gl_pathv[pg->index++] = s;
+  return 1;
+
+nospace:
+  pg->pglob->gl_pathc = pg->index;
+  _globfree (pg->pglob);
+  return 0;
+}
+
+
+static int glob_recurse (struct globi *pg, const char *base,
+                         const char *pattern)
+{
+  const char *s, *lpat;
+  size_t base_len, len;
+  char path[MAXPATHLEN+1];
+  DIR *dir;
+  struct dirent *ent;
+  int r, fnm_flags;
+
+  /* TODO: Don't forget to check for DBCS lead bytes when adding
+     support for backslashes! */
+
+  s = strchr (pattern, '/');
+  if (s == NULL)
+    lpat = pattern;
+  else
+    {
+      char *tmp = alloca (s - pattern + 1);
+      memcpy (tmp, pattern, s - pattern);
+      tmp[s - pattern] = 0;
+      lpat = tmp;
+    }
+  base_len = strlen (base);
+  if (base_len != 0)
+    {
+      if (base_len >= sizeof (path))
+        {
+          if (pg->errfun != NULL && pg->errfun (base, ENAMETOOLONG) != 0)
+            return GLOB_ABEND;
+          if (pg->pglob->gl_flags & GLOB_ERR)
+            return GLOB_ABEND;
+        }
+      memcpy (path, base, base_len);
+    }
+
+  fnm_flags = 0;
+  if (pg->pglob->gl_flags & GLOB_NOESCAPE)
+    fnm_flags |= FNM_NOESCAPE;
+  if (!(pg->pglob->gl_flags & GLOB_PERIOD))
+    fnm_flags |= FNM_PERIOD;
+
+  /* TODO: Optimize for lpat not containing global characters. */
+
+  dir = _opendir (*base != 0 ? base : ".");
+  if (dir == NULL)
+    {
+      if (pg->errfun != NULL && pg->errfun (base, errno) != 0)
+        return GLOB_ABEND;
+      if (pg->pglob->gl_flags & GLOB_ERR)
+        return GLOB_ABEND;
+      return 0;
+    }
+  while ((ent = _readdir (dir)) != NULL)
+    {
+      if (_fnmatch (lpat, ent->d_name, fnm_flags) == 0)
+        {
+          len = base_len + ent->d_namlen;
+          if (len >= sizeof (path) - 1)
+            {
+              /* This cannot happen.  Handle it anyway. */
+              if (pg->errfun != NULL && pg->errfun (base, ENAMETOOLONG) != 0)
+                return GLOB_ABEND;
+              if (pg->pglob->gl_flags & GLOB_ERR)
+                return GLOB_ABEND;
+            }
+          if (s == NULL)
+            {
+              memcpy (path + base_len, ent->d_name, ent->d_namlen);
+              if ((pg->pglob->gl_flags & GLOB_MARK) && (ent->d_attr & A_DIR))
+                path[len++] = '/';
+              path[len] = 0;
+              if (!glob_add (pg, path))
+                {
+                  _closedir (dir);
+                  return GLOB_NOSPACE;
+                }
+              pg->pglob->gl_pathc += 1;
+            }
+          else if (ent->d_attr & A_DIR)
+            {
+              memcpy (path + base_len, ent->d_name, ent->d_namlen);
+              path[len++] = '/';
+              path[len] = 0;
+              r = glob_recurse (pg, path, s + 1);
+              if (r != 0)
+                {
+                  _closedir (dir);
+                  return r;
+                }
+            }
+        }
+    }
+  _closedir (dir);
+  return 0;
+}
+
+
+static int glob_compare (const void *x1, const void *x2)
+{
+  return strcoll (*(const char * const *)x1, *(const char * const *)x2);
+}
+
+
+int _glob (const char *pattern, int flags,
+           int (*errfun)(const char *e_path, int e_errno), glob_t *pglob)
+{
+  struct globi g;
+  size_t i, old, offs, prefix_len;
+  int r;
+  char prefix[4];
+
+  g.pglob = pglob;
+  g.errfun = errfun;
+  offs = (flags & GLOB_DOOFFS) ? pglob->gl_offs : 0;
+  if (flags & GLOB_APPEND)
+    g.index = offs + pglob->gl_pathc;
+  else
+    {
+      g.index = 0;
+      pglob->gl_pathc = 0;
+      pglob->gl_pathv = NULL;
+      pglob->gl_flags = flags;
+      pglob->gl_alloc = 0;
+      for (i = 0; i < offs; ++i)
+        if (!glob_add (&g, NULL))
+          return GLOB_NOSPACE;
+    }
+  old = g.index;
+
+  prefix_len = 0;
+  if (strncmp (pattern + prefix_len, "//", 2) == 0)
+    prefix_len += 2;            /* UNC */
+  else
+    {
+      if (_fngetdrive (pattern + prefix_len) != 0)
+        prefix_len += 2;
+      if (pattern[prefix_len] == '/')
+        prefix_len += 1;
+    }
+  memcpy (prefix, pattern, prefix_len);
+  prefix[prefix_len] = 0;
+  r = glob_recurse (&g, prefix, pattern + prefix_len);
+  if (r != 0)
+    return r;
+
+  if (g.index == old)
+    {
+      if (flags & GLOB_NOCHECK)
+        {
+          if (!glob_add (&g, pattern))
+            return GLOB_NOSPACE;
+          pglob->gl_pathc += 1;
+        }
+      else
+        return GLOB_NOMATCH;
+    }
+
+  if (!(flags & GLOB_NOSORT))
+    qsort (pglob->gl_pathv + old, g.index - old, sizeof (pglob->gl_pathv[0]),
+           glob_compare);
+
+  if (!glob_add (&g, NULL))
+    return GLOB_NOSPACE;
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/labs.c
===================================================================
--- trunk/src/emx/src/lib/misc/labs.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/labs.c	(revision 18)
@@ -0,0 +1,6 @@
+/* labs.c (emx+gcc) -- Copyright (c) 1992-1993 by Eberhard Mattes */
+
+long labs (long n)
+{
+  return (n < 0 ? -n : n);
+}
Index: trunk/src/emx/src/lib/misc/makefile
===================================================================
--- trunk/src/emx/src/lib/misc/makefile	(revision 18)
+++ trunk/src/emx/src/lib/misc/makefile	(revision 18)
@@ -0,0 +1,155 @@
+#
+# /emx/src/lib/misc/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+abort.o: abort.c $(I)stdlib.h $(SIGNAL) $(I)emx/startup.h
+abs.o: abs.c $(I)stdlib.h
+abspath.o: abspath.c $(I)stdlib.h $(ERRNO) $(I)string.h $(I)alloca.h \
+		$(I)sys/param.h $(I)emx/syscalls.h $(I)sys/nls.h
+alarm.o: alarm.c $(I)stdlib.h $(I)emx/syscalls.h
+assert.o: assert.c $(I)stdlib.h $(I)stdio.h $(I)assert.h
+atexit.o: atexit.c $(I)stdlib.h $(I)emx/startup.h
+brk.o: brk.c $(I)emx/syscalls.h $(I)stdlib.h
+chdir.o: chdir.c $(I)stdlib.h $(I)string.h $(I)emx/syscalls.h $(I)emx/io.h
+chdir2.o: chdir2.c $(I)stdlib.h $(I)string.h $(ERRNO) $(I)emx/syscalls.h \
+		$(I)emx/io.h
+chdrive.o: chdrive.c $(I)stdlib.h $(I)emx/syscalls.h
+core.o: core.c $(I)stdlib.h $(I)emx/syscalls.h
+cuserid.o: cuserid.c $(I)stdio.h $(I)stdlib.h $(I)string.h
+defext.o: defext.c $(I)stdlib.h $(I)string.h $(I)sys/nls.h
+dirent.o: dirent.c $(I)emx/syscalls.h $(I)stdlib.h $(I)sys/types.h \
+		$(I)sys/stat.h $(I)dirent.h $(I)sys/dirent.h $(I)io.h \
+		$(I)string.h $(ERRNO) $(I)emx/io.h
+div.o: div.s $(ASM386H)
+dtread.o: dtread.c $(I)emx/syscalls.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+		$(I)time.h $(I)sys/param.h $(I)sys/types.h $(I)sys/dirent.h \
+		$(I)sys/dirtree.h $(I)emx/time.h $(I)emx/io.h
+dtsort.o: dtsort.c $(I)stdlib.h $(I)string.h $(I)sys/types.h $(I)sys/dirent.h \
+		$(I)sys/nls.h $(I)sys/dirtree.h
+dtsplit.o: dtsplit.c $(I)stdlib.h $(I)string.h $(ERRNO) $(I)sys/param.h \
+		$(I)sys/dirtree.h $(I)emx/io.h
+envargs.o: envargs.c $(I)stdlib.h $(I)string.h $(I)emx/startup.h
+execname.o: execname.c $(I)stdlib.h $(I)emx/syscalls.h
+filesys.o: filesys.c $(I)emx/syscalls.h $(I)stdlib.h
+fnexplod.o: fnexplod.c $(I)emx/syscalls.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+		$(I)sys/param.h $(S)types.h $(S)stat.h
+fngetdrv.o: fngetdrv.c $(I)stdlib.h
+fnmatch.o: fnmatch.c $(I)string.h $(I)ctype.h $(I)sys/nls.h $(I)fnmatch.h
+fnisabs.o: fnisabs.c $(I)stdlib.h $(I)ctype.h
+fnisrel.o: fnisrel.c $(I)stdlib.h $(I)ctype.h
+fnslashi.o: fnslashi.c $(I)stdlib.h $(I)sys/nls.h
+fpathcon.o: fpathcon.c $(I)unistd.h $(I)limits.h $(ERRNO)
+fullpath.o: fullpath.c $(I)stdlib.h $(I)stdio.h $(I)string.h $(I)sys/param.h \
+		$(I)sys/nls.h $(ERRNO) $(I)emx/syscalls.h $(I)emx/io.h
+getcwd.o: getcwd.c $(I)stdlib.h $(I)string.h $(ERRNO) $(I)sys/param.h \
+		$(I)emx/syscalls.h
+getcwd1.o: getcwd1.c $(I)stdlib.h $(I)emx/syscalls.h
+getcwd2.o: getcwd2.c $(I)stdlib.h $(I)string.h $(ERRNO) $(I)sys/param.h \
+		$(I)emx/syscalls.h
+getdrive.o: getdrive.c $(I)stdlib.h $(I)emx/syscalls.h
+getegid.o: getegid.c $(I)sys/types.h $(I)unistd.h
+getext.o: getext.c $(I)stdlib.h $(I)string.h $(I)sys/nls.h
+getext2.o: getext2.c $(I)stdlib.h $(I)string.h
+geteuid.o: geteuid.c $(I)sys/types.h $(I)unistd.h
+getgid.o: getgid.c $(I)sys/types.h $(I)unistd.h
+getgrgid.o: getgrgid.c $(I)sys/types.h $(I)grp.h $(I)string.h
+getgrnam.o: getgrnam.c $(I)sys/types.h $(I)grp.h $(I)string.h
+getgroup.o: getgroup.c $(I)sys/types.h $(I)unistd.h
+getlogin.o: getlogin.c $(I)unistd.h $(I)stdio.h $(I)stdlib.h $(I)string.h
+getname.o: getname.c $(I)stdlib.h $(I)string.h $(I)sys/nls.h
+getopt.o: getopt.c $(I)getopt.h $(I)stdio.h $(I)stdlib.h $(I)string.h
+getpages.o: getpages.c $(I)stdlib.h
+getpass.o: getpass.c $(I)unistd.h
+getpass1.o: getpass1.c $(I)stdio.h $(I)stdlib.h $(I)conio.h $(I)pwd.h \
+		$(I)unistd.h
+getpass2.o: getpass2.c $(I)unistd.h $(I)sys/ioctl.h
+getpgrp.o: getpgrp.c $(I)sys/types.h $(I)unistd.h
+getpwuid.o: getpwuid.c $(I)sys/types.h $(I)pwd.h $(I)emx/pwd.h
+getpwnam.o: getpwnam.c $(I)stdlib.h $(I)sys/types.h $(I)pwd.h $(ERRNO) \
+		$(I)emx/pwd.h
+getuid.o: getuid.c $(I)stdlib.h $(I)sys/types.h $(I)unistd.h
+getvol.o: getvol.c $(I)stdlib.h $(I)string.h $(I)os2emx.h $(I)emx/syscalls.h \
+		$(I)emx/thread.h
+getwd.o: getwd.c $(I)stdlib.h $(I)string.h $(ERRNO) $(I)sys/param.h \
+		$(I)emx/syscalls.h
+int86.o: int86.s $(ASM386H)
+labs.o: labs.c $(I)stdlib.h
+makepath.o: makepath.c $(I)stdlib.h $(I)sys/nls.h
+memacc.o: memacc.c $(I)emx/syscalls.h $(I)sys/hw.h
+mkdir.o: mkdir.c $(I)emx/syscalls.h $(I)stdlib.h $(ERRNO)
+os2bad.o: os2bad.c $(I)stdlib.h $(I)emx/syscalls.h
+path.o: path.c $(I)string.h $(I)stdlib.h $(ERRNO) $(I)io.h
+pathconf.o: pathconf.c $(I)unistd.h $(I)limits.h $(ERRNO)
+perror.o: perror.c $(I)stdlib.h
+portacc.o: portacc.c $(I)emx/syscalls.h $(I)sys/hw.h
+pwd.o: pwd.c $(I)stdio.h $(I)stdlib.h $(I)string.h $(I)pwd.h $(I)unistd.h \
+		$(I)emx/pwd.h
+rand.o: rand.c $(I)stdlib.h $(I)emx/thread.h
+readkbd.o: readkbd.c $(I)stdlib.h $(I)emx/syscalls.h
+remext.o: remext.c $(I)stdlib.h $(I)string.h $(I)sys/nls.h
+response.o: response.c $(I)stdlib.h $(I)stdio.h $(I)string.h $(I)emx/startup.h
+rmdir.o: rmdir.c $(I)emx/syscalls.h $(I)stdlib.h $(ERRNO)
+sbrk.o: sbrk.c $(I)emx/syscalls.h $(I)stdlib.h
+scrsize.o: scrsize.c $(I)emx/syscalls.h
+searchen.o: searchen.c $(I)stdlib.h $(I)string.h $(I)io.h $(I)emx/io.h
+setgid.o: setgid.c $(I)unistd.h $(I)sys/types.h $(ERRNO)
+setjmp.o: setjmp.s $(ASM386H)
+setpgid.o: setpgid.c $(I)sys/types.h $(I)unistd.h $(ERRNO)
+setsid.o: setsid.c $(I)sys/types.h $(I)unistd.h $(ERRNO)
+setsyser.o: setsyser.c $(I)emx/syscalls.h
+setuid.o: setuid.c $(I)unistd.h $(I)sys/types.h $(ERRNO)
+sigsetjm.o: sigsetjm.s $(ASM386H)
+sleep.o: sleep.c $(I)stdlib.h $(I)emx/syscalls.h
+sleep2.o: sleep2.c $(I)stdlib.h $(I)emx/syscalls.h
+splitarg.o: splitarg.c $(I)stdlib.h $(ERRNO)
+splitpat.o: splitpat.c $(I)stdlib.h $(I)string.h $(I)sys/nls.h
+swchar.o: swchar.c $(I)stdlib.h $(I)emx/syscalls.h
+sysconf.o: sysconf.c $(I)unistd.h $(I)limits.h $(I)time.h $(ERRNO)
+syserr.o: syserr.c
+syserrno.o: syserrno.c $(I)emx/syscalls.h
+uflags.o: uflags.c $(I)emx/syscalls.h $(S)uflags.h
+uldiv.o: uldiv.s $(ASM386H)
+ulimit.o: ulimit.c $(I)stdarg.h $(I)stdlib.h $(I)ulimit.h $(S)ulimit.h \
+		$(ERRNO) $(I)emx/syscalls.h
+uname.o: uname.c $(I)stdlib.h $(I)string.h $(I)sys/utsname.h
+wildcard.o: wildcard.c $(I)stdlib.h $(I)stdio.h $(I)string.h \
+		$(I)emx/syscalls.h $(I)emx/startup.h
+
+# The following modules contain functions which take a pointer to
+# a function as argument
+
+bsearch.o: bsearch.c $(I)stdlib.h
+	$(GCC) -fexceptions -c ../bsearch.c
+
+ftw.o: ftw.c $(I)stdlib.h $(I)sys/types.h $(I)sys/stat.h $(I)dirent.h \
+		$(I)sys/dirent.h $(I)io.h $(I)string.h $(I)sys/param.h \
+		$(ERRNO) $(I)ftw.h $(I)emx/io.h
+	$(GCC) -fexceptions -c ../ftw.c
+
+glob.o: glob.c $(I)stdlib.h $(I)string.h $(ERRNO) $(I)unistd.h $(I)fnmatch.h \
+		$(I)glob.h $(I)sys/types.h $(I)dirent.h $(I)sys/dirent.h \
+		$(I)sys/stat.h $(I)sys/param.h
+	$(GCC) -fexceptions -c ../glob.c
+
+qsort.o: qsort.c $(I)stdlib.h $(I)memory.h
+	$(GCC) -fexceptions -c ../qsort.c
+
+$(DSTLIB): abort.o abs.o abspath.o alarm.o assert.o atexit.o brk.o \
+    bsearch.o chdir.o chdir2.o chdrive.o core.o cuserid.o defext.o \
+    dirent.o div.o dtread.o dtsort.o dtsplit.o envargs.o execname.o \
+    filesys.o fnexplod.o fngetdrv.o fnisabs.o fnisrel.o fnmatch.o \
+    fnslashi.o fpathcon.o ftw.o fullpath.o getcwd.o getcwd1.o getcwd2.o \
+    getdrive.o getegid.o geteuid.o getext.o getext2.o getgid.o \
+    getgrgid.o getgrnam.o getgroup.o getlogin.o getname.o getopt.o \
+    getpages.o getpass.o getpass1.o getpass2.o getpgrp.o getpwnam.o \
+    getpwuid.o getuid.o getvol.o getwd.o glob.o int86.o labs.o \
+    makepath.o memacces.o mkdir.o os2bad.o path.o pathconf.o perror.o \
+    portacce.o pwd.o qsort.o rand.o readkbd.o remext.o response.o \
+    rmdir.o sbrk.o scrsize.o searchen.o setgid.o setjmp.o setpgid.o \
+    setsid.o setuid.o sigsetjm.o sleep.o sleep2.o splitarg.o \
+    setsyser.o splitpat.o swchar.o sysconf.o syserr.o syserrno.o \
+    uflags.o uldiv.o ulimit.o uname.o wildcard.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/misc/makepath.c
===================================================================
--- trunk/src/emx/src/lib/misc/makepath.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/makepath.c	(revision 18)
@@ -0,0 +1,58 @@
+/* makepath.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/nls.h>
+
+void _makepath (char *dst, const char *drive, const char *dir,
+                const char *fname, const char *ext)
+{
+  int n;
+  char slash, last;
+
+  n = 0; slash = '/';
+  if (drive != NULL && *drive != 0)
+    {
+      dst[n++] = *drive;
+      dst[n++] = ':';
+    }
+  if (dir != NULL && *dir != 0)
+    {
+      last = 0;
+      while (n < _MAX_PATH - 1 && *dir != 0)
+        {
+          if (_nls_is_dbcs_lead ((unsigned char)*dir))
+            {
+              if (dir[1] == 0)
+                ++dir;          /* Invalid DBCS character */
+              else if (n + 1 < _MAX_PATH - 1)
+                {
+                  dst[n++] = *dir++;
+                  dst[n++] = *dir++;
+                }
+              last = 0;
+            }
+          else
+            {
+              last = *dir;
+              if (*dir == '\\')
+                slash = '\\';
+              dst[n++] = *dir++;
+            }
+        }
+      if (last != '\\' && last != '/' && n < _MAX_PATH - 1)
+        dst[n++] = slash;
+    }
+  if (fname != NULL)
+    {
+      while (n < _MAX_PATH - 1 && *fname != 0)
+        dst[n++] = *fname++;
+    }
+  if (ext != NULL && *ext != 0)
+    {
+      if (*ext != '.' && n < _MAX_PATH - 1)
+        dst[n++] = '.';
+      while (n < _MAX_PATH - 1 && *ext != 0)
+        dst[n++] = *ext++;
+    }
+  dst[n] = 0;
+}
Index: trunk/src/emx/src/lib/misc/memacces.c
===================================================================
--- trunk/src/emx/src/lib/misc/memacces.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/memacces.c	(revision 18)
@@ -0,0 +1,9 @@
+/* memacces.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <sys/hw.h>
+#include <emx/syscalls.h>
+
+void *_memaccess (unsigned first, unsigned last, int flag)
+{
+  return __memaccess (first, last, flag);
+}
Index: trunk/src/emx/src/lib/misc/mkdir.c
===================================================================
--- trunk/src/emx/src/lib/misc/mkdir.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/mkdir.c	(revision 18)
@@ -0,0 +1,18 @@
+/* mkdir.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+int _mkdir (const char *name, long mode)
+{
+  mode = 0;                     /* Keep the compiler happy */
+  if (__mkdir (name) == 0)
+    return 0;
+  else
+    {
+      if (errno == EACCES)
+        errno = EEXIST;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/misc/os2bad.c
===================================================================
--- trunk/src/emx/src/lib/misc/os2bad.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/os2bad.c	(revision 18)
@@ -0,0 +1,12 @@
+/* os2bad.c (emx+gcc) */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+static char msg[] = "\r\nOS/2 API call not fixed up\r\n";
+
+void _os2_bad (void)
+{
+  __write (2, msg, sizeof (msg) - 1);
+  _exit (2);
+}
Index: trunk/src/emx/src/lib/misc/path.c
===================================================================
--- trunk/src/emx/src/lib/misc/path.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/path.c	(revision 18)
@@ -0,0 +1,29 @@
+/* path.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <errno.h>
+
+int _path (char *dst, const char *name)
+{
+  if (strpbrk (name, "/\\:") != NULL)
+    {
+      if (_access (name, 4) == 0)
+        strcpy (dst, name);
+      else
+        dst[0] = 0;
+    }
+  else
+    {
+      _searchenv (name, "EMXPATH", dst);
+      if (dst[0] == 0)
+        _searchenv (name, "PATH", dst);
+    }
+  if (dst[0] == 0)
+    {
+      errno = ENOENT;
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/pathconf.c
===================================================================
--- trunk/src/emx/src/lib/misc/pathconf.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/pathconf.c	(revision 18)
@@ -0,0 +1,44 @@
+/* pathconf.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+/* Return the POSIX.1  minimum values, for now. */
+
+long _pathconf (const char *path, int name)
+{
+  switch (name)
+    {
+    case _PC_LINK_MAX:
+      return _POSIX_LINK_MAX;
+
+    case _PC_MAX_CANON:
+      return _POSIX_MAX_CANON;
+
+    case _PC_MAX_INPUT:
+      return _POSIX_MAX_INPUT;
+
+    case _PC_NAME_MAX:
+      return _POSIX_NAME_MAX;
+
+    case _PC_PATH_MAX:
+      return _POSIX_PATH_MAX;
+
+    case _PC_PIPE_BUF:
+      return _POSIX_PIPE_BUF;
+
+    case _PC_CHOWN_RESTRICTED:
+      return 1;
+
+    case _PC_NO_TRUNC:
+      return 1;                 /* TODO */
+
+    case _PC_VDISABLE:
+      return 0;
+
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/misc/perror.c
===================================================================
--- trunk/src/emx/src/lib/misc/perror.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/perror.c	(revision 18)
@@ -0,0 +1,20 @@
+/* perror.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void perror (const char *string)
+{
+  int e = errno;
+
+  if (string != NULL && *string != 0)
+    {
+      fputs (string, stderr);
+      fputs (": ", stderr);
+    }
+  if (e >= 0 && e < _sys_nerr)
+    fputs (_sys_errlist[e], stderr);
+  else
+    fprintf (stderr, "Unknown error %d", e);
+  fputc ('\n', stderr);
+}
Index: trunk/src/emx/src/lib/misc/portacce.c
===================================================================
--- trunk/src/emx/src/lib/misc/portacce.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/portacce.c	(revision 18)
@@ -0,0 +1,9 @@
+/* portacce.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <sys/hw.h>
+#include <emx/syscalls.h>
+
+int _portaccess (unsigned first, unsigned last)
+{
+  return __portaccess (first, last);
+}
Index: trunk/src/emx/src/lib/misc/pwd.c
===================================================================
--- trunk/src/emx/src/lib/misc/pwd.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/pwd.c	(revision 18)
@@ -0,0 +1,73 @@
+/* pwd.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <emx/pwd.h>
+
+
+static void path_assign (char *dst, const char *src, size_t dst_size)
+{
+  _strncpy (dst, src, dst_size);
+  _fnslashify (dst);
+}
+
+
+struct passwd *_getpw (uid_t uid, const char *name)
+{
+  static struct passwd tmp_pwd;
+  static char tmp_name[L_cuserid];
+  static char tmp_dir[70];
+  static char tmp_shell[70];
+  const char *dir;
+  const char *shell;
+
+  if (name == NULL)
+    name = getenv ("LOGNAME");
+  if (name == NULL)
+    name = getenv ("USER");
+  if (name == NULL)
+    name = "root";
+
+  dir = getenv ("HOME");
+  if (dir == NULL)
+    dir = "/";
+
+  shell = getenv ("SHELL");
+  if (shell == NULL)
+    shell = getenv ("COMSPEC");
+  if (shell == NULL)
+    shell = "/bin/sh";
+
+  _strncpy (tmp_name, name, sizeof (tmp_name));
+  path_assign (tmp_dir, dir, sizeof (tmp_dir));
+  path_assign (tmp_shell, shell, sizeof (tmp_shell));
+  tmp_pwd.pw_name = tmp_name;
+  tmp_pwd.pw_passwd = "";
+  tmp_pwd.pw_uid = uid;
+  tmp_pwd.pw_gid = 0;
+  tmp_pwd.pw_age = "";
+  tmp_pwd.pw_comment = "";
+  tmp_pwd.pw_gecos = "";
+  tmp_pwd.pw_dir = tmp_dir;
+  tmp_pwd.pw_shell = tmp_shell;
+  return &tmp_pwd;
+}
+
+
+struct passwd *_getpwent (void)
+{
+  return NULL;                  /* End of /etc/passwd reached */
+}
+
+
+void _setpwent (void)
+{
+}
+
+
+void _endpwent (void)
+{
+}
Index: trunk/src/emx/src/lib/misc/qsort.c
===================================================================
--- trunk/src/emx/src/lib/misc/qsort.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/qsort.c	(revision 18)
@@ -0,0 +1,66 @@
+/* qsort.c (emx+gcc) -- Copyright (c) 1990-1994 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <memory.h>
+
+static void qsort1 (char *l, char *r, size_t width,
+                    int (*compare)(const void *x1, const void *x2));
+
+void qsort (void *base, size_t num, size_t width,
+            int (*compare)(const void *x1, const void *x2))
+{
+  if (width > 0 && num > 1 && base != NULL)
+    qsort1 ((char *)base, (char *)base+(num-1)*width, width, compare);
+}
+
+
+static void qsort1 (char *l, char *r, size_t width,
+                    int (*compare)(const void *x1, const void *x2))
+{
+  char *i, *j, *x;
+
+redo:
+  i = l; j = r;
+  x = l + width * (((r-l) / width) >> 1);
+  do
+    {
+      while (i != x && compare ((void *)i, (void *)x) < 0)
+        i += width;
+      while (j != x && compare ((void *)j, (void *)x) > 0)
+        j -= width;
+      if (i < j)
+        {
+          _memswap (i, j, width);
+          if (x == i)
+            x = j;
+          else if (x == j)
+            x = i;
+        }
+      if (i <= j)
+        {
+          i += width;           /* (almost) no danger */
+          if (j > l)
+            j -= width;         /* avoid wrap-around */
+        }
+    } while (i <= j);
+  if (j-l < r-i)
+    {
+      if (l < j)
+        qsort1 (l, j, width, compare);
+      if (i < r)
+        {
+          l = i;
+          goto redo;            /* qsort1 (i, r, width, compare) */
+        }
+    }
+  else
+    {
+      if (i < r)
+        qsort1 (i, r, width, compare);
+      if (l < j)
+        {
+          r = j;                /* qsort1 (l, j, width, compare) */
+          goto redo;
+        }
+    }
+}
Index: trunk/src/emx/src/lib/misc/rand.c
===================================================================
--- trunk/src/emx/src/lib/misc/rand.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/rand.c	(revision 18)
@@ -0,0 +1,31 @@
+/* rand.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/thread.h>
+
+#if defined (__MT__)
+#define _rand (tp->_th_rand)
+#else
+static unsigned int _rand = 1;
+#endif
+
+
+int rand (void)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread();
+#endif
+
+  _rand = _rand * 69069 + 5;
+  return (_rand >> 16) & 0x7fff;
+}
+
+
+void srand (unsigned int seed)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread();
+#endif
+
+  _rand = seed;
+}
Index: trunk/src/emx/src/lib/misc/readkbd.c
===================================================================
--- trunk/src/emx/src/lib/misc/readkbd.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/readkbd.c	(revision 18)
@@ -0,0 +1,9 @@
+/* readkbd.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+int _read_kbd (int echo, int wait, int sig)
+{
+  return __read_kbd (echo, wait, sig);
+}
Index: trunk/src/emx/src/lib/misc/remext.c
===================================================================
--- trunk/src/emx/src/lib/misc/remext.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/remext.c	(revision 18)
@@ -0,0 +1,50 @@
+/* remext.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/nls.h>
+
+/* Note that _nls_is_dbcs_lead() returns false for all characters if
+   _nls_init() has not been called.  In consequence, this function
+   works properly for SBCS strings even if _nls_init() has not been
+   called. */
+
+#define FALSE   0
+#define TRUE    1
+
+void _remext (char *path)
+{
+  int dot, sep;
+  char *dotp;
+
+  dot = FALSE; sep = TRUE; dotp = NULL;
+  while (*path != 0)
+    if (_nls_is_dbcs_lead ((unsigned char)*path))
+      {
+        if (path[1] == 0)       /* Invalid DBCS character */
+          break;
+        path += 2;
+        sep = FALSE;
+      }
+    else
+      switch (*path++)
+        {
+        case '.':
+          /* Note that PATH has been incremented. */
+          dotp = (sep ? NULL : path - 1);
+          dot = TRUE;
+          sep = FALSE;
+          break;
+        case ':':
+        case '/':
+        case '\\':
+          dot = FALSE;
+          sep = TRUE;
+          break;
+        default:
+          sep = FALSE;
+          break;
+        }
+  if (dot && dotp != NULL)
+    *dotp = 0;
+}
Index: trunk/src/emx/src/lib/misc/response.c
===================================================================
--- trunk/src/emx/src/lib/misc/response.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/response.c	(revision 18)
@@ -0,0 +1,71 @@
+/* response.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <emx/startup.h>
+
+#define RPUT(x) do \
+  { \
+    if (new_argc >= new_alloc) \
+      { \
+        new_alloc += 20; \
+        new_argv = (char **)realloc (new_argv, new_alloc * sizeof (char *)); \
+        if (new_argv == NULL) \
+          goto out_of_memory; \
+      } \
+    new_argv[new_argc++] = x; \
+  } while (0)
+
+
+void _response (int *argcp, char ***argvp)
+{
+  int i, old_argc, new_argc, new_alloc;
+  char **old_argv, **new_argv;
+  char line[1+512], *p;
+  FILE *f;
+
+  old_argc = *argcp; old_argv = *argvp;
+  for (i = 1; i < old_argc; ++i)
+    if (old_argv[i] != NULL
+        && !(old_argv[i][-1] & (_ARG_DQUOTE|_ARG_WILDCARD))
+        && old_argv[i][0] == '@')
+      break;
+  if (i >= old_argc)
+    return;                     /* do nothing */
+  new_argv = NULL; new_alloc = 0; new_argc = 0;
+  for (i = 0; i < old_argc; ++i)
+    {
+      if (i == 0 || old_argv[i] == NULL
+          || (old_argv[i][-1] & (_ARG_DQUOTE|_ARG_WILDCARD))
+          || old_argv[i][0] != '@'
+          || (f = fopen (old_argv[i]+1, "rt")) == NULL)
+        RPUT (old_argv[i]);
+      else
+        {
+          line[0] = _ARG_NONZERO|_ARG_RESPONSE;
+          while (fgets (line+1, sizeof (line)-1, f) != NULL)
+            {
+              p = strchr (line+1, '\n');
+              if (p != NULL) *p = 0;
+              p = _strdup (line);
+              if (p == NULL)
+                goto out_of_memory;
+              RPUT (p+1);
+            }
+          if (ferror (f))
+            {
+              fputs ("Cannot read response file\n", stderr);
+              exit (255);
+            }
+          fclose (f);
+        }
+    }
+  RPUT (NULL); --new_argc;
+  *argcp = new_argc; *argvp = new_argv;
+  return;
+
+out_of_memory:
+  fputs ("Out of memory while reading response file\n", stderr);
+  exit (255);
+}
Index: trunk/src/emx/src/lib/misc/rmdir.c
===================================================================
--- trunk/src/emx/src/lib/misc/rmdir.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/rmdir.c	(revision 18)
@@ -0,0 +1,14 @@
+/* rmdir.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+int _rmdir (const char *name)
+{
+  if (__rmdir (name) == 0)
+    return 0;
+  if (errno == EACCES)
+    errno = ENOTEMPTY;
+  return -1;
+}
Index: trunk/src/emx/src/lib/misc/sbrk.c
===================================================================
--- trunk/src/emx/src/lib/misc/sbrk.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/sbrk.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sbrk.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+void *_sbrk (int incr)
+{
+  return __sbrk (incr);
+}
Index: trunk/src/emx/src/lib/misc/scrsize.c
===================================================================
--- trunk/src/emx/src/lib/misc/scrsize.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/scrsize.c	(revision 18)
@@ -0,0 +1,8 @@
+/* scrsize.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+void _scrsize (int *dst)
+{
+  __scrsize (dst);
+}
Index: trunk/src/emx/src/lib/misc/searchen.c
===================================================================
--- trunk/src/emx/src/lib/misc/searchen.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/searchen.c	(revision 18)
@@ -0,0 +1,39 @@
+/* searchen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <emx/io.h>
+
+void _searchenv (const char *file, const char *var, char *path)
+{
+  char *list, *end;
+  int i;
+  
+  strcpy (path, file);
+  if (_access (path, 4) == 0)
+    return;
+  list = getenv (var);
+  if (list != NULL)
+    for (;;)
+      {
+        while (*list == ' ' || *list == '\t') ++list;
+        if (*list == 0) break;
+        end = list;
+        while (*end != 0 && *end != ';') ++end;
+        i = end - list;
+        while (i>0 && (list[i-1] == ' ' || list[i-1] == '\t')) --i;
+        if (i != 0)
+          {
+            memcpy (path, list, i);
+            if (!_trslash (list, i, 0))
+              path[i++] = '\\';
+            strcpy (path+i, file);
+            if (_access (path, 4) == 0)
+              return;
+          }
+        if (*end == 0) break;
+        list = end + 1;
+      }
+  path[0] = 0;
+}
Index: trunk/src/emx/src/lib/misc/setgid.c
===================================================================
--- trunk/src/emx/src/lib/misc/setgid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/setgid.c	(revision 18)
@@ -0,0 +1,15 @@
+/* setgid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+
+int _setgid (gid_t gid)
+{
+  if (gid != 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/setpgid.c
===================================================================
--- trunk/src/emx/src/lib/misc/setpgid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/setpgid.c	(revision 18)
@@ -0,0 +1,11 @@
+/* setpgid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+
+int _setpgid (pid_t pid, pid_t pgid)
+{
+  errno = ENOSYS;
+  return -1;
+}
Index: trunk/src/emx/src/lib/misc/setsid.c
===================================================================
--- trunk/src/emx/src/lib/misc/setsid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/setsid.c	(revision 18)
@@ -0,0 +1,11 @@
+/* setsid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+
+pid_t _setsid (void)
+{
+  errno = EPERM;
+  return -1;
+}
Index: trunk/src/emx/src/lib/misc/setsyser.c
===================================================================
--- trunk/src/emx/src/lib/misc/setsyser.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/setsyser.c	(revision 18)
@@ -0,0 +1,8 @@
+/* setsyser.c (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int _setsyserrno (int errcode)
+{
+  return __setsyserrno (errcode);
+}
Index: trunk/src/emx/src/lib/misc/setuid.c
===================================================================
--- trunk/src/emx/src/lib/misc/setuid.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/setuid.c	(revision 18)
@@ -0,0 +1,15 @@
+/* setuid.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+
+int _setuid (uid_t uid)
+{
+  if (uid != 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/sleep.c
===================================================================
--- trunk/src/emx/src/lib/misc/sleep.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/sleep.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sleep.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+unsigned _sleep (unsigned sec)
+{
+  return __sleep (sec);
+}
Index: trunk/src/emx/src/lib/misc/sleep2.c
===================================================================
--- trunk/src/emx/src/lib/misc/sleep2.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/sleep2.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sleep2.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+unsigned _sleep2 (unsigned millisec)
+{
+  return __sleep2 (millisec);
+}
Index: trunk/src/emx/src/lib/misc/splitarg.c
===================================================================
--- trunk/src/emx/src/lib/misc/splitarg.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/splitarg.c	(revision 18)
@@ -0,0 +1,72 @@
+/* splitarg.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#define WHITE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
+
+char ** _splitargs (char *string, int *count)
+{
+  int argc, arga, src, dst, bs, quote;
+  char *q, **argv;
+
+  argv = NULL; argc = 0; arga = 0; dst = 0; src = 0;
+  while (WHITE (string[src]))
+    ++src;
+  do 
+    {
+      if (argc >= arga)
+        {
+          arga += 16;
+          argv = realloc (argv, arga * sizeof (*argv));
+          if (argv == NULL)
+            {
+              errno = ENOMEM;
+              return NULL;
+            }
+        }
+      if (string[src] == 0)
+        q = NULL;
+      else
+        {
+          q = string+dst; bs = 0; quote = 0;
+          for (;;)
+            {
+              if (string[src] == '"')
+                {
+                  while (bs >= 2)
+                    {
+                      string[dst++] = '\\';
+                      bs -= 2;
+                    }
+                  if (bs & 1)
+                    string[dst++] = '"';
+                  else
+                    quote = !quote;
+                  bs = 0;
+                }
+              else if (string[src] == '\\')
+                ++bs;
+              else
+                {
+                  while (bs != 0)
+                    {
+                      string[dst++] = '\\';
+                      --bs;
+                    }
+                  if (string[src] == 0 || (WHITE (string[src]) && !quote))
+                    break;
+                  string[dst++] = string[src];
+                }
+              ++src;
+            }
+          while (WHITE (string[src]))
+            ++src;
+          string[dst++] = 0;
+        }
+      argv[argc++] = q;
+    } while (q != NULL);
+  if (count != NULL)
+    *count = argc - 1;
+  return argv;
+}
Index: trunk/src/emx/src/lib/misc/splitpat.c
===================================================================
--- trunk/src/emx/src/lib/misc/splitpat.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/splitpat.c	(revision 18)
@@ -0,0 +1,74 @@
+/* splitpath.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/nls.h>
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+void _splitpath (const char *src, char *drive, char *dir, char *fname,
+                 char *ext)
+{
+  int i, j;
+
+  i = 0;
+  while (src[i] != 0)
+    if (_nls_is_dbcs_lead ((unsigned char)src[i]))
+      {
+        if (src[i+1] == 0)      /* Invalid DBCS character */
+          break;
+        i += 2;
+      }
+    else if (src[i] == ':')
+      break;
+    else
+      ++i;
+
+  if (i > 0 && i + 2 <= _MAX_DRIVE && src[i] == ':')
+    {
+      if (drive != NULL)
+        _strncpy (drive, src, min (i+2, _MAX_DRIVE));
+      src += i + 1;
+    }
+  else if (drive != NULL)
+    *drive = 0;
+  
+  i = 0; j = 0;
+  while (src[j] != 0)
+    if (_nls_is_dbcs_lead ((unsigned char)src[j]))
+      {
+        if (src[j+1] == 0)      /* Invalid DBCS character */
+          break;
+        j += 2;
+      }
+    else if (src[j] == '/' || src[j] == '\\')
+      i = ++j;
+    else
+      ++j;
+
+  if (dir != NULL)
+    _strncpy (dir, src, min (_MAX_DIR, i + 1));
+  src += i;
+  
+  i = 0; j = 0;
+  while (src[j] != 0)
+    if (_nls_is_dbcs_lead ((unsigned char)src[j]))
+      {
+        if (src[j+1] == 0)      /* Invalid DBCS character */
+          break;
+        j += 2;
+      }
+    else if (src[j] == '.')
+      i = j++;
+    else
+      ++j;
+
+  if (i == 0)
+    i = j;
+  if (fname != NULL)
+    _strncpy (fname, src, min (_MAX_FNAME, i + 1));
+  src += i;
+  
+  if (ext != NULL)
+    _strncpy (ext, src, _MAX_EXT);
+}
Index: trunk/src/emx/src/lib/misc/swchar.c
===================================================================
--- trunk/src/emx/src/lib/misc/swchar.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/swchar.c	(revision 18)
@@ -0,0 +1,15 @@
+/* swchar.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+char _swchar (void)
+{
+  int x;
+
+  x = __swchar (0, 0);
+  if (x & 0xff)
+    return 0;
+  else
+    return (char)((x>>8) & 0xff);
+}
Index: trunk/src/emx/src/lib/misc/sysconf.c
===================================================================
--- trunk/src/emx/src/lib/misc/sysconf.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/sysconf.c	(revision 18)
@@ -0,0 +1,51 @@
+/* sysconf.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <limits.h>
+#include <time.h>
+#include <errno.h>
+
+/* Return the POSIX.1  minimum values, for now. */
+
+long _sysconf (int name)
+{
+  switch (name)
+    {
+    case _SC_ARG_MAX:
+      return _POSIX_ARG_MAX;
+
+    case _SC_CHILD_MAX:
+      return _POSIX_CHILD_MAX;
+
+    case _SC_CLK_TCK:
+      /* On emx, CLK_TCK is a constant.  On other systems, it may a
+         macro which calls sysconf (_SC_CLK_TCK). */
+
+      return CLK_TCK;
+
+    case _SC_NGROUPS_MAX:
+      return _POSIX_NGROUPS_MAX;
+
+    case _SC_OPEN_MAX:
+      return _POSIX_OPEN_MAX;
+
+    case _SC_STREAM_MAX:
+      return _POSIX_STREAM_MAX;
+
+    case _SC_TZNAME_MAX:
+      return _POSIX_TZNAME_MAX;
+
+    case _SC_JOB_CONTROL:
+      return -1;
+
+    case _SC_SAVED_IDS:
+      return -1;
+
+    case _SC_VERSION:
+      return _POSIX_VERSION;
+
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/misc/syserr.c
===================================================================
--- trunk/src/emx/src/lib/misc/syserr.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/syserr.c	(revision 18)
@@ -0,0 +1,74 @@
+/* syserr.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+const char * const _sys_errlist[] =
+{
+  /*  0 EZERO          */ "Error 0",
+  /*  1 EPERM          */ "Operation not permitted",
+  /*  2 ENOENT         */ "No such file or directory",
+  /*  3 ESRCH          */ "No such process",
+  /*  4 EINTR          */ "Interrupted system call",
+  /*  5 EIO            */ "I/O error",
+  /*  6 ENXIO          */ "No such device or address",
+  /*  7 E2BIG          */ "Arguments or environment too big",
+  /*  8 ENOEXEC        */ "Invalid executable file format",
+  /*  9 EBADF          */ "Bad file number",
+  /* 10 ECHILD         */ "No children",
+  /* 11 EAGAIN         */ "Resource temporarily unavailable",
+  /* 12 ENOMEM         */ "Not enough memory",
+  /* 13 EACCES         */ "Permission denied",
+  /* 14 EFAULT         */ "Bad address",
+  /* 15 ENOLCK         */ "No locks available",
+  /* 16 EBUSY          */ "Resource busy",
+  /* 17 EEXIST         */ "File exists",
+  /* 18 EXDEV          */ "Cross-device link",
+  /* 19 ENODEV         */ "No such device",
+  /* 20 ENOTDIR        */ "Not a directory",
+  /* 21 EISDIR         */ "Is a directory",
+  /* 22 EINVAL         */ "Invalid argument",
+  /* 23 ENFILE         */ "Too many open files in system",
+  /* 24 EMFILE         */ "Too many open files",
+  /* 25 ENOTTY         */ "Inappropriate ioctl",
+  /* 26 EDEADLK        */ "Resource deadlock avoided",
+  /* 27 EFBIG          */ "File too large",
+  /* 28 ENOSPC         */ "Disk full",
+  /* 29 ESPIPE         */ "Invalid seek",
+  /* 30 EROFS          */ "Read-only file system",
+  /* 31 EMLINK         */ "Too many links",
+  /* 32 EPIPE          */ "Broken pipe",
+  /* 33 EDOM           */ "Domain error",
+  /* 34 ERANGE         */ "Result too large",
+  /* 35 ENOTEMPTY      */ "Directory not empty",
+  /* 36 EINPROGRESS    */ "Operation now in progress",
+  /* 37 ENOSYS         */ "Function not implemented",
+  /* 38 ENAMETOOLONG   */ "File name too long",
+  /* 39 EDESTADDRREQ   */ "Destination address required",
+  /* 40 EMSGSIZE       */ "Message too long",
+  /* 41 EPROTOTYPE     */ "Protocol wrong type for socket",
+  /* 42 ENOPROTOOPT    */ "Option not supported by protocol",
+  /* 43 EPROTONOSUPPORT */ "Protocol not supported",
+  /* 44 ESOCKTNOSUPPORT */ "Socket type not supported",
+  /* 45 EOPNOTSUPP     */ "Operation not supported on socket",
+  /* 46 EPFNOSUPPORT   */ "Protocol family not supported",
+  /* 47 EAFNOSUPPORT   */ "Address family not supported by protocol family",
+  /* 48 EADDRINUSE     */ "Address already in use",
+  /* 49 EADDRNOTAVAIL  */ "Can't assign requested address",
+  /* 50 ENETDOWN       */ "Network is down",
+  /* 51 ENETUNREACH    */ "Network is unreachable",
+  /* 52 ENETRESET      */ "Network dropped connection on reset",
+  /* 53 ECONNABORTED   */ "Software caused connection abort",
+  /* 54 ECONNRESET     */ "Connection reset by peer",
+  /* 55 ENOBUFS        */ "No buffer space available",
+  /* 56 EISCONN        */ "Socket is already connected",
+  /* 57 ENOTCONN       */ "Socket is not connected",
+  /* 58 ESHUTDOWN      */ "Can't send after socket shutdown",
+  /* 59 ETOOMANYREFS   */ "Too many references: can't splice",
+  /* 60 ETIMEDOUT      */ "Connection timed out",
+  /* 61 ECONNREFUSED   */ "Connection refused",
+  /* 62 ELOOP          */ "Too many levels of symbolic links",
+  /* 63 ENOTSOCK       */ "Socket operation on non-socket",
+  /* 64 EHOSTDOWN      */ "Host is down",
+  /* 65 EHOSTUNREACH   */ "No route to host",
+  /* 66 EALREADY       */ "Operation already in progress"
+};
+
+const int _sys_nerr = sizeof (_sys_errlist) / sizeof (_sys_errlist[0]);
Index: trunk/src/emx/src/lib/misc/syserrno.c
===================================================================
--- trunk/src/emx/src/lib/misc/syserrno.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/syserrno.c	(revision 18)
@@ -0,0 +1,8 @@
+/* syserrno.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int _syserrno (void)
+{
+  return __syserrno ();
+}
Index: trunk/src/emx/src/lib/misc/uflags.c
===================================================================
--- trunk/src/emx/src/lib/misc/uflags.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/uflags.c	(revision 18)
@@ -0,0 +1,9 @@
+/* uflags.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <sys/uflags.h>
+#include <emx/syscalls.h>
+
+int _uflags (int mask, int new_bits)
+{
+  return __uflags (mask, new_bits);
+}
Index: trunk/src/emx/src/lib/misc/ulimit.c
===================================================================
--- trunk/src/emx/src/lib/misc/ulimit.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/ulimit.c	(revision 18)
@@ -0,0 +1,33 @@
+/* ulimit.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ulimit.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+long _ulimit (int cmd, ...)
+{
+  va_list arg_ptr;
+  long newlimit;
+
+  switch (cmd)
+    {
+    case UL_GFILLIM:
+      return 1 << 21;
+    case UL_SFILLIM:
+      va_start (arg_ptr, cmd);
+      newlimit = va_arg (arg_ptr, long);
+      va_end (arg_ptr);
+      return newlimit;
+    case UL_GMEMLIM:
+      return __ulimit (cmd, 0);
+    case UL_NOFILES:
+      return 40;
+    case UL_OBJREST:
+      return __ulimit (cmd, 0);
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/misc/uname.c
===================================================================
--- trunk/src/emx/src/lib/misc/uname.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/uname.c	(revision 18)
@@ -0,0 +1,31 @@
+/* uname.c (emx+gcc) -- Copyright (c) 1993 by Kai Uwe Rommel */
+/*                      Copyright (c) 1993-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/utsname.h>
+
+#define SET(dst,src) _strncpy (name->dst, (src), sizeof (name->dst))
+#define CHR(x)       (char)((x)+'0')
+
+int _uname (struct utsname *name)
+{
+  char *host;
+  int dos;
+
+  dos = (_osmode == DOS_MODE && _osmajor < 10);
+  host = getenv ("HOSTNAME");
+  if (host == NULL)
+    host = "standalone";
+
+  SET (sysname, (dos ? "MS-DOS" : "OS/2"));
+  SET (nodename, host);
+  SET (release, "1");
+  name->version[0] = (dos ? CHR (_osmajor) : CHR (_osmajor / 10));
+  name->version[1] = '.';
+  name->version[2] = CHR (_osminor / 10);
+  name->version[3] = CHR (_osminor % 10);
+  name->version[4] = 0;
+  SET (machine, "i386");
+  return 0;
+}
Index: trunk/src/emx/src/lib/misc/wildcard.c
===================================================================
--- trunk/src/emx/src/lib/misc/wildcard.c	(revision 18)
+++ trunk/src/emx/src/lib/misc/wildcard.c	(revision 18)
@@ -0,0 +1,74 @@
+/* wildcard.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <emx/startup.h>
+#include <emx/syscalls.h>
+
+#define WPUT(x) do { \
+    if (new_argc >= new_alloc) \
+      { \
+        new_alloc += 20; \
+        new_argv = (char **)realloc (new_argv, new_alloc * sizeof (char *)); \
+        if (new_argv == NULL) \
+            goto out_of_memory; \
+      } \
+    new_argv[new_argc++] = x; \
+  } while (0)
+
+
+
+void _wildcard (int *argcp, char ***argvp)
+{
+  int i, old_argc, new_argc, new_alloc;
+  char **old_argv, **new_argv;
+  char line[256], *p, *q;
+  struct _find find;
+
+  old_argc = *argcp; old_argv = *argvp;
+  _rfnlwr ();
+  for (i = 1; i < old_argc; ++i)
+    if (old_argv[i] != NULL &&
+        !(old_argv[i][-1] & (_ARG_DQUOTE|_ARG_RESPONSE)) &&
+        strpbrk (old_argv[i], "?*") != NULL)
+      break;
+  if (i >= old_argc)
+    return;                 /* do nothing */
+  new_argv = NULL; new_alloc = 0; new_argc = 0;
+  for (i = 0; i < old_argc; ++i)
+    {
+      if (i == 0 || old_argv[i] == NULL
+          || (old_argv[i][-1] & (_ARG_DQUOTE|_ARG_RESPONSE))
+          || strpbrk (old_argv[i], "?*") == NULL
+          || __findfirst (old_argv[i], 0x10, &find) != 0)
+        WPUT (old_argv[i]);
+      else
+        {
+          line[0] = _ARG_NONZERO|_ARG_WILDCARD;
+          strcpy (line+1, old_argv[i]);
+          p = _getname (line + 1);
+          do
+            {
+              if (strcmp (find.name, ".") != 0 &&
+                  strcmp (find.name, "..") != 0)
+                {
+                  strcpy (p, find.name);
+                  _fnlwr2 (p, line+1);
+                  q = _strdup (line);
+                  if (q == NULL)
+                    goto out_of_memory;
+                  WPUT (q+1);
+                }
+            } while (__findnext (&find) == 0);
+        }
+    }
+  WPUT (NULL); --new_argc;
+  *argcp = new_argc; *argvp = new_argv;
+  _rfnlwr ();
+  return;
+
+out_of_memory:
+  fputs ("Out of memory while expanding wildcards\n", stderr);
+  exit (255);
+}
Index: trunk/src/emx/src/lib/moddef/makefile
===================================================================
--- trunk/src/emx/src/lib/moddef/makefile	(revision 18)
+++ trunk/src/emx/src/lib/moddef/makefile	(revision 18)
@@ -0,0 +1,32 @@
+#
+# /emx/src/lib/moddef/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+
+.PHONY: clean default dstlib moddef
+
+MD=$(I)sys/moddef.h
+
+LIBMODDEF=$(L)moddef.a
+
+default: moddef
+
+moddef .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(LIBMODDEF)
+
+clean:
+	-del $(CPU)\*.o $(DELOPT)
+
+moddef1.o: moddef1.c $(MD) $(I)stdio.h $(I)stdlib.h $(I)string.h $(ERRNO) \
+                     $(I)ctype.h $(I)share.h
+moddef2.o: moddef2.c $(MD) $(I)stdio.h
+moddef3.o: moddef3.c $(MD) $(I)stdio.h
+
+$(LIBMODDEF): moddef1.o moddef2.o moddef3.o
+	-del $(LIBMODDEF)
+	$(AR) r $(LIBMODDEF) *.o
Index: trunk/src/emx/src/lib/moddef/moddef1.c
===================================================================
--- trunk/src/emx/src/lib/moddef/moddef1.c	(revision 18)
+++ trunk/src/emx/src/lib/moddef/moddef1.c	(revision 18)
@@ -0,0 +1,300 @@
+/* moddef1.c (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <share.h>
+#include <errno.h>
+#include <sys/moddef.h>
+
+#define ERRNO (*_errno ())
+
+#define MDF_OPEN 0x0001
+
+struct _md
+{
+  _md_token token;
+  FILE *file;
+  long number;
+  long linenumber;
+  unsigned flags;
+  const char *ptr;
+  char string[512];
+  char buffer[512];
+};
+
+/* An entry of the keywords table associates a keyword string with a
+   token index. */
+
+struct keyword
+{
+  char *name;
+  _md_token token;
+};
+
+/* This table contains all the keywords.  Some of the keywords are not
+   (officially) used. */
+
+static struct keyword keywords[] =
+{
+  {"ALIAS",           _MD_ALIAS},
+  {"BASE",            _MD_BASE},
+  {"CLASS",           _MD_CLASS},
+  {"CODE",            _MD_CODE},
+  {"CONFORMING",      _MD_CONFORMING},
+  {"CONTIGUOUS",      _MD_CONTIGUOUS},
+  {"DATA",            _MD_DATA},
+  {"DESCRIPTION",     _MD_DESCRIPTION},
+  {"DEV386",          _MD_DEV386},
+  {"DEVICE",          _MD_DEVICE},
+  {"DISCARDABLE",     _MD_DISCARDABLE},
+  {"DOS4",            _MD_DOS4},
+  {"DYNAMIC",         _MD_DYNAMIC},
+  {"EXECUTEONLY",     _MD_EXECUTEONLY},
+  {"EXECUTE-ONLY",    _MD_EXECUTEONLY},
+  {"EXECUTEREAD",     _MD_EXECUTEREAD},
+  {"EXETYPE",         _MD_EXETYPE},
+  {"EXPANDDOWN",      _MD_EXPANDDOWN},
+  {"EXPORTS",         _MD_EXPORTS},
+  {"FIXED",           _MD_FIXED},
+  {"HEAPSIZE",        _MD_HEAPSIZE},
+  {"HUGE",            _MD_HUGE},
+  {"IMPORTS",         _MD_IMPORTS},
+  {"IMPURE",          _MD_IMPURE},
+  {"INCLUDE",         _MD_INCLUDE},
+  {"INITGLOBAL",      _MD_INITGLOBAL},
+  {"INITINSTANCE",    _MD_INITINSTANCE},
+  {"INVALID",         _MD_INVALID},
+  {"IOPL",            _MD_IOPL},
+  {"LIBRARY",         _MD_LIBRARY},
+  {"LOADONCALL",      _MD_LOADONCALL},
+  {"LONGNAMES",       _MD_NEWFILES},
+  {"MAXVAL",          _MD_MAXVAL},
+  {"MIXED1632",       _MD_MIXED1632},
+  {"MOVABLE",         _MD_MOVEABLE},
+  {"MOVEABLE",        _MD_MOVEABLE},
+  {"MULTIPLE",        _MD_MULTIPLE},
+  {"NAME",            _MD_NAME},
+  {"NEWFILES",        _MD_NEWFILES},
+  {"NODATA",          _MD_NODATA},
+  {"NOEXPANDDOWN",    _MD_NOEXPANDDOWN},
+  {"NOIOPL",          _MD_NOIOPL},
+  {"NONAME",          _MD_NONAME},
+  {"NONCONFORMING",   _MD_NONCONFORMING},
+  {"NONDISCARDABLE",  _MD_NONDISCARDABLE},
+  {"NONE",            _MD_NONE},
+  {"NONPERMANENT",    _MD_NONPERMANENT},
+  {"NONSHARED",       _MD_NONSHARED},
+  {"NOTWINDOWCOMPAT", _MD_NOTWINDOWCOMPAT},
+  {"OBJECTS",         _MD_OBJECTS},
+  {"OLD",             _MD_OLD},
+  {"ORDER",           _MD_ORDER},
+  {"OS2",             _MD_OS2},
+  {"PERMANENT",       _MD_PERMANENT},
+  {"PHYSICAL",        _MD_PHYSICAL},
+  {"PRELOAD",         _MD_PRELOAD},
+  {"PRIVATE",         _MD_PRIVATE},
+  {"PRIVATELIB",      _MD_PRIVATELIB},
+  {"PROTECT",         _MD_PROTECT},
+  {"PROTMODE",        _MD_PROTMODE},
+  {"PURE",            _MD_PURE},
+  {"READONLY",        _MD_READONLY},
+  {"READWRITE",       _MD_READWRITE},
+  {"REALMODE",        _MD_REALMODE},
+  {"RESIDENT",        _MD_RESIDENT},
+  {"RESIDENTNAME",    _MD_RESIDENTNAME},
+  {"SEGMENTS",        _MD_SEGMENTS},
+  {"SHARED",          _MD_SHARED},
+  {"SINGLE",          _MD_SINGLE},
+  {"STACKSIZE",       _MD_STACKSIZE},
+  {"STUB",            _MD_STUB},
+  {"SWAPPABLE",       _MD_SWAPPABLE},
+  {"TERMGLOBAL",      _MD_TERMGLOBAL},
+  {"TERMINSTANCE",    _MD_TERMINSTANCE},
+  {"UNKNOWN",         _MD_UNKNOWN},
+  {"VIRTUAL",         _MD_VIRTUAL},
+  {"WINDOWAPI",       _MD_WINDOWAPI},
+  {"WINDOWCOMPAT",    _MD_WINDOWCOMPAT},
+  {"WINDOWS",         _MD_WINDOWS},
+  {NULL,              _MD_word}
+};
+
+
+_md_token _md_get_token (const struct _md *md)
+{
+  return md->token;
+}
+
+
+long _md_get_number (const struct _md *md)
+{
+  return md->number;
+}
+
+
+const char *_md_get_string (const struct _md *md)
+{
+  return md->string;
+}
+
+
+long _md_get_linenumber (const struct _md *md)
+{
+  return md->linenumber;
+}
+
+
+/* Read a line from the module definition file to md->buffer.  Set
+   md->token and return -1 on error or if the end of the file is
+   reached.  Otherwise, return 0, increment the line number and move
+   md->ptr to the start of the line. */
+
+static int get_line (struct _md *md)
+{
+  char *p;
+  
+  if (fgets (md->buffer, sizeof (md->buffer), md->file) == NULL)
+    {
+      md->token = (ferror (md->file) ? _MD_ioerror : _MD_eof);
+      return -1;
+    }
+  p = strchr (md->buffer, '\n');
+  if (p != NULL) *p = 0;
+  md->ptr = md->buffer;
+  ++md->linenumber;
+  return 0;
+}
+
+
+_md_token _md_next_token (struct _md *md)
+{
+  const char *start, *end;
+  char *p, quote_char;
+  long n;
+  int i;
+
+  md->number = 0;
+  md->string[0] = 0;
+  for (;;)
+    {
+      if (*md->ptr == ' ' || *md->ptr == '\t')
+        ++md->ptr;
+      else if (*md->ptr == 0 || *md->ptr == ';')
+        {
+          if (get_line (md) != 0)
+            return md->token;
+        }
+      else
+        break;
+    }
+  if (*md->ptr == '\'' || *md->ptr == '\"')
+    {
+      quote_char = *md->ptr;
+      md->token = _MD_quote;
+      start = ++md->ptr;
+      while (*md->ptr != 0 &&
+             (*md->ptr != quote_char || md->ptr[1] == quote_char))
+        ++md->ptr;
+      if (*md->ptr != quote_char)
+        {
+          md->token = _MD_missingquote;
+          return md->token;
+        }
+      end = md->ptr++;
+    }
+  else if (*md->ptr == '=')
+    {
+      md->token = _MD_equal;
+      start = md->ptr++; end = md->ptr;
+    }
+  else if (*md->ptr == '@')
+    {
+      md->token = _MD_at;
+      start = md->ptr++; end = md->ptr;
+    }
+  else if (*md->ptr == '.')
+    {
+      md->token = _MD_dot;
+      start = md->ptr++; end = md->ptr;
+    }
+  else
+    {
+      md->token = _MD_word;
+      start = md->ptr++;
+      md->ptr += strcspn (md->ptr, " \t=@.");
+      end = md->ptr;
+    }
+  _strncpy (md->string, start, end+1-start);
+  if (md->token == _MD_word)
+    for (i = 0; keywords[i].name != NULL; ++i)
+      if (stricmp (md->string, keywords[i].name) == 0)
+        {
+          md->token = keywords[i].token;
+          break;
+        }
+  if (md->token == _MD_word)
+    {
+      if (isdigit ((unsigned char)md->string[0]))
+        {
+          ERRNO = 0;
+          n = strtol (md->string, &p, 0);
+          if (p != md->string && *p == 0 && ERRNO == 0)
+            {
+              md->token = _MD_number;
+              md->number = n;
+            }
+        }
+    }
+  return md->token;
+}
+
+
+struct _md *_md_use_file (FILE *f)
+{
+  struct _md *p;
+
+  p = malloc (sizeof (*p));
+  if (p == NULL)
+    {
+      ERRNO = ENOMEM;
+      return NULL;
+    }
+  p->token = _MD_eof;
+  p->string[0] = 0;
+  p->buffer[0] = 0;
+  p->ptr = p->buffer;
+  p->number = 0;
+  p->linenumber = 0;
+  p->file = f;
+  p->flags = 0;
+  return p;
+}
+
+
+struct _md *_md_open (const char *fname)
+{
+  FILE *f;
+  struct _md *p;
+
+  f = _fsopen (fname, "rt", SH_DENYWR);
+  if (f == NULL)
+    return NULL;
+  p = _md_use_file (f);
+  if (p == NULL)
+    fclose (f);
+  else
+    p->flags |= MDF_OPEN;
+  return p;
+}
+
+
+int _md_close (struct _md *md)
+{
+  int result = 0;
+
+  if (md->flags & MDF_OPEN)
+    result = fclose (md->file);
+  free (md);
+  return result;
+}
Index: trunk/src/emx/src/lib/moddef/moddef2.c
===================================================================
--- trunk/src/emx/src/lib/moddef/moddef2.c	(revision 18)
+++ trunk/src/emx/src/lib/moddef/moddef2.c	(revision 18)
@@ -0,0 +1,639 @@
+/* moddef2.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/moddef.h>
+
+#define FALSE 0
+#define TRUE  1
+
+typedef int _md_callback (struct _md *md, const _md_stmt *stmt,
+                          _md_token token, void *arg);
+
+static int error (struct _md *md, _md_callback *callback, _md_stmt *stmt,
+                  _md_token stmt_token, _md_error code, void *arg)
+{
+  stmt->error.code = code;
+  stmt->error.stmt = stmt_token;
+  return callback (md, stmt, _MD_parseerror, arg);
+}
+
+static _md_token sync (struct _md *md)
+{
+  _md_token token;
+
+  token = _md_get_token (md);
+  for (;;)
+    switch (token)
+      {
+      case _MD_BASE:
+      case _MD_CODE:
+      case _MD_DATA:
+      case _MD_DESCRIPTION:
+      case _MD_EXETYPE:
+      case _MD_EXPORTS:
+      case _MD_HEAPSIZE:
+      case _MD_IMPORTS:
+      case _MD_OLD:
+      case _MD_PROTMODE:
+      case _MD_REALMODE:
+      case _MD_SEGMENTS:
+      case _MD_STACKSIZE:
+      case _MD_STUB:
+      case _MD_eof:
+      case _MD_ioerror:
+      case _MD_missingquote:
+        return token;
+      default:
+        token = _md_next_token (md);
+        break;
+      }
+}
+
+
+#define ERROR(CODE) \
+  do { result = error (md, callback, &stmt, stmt_token, (CODE), arg); \
+       if (result != 0) return result; \
+       token = sync (md); goto next_stmt;} while (FALSE)
+
+#define CALLBACK \
+  do { result = callback (md, &stmt, stmt_token, arg); \
+       if (result != 0) return result; } while (FALSE)
+
+int _md_parse (struct _md *md, _md_callback *callback, void *arg)
+{
+  _md_token token, stmt_token;
+  _md_stmt stmt;
+  const char *s;
+  long n;
+  int ok, result;
+
+  token = _md_get_token (md);
+  stmt_token = token;
+  switch (stmt_token)
+    {
+    case _MD_eof:
+      ERROR (_MDE_EMPTY);
+      break;
+
+    case _MD_NAME:
+      token = _md_next_token (md);
+      stmt.name.name[0] = 0;
+      if (token == _MD_quote || token == _MD_word)
+        {
+          _strncpy (stmt.name.name, _md_get_string (md),
+                    sizeof (stmt.name.name));
+          token = _md_next_token (md);
+        }
+      switch (token)
+        {
+        case _MD_WINDOWAPI:
+          stmt.name.pmtype = _MDT_WINDOWAPI;
+          token = _md_next_token (md);
+          break;
+        case _MD_WINDOWCOMPAT:
+          stmt.name.pmtype = _MDT_WINDOWCOMPAT;
+          token = _md_next_token (md);
+          break;
+        case _MD_NOTWINDOWCOMPAT:
+          stmt.name.pmtype = _MDT_NOTWINDOWCOMPAT;
+          token = _md_next_token (md);
+          break;
+        default:
+          stmt.name.pmtype = _MDT_DEFAULT;
+          break;
+        }
+      stmt.name.newfiles = FALSE;
+      if (token == _MD_NEWFILES)
+        {
+          stmt.name.newfiles = TRUE;
+          token = _md_next_token (md);
+        }
+      CALLBACK;
+      break;
+
+    case _MD_LIBRARY:
+      token = _md_next_token (md);
+      if (token == _MD_quote || token == _MD_word)
+        {
+          _strncpy (stmt.library.name, _md_get_string (md),
+                    sizeof (stmt.library.name));
+          token = _md_next_token (md);
+        }
+      switch (token)
+        {
+        case _MD_INITGLOBAL:
+          stmt.library.init = _MDIT_GLOBAL;
+          token = _md_next_token (md);
+          break;
+        case _MD_INITINSTANCE:
+          stmt.library.init = _MDIT_INSTANCE;
+          token = _md_next_token (md);
+          break;
+        default:
+          stmt.library.init = _MDIT_DEFAULT;
+          break;
+        }
+      switch (token)
+        {
+        case _MD_TERMGLOBAL:
+          stmt.library.term = _MDIT_GLOBAL;
+          token = _md_next_token (md);
+          break;
+        case _MD_TERMINSTANCE:
+          stmt.library.term = _MDIT_INSTANCE;
+          token = _md_next_token (md);
+          break;
+        default:
+          stmt.library.term = _MDIT_DEFAULT;
+          break;
+        }
+      if (token == _MD_PRIVATELIB)
+        token = _md_next_token (md);
+      CALLBACK;
+      break;
+
+    case _MD_VIRTUAL:
+    case _MD_PHYSICAL:
+      token = _md_next_token (md);
+      if (token != _MD_DEVICE)
+        ERROR (_MDE_DEVICE_EXPECTED);
+      token = _md_next_token (md);
+      stmt.device.name[0] = 0;
+      if (token == _MD_quote || token == _MD_word)
+        {
+          _strncpy (stmt.device.name, _md_get_string (md),
+                    sizeof (stmt.device.name));
+          token = _md_next_token (md);
+        }
+      CALLBACK;
+      break;
+
+    default:
+      break;
+    }
+
+next_stmt:
+  while (token != _MD_eof)
+    {
+      stmt_token = token;
+      switch (stmt_token)
+        {
+        case _MD_BASE:
+          token = _md_next_token (md);
+          if (token != _MD_equal)
+            ERROR (_MDE_EQUAL_EXPECTED);
+          token = _md_next_token (md);
+          if (token != _MD_number)
+            ERROR (_MDE_NUMBER_EXPECTED);
+          stmt.base.addr = _md_get_number (md);
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_CODE:
+          token = _md_next_token (md);
+          stmt.segment.segname[0] = 0;
+          stmt.segment.classname[0] = 0;
+          stmt.segment.attr = 0;
+          ok = TRUE;
+          while (ok)
+            {
+              switch (token)
+                {
+                case _MD_CONFORMING:
+                  stmt.segment.attr |= _MDS_CONFORMING;
+                  break;
+                case _MD_DISCARDABLE:
+                  stmt.segment.attr |= _MDS_DISCARDABLE;
+                  break;
+                case _MD_EXECUTEONLY:
+                  stmt.segment.attr |= _MDS_EXECUTEONLY;
+                  break;
+                case _MD_EXECUTEREAD:
+                  stmt.segment.attr |= _MDS_EXECUTEREAD;
+                  break;
+                case _MD_FIXED:
+                  stmt.segment.attr |= _MDS_FIXED;
+                  break;
+                case _MD_IOPL:
+                  stmt.segment.attr |= _MDS_IOPL;
+                  break;
+                case _MD_LOADONCALL:
+                  stmt.segment.attr |= _MDS_LOADONCALL;
+                  break;
+                case _MD_MOVEABLE:
+                  stmt.segment.attr |= _MDS_MOVEABLE;
+                  break;
+                case _MD_NOIOPL:
+                  stmt.segment.attr |= _MDS_NOIOPL;
+                  break;
+                case _MD_NONCONFORMING:
+                  stmt.segment.attr |= _MDS_NONCONFORMING;
+                  break;
+                case _MD_NONDISCARDABLE:
+                  stmt.segment.attr |= _MDS_NONDISCARDABLE;
+                  break;
+                case _MD_NONSHARED:
+                case _MD_IMPURE:
+                  stmt.segment.attr |= _MDS_NONSHARED;
+                  break;
+                case _MD_PRELOAD:
+                  stmt.segment.attr |= _MDS_PRELOAD;
+                  break;
+                case _MD_SHARED:
+                case _MD_PURE:
+                  stmt.segment.attr |= _MDS_SHARED;
+                  break;
+                default:
+                  ok = FALSE;
+                  break;
+                }
+              if (ok)
+                token = _md_next_token (md);
+            }
+          CALLBACK;
+          break;
+
+        case _MD_DATA:
+          token = _md_next_token (md);
+          stmt.segment.segname[0] = 0;
+          stmt.segment.classname[0] = 0;
+          stmt.segment.attr = 0;
+          ok = TRUE;
+          while (ok)
+            {
+              switch (token)
+                {
+                case _MD_FIXED:
+                  stmt.segment.attr |= _MDS_FIXED;
+                  break;
+                case _MD_IOPL:
+                  stmt.segment.attr |= _MDS_IOPL;
+                  break;
+                case _MD_LOADONCALL:
+                  stmt.segment.attr |= _MDS_LOADONCALL;
+                  break;
+                case _MD_MOVEABLE:
+                  stmt.segment.attr |= _MDS_MOVEABLE;
+                  break;
+                case _MD_MULTIPLE:
+                  stmt.segment.attr |= _MDS_MULTIPLE;
+                  break;
+                case _MD_NOIOPL:
+                  stmt.segment.attr |= _MDS_NOIOPL;
+                  break;
+                case _MD_NONE:
+                  stmt.segment.attr |= _MDS_NONE;
+                  break;
+                case _MD_NONSHARED:
+                case _MD_IMPURE:
+                  stmt.segment.attr |= _MDS_NONSHARED;
+                  break;
+                case _MD_PRELOAD:
+                  stmt.segment.attr |= _MDS_PRELOAD;
+                  break;
+                case _MD_READONLY:
+                  stmt.segment.attr |= _MDS_READONLY;
+                  break;
+                case _MD_READWRITE:
+                  stmt.segment.attr |= _MDS_READWRITE;
+                  break;
+                case _MD_SHARED:
+                case _MD_PURE:
+                  stmt.segment.attr |= _MDS_SHARED;
+                  break;
+                case _MD_SINGLE:
+                  stmt.segment.attr |= _MDS_SINGLE;
+                  break;
+                default:
+                  ok = FALSE;
+                  break;
+                }
+              if (ok)
+                token = _md_next_token (md);
+            }
+          CALLBACK;
+          break;
+
+        case _MD_DESCRIPTION:
+          token = _md_next_token (md);
+          if (token != _MD_quote)
+            ERROR (_MDE_STRING_EXPECTED);
+          s = _md_get_string (md);
+          if (*s == 0 || strlen (s) > 255)
+            ERROR (_MDE_STRING_TOO_LONG);
+          _strncpy (stmt.descr.string, s, sizeof (stmt.descr.string));
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_EXETYPE:
+          token = _md_next_token (md);
+          switch (token)
+            {
+            case _MD_OS2:
+              stmt.exetype.type = _MDX_OS2;
+              token = _md_next_token (md);
+              break;
+            case _MD_UNKNOWN:
+              stmt.exetype.type = _MDX_UNKNOWN;
+              token = _md_next_token (md);
+              break;
+            case _MD_WINDOWS:
+              stmt.exetype.type = _MDX_WINDOWS;
+              stmt.exetype.major_version = 0;
+              stmt.exetype.minor_version = 0;
+              token = _md_next_token (md);
+              if (token == _MD_number)
+                {
+                  stmt.exetype.major_version = _md_get_number (md);
+                  token = _md_next_token (md);
+                  if (token == _MD_dot)
+                    {
+                      token = _md_next_token (md);
+                      if (token == _MD_number)
+                        {
+                          stmt.exetype.minor_version = _md_get_number (md);
+                          token = _md_next_token (md);
+                        }
+                    }
+                }
+              break;
+            default:
+              stmt.exetype.type = _MDX_DEFAULT;
+              break;
+            }
+          CALLBACK;
+          break;
+
+        case _MD_EXPORTS:
+          token = _md_next_token (md);
+          while (token == _MD_quote || token == _MD_word)
+            {
+              stmt.export.ordinal = 0;
+              stmt.export.pwords = 0;
+              stmt.export.flags = 0;
+              stmt.export.internalname[0] = 0;
+              _strncpy (stmt.export.entryname, _md_get_string (md),
+                        sizeof (stmt.export.entryname));
+              token = _md_next_token (md);
+              if (token == _MD_equal)
+                {
+                  token = _md_next_token (md);
+                  if (token != _MD_quote && token != _MD_word)
+                    ERROR (_MDE_NAME_EXPECTED);
+                  _strncpy (stmt.export.internalname, _md_get_string (md),
+                            sizeof (stmt.export.internalname));
+                  token = _md_next_token (md);
+                }
+              if (token == _MD_at)
+                {
+                  stmt.export.flags |= _MDEP_ORDINAL;
+                  token = _md_next_token (md);
+                  if (token != _MD_number)
+                    ERROR (_MDE_NUMBER_EXPECTED);
+                  n = _md_get_number (md);
+                  if (n < 1 || n > 65535)
+                    ERROR (_MDE_INVALID_ORDINAL);
+                  stmt.export.ordinal = n;
+                  token = _md_next_token (md);
+                  if (token == _MD_NONAME)
+                    {
+                      stmt.export.flags |= _MDEP_NONAME;
+                      token = _md_next_token (md);
+                    }
+                  else if (token == _MD_RESIDENTNAME)
+                    {
+                      stmt.export.flags |= _MDEP_RESIDENTNAME;
+                      token = _md_next_token (md);
+                    }
+                }
+              if (token == _MD_NODATA)
+                {
+                  stmt.export.flags |= _MDEP_NODATA;
+                  token = _md_next_token (md);
+                }
+              if (token == _MD_number)
+                {
+                  stmt.export.flags |= _MDEP_PWORDS;
+                  stmt.export.pwords = _md_get_number (md);
+                  token = _md_next_token (md);
+                }
+              CALLBACK;
+            }
+          break;
+
+        case _MD_HEAPSIZE:
+          token = _md_next_token (md);
+          if (token == _MD_number)
+            {
+              stmt.heapsize.maxval = FALSE;
+              stmt.heapsize.size = _md_get_number (md);
+            }
+          else if (token == _MD_MAXVAL)
+            {
+              stmt.heapsize.size = 0;
+              stmt.heapsize.maxval = TRUE;
+            }
+          else
+            ERROR (_MDE_NUMBER_EXPECTED);
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_IMPORTS:
+          token = _md_next_token (md);
+          while (token == _MD_quote || token == _MD_word)
+            {
+              _strncpy (stmt.import.modulename, _md_get_string (md),
+                        sizeof (stmt.import.modulename));
+              stmt.import.entryname[0] = 0;
+              stmt.import.internalname[0] = 0;
+              stmt.import.ordinal = 0;
+              stmt.import.flags = 0;
+              token = _md_next_token (md);
+              if (token == _MD_equal)
+                {
+                  _strncpy (stmt.import.internalname, stmt.import.modulename,
+                            sizeof (stmt.import.internalname));
+                  token = _md_next_token (md);
+                  if (token != _MD_quote && token != _MD_word)
+                    ERROR (_MDE_NAME_EXPECTED);
+                  _strncpy (stmt.import.modulename, _md_get_string (md),
+                            sizeof (stmt.import.modulename));
+                  token = _md_next_token (md);
+                }
+              if (token != _MD_dot)
+                ERROR (_MDE_DOT_EXPECTED);
+              token = _md_next_token (md);
+              if (token == _MD_word)
+                _strncpy (stmt.import.entryname, _md_get_string (md),
+                          sizeof (stmt.import.entryname));
+              else if (token == _MD_number)
+                {
+                  stmt.import.flags |= _MDIP_ORDINAL;
+                  n = _md_get_number (md);
+                  if (n < 1 || n > 65535)
+                    ERROR (_MDE_INVALID_ORDINAL);
+                  stmt.import.ordinal = n;
+                }
+              else
+                ERROR (_MDE_NUMBER_EXPECTED);
+              token = _md_next_token (md);
+              CALLBACK;
+            }
+          break;
+
+        case _MD_OLD:
+          token = _md_next_token (md);
+          if (token != _MD_quote)
+            ERROR (_MDE_STRING_EXPECTED);
+          _strncpy (stmt.old.name, _md_get_string (md),
+                    sizeof (stmt.old.name));
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_PROTMODE:
+        case _MD_REALMODE:
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_SEGMENTS:
+          token = _md_next_token (md);
+          while (token == _MD_quote || token == _MD_word)
+            {
+              _strncpy (stmt.segment.segname, _md_get_string (md),
+                        sizeof (stmt.segment.segname));
+              token = _md_next_token (md);
+              if (token == _MD_CLASS)
+                {
+                  token = _md_next_token (md);
+                  if (token != _MD_quote && token != _MD_word)
+                    ERROR (_MDE_NAME_EXPECTED);
+                  _strncpy (stmt.segment.classname, _md_get_string (md),
+                            sizeof (stmt.segment.classname));
+                  token = _md_next_token (md);
+                }
+              else
+                stmt.segment.classname[0] = 0;
+              stmt.segment.attr = 0;
+              ok = TRUE;
+              while (ok)
+                {
+                  switch (token)
+                    {
+                    case _MD_ALIAS:
+                      stmt.segment.attr |= _MDS_ALIAS;
+                      break;
+                    case _MD_CONFORMING:
+                      stmt.segment.attr |= _MDS_CONFORMING;
+                      break;
+                    case _MD_DISCARDABLE:
+                      stmt.segment.attr |= _MDS_DISCARDABLE;
+                      break;
+                    case _MD_EXECUTEONLY:
+                      stmt.segment.attr |= _MDS_EXECUTEONLY;
+                      break;
+                    case _MD_EXECUTEREAD:
+                      stmt.segment.attr |= _MDS_EXECUTEREAD;
+                      break;
+                    case _MD_FIXED:
+                      stmt.segment.attr |= _MDS_FIXED;
+                      break;
+                    case _MD_INVALID:
+                      stmt.segment.attr |= _MDS_INVALID;
+                      break;
+                    case _MD_IOPL:
+                      stmt.segment.attr |= _MDS_IOPL;
+                      break;
+                    case _MD_LOADONCALL:
+                      stmt.segment.attr |= _MDS_LOADONCALL;
+                      break;
+                    case _MD_MIXED1632:
+                      stmt.segment.attr |= _MDS_MIXED1632;
+                      break;
+                    case _MD_MOVEABLE:
+                      stmt.segment.attr |= _MDS_MOVEABLE;
+                      break;
+                    case _MD_NOIOPL:
+                      stmt.segment.attr |= _MDS_NOIOPL;
+                      break;
+                    case _MD_NONCONFORMING:
+                      stmt.segment.attr |= _MDS_NONCONFORMING;
+                      break;
+                    case _MD_NONDISCARDABLE:
+                      stmt.segment.attr |= _MDS_NONDISCARDABLE;
+                      break;
+                    case _MD_NONSHARED:
+                    case _MD_IMPURE:
+                      stmt.segment.attr |= _MDS_NONSHARED;
+                      break;
+                    case _MD_PRELOAD:
+                      stmt.segment.attr |= _MDS_PRELOAD;
+                      break;
+                    case _MD_READONLY:
+                      stmt.segment.attr |= _MDS_READONLY;
+                      break;
+                    case _MD_READWRITE:
+                      stmt.segment.attr |= _MDS_READWRITE;
+                      break;
+                    case _MD_SHARED:
+                    case _MD_PURE:
+                      stmt.segment.attr |= _MDS_SHARED;
+                      break;
+                    default:
+                      ok = FALSE;
+                      break;
+                    }
+                  if (ok)
+                    token = _md_next_token (md);
+                }
+              CALLBACK;
+            }
+          break;
+
+        case _MD_STACKSIZE:
+          token = _md_next_token (md);
+          if (token != _MD_number)
+            ERROR (_MDE_NUMBER_EXPECTED);
+          stmt.stacksize.size = _md_get_number (md);
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_STUB:
+          token = _md_next_token (md);
+          if (token == _MD_quote)
+            {
+              _strncpy (stmt.stub.name, _md_get_string (md),
+                        sizeof (stmt.stub.name));
+              stmt.stub.none = FALSE;
+            }
+          else if (token == _MD_NONE)
+            {
+              stmt.stub.name[0] = 0;
+              stmt.stub.none = TRUE;
+            }
+          else
+            ERROR (_MDE_STRING_EXPECTED);
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_ioerror:
+          ERROR (_MDE_IO_ERROR);
+          break;
+
+        case _MD_missingquote:
+          ERROR (_MDE_MISSING_QUOTE);
+          break;
+
+        default:
+          ERROR (_MDE_INVALID_STMT);
+        }
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/moddef/moddef3.c
===================================================================
--- trunk/src/emx/src/lib/moddef/moddef3.c	(revision 18)
+++ trunk/src/emx/src/lib/moddef/moddef3.c	(revision 18)
@@ -0,0 +1,35 @@
+/* moddef3.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <sys/moddef.h>
+
+const char *_md_errmsg (_md_error code)
+{
+  switch (code)
+    {
+    case _MDE_IO_ERROR:
+      return "Cannot read";
+    case _MDE_MISSING_QUOTE:
+      return "Missing quote";
+    case _MDE_EMPTY:
+      return "Empty file";
+    case _MDE_NAME_EXPECTED:
+      return "Name expected";
+    case _MDE_STRING_EXPECTED:
+      return "String expected";
+    case _MDE_NUMBER_EXPECTED:
+      return "Number expected";
+    case _MDE_EQUAL_EXPECTED:
+      return "`=' expected";
+    case _MDE_DOT_EXPECTED:
+      return "`.' expected";
+    case _MDE_STRING_TOO_LONG:
+      return "String too long";
+    case _MDE_INVALID_ORDINAL:
+      return "Invalid ordinal number";
+    case _MDE_INVALID_STMT:
+      return "Invalid statement";
+    default:
+      return "Unknown error";
+    }
+}
Index: trunk/src/emx/src/lib/omflib/makefile
===================================================================
--- trunk/src/emx/src/lib/omflib/makefile	(revision 18)
+++ trunk/src/emx/src/lib/omflib/makefile	(revision 18)
@@ -0,0 +1,44 @@
+#
+# /emx/src/lib/omflib/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+
+.PHONY: clean realclean default dstlib omflib
+
+OMFLIB=$(L)omflib.a
+DEP=$(S)omflib.h omflib0.h
+OBJECTS=omflibam.o omflibap.o omflibcl.o omflibcp.o omflibcr.o \
+	omflibdl.o omflibex.o omflibpb.o omflibrd.o omflibut.o \
+	omflibwr.o
+
+default:	omflib
+
+omflib .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(OMFLIB)
+
+$(OMFLIB):	$(OBJECTS)
+	-del $(OMFLIB)
+	$(AR) r $(OMFLIB) $(OBJECTS)
+
+omflibam.o:	omflibam.c $(DEP)
+omflibap.o:	omflibap.c $(DEP) $(ERRNO)
+omflibcl.o:	omflibcl.c $(DEP) $(ERRNO)
+omflibcp.o:	omflibcp.c $(DEP)
+omflibcr.o:	omflibcr.c $(DEP) $(ERRNO)
+omflibdl.o:	omflibdl.c $(DEP)
+omflibex.o:	omflibex.c $(DEP)
+omflibpb.o:	omflibpb.c $(DEP)
+omflibrd.o:	omflibrd.c $(DEP) $(ERRNO)
+omflibut.o:	omflibut.c $(DEP)
+omflibwr.o:	omflibwr.c $(DEP)
+
+clean:
+	-del $(CPU)\*.o
+
+realclean: clean
+	-del $(OMFLIB)
Index: trunk/src/emx/src/lib/omflib/omflib0.h
===================================================================
--- trunk/src/emx/src/lib/omflib/omflib0.h	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflib0.h	(revision 18)
@@ -0,0 +1,96 @@
+/* omflib0.h (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Private header file for the emx OMFLIB library. */
+
+#define FALSE 0
+#define TRUE  1
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+
+#define FLAG_DELETED  0x0001
+
+enum omf_state
+{
+  OS_EMPTY,                     /* Empty module */
+  OS_SIMPLE,                    /* Alias or import definition only */
+  OS_OTHER,                     /* Any other records present */
+};
+
+struct omfmod
+{
+  char *name;
+  word page;
+  word flags;
+};
+
+struct pubsym
+{
+  word page;
+  char *name;
+};
+
+struct omflib
+{
+  FILE *f;
+  long dict_offset;
+  int page_size;
+  int dict_blocks;
+  int flags;
+  struct omfmod *mod_tab;
+  int mod_alloc;
+  int mod_count;
+  byte *dict;
+  int block_index;
+  int block_index_delta;
+  int bucket_index;
+  int bucket_index_delta;
+  struct pubsym *pub_tab;
+  int pub_alloc;
+  int pub_count;
+  char output;
+  word mod_page;
+  enum omf_state state;
+  char mod_name[256+1];
+};
+
+struct ptr
+{
+  byte *ptr;
+  int len;
+};
+
+#pragma pack(1)
+
+struct omf_rec
+{
+  byte rec_type;
+  word rec_len;
+};
+
+struct lib_header
+{
+  byte rec_type;
+  word rec_len;
+  dword dict_offset;
+  word dict_blocks;
+  byte flags;
+};
+
+#pragma pack()
+
+int omflib_set_error (char *error);
+int omflib_read_dictionary (struct omflib *p, char *error);
+void omflib_hash (struct omflib *p, const byte *name);
+int omflib_pad (FILE *f, int size, int force, char *error);
+int omflib_copy_module (struct omflib *dst_lib, FILE *dst_file,
+    struct omflib *src_lib, FILE *src_file, const char *mod_name, char *error);
+int omflib_make_mod_tab (struct omflib *p, char *error);
+int omflib_pubdef (struct omf_rec *rec, byte *buf, word page,
+    int (*walker)(const char *name, char *error), char *error);
+int omflib_impdef (struct omf_rec *rec, byte *buf, word page,
+    int (*walker)(const char *name, char *error), char *error);
+int omflib_alias (struct omf_rec *rec, byte *buf, word page,
+    int (*walker)(const char *name, char *error), char *error);
Index: trunk/src/emx/src/lib/omflib/omflibam.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibam.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibam.c	(revision 18)
@@ -0,0 +1,27 @@
+/* omflibam.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Add an OBJ module to an OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+int omflib_add_module (struct omflib *p, const char *fname, char *error)
+{
+  FILE *f;
+  char name[256];
+  char obj_fname[256+4];
+  int ret;
+
+  omflib_module_name (name, fname);
+  strcpy (obj_fname, fname);
+  _defext (obj_fname, "obj");
+  f = fopen (obj_fname, "rb");
+  if (f == NULL)
+    return omflib_set_error (error);
+  ret = omflib_copy_module (p, p->f, NULL, f, name, error);
+  fclose (f);
+  return ret;
+}
Index: trunk/src/emx/src/lib/omflib/omflibap.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibap.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibap.c	(revision 18)
@@ -0,0 +1,42 @@
+/* omflibap.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Declare a symbol public. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+int omflib_add_pub (struct omflib *p, const char *name, word page, char *error)
+{
+  int i;
+
+  if (strncmp (name, "__POST$", 7) == 0)
+    return 0;
+
+  if (p->pub_count >= p->pub_alloc)
+    {
+      p->pub_alloc += 32;
+      p->pub_tab = realloc (p->pub_tab,
+                            p->pub_alloc * sizeof (struct pubsym));
+      if (p->pub_tab == NULL)
+        {
+          errno = ENOMEM;
+          strcpy (error, strerror (errno));
+          p->pub_alloc = 0;
+          p->pub_count = 0;
+          return -1;
+        }
+    }
+  i = p->pub_count;
+  if ((p->pub_tab[i].name = strdup (name)) == NULL)
+    {
+      errno = ENOMEM;
+      return omflib_set_error (error);
+    }
+  p->pub_tab[i].page = page;
+  ++p->pub_count;
+  return 0;
+}
Index: trunk/src/emx/src/lib/omflib/omflibcl.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibcl.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibcl.c	(revision 18)
@@ -0,0 +1,99 @@
+/* omflibcl.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Copy an OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+int omflib_copy_lib (struct omflib *dst, struct omflib *src, char *error)
+{
+  int i, rc, *reverse;
+  long long_page;
+  struct omf_rec rec;
+
+  if (src->mod_count == -1 && omflib_make_mod_tab (src, error) != 0)
+    return -1;
+
+  /* Build a vector which maps page numbers to module table
+     entries. */
+
+  reverse = malloc (65536 * sizeof (*reverse));
+  if (reverse == NULL)
+    {
+      errno = ENOMEM;
+      return omflib_set_error (error);
+    }
+
+  for (i = 0; i < 65536; ++i)
+    reverse[i] = -1;
+  for (i = 0; i < src->mod_count; ++i)
+    reverse[src->mod_tab[i].page] = i;
+
+  /* Now read the source library sequentially, starting on page 1. */
+
+  fseek (src->f, src->page_size, SEEK_SET);
+  for (;;)
+    {
+      long_page = ftell (src->f) / src->page_size;
+      if (long_page == -1)
+        {
+          omflib_set_error (error);
+          free (reverse);
+          return -1;
+        }
+      if (long_page > 65535)
+        {
+          strcpy (error, "Source library too big");
+          free (reverse);
+          return -1;
+        }
+      if (fread (&rec, sizeof (rec), 1, src->f) != 1)
+        {
+          if (ferror (src->f))
+            omflib_set_error (error);
+          else
+            strcpy (error, "Unexpected end of file");
+          free (reverse);
+          return -1;
+        }
+      if (rec.rec_type == LIBEND)
+        break;
+      if (rec.rec_type != THEADR)
+        {
+          strcpy (error, "THEADR or LIBEND expected");
+          free (reverse);
+          return -1;
+        }
+      fseek (src->f, -sizeof (rec), SEEK_CUR);
+      i = reverse[long_page];
+      if (i == -1)
+        {
+          /* Unknown module, perhaps an import definition.  Copy the
+             module. */
+          rc = omflib_copy_module (dst, dst->f, src, src->f, NULL, error);
+        }
+      else if (src->mod_tab[i].flags & FLAG_DELETED)
+        {
+          /* Module marked for deletion.  Skip it. */
+          rc = omflib_copy_module (NULL, NULL, src, src->f, NULL, error);
+        }
+      else
+        {
+          /* Copy the module. */
+          rc = omflib_copy_module (dst, dst->f, src, src->f,
+                                   src->mod_tab[i].name, error);
+        }
+      if (rc != 0)
+        {
+          free (reverse);
+          return rc;
+        }
+    }
+  free (reverse);
+  return 0;
+}
Index: trunk/src/emx/src/lib/omflib/omflibcp.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibcp.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibcp.c	(revision 18)
@@ -0,0 +1,203 @@
+/* omflibcp.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Copy a module from one OMFLIB to another OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+static struct omflib *pubdef_dst_lib;
+static word pubdef_page;
+
+
+static int add_pubdef (const char *name, char *error);
+
+
+int omflib_copy_module (struct omflib *dst_lib, FILE *dst_file,
+                        struct omflib *src_lib, FILE *src_file,
+                        const char *mod_name, char *error)
+{
+  struct omf_rec rec;
+  word page;
+  long long_page, pos;
+  char theadr_name[256];
+  char libmod_name[256];
+  char caller_name[256];
+  byte buf[1024], buf2[256+6];
+  enum omf_state state;
+  enum {RT_THEADR, RT_OTHER} cur_rt, prev_rt;
+  int copy;
+
+  theadr_name[0] = 0; libmod_name[0] = 0;
+  if (mod_name == NULL)
+    caller_name[0] = 0;
+  else
+    omflib_module_name (caller_name, mod_name);
+  if (dst_lib != NULL)
+    {
+      long_page = ftell (dst_file) / dst_lib->page_size;
+      if (long_page > 65535)
+        {
+          strcpy (error, "Library too big -- increase page size");
+          return -1;
+        }
+      page = (word)long_page;
+    }
+  else
+    page = 0;
+  state = OS_EMPTY; prev_rt = RT_OTHER;
+  do
+    {
+      if (fread (&rec, sizeof (rec), 1, src_file) != 1)
+        goto failure_src;
+      if (rec.rec_len > sizeof (buf))
+        {
+          strcpy (error, "Record too long");
+          return -1;
+        }
+      if (fread (buf, rec.rec_len, 1, src_file) != 1)
+        goto failure_src;
+      copy = TRUE; cur_rt = RT_OTHER;
+      switch (rec.rec_type)
+        {
+        case THEADR:
+          if (rec.rec_len == 0 || buf[0] + 1 > rec.rec_len)
+            {
+              strcpy (error, "Truncated THEADR record");
+              return -1;
+            }
+          buf[1+buf[0]] = 0;
+          omflib_module_name (theadr_name, buf + 1);
+          state = OS_EMPTY; cur_rt = RT_THEADR;
+          break;
+
+        case PUBDEF:
+        case PUBDEF|REC32:
+          if (dst_lib != NULL)
+            {
+              pubdef_dst_lib = dst_lib;
+              pubdef_page = page;
+              if (omflib_pubdef (&rec, buf, page, add_pubdef, error) != 0)
+                return -1;
+            }
+          state = OS_OTHER;
+          break;
+
+        case ALIAS:
+          if (dst_lib != NULL)
+            {
+              pubdef_dst_lib = dst_lib;
+              pubdef_page = page;
+              if (omflib_alias (&rec, buf, page, add_pubdef, error) != 0)
+                return -1;
+            }
+          state = (state == OS_EMPTY ? OS_SIMPLE : OS_OTHER);
+          break;
+
+        case COMENT:
+          if (rec.rec_len >= 3 && buf[1] == IMPDEF_CLASS
+              && buf[2] == IMPDEF_SUBTYPE)
+            {
+              if (dst_lib != NULL)
+                {
+                  pubdef_dst_lib = dst_lib;
+                  pubdef_page = page;
+                  if (omflib_impdef (&rec, buf, page, add_pubdef, error) != 0)
+                    return -1;
+                }
+              state = (state == OS_EMPTY ? OS_SIMPLE : OS_OTHER);
+            }
+          else if (rec.rec_len >= 2 && buf[1] == LIBMOD_CLASS)
+            {
+              if (dst_lib == NULL || mod_name != NULL)
+                copy = FALSE;
+              if (rec.rec_len < 3 || buf[2] + 3 > rec.rec_len)
+                {
+                  strcpy (error, "Truncated LIBMOD record");
+                  return -1;
+                }
+              buf[3+buf[2]] = 0;
+              omflib_module_name (libmod_name, buf + 3);
+              state = OS_OTHER;
+            }
+          else
+            state = OS_OTHER;
+          break;
+
+        case MODEND:
+        case MODEND|REC32:
+          /* Don't change STATE. */
+          break;
+
+        default:
+          state = OS_OTHER;
+        }
+
+      if (prev_rt == RT_THEADR && dst_lib != NULL && mod_name != NULL)
+        {
+          if (state == OS_SIMPLE)
+            cur_rt = RT_THEADR; /* Check again after next record */
+          else if (strcmp (caller_name, theadr_name) != 0)
+            {
+              buf2[0] = 0;
+              buf2[1] = LIBMOD_CLASS;
+              buf2[2] = strlen (caller_name);
+              memcpy (buf2 + 3, caller_name, buf2[2]);
+              if (omflib_write_record (dst_lib, COMENT, buf2[2] + 3, buf2,
+                                       TRUE, error) != 0)
+                return -1;
+            }
+        }
+      if (copy && dst_file != NULL)
+        {
+          if (fwrite (&rec, sizeof (rec), 1, dst_file) != 1
+              || fwrite (buf, rec.rec_len, 1, dst_file) != 1)
+            return omflib_set_error (error);
+        }
+      prev_rt = cur_rt;
+    } while (rec.rec_type != MODEND && rec.rec_type != (MODEND|REC32));
+  if (src_lib != NULL)
+    {
+      pos = ftell (src_file);
+      if (pos % src_lib->page_size != 0)
+        fseek (src_file, src_lib->page_size - pos % src_lib->page_size,
+               SEEK_CUR);
+    }
+  if (dst_lib != NULL)
+    {
+      /* Don't use PUBDEF for the module name for modules that contain
+         only an alias or an import definition. */
+
+      if (state != OS_SIMPLE)
+        {
+          if (caller_name[0] != 0)
+            strcpy (buf2, caller_name);
+          else if (libmod_name[0] != 0)
+            strcpy (buf2, libmod_name);
+          else
+            strcpy (buf2, theadr_name);
+          strcat (buf2, "!");
+          if (omflib_add_pub (dst_lib, buf2, page, error) != 0)
+            return -1;
+        }
+      if (dst_file != NULL
+          && omflib_pad (dst_file, dst_lib->page_size, FALSE, error) != 0)
+        return -1;
+    }
+  return 0;
+  
+failure_src:
+  if (ferror (src_file))
+    return omflib_set_error (error);
+  strcpy (error, "Unexpected end of file");
+  return -1;
+}
+
+
+static int add_pubdef (const char *name, char *error)
+{
+  return omflib_add_pub (pubdef_dst_lib, name, pubdef_page, error);
+}
Index: trunk/src/emx/src/lib/omflib/omflibcr.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibcr.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibcr.c	(revision 18)
@@ -0,0 +1,285 @@
+/* omflibcr.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Create a new OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+struct omflib *omflib_create (const char *fname, int page_size, char *error)
+{
+  struct omflib *p;
+  FILE *f;
+
+  if (page_size < 16 || page_size > 32768
+      || (page_size & (page_size - 1)) != 0)
+    {
+      strcpy (error, "Invalid page size");
+      return NULL;
+    }
+  f = fopen (fname, "wb");
+  if (f == NULL)
+    {
+      strcpy (error, strerror (errno));
+      return NULL;
+    }
+  p = malloc (sizeof (struct omflib));
+  if (p == NULL)
+    {
+      errno = ENOMEM;
+      strcpy (error, strerror (errno));
+      fclose (f);
+      remove (fname);
+      return NULL;
+    }
+  p->f = f;
+  p->page_size = page_size;
+  p->dict_offset = 0;
+  p->dict_blocks = 0;
+  p->flags = 1;
+  p->mod_tab = NULL;
+  p->mod_alloc = 0;
+  p->mod_count = -1;
+  p->dict = NULL;
+  p->pub_tab = NULL;
+  p->pub_alloc = 0;
+  p->pub_count = 0;
+  p->output = TRUE;
+  p->state = OS_EMPTY;
+  p->mod_page = 0;
+  p->mod_name[0] = 0;
+  return p;
+}
+
+
+int omflib_header (struct omflib *p, char *error)
+{
+  fseek (p->f, 0, SEEK_SET);
+  return omflib_pad (p->f, p->page_size, TRUE, error);
+}
+
+
+static int omflib_add_dict (struct omflib *p, const char *name, int page,
+                            char *error)
+{
+  int block_index, bucket_index;
+  int bv, len, bucket_count;
+  byte *block, *ptr;
+  byte buf[257];
+  int (*compare)(const void *s1, const void *s2, size_t n);
+
+  len = strlen (name);
+  if (len > 255)
+    {
+      strcpy (error, "Symbol name too long");
+      return -1;
+    }
+  buf[0] = (byte)len;
+  memcpy (buf+1, name, len);
+  omflib_hash (p, buf);
+  block_index = p->block_index;
+  bucket_index = p->bucket_index;
+  compare = (p->flags & 1 ? memcmp : memicmp);
+  bucket_count = 37;
+  block = p->dict + 512 * block_index;
+  for (;;)
+    {
+      bv = block[bucket_index];
+      if (bv == 0)
+        {
+          if (block[37] == 0xff)
+            bucket_count = 0;
+          else if (2 * block[37] + len + 4 > 512)
+            {
+              block[37] = 0xff;
+              bucket_count = 0;
+            }
+          else
+            {
+              block[bucket_index] = block[37];
+              ptr = block + 2 * block[37];
+              memcpy (ptr, buf, len+1);
+              ptr[len+1] = (byte)page;
+              ptr[len+2] = (byte)(page >> 8);
+              block[37] = (2 * block[37] + len + 3 + 1) / 2;
+              if (block[37] == 0) block[37] = 0xff;
+              return 0;
+            }
+        }
+      else
+        {
+          ptr = block + 2 * bv;
+          if (*ptr == len && compare (ptr+1, buf+1, len) == 0)
+            {
+              strcpy (error, "Symbol multiply defined: ");
+              strcat (error, name);
+              return -1;
+            }
+        }
+      if (bucket_count != 0)
+        {
+          bucket_index += p->bucket_index_delta;
+          if (bucket_index >= 37)
+            bucket_index -= 37;
+          --bucket_count;
+        }
+      if (bucket_count == 0)
+        {
+          block_index += p->block_index_delta;
+          if (block_index >= p->dict_blocks)
+            block_index -= p->dict_blocks;
+          if (block_index == p->block_index)
+            return 1;
+          bucket_count = 37;
+          block = p->dict + 512 * block_index;
+        }
+    }
+}
+
+
+static int omflib_build_dict (struct omflib *p, char *error)
+{
+  int i, ret;
+
+  p->dict = realloc (p->dict, p->dict_blocks * 512);
+  if (p->dict == NULL)
+    {
+      errno = ENOMEM;
+      return omflib_set_error (error);
+    }
+  memset (p->dict, 0, p->dict_blocks * 512);
+  for (i = 0; i < p->dict_blocks; ++i)
+    p->dict[i * 512 + 37] = 38 / 2;
+  for (i = 0; i < p->pub_count; ++i)
+    {
+      ret = omflib_add_dict (p, p->pub_tab[i].name, p->pub_tab[i].page, error);
+      if (ret != 0)
+        return ret;
+    }
+  return 0;
+}
+
+
+static unsigned isqrt (unsigned x)
+{
+  unsigned a, r, e, i;
+
+  a = r = e = 0;
+  for (i = 0; i < 32 / 2; ++i)
+    {
+      r = (r << 2) | (x >> (32-2));
+      x <<= 2; a <<= 1;
+      e = (a << 1) | 1;
+      if (r >= e)
+        {
+          r -= e;
+          a |= 1;
+        }
+    }
+  return a;
+}
+
+
+/* Speed doesn't matter here. */
+
+static int is_prime (unsigned n)
+{
+  unsigned i, q;
+
+  q = isqrt (n);
+  for (i = 3; i <= q; i += 2)
+    if (n % i == 0)
+      return 0;
+  return 1;
+}
+
+
+static unsigned next_prime (unsigned n)
+{
+  if (n <= 1)
+    return 2;
+  if (n % 2 == 0)
+    --n;
+  do
+    {
+      n += 2;
+    } while (!is_prime (n));
+  return n;
+}
+
+
+int omflib_finish (struct omflib *p, char *error)
+{
+  struct lib_header hdr;
+  int len, i, blocks;
+  unsigned prime;
+  long pos;
+  struct omf_rec rec;
+
+  if (!p->output)
+    return 0;
+  len = 0;
+  for (i = 0; i < p->pub_count; ++i)
+    len += strlen (p->pub_tab[i].name) + 3;
+  blocks = (len + 511) / 512;
+  blocks += (blocks * 128) / 512;
+  ++blocks;
+  prime = blocks;
+  for (;;)
+    {
+      prime = next_prime (prime);
+      if (prime > 65535)
+        {
+          strcpy (error, "Too many dictionary blocks");
+          return -1;
+        }
+      p->dict_blocks = prime;
+      i = omflib_build_dict (p, error);
+      if (i < 0)
+        return i;
+      if (i == 0)
+        break;
+    }
+  pos = ftell (p->f) + 3;
+  rec.rec_type = LIBEND;
+  if ((pos & 511) == 0)
+    rec.rec_len = 0;
+  else
+    rec.rec_len = (word)(((pos | 511) + 1) - pos);
+  if (fwrite (&rec, sizeof (rec), 1, p->f) != 1)
+    return omflib_set_error (error);
+  if (omflib_pad (p->f, 512, FALSE, error) != 0)
+    return -1;
+  hdr.rec_type = LIBHDR;
+  hdr.rec_len = p->page_size - 3;
+  hdr.dict_offset = ftell (p->f);
+  hdr.dict_blocks = p->dict_blocks;
+  hdr.flags = (byte)p->flags;
+  fseek (p->f, 0, SEEK_SET);
+  if (fwrite (&hdr, sizeof (hdr), 1, p->f) != 1)
+    return omflib_set_error (error);
+  fseek (p->f, hdr.dict_offset, SEEK_SET);
+  if (fwrite (p->dict, 512, p->dict_blocks, p->f) != p->dict_blocks)
+    return omflib_set_error (error);
+  return 0;
+}
+
+
+int omflib_pad (FILE *f, int size, int force, char *error)
+{
+  long pos;
+
+  pos = ftell (f);
+  while ((pos & (size-1)) != 0 || force)
+    {
+      force = FALSE;
+      if (fputc (0, f) != 0)
+        return omflib_set_error (error);
+      ++pos;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/omflib/omflibdl.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibdl.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibdl.c	(revision 18)
@@ -0,0 +1,31 @@
+/* omflibdl.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+/* Mark a module of an OMFLIB as deleted. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+int omflib_mark_deleted (struct omflib *p, const char *name, char *error)
+{
+  char buf[256];
+  int (*compare)(const char *s1, const char *s2);
+  int i;
+
+  if (p->mod_count == -1 && omflib_make_mod_tab (p, error) != 0)
+    return -1;
+  omflib_module_name (buf, name);
+  compare = (p->flags & 1 ? strcmp : stricmp);
+  for (i = 0; i < p->mod_count; ++i)
+    if (compare (p->mod_tab[i].name, buf) == 0)
+      {
+        p->mod_tab[i].flags |= FLAG_DELETED;
+        return 0;
+      }
+  strcpy (error, "Module not found: ");
+  strcat (error, buf);
+  return 0;
+}
Index: trunk/src/emx/src/lib/omflib/omflibex.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibex.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibex.c	(revision 18)
@@ -0,0 +1,41 @@
+/* omflibex.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+/* Extract a module of an OMFLIB into an OBJ file. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+int omflib_extract (struct omflib *p, const char *name, char *error)
+{
+  char buf[256+4];
+  int page;
+  FILE *f;
+
+  if (p->dict == NULL && omflib_read_dictionary (p, error) != 0)
+    return -1;
+  page = omflib_find_module (p, name, error);
+  if (page == 0)
+    {
+      strcpy (error, "Module not found");
+      return -1;
+    }
+  _strncpy (buf, name, 255);
+  _defext (buf, "obj");
+  f = fopen (buf, "wb");
+  if (f == NULL)
+    return omflib_set_error (error);
+  fseek (p->f, page * p->page_size, SEEK_SET);
+  if (omflib_copy_module (NULL, f, p, p->f, NULL, error) != 0)
+    {
+      fclose (f);
+      remove (buf);
+      return -1;
+    }
+  if (fflush (f) != 0 || fclose (f) != 0)
+    return omflib_set_error (error);
+  return 0;
+}
Index: trunk/src/emx/src/lib/omflib/omflibpb.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibpb.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibpb.c	(revision 18)
@@ -0,0 +1,181 @@
+/* omflibpb.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+/* Call a function for all the PUBDEF, IMPDEF, and ALIAS records of an
+   OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+static int omflib_get_index (struct ptr *p, int *dst, char *error);
+
+
+int omflib_pubdef_walk (struct omflib *p, word page,
+                        int (*walker)(const char *name, char *error),
+                        char *error)
+{
+  struct omf_rec rec;
+  byte buf[1024];
+  int ret;
+
+  fseek (p->f, page * p->page_size, SEEK_SET);
+  do
+    {
+      if (fread (&rec, sizeof (rec), 1, p->f) != 1)
+        goto failure;
+      if (rec.rec_len > sizeof (buf))
+        {
+          strcpy (error, "Record too long");
+          return -1;
+        }
+      if (fread (buf, rec.rec_len, 1, p->f) != 1)
+        goto failure;
+      if (rec.rec_type == PUBDEF || rec.rec_type == (PUBDEF|REC32))
+        {
+          ret = omflib_pubdef (&rec, buf, page, walker, error);
+          if (ret != 0) return ret;
+        }
+      else if (rec.rec_type == ALIAS)
+        {
+          ret = omflib_alias (&rec, buf, page, walker, error);
+          if (ret != 0) return ret;
+        }
+      else if (rec.rec_type == COMENT && rec.rec_len >= 2 &&
+               buf[1] == IMPDEF_CLASS && buf[2] == IMPDEF_SUBTYPE)
+        {
+          ret = omflib_impdef (&rec, buf, page, walker, error);
+          if (ret != 0) return ret;
+        }
+    } while (rec.rec_type != MODEND && rec.rec_type != (MODEND|REC32));
+  return 0;
+
+failure:
+  if (ferror (p->f))
+    return omflib_set_error (error);
+  strcpy (error, "Unexpected end of file");
+  return -1;
+}
+
+
+int omflib_pubdef (struct omf_rec *rec, byte *buf, word page,
+                   int (*walker)(const char *name, char *error),
+                   char *error)
+{
+  int group_index, segment_index, type_index;
+  struct ptr ptr;
+  int len, i, ret;
+  char name[256];
+
+  ptr.ptr = buf;
+  ptr.len = rec->rec_len - 1;
+  if (omflib_get_index (&ptr, &group_index, error) != 0)
+    return -1;
+  if (omflib_get_index (&ptr, &segment_index, error) != 0)
+    return -1;
+  if (segment_index == 0)
+    {
+      if (ptr.len < 2)
+        goto too_short;
+      ptr.ptr += 2; ptr.len -= 2;
+    }
+
+  while (ptr.len > 0)
+    {
+      if (ptr.len < 1)
+        goto too_short;
+      len = ptr.ptr[0];
+      ++ptr.ptr; --ptr.len;
+      if (ptr.len < len)
+        goto too_short;
+      memcpy (name, ptr.ptr, len);
+      name[len] = 0;
+      ptr.ptr += len; ptr.len -= len;
+      i = (rec->rec_type == (PUBDEF|REC32) ? 4 : 2);
+      if (ptr.len < i) goto too_short;
+      ptr.ptr += i; ptr.len -= i;
+      if (omflib_get_index (&ptr, &type_index, error) != 0)
+        return -1;
+      ret = walker (name, error);
+      if (ret != 0) return ret;
+    }
+  if (ptr.len != 0)
+    {
+      strcpy (error, "Invalid PUBDEF record");
+      return -1;
+    }
+  return 0;
+
+too_short:
+  strcpy (error, "PUBDEF record too short");
+  return -1;
+}
+
+
+int omflib_impdef (struct omf_rec *rec, byte *buf, word page,
+                   int (*walker)(const char *name, char *error),
+                   char *error)
+{
+  int len;
+  char name[256];
+
+  if (rec->rec_len < 5) goto too_short;
+  len = buf[4];
+  if (len + 5 > rec->rec_len) goto too_short;
+  memcpy (name, buf+5, len);
+  name[len] = 0;
+  return walker (name, error);
+
+too_short:
+  strcpy (error, "IMPDEF record too short");
+  return -1;
+}
+
+
+int omflib_alias (struct omf_rec *rec, byte *buf, word page,
+                  int (*walker)(const char *name, char *error),
+                  char *error)
+{
+  int len;
+  char name[256];
+
+  if (rec->rec_len < 1) goto too_short;
+  len = buf[0];
+  if (len + 2 > rec->rec_len) goto too_short;
+  memcpy (name, buf+1, len);
+  name[len] = 0;
+  return walker (name, error);
+
+too_short:
+  strcpy (error, "ALIAS record too short");
+  return -1;
+}
+
+
+static int omflib_get_index (struct ptr *p, int *dst, char *error)
+{
+  if (p->len < 1)
+    goto too_short;
+  if (p->ptr[0] <= 0x7f)
+    {
+      *dst = p->ptr[0];
+      ++p->ptr;
+      --p->len;
+      return 0;
+    }
+  else if (p->len < 2)
+    goto too_short;
+  else
+    {
+      *dst = ((p->ptr[0] & 0x7f) << 8) | p->ptr[1];
+      p->ptr += 2;
+      p->len -= 2;
+      return 0;
+    }
+
+too_short:
+  strcpy (error, "Record too short");
+  return -1;
+}
Index: trunk/src/emx/src/lib/omflib/omflibrd.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibrd.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibrd.c	(revision 18)
@@ -0,0 +1,261 @@
+/* omflibrd.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Read an OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+struct omflib *omflib_open (const char *fname, char *error)
+{
+  FILE *f;
+  struct omflib *p;
+  struct lib_header hdr;
+
+  f = fopen (fname, "rb");
+  if (f == NULL)
+    goto failure;
+  if (fread (&hdr, sizeof (hdr), 1, f) != 1)
+    {
+      if (ferror (f))
+        goto failure;
+      strcpy (error, "Invalid library header");
+      fclose (f);
+      return NULL;
+    }
+  if (hdr.rec_type != LIBHDR || hdr.rec_len < 7)
+    {
+      strcpy (error, "Invalid library header");
+      fclose (f);
+      return NULL;
+    }
+  p = malloc (sizeof (struct omflib));
+  if (p == NULL)
+    {
+      errno = ENOMEM;
+      goto failure;
+    }
+  p->f = f;
+  p->page_size = hdr.rec_len + 3;
+  p->dict_offset = hdr.dict_offset;
+  p->dict_blocks = hdr.dict_blocks;
+  p->flags = hdr.flags;
+  p->mod_tab = NULL;
+  p->mod_alloc = 0;
+  p->mod_count = -1;
+  p->dict = NULL;
+  p->pub_tab = NULL;
+  p->pub_alloc = 0;
+  p->pub_count = 0;
+  p->output = FALSE;
+  p->state = OS_EMPTY;
+  p->mod_page = 0;
+  p->mod_name[0] = 0;
+  return p;
+
+failure:
+  strcpy (error, strerror (errno));
+  if (f != NULL)
+    fclose (f);
+  return NULL;
+}
+
+
+int omflib_read_dictionary (struct omflib *p, char *error)
+{
+  if (p->output)
+    {
+      strcpy (error, "Not implemented for output library");
+      return -1;
+    }
+  p->dict = malloc (512 * p->dict_blocks);
+  if (p->dict == NULL)
+    {
+      errno = ENOMEM;
+      return omflib_set_error (error);
+    }
+  fseek (p->f, p->dict_offset, SEEK_SET);
+  if (fread (p->dict, 512, p->dict_blocks, p->f) != p->dict_blocks)
+    {
+      if (ferror (p->f))
+        strcpy (error, strerror (errno));
+      else
+        strcpy (error, "Dictionary truncated");
+      free (p->dict);
+      p->dict = NULL;
+      return -1;
+    }
+  return 0;
+}
+
+
+static int mod_compare (const void *x1, const void *x2)
+{
+  word page1, page2;
+
+  page1 = ((const struct omfmod *)x1)->page;
+  page2 = ((const struct omfmod *)x2)->page;
+  if (page1 < page2)
+    return -1;
+  else if (page1 > page2)
+    return 1;
+  else
+    return 0;
+}
+
+
+int omflib_make_mod_tab (struct omflib *p, char *error)
+{
+  int block, bucket, bv, len;
+  char string[256];
+  struct omfmod *mod;
+  byte *d, *s;
+
+  if (p->dict == NULL && omflib_read_dictionary (p, error) != 0)
+    return -1;
+  p->mod_count = 0;
+  d = p->dict;
+  for (block = 0; block < p->dict_blocks; ++block, d += 512)
+    for (bucket = 0; bucket < 37; ++bucket)
+      {
+        bv = d[bucket];
+        if (bv != 0)
+          {
+            s = d + bv * 2;
+            len = *s;
+            if (s[len] == '!')
+              {
+                memcpy (string, s+1, len-1);
+                string[len-1] = 0;
+                if (p->mod_count >= p->mod_alloc)
+                  {
+                    p->mod_alloc += 16;
+                    p->mod_tab = realloc (p->mod_tab, p->mod_alloc
+                                          * sizeof (struct omfmod));
+                    if (p->mod_tab == NULL)
+                      {
+                        p->mod_count = -1;
+                        p->mod_alloc = 0;
+                        errno = ENOMEM;
+                        return omflib_set_error (error);
+                      }
+                  }
+                mod = &p->mod_tab[p->mod_count];
+                mod->page = s[len+1] | (s[len+2] << 8);
+                mod->name = strdup (string);
+                mod->flags = 0;
+                if (mod->name == NULL)
+                  {
+                    errno = ENOMEM;
+                    return omflib_set_error (error);
+                  }
+                ++p->mod_count;
+              }
+          }
+      }
+  qsort (p->mod_tab, p->mod_count, sizeof (p->mod_tab[0]), mod_compare);
+  return 0;
+}
+
+
+int omflib_module_count (struct omflib *p, char *error)
+{
+  if (p->mod_count == -1 && omflib_make_mod_tab (p, error) != 0)
+    return -1;
+  return p->mod_count;
+}
+
+
+int omflib_module_info (struct omflib *p, int n, char *name, int *page,
+                        char *error)
+{
+  if (p->mod_count == -1 && omflib_make_mod_tab (p, error) != 0)
+      return -1;
+  if (n < 0 || n >= p->mod_count)
+    {
+      strcpy (error, "Module number out of range");
+      return -1;
+    }
+  strcpy (name, p->mod_tab[n].name);
+  *page = p->mod_tab[n].page;
+  return 0;
+}
+
+
+int omflib_find_symbol (struct omflib *p, const char *name, char *error)
+{
+  int block_index, bucket_index;
+  int bv, len, bucket_count;
+  byte *ptr, *block, buf[257];
+  int (*compare)(const void *s1, const void *s2, size_t n);
+
+  if (p->dict == NULL && omflib_read_dictionary (p, error) != 0)
+    return -1;
+  len = strlen (name);
+  if (len > 255)
+    {
+      strcpy (error, "Symbol name too long");
+      return -1;
+    }
+  buf[0] = (byte)len;
+  memcpy (buf+1, name, len);
+  omflib_hash (p, buf);
+  block_index = p->block_index;
+  bucket_index = p->bucket_index;
+  bucket_count = 37;
+  compare = (p->flags & 1 ? memcmp : memicmp);
+  for (;;)
+    {
+      block = p->dict + 512 * block_index;
+      bv = block[bucket_index];
+      if (bv == 0)
+        {
+          if (block[37] != 0xff)
+            return 0;
+          bucket_count = 0;     /* Keep bucket_index! */
+        }
+      else
+        {
+          ptr = block + 2 * bv;
+          if (*ptr == len && compare (ptr+1, buf+1, len) == 0)
+            return ptr[len+1] + (ptr[len+2] << 8);
+          bucket_index += p->bucket_index_delta;
+          if (bucket_index >= 37)
+            bucket_index -= 37;
+          --bucket_count;
+        }
+      if (bucket_count == 0)
+        {
+          block_index += p->block_index_delta;
+          if (block_index >= p->dict_blocks)
+            block_index -= p->dict_blocks;
+          if (block_index == p->block_index)
+            return 0;
+          bucket_count = 37;
+        }
+    }
+}
+
+
+int omflib_find_module (struct omflib *p, const char *name, char *error)
+{
+  char buf[256+1];
+
+  if (omflib_module_name (buf, name) != 0)
+    {
+      strcpy (error, "Module name too long");
+      return -1;
+    }
+  strcat (buf, "!");
+  return omflib_find_symbol (p, buf, error);
+}
+
+
+long omflib_page_pos (struct omflib *p, int page)
+{
+  return page * p->page_size;
+}
Index: trunk/src/emx/src/lib/omflib/omflibut.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibut.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibut.c	(revision 18)
@@ -0,0 +1,100 @@
+/* omflibut.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Utility functions for dealing with OMFLIBs. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+int omflib_set_error (char *error)
+{
+  strcpy (error, strerror (errno));
+  return -1;
+}
+
+
+int omflib_close (struct omflib *p, char *error)
+{
+  int i;
+
+  fclose (p->f);
+  if (p->dict != NULL)
+    free (p->dict);
+  if (p->mod_tab != NULL)
+    {
+      for (i = 0; i < p->mod_count; ++i)
+        free (p->mod_tab[i].name);
+      free (p->mod_tab);
+    }
+  if (p->pub_tab != NULL)
+    {
+      for (i = 0; i < p->pub_count; ++i)
+        free (p->pub_tab[i].name);
+      free (p->pub_tab);
+    }
+  free (p);
+  return 0;
+}
+
+
+#define ROL2(x) (((unsigned)(x) << 2) | ((unsigned)(x) >> 14))
+#define ROR2(x) (((unsigned)(x) >> 2) | ((unsigned)(x) << 14))
+
+void omflib_hash (struct omflib *p, const byte *name)
+{
+  int i, len;
+  word block_index, bucket_index, block_index_delta, bucket_index_delta;
+  byte c;
+
+  len = name[0];
+  block_index = 0;
+  block_index_delta = 0;
+  bucket_index = 0;
+  bucket_index_delta = 0;
+  for (i = 0; i < len; ++i)
+    {
+      c = name[i] | 0x20;
+      block_index = ROL2 (block_index) ^ c;
+      bucket_index_delta = ROR2 (bucket_index_delta) ^ c;
+      c = name[len-i] | 0x20;
+      bucket_index = ROR2 (bucket_index) ^ c;
+      block_index_delta = ROL2 (block_index_delta) ^ c;
+    }
+  p->block_index = block_index % p->dict_blocks;
+  p->block_index_delta = block_index_delta % p->dict_blocks;
+  if (p->block_index_delta == 0)
+    p->block_index_delta = 1;
+  p->bucket_index = bucket_index % 37;
+  p->bucket_index_delta = bucket_index_delta % 37;
+  if (p->bucket_index_delta == 0)
+    p->bucket_index_delta = 1;
+}
+
+
+int omflib_module_name (char *dst, const char *src)
+{
+  const char *base;
+  char *s;
+  int len;
+
+  base = _getname (src);
+  s = strchr (base, '.');
+  if (s != NULL)
+    len = s - base;
+  else
+    len = strlen (base);
+  if (len > 255)
+    {
+      memcpy (dst, base, 255);
+      dst[255] = 0;
+      return -1;
+    }
+  else
+    {
+      memcpy (dst, base, len);
+      dst[len] = 0;
+      return 0;
+    }
+}
Index: trunk/src/emx/src/lib/omflib/omflibwr.c
===================================================================
--- trunk/src/emx/src/lib/omflib/omflibwr.c	(revision 18)
+++ trunk/src/emx/src/lib/omflib/omflibwr.c	(revision 18)
@@ -0,0 +1,102 @@
+/* omflibwr.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Write an OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+int omflib_write_record (struct omflib *p, byte rec_type, word rec_len,
+                         const byte *buffer, int chksum, char *error)
+{
+  struct omf_rec rec;
+  byte sum;
+  int i, len;
+  char name[256];
+
+  rec.rec_type = rec_type;
+  rec.rec_len = (chksum ? rec_len + 1 : rec_len);
+  if (fwrite (&rec, sizeof (rec), 1, p->f) != 1
+      || fwrite (buffer, rec_len, 1, p->f) != 1)
+    return omflib_set_error (error);
+  if (chksum)
+    {
+      sum = rec_type + (rec.rec_len & 0xff) + (rec.rec_len >> 8);
+      for (i = 0; i < rec_len; ++i)
+        sum += buffer[i];
+      sum = (byte)(256 - sum);
+      if (fputc (sum, p->f) == EOF)
+        return omflib_set_error (error);
+    }
+  switch (rec_type)
+    {
+    case MODEND:
+    case MODEND|REC32:
+      if (omflib_pad (p->f, p->page_size, FALSE, error) != 0)
+        return -1;
+      if (p->state != OS_SIMPLE)
+        {
+          len = strlen (p->mod_name);
+          if (len < 255)
+            {
+              memcpy (name, p->mod_name, len);
+              name[len] = '!';
+              name[len+1] = 0;
+              if (omflib_add_pub (p, name, p->mod_page, error) != 0)
+                return -1;
+            }
+        }
+      break;
+
+    case THEADR:
+      p->state = OS_EMPTY;
+      break;
+
+    case ALIAS:
+      p->state = (p->state == OS_EMPTY ? OS_SIMPLE : OS_OTHER);
+      break;
+
+    case COMENT:
+      if (p->state == OS_EMPTY && rec_len >= 3
+          && buffer[1] == IMPDEF_CLASS && buffer[2] == IMPDEF_SUBTYPE)
+        p->state = OS_SIMPLE;
+      else
+        p->state = OS_OTHER;
+      break;
+
+    default:
+      p->state = OS_OTHER;
+      break;
+    }
+  return 0;
+}
+
+
+int omflib_write_module (struct omflib *p, const char *name, word *pagep,
+                         char *error)
+{
+  byte buf[256];
+  long long_page;
+  int len;
+
+  p->state = OS_EMPTY;
+  if (omflib_module_name (p->mod_name, name) != 0)
+    {
+      strcpy (error, "Module name too long");
+      return -1;
+    }
+  long_page = ftell (p->f) / p->page_size;
+  if (long_page > 65535)
+    {
+      strcpy (error, "Library too big -- increase page size");
+      return -1;
+    }
+  *pagep = p->mod_page = (word)long_page;
+  len = strlen (name);
+  memcpy (buf+1, name, len);
+  buf[0] = (byte)len;
+  return omflib_write_record (p, THEADR, len + 1, buf, TRUE, error);
+}
Index: trunk/src/emx/src/lib/os2_386/code2.s
===================================================================
--- trunk/src/emx/src/lib/os2_386/code2.s	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/code2.s	(revision 18)
@@ -0,0 +1,24 @@
+/ code2.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  _DosGetMessage
+        .globl  __msgseg32
+
+__msgseg32:
+        .byte   0xff
+        .asciz  "MSGSEG32"
+        .byte   0x01, 0x80, 0x00, 0x00
+        .long   L_tab
+
+        .align  2, 0x90
+
+_DosGetMessage:
+        PROFILE_NOFRAME
+        popl    %ecx                    /* return address */
+        pushl   $__msgseg32
+        pushl   %ecx
+        jmp     _DosTrueGetMessage
+
+L_tab:  .short  0x0000
+        .short  0xffff
Index: trunk/src/emx/src/lib/os2_386/code3.s
===================================================================
--- trunk/src/emx/src/lib/os2_386/code3.s	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/code3.s	(revision 18)
@@ -0,0 +1,16 @@
+/ code3.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  _DosQueryMessageCP
+
+_DosQueryMessageCP:
+        PROFILE_NOFRAME
+        pushl   0(%esp)
+        movl    $__msgseg32, %eax
+        xchgl   20(%esp), %eax
+        xchgl   16(%esp), %eax
+        xchgl   12(%esp), %eax
+        xchgl   8(%esp), %eax
+        movl    %eax, 4(%esp)
+        jmp     _DosIQueryMessageCP
Index: trunk/src/emx/src/lib/os2_386/ctls.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/ctls.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/ctls.imp	(revision 18)
@@ -0,0 +1,9 @@
+;
+; ctls.imp
+;
+WinDefFileDlgProc               pmctls  5 4
+WinDefFontDlgProc               pmctls  3 4
+WinFileDlg                      pmctls  4 3
+WinFontDlg                      pmctls  2 3
+WinFreeFileDlgList              pmctls  6 1
+WinRegisterCircularSlider       pmctls 24 ?
Index: trunk/src/emx/src/lib/os2_386/dos.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/dos.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/dos.imp	(revision 18)
@@ -0,0 +1,195 @@
+;
+; dos.imp
+;
+DosAcknowledgeSignalException   doscalls 418 1
+DosAddMuxWaitSem                doscalls 341 2
+DosAllocMem                     doscalls 299 3
+DosAllocSharedMem               doscalls 300 4
+DosAllocThreadLocalMemory       doscalls 454 2
+DosAsyncTimer                   doscalls 350 3
+DosBeep                         doscalls 286 2
+DosCallNPipe                    doscalls 240 7
+DosCancelLockRequest            doscalls 429 2
+DosClose                        doscalls 257 1
+DosCloseChangeNotify            doscalls 442 ?
+DosCloseEventSem                doscalls 326 1
+DosCloseMutexSem                doscalls 333 1
+DosCloseMuxWaitSem              doscalls 339 1
+DosCloseVDD                     doscalls 310 1
+DosConnectNPipe                 doscalls 241 1
+DosCopy                         doscalls 258 3
+DosCreateDir                    doscalls 270 2
+DosCreateEventSem               doscalls 324 4
+DosCreateMutexSem               doscalls 331 4
+DosCreateMuxWaitSem             doscalls 337 5
+DosCreateNPipe                  doscalls 243 7
+DosCreatePipe                   doscalls 239 3
+DosCreateThread                 doscalls 311 5
+DosDebug                        doscalls 317 1
+DosDelete                       doscalls 259 1
+DosDeleteDir                    doscalls 226 1
+DosDeleteMuxWaitSem             doscalls 342 2
+DosDevConfig                    doscalls 231 2
+DosDevIOCtl                     doscalls 284 9
+DosDisConnectNPipe              doscalls 242 1
+DosDumpProcess                  doscalls 113 3
+DosDupHandle                    doscalls 260 2
+DosDynamicTrace                 doscalls 316 ?
+DosEditName                     doscalls 261 5
+DosEnterCritSec                 doscalls 232 0
+DosEnterMustComplete            doscalls 380 1
+DosEnumAttribute                doscalls 372 7
+DosErrClass                     doscalls 211 4
+DosError                        doscalls 212 1
+DosExecPgm                      doscalls 283 7
+DosExit                         doscalls 234 2
+DosExitCritSec                  doscalls 233 0
+DosExitList                     doscalls 296 2
+DosExitMustComplete             doscalls 381 1
+DosFlatToSel                    doscalls 425 R
+DosFreeThreadLocalMemory        doscalls 455 1
+DosFSAttach                     doscalls 269 5
+DosFSCtl                        doscalls 285 10
+DosFindClose                    doscalls 263 1
+DosFindFirst                    doscalls 264 7
+DosFindNext                     doscalls 265 4
+DosForceDelete                  doscalls 110 1
+DosForceSystemDump              doscalls 444 1
+DosFreeMem                      doscalls 304 1
+DosFreeModule                   doscalls 322 1
+DosFreeResource                 doscalls 353 1
+DosGetDateTime                  doscalls 230 1
+DosGetInfoBlocks                doscalls 312 2
+DosGetNamedSharedMem            doscalls 301 3
+DosGetResource                  doscalls 352 4
+DosGetSharedMem                 doscalls 302 2
+DosGiveSharedMem                doscalls 303 3
+DosInitializePorthole           doscalls 580 ?
+DosKillProcess                  doscalls 235 2
+DosKillThread                   doscalls 111 1
+DosLoadModule                   doscalls 318 4
+DosMove                         doscalls 271 2
+DosOpen                         doscalls 273 8
+DosOpenChangeNotify             doscalls 440 ?
+DosOpenEventSem                 doscalls 325 2
+DosOpenMutexSem                 doscalls 332 2
+DosOpenMuxWaitSem               doscalls 338 2
+DosOpenVDD                      doscalls 308 2
+DosPM16SemChk                   doscalls 596 ?
+DosPM16SemRst                   doscalls 875 ?
+DosPMPostEventSem               doscalls 590 ?
+DosPMRequestMutexSem            doscalls 593 ?
+DosPMWaitEventSem               doscalls 591 ?
+DosPMWaitMuxWaitSem             doscalls 595 ?
+DosPeekNPipe                    doscalls 244 6
+DosPhysicalDisk                 doscalls 287 5
+DosPostEventSem                 doscalls 328 1
+DosProfile                      doscalls 377 4
+DosProtectClose                 doscalls 638 2
+DosProtectEnumAttribute         doscalls 636 8
+DosProtectOpen                  doscalls 637 9
+DosProtectQueryFHState          doscalls 645 3
+DosProtectQueryFileInfo         doscalls 646 5
+DosProtectRead                  doscalls 641 5
+DosProtectSetFHState            doscalls 644 3
+DosProtectSetFileInfo           doscalls 643 5
+DosProtectSetFileLocks          doscalls 639 6
+DosProtectSetFilePtr            doscalls 621 5
+DosProtectSetFileSize           doscalls 640 3
+DosProtectWrite                 doscalls 642 5
+DosQueryABIOSSupport            doscalls 371 0
+DosQueryAppType                 doscalls 323 2
+DosQueryCp                      doscalls 291 3
+DosQueryCurrentDir              doscalls 274 3
+DosQueryCurrentDisk             doscalls 275 2
+DosQueryDOSProperty             doscalls 373 4
+DosQueryEventSem                doscalls 330 2
+DosQueryExtLIBPATH              doscalls 874 2
+DosQueryFHState                 doscalls 276 2
+DosQueryFSAttach                doscalls 277 5
+DosQueryFSInfo                  doscalls 278 4
+DosQueryFileInfo                doscalls 279 4
+DosQueryHeaderInfo              doscalls 582 ?
+DosQueryHType                   doscalls 224 3
+DosQueryMem                     doscalls 306 3
+DosQueryModFromEIP              doscalls 360 6
+DosQueryModuleHandle            doscalls 319 2
+DosQueryModuleName              doscalls 320 3
+DosQueryMutexSem                doscalls 336 4
+DosQueryMuxWaitSem              doscalls 343 4
+DosQueryNPHState                doscalls 245 2
+DosQueryNPipeInfo               doscalls 248 4
+DosQueryNPipeSemState           doscalls 249 3
+DosQueryPathInfo                doscalls 223 4
+DosQueryProcAddr                doscalls 321 4
+DosQueryProcType                doscalls 586 4
+DosQueryRASInfo                 doscalls 112 2
+DosQueryResourceSize            doscalls 572 4
+DosQuerySysInfo                 doscalls 348 4
+DosQuerySysState                doscalls 368 6
+DosQueryThreadContext           doscalls 877 3
+DosQueryVerify                  doscalls 225 1
+DosRaiseException               doscalls 356 1
+DosRawReadNPipe                 doscalls 246 4
+DosRawWriteNPipe                doscalls 247 2
+DosRead                         doscalls 281 4
+DosRegisterPerfCtrs             doscalls 367 3
+DosReleaseMutexSem              doscalls 335 1
+DosReplaceModule                doscalls 417 3
+DosRequestMutexSem              doscalls 334 2
+DosRequestVDD                   doscalls 309 7
+DosResetBuffer                  doscalls 254 1
+DosResetChangeNotify            doscalls 441 ?
+DosResetEventSem                doscalls 327 2
+DosResumeThread                 doscalls 237 1
+DosScanEnv                      doscalls 227 2
+DosSearchPath                   doscalls 228 5
+DosSelToFlat                    doscalls 426 R
+DosSendSignalException          doscalls 379 2
+DosSetCp                        doscalls 288 ?
+DosSetCurrentDir                doscalls 255 1
+DosSetDOSProperty               doscalls 374 4
+DosSetDateTime                  doscalls 292 1
+DosSetDefaultDisk               doscalls 220 1
+DosSetExceptionHandler          doscalls 354 1
+DosSetExtLIBPATH                doscalls 873 2
+DosSetFHState                   doscalls 221 2
+DosSetFSInfo                    doscalls 222 4
+DosSetFileInfo                  doscalls 218 4
+DosSetFileLocks                 doscalls 428 5
+DosSetFilePtr                   doscalls 256 4
+DosSetFileSize                  doscalls 272 2
+DosSetMaxFH                     doscalls 209 1
+DosSetMem                       doscalls 305 3
+DosSetNPHState                  doscalls 250 2
+DosSetNPipeSem                  doscalls 251 3
+DosSetPathInfo                  doscalls 219 5
+DosSetProcessCp                 doscalls 289 1
+DosSetRelMaxFH                  doscalls 382 2
+DosSetSignalExceptionFocus      doscalls 378 2
+DosSetVerify                    doscalls 210 1
+DosShutdown                     doscalls 415 1
+DosSleep                        doscalls 229 1
+DosStartTimer                   doscalls 351 3
+DosStopTimer                    doscalls 290 1
+DosSysCtl                       doscalls 876 ?
+DosSubAllocMem                  doscalls 345 3
+DosSubFreeMem                   doscalls 346 3
+DosSubSetMem                    doscalls 344 3
+DosSubUnsetMem                  doscalls 347 1
+DosSuppressPopUps               doscalls 114 2
+DosSuspendThread                doscalls 238 1
+DosTib                          doscalls 419 ?
+DosTmrQueryFreq                 doscalls 362 1
+DosTmrQueryTime                 doscalls 363 1
+DosSetPriority                  doscalls 236 4
+DosTransactNPipe                doscalls 252 6
+DosUnsetExceptionHandler        doscalls 355 1
+DosUnwindException              doscalls 357 3
+DosVerifyPidTid                 doscalls 460 2
+DosWaitChild                    doscalls 280 5
+DosWaitEventSem                 doscalls 329 2
+DosWaitMuxWaitSem               doscalls 340 3
+DosWaitNPipe                    doscalls 253 2
+DosWaitThread                   doscalls 349 2
+DosWrite                        doscalls 282 4
Index: trunk/src/emx/src/lib/os2_386/dos16.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/dos16.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/dos16.imp	(revision 18)
@@ -0,0 +1,182 @@
+;
+; dos16.imp
+;
+Dos16AllocHuge                  doscalls  40 F
+Dos16AllocSeg                   doscalls  34 F
+Dos16AllocShrSeg                doscalls  35 F
+Dos16Beep                       doscalls  50 F
+Dos16BufReset                   doscalls  56 F
+Dos16CLIAccess                  doscalls  51 F
+Dos16CWait                      doscalls   2 F
+Dos16Callback                   doscalls 157 F
+Dos16ChDir                      doscalls  57 F
+Dos16ChgFilePtr                 doscalls  58 F
+Dos16Close                      doscalls  59 F
+Dos16CloseChangeNotify          doscalls 439 F
+Dos16CloseSem                   doscalls  23 F
+Dos16CloseVDD                   doscalls 268 F
+Dos16Copy                       doscalls 201 F
+Dos16CreateCSAlias              doscalls  43 F
+Dos16CreateSem                  doscalls  24 F
+Dos16CreateThread               doscalls 145 F
+Dos16Delete                     doscalls  60 F
+Dos16DevConfig                  doscalls  52 F
+Dos16DevIOCtl                   doscalls  53 F
+Dos16DevIOCtl2                  doscalls  99 F
+Dos16DupHandle                  doscalls  61 F
+Dos16DynamicTrace               doscalls 165 F
+Dos16EditName                   doscalls 191 F
+Dos16EnterCritSec               doscalls   3 F
+Dos16EnumAttribute              doscalls 204 F
+Dos16ErrClass                   doscalls 139 F
+Dos16Error                      doscalls 120 F
+Dos16ExecPgm                    doscalls 144 F
+Dos16Exit                       doscalls   5 F
+Dos16ExitCritSec                doscalls   6 F
+Dos16ExitList                   doscalls   7 F
+Dos16FSAttach                   doscalls 181 F
+Dos16FSCtl                      doscalls 183 F
+Dos16FSRamSemClear              doscalls 162 F
+Dos16FSRamSemRequest            doscalls 161 F
+Dos16FileIO                     doscalls 186 F
+Dos16FileLocks                  doscalls  62 F
+Dos16FindClose                  doscalls  63 F
+Dos16FindFirst                  doscalls  64 F
+Dos16FindFirst2                 doscalls 184 F
+Dos16FindNext                   doscalls  65 F
+Dos16FindNotifyClose            doscalls 187 F
+Dos16FindNotifyFirst            doscalls 188 F
+Dos16FindNotifyNext             doscalls 189 F
+Dos16FlagProcess                doscalls  15 F
+Dos16FlatToSel                  doscalls 423 F
+Dos16ForceDelete                doscalls 203 F
+Dos16FreeModule                 doscalls  46 F
+Dos16FreeResource               doscalls 208 F
+Dos16FreeSeg                    doscalls  39 F
+Dos16GetCp                      doscalls 130 F
+Dos16GetDateTime                doscalls  33 F
+Dos16GetEnv                     doscalls  91 F
+Dos16GetHugeShift               doscalls  41 F
+Dos16GetInfoSeg                 doscalls   8 F
+Dos16GetMachineMode             doscalls  49 F
+Dos16GetModHandle               doscalls  47 F
+Dos16GetModName                 doscalls  48 F
+Dos16GetPID                     doscalls  94 F
+Dos16GetPPID                    doscalls 156 F
+Dos16GetProcAddr                doscalls  45 F
+Dos16GetPrty                    doscalls   9 F
+Dos16GetResource                doscalls 155 F
+Dos16GetResource2               doscalls 207 F
+Dos16GetSeg                     doscalls 121 F
+Dos16GetShrSeg                  doscalls  36 F
+Dos16GetVersion                 doscalls  92 F
+Dos16GiveSeg                    doscalls  37 F
+Dos16GlobalInfo                 doscalls 217 F
+Dos16HoldSignal                 doscalls  13 F
+Dos16HugeIncr                   doscalls 136 F
+Dos16Hugeshift                  doscalls 135 F
+Dos16InitializePortHole         doscalls 583 F
+Dos16KillProcess                doscalls  10 F
+Dos16LibInit                    doscalls  96 F
+Dos16LoadModule                 doscalls  44 F
+Dos16LocalInfo                  doscalls 216 F
+Dos16LockSeg                    doscalls 122 F
+Dos16MakePipe                   doscalls  16 F
+Dos16MaxPathLen                 doscalls 214 F
+Dos16MemAvail                   doscalls 127 F
+Dos16MkDir                      doscalls  66 F
+Dos16MkDir2                     doscalls 185 F
+Dos16Move                       doscalls  67 F
+Dos16MuxSemWait                 doscalls  22 F
+Dos16NewSize                    doscalls  68 F
+Dos16Open                       doscalls  70 F
+Dos16Open2                      doscalls  95 F
+Dos16OpenChangeNotify           doscalls 437 F
+Dos16OpenSem                    doscalls  25 F
+Dos16OpenVDD                    doscalls 266 F
+DOs16PMMuxSemWait               doscalls 575 F
+Dos16PMSemWait                  doscalls 574 F
+Dos16PageSize                   doscalls 215 F
+Dos16PhysicalDisk               doscalls 129 F
+Dos16PortAccess                 doscalls  69 F
+Dos16ProtectChgFilePtr          doscalls 634 F
+Dos16ProtectClose               doscalls 622 F
+Dos16ProtectEnumAttribute       doscalls 635 F
+Dos16ProtectFileLocks           doscalls 624 F
+Dos16ProtectFileio              doscalls 623 F
+Dos16ProtectNewSize             doscalls 627 F
+Dos16ProtectOpen                doscalls 628 F
+Dos16ProtectQFHandState         doscalls 629 F
+Dos16ProtectQFileInfo           doscalls 631 F
+Dos16ProtectSetFHandState       doscalls 630 F
+Dos16ProtectSetFileInfo         doscalls 632 F
+Dos16QAppType                   doscalls 163 F
+Dos16QCurDir                    doscalls  71 F
+Dos16QCurDisk                   doscalls  72 F
+Dos16QFHandState                doscalls  73 F
+Dos16QFSAttach                  doscalls 182 F
+Dos16QFSInfo                    doscalls  76 F
+Dos16QFileInfo                  doscalls  74 F
+Dos16QFileMode                  doscalls  75 F
+Dos16QHandType                  doscalls  77 F
+Dos16QPathInfo                  doscalls  98 F
+Dos16QProcStatus                doscalls 154 F
+Dos16QSysInfo                   doscalls 166 F
+Dos16QVerify                    doscalls  78 F
+Dos16QueryDosProperty           doscalls 375 F
+Dos16QueryExtLIBPATH            doscalls 999 F
+Dos16QueryHeaderInfo            doscalls 584 F
+Dos16QueryResourceSize          doscalls 573 F
+Dos16Queryproctype              doscalls 587 F
+Dos16R2StackRealloc             doscalls 160 F
+Dos16Read                       doscalls 137 F
+Dos16ReadAsync                  doscalls 149 F
+Dos16ReallocHuge                doscalls  42 F
+Dos16ReallocSeg                 doscalls  38 F
+Dos16RegisterPerfCtrs           doscalls 422 F
+Dos16RequestVDD                 doscalls 267 F
+Dos16ResetChangeNotify          doscalls 438 F
+Dos16ResumeThread               doscalls  26 F
+Dos16RmDir                      doscalls  80 F
+Dos16ScanEnv                    doscalls 152 F
+Dos16SearchPath                 doscalls 151 F
+Dos16SelToFlat                  doscalls 424 F
+Dos16SelectDisk                 doscalls  81 F
+Dos16SemClear                   doscalls 141 F
+Dos16SemRequest                 doscalls 140 F
+Dos16SemSet                     doscalls 143 F
+Dos16SemSetWait                 doscalls  20 F
+Dos16SemWait                    doscalls 142 F
+Dos16SendSignal                 doscalls 134 F
+Dos16SetCp                      doscalls 153 F
+Dos16SetDateTime                doscalls  28 F
+Dos16SetDosProperty             doscalls 376 F
+Dos16SetExtLIBPATH              doscalls 998 F
+Dos16SetFHandState              doscalls  82 F
+Dos16SetFSInfo                  doscalls  97 F
+Dos16SetFileInfo                doscalls  83 F
+Dos16SetFileMode                doscalls  84 F
+Dos16SetMaxFH                   doscalls  85 F
+Dos16SetPathInfo                doscalls 104 F
+Dos16SetProcCp                  doscalls 164 F
+Dos16SetPrty                    doscalls  11 F
+Dos16SetSigHandler              doscalls  14 F
+Dos16SetVec                     doscalls  89 F
+Dos16SetVerify                  doscalls  86 F
+Dos16Shutdown                   doscalls 206 F
+Dos16SizeSeg                    doscalls 126 F
+Dos16Sleep                      doscalls  32 F
+Dos16SubAlloc                   doscalls 147 F
+Dos16SubFree                    doscalls 148 F
+Dos16SubSet                     doscalls 146 F
+Dos16SuspendThread              doscalls  27 F
+Dos16SysTrace                   doscalls  90 F
+Dos16SystemService              doscalls  88 F
+Dos16TimerAsync                 doscalls  29 F
+Dos16TimerStart                 doscalls  30 F
+Dos16TimerStop                  doscalls  31 F
+Dos16TmrQueryFreq               doscalls 420 F
+Dos16TmrQueryTime               doscalls 421 F
+Dos16UnlockSeg                  doscalls 123 F
+Dos16Write                      doscalls 138 F
+Dos16WriteAsync                 doscalls 150 F
Index: trunk/src/emx/src/lib/os2_386/drag.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/drag.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/drag.imp	(revision 18)
@@ -0,0 +1,44 @@
+;
+; drag.imp
+;
+DrgAcceptDroppedFiles           pmdrag 66 5
+DrgAccessDraginfo               pmdrag 32 1
+DrgAddStrHandle                 pmdrag 33 1
+DrgAllocDraginfo                pmdrag 34 1
+DrgAllocDragtransfer            pmdrag 35 1
+DrgCancelLazyDrag               pmdrag 68 0
+DrgDeleteDraginfoStrHandles     pmdrag 36 1
+DrgDeleteStrHandle              pmdrag 37 1
+DrgDrag                         pmdrag 38 6
+DrgDragFiles                    pmdrag 65 9
+DrgFreeDraginfo                 pmdrag 39 1
+DrgFreeDragtransfer             pmdrag 40 1
+DrgGetPS                        pmdrag 41 1
+DrgLazyDrag                     pmdrag 67 5
+DrgLazyDrop                     pmdrag 69 3
+DrgPostTransferMsg              pmdrag 42 6
+DrgPushDraginfo                 pmdrag 43 2
+DrgQueryDragStatus              pmdrag 73 0
+DrgQueryDraginfoPtr             pmdrag 70 1
+DrgQueryDraginfoPtrFromDragitem pmdrag 72 1
+DrgQueryDraginfoPtrFromHwnd     pmdrag 71 1
+DrgQueryDragitem                pmdrag 44 4
+DrgQueryDragitemCount           pmdrag 45 1
+DrgQueryDragitemPtr             pmdrag 46 2
+DrgQueryNativeRMF               pmdrag 47 3
+DrgQueryNativeRMFLen            pmdrag 48 1
+DrgQueryStrName                 pmdrag 49 3
+DrgQueryStrNameLen              pmdrag 50 1
+DrgQueryTrueType                pmdrag 51 3
+DrgQueryTrueTypeLen             pmdrag 52 1
+DrgReallocDraginfo              pmdrag 74 2
+DrgReleasePS                    pmdrag 53 1
+DrgSendTransferMsg              pmdrag 54 4
+DrgSetDragImage                 pmdrag 56 4
+DrgSetDragPointer               pmdrag 55 2
+DrgSetDragitem                  pmdrag 57 4
+DrgVerifyNativeRMF              pmdrag 58 2
+DrgVerifyRMF                    pmdrag 59 3
+DrgVerifyTrueType               pmdrag 60 2
+DrgVerifyType                   pmdrag 61 2
+DrgVerifyTypeSet                pmdrag 62 4
Index: trunk/src/emx/src/lib/os2_386/emxwrap.def
===================================================================
--- trunk/src/emx/src/lib/os2_386/emxwrap.def	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/emxwrap.def	(revision 18)
@@ -0,0 +1,122 @@
+;
+; emxwrap.def
+;
+LIBRARY EMXWRAP INITINSTANCE
+DESCRIPTION 'emxwrap.dll 0.9d -- Copyright (c) 1993-1998 by Eberhard Mattes'
+DATA
+   SINGLE NONSHARED
+EXPORTS
+  EMX_REVISION = emx_revision @1 RESIDENTNAME
+
+  WinDefAVioWindowProc        @30
+
+  VioEndPopUp                 @101
+  VioGetPhysBuf               @102
+  VioGetAnsi                  @103
+  VioSetAnsi                  @105
+  VioDeRegister               @106
+  VioScrollUp                 @107
+  VioPrtSc                    @108
+  VioGetCurPos                @109
+  VioWrtCellStr               @110
+  VioPopUp                    @111
+  VioScrollRt                 @112
+  VioWrtCharStr               @113
+  VioSetCurPos                @115
+  VioScrUnLock                @118
+  VioWrtTTY                   @119
+  VioGetMode                  @121
+  VioSetMode                  @122
+  VioScrLock                  @123
+  VioReadCellStr              @124
+  VioSavRedrawWait            @125
+  VioWrtNAttr                 @126
+  VioGetCurType               @127
+  VioSavRedrawUndo            @128
+  VioGetFont                  @129
+  VioReadCharStr              @130
+  VioGetBuf                   @131
+  VioSetCurType               @132
+  VioSetFont                  @133
+  VioModeUndo                 @135
+  VioModeWait                 @137
+  VioGetCp                    @140
+  VioSetCp                    @142
+  VioShowBuf                  @143
+  VioScrollLf                 @144
+  VioRegister                 @145
+  VioGetConfig                @146
+  VioScrollDn                 @147
+  VioWrtCharStrAtt            @148
+  VioGetState                 @149
+  VioPrtScToggle              @150
+  VioSetState                 @151
+  VioWrtNCell                 @152
+  VioWrtNChar                 @153
+  VioAssociate                @155
+  VioCreatePS                 @156
+  VioDeleteSetId              @157
+  VioGetDeviceCellSize        @158
+  VioGetOrg                   @159
+  VioCreateLogFont            @160
+  VioDestroyPS                @161
+  VioQuerySetIds              @162
+  VioSetOrg                   @163
+  VioQueryFonts               @164
+  VioSetDeviceCellSize        @165
+  VioShowPS                   @166
+  VioGlobalReg                @170
+  VioCheckCharType            @175
+
+  KbdSetCustXt                @201
+  KbdGetCp                    @203
+  KbdCharIn                   @204
+  KbdSetCp                    @205
+  KbdSynch                    @207
+  KbdRegister                 @208
+  KbdStringIn                 @209
+  KbdGetStatus                @210
+  KbdSetStatus                @211
+  KbdGetFocus                 @212
+  KbdFlushBuffer              @213
+  KbdXlate                    @214
+  KbdClose                    @217
+  KbdFreeFocus                @218
+  KbdDeRegister               @220
+  KbdSetFgnd                  @221
+  KbdPeek                     @222
+  KbdOpen                     @223
+  KbdGetHWID                  @224
+  KbdSetHWID                  @225
+
+  MouGetPtrShape              @301
+  MouSetPtrShape              @302
+  MouGetNumMickeys            @303
+  MouGetScaleFact             @306
+  MouFlushQue                 @307
+  MouGetNumButtons            @308
+  MouClose                    @309
+  MouSetScaleFact             @311
+  MouGetNumQueEl              @313
+  MouDeRegister               @314
+  MouGetEventMask             @315
+  MouSetEventMask             @316
+  MouOpen                     @317
+  MouRemovePtr                @318
+  MouGetPtrPos                @319
+  MouReadEventQue             @320
+  MouSetPtrPos                @321
+  MouGetDevStatus             @322
+  MouSynch                    @323
+  MouRegister                 @324
+  MouSetDevStatus             @325
+  MouDrawPtr                  @326
+  MouInitReal                 @327
+  MouSetThreshold             @329
+  MouGetThreshold             @330
+
+  DosMonWrite                 @401
+  DosMonRead                  @402
+  DosMonClose                 @403
+  DosMonOpen                  @404
+  DosMonReg                   @405
Index: trunk/src/emx/src/lib/os2_386/gpi.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/gpi.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/gpi.imp	(revision 18)
@@ -0,0 +1,277 @@
+;
+; gpi.imp
+;
+DevCloseDC                      pmgpi 604 1
+DevEscape                       pmgpi 605 6
+DevOpenDC                       pmgpi 610 6
+DevPostDeviceModes              pmgpi 609 6
+DevQueryCaps                    pmgpi 606 4
+DevQueryDeviceNames             pmgpi 607 7
+DevQueryHardcopyCaps            pmgpi 608 4
+DevStdOpen                      pmgpi 625 ?
+GpiAnimatePalette               pmgpi 595 5
+GpiAssociate                    pmgpi 351 2
+GpiBeginArea                    pmgpi 352 2
+GpiBeginElement                 pmgpi 353 3
+GpiBeginInkPath                 pmgpi 670 3
+GpiBeginPath                    pmgpi 354 2
+GpiBitBlt                       pmgpi 355 6
+GpiBox                          pmgpi 356 5
+GpiCallSegmentMatrix            pmgpi 357 5
+GpiCharString                   pmgpi 358 3
+GpiCharStringAt                 pmgpi 359 4
+GpiCharStringPos                pmgpi 580 6
+GpiCharStringPosAt              pmgpi 581 7
+GpiCloseFigure                  pmgpi 360 1
+GpiCloseSegment                 pmgpi 361 1
+GpiCombineRegion                pmgpi 362 5
+GpiComment                      pmgpi 363 3
+GpiConvert                      pmgpi 364 5
+GpiConvertWithMatrix            pmgpi 618 5
+GpiCopyMetaFile                 pmgpi 365 1
+GpiCorrelateChain               pmgpi 366 6
+GpiCorrelateFrom                pmgpi 367 8
+GpiCorrelateSegment             pmgpi 582 7
+GpiCreateBitmap                 pmgpi 598 5
+GpiCreateLogColorTable          pmgpi 592 6
+GpiCreateLogFont                pmgpi 368 4
+GpiCreatePS                     pmgpi 369 4
+GpiCreatePalette                pmgpi 594 5
+GpiCreateRegion                 pmgpi 370 3
+GpiDeleteBitmap                 pmgpi 371 1
+GpiDeleteElement                pmgpi 372 1
+GpiDeleteElementRange           pmgpi 373 3
+GpiDeleteElementsBetweenLabels  pmgpi 374 3
+GpiDeleteMetaFile               pmgpi 375 1
+GpiDeletePalette                pmgpi 577 1
+GpiDeleteSegment                pmgpi 376 2
+GpiDeleteSegments               pmgpi 377 3
+GpiDeleteSetId                  pmgpi 378 2
+GpiDestroyPS                    pmgpi 379 1
+GpiDestroyRegion                pmgpi 611 2
+GpiDrawBits                     pmgpi 603 7
+GpiDrawChain                    pmgpi 380 1
+GpiDrawDynamics                 pmgpi 381 1
+GpiDrawFrom                     pmgpi 382 3
+GpiDrawSegment                  pmgpi 383 2
+GpiElement                      pmgpi 384 5
+GpiEndArea                      pmgpi 385 1
+GpiEndElement                   pmgpi 386 1
+GpiEndInkPath                   pmgpi 671 2
+GpiEndPath                      pmgpi 387 1
+GpiEqualRegion                  pmgpi 388 3
+GpiErase                        pmgpi 389 1
+GpiErrorSegmentData             pmgpi 390 3
+GpiExcludeClipRectangle         pmgpi 391 2
+GpiFillPath                     pmgpi 392 3
+GpiFloodFill                    pmgpi 560 3
+GpiFrameRegion                  pmgpi 617 3
+GpiFullArc                      pmgpi 393 3
+GpiGetData                      pmgpi 394 6
+GpiImage                        pmgpi 395 5
+GpiIntersectClipRectangle       pmgpi 396 2
+GpiLabel                        pmgpi 397 2
+GpiLine                         pmgpi 398 2
+GpiLoadBitmap                   pmgpi 399 5
+GpiLoadFonts                    pmgpi 400 2
+GpiLoadMetaFile                 pmgpi 401 2
+GpiLoadPublicFonts              pmgpi 622 2
+GpiMarker                       pmgpi 402 2
+GpiModifyPath                   pmgpi 403 3
+GpiMove                         pmgpi 404 2
+GpiOffsetClipRegion             pmgpi 405 2
+GpiOffsetElementPointer         pmgpi 406 2
+GpiOffsetRegion                 pmgpi 407 3
+GpiOpenSegment                  pmgpi 408 2
+GpiOutlinePath                  pmgpi 563 3
+GpiPaintRegion                  pmgpi 409 2
+GpiPartialArc                   pmgpi 612 5
+GpiPathToRegion                 pmgpi 559 3
+GpiPlayMetaFile                 pmgpi 411 7
+GpiPointArc                     pmgpi 412 2
+GpiPolyFillet                   pmgpi 413 3
+GpiPolyFilletSharp              pmgpi 414 4
+GpiPolyLine                     pmgpi 415 3
+GpiPolyLineDisjoint             pmgpi 558 3
+GpiPolyMarker                   pmgpi 416 3
+GpiPolySpline                   pmgpi 417 3
+GpiPolygons                     pmgpi 650 5
+GpiPop                          pmgpi 418 2
+GpiPtInRegion                   pmgpi 419 3
+GpiPtVisible                    pmgpi 420 2
+GpiPutData                      pmgpi 421 4
+GpiQueryArcParams               pmgpi 422 2
+GpiQueryAttrMode                pmgpi 423 1
+GpiQueryAttrs                   pmgpi 583 4
+GpiQueryBackColor               pmgpi 424 1
+GpiQueryBackMix                 pmgpi 425 1
+GpiQueryBitmapBits              pmgpi 599 5
+GpiQueryBitmapDimension         pmgpi 426 2
+GpiQueryBitmapHandle            pmgpi 427 2
+GpiQueryBitmapInfoHeader        pmgpi 601 2
+GpiQueryBitmapParameters        pmgpi 573 2
+GpiQueryBoundaryData            pmgpi 428 2
+GpiQueryCharAngle               pmgpi 429 2
+GpiQueryCharBox                 pmgpi 430 2
+GpiQueryCharBreakExtra          pmgpi 615 2
+GpiQueryCharDirection           pmgpi 431 1
+GpiQueryCharExtra               pmgpi 613 2
+GpiQueryCharMode                pmgpi 432 1
+GpiQueryCharSet                 pmgpi 433 1
+GpiQueryCharShear               pmgpi 434 2
+GpiQueryCharStringPos           pmgpi 584 6
+GpiQueryCharStringPosAt         pmgpi 585 7
+GpiQueryClipBox                 pmgpi 435 2
+GpiQueryClipRegion              pmgpi 436 1
+GpiQueryColor                   pmgpi 437 1
+GpiQueryColorData               pmgpi 438 3
+GpiQueryColorIndex              pmgpi 439 3
+GpiQueryCp                      pmgpi 440 1
+GpiQueryCurrentPosition         pmgpi 441 2
+GpiQueryDefArcParams            pmgpi 567 2
+GpiQueryDefAttrs                pmgpi 590 4
+GpiQueryDefCharBox              pmgpi 442 2
+GpiQueryDefTag                  pmgpi 568 2
+GpiQueryDefViewingLimits        pmgpi 569 2
+GpiQueryDefaultViewMatrix       pmgpi 443 3
+GpiQueryDevice                  pmgpi 444 1
+GpiQueryDeviceBitmapFormats     pmgpi 445 3
+GpiQueryDrawControl             pmgpi 446 2
+GpiQueryDrawingMode             pmgpi 447 1
+GpiQueryEditMode                pmgpi 448 1
+GpiQueryElement                 pmgpi 449 4
+GpiQueryElementPointer          pmgpi 450 1
+GpiQueryElementType             pmgpi 451 4
+GpiQueryFaceString              pmgpi 575 5
+GpiQueryFontAction              pmgpi 576 2
+GpiQueryFontFileDescriptions    pmgpi 452 4
+GpiQueryFontMetrics             pmgpi 453 3
+GpiQueryFonts                   pmgpi 586 6
+GpiQueryFullFontFileDescs       pmgpi 657 5
+GpiQueryGraphicsField           pmgpi 454 2
+GpiQueryInitialSegmentAttrs     pmgpi 455 2
+GpiQueryKerningPairs            pmgpi 456 3
+GpiQueryLineEnd                 pmgpi 457 1
+GpiQueryLineJoin                pmgpi 458 1
+GpiQueryLineType                pmgpi 459 1
+GpiQueryLineWidth               pmgpi 460 1
+GpiQueryLineWidthGeom           pmgpi 461 1
+GpiQueryLogColorTable           pmgpi 593 5
+GpiQueryLogicalFont             pmgpi 574 5
+GpiQueryMarker                  pmgpi 462 1
+GpiQueryMarkerBox               pmgpi 463 2
+GpiQueryMarkerSet               pmgpi 464 1
+GpiQueryMetaFileBits            pmgpi 465 4
+GpiQueryMetaFileLength          pmgpi 466 1
+GpiQueryMix                     pmgpi 467 1
+GpiQueryModelTransformMatrix    pmgpi 468 3
+GpiQueryNearestColor            pmgpi 469 3
+GpiQueryNumberSetIds            pmgpi 470 1
+GpiQueryPS                      pmgpi 471 2
+GpiQueryPageViewport            pmgpi 472 2
+GpiQueryPalette                 pmgpi 579 1
+GpiQueryPaletteInfo             pmgpi 597 5
+GpiQueryPattern                 pmgpi 473 1
+GpiQueryPatternRefPoint         pmgpi 474 2
+GpiQueryPatternSet              pmgpi 475 1
+GpiQueryPel                     pmgpi 476 2
+GpiQueryPickAperturePosition    pmgpi 477 2
+GpiQueryPickApertureSize        pmgpi 478 2
+GpiQueryRGBColor                pmgpi 479 3
+GpiQueryRealColors              pmgpi 480 5
+GpiQueryRegionBox               pmgpi 481 3
+GpiQueryRegionRects             pmgpi 587 5
+GpiQuerySegmentAttrs            pmgpi 482 3
+GpiQuerySegmentNames            pmgpi 483 5
+GpiQuerySegmentPriority         pmgpi 484 3
+GpiQuerySegmentTransformMatrix  pmgpi 485 4
+GpiQuerySetIds                  pmgpi 486 5
+GpiQueryStopDraw                pmgpi 487 1
+GpiQueryTag                     pmgpi 488 2
+GpiQueryTextAlignment           pmgpi 648 3
+GpiQueryTextBox                 pmgpi 489 5
+GpiQueryViewingLimits           pmgpi 490 2
+GpiQueryViewingTransformMatrix  pmgpi 491 3
+GpiQueryWidthTable              pmgpi 492 4
+GpiRectInRegion                 pmgpi 494 3
+GpiRectVisible                  pmgpi 495 2
+GpiRemoveDynamics               pmgpi 496 3
+GpiResetBoundaryData            pmgpi 497 1
+GpiResetPS                      pmgpi 498 2
+GpiRestorePS                    pmgpi 499 2
+GpiResumePlay                   pmgpi 562 ?
+GpiRotate                       pmgpi 566 5
+GpiSaveMetaFile                 pmgpi 500 2
+GpiSavePS                       pmgpi 501 1
+GpiScale                        pmgpi 565 5
+GpiSelectPalette                pmgpi 578 2
+GpiSetArcParams                 pmgpi 502 2
+GpiSetAttrMode                  pmgpi 503 2
+GpiSetAttrs                     pmgpi 588 5
+GpiSetBackColor                 pmgpi 504 2
+GpiSetBackMix                   pmgpi 505 2
+GpiSetBitmap                    pmgpi 506 2
+GpiSetBitmapBits                pmgpi 602 5
+GpiSetBitmapDimension           pmgpi 507 2
+GpiSetBitmapId                  pmgpi 508 3
+GpiSetCharAngle                 pmgpi 509 2
+GpiSetCharBox                   pmgpi 510 2
+GpiSetCharBreakExtra            pmgpi 616 2
+GpiSetCharDirection             pmgpi 511 2
+GpiSetCharExtra                 pmgpi 614 2
+GpiSetCharMode                  pmgpi 512 2
+GpiSetCharSet                   pmgpi 513 2
+GpiSetCharShear                 pmgpi 514 2
+GpiSetClipPath                  pmgpi 515 3
+GpiSetClipRegion                pmgpi 516 3
+GpiSetColor                     pmgpi 517 2
+GpiSetCp                        pmgpi 518 2
+GpiSetCurrentPosition           pmgpi 519 2
+GpiSetDefArcParams              pmgpi 570 2
+GpiSetDefAttrs                  pmgpi 591 4
+GpiSetDefTag                    pmgpi 571 2
+GpiSetDefViewingLimits          pmgpi 572 2
+GpiSetDefaultViewMatrix         pmgpi 520 4
+GpiSetDrawControl               pmgpi 521 3
+GpiSetDrawingMode               pmgpi 522 2
+GpiSetEditMode                  pmgpi 523 2
+GpiSetElementPointer            pmgpi 524 2
+GpiSetElementPointerAtLabel     pmgpi 525 2
+GpiSetGraphicsField             pmgpi 526 2
+GpiSetInitialSegmentAttrs       pmgpi 527 3
+GpiSetLineEnd                   pmgpi 528 2
+GpiSetLineJoin                  pmgpi 529 2
+GpiSetLineType                  pmgpi 530 2
+GpiSetLineWidth                 pmgpi 531 2
+GpiSetLineWidthGeom             pmgpi 532 2
+GpiSetMarker                    pmgpi 533 2
+GpiSetMarkerBox                 pmgpi 534 2
+GpiSetMarkerSet                 pmgpi 535 2
+GpiSetMetaFileBits              pmgpi 536 4
+GpiSetMix                       pmgpi 537 2
+GpiSetModelTransformMatrix      pmgpi 538 4
+GpiSetPS                        pmgpi 539 3
+GpiSetPageViewport              pmgpi 540 2
+GpiSetPaletteEntries            pmgpi 596 5
+GpiSetPattern                   pmgpi 541 2
+GpiSetPatternRefPoint           pmgpi 542 2
+GpiSetPatternSet                pmgpi 543 2
+GpiSetPel                       pmgpi 544 2
+GpiSetPickAperturePosition      pmgpi 545 2
+GpiSetPickApertureSize          pmgpi 589 3
+GpiSetRegion                    pmgpi 546 4
+GpiSetSegmentAttrs              pmgpi 547 4
+GpiSetSegmentPriority           pmgpi 548 4
+GpiSetSegmentTransformMatrix    pmgpi 549 5
+GpiSetStopDraw                  pmgpi 550 2
+GpiSetTag                       pmgpi 551 2
+GpiSetTextAlignment             pmgpi 649 3
+GpiSetViewingLimits             pmgpi 552 2
+GpiSetViewingTransformMatrix    pmgpi 553 4
+GpiStrokeInkPath                pmgpi 672 5
+GpiStrokePath                   pmgpi 554 3
+GpiSuspendPlay                  pmgpi 561 ?
+GpiTranslate                    pmgpi 564 4
+GpiUnloadFonts                  pmgpi 555 2
+GpiUnloadPublicFonts            pmgpi 623 2
+GpiWCBitBlt                     pmgpi 557 6
Index: trunk/src/emx/src/lib/os2_386/help.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/help.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/help.imp	(revision 18)
@@ -0,0 +1,24 @@
+;
+; help.imp
+;
+DdfBeginList                    helpmgr  82 4
+DdfBitmap                       helpmgr  88 3
+DdfEndList                      helpmgr  84 1
+DdfHyperText                    helpmgr  81 4
+DdfInform                       helpmgr  79 3
+DdfInitialize                   helpmgr  74 3
+DdfListItem                     helpmgr  83 3
+DdfMetafile                     helpmgr  86 3
+DdfPara                         helpmgr  75 1
+DdfSetColor                     helpmgr  78 3
+DdfSetFont                      helpmgr  87 4
+DdfSetFontStyle                 helpmgr  80 2
+DdfSetFormat                    helpmgr  76 2
+DdfSetTextAlign                 helpmgr  77 2
+DdfText                         helpmgr  85 2
+WinAssociateHelpInstance        helpmgr  54 2
+WinCreateHelpInstance           helpmgr  51 2
+WinCreateHelpTable              helpmgr  56 2
+WinDestroyHelpInstance          helpmgr  52 1
+WinLoadHelpTable                helpmgr  55 3
+WinQueryHelpInstance            helpmgr  53 1
Index: trunk/src/emx/src/lib/os2_386/kbd1.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd1.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd1.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd1.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetCustXt) ();
+
+USHORT KbdSetCustXt (PUSHORT pusCodePage, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pusCodePage);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16SetCustXt)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd10.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd10.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd10.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd10.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16GetStatus) ();
+
+USHORT KbdGetStatus (PKBDINFO pkbdinfo, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdinfo);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16GetStatus)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd11.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd11.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd11.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd11.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetStatus) ();
+
+USHORT KbdSetStatus (PKBDINFO pkbdinfo, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdinfo);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16SetStatus)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd12.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd12.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd12.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd12.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16GetFocus) ();
+
+USHORT KbdGetFocus (USHORT fWait, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2);
+           _THUNK_SHORT (fWait);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16GetFocus)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd13.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd13.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd13.c	(revision 18)
@@ -0,0 +1,14 @@
+/* kbd13.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16FlushBuffer) ();
+
+USHORT KbdFlushBuffer (HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16FlushBuffer)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd14.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd14.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd14.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd14.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Xlate) ();
+
+USHORT KbdXlate (PKBDTRANS pkbdtrans, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdtrans);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16Xlate)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd16.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd16.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd16.imp	(revision 18)
@@ -0,0 +1,23 @@
+;
+; kbd16.imp
+;
+Kbd16CharIn                     kbdcalls   4 F
+Kbd16Close                      kbdcalls  17 F
+Kbd16DeRegister                 kbdcalls  20 F
+Kbd16FlushBuffer                kbdcalls  13 F
+Kbd16FreeFocus                  kbdcalls  18 F
+Kbd16GetCp                      kbdcalls   3 F
+Kbd16GetFocus                   kbdcalls  12 F
+Kbd16GetHWID                    kbdcalls  24 F
+Kbd16GetStatus                  kbdcalls  10 F
+Kbd16Open                       kbdcalls  23 F
+Kbd16Peek                       kbdcalls  22 F
+Kbd16Register                   kbdcalls   8 F
+Kbd16SetCp                      kbdcalls   5 F
+Kbd16SetCustXt                  kbdcalls   1 F
+Kbd16SetFgnd                    kbdcalls  21 F
+Kbd16SetHWID                    kbdcalls  25 F
+Kbd16SetStatus                  kbdcalls  11 F
+Kbd16StringIn                   kbdcalls   9 F
+Kbd16Synch                      kbdcalls   7 F
+Kbd16Xlate                      kbdcalls  14 F
Index: trunk/src/emx/src/lib/os2_386/kbd17.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd17.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd17.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd17.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Close) ();
+
+
+USHORT KbdClose (HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16Close)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd18.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd18.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd18.c	(revision 18)
@@ -0,0 +1,14 @@
+/* kbd18.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16FreeFocus) ();
+
+USHORT KbdFreeFocus (HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16FreeFocus)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd20.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd20.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd20.c	(revision 18)
@@ -0,0 +1,13 @@
+/* kbd20.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16DeRegister) ();
+
+USHORT KbdDeRegister (VOID)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (0);
+           _THUNK_CALL (Kbd16DeRegister)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd21.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd21.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd21.c	(revision 18)
@@ -0,0 +1,13 @@
+/* kbd21.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetFgnd) ();
+
+USHORT KbdSetFgnd (VOID)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (0);
+           _THUNK_CALL (Kbd16SetFgnd)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd22.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd22.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd22.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd22.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Peek) ();
+
+USHORT KbdPeek (PKBDKEYINFO pkbci, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbci);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16Peek)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd23.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd23.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd23.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd23.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Open) ();
+
+
+USHORT KbdOpen (PHKBD phkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4);
+           _THUNK_FLAT (phkbd);
+           _THUNK_CALL (Kbd16Open)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd24.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd24.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd24.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd24.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16GetHWID) ();
+
+USHORT KbdGetHWID (PKBDHWID pkbdhwid, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdhwid);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16GetHWID)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd25.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd25.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd25.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd25.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetHWID) ();
+
+USHORT KbdSetHWID (PKBDHWID pkbdhwid, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdhwid);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16SetHWID)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd3.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd3.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd3.c	(revision 18)
@@ -0,0 +1,16 @@
+/* kbd3.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16GetCp) ();
+
+USHORT KbdGetCp (ULONG ulReserved, PUSHORT pidCP, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_LONG (ulReserved);
+           _THUNK_FLAT (pidCP);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16GetCp)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd4.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd4.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd4.c	(revision 18)
@@ -0,0 +1,16 @@
+/* kbd4.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16CharIn) ();
+
+USHORT KbdCharIn (PKBDKEYINFO pkbci, USHORT fWait, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2);
+           _THUNK_FLAT (pkbci);
+           _THUNK_SHORT (fWait);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16CharIn)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd5.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd5.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd5.c	(revision 18)
@@ -0,0 +1,16 @@
+/* kbd5.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetCp) ();
+
+USHORT KbdSetCp (USHORT usReserved, USHORT idCP, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usReserved);
+           _THUNK_SHORT (idCP);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16SetCp)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd7.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd7.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd7.c	(revision 18)
@@ -0,0 +1,14 @@
+/* kbd7.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Synch) ();
+
+USHORT KbdSynch (USHORT fWait)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (fWait);
+           _THUNK_CALL (Kbd16Synch)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd8.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd8.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd8.c	(revision 18)
@@ -0,0 +1,16 @@
+/* kbd8.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Register) ();
+
+USHORT KbdRegister (PCSZ pszModName, PCSZ pszEntryName, ULONG ulFunMask)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4);
+           _THUNK_FLAT ((PSZ)pszModName);
+           _THUNK_FLAT ((PSZ)pszEntryName);
+           _THUNK_LONG (ulFunMask);
+           _THUNK_CALL (Kbd16Register)));
+}
Index: trunk/src/emx/src/lib/os2_386/kbd9.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/kbd9.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/kbd9.c	(revision 18)
@@ -0,0 +1,17 @@
+/* kbd9.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16StringIn) ();
+
+USHORT KbdStringIn (PCH pch, PSTRINGINBUF pchIn, USHORT fWait, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2+2);
+           _THUNK_FLAT (pch);
+           _THUNK_FLAT (pchIn);
+           _THUNK_SHORT (fWait);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16StringIn)));
+}
Index: trunk/src/emx/src/lib/os2_386/makefile
===================================================================
--- trunk/src/emx/src/lib/os2_386/makefile	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/makefile	(revision 18)
@@ -0,0 +1,105 @@
+#
+# /emx/src/lib/os2_386/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.PHONY: clean default os2 emxwrap
+
+.SOURCE.c: ..
+.SOURCE.imp: ..
+.SOURCE.s: ..
+
+LIBOS2=$(L)$(LIBNAME)
+EMXWRAP=\emx\dll\emxwrap.dll
+
+default:    os2 emxwrap
+
+os2 .SETDIR=st:
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN) LIBNAME=os2.a MT_CCFLAGS= EMXIMP_FLAGS=
+
+os2-p .SETDIR=st_p:
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN) LIBNAME=os2_p.a MT_CCFLAGS=-pg EMXIMP_FLAGS=-m
+
+emxwrap: $(EMXWRAP) $(L)wrap.a $(L)wrap.lib
+
+dstlib: $(LIBOS2)
+
+clean:
+	-del st\*.o $(DELOPT)
+	-del st_p\*.o $(DELOPT)
+	-del *.obj $(DELOPT)
+	-del emxwrap1.c $(DELOPT)
+
+IMPFILES=dos.imp gpi.imp help.imp msg.imp nls.imp que.imp ses.imp shl.imp \
+    win.imp ctls.imp pic.imp drag.imp spl.imp wp.imp rexxapi.imp rexx.imp \
+    som.imp dos16.imp kbd16.imp mon16.imp vio16.imp mou16.imp pmviop16.imp \
+    pmmerge.imp
+
+OFILES=code2.o code3.o \
+    kbd1.o kbd3.o kbd4.o kbd5.o kbd7.o kbd8.o kbd9.o kbd10.o kbd11.o \
+    kbd12.o kbd13.o kbd14.o kbd17.o kbd18.o kbd20.o kbd21.o kbd22.o \
+    kbd23.o kbd24.o kbd25.o \
+    vio1.o vio2.o vio3.o vio5.o vio6.o vio7.o vio8.o vio9.o vio10.o vio11.o \
+    vio12.o vio13.o vio15.o vio18.o vio19.o vio21.o vio22.o vio23.o vio24.o \
+    vio25.o vio26.o vio27.o vio28.o vio29.o vio30.o vio31.o vio32.o vio33.o \
+    vio35.o vio37.o vio40.o vio42.o vio43.o vio44.o vio45.o vio46.o vio47.o \
+    vio48.o vio49.o vio50.o vio51.o vio52.o vio53.o vio55.o vio56.o vio57.o \
+    vio58.o vio59.o vio60.o vio61.o vio62.o vio63.o vio64.o vio65.o vio66.o \
+    vio70.o vio75.o \
+    mou1.o mou2.o mou3.o mou6.o mou7.o mou8.o mou9.o mou11.o mou13.o mou14.o \
+    mou15.o mou16.o mou17.o mou18.o mou19.o mou20.o mou21.o mou22.o mou23.o \
+    mou24.o mou25.o mou26.o mou27.o mou29.o mou30.o \
+    pmviop30.o \
+    mon1.o mon2.o mon3.o mon4.o mon5.o
+
+CFILES= \
+    kbd1.c kbd3.c kbd4.c kbd5.c kbd7.c kbd8.c kbd9.c kbd10.c kbd11.c \
+    kbd12.c kbd13.c kbd14.c kbd17.c kbd18.c kbd20.c kbd21.c kbd22.c \
+    kbd23.c kbd24.c kbd25.c \
+    vio1.c vio2.c vio3.c vio5.c vio6.c vio7.c vio8.c vio9.c vio10.c vio11.c \
+    vio12.c vio13.c vio15.c vio18.c vio19.c vio21.c vio22.c vio23.c vio24.c \
+    vio25.c vio26.c vio27.c vio28.c vio29.c vio30.c vio31.c vio32.c vio33.c \
+    vio35.c vio37.c vio40.c vio42.c vio43.c vio44.c vio45.c vio46.c vio47.c \
+    vio48.c vio49.c vio50.c vio51.c vio52.c vio53.c vio55.c vio56.c vio57.c \
+    vio58.c vio59.c vio60.c vio61.c vio62.c vio63.c vio64.c vio65.c vio66.c \
+    vio70.c vio75.c \
+    mou1.c mou2.c mou3.c mou6.c mou7.c mou8.c mou9.c mou11.c mou13.c mou14.c \
+    mou15.c mou16.c mou17.c mou18.c mou19.c mou20.c mou21.c mou22.c mou23.c \
+    mou24.c mou25.c mou26.c mou27.c mou29.c mou30.c \
+    pmviop30.c \
+    mon1.c mon2.c mon3.c mon4.c mon5.c
+
+code2.o: code2.s $(ASM386H)
+code3.o: code3.s $(ASM386H)
+
+TEMP=$(strip $(IMPFILES))
+DOTDOT_IMPFILES=../$(TEMP:s! ! ../!)
+
+$(LIBOS2): $(IMPFILES) $(OFILES)
+	emximp $(EMXIMP_FLAGS) -o $(LIBOS2) $(DOTDOT_IMPFILES)
+	$(AR) r $(LIBOS2) *.o
+
+$(L)wrap.a: $(L)wrap.lib
+	emximp -o $(L)wrap.a $(L)wrap.lib
+
+$(L)wrap.lib: emxwrap.def
+	emximp -o emxwrap.imp emxwrap.def
+	emximp -o $(L)wrap.lib emxwrap.imp
+	-del emxwrap.imp
+
+
+emxwrap1.c: $(CFILES)
+	emxcat -o emxwrap1.c vio*.c kbd*.c mou*.c pmviop*.c mon*.c
+
+emxwrap1.obj: emxwrap1.c
+	$(CC) -c -Zomf emxwrap1.c
+
+revision.obj: revision.c
+	$(CC) -c -Zomf revision.c
+
+$(EMXWRAP): $(L)res0.obj revision.obj emxwrap1.obj emxwrap.def \
+    $(L)emx2.lib $(L)os2.lib
+	link386 /noi /noe /nod $(L)res0 revision emxwrap1, emxwrap.dll, \
+		nul, $(L)emx2 $(L)os2, emxwrap;
+	copy emxwrap.dll $(EMXWRAP)
+	del emxwrap.dll
Index: trunk/src/emx/src/lib/os2_386/mon1.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mon1.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mon1.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mon1.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonWrite) ();
+
+USHORT DosMonWrite (PBYTE pbOutBuf, PBYTE pbDataBuf, USHORT cbData)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pbOutBuf);
+           _THUNK_FLAT (pbDataBuf);
+           _THUNK_SHORT (cbData);
+           _THUNK_CALL (Dos16MonWrite)));
+}
Index: trunk/src/emx/src/lib/os2_386/mon16.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/mon16.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mon16.imp	(revision 18)
@@ -0,0 +1,8 @@
+;
+; mon16.imp
+;
+Dos16MonWrite                   moncalls  1 F
+Dos16MonRead                    moncalls  2 F
+Dos16MonClose                   moncalls  3 F
+Dos16MonOpen                    moncalls  4 F
+Dos16MonReg                     moncalls  5 F
Index: trunk/src/emx/src/lib/os2_386/mon2.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mon2.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mon2.c	(revision 18)
@@ -0,0 +1,18 @@
+/* mon2.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonRead) ();
+
+USHORT DosMonRead (PBYTE pbInBuf, USHORT fWait, PBYTE pbDataBuf,
+                   PUSHORT pcbData)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+4+4);
+           _THUNK_FLAT (pbInBuf);
+           _THUNK_SHORT (fWait);
+           _THUNK_FLAT (pbDataBuf);
+           _THUNK_FLAT (pcbData);
+           _THUNK_CALL (Dos16MonRead)));
+}
Index: trunk/src/emx/src/lib/os2_386/mon3.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mon3.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mon3.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mon3.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonClose) ();
+
+USHORT DosMonClose (HMONITOR hmon)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hmon);
+           _THUNK_CALL (Dos16MonClose)));
+}
Index: trunk/src/emx/src/lib/os2_386/mon4.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mon4.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mon4.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mon4.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonOpen) ();
+
+USHORT DosMonOpen (PSZ pszDevName, PHMONITOR phmon)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4);
+           _THUNK_FLAT (pszDevName);
+           _THUNK_FLAT (phmon);
+           _THUNK_CALL (Dos16MonOpen)));
+}
Index: trunk/src/emx/src/lib/os2_386/mon5.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mon5.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mon5.c	(revision 18)
@@ -0,0 +1,19 @@
+/* mon5.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonReg) ();
+
+USHORT DosMonReg (HMONITOR hmon, PBYTE pbInBuf, PBYTE pbOutBuf,
+		  USHORT fPosition, USHORT usIndex)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+4+2+2);
+           _THUNK_SHORT (hmon);
+           _THUNK_FLAT (pbInBuf);
+           _THUNK_FLAT (pbOutBuf);
+           _THUNK_SHORT (fPosition);
+           _THUNK_SHORT (usIndex);
+           _THUNK_CALL (Dos16MonReg)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou1.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou1.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou1.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mou1.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetPtrShape) ();
+
+USHORT MouGetPtrShape (PBYTE pBuf, PPTRSHAPE pmoupsInfo, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pBuf);
+           _THUNK_FLAT (pmoupsInfo);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetPtrShape)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou11.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou11.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou11.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou11.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetScaleFact) ();
+
+USHORT MouSetScaleFact (PSCALEFACT pmouscFactors, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmouscFactors);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetScaleFact)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou13.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou13.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou13.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou13.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetNumQueEl) ();
+
+USHORT MouGetNumQueEl (PMOUQUEINFO qmouqi, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (qmouqi);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetNumQueEl)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou14.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou14.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou14.c	(revision 18)
@@ -0,0 +1,13 @@
+/* mou14.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16DeRegister) ();
+
+USHORT MouDeRegister (VOID)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (0);
+           _THUNK_CALL (Mou16DeRegister)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou15.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou15.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou15.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou15.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetEventMask) ();
+
+USHORT MouGetEventMask (PUSHORT pfsEvents, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfsEvents);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetEventMask)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou16.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou16.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou16.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou16.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetEventMask) ();
+
+USHORT MouSetEventMask (PUSHORT pfsEvents, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfsEvents);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetEventMask)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou16.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou16.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou16.imp	(revision 18)
@@ -0,0 +1,30 @@
+;
+; Mou16.imp
+;
+Mou16Close                      moucalls   9 F
+Mou16DeRegister                 moucalls  14 F
+Mou16DrawPtr                    moucalls  26 F
+Mou16FlushQue                   moucalls   7 F
+Mou16GetDevStatus               moucalls  22 F
+Mou16GetEventMask               moucalls  15 F
+Mou16GetHotKey                  moucalls   4 F
+Mou16GetNumButtons              moucalls   8 F
+Mou16GetNumMickeys              moucalls   3 F
+Mou16GetNumQueEl                moucalls  13 F
+Mou16GetPtrPos                  moucalls  19 F
+Mou16GetPtrShape                moucalls   1 F
+Mou16GetScaleFact               moucalls   6 F
+Mou16GetThreshold               moucalls  29 F
+Mou16InitReal                   moucalls  27 F
+Mou16Open                       moucalls  17 F
+Mou16ReadEventQue               moucalls  20 F
+Mou16Register                   moucalls  24 F
+Mou16RemovePtr                  moucalls  18 F
+Mou16SetDevStatus               moucalls  25 F
+Mou16SetEventMask               moucalls  16 F
+Mou16SetHotKey                  moucalls  10 F
+Mou16SetPtrPos                  moucalls  21 F
+Mou16SetPtrShape                moucalls   2 F
+Mou16SetScaleFact               moucalls  11 F
+Mou16SetThreshold               moucalls  30 F
+Mou16Synch                      moucalls  23 F
Index: trunk/src/emx/src/lib/os2_386/mou17.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou17.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou17.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou17.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16Open) ();
+
+USHORT MouOpen (PCSZ pszDvrName, PHMOU phmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4);
+           _THUNK_FLAT ((PSZ)pszDvrName);
+           _THUNK_FLAT (phmou);
+           _THUNK_CALL (Mou16Open)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou18.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou18.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou18.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou18.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16RemovePtr) ();
+
+USHORT MouRemovePtr (PNOPTRRECT pmourtRect, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmourtRect);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16RemovePtr)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou19.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou19.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou19.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou19.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetPtrPos) ();
+
+USHORT MouGetPtrPos (PPTRLOC pmouLoc, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmouLoc);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetPtrPos)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou2.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou2.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou2.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mou2.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetPtrShape) ();
+
+USHORT MouSetPtrShape (PBYTE pBuf, PPTRSHAPE pmoupsInfo, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pBuf);
+           _THUNK_FLAT (pmoupsInfo);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetPtrShape)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou20.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou20.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou20.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mou20.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16ReadEventQue) ();
+
+USHORT MouReadEventQue (PMOUEVENTINFO pmouevEvent, PUSHORT pfWait, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pmouevEvent);
+           _THUNK_FLAT (pfWait);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16ReadEventQue)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou21.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou21.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou21.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou21.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetPtrPos) ();
+
+USHORT MouSetPtrPos (PPTRLOC pmouLoc, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmouLoc);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetPtrPos)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou22.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou22.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou22.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou22.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetDevStatus) ();
+
+USHORT MouGetDevStatus (PUSHORT pfsDevStatus, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfsDevStatus);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetDevStatus)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou23.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou23.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou23.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou23.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16Synch) ();
+
+USHORT MouSynch (USHORT fWait)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (fWait);
+           _THUNK_CALL (Mou16Synch)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou24.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou24.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou24.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mou24.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16Register) ();
+
+USHORT MouRegister (PCSZ pszModName, PCSZ pszEntryName, ULONG ulFunMask)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4);
+           _THUNK_FLAT ((PSZ)pszModName);
+           _THUNK_FLAT ((PSZ)pszEntryName);
+           _THUNK_LONG (ulFunMask);
+           _THUNK_CALL (Mou16Register)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou25.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou25.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou25.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou25.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetDevStatus) ();
+
+USHORT MouSetDevStatus (PUSHORT pfsDevStatus, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfsDevStatus);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetDevStatus)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou26.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou26.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou26.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou26.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16DrawPtr) ();
+
+USHORT MouDrawPtr (HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16DrawPtr)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou27.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou27.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou27.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou27.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16InitReal) ();
+
+USHORT MouInitReal (PCSZ pszDriverName)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4);
+           _THUNK_FLAT ((PSZ)pszDriverName);
+           _THUNK_CALL (Mou16InitReal)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou29.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou29.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou29.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou29.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetThreshold) ();
+
+USHORT MouSetThreshold (PTHRESHOLD pthreshold, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pthreshold);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetThreshold)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou3.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou3.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou3.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou3.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetNumMickeys) ();
+
+USHORT MouGetNumMickeys (PUSHORT pcMickeys, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pcMickeys);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetNumMickeys)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou30.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou30.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou30.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou30.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetThreshold) ();
+
+USHORT MouGetThreshold (PTHRESHOLD pthreshold, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pthreshold);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetThreshold)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou6.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou6.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou6.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou6.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetScaleFact) ();
+
+USHORT MouGetScaleFact (PSCALEFACT pmouscFactors, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmouscFactors);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetScaleFact)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou7.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou7.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou7.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou7.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16FlushQue) ();
+
+USHORT MouFlushQue (HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16FlushQue)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou8.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou8.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou8.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou8.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetNumButtons) ();
+
+USHORT MouGetNumButtons (PUSHORT pcButtons, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pcButtons);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetNumButtons)));
+}
Index: trunk/src/emx/src/lib/os2_386/mou9.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/mou9.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/mou9.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou9.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16Close) ();
+
+USHORT MouClose (HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16Close)));
+}
Index: trunk/src/emx/src/lib/os2_386/msg.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/msg.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/msg.imp	(revision 18)
@@ -0,0 +1,7 @@
+;
+; msg.imp
+;
+DosInsertMessage        msg 4 7
+DosPutMessage           msg 5 3
+DosTrueGetMessage       msg 6 8
+DosIQueryMessageCP      msg 8 5
Index: trunk/src/emx/src/lib/os2_386/nls.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/nls.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/nls.imp	(revision 18)
@@ -0,0 +1,7 @@
+;
+; nls.imp
+;
+DosMapCase              nls        7 3
+DosQueryCollate         nls        8 4
+DosQueryCtryInfo        nls        5 4
+DosQueryDBCSEnv         nls        6 3
Index: trunk/src/emx/src/lib/os2_386/pic.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/pic.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/pic.imp	(revision 18)
@@ -0,0 +1,6 @@
+;
+; pic.imp
+;
+PicIchg                         pmpic 12 4
+PicPrint                        pmpic 11 4
+PrfPif2Met                      pmpic 13 ?
Index: trunk/src/emx/src/lib/os2_386/pmmerge.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/pmmerge.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/pmmerge.imp	(revision 18)
@@ -0,0 +1,5 @@
+;
+; pmmerge.imp
+;
+WinQueryControlColors           pmmerge 5470 5
+WinSetControlColors             pmmerge 5471 5
Index: trunk/src/emx/src/lib/os2_386/pmviop16.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/pmviop16.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/pmviop16.imp	(revision 18)
@@ -0,0 +1,4 @@
+;
+; pmviop16.imp
+;
+Win16DefAVioWindowProc          pmviop    30 F
Index: trunk/src/emx/src/lib/os2_386/pmviop30.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/pmviop30.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/pmviop30.c	(revision 18)
@@ -0,0 +1,17 @@
+/* pmviop30.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Win16DefAVioWindowProc) ();
+
+MRESULT WinDefAVioWindowProc (HWND hwnd, USHORT msg, ULONG mp1, ULONG mp2)
+{
+  return ((MRESULT)
+          (_THUNK_PROLOG (4+2+4+4);
+           _THUNK_LONG ((ULONG)hwnd);
+           _THUNK_SHORT (msg);
+           _THUNK_LONG (mp1);
+           _THUNK_LONG (mp2);
+           _THUNK_CALL (Win16DefAVioWindowProc)));
+}
Index: trunk/src/emx/src/lib/os2_386/que.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/que.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/que.imp	(revision 18)
@@ -0,0 +1,11 @@
+;
+; que.imp
+;
+DosCloseQueue           quecalls  11 1
+DosCreateQueue          quecalls  16 3
+DosOpenQueue            quecalls  15 3
+DosPeekQueue            quecalls  13 8
+DosPurgeQueue           quecalls  10 1
+DosQueryQueue           quecalls  12 2
+DosReadQueue            quecalls   9 8
+DosWriteQueue           quecalls  14 5
Index: trunk/src/emx/src/lib/os2_386/revision.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/revision.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/revision.c	(revision 18)
@@ -0,0 +1,19 @@
+/* revision.c (emx+gcc) -- Copyright (c) 1993-1999 by Eberhard Mattes */
+
+#define INCL_REXXSAA
+#include <os2emx.h>
+
+static char const revision[] = "60";
+
+ULONG emx_revision (PCSZ name, LONG argc, const RXSTRING *argv,
+                    PCSZ queuename, PRXSTRING retstr)
+{
+  int i;
+
+  if (argc != 0)
+    return 1;
+  for (i = 0; revision[i] != 0; ++i)
+    retstr->strptr[i] = revision[i];
+  retstr->strlength = i;
+  return 0;
+}
Index: trunk/src/emx/src/lib/os2_386/rexx.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/rexx.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/rexx.imp	(revision 18)
@@ -0,0 +1,8 @@
+;
+; rexx.imp
+;
+RexxStart               rexx       1 9
+RexxVariablePool        rexx       2 1
+RexxSetHalt             rexx       3 2
+RexxSetTrace            rexx       4 2
+RexxResetTrace          rexx       5 2
Index: trunk/src/emx/src/lib/os2_386/rexxapi.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/rexxapi.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/rexxapi.imp	(revision 18)
@@ -0,0 +1,32 @@
+;
+; rexxapi.imp
+;
+RexxAddMacro                    rexxapi   22 3
+RexxAddQueue                    rexxapi    3 ?
+RexxCallExit                    rexxapi   15 ?
+RexxCallFunction                rexxapi   21 ?
+RexxCallSubcom                  rexxapi   16 ?
+RexxClearMacroSpace             rexxapi   24 0
+RexxCreateQueue                 rexxapi    1 ?
+RexxDeleteQueue                 rexxapi    2 ?
+RexxDeregisterExit              rexxapi   13 2
+RexxDeregisterFunction          rexxapi   19 1
+RexxDeregisterSubcom            rexxapi    9 2
+RexxDropMacro                   rexxapi   23 1
+RexxExecuteMacroFunction        rexxapi   29 ?
+RexxLoadMacroSpace              rexxapi   25 3
+RexxLoadSubcom                  rexxapi   10 ?
+RexxPullQueue                   rexxapi    4 ?
+RexxQueryExit                   rexxapi   14 4
+RexxQueryFunction               rexxapi   20 1
+RexxQueryMacro                  rexxapi   26 2
+RexxQueryQueue                  rexxapi    5 ?
+RexxQuerySubcom                 rexxapi    8 4
+RexxRegisterExitDll             rexxapi   11 5
+RexxRegisterExitExe             rexxapi   12 3
+RexxRegisterFunctionDll         rexxapi   17 3
+RexxRegisterFunctionExe         rexxapi   18 2
+RexxRegisterSubcomDll           rexxapi    6 5
+RexxRegisterSubcomExe           rexxapi    7 3
+RexxReorderMacro                rexxapi   27 2
+RexxSaveMacroSpace              rexxapi   28 3
Index: trunk/src/emx/src/lib/os2_386/ses.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/ses.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/ses.imp	(revision 18)
@@ -0,0 +1,7 @@
+;
+; ses.imp
+;
+DosSelectSession        sesmgr    38 1
+DosSetSession           sesmgr    39 2
+DosStartSession         sesmgr    37 3
+DosStopSession          sesmgr    40 2
Index: trunk/src/emx/src/lib/os2_386/shl.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/shl.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/shl.imp	(revision 18)
@@ -0,0 +1,32 @@
+;
+; shl.imp
+;
+PrfAddProgram                   pmshapi 109 3
+PrfChangeProgram                pmshapi 110 3
+PrfCloseProfile                 pmshapi 103 1
+PrfDestroyGroup                 pmshapi 106 2
+PrfOpenProfile                  pmshapi 102 2
+PrfQueryDefinition              pmshapi 111 4
+PrfQueryProfile                 pmshapi 107 2
+PrfQueryProfileData             pmshapi 117 5
+PrfQueryProfileInt              pmshapi 114 4
+PrfQueryProfileSize             pmshapi 101 4
+PrfQueryProfileString           pmshapi 115 6
+PrfQueryProgramTitles           pmshapi 113 5
+PrfRemoveProgram                pmshapi 104 2
+PrfReset                        pmshapi 108 2
+PrfWriteProfileData             pmshapi 118 5
+PrfWriteProfileString           pmshapi 116 4
+WinAddSwitchEntry               pmshapi 120 1
+WinChangeSwitchEntry            pmshapi 123 2
+WinCreateSwitchEntry            pmshapi 121 2
+WinQuerySessionTitle            pmshapi 122 4
+WinQuerySwitchEntry             pmshapi 124 2
+WinQuerySwitchHandle            pmshapi 125 2
+WinQuerySwitchList              pmshapi 126 3
+WinQueryTaskSizePos             pmshapi 127 3
+WinQueryTaskTitle               pmshapi 128 3
+WinRemoveSwitchEntry            pmshapi 129 1
+WinStartApp                     pmshapi 119 5
+WinSwitchToProgram              pmshapi 131 1
+WinTerminateApp                 pmshapi 130 1
Index: trunk/src/emx/src/lib/os2_386/som.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/som.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/som.imp	(revision 18)
@@ -0,0 +1,50 @@
+;
+; som.imp
+;
+SOMCalloc                       som        1 ?
+SOMClassCClassData              som        2 ?
+SOMClassClassData               som        3 ?
+SOMClassInitFuncName            som        4 ?
+SOMClassMgrCClassData           som        5 ?
+SOMClassMgrClassData            som        6 ?
+SOMClassMgrNewClass             som       20 ?
+SOMClassMgrObject               som        7 ?
+SOMClassNewClass                som       21 ?
+SOMDeleteModule                 som        8 ?
+SOMError                        som        9 ?
+SOMFree                         som       10 ?
+SOMLoadModule                   som       11 ?
+SOMMalloc                       som       12 ?
+SOMObjectCClassData             som       13 ?
+SOMObjectClassData              som       14 ?
+SOMObjectNewClass               som       22 ?
+SOMOutCharRoutine               som       15 ?
+SOMRealloc                      som       16 ?
+SOM_AssertLevel                 som       17 ?
+SOM_TraceLevel                  som       18 ?
+SOM_WarnLevel                   som       19 ?
+somAssert                       som       23 5
+somBeginPersistentIds           som       24 0
+somCheckArgs                    som       25 ?
+somCheckId                      som       26 1
+somCompareIds                   som       27 2
+somConstructClass               som       28 4
+somDataResolve                  som       47 2
+somEndPersistentIds             som       29 0
+somEnvironmentNew               som       30 0
+somIdFromString                 som       31 1
+somLPrintf                      som       32 ?
+somParentResolve                som       33 2
+somPrefixLevel                  som       34 1
+somPrintf                       som       35 ?
+somRegisterId                   som       36 1
+somResolve                      som       37 2
+somSaveMetrics                  som       38 ?
+somSetExpectedIds               som       39 2
+somStringFromId                 som       40 1
+somTest                         som       41 5
+somTestCls                      som       42 4
+somTotalRegIds                  som       43 0
+somUniqueKey                    som       44 1
+somVprintf                      som       45 2
+somWriteMetrics                 som       46 ?
Index: trunk/src/emx/src/lib/os2_386/spl.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/spl.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/spl.imp	(revision 18)
@@ -0,0 +1,60 @@
+;
+; spl.imp
+;
+PrtAbort                        pmspl 375 1
+PrtClose                        pmspl 373 1
+PrtDevIOCtl                     pmspl 372 5
+PrtOpen                         pmspl 370 8
+PrtWrite                        pmspl 371 4
+SplControlDevice                pmspl 380 3
+SplCopyJob                      pmspl 442 6
+SplCreateDevice                 pmspl 401 4
+SplCreatePort                   pmspl 413 6
+SplCreateQueue                  pmspl 393 4
+SplDeleteDevice                 pmspl 403 2
+SplDeleteJob                    pmspl 386 3
+SplDeletePort                   pmspl 414 2
+SplDeleteQueue                  pmspl 396 2
+SplEnumDevice                   pmspl 382 8
+SplEnumDriver                   pmspl 406 8
+SplEnumJob                      pmspl 392 9
+SplEnumPort                     pmspl 408 8
+SplEnumPrinter                  pmspl 441 9
+SplEnumQueue                    pmspl 399 8
+SplEnumQueueProcessor           pmspl 407 8
+SplHoldJob                      pmspl 385 3
+SplHoldQueue                    pmspl 394 2
+SplInit                         pmspl 320 ?
+SplMessageBox                   pmspl 307 7
+SplPurgeQueue                   pmspl 404 2
+SplQmAbort                      pmspl 305 1
+SplQmAbortDoc                   pmspl 308 1
+SplQmClose                      pmspl 306 1
+SplQmEndDoc                     pmspl 303 1
+SplQmGetJobID                   pmspl 608 5
+SplQmNewPage                    pmspl 607 2
+SplQmOpen                       pmspl 301 3
+SplQmSetup                      pmspl 443 ?
+SplQmStartDoc                   pmspl 302 2
+SplQmWrite                      pmspl 304 3
+SplQueryDevice                  pmspl 381 6
+SplQueryDriver                  pmspl 446 7
+SplQueryJob                     pmspl 390 7
+SplQueryJobId                   pmspl 405 ?
+SplQueryPath                    pmspl 412 ?
+SplQueryPort                    pmspl 410 6
+SplQueryQueue                   pmspl 397 6
+SplReleaseJob                   pmspl 384 3
+SplReleaseQueue                 pmspl 395 2
+SplSetDevice                    pmspl 402 6
+SplSetDriver                    pmspl 447 7
+SplSetJob                       pmspl 391 7
+SplSetPort                      pmspl 411 6
+SplSetQueue                     pmspl 398 6
+SplStdClose                     pmspl 351 1
+SplStdDelete                    pmspl 354 1
+SplStdGetBits                   pmspl 355 4
+SplStdOpen                      pmspl 350 1
+SplStdQueryLength               pmspl 356 1
+SplStdStart                     pmspl 352 1
+SplStdStop                      pmspl 353 1
Index: trunk/src/emx/src/lib/os2_386/vio1.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio1.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio1.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio1.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16EndPopUp) ();
+
+USHORT VioEndPopUp (HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16EndPopUp)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio10.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio10.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio10.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio10.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtCellStr) ();
+
+USHORT VioWrtCellStr (PCCH pchCellStr, USHORT cb, USHORT usRow,
+                      USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PCH)pchCellStr);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtCellStr)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio11.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio11.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio11.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio11.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16PopUp) ();
+
+USHORT VioPopUp (PUSHORT pfWait, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfWait);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16PopUp)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio12.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio12.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio12.c	(revision 18)
@@ -0,0 +1,21 @@
+/* vio12.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrollRt) ();
+
+USHORT VioScrollRt (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbCol, PBYTE pCell, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2+2+4+2);
+           _THUNK_SHORT (usTopRow);
+           _THUNK_SHORT (usLeftCol);
+           _THUNK_SHORT (usBotRow);
+           _THUNK_SHORT (usRightCol);
+           _THUNK_SHORT (cbCol);
+           _THUNK_FLAT (pCell);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrollRt)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio13.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio13.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio13.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio13.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtCharStr) ();
+
+USHORT VioWrtCharStr (PCCH pch, USHORT cb, USHORT usRow, USHORT usColumn,
+                      HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PCH)pch);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtCharStr)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio15.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio15.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio15.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio15.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetCurPos) ();
+
+USHORT VioSetCurPos (USHORT usRow, USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetCurPos)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio16.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio16.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio16.imp	(revision 18)
@@ -0,0 +1,61 @@
+;
+; vio16.imp
+;
+Vio16Associate                  viocalls  55 F
+Vio16CheckCharType              viocalls  75 F
+Vio16CreateLogFont              viocalls  60 F
+Vio16CreatePS                   viocalls  56 F
+Vio16DeleteSetId                viocalls  57 F
+Vio16DeRegister                 viocalls   6 F
+Vio16DestroyPS                  viocalls  61 F
+Vio16EndPopUp                   viocalls   1 F
+Vio16GetAnsi                    viocalls   3 F
+Vio16GetBuf                     viocalls  31 F
+Vio16GetConfig                  viocalls  46 F
+Vio16GetCp                      viocalls  40 F
+Vio16GetCurPos                  viocalls   9 F
+Vio16GetCurType                 viocalls  27 F
+Vio16GetDeviceCellSize          viocalls  58 F
+Vio16GetFont                    viocalls  29 F
+Vio16GetMode                    viocalls  21 F
+Vio16GetOrg                     viocalls  59 F
+Vio16GetPhysBuf                 viocalls   2 F
+Vio16GetPSAddress               viocalls  67 F
+Vio16GetState                   viocalls  49 F
+Vio16GlobalReg                  viocalls  70 F
+Vio16ModeUndo                   viocalls  35 F
+Vio16ModeWait                   viocalls  37 F
+Vio16PopUp                      viocalls  11 F
+Vio16PrtSc                      viocalls   8 F
+Vio16PrtScToggle                viocalls  50 F
+Vio16QueryFonts                 viocalls  64 F
+Vio16QuerySetIds                viocalls  62 F
+Vio16ReadCellStr                viocalls  24 F
+Vio16ReadCharStr                viocalls  30 F
+Vio16Register                   viocalls  45 F
+Vio16SavRedrawUndo              viocalls  28 F
+Vio16SavRedrawWait              viocalls  25 F
+Vio16ScrLock                    viocalls  23 F
+Vio16ScrollDn                   viocalls  47 F
+Vio16ScrollLf                   viocalls  44 F
+Vio16ScrollRt                   viocalls  12 F
+Vio16ScrollUp                   viocalls   7 F
+Vio16ScrUnLock                  viocalls  18 F
+Vio16SetAnsi                    viocalls   5 F
+Vio16SetCp                      viocalls  42 F
+Vio16SetCurPos                  viocalls  15 F
+Vio16SetCurType                 viocalls  32 F
+Vio16SetDeviceCellSize          viocalls  65 F
+Vio16SetFont                    viocalls  33 F
+Vio16SetMode                    viocalls  22 F
+Vio16SetOrg                     viocalls  63 F
+Vio16SetState                   viocalls  51 F
+Vio16ShowBuf                    viocalls  43 F
+Vio16ShowPS                     viocalls  66 F
+Vio16WrtCellStr                 viocalls  10 F
+Vio16WrtCharStr                 viocalls  13 F
+Vio16WrtCharStrAtt              viocalls  48 F
+Vio16WrtNAttr                   viocalls  26 F
+Vio16WrtNCell                   viocalls  52 F
+Vio16WrtNChar                   viocalls  53 F
+Vio16WrtTTY                     viocalls  19 F
Index: trunk/src/emx/src/lib/os2_386/vio18.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio18.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio18.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio18.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrUnLock) ();
+
+USHORT VioScrUnLock (HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrUnLock)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio19.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio19.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio19.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio19.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtTTY) ();
+
+USHORT VioWrtTTY (PCCH pch, USHORT cb, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2);
+           _THUNK_FLAT ((PCH)pch);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtTTY)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio2.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio2.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio2.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio2.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetPhysBuf) ();
+
+USHORT VioGetPhysBuf (PVIOPHYSBUF pvioPhysBuf, USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioPhysBuf);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16GetPhysBuf)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio21.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio21.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio21.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio21.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetMode) ();
+
+USHORT VioGetMode (PVIOMODEINFO pvioModeInfo, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioModeInfo);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetMode)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio22.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio22.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio22.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio22.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetMode) ();
+
+USHORT VioSetMode (PVIOMODEINFO pvioModeInfo, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioModeInfo);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetMode)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio23.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio23.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio23.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio23.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrLock) ();
+
+USHORT VioScrLock (USHORT fWait, PUCHAR pfNotLocked, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (fWait);
+           _THUNK_FLAT (pfNotLocked);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrLock)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio24.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio24.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio24.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio24.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ReadCellStr) ();
+
+USHORT VioReadCellStr (PCH pchCellStr, PUSHORT pcb, USHORT usRow,
+                       USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2+2+2);
+           _THUNK_FLAT (pchCellStr);
+           _THUNK_FLAT (pcb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ReadCellStr)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio25.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio25.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio25.c	(revision 18)
@@ -0,0 +1,17 @@
+/* vio25.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SavRedrawWait) ();
+
+USHORT VioSavRedrawWait (USHORT usRedrawInd, PUSHORT pusNotifyType,
+                         USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (usRedrawInd);
+           _THUNK_FLAT (pusNotifyType);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16SavRedrawWait)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio26.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio26.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio26.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio26.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtNAttr) ();
+
+USHORT VioWrtNAttr (const BYTE *pAttr, USHORT cb, USHORT usRow,
+                    USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PBYTE)pAttr);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtNAttr)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio27.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio27.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio27.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio27.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetCurType) ();
+
+USHORT VioGetCurType (PVIOCURSORINFO pvioCursorInfo, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioCursorInfo);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetCurType)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio28.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio28.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio28.c	(revision 18)
@@ -0,0 +1,17 @@
+/* vio28.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SavRedrawUndo) ();
+
+USHORT VioSavRedrawUndo (USHORT usOwnerInd, USHORT usKillInd,
+                         USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usOwnerInd);
+           _THUNK_SHORT (usKillInd);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16SavRedrawUndo)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio29.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio29.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio29.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio29.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetFont) ();
+
+USHORT VioGetFont (PVIOFONTINFO pviofi, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pviofi);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetFont)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio3.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio3.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio3.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio3.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetAnsi) ();
+
+USHORT VioGetAnsi (PUSHORT pfAnsi, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfAnsi);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetAnsi)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio30.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio30.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio30.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio30.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ReadCharStr) ();
+
+USHORT VioReadCharStr (PCH pch, PUSHORT pcb, USHORT usRow, USHORT usColumn,
+                       HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2+2+2);
+           _THUNK_FLAT (pch);
+           _THUNK_FLAT (pcb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ReadCharStr)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio31.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio31.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio31.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio31.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetBuf) ();
+
+USHORT VioGetBuf (PULONG pLVB, PUSHORT pcbLVB, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pLVB);
+           _THUNK_FLAT (pcbLVB);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetBuf)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio32.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio32.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio32.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio32.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetCurType) ();
+
+USHORT VioSetCurType (PVIOCURSORINFO pvioCursorInfo, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioCursorInfo);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetCurType)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio33.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio33.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio33.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio33.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetFont) ();
+
+USHORT VioSetFont (PVIOFONTINFO pviofi, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pviofi);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetFont)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio35.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio35.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio35.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio35.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ModeUndo) ();
+
+USHORT VioModeUndo (USHORT usOwnerInd, USHORT usKillInd, USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usOwnerInd);
+           _THUNK_SHORT (usKillInd);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16ModeUndo)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio37.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio37.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio37.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio37.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ModeWait) ();
+
+USHORT VioModeWait (USHORT usReqType, PUSHORT pNotifyType, USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (usReqType);
+           _THUNK_FLAT (pNotifyType);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16ModeWait)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio40.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio40.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio40.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio40.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetCp) ();
+
+USHORT VioGetCp (USHORT usReserved, PUSHORT pusCodePage, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (usReserved);
+           _THUNK_FLAT (pusCodePage);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetCp)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio42.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio42.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio42.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio42.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetCp) ();
+
+USHORT VioSetCp (USHORT usReserved, USHORT usCodePage, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usReserved);
+           _THUNK_SHORT (usCodePage);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetCp)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio43.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio43.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio43.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio43.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ShowBuf) ();
+
+USHORT VioShowBuf (USHORT offLVB, USHORT cb, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (offLVB);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ShowBuf)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio44.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio44.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio44.c	(revision 18)
@@ -0,0 +1,21 @@
+/* vio44.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrollLf) ();
+
+USHORT VioScrollLf (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbCol, PBYTE pCell, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2+2+4+2);
+           _THUNK_SHORT (usTopRow);
+           _THUNK_SHORT (usLeftCol);
+           _THUNK_SHORT (usBotRow);
+           _THUNK_SHORT (usRightCol);
+           _THUNK_SHORT (cbCol);
+           _THUNK_FLAT (pCell);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrollLf)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio45.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio45.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio45.c	(revision 18)
@@ -0,0 +1,18 @@
+/* vio45.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16Register) ();
+
+USHORT VioRegister (PCSZ pszModName, PCSZ pszEntryName,
+                    ULONG ulFunMask1, ULONG ulFunMask2)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+4);
+           _THUNK_FLAT ((PSZ)pszModName);
+           _THUNK_FLAT ((PSZ)pszEntryName);
+           _THUNK_LONG (ulFunMask1);
+           _THUNK_LONG (ulFunMask2);
+           _THUNK_CALL (Vio16Register)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio46.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio46.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio46.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio46.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetConfig) ();
+
+USHORT VioGetConfig (USHORT usConfigId, PVIOCONFIGINFO pvioin, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (usConfigId);
+           _THUNK_FLAT (pvioin);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetConfig)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio47.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio47.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio47.c	(revision 18)
@@ -0,0 +1,21 @@
+/* vio47.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrollDn) ();
+
+USHORT VioScrollDn (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+                    USHORT usRightCol, USHORT cbLines, PBYTE pCell, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2+2+4+2);
+           _THUNK_SHORT (usTopRow);
+           _THUNK_SHORT (usLeftCol);
+           _THUNK_SHORT (usBotRow);
+           _THUNK_SHORT (usRightCol);
+           _THUNK_SHORT (cbLines);
+           _THUNK_FLAT (pCell);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrollDn)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio48.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio48.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio48.c	(revision 18)
@@ -0,0 +1,20 @@
+/* vio48.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtCharStrAtt) ();
+
+USHORT VioWrtCharStrAtt (PCCH pch, USHORT cb, USHORT usRow,
+                         USHORT usColumn, PBYTE pAttr, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+4+2);
+           _THUNK_FLAT ((PCH)pch);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_FLAT (pAttr);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtCharStrAtt)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio49.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio49.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio49.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio49.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetState) ();
+
+USHORT VioGetState (PVOID pvioState, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioState);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetState)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio5.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio5.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio5.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio5.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetAnsi) ();
+
+USHORT VioSetAnsi (USHORT fAnsi, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2);
+           _THUNK_SHORT (fAnsi);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetAnsi)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio50.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio50.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio50.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio50.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16PrtScToggle) ();
+
+USHORT VioPrtScToggle (HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16PrtScToggle)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio51.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio51.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio51.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio51.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetState) ();
+
+USHORT VioSetState (CPVOID pvioState, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT ((PVOID)pvioState);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetState)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio52.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio52.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio52.c	(revision 18)
@@ -0,0 +1,20 @@
+/* vio52.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtNCell) ();
+
+USHORT VioWrtNCell (const BYTE *pCell, USHORT cb, USHORT usRow,
+                    USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PBYTE)pCell);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtNCell)));
+}
+
Index: trunk/src/emx/src/lib/os2_386/vio53.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio53.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio53.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio52.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtNChar) ();
+
+USHORT VioWrtNChar (PCCH pch, USHORT cb, USHORT usRow, USHORT usColumn,
+                    HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PCH)pch);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtNChar)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio55.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio55.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio55.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio55.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16Associate) ();
+
+USHORT VioAssociate (HDC hdc, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_LONG ((ULONG)hdc);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16Associate)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio56.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio56.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio56.c	(revision 18)
@@ -0,0 +1,20 @@
+/* vio56.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16CreatePS) ();
+
+USHORT VioCreatePS (PHVPS phvps, SHORT sDepth, SHORT sWidth, SHORT sFormat,
+                    SHORT sAttrs, HVPS hvpsReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2+2);
+           _THUNK_FLAT (phvps);
+           _THUNK_SHORT (sDepth);
+           _THUNK_SHORT (sWidth);
+           _THUNK_SHORT (sFormat);
+           _THUNK_SHORT (sAttrs);
+           _THUNK_SHORT (hvpsReserved);
+           _THUNK_CALL (Vio16CreatePS)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio57.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio57.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio57.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio57.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16DeleteSetId) ();
+
+USHORT VioDeleteSetId (LONG llcid, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_LONG (llcid);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16DeleteSetId)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio58.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio58.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio58.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio58.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetDeviceCellSize) ();
+
+USHORT VioGetDeviceCellSize (PSHORT psHeight, PSHORT psWidth, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (psHeight);
+           _THUNK_FLAT (psWidth);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16GetDeviceCellSize)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio59.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio59.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio59.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio59.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetOrg) ();
+
+USHORT VioGetOrg (PSHORT psRow, PSHORT psColumn, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (psRow);
+           _THUNK_FLAT (psColumn);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16GetOrg)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio6.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio6.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio6.c	(revision 18)
@@ -0,0 +1,13 @@
+/* vio6.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16DeRegister) ();
+
+USHORT VioDeRegister (VOID)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (0);
+           _THUNK_CALL (Vio16DeRegister)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio60.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio60.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio60.c	(revision 18)
@@ -0,0 +1,18 @@
+/* vio60.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16CreateLogFont) ();
+
+USHORT VioCreateLogFont (PFATTRS pfatattrs, LONG llcid, PSTR8 pName,
+                         HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+2);
+           _THUNK_FLAT (pfatattrs);
+           _THUNK_LONG (llcid);
+           _THUNK_FLAT (pName);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16CreateLogFont)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio61.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio61.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio61.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio61.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16DestroyPS) ();
+
+USHORT VioDestroyPS (HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16DestroyPS)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio62.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio62.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio62.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio62.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16QuerySetIds) ();
+
+USHORT VioQuerySetIds (PLONG allcids, PSTR8 pNames, PLONG alTypes, LONG lcount,
+                       HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+4+2);
+           _THUNK_FLAT (allcids);
+           _THUNK_FLAT (pNames);
+           _THUNK_FLAT (alTypes);
+           _THUNK_LONG (lcount);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16QuerySetIds)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio63.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio63.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio63.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio63.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetOrg) ();
+
+USHORT VioSetOrg (SHORT sRow, SHORT sColumn, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (sRow);
+           _THUNK_SHORT (sColumn);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16SetOrg)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio64.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio64.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio64.c	(revision 18)
@@ -0,0 +1,22 @@
+/* vio64.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16QueryFonts) ();
+
+USHORT VioQueryFonts (PLONG plRemfonts, PFONTMETRICS afmMetrics,
+                      LONG lMetricsLength, PLONG plFonts, PSZ pszFacename,
+                      ULONG flOptions, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+4+4+4+2);
+           _THUNK_FLAT (plRemfonts);
+           _THUNK_FLAT (afmMetrics);
+           _THUNK_LONG (lMetricsLength);
+           _THUNK_FLAT (plFonts);
+           _THUNK_FLAT (pszFacename);
+           _THUNK_LONG (flOptions);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16QueryFonts)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio65.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio65.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio65.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio65.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetDeviceCellSize) ();
+
+USHORT VioSetDeviceCellSize (SHORT sHeight, SHORT sWidth, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (sHeight);
+           _THUNK_SHORT (sWidth);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16SetDeviceCellSize)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio66.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio66.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio66.c	(revision 18)
@@ -0,0 +1,17 @@
+/* vio66.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ShowPS) ();
+
+USHORT VioShowPS (SHORT sDepth, SHORT sWidth, SHORT soffCell, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2);
+           _THUNK_SHORT (sDepth);
+           _THUNK_SHORT (sWidth);
+           _THUNK_SHORT (soffCell);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16ShowPS)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio7.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio7.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio7.c	(revision 18)
@@ -0,0 +1,21 @@
+/* vio7.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrollUp) ();
+
+USHORT VioScrollUp (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbLines, PBYTE pCell, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2+2+4+2);
+           _THUNK_SHORT (usTopRow);
+           _THUNK_SHORT (usLeftCol);
+           _THUNK_SHORT (usBotRow);
+           _THUNK_SHORT (usRightCol);
+           _THUNK_SHORT (cbLines);
+           _THUNK_FLAT (pCell);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrollUp)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio70.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio70.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio70.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio70.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GlobalReg) ();
+
+USHORT VioGlobalReg (PCSZ pszModName, PCSZ pszEntryName,
+                     ULONG ulFunMask1, ULONG ulFunMask2, USHORT usReturn)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+4+2);
+           _THUNK_FLAT ((PSZ)pszModName);
+           _THUNK_FLAT ((PSZ)pszEntryName);
+           _THUNK_LONG (ulFunMask1);
+           _THUNK_LONG (ulFunMask2);
+           _THUNK_SHORT (usReturn);
+           _THUNK_CALL (Vio16GlobalReg)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio75.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio75.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio75.c	(revision 18)
@@ -0,0 +1,18 @@
+/* vio75.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16CheckCharType) ();
+
+USHORT VioCheckCharType (PUSHORT pType, USHORT usRow, USHORT usColumn,
+                         HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2);
+           _THUNK_FLAT (pType);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16CheckCharType)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio8.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio8.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio8.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio8.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16PrtSc) ();
+
+USHORT VioPrtSc (HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16PrtSc)));
+}
Index: trunk/src/emx/src/lib/os2_386/vio9.c
===================================================================
--- trunk/src/emx/src/lib/os2_386/vio9.c	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/vio9.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio9.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetCurPos) ();
+
+USHORT VioGetCurPos (PUSHORT pusRow, PUSHORT pusColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pusRow);
+           _THUNK_FLAT (pusColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetCurPos)));
+}
Index: trunk/src/emx/src/lib/os2_386/win.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/win.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/win.imp	(revision 18)
@@ -0,0 +1,264 @@
+;
+; win.imp
+;
+WinAddAtom                      pmwin  700 2
+WinAlarm                        pmwin  701 2
+WinBeginEnumWindows             pmwin  702 1
+WinBeginPaint                   pmwin  703 3
+WinBroadcastMsg                 pmwin  901 5
+WinCalcFrameRect                pmwin  704 3
+WinCallMsgFilter                pmwin  905 3
+WinCancelShutdown               pmwin  705 2
+WinCheckInput                   pmwin  998 1
+WinCloseClipbrd                 pmwin  707 1
+WinCompareStrings               pmwin  708 6
+WinCopyAccelTable               pmwin  709 3
+WinCopyRect                     pmwin  710 3
+WinCpTranslateChar              pmwin  711 4
+WinCpTranslateString            pmwin  712 6
+WinCreateAccelTable             pmwin  713 2
+WinCreateAtomTable              pmwin  714 2
+WinCreateCursor                 pmwin  715 7
+WinCreateDlg                    pmwin  922 5
+WinCreateFrameControls          pmwin  906 3
+WinCreateMenu                   pmwin  907 2
+WinCreateMsgQueue               pmwin  716 2
+WinCreatePointer                pmwin  717 5
+WinCreatePointerIndirect        pmwin  942 2
+WinCreateStdWindow              pmwin  908 9
+WinCreateWindow                 pmwin  909 13
+WinDdeInitiate                  pmwin  718 4
+WinDdePostMsg                   pmwin  719 5
+WinDdeRespond                   pmwin  720 5
+WinDefDlgProc                   pmwin  910 4
+WinDefWindowProc                pmwin  911 4
+WinDeleteAtom                   pmwin  721 2
+WinDeleteLibrary                pmwin  722 2
+WinDeleteProcedure              pmwin  987 2
+WinDestroyAccelTable            pmwin  723 1
+WinDestroyAtomTable             pmwin  724 1
+WinDestroyCursor                pmwin  725 1
+WinDestroyMsgQueue              pmwin  726 1
+WinDestroyPointer               pmwin  727 1
+WinDestroyWindow                pmwin  728 1
+WinDismissDlg                   pmwin  729 2
+WinDispatchMsg                  pmwin  912 2
+WinDlgBox                       pmwin  923 6
+WinDrawBitmap                   pmwin  730 7
+WinDrawBorder                   pmwin  731 7
+WinDrawPointer                  pmwin  732 5
+WinDrawText                     pmwin  913 7
+WinEmptyClipbrd                 pmwin  733 1
+WinEnablePhysInput              pmwin  734 2
+WinEnableWindow                 pmwin  735 2
+WinEnableWindowUpdate           pmwin  736 2
+WinEndEnumWindows               pmwin  737 1
+WinEndPaint                     pmwin  738 1
+WinEnumClipbrdFmts              pmwin  739 2
+WinEnumDlgItem                  pmwin  740 3
+WinEqualRect                    pmwin  741 3
+WinExcludeUpdateRegion          pmwin  742 2
+WinFillRect                     pmwin  743 3
+WinFindAtom                     pmwin  744 2
+WinFlashWindow                  pmwin  745 2
+WinFocusChange                  pmwin  746 3
+WinFreeErrorInfo                pmwin  748 1
+WinGetClipPS                    pmwin  749 3
+WinGetCurrentTime               pmwin  750 1
+WinGetDlgMsg                    pmwin  914 2
+WinGetErasePS                   pmwin  952 ?
+WinGetErrorInfo                 pmwin  751 1
+WinGetKeyState                  pmwin  752 2
+WinGetLastError                 pmwin  753 1
+WinGetMaxPosition               pmwin  754 2
+WinGetMinPosition               pmwin  755 3
+WinGetMsg                       pmwin  915 5
+WinGetNextWindow                pmwin  756 1
+WinGetPS                        pmwin  757 1
+WinGetPhysKeyState              pmwin  758 2
+WinGetScreenPS                  pmwin  759 1
+WinGetSysBitmap                 pmwin  760 2
+WinInSendMsg                    pmwin  761 1
+WinInflateRect                  pmwin  762 4
+WinInitialize                   pmwin  763 1
+WinIntersectRect                pmwin  764 4
+WinInvalidateRect               pmwin  765 3
+WinInvalidateRegion             pmwin  766 3
+WinInvertRect                   pmwin  767 2
+WinIsChild                      pmwin  768 2
+WinIsPhysInputEnabled           pmwin  769 1
+WinIsRectEmpty                  pmwin  770 2
+WinIsThreadActive               pmwin  771 1
+WinIsWindow                     pmwin  772 2
+WinIsWindowEnabled              pmwin  773 1
+WinIsWindowShowing              pmwin  774 1
+WinIsWindowVisible              pmwin  775 1
+WinLoadAccelTable               pmwin  776 3
+WinLoadDlg                      pmwin  924 6
+WinLoadLibrary                  pmwin  777 2
+WinLoadMenu                     pmwin  778 3
+WinLoadMessage                  pmwin  779 5
+WinLoadPointer                  pmwin  780 3
+WinLoadProcedure                pmwin  986 3
+WinLoadString                   pmwin  781 5
+WinLockPointerUpdate            pmwin  997 3
+WinLockInput                    pmwin  995 2
+WinLockVisRegions               pmwin  782 2
+WinLockWindowUpdate             pmwin  784 2
+WinMakePoints                   pmwin  785 3
+WinMakeRect                     pmwin  786 2
+WinMapDlgPoints                 pmwin  787 4
+WinMapWindowPoints              pmwin  788 4
+WinMessageBox                   pmwin  789 6
+WinMessageBox2                  pmwin 1015 6
+WinMsgMuxSemWait                pmwin  916 3
+WinMsgSemWait                   pmwin  790 2
+WinMultWindowFromIDs            pmwin  917 4
+WinNextChar                     pmwin  791 4
+WinOffsetRect                   pmwin  792 4
+WinOpenClipbrd                  pmwin  793 1
+WinOpenWindowDC                 pmwin  794 1
+WinPeekMsg                      pmwin  918 6
+WinPopupMenu                    pmwin  937 7
+WinPostMsg                      pmwin  919 4
+WinPostQueueMsg                 pmwin  902 4
+WinPrevChar                     pmwin  795 5
+WinProcessDlg                   pmwin  796 1
+WinPtInRect                     pmwin  797 3
+WinQueueFromID                  pmwin  993 3
+WinQueryAccelTable              pmwin  798 2
+WinQueryActiveWindow            pmwin  799 1
+WinQueryAnchorBlock             pmwin  800 1
+WinQueryAtomLength              pmwin  801 2
+WinQueryAtomName                pmwin  802 4
+WinQueryAtomUsage               pmwin  803 2
+WinQueryCapture                 pmwin  804 1
+WinQueryClassInfo               pmwin  925 3
+WinQueryClassName               pmwin  805 3
+WinQueryClassThunkProc          pmwin  931 1
+WinQueryClipbrdData             pmwin  806 2
+WinQueryClipbrdFmtInfo          pmwin  807 3
+WinQueryClipbrdOwner            pmwin  808 1
+WinQueryClipbrdViewer           pmwin  809 1
+WinQueryCp                      pmwin  810 1
+WinQueryCpList                  pmwin  811 3
+WinQueryCursorInfo              pmwin  812 2
+WinQueryDesktopBkgnd            pmwin  936 2
+WinQueryDesktopWindow           pmwin  813 2
+WinQueryDlgItemShort            pmwin  814 4
+WinQueryDlgItemText             pmwin  815 4
+WinQueryDlgItemTextLength       pmwin  816 2
+WinQueryFocus                   pmwin  817 1
+WinQueryMsgPos                  pmwin  818 2
+WinQueryMsgTime                 pmwin  819 1
+WinQueryObjectWindow            pmwin  820 1
+WinQueryPointer                 pmwin  821 1
+WinQueryPointerInfo             pmwin  822 2
+WinQueryPointerPos              pmwin  823 2
+WinQueryPresParam               pmwin  939 7
+WinQueryQueueInfo               pmwin  824 3
+WinQueryQueueStatus             pmwin  825 1
+WinQuerySendMsg                 pmwin  990 4
+WinQuerySysColor                pmwin  826 3
+WinQuerySysModalWindow          pmwin  827 1
+WinQuerySysPointer              pmwin  828 3
+WinQuerySysPointerData          pmwin 1003 3
+WinQuerySysValue                pmwin  829 2
+WinQuerySystemAtomTable         pmwin  830 0
+WinQueryUpdateRect              pmwin  831 2
+WinQueryUpdateRegion            pmwin  832 2
+WinQueryVersion                 pmwin  833 1
+WinQueryVisibleRegion           pmwin 1000 2
+WinQueryWindow                  pmwin  834 2
+WinQueryWindowDC                pmwin  835 1
+WinQueryWindowModel             pmwin  934 1
+WinQueryWindowPos               pmwin  837 2
+WinQueryWindowProcess           pmwin  838 3
+WinQueryWindowPtr               pmwin  839 2
+WinQueryWindowRect              pmwin  840 2
+WinQueryWindowText              pmwin  841 3
+WinQueryWindowTextLength        pmwin  842 1
+WinQueryWindowThunkProc         pmwin  933 1
+WinQueryWindowULong             pmwin  843 2
+WinQueryWindowUShort            pmwin  844 2
+WinRealizePalette               pmwin  941 3
+WinRegisterClass                pmwin  926 5
+WinRegisterUserDatatype         pmwin  845 4
+WinRegisterUserMsg              pmwin  846 7
+WinReleaseErasePS               pmwin  953 ?
+WinReleaseHook                  pmwin  927 5
+WinReleasePS                    pmwin  848 1
+WinRemovePresParam              pmwin  940 2
+WinReplyMsg                     pmwin  991 4
+WinRequestMutexSem              pmwin  979 2
+WinSaveWindowPos                pmwin  943 3
+WinScrollWindow                 pmwin  849 8
+WinSendDlgItemMsg               pmwin  903 5
+WinSendMsg                      pmwin  920 4
+WinSetAccelTable                pmwin  850 3
+WinSetActiveWindow              pmwin  851 2
+WinSetCapture                   pmwin  852 2
+WinSetClassMsgInterest          pmwin  853 4
+WinSetClassThunkProc            pmwin  930 2
+WinSetClipbrdData               pmwin  854 4
+WinSetClipbrdOwner              pmwin  855 2
+WinSetClipbrdViewer             pmwin  856 2
+WinSetCp                        pmwin  857 2
+WinSetDesktopBkgnd              pmwin  935 2
+WinSetDlgItemShort              pmwin  858 4
+WinSetDlgItemText               pmwin  859 3
+WinSetErrorInfo                 pmwin  977 ?
+WinSetFocus                     pmwin  860 2
+WinSetHook                      pmwin  928 5
+WinSetKeyboardStateTable        pmwin  921 3
+WinSetMsgInterest               pmwin  861 3
+WinSetMsgMode                   pmwin  862 3
+WinSetMultWindowPos             pmwin  863 3
+WinSetOwner                     pmwin  864 2
+WinSetParent                    pmwin  865 3
+WinSetPointer                   pmwin  866 2
+WinSetPointerOwner              pmwin  971 3
+WinSetPointerPos                pmwin  867 3
+WinSetPresParam                 pmwin  938 4
+WinSetRect                      pmwin  868 6
+WinSetRectEmpty                 pmwin  869 2
+WinSetSynchroMode               pmwin  870 2
+WinSetSysColors                 pmwin  871 6
+WinSetSysModalWindow            pmwin  872 2
+WinSetSysPointerData            pmwin 1002 3
+WinSetSysValue                  pmwin  873 3
+WinSetVisibleRegionNotify       pmwin 1001 2
+WinSetWindowBits                pmwin  874 4
+WinSetWindowPos                 pmwin  875 7
+WinSetWindowPtr                 pmwin  876 3
+WinSetWindowText                pmwin  877 2
+WinSetWindowThunkProc           pmwin  932 2
+WinSetWindowULong               pmwin  878 3
+WinSetWindowUShort              pmwin  879 3
+WinShowCursor                   pmwin  880 2
+WinShowPointer                  pmwin  881 2
+WinShowTrackRect                pmwin  882 2
+WinShowWindow                   pmwin  883 2
+WinStartTimer                   pmwin  884 4
+WinStopTimer                    pmwin  885 3
+WinStretchPointer               pmwin  968 ?
+WinSubclassWindow               pmwin  929 2
+WinSubstituteStrings            pmwin  886 4
+WinSubtractRect                 pmwin  887 4
+WinTerminate                    pmwin  888 1
+WinThreadAssocQueue             pmwin  304 2
+WinTrackRect                    pmwin  890 3
+WinTranslateAccel               pmwin  904 4
+WinUnionRect                    pmwin  891 4
+WinUpdateWindow                 pmwin  892 1
+WinUpper                        pmwin  893 4
+WinUpperChar                    pmwin  894 4
+WinValidateRect                 pmwin  895 3
+WinValidateRegion               pmwin  896 3
+WinWaitEventSem                 pmwin  978 2
+WinWaitMsg                      pmwin  897 3
+WinWaitMuxWaitSem               pmwin  980 3
+WinWakeThread                   pmwin  992 1
+WinWindowFromDC                 pmwin  898 1
+WinWindowFromID                 pmwin  899 2
+WinWindowFromPoint              pmwin  900 3
Index: trunk/src/emx/src/lib/os2_386/wp.imp
===================================================================
--- trunk/src/emx/src/lib/os2_386/wp.imp	(revision 18)
+++ trunk/src/emx/src/lib/os2_386/wp.imp	(revision 18)
@@ -0,0 +1,209 @@
+;
+; wp.imp
+;
+
+M_WPAbstractCClassData          pmwp     325 ?
+M_WPAbstractClassData           pmwp     326 ?
+M_WPAbstractNewClass            pmwp     327 ?
+M_WPBitmapCClassData            pmwp     367 ?
+M_WPBitmapClassData             pmwp     368 ?
+M_WPBitmapNewClass              pmwp     369 ?
+M_WPCommandFileCClassData       pmwp     385 ?
+M_WPCommandFileClassData        pmwp     386 ?
+M_WPCommandFileNewClass         pmwp     387 ?
+M_WPDataFileCClassData          pmwp     316 ?
+M_WPDataFileClassData           pmwp     317 ?
+M_WPDataFileNewClass            pmwp     318 ?
+M_WPDesktopCClassData           pmwp     355 ?
+M_WPDesktopClassData            pmwp     356 ?
+M_WPDesktopNewClass             pmwp     357 ?
+M_WPDiskCClassData              pmwp     331 ?
+M_WPDiskClassData               pmwp     332 ?
+M_WPDiskNewClass                pmwp     333 ?
+M_WPDrivesCClassData            pmwp     340 ?
+M_WPDrivesClassData             pmwp     341 ?
+M_WPDrivesNewClass              pmwp     342 ?
+M_WPFileSystemCClassData        pmwp     310 ?
+M_WPFileSystemClassData         pmwp     311 ?
+M_WPFileSystemNewClass          pmwp     312 ?
+M_WPFolderCClassData            pmwp     313 ?
+M_WPFolderClassData             pmwp     314 ?
+M_WPFolderNewClass              pmwp     315 ?
+M_WPIconCClassData              pmwp     361 ?
+M_WPIconClassData               pmwp     362 ?
+M_WPIconNewClass                pmwp     363 ?
+M_WPLaunchPadCClassData         pmwp     470 ?
+M_WPLaunchPadClassData          pmwp     471 ?
+M_WPLaunchPadNewClass           pmwp     472 ?
+M_WPMetCClassData               pmwp     406 ?
+M_WPMetClassData                pmwp     407 ?
+M_WPMetNewClass                 pmwp     408 ?
+M_WPMinWinViewerNewClass        pmwp     459 ?
+M_WPNetLinkCClassData           pmwp     400 ?
+M_WPNetLinkClassData            pmwp     401 ?
+M_WPNetLinkNewClass             pmwp     402 ?
+M_WPNetgrpCClassData            pmwp     391 ?
+M_WPNetgrpClassData             pmwp     392 ?
+M_WPNetgrpNewClass              pmwp     393 ?
+M_WPNetworkCClassData           pmwp     388 ?
+M_WPNetworkClassData            pmwp     389 ?
+M_WPNetworkNewClass             pmwp     390 ?
+M_WPObjectCClassData            pmwp     322 ?
+M_WPObjectClassData             pmwp     323 ?
+M_WPObjectNewClass              pmwp     324 ?
+M_WPPifCClassData               pmwp     403 ?
+M_WPPifClassData                pmwp     404 ?
+M_WPPifNewClass                 pmwp     405 ?
+M_WPPointerCClassData           pmwp     364 ?
+M_WPPointerClassData            pmwp     365 ?
+M_WPPointerNewClass             pmwp     366 ?
+M_WPProgramCClassData           pmwp     343 ?
+M_WPProgramClassData            pmwp     344 ?
+M_WPProgramFileCClassData       pmwp     346 ?
+M_WPProgramFileClassData        pmwp     347 ?
+M_WPProgramFileNewClass         pmwp     348 ?
+M_WPProgramNewClass             pmwp     345 ?
+M_WPRootFolderCClassData        pmwp     358 ?
+M_WPRootFolderClassData         pmwp     359 ?
+M_WPRootFolderNewClass          pmwp     360 ?
+M_WPServerCClassData            pmwp     394 ?
+M_WPServerClassData             pmwp     395 ?
+M_WPServerNewClass              pmwp     396 ?
+M_WPShadowCClassData            pmwp     328 ?
+M_WPShadowClassData             pmwp     329 ?
+M_WPShadowNewClass              pmwp     330 ?
+M_WPSharedDirCClassData         pmwp     397 ?
+M_WPSharedDirClassData          pmwp     398 ?
+M_WPSharedDirNewClass           pmwp     399 ?
+M_WPShredderCClassData          pmwp     349 ?
+M_WPShredderClassData           pmwp     350 ?
+M_WPShredderNewClass            pmwp     351 ?
+M_WPStartupCClassData           pmwp     334 ?
+M_WPStartupClassData            pmwp     335 ?
+M_WPStartupNewClass             pmwp     336 ?
+M_WPTemplatesCClassData         pmwp     319 ?
+M_WPTemplatesClassData          pmwp     320 ?
+M_WPTemplatesNewClass           pmwp     321 ?
+M_WPTransientCClassData         pmwp     337 ?
+M_WPTransientClassData          pmwp     338 ?
+M_WPTransientNewClass           pmwp     339 ?
+OldWinCreateObject              pmwp     202 ?
+ShlGetUserWordPtr               pmwp     224 2
+WPAbstractCClassData            pmwp      25 ?
+WPAbstractClassData             pmwp      26 ?
+WPAbstractNewClass              pmwp      27 ?
+WPBitmapCClassData              pmwp      67 ?
+WPBitmapClassData               pmwp      68 ?
+WPBitmapNewClass                pmwp      69 ?
+WPClassManagerCClassData        pmwp      88 ?
+WPClassManagerClassData         pmwp      89 ?
+WPClassManagerNewClass          pmwp      90 ?
+WPCommandFileCClassData         pmwp      85 ?
+WPCommandFileClassData          pmwp      86 ?
+WPCommandFileNewClass           pmwp      87 ?
+WPDataFileCClassData            pmwp      16 ?
+WPDataFileClassData             pmwp      17 ?
+WPDataFileNewClass              pmwp      18 ?
+WPDesktopCClassData             pmwp      55 ?
+WPDesktopClassData              pmwp      56 ?
+WPDesktopNewClass               pmwp      57 ?
+WPDiskCClassData                pmwp      34 ?
+WPDiskClassData                 pmwp      35 ?
+WPDiskNewClass                  pmwp      36 ?
+WPDrivesCClassData              pmwp      43 ?
+WPDrivesClassData               pmwp      44 ?
+WPDrivesNewClass                pmwp      45 ?
+WPFileSystemCClassData          pmwp      10 ?
+WPFileSystemClassData           pmwp      11 ?
+WPFileSystemNewClass            pmwp      12 ?
+WPFolderCClassData              pmwp      13 ?
+WPFolderClassData               pmwp      14 ?
+WPFolderNewClass                pmwp      15 ?
+WPIconCClassData                pmwp      61 ?
+WPIconClassData                 pmwp      62 ?
+WPIconNewClass                  pmwp      63 ?
+WPLaunchPadCClassData           pmwp     467 ?
+WPLaunchPadClassData            pmwp     468 ?
+WPLaunchPadNewClass             pmwp     469 ?
+WPMetCClassData                 pmwp      94 ?
+WPMetClassData                  pmwp      95 ?
+WPMetNewClass                   pmwp      96 ?
+WPMinWinViewerCClassData        pmwp     456 ?
+WPMinWinViewerClassData         pmwp     457 ?
+WPMinWinViewerNewClass          pmwp     458 ?
+WPNetLinkCClassData             pmwp     418 ?
+WPNetLinkClassData              pmwp     419 ?
+WPNetLinkNewClass               pmwp     420 ?
+WPNetgrpCClassData              pmwp     421 ?
+WPNetgrpClassData               pmwp     422 ?
+WPNetgrpNewClass                pmwp     423 ?
+WPNetworkCClassData             pmwp     409 ?
+WPNetworkClassData              pmwp     410 ?
+WPNetworkNewClass               pmwp     411 ?
+WPObjectCClassData              pmwp      22 ?
+WPObjectClassData               pmwp      23 ?
+WPObjectNewClass                pmwp      24 ?
+WPPifCClassData                 pmwp      91 ?
+WPPifClassData                  pmwp      92 ?
+WPPifNewClass                   pmwp      93 ?
+WPPointerCClassData             pmwp      64 ?
+WPPointerClassData              pmwp      65 ?
+WPPointerNewClass               pmwp      66 ?
+WPProgramCClassData             pmwp      46 ?
+WPProgramClassData              pmwp      47 ?
+WPProgramFileCClassData         pmwp      49 ?
+WPProgramFileClassData          pmwp      50 ?
+WPProgramFileNewClass           pmwp      51 ?
+WPProgramNewClass               pmwp      48 ?
+WPRootFolderCClassData          pmwp      58 ?
+WPRootFolderClassData           pmwp      59 ?
+WPRootFolderNewClass            pmwp      60 ?
+WPServerCClassData              pmwp     415 ?
+WPServerClassData               pmwp     416 ?
+WPServerNewClass                pmwp     417 ?
+WPShadowCClassData              pmwp      31 ?
+WPShadowClassData               pmwp      32 ?
+WPShadowNewClass                pmwp      33 ?
+WPSharedDirCClassData           pmwp     412 ?
+WPSharedDirClassData            pmwp     413 ?
+WPSharedDirNewClass             pmwp     414 ?
+WPShredderCClassData            pmwp      52 ?
+WPShredderClassData             pmwp      53 ?
+WPShredderNewClass              pmwp      54 ?
+WPStartupCClassData             pmwp      37 ?
+WPStartupClassData              pmwp      38 ?
+WPStartupNewClass               pmwp      39 ?
+WPTemplatesCClassData           pmwp      28 ?
+WPTemplatesClassData            pmwp      29 ?
+WPTemplatesNewClass             pmwp      30 ?
+WPTransientCClassData           pmwp      40 ?
+WPTransientClassData            pmwp      41 ?
+WPTransientNewClass             pmwp      42 ?
+WinCopyObject                   pmwp     288 3
+WinCreateObject                 pmwp     281 5
+WinCreateShadow                 pmwp     289 3
+WinDeregisterObjectClass        pmwp     201 1
+WinDestroyObject                pmwp     251 1
+WinEnumObjectClasses            pmwp     205 2
+WinFreeFileIcon                 pmwp     216 1
+WinIsSOMDDReady                 pmwp     480 0
+WinIsWPDServerReady             pmwp     465 0
+WinLoadFileIcon                 pmwp     209 2
+WinLockupSystem                 pmwp     283 1
+WinMoveObject                   pmwp     287 3
+WinOpenObject                   pmwp     286 3
+WinQueryActiveDesktopPathname   pmwp     262 2
+WinQueryObject                  pmwp     252 1
+WinQueryObjectPath              pmwp     263 3
+WinRegisterObjectClass          pmwp     200 2
+WinReplaceObjectClass           pmwp     219 3
+WinRestartSOMDD                 pmwp     464 1
+WinRestartWPDServer             pmwp     463 1
+WinRestartWorkplace             pmwp     221 ?
+WinRestoreWindowPos             pmwp     208 3
+WinSaveObject                   pmwp     285 2
+WinSetFileIcon                  pmwp     210 2
+WinSetObjectData                pmwp     250 2
+WinShutdownSystem               pmwp     149 2
+WinStoreWindowPos               pmwp     207 3
+WinUnlockSystem                 pmwp     282 2
Index: trunk/src/emx/src/lib/process/386/_errno.s
===================================================================
--- trunk/src/emx/src/lib/process/386/_errno.s	(revision 18)
+++ trunk/src/emx/src/lib/process/386/_errno.s	(revision 18)
@@ -0,0 +1,43 @@
+/ _errno.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+#if defined (__MT__)
+
+        .globl  __errno
+        .globl  __errno_fun
+
+        .text
+
+        ALIGN
+
+__errno:
+__errno_fun:
+        cmpb    $0, __osmode            /* _osmode == DOS_MODE? */
+        je      1f                      /* Yes -> */
+        fs
+        movl    12, %eax                /* ptib2 */
+        movl    0(%eax), %eax           /* TID */
+        movl    __thread_tab(,%eax,4), %eax
+/       addl    $0, %eax                /* address of errno */
+Lreturn:EPILOGUE(_errno)
+
+        ALIGN
+
+1:      movl    __thread_tab+4, %eax
+/       addl    $0, %eax                /* address of errno */
+        jmp     Lreturn
+
+#else
+
+        .globl  __errno
+
+        .text
+
+        ALIGN
+
+__errno:
+        movl    $_errno, %eax
+        EPILOGUE(_errno)
+
+#endif
Index: trunk/src/emx/src/lib/process/386/gettid.s
===================================================================
--- trunk/src/emx/src/lib/process/386/gettid.s	(revision 18)
+++ trunk/src/emx/src/lib/process/386/gettid.s	(revision 18)
@@ -0,0 +1,21 @@
+/ gettid.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  __gettid
+
+        .text
+
+        ALIGN
+
+__gettid:
+        cmpb    $0, __osmode            /* _osmode == DOS_MODE? */
+        je      1f                      /* Yes -> */
+        fs
+        movl    12, %eax                /* ptib2 */
+        movl    0(%eax), %eax           /* TID */
+Lreturn:EPILOGUE(_gettid)
+
+        ALIGN
+1:      movl    $1, %eax
+        jmp     Lreturn
Index: trunk/src/emx/src/lib/process/386/thread.s
===================================================================
--- trunk/src/emx/src/lib/process/386/thread.s	(revision 18)
+++ trunk/src/emx/src/lib/process/386/thread.s	(revision 18)
@@ -0,0 +1,37 @@
+/ thread.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#if defined (__MT__)
+
+#include <emx/asm386.h>
+
+        .globl  __thread
+
+        .text
+
+        ALIGN
+
+__thread:
+        cmpb    $0, __osmode            /* _osmode == DOS_MODE? */
+        je      1f                      /* Yes -> */
+        fs
+        movl    12, %eax                /* ptib2 */
+        movl    0(%eax), %edx           /* TID */
+        movl    __thread_tab(,%edx,4), %eax
+        testl   %eax, %eax
+        jz      2f
+Lreturn:EPILOGUE(_thread)
+
+        ALIGN
+1:      movl    __thread_tab+4, %eax
+        jmp     Lreturn
+
+        ALIGN
+2:      pushl   %edx
+        call    ___alloc_thread
+        popl    %edx
+        testl   %eax, %eax
+        jz      Lreturn
+        movl    %eax, __thread_tab(,%edx,4)
+        jmp     Lreturn
+
+#endif
Index: trunk/src/emx/src/lib/process/386/threadid.s
===================================================================
--- trunk/src/emx/src/lib/process/386/threadid.s	(revision 18)
+++ trunk/src/emx/src/lib/process/386/threadid.s	(revision 18)
@@ -0,0 +1,14 @@
+/ threadid.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  ___threadid
+
+        .text
+
+        ALIGN
+
+___threadid:
+        fs
+        movl    12, %eax                /* ptib2 */
+        EPILOGUE(__threadid)
Index: trunk/src/emx/src/lib/process/beginthr.c
===================================================================
--- trunk/src/emx/src/lib/process/beginthr.c	(revision 18)
+++ trunk/src/emx/src/lib/process/beginthr.c	(revision 18)
@@ -0,0 +1,134 @@
+/* beginth.c (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes */
+
+#if defined (__MT__)
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <emx/thread.h>
+#include <emx/syscalls.h>
+#define INCL_DOSPROCESS
+#define INCL_DOSERRORS
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+
+#define MAX_THREADS 1024
+
+static struct _thread thread_1 =
+{
+  0,                            /* _th_errno */
+  NULL,                         /* _th_arg */
+  NULL,                         /* _th_start */
+  NULL,                         /* _th_strtok_ptr (must be NULL) */
+  {0},                          /* _th_asctime_buf */
+  {0},                          /* _th_tmpnam_buf */
+  {0},                          /* _th_gmtime_buf */
+  1,                            /* _th_rand */
+  NULL,                         /* _th_store */
+  0,                            /* _th_mblen_shift */
+  0,                            /* _th_mbtowc_shift */
+  0,                            /* _th_wctomb_shift */
+  "",                           /* _th_vollabel */
+  "",                           /* _th_error */
+  NULL,                         /* _th_rheap */
+  NULL,                         /* _th_theap */
+  ""                            /* _th_ttyname */
+};
+
+struct _thread *_thread_tab[MAX_THREADS+1] = {NULL, &thread_1};
+
+
+struct _thread *__alloc_thread (void)
+{
+  struct _thread *tp;
+  ULONG rc;
+
+  rc = DosAllocMem ((PPVOID)&tp, sizeof (struct _thread),
+                    PAG_COMMIT|PAG_READ|PAG_WRITE);
+  if (rc != 0)
+    return NULL;
+  memset (tp, 0, sizeof (struct _thread));
+  tp->_th_rand = 1;             /* Initialize rand() */
+  return tp;
+}
+
+
+static void start_thread (struct _thread *tp)
+{
+  EXCEPTIONREGISTRATIONRECORD reg;
+
+  __initthread (&reg);
+  tp->_th_start (tp->_th_arg);
+  _endthread();
+}
+
+
+int _beginthread (void (*start)(void *arg), void *stack, unsigned stack_size,
+                  void *arg_list)
+{
+  ULONG rc;
+  TID tid;
+  struct _thread *tp;
+
+  tp = __alloc_thread ();
+  if (tp == NULL)
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+  tp->_th_start = start;
+  tp->_th_arg = arg_list;
+  rc = DosCreateThread (&tid, (PFNTHREAD)start_thread, (ULONG)tp,
+                        3, stack_size);
+  if (rc != 0)
+    {
+      if (rc == ERROR_NOT_ENOUGH_MEMORY)
+        errno = ENOMEM;
+      else if (rc == ERROR_MAX_THRDS_REACHED)
+        errno = EAGAIN;
+      else
+        errno = EINVAL;
+      DosFreeMem (tp);
+      return -1;
+    }
+  if (tid > MAX_THREADS)
+    {
+      DosKillThread (tid);
+      errno = EAGAIN;
+      DosFreeMem (tp);
+      return -1;
+    }
+  if (__newthread (tid) != 0)
+    {
+      DosKillThread (tid);
+      DosFreeMem (tp);
+      return -1;
+    }
+  _thread_tab[tid] = tp;
+  rc = DosResumeThread (tid);
+  if (rc != 0)
+    {
+      errno = ESRCH;
+      DosFreeMem (tp);
+      return -1;
+    }
+  return tid;
+}
+
+
+void _endthread (void)
+{
+  struct _thread *tp;
+  int tid;
+
+  tid = _gettid ();
+  tp = _thread ();
+  if (tp != &thread_1)
+    DosFreeMem (tp);
+  _thread_tab[tid] = NULL;
+  __endthread (tid);
+  for (;;)
+    DosExit ((tid == 1 ? EXIT_PROCESS : EXIT_THREAD), 0);
+}
+
+#endif
Index: trunk/src/emx/src/lib/process/execl.c
===================================================================
--- trunk/src/emx/src/lib/process/execl.c	(revision 18)
+++ trunk/src/emx/src/lib/process/execl.c	(revision 18)
@@ -0,0 +1,19 @@
+/* execl.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <process.h>
+
+int _execl (const char *name, const char *arg0, ...)
+{
+  va_list arg_ptr;
+  int result;
+
+  va_start (arg_ptr, name);
+
+  /* Note: Passing `arg_ptr' to spawnv() is not portable. */
+
+  result = _spawnv (P_OVERLAY, name, (char * const *)arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/process/execle.c
===================================================================
--- trunk/src/emx/src/lib/process/execle.c	(revision 18)
+++ trunk/src/emx/src/lib/process/execle.c	(revision 18)
@@ -0,0 +1,25 @@
+/* execle.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <process.h>
+
+int _execle (const char *name, const char *arg0, ...)
+{
+  va_list arg_ptr;
+  char * const *env_ptr;
+  int result;
+
+  va_start (arg_ptr, name);
+  while (va_arg (arg_ptr, char *) != NULL)
+    /* do nothing */;
+  env_ptr = va_arg (arg_ptr, char * const *);
+  va_end (arg_ptr);
+  va_start (arg_ptr, name);
+
+  /* Note: Passing `arg_ptr' to spawnve() is not portable. */
+
+  result = _spawnve (P_OVERLAY, name, (char * const *)arg_ptr, env_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/process/execlp.c
===================================================================
--- trunk/src/emx/src/lib/process/execlp.c	(revision 18)
+++ trunk/src/emx/src/lib/process/execlp.c	(revision 18)
@@ -0,0 +1,19 @@
+/* execlp.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <process.h>
+
+int _execlp (const char *name, const char *arg0, ...)
+{
+  va_list arg_ptr;
+  int result;
+
+  va_start (arg_ptr, name);
+
+  /* Note: Passing `arg_ptr' to spawnvp() is not portable. */
+
+  result = _spawnvp (P_OVERLAY, name, (char * const *)arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/process/execlpe.c
===================================================================
--- trunk/src/emx/src/lib/process/execlpe.c	(revision 18)
+++ trunk/src/emx/src/lib/process/execlpe.c	(revision 18)
@@ -0,0 +1,25 @@
+/* execlpe.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <process.h>
+
+int _execlpe (const char *name, const char *arg0, ...)
+{
+  va_list arg_ptr;
+  char * const *env_ptr;
+  int result;
+
+  va_start (arg_ptr, name);
+  while (va_arg (arg_ptr, char *) != NULL)
+    /* do nothing */;
+  env_ptr = va_arg (arg_ptr, char * const *);
+  va_end (arg_ptr);
+  va_start (arg_ptr, name);
+
+  /* Note: Passing `arg_ptr' to spawnvpe() is not portable. */
+
+  result = _spawnvpe (P_OVERLAY, name, (char * const *)arg_ptr, env_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/process/execv.c
===================================================================
--- trunk/src/emx/src/lib/process/execv.c	(revision 18)
+++ trunk/src/emx/src/lib/process/execv.c	(revision 18)
@@ -0,0 +1,8 @@
+/* execv.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <process.h>
+
+int _execv (const char *name, char * const argv[])
+{
+  return _spawnv (P_OVERLAY, name, argv);
+}
Index: trunk/src/emx/src/lib/process/execve.c
===================================================================
--- trunk/src/emx/src/lib/process/execve.c	(revision 18)
+++ trunk/src/emx/src/lib/process/execve.c	(revision 18)
@@ -0,0 +1,8 @@
+/* execve.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <process.h>
+
+int _execve (const char *name, char * const argv[], char * const envp[])
+{
+  return _spawnve (P_OVERLAY, name, argv, envp);
+}
Index: trunk/src/emx/src/lib/process/execvp.c
===================================================================
--- trunk/src/emx/src/lib/process/execvp.c	(revision 18)
+++ trunk/src/emx/src/lib/process/execvp.c	(revision 18)
@@ -0,0 +1,8 @@
+/* execvp.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <process.h>
+
+int _execvp (const char *name, char * const argv[])
+{
+  return _spawnvp (P_OVERLAY, name, argv);
+}
Index: trunk/src/emx/src/lib/process/execvpe.c
===================================================================
--- trunk/src/emx/src/lib/process/execvpe.c	(revision 18)
+++ trunk/src/emx/src/lib/process/execvpe.c	(revision 18)
@@ -0,0 +1,8 @@
+/* execvpe.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <process.h>
+
+int _execvpe (const char *name, char * const argv[], char * const envp[])
+{
+  return _spawnvpe (P_OVERLAY, name, argv, envp);
+}
Index: trunk/src/emx/src/lib/process/fmutex.c
===================================================================
--- trunk/src/emx/src/lib/process/fmutex.c	(revision 18)
+++ trunk/src/emx/src/lib/process/fmutex.c	(revision 18)
@@ -0,0 +1,137 @@
+/* fmutex.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSPROCESS
+#define INCL_DOSERRORS
+#include <os2.h>
+#include <stdlib.h>
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/smutex.h>
+
+/* These functions are available even in single-thread libraries. */
+
+
+unsigned _fmutex_create (_fmutex *sem, unsigned flags)
+{
+  sem->fs = _FMS_AVAILABLE;
+  if (_osmode == DOS_MODE)
+    return 0;
+  return DosCreateEventSem (NULL, (PHEV)&sem->hev,
+                            (flags & _FMC_SHARED) ? DC_SEM_SHARED : 0,
+                            FALSE);
+}
+
+
+unsigned _fmutex_open (_fmutex *sem)
+{
+  if (_osmode == DOS_MODE)
+    return 0;
+  return DosOpenEventSem (NULL, (PHEV)&sem->hev);
+}
+
+
+unsigned _fmutex_close (_fmutex *sem)
+{
+  if (_osmode == DOS_MODE)
+    return 0;
+  return DosCloseEventSem (sem->hev);
+}
+
+
+unsigned __fmutex_request_internal (_fmutex *sem, unsigned flags,
+                                    signed char fs)
+{
+  ULONG rc, count;
+
+  if (fs == _FMS_UNINIT)
+    return ERROR_INVALID_HANDLE;
+
+  if (flags & _FMR_NOWAIT)
+    {
+      if (fs == _FMS_OWNED_HARD)
+        {
+          if (__cxchg (&sem->fs, _FMS_OWNED_HARD) == _FMS_AVAILABLE)
+            return 0;
+        }
+      return ERROR_MUTEX_OWNED;
+    }
+
+  for (;;)
+    {
+      rc = DosResetEventSem (sem->hev, &count);
+      if (rc != 0 && rc != ERROR_ALREADY_RESET)
+        return rc;
+      if (__cxchg (&sem->fs, _FMS_OWNED_HARD) == _FMS_AVAILABLE)
+        return 0;
+      do
+        {
+          rc = DosWaitEventSem (sem->hev, SEM_INDEFINITE_WAIT);
+        } while (rc == ERROR_INTERRUPT && (flags & _FMR_IGNINT));
+      if (rc != 0)
+        return rc;
+    }
+}
+
+
+unsigned __fmutex_release_internal (_fmutex *sem)
+{
+  ULONG rc;
+
+  rc = DosPostEventSem (sem->hev);
+  if (rc != 0 && rc != ERROR_ALREADY_POSTED)
+    return rc;
+
+  /* Give up our time slice to give other threads a chance.  Without
+     doing so, a thread which continuously requests and releases a
+     _fmutex semaphore may prevent all other threads requesting the
+     _fmutex semaphore from running, forever.
+
+     Why?  Without DosSleep, the thread will keep the CPU for the rest
+     of the time slice.  It may request (and get) the semaphore again
+     in the same time slice, perhaps multiple times.  Assume that the
+     semaphore is still owned at the end of the time slice.  In one of
+     the next time slices, all the other threads blocking on the
+     semaphore will wake up for a short while only to see that the
+     semaphore is owned; they will all go sleeping again.  The thread
+     which owns the semaphore will get the CPU again.  And may happen
+     to own the semaphore again at the end of the time slice.  And so
+     on.  DosSleep reduces that problem a bit.
+
+     Even with DosSleep(0), assignment of time slices to threads
+     requesting a _fmutex semaphore can be quite unbalanced: The more
+     frequently a thread requests a _fmutex semaphore, the more CPU
+     time it will get.  In consequence, a thread which only rarely
+     needs the resource protected by the _fmutex semaphore will get
+     much less CPU time than threads competing heavily for the
+     resource.
+
+     DosSleep(1) would make _fmutex semaphores behave a bit better,
+     but would also give up way too much CPU time (in the average,
+     half a time slice (or one and a half?) per call of this
+     function).
+
+     DosReleaseMutexSem does a better job; it gives the time slice to
+     the thread which has waited longest on the semaphore (if all the
+     threads have the same priority).
+
+     Unfortunately, we cannot use an HMTX instead of an HEV because
+     only the owner (the thread which got assigned ownership by
+     DosRequestMutexSem) can release the HMTX with DosReleaseMutexSem.
+     If we could, that would take advantage of the FIFO of blocked
+     threads maintained by the kernel for each HMTX.
+
+     Using an HMTX would require the first thread requesting an owned
+     _fmutex semaphore to request the HMTX on behalf of the thread
+     owning the _fmutex semaphore. */
+
+  DosSleep (0);
+  return 0;
+}
+
+
+void _fmutex_dummy (_fmutex *sem)
+{
+  sem->fs = _FMS_AVAILABLE;
+  sem->hev = 0;
+}
Index: trunk/src/emx/src/lib/process/fmutex2.c
===================================================================
--- trunk/src/emx/src/lib/process/fmutex2.c	(revision 18)
+++ trunk/src/emx/src/lib/process/fmutex2.c	(revision 18)
@@ -0,0 +1,42 @@
+/* fmutex2.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+
+/* These functions call abort() and therefore must not be linked in
+   when building emx.dll. */
+
+void _fmutex_checked_close (_fmutex *sem)
+{
+  if (_fmutex_close (sem) != 0)
+    abort ();
+}
+
+
+void _fmutex_checked_create (_fmutex *sem, unsigned flags)
+{
+  if (_fmutex_create (sem, flags) != 0)
+    abort ();
+}
+
+
+void _fmutex_checked_open (_fmutex *sem)
+{
+  if (_fmutex_open (sem) != 0)
+    abort ();
+}
+
+
+void _fmutex_checked_release (_fmutex *sem)
+{
+  if (_fmutex_release (sem) != 0)
+    abort ();
+}
+
+
+void _fmutex_checked_request (_fmutex *sem, unsigned flags)
+{
+  if (_fmutex_request (sem, flags) != 0)
+    abort ();
+}
Index: trunk/src/emx/src/lib/process/fork.c
===================================================================
--- trunk/src/emx/src/lib/process/fork.c	(revision 18)
+++ trunk/src/emx/src/lib/process/fork.c	(revision 18)
@@ -0,0 +1,18 @@
+/* fork.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <process.h>
+#include <emx/syscalls.h>
+
+extern void _rmutex_fork (void);
+
+int _fork (void)
+{
+  int pid;
+
+  pid = __fork ();
+#if defined (__MT__)
+  if (pid == 0)
+    _rmutex_fork ();
+#endif
+  return pid;
+}
Index: trunk/src/emx/src/lib/process/getpid.c
===================================================================
--- trunk/src/emx/src/lib/process/getpid.c	(revision 18)
+++ trunk/src/emx/src/lib/process/getpid.c	(revision 18)
@@ -0,0 +1,9 @@
+/* getpid.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <process.h>
+#include <emx/syscalls.h>
+
+int _getpid (void)
+{
+  return __getpid ();
+}
Index: trunk/src/emx/src/lib/process/getppid.c
===================================================================
--- trunk/src/emx/src/lib/process/getppid.c	(revision 18)
+++ trunk/src/emx/src/lib/process/getppid.c	(revision 18)
@@ -0,0 +1,9 @@
+/* getppid.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <process.h>
+#include <emx/syscalls.h>
+
+int _getppid (void)
+{
+  return __getppid ();
+}
Index: trunk/src/emx/src/lib/process/kill.c
===================================================================
--- trunk/src/emx/src/lib/process/kill.c	(revision 18)
+++ trunk/src/emx/src/lib/process/kill.c	(revision 18)
@@ -0,0 +1,9 @@
+/* kill.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <signal.h>
+#include <emx/syscalls.h>
+
+int _kill (int pid, int sig)
+{
+  return __kill (pid, sig);
+}
Index: trunk/src/emx/src/lib/process/makefile
===================================================================
--- trunk/src/emx/src/lib/process/makefile	(revision 18)
+++ trunk/src/emx/src/lib/process/makefile	(revision 18)
@@ -0,0 +1,66 @@
+#
+# /emx/src/lib/process/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+beginthr.o: beginthr.c $(I)stdlib.h $(ERRNO) $(I)os2emx.h $(I)emx/syscalls.h \
+		$(I)emx/thread.h
+execl.o: execl.c $(PROCESS) $(I)stddef.h $(I)stdarg.h
+execle.o: execle.c $(PROCESS) $(I)stddef.h $(I)stdarg.h
+execlp.o: execlp.c $(PROCESS) $(I)stddef.h $(I)stdarg.h
+execlpe.o: execlpe.c $(PROCESS) $(I)stddef.h $(I)stdarg.h
+execv.o: execv.c $(PROCESS)
+execve.o: execve.c $(PROCESS)
+execvp.o: execvp.c $(PROCESS)
+execvpe.o: execvpe.c $(PROCESS)
+fmutex.o: fmutex.c $(I)os2emx.h $(I)stdlib.h $(BUILTIN) $(S)fmutex.h \
+		$(S)smutex.h
+fmutex2.o: fmutex2.c $(I)stdlib.h $(BUILTIN) $(S)fmutex.h
+fork.o: fork.c $(I)emx/syscalls.h $(PROCESS)
+getpid.o: getpid.c $(I)emx/syscalls.h $(PROCESS)
+getppid.o: getppid.c $(I)emx/syscalls.h $(PROCESS)
+gettid.o: gettid.s $(ASM386H)
+kill.o: kill.c $(I)emx/syscalls.h $(SIGNAL)
+pause.o: pause.c $(I)emx/syscalls.h $(SIGNAL) $(ERRNO)
+profil.o: profil.c $(I)emx/syscalls.h $(I)stdlib.h $(I)stddef.h $(ERRNO)
+ptrace.o: ptrace.c $(I)sys/ptrace.h
+raise.o: raise.c $(I)emx/syscalls.h $(SIGNAL)
+rmutex.o: rmutex.c $(I)stdlib.h $(BUILTIN) $(S)fmutex.h $(S)rmutex.h
+sigactio.o: sigactio.c $(I)emx/syscalls.h $(SIGNAL)
+sigaddse.o: sigaddse.c $(SIGNAL) $(ERRNO)
+sigdelse.o: sigdelse.c $(SIGNAL) $(ERRNO)
+sigempty.o: sigempty.c $(SIGNAL)
+sigfills.o: sigfills.c $(SIGNAL)
+sigismem.o: sigismem.c $(SIGNAL) $(ERRNO)
+signal.o: signal.c $(I)emx/syscalls.h $(SIGNAL)
+sigpendi.o: sigpendi.c $(I)emx/syscalls.h $(SIGNAL)
+sigprocm.o: sigprocm.c $(I)emx/syscalls.h $(SIGNAL)
+sigsuspe.o: sigsuspe.c $(I)emx/syscalls.h $(SIGNAL)
+smutex.o: smutex.c $(I)os2emx.h $(BUILTIN) $(S)smutex.h
+spawnl.o: spawnl.c $(PROCESS) $(I)stddef.h $(I)stdarg.h
+spawnle.o: spawnle.c $(PROCESS) $(I)stddef.h $(I)stdarg.h
+spawnlp.o: spawnlp.c $(PROCESS) $(I)stddef.h $(I)stdarg.h
+spawnlpe.o: spawnlpe.c $(PROCESS) $(I)stddef.h $(I)stdarg.h
+spawnv.o: spawnv.c $(PROCESS) $(I)stddef.h
+spawnve.o: spawnve.c $(I)emx/syscalls.h $(I)stdlib.h $(PROCESS) $(I)string.h \
+		$(ERRNO) $(I)emx/startup.h
+spawnvp.o: spawnvp.c $(PROCESS) $(I)stddef.h
+spawnvpe.o: spawnvpe.c $(PROCESS) $(I)stdlib.h
+system.o: system.c $(PROCESS) $(I)stdlib.h $(I)string.h $(ERRNO) $(I)io.h
+thread.o: thread.s $(ASM386H)
+threadid.o: threadid.s $(ASM386H)
+threadst.o: threadst.c $(I)stdlib.h $(I)emx/syscalls.h $(I)emx/thread.h
+wait.o: wait.c $(I)emx/syscalls.h $(I)stdlib.h $(PROCESS) $(ERRNO)
+waitpid.o: waitpid.c $(I)emx/syscalls.h $(I)stdlib.h $(PROCESS) $(ERRNO)
+_errno.o: _errno.s $(ASM386H)
+
+$(DSTLIB): beginthr.o execl.o execle.o execlp.o execlpe.o \
+    execv.o execve.o execvp.o execvpe.o fmutex.o fmutex2.o fork.o getpid.o \
+    getppid.o gettid.o kill.o pause.o profil.o ptrace.o raise.o rmutex.o \
+    sigactio.o sigaddse.o sigdelse.o sigempty.o sigfills.o sigismem.o \
+    signal.o sigpendi.o sigprocm.o sigsuspe.o smutex.o spawnl.o spawnle.o \
+    spawnlp.o spawnlpe.o spawnv.o spawnve.o spawnvp.o spawnvpe.o system.o \
+    thread.o threadid.o threadst.o wait.o waitpid.o _errno.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/process/pause.c
===================================================================
--- trunk/src/emx/src/lib/process/pause.c	(revision 18)
+++ trunk/src/emx/src/lib/process/pause.c	(revision 18)
@@ -0,0 +1,12 @@
+/* pause.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <signal.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+int _pause (void)
+{
+  __pause ();
+  errno = EINTR;
+  return -1;
+}
Index: trunk/src/emx/src/lib/process/profil.c
===================================================================
--- trunk/src/emx/src/lib/process/profil.c	(revision 18)
+++ trunk/src/emx/src/lib/process/profil.c	(revision 18)
@@ -0,0 +1,23 @@
+/* profil.c (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+int _profil (void *buff, unsigned bufsiz, unsigned offset, unsigned scale)
+{
+  struct _profil data;
+
+  if (_osmode == OS2_MODE && *_threadid != 1)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  data.cb = sizeof (data);
+  data.buff = buff;
+  data.bufsiz = bufsiz;
+  data.offset = offset;
+  data.scale = scale;
+  return __profil (&data);
+}
Index: trunk/src/emx/src/lib/process/ptrace.c
===================================================================
--- trunk/src/emx/src/lib/process/ptrace.c	(revision 18)
+++ trunk/src/emx/src/lib/process/ptrace.c	(revision 18)
@@ -0,0 +1,9 @@
+/* ptrace.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <sys/ptrace.h>
+#include <emx/syscalls.h>
+
+int _ptrace (int request, int pid, int addr, int data)
+{
+  return __ptrace (request, pid, addr, data);
+}
Index: trunk/src/emx/src/lib/process/raise.c
===================================================================
--- trunk/src/emx/src/lib/process/raise.c	(revision 18)
+++ trunk/src/emx/src/lib/process/raise.c	(revision 18)
@@ -0,0 +1,9 @@
+/* raise.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <signal.h>
+#include <emx/syscalls.h>
+
+int raise (int sig)
+{
+  return __raise (sig);
+}
Index: trunk/src/emx/src/lib/process/rmutex.c
===================================================================
--- trunk/src/emx/src/lib/process/rmutex.c	(revision 18)
+++ trunk/src/emx/src/lib/process/rmutex.c	(revision 18)
@@ -0,0 +1,171 @@
+/* rmutex.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#define INCL_DOSERRORS
+#include <os2.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/rmutex.h>
+
+/* These functions are available even in single-thread libraries. */
+
+
+static _rmutex *_rmutex_head;   /* Initialized to NULL */
+static _rmutex *_rmutex_tail;   /* Initialized to NULL */
+
+static void _rmutex_add (_rmutex *sem)
+{
+  sem->prev = NULL;
+  if (_rmutex_head == NULL)
+    _rmutex_tail = sem;
+  else
+    _rmutex_head->prev = sem;
+  sem->next = _rmutex_head;
+  _rmutex_head = sem;
+}
+
+
+static void _rmutex_remove (_rmutex *sem)
+{
+  if (sem->prev == NULL)
+    _rmutex_head = sem->next;
+  else
+    sem->prev->next = sem->next;
+  if (sem->next == NULL)
+    _rmutex_tail = sem->prev;
+  else
+    sem->next->prev = sem->prev;
+}
+
+
+unsigned _rmutex_create (_rmutex *sem, unsigned flags)
+{
+  unsigned rc;
+
+  rc = _fmutex_create (&sem->fm, flags);
+  if (rc == 0)
+    {
+#if !defined (NDEBUG)
+      _rmutex *p;
+      for (p = _rmutex_head; p != NULL; p = p->next)
+        if (sem == p)
+          abort ();
+#endif
+      sem->count = 1;
+      sem->flags = (unsigned char)flags;
+      if (flags & _FMC_SHARED)
+        {
+          /* Shared _rmutex semaphores cannot be registered -- that
+             would mess up the doubly-linked list. */
+
+          sem->next = NULL;
+          sem->prev = NULL;
+        }
+      else
+        _rmutex_add (sem);
+    }
+  return rc;
+}
+
+
+unsigned _rmutex_open (_rmutex *sem)
+{
+  unsigned rc;
+
+  rc = _fmutex_open (&sem->fm);
+  if (rc == 0)
+    {
+#if !defined (NDEBUG)
+      _rmutex *p;
+      for (p = _rmutex_head; p != NULL; p = p->next)
+        if (sem == p)
+          break;
+      if (p == NULL)
+        abort ();
+#endif
+      if (sem->count == USHRT_MAX)
+        abort ();
+      sem->count += 1;
+    }
+  return rc;
+}
+
+
+unsigned _rmutex_close (_rmutex *sem)
+{
+  unsigned rc;
+
+  rc = _fmutex_close (&sem->fm);
+
+  /* If it can't be closed, it probably wasn't created or opened.
+     Avoid messing up the doubly-linked list.  Shared semaphores
+     haven't been added to the list. */
+
+  if (rc == 0 && !(sem->flags & _FMC_SHARED))
+    {
+      if (sem->count == 0)
+        abort ();
+      sem->count -= 1;
+      if (sem->count == 0)
+        _rmutex_remove (sem);
+    }
+  return rc;
+}
+
+
+void _rmutex_dummy (_rmutex *sem)
+{
+  sem->prev = NULL;
+  sem->next = NULL;
+  sem->flags = 0;
+  sem->count = 0;
+  _fmutex_dummy (&sem->fm);
+}
+
+
+void _rmutex_checked_close (_rmutex *sem)
+{
+  if (_rmutex_close (sem) != 0)
+    abort ();
+}
+
+
+void _rmutex_checked_create (_rmutex *sem, unsigned flags)
+{
+  if (_rmutex_create (sem, flags) != 0)
+    abort ();
+}
+
+
+void _rmutex_checked_open (_rmutex *sem)
+{
+  if (_rmutex_open (sem) != 0)
+    abort ();
+}
+
+
+void _rmutex_fork (void)
+{
+  _rmutex *p;
+  unsigned i;
+
+  for (p = _rmutex_head; p != NULL; p = p->next)
+    {
+      if (p->flags & _FMC_SHARED)
+        _fmutex_checked_open (&p->fm);
+      else
+        _fmutex_checked_create (&p->fm, p->flags);
+
+      /* This is important for the _rmutex semaphores of heaps! */
+
+      for (i = 1; i < p->count; ++i)
+        _fmutex_checked_open (&p->fm);
+
+      /* Even if the semaphore was owned by the parent process, it's
+         available now in the child process.  This might cause
+         problems due to inconsistent data structures -- resolving
+         this problem (by making sure that all _rmutex semaphores are
+         available when calling fork()) is left to the application. */
+    }
+}
Index: trunk/src/emx/src/lib/process/sigactio.c
===================================================================
--- trunk/src/emx/src/lib/process/sigactio.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigactio.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sigactio.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <signal.h>
+#include <emx/syscalls.h>
+
+int _sigaction (int sig, const struct sigaction *iact, struct sigaction *oact)
+{
+  return __sigaction (sig, iact, oact);
+}
Index: trunk/src/emx/src/lib/process/sigaddse.c
===================================================================
--- trunk/src/emx/src/lib/process/sigaddse.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigaddse.c	(revision 18)
@@ -0,0 +1,14 @@
+/* sigaddse.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <signal.h>
+#include <errno.h>
+
+int _sigaddset (sigset_t *set, int sig)
+{
+  if (sig < 1 || sig >= NSIG)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return __sigaddset (set, sig);
+}
Index: trunk/src/emx/src/lib/process/sigbsd.c
===================================================================
--- trunk/src/emx/src/lib/process/sigbsd.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigbsd.c	(revision 18)
@@ -0,0 +1,10 @@
+/* sigbsd.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <sys/uflags.h>
+
+static void sigbsd (void)
+{
+  _uflags (_UF_SIG_MODEL, _UF_SIG_BSD);
+}
+
+__asm__ ("\t.stabs \"___CTOR_LIST__\", 23, 0, 0, _sigbsd");
Index: trunk/src/emx/src/lib/process/sigdelse.c
===================================================================
--- trunk/src/emx/src/lib/process/sigdelse.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigdelse.c	(revision 18)
@@ -0,0 +1,14 @@
+/* sigdelse.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <signal.h>
+#include <errno.h>
+
+int _sigdelset (sigset_t *set, int sig)
+{
+  if (sig < 1 || sig >= NSIG)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return __sigdelset (set, sig);
+}
Index: trunk/src/emx/src/lib/process/sigempty.c
===================================================================
--- trunk/src/emx/src/lib/process/sigempty.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigempty.c	(revision 18)
@@ -0,0 +1,8 @@
+/* sigempty.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <signal.h>
+
+int _sigemptyset (sigset_t *set)
+{
+  return __sigemptyset (set);
+}
Index: trunk/src/emx/src/lib/process/sigfills.c
===================================================================
--- trunk/src/emx/src/lib/process/sigfills.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigfills.c	(revision 18)
@@ -0,0 +1,8 @@
+/* sigfills.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <signal.h>
+
+int _sigfillset (sigset_t *set)
+{
+  return __sigfillset (set);
+}
Index: trunk/src/emx/src/lib/process/sigismem.c
===================================================================
--- trunk/src/emx/src/lib/process/sigismem.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigismem.c	(revision 18)
@@ -0,0 +1,14 @@
+/* sigismem.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <signal.h>
+#include <errno.h>
+
+int _sigismember (const sigset_t *set, int sig)
+{
+  if (sig < 1 || sig >= NSIG)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return __sigismember (set, sig);
+}
Index: trunk/src/emx/src/lib/process/signal.c
===================================================================
--- trunk/src/emx/src/lib/process/signal.c	(revision 18)
+++ trunk/src/emx/src/lib/process/signal.c	(revision 18)
@@ -0,0 +1,9 @@
+/* signal.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <signal.h>
+#include <emx/syscalls.h>
+
+void (*signal (int sig, void (*handler)()))(int sig)
+{
+  return __signal (sig, handler);
+}
Index: trunk/src/emx/src/lib/process/sigpendi.c
===================================================================
--- trunk/src/emx/src/lib/process/sigpendi.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigpendi.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sigpendi.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <signal.h>
+#include <emx/syscalls.h>
+
+int _sigpending (sigset_t *set)
+{
+  return __sigpending (set);
+}
Index: trunk/src/emx/src/lib/process/sigprocm.c
===================================================================
--- trunk/src/emx/src/lib/process/sigprocm.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigprocm.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sigprocm.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <signal.h>
+#include <emx/syscalls.h>
+
+int _sigprocmask (int how, const sigset_t *iset, sigset_t *oset)
+{
+  return __sigprocmask (how, iset, oset);
+}
Index: trunk/src/emx/src/lib/process/sigsuspe.c
===================================================================
--- trunk/src/emx/src/lib/process/sigsuspe.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigsuspe.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sigsuspe.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <signal.h>
+#include <emx/syscalls.h>
+
+int _sigsuspend (const sigset_t *mask)
+{
+  return __sigsuspend (mask);
+}
Index: trunk/src/emx/src/lib/process/sigsysv.c
===================================================================
--- trunk/src/emx/src/lib/process/sigsysv.c	(revision 18)
+++ trunk/src/emx/src/lib/process/sigsysv.c	(revision 18)
@@ -0,0 +1,10 @@
+/* sigsysv.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <sys/uflags.h>
+
+static void sigsysv (void)
+{
+  _uflags (_UF_SIG_MODEL, _UF_SIG_SYSV);
+}
+
+__asm__ ("\t.stabs \"___CTOR_LIST__\", 23, 0, 0, _sigsysv");
Index: trunk/src/emx/src/lib/process/smutex.c
===================================================================
--- trunk/src/emx/src/lib/process/smutex.c	(revision 18)
+++ trunk/src/emx/src/lib/process/smutex.c	(revision 18)
@@ -0,0 +1,15 @@
+/* smutex.c (emx+gcc) */
+
+#define INCL_DOSPROCESS
+#include <os2.h>
+#include <sys/builtin.h>
+#include <sys/smutex.h>
+
+
+void __smutex_request_internal (volatile _smutex *sem)
+{
+  do
+    {
+      DosSleep (1);
+    } while (__cxchg (sem, 1) != 0);
+}
Index: trunk/src/emx/src/lib/process/spawnl.c
===================================================================
--- trunk/src/emx/src/lib/process/spawnl.c	(revision 18)
+++ trunk/src/emx/src/lib/process/spawnl.c	(revision 18)
@@ -0,0 +1,19 @@
+/* spawnl.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <process.h>
+
+int _spawnl (int mode, const char *name, const char *arg0, ...)
+{
+  va_list arg_ptr;
+  int result;
+
+  va_start (arg_ptr, name);
+
+  /* Note: Passing `arg_ptr' to spawnv() is not portable. */
+
+  result = _spawnv (mode, name, (char * const *)arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/process/spawnle.c
===================================================================
--- trunk/src/emx/src/lib/process/spawnle.c	(revision 18)
+++ trunk/src/emx/src/lib/process/spawnle.c	(revision 18)
@@ -0,0 +1,25 @@
+/* spawnle.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <process.h>
+
+int _spawnle (int mode, const char *name, const char *arg0, ...)
+{
+  va_list arg_ptr;
+  char * const *env_ptr;
+  int result;
+
+  va_start (arg_ptr, name);
+  while (va_arg (arg_ptr, char *) != NULL)
+    /* do nothing */;
+  env_ptr = va_arg (arg_ptr, char * const *);
+  va_end (arg_ptr);
+  va_start (arg_ptr, name);
+
+  /* Note: Passing `arg_ptr' to spawnve() is not portable. */
+
+  result = _spawnve (mode, name, (char * const *)arg_ptr, env_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/process/spawnlp.c
===================================================================
--- trunk/src/emx/src/lib/process/spawnlp.c	(revision 18)
+++ trunk/src/emx/src/lib/process/spawnlp.c	(revision 18)
@@ -0,0 +1,19 @@
+/* spawnlp.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <process.h>
+
+int _spawnlp (int mode, const char *name, const char *arg0, ...)
+{
+  va_list arg_ptr;
+  int result;
+
+  va_start (arg_ptr, name);
+
+  /* Note: Passing `arg_ptr' to spawnvp() is not portable. */
+
+  result = _spawnvp (mode, name, (char * const *)arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/process/spawnlpe.c
===================================================================
--- trunk/src/emx/src/lib/process/spawnlpe.c	(revision 18)
+++ trunk/src/emx/src/lib/process/spawnlpe.c	(revision 18)
@@ -0,0 +1,25 @@
+/* spawnlpe.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <process.h>
+
+int _spawnlpe (int mode, const char *name, const char *arg0, ...)
+{
+  va_list arg_ptr;
+  char * const *env_ptr;
+  int result;
+
+  va_start (arg_ptr, name);
+  while (va_arg (arg_ptr, char *) != NULL)
+    /* do nothing */;
+  env_ptr = va_arg (arg_ptr, char * const *);
+  va_end (arg_ptr);
+  va_start (arg_ptr, name);
+
+  /* Note: Passing `arg_ptr' to spawnvpe() is not portable. */
+
+  result = _spawnvpe (mode, name, (char * const *)arg_ptr, env_ptr);
+  va_end (arg_ptr);
+  return result;
+}
Index: trunk/src/emx/src/lib/process/spawnv.c
===================================================================
--- trunk/src/emx/src/lib/process/spawnv.c	(revision 18)
+++ trunk/src/emx/src/lib/process/spawnv.c	(revision 18)
@@ -0,0 +1,9 @@
+/* spawnv.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <process.h>
+
+int _spawnv (int mode, const char *name, char * const argv[])
+{
+  return _spawnve (mode, name, argv, NULL);
+}
Index: trunk/src/emx/src/lib/process/spawnve.c
===================================================================
--- trunk/src/emx/src/lib/process/spawnve.c	(revision 18)
+++ trunk/src/emx/src/lib/process/spawnve.c	(revision 18)
@@ -0,0 +1,71 @@
+/* spawnve.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <errno.h>
+#include <emx/startup.h>
+#include <emx/syscalls.h>
+
+int _spawnve (int mode, const char *name, char * const argv[],
+              char * const envp[])
+{
+  struct _new_proc np;
+  int i, size, n;
+  const char * const *p;
+  char *d;
+  char exe[512];
+
+  /* Kludge alert: Unfortunately, the `mode' member was made only 16
+     bits wide originally.  Bit 15 is used to indicate that the
+     `mode2' member is used, which holds the upper 16 bits of MODE.
+     This allows using emx 0.8 applications with emx 0.9 as emx
+     doesn't look at `mode2' unless bit 15 of `mode' is set.  Of
+     course, this fails if an (old) application program sets bit 15 of
+     MODE. */
+
+  np.mode = (unsigned short)(mode | 0x8000);
+  np.mode2 = (unsigned short)((unsigned)mode >> 16);
+
+  if (envp == NULL) envp = _environ;
+  if (strlen (name) >= sizeof (exe) - 4)
+    {
+      errno = ENAMETOOLONG;
+      return -1;
+    }
+  strcpy (exe, name);
+  _defext (exe, "exe");
+  np.fname_off = (unsigned long)exe;
+  size = 1; n = 0;
+  for (p = (const char * const *)envp; *p != NULL; ++p)
+    {
+      ++n; size += 1 + strlen (*p);
+    }
+  d = alloca (size);
+  np.env_count = n; np.env_size = size;
+  np.env_off = (unsigned long)d;
+  for (p = (const char * const *)envp; *p != NULL; ++p)
+    {
+      i = strlen (*p);
+      memcpy (d, *p, i+1);
+      d += i+1;
+    }
+  *d = 0;
+  size = 0; n = 0;
+  for (p = (const char * const *)argv; *p != NULL; ++p)
+    {
+      ++n; size += 2 + strlen (*p);
+    }
+  d = alloca (size);
+  np.arg_count = n; np.arg_size = size;
+  np.arg_off = (unsigned long)d;
+  for (p = (const char * const *)argv; *p != NULL; ++p)
+    {
+      i = strlen (*p);
+      *d++ = _ARG_NONZERO;
+      memcpy (d, *p, i+1);
+      d += i+1;
+    }
+  i = __spawnve (&np);
+  return i;
+}
Index: trunk/src/emx/src/lib/process/spawnvp.c
===================================================================
--- trunk/src/emx/src/lib/process/spawnvp.c	(revision 18)
+++ trunk/src/emx/src/lib/process/spawnvp.c	(revision 18)
@@ -0,0 +1,9 @@
+/* spawnvp.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stddef.h>
+#include <process.h>
+
+int _spawnvp (int mode, const char *name, char * const argv[])
+{
+  return _spawnvpe (mode, name, argv, NULL);
+}
Index: trunk/src/emx/src/lib/process/spawnvpe.c
===================================================================
--- trunk/src/emx/src/lib/process/spawnvpe.c	(revision 18)
+++ trunk/src/emx/src/lib/process/spawnvpe.c	(revision 18)
@@ -0,0 +1,23 @@
+/* spawnvpe.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <process.h>
+#include <errno.h>
+
+int _spawnvpe (int mode, const char *name, char * const argv[],
+               char * const envp[])
+{
+  char exe[512];
+  char path[512];
+
+  if (strlen (name) >= sizeof (exe) - 4)
+    {
+      errno = ENAMETOOLONG;
+      return -1;
+    }
+  strcpy (exe, name);
+  _defext (exe, "exe");
+  if (_path (path, exe) != 0)
+    return -1;
+  return _spawnve (mode, path, argv, envp);
+}
Index: trunk/src/emx/src/lib/process/system.c
===================================================================
--- trunk/src/emx/src/lib/process/system.c	(revision 18)
+++ trunk/src/emx/src/lib/process/system.c	(revision 18)
@@ -0,0 +1,38 @@
+/* system.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <io.h>
+#include <errno.h>
+
+int system (const char *name)
+{
+  int rc;
+  const char *sh, *base, *opt;
+
+  sh = getenv ("EMXSHELL");
+  if (sh == NULL)
+    sh = getenv ("COMSPEC");
+  if (sh == NULL)
+    {
+      errno = ENOENT;
+      return -1;
+    }
+  if (name == NULL)   /* Check for command interpreter */
+    return _access (sh, 0) == 0;
+  if (*name == 0)
+    rc = _spawnlp (P_WAIT, sh, sh, (char *)0);
+  else
+    {
+      base = _getname (sh);
+      if (_stricmp (base, "cmd.exe") == 0 || _stricmp (base, "4os2.exe") == 0
+          || _stricmp (base, "command.com") == 0
+          || _stricmp (base, "4dos.com") == 0)
+        opt = "/c";
+      else
+        opt = "-c";
+      rc = _spawnlp (P_WAIT, sh, sh, opt, name, (char *)0);
+    }
+  return rc;
+}
Index: trunk/src/emx/src/lib/process/threadst.c
===================================================================
--- trunk/src/emx/src/lib/process/threadst.c	(revision 18)
+++ trunk/src/emx/src/lib/process/threadst.c	(revision 18)
@@ -0,0 +1,13 @@
+/* threadst.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#if defined (__MT__)
+
+#include <stdlib.h>
+#include <emx/thread.h>
+
+void **_threadstore (void)
+{
+  return &_thread()->_th_store;
+}
+
+#endif
Index: trunk/src/emx/src/lib/process/wait.c
===================================================================
--- trunk/src/emx/src/lib/process/wait.c	(revision 18)
+++ trunk/src/emx/src/lib/process/wait.c	(revision 18)
@@ -0,0 +1,15 @@
+/* wait.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <process.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+int _wait (int *status)
+{
+  int dummy;
+
+  if (status == NULL)
+    status = &dummy;
+  return __wait (status);
+}
Index: trunk/src/emx/src/lib/process/waitpid.c
===================================================================
--- trunk/src/emx/src/lib/process/waitpid.c	(revision 18)
+++ trunk/src/emx/src/lib/process/waitpid.c	(revision 18)
@@ -0,0 +1,15 @@
+/* waitpid.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <process.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+int _waitpid (int pid, int *status, int options)
+{
+  int dummy;
+
+  if (status == NULL)
+    status = &dummy;
+  return __waitpid (pid, status, options);
+}
Index: trunk/src/emx/src/lib/socket/386/swapl.s
===================================================================
--- trunk/src/emx/src/lib/socket/386/swapl.s	(revision 18)
+++ trunk/src/emx/src/lib/socket/386/swapl.s	(revision 18)
@@ -0,0 +1,14 @@
+/ swapl.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+        .globl  __swapl
+
+        .text
+
+        .align  2, 0x90
+
+__swapl:
+        movl    1*4(%esp), %eax         /* x */
+        xchgb   %al, %ah
+        roll    $16, %eax
+        xchgb   %al, %ah
+        ret
Index: trunk/src/emx/src/lib/socket/386/swaps.s
===================================================================
--- trunk/src/emx/src/lib/socket/386/swaps.s	(revision 18)
+++ trunk/src/emx/src/lib/socket/386/swaps.s	(revision 18)
@@ -0,0 +1,12 @@
+/ swaps.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+        .globl  __swaps
+
+        .text
+
+        .align  2, 0x90
+
+__swaps:
+        movl    1*4(%esp), %eax         /* x */
+        xchgb   %al, %ah
+        ret
Index: trunk/src/emx/src/lib/socket/accept.c
===================================================================
--- trunk/src/emx/src/lib/socket/accept.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/accept.c	(revision 18)
@@ -0,0 +1,23 @@
+/* accept.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int accept (int handle, struct sockaddr *addr, int *paddrlen)
+{
+  int s, *pflags;
+
+  s = __accept (handle, addr, paddrlen);
+  if (s < 0)
+    return -1;
+  if ((pflags = _fd_init (s)) == NULL)
+    {
+      __close (s);
+      errno = EMFILE;
+      return -1;
+    }
+  *pflags = O_RDWR | F_SOCKET;
+  return s;
+}
Index: trunk/src/emx/src/lib/socket/bind.c
===================================================================
--- trunk/src/emx/src/lib/socket/bind.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/bind.c	(revision 18)
@@ -0,0 +1,8 @@
+/* bind.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int bind (int handle, struct sockaddr *addr, int addrlen)
+{
+  return __bind (handle, addr, addrlen);
+}
Index: trunk/src/emx/src/lib/socket/connect.c
===================================================================
--- trunk/src/emx/src/lib/socket/connect.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/connect.c	(revision 18)
@@ -0,0 +1,8 @@
+/* connect.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int connect (int handle, struct sockaddr *addr, int addrlen)
+{
+  return __connect (handle, addr, addrlen);
+}
Index: trunk/src/emx/src/lib/socket/gethosti.c
===================================================================
--- trunk/src/emx/src/lib/socket/gethosti.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/gethosti.c	(revision 18)
@@ -0,0 +1,12 @@
+/* gethosti.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int gethostid (void)
+{
+  int result;
+
+  if (__gethostid (&result) != 0)
+    result = -1;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/gethostn.c
===================================================================
--- trunk/src/emx/src/lib/socket/gethostn.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/gethostn.c	(revision 18)
@@ -0,0 +1,8 @@
+/* gethostn.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int gethostname (char *name, int len)
+{
+  return __gethostname (name, len);
+}
Index: trunk/src/emx/src/lib/socket/getpeern.c
===================================================================
--- trunk/src/emx/src/lib/socket/getpeern.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/getpeern.c	(revision 18)
@@ -0,0 +1,8 @@
+/* getpeern.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int getpeername (int handle, struct sockaddr *name, int *pnamelen)
+{
+  return __getpeername (handle, name, pnamelen);
+}
Index: trunk/src/emx/src/lib/socket/getsockh.c
===================================================================
--- trunk/src/emx/src/lib/socket/getsockh.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/getsockh.c	(revision 18)
@@ -0,0 +1,8 @@
+/* getsockh.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int _getsockhandle (int handle)
+{
+  return __getsockhandle (handle);
+}
Index: trunk/src/emx/src/lib/socket/getsockn.c
===================================================================
--- trunk/src/emx/src/lib/socket/getsockn.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/getsockn.c	(revision 18)
@@ -0,0 +1,8 @@
+/* getsockn.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int getsockname (int handle, struct sockaddr *name, int *pnamelen)
+{
+  return __getsockname (handle, name, pnamelen);
+}
Index: trunk/src/emx/src/lib/socket/getsocko.c
===================================================================
--- trunk/src/emx/src/lib/socket/getsocko.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/getsocko.c	(revision 18)
@@ -0,0 +1,8 @@
+/* getsocko.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int getsockopt (int handle, int level, int optname, void *optval, int *poptlen)
+{
+  return __getsockopt (handle, level, optname, optval, poptlen);
+}
Index: trunk/src/emx/src/lib/socket/ghostbya.c
===================================================================
--- trunk/src/emx/src/lib/socket/ghostbya.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/ghostbya.c	(revision 18)
@@ -0,0 +1,27 @@
+/* ghostbya.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+extern int h_errno;
+
+struct hostent *gethostbyaddr (const char *addr, int len, int type)
+{
+  struct hostent *result;
+  int saved_errno;
+
+  saved_errno = errno;
+  if (__gethostbyaddr (addr, len, type, &result) != 0)
+    {
+      if (errno > 4)            /* ENOSYS! */
+        h_errno = NO_RECOVERY;
+      else
+        h_errno = errno;
+      result = NULL;
+    }
+  errno = saved_errno;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/ghostbyn.c
===================================================================
--- trunk/src/emx/src/lib/socket/ghostbyn.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/ghostbyn.c	(revision 18)
@@ -0,0 +1,27 @@
+/* ghostbyn.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+
+extern int h_errno;
+
+struct hostent *gethostbyname (const char *name)
+{
+  struct hostent *result;
+  int saved_errno;
+
+  saved_errno = errno;
+  if (__gethostbyname (name, &result) != 0)
+    {
+      if (errno > 4)            /* ENOSYS! */
+        h_errno = NO_RECOVERY;
+      else
+        h_errno = errno;
+      result = NULL;
+    }
+  errno = saved_errno;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/gnetbyad.c
===================================================================
--- trunk/src/emx/src/lib/socket/gnetbyad.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/gnetbyad.c	(revision 18)
@@ -0,0 +1,13 @@
+/* gnetbyad.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+struct netent *getnetbyaddr (long net)
+{
+  struct netent *result;
+
+  if (__getnetbyaddr (net, &result) != 0)
+    result = NULL;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/gnetbyna.c
===================================================================
--- trunk/src/emx/src/lib/socket/gnetbyna.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/gnetbyna.c	(revision 18)
@@ -0,0 +1,13 @@
+/* gnetbyna.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+struct netent *getnetbyname (const char *name)
+{
+  struct netent *result;
+
+  if (__getnetbyname (name, &result) != 0)
+    result = NULL;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/gprotbna.c
===================================================================
--- trunk/src/emx/src/lib/socket/gprotbna.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/gprotbna.c	(revision 18)
@@ -0,0 +1,13 @@
+/* gprotbna.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+struct protoent *getprotobyname (const char *name)
+{
+  struct protoent *result;
+
+  if (__getprotobyname (name, &result) != 0)
+    result = NULL;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/gprotbnu.c
===================================================================
--- trunk/src/emx/src/lib/socket/gprotbnu.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/gprotbnu.c	(revision 18)
@@ -0,0 +1,13 @@
+/* gprotbnu.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+struct protoent *getprotobynumber (int proto)
+{
+  struct protoent *result;
+
+  if (__getprotobynumber (proto, &result) != 0)
+    result = NULL;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/gservbyn.c
===================================================================
--- trunk/src/emx/src/lib/socket/gservbyn.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/gservbyn.c	(revision 18)
@@ -0,0 +1,13 @@
+/* gservbyn.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+struct servent *getservbyname (const char *name, const char *proto)
+{
+  struct servent *result;
+
+  if (__getservbyname (name, proto, &result) != 0)
+    result = NULL;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/gservbyp.c
===================================================================
--- trunk/src/emx/src/lib/socket/gservbyp.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/gservbyp.c	(revision 18)
@@ -0,0 +1,13 @@
+/* gservbyp.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+struct servent *getservbyport (int port, const char *proto)
+{
+  struct servent *result;
+
+  if (__getservbyport (port, proto, &result) != 0)
+    result = NULL;
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/herrno.c
===================================================================
--- trunk/src/emx/src/lib/socket/herrno.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/herrno.c	(revision 18)
@@ -0,0 +1,6 @@
+/* herrno.c (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes */
+
+/* This variable must be initialized as no extended dictionary entries
+   are built for COMDEF. */
+
+int h_errno = 0;
Index: trunk/src/emx/src/lib/socket/herror.c
===================================================================
--- trunk/src/emx/src/lib/socket/herror.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/herror.c	(revision 18)
@@ -0,0 +1,42 @@
+/* herror.c (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+extern int h_errno;
+
+void herror (const char *string)
+{
+  int e = h_errno;
+  const char *msg;
+
+  if (string != NULL && *string != 0)
+    {
+      fputs (string, stderr);
+      fputs (": ", stderr);
+    }
+  switch (e)
+    {
+    case 0:
+      msg = "Error 0";
+      break;
+    case HOST_NOT_FOUND:
+      msg = "Host not found";
+      break;
+    case TRY_AGAIN:
+      msg = "Host name lookup failure";
+      break;
+    case NO_RECOVERY:
+      msg = "Unknown server error";
+      break;
+    case NO_DATA:
+      msg = "No address associated with name";
+      break;
+    default:
+      fprintf (stderr, "Unknown error %d\n", e);
+      return;
+    }
+  fputs (msg, stderr);
+  fputc ('\n', stderr);
+}
Index: trunk/src/emx/src/lib/socket/impsockh.c
===================================================================
--- trunk/src/emx/src/lib/socket/impsockh.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/impsockh.c	(revision 18)
@@ -0,0 +1,23 @@
+/* impsockh.c (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int _impsockhandle (int handle, int flags)
+{
+  int fd, *pflags;
+
+  fd = __impsockhandle (handle, flags);
+  if (fd == -1)
+    return -1;
+  if ((pflags = _fd_init (fd)) == NULL)
+    {
+      errno = EMFILE;
+      return -1;
+    }
+
+  *pflags = O_RDWR | F_SOCKET;
+  return fd;
+}
Index: trunk/src/emx/src/lib/socket/inetaddr.c
===================================================================
--- trunk/src/emx/src/lib/socket/inetaddr.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/inetaddr.c	(revision 18)
@@ -0,0 +1,52 @@
+/* inetaddr.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+unsigned long inet_addr (const char *s)
+{
+  unsigned long numbers[4];
+  unsigned long r;
+  int i;
+  char *e;
+  long n;
+
+  if (!isdigit ((unsigned char)*s))
+    return INADDR_NONE;
+  for (i = 0; i < 4; ++i)
+    {
+      n = strtol (s, &e, 0);
+      if (e == s)
+        return INADDR_NONE;
+      s = e;
+      numbers[i] = n;
+      if (*s != '.')
+        break;
+      ++s;
+      if (!isdigit ((unsigned char)*s))
+        return INADDR_NONE;
+    }
+  if (*s != 0 && !isspace ((unsigned char)*s))
+    return INADDR_NONE;
+
+  switch (i)
+    {
+    case 0:
+      r = numbers[0];
+      break;
+    case 1:
+      r = (numbers[0] << 24) | (numbers[1] & 0xffffff);
+      break;
+    case 2:
+      r = ((numbers[0] << 24) | ((numbers[1] & 0xff) << 16)
+           | (numbers[2] & 0xffff));
+      break;
+    default:
+      r = ((numbers[0] << 24) | ((numbers[1] & 0xff) << 16)
+           | ((numbers[2] & 0xff) << 8) | (numbers[3] & 0xff));
+      break;
+    }
+  return htonl (r);
+}
Index: trunk/src/emx/src/lib/socket/inetlnao.c
===================================================================
--- trunk/src/emx/src/lib/socket/inetlnao.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/inetlnao.c	(revision 18)
@@ -0,0 +1,17 @@
+/* inetlnao.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+unsigned long inet_lnaof (struct in_addr in)
+{
+  unsigned long temp;
+
+  temp = ntohl (in.s_addr);
+  if (IN_CLASSA (temp))
+    return temp & IN_CLASSA_HOST;
+  else if (IN_CLASSB (temp))
+    return temp & IN_CLASSB_HOST;
+  else
+    return temp & IN_CLASSC_HOST;
+}
Index: trunk/src/emx/src/lib/socket/inetmkad.c
===================================================================
--- trunk/src/emx/src/lib/socket/inetmkad.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/inetmkad.c	(revision 18)
@@ -0,0 +1,20 @@
+/* inetmkad.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+struct in_addr inet_makeaddr (u_long net, u_long host)
+{
+  unsigned long unet;
+  struct in_addr in;
+
+  unet = net;
+  if (unet < 0xc0)
+    in.s_addr = (unet << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
+  else if (unet < 0x10000)
+    in.s_addr = (unet << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
+  else
+    in.s_addr = (unet << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
+  in.s_addr = htonl (in.s_addr);
+  return in;
+}
Index: trunk/src/emx/src/lib/socket/inetneto.c
===================================================================
--- trunk/src/emx/src/lib/socket/inetneto.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/inetneto.c	(revision 18)
@@ -0,0 +1,17 @@
+/* inetneto.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+unsigned long inet_netof (struct in_addr in)
+{
+  unsigned long temp;
+
+  temp = ntohl (in.s_addr);
+  if (IN_CLASSA (temp))
+    return (temp & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
+  else if (IN_CLASSB (temp))
+    return (temp & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
+  else
+    return (temp & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
+}
Index: trunk/src/emx/src/lib/socket/inetnetw.c
===================================================================
--- trunk/src/emx/src/lib/socket/inetnetw.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/inetnetw.c	(revision 18)
@@ -0,0 +1,52 @@
+/* inetnetw.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+unsigned long inet_network (const char *s)
+{
+  unsigned long numbers[4];
+  unsigned long r;
+  int i;
+  char *e;
+  long n;
+
+  if (!isdigit ((unsigned char)*s))
+    return INADDR_NONE;
+  for (i = 0; i < 4; ++i)
+    {
+      n = strtol (s, &e, 0);
+      if (e == s)
+        return INADDR_NONE;
+      s = e;
+      numbers[i] = n;
+      if (*s != '.')
+        break;
+      ++s;
+      if (!isdigit ((unsigned char)*s))
+        return INADDR_NONE;
+    }
+  if (*s != 0 && !isspace ((unsigned char)*s))
+    return INADDR_NONE;
+
+  switch (i)
+    {
+    case 0:
+      r = numbers[0] & 0xff;
+      break;
+    case 1:
+      r = ((numbers[0] & 0xff) << 8) | (numbers[1] & 0xff);
+      break;
+    case 2:
+      r = (((numbers[0] & 0xff) << 16) | ((numbers[1] & 0xff) << 8)
+           | (numbers[2] & 0xff));
+      break;
+    default:
+      r = (((numbers[0] & 0xff) << 24) | ((numbers[1] & 0xff) << 16)
+           | ((numbers[2] & 0xff) << 8) | (numbers[3] & 0xff));
+      break;
+    }
+  return r;
+}
Index: trunk/src/emx/src/lib/socket/inetntoa.c
===================================================================
--- trunk/src/emx/src/lib/socket/inetntoa.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/inetntoa.c	(revision 18)
@@ -0,0 +1,22 @@
+/* inetntoa.c (emx+gcc) -- Copyright (c) 1994-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <emx/thread.h>
+
+char *inet_ntoa (struct in_addr in)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#define result (tp->_th_inetntoa)
+#else
+  static char result[16];
+#endif
+  unsigned char *t;
+
+  t = (unsigned char *)&in;
+  sprintf (result, "%d.%d.%d.%d",
+           t[0] & 0xff, t[1] & 0xff, t[2] & 0xff, t[3] & 0xff);
+  return result;
+}
Index: trunk/src/emx/src/lib/socket/listen.c
===================================================================
--- trunk/src/emx/src/lib/socket/listen.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/listen.c	(revision 18)
@@ -0,0 +1,8 @@
+/* listen.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int listen (int handle, int backlog)
+{
+  return __listen (handle, backlog);
+}
Index: trunk/src/emx/src/lib/socket/makefile
===================================================================
--- trunk/src/emx/src/lib/socket/makefile	(revision 18)
+++ trunk/src/emx/src/lib/socket/makefile	(revision 18)
@@ -0,0 +1,73 @@
+#
+# /emx/src/lib/socket/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+.SOURCE.s: ..
+
+.PHONY: clean default dstlib socket
+
+LIBSOCKET=$(L)socket.a
+
+LIBC_CCFLAGS = -D__ST_MT_ERRNO__
+
+default:    socket
+
+socket .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(LIBSOCKET)
+
+clean:
+	-del $(CPU)\*.o $(DELOPT)
+
+accept.o: accept.c $(I)emx/syscalls.h $(ERRNO) $(FCNTL) $(I)emx/io.h
+bind.o: bind.c $(I)emx/syscalls.h
+connect.o: connect.c $(I)emx/syscalls.h
+gethosti.o: gethosti.c $(I)emx/syscalls.h
+gethostn.o: gethostn.c $(I)emx/syscalls.h
+getpeern.o: getpeern.c $(I)emx/syscalls.h
+gnetbyad.o: gnetbyad.c $(I)stdlib.h $(I)emx/syscalls.h
+gnetbyna.o: gnetbyna.c $(I)stdlib.h $(I)emx/syscalls.h
+gprotbna.o: gprotbna.c $(I)stdlib.h $(I)emx/syscalls.h
+gprotbnu.o: gprotbnu.c $(I)stdlib.h $(I)emx/syscalls.h
+getsockh.o: getsockh.c $(I)emx/syscalls.h
+getsockn.o: getsockn.c $(I)emx/syscalls.h
+getsocko.o: getsocko.c $(I)emx/syscalls.h
+ghostbya.o: ghostbya.c $(I)stdlib.h $(I)emx/syscalls.h $(ERRNO) \
+		$(S)types.h $(I)netdb.h
+ghostbyn.o: ghostbyn.c $(I)stdlib.h $(I)emx/syscalls.h $(ERRNO) \
+		$(S)types.h $(I)netdb.h
+gservbyn.o: gservbyn.c $(I)stdlib.h $(I)emx/syscalls.h
+gservbyp.o: gservbyp.c $(I)stdlib.h $(I)emx/syscalls.h
+herror.o: herror.c $(I)stdio.h $(S)types.h $(I)netdb.h
+herrno.o: herrno.c
+impsockh.o: impsockh.c $(I)emx/syscalls.h $(FCNTL) $(I)emx/io.h
+inetaddr.o: inetaddr.c $(I)stdlib.h $(I)ctype.h $(S)types.h $(I)netinet/in.h
+inetlnao.o: inetlnao.c $(S)types.h $(I)netinet/in.h
+inetmkad.o: inetmkad.c $(S)types.h $(I)netinet/in.h
+inetneto.o: inetneto.c $(S)types.h $(I)netinet/in.h
+inetnetw.o: inetnetw.c $(I)stdlib.h $(I)ctype.h $(S)types.h $(I)netinet/in.h
+inetntoa.o: inetntoa.c $(I)stdio.h $(S)types.h $(I)netinet/in.h \
+		$(I)emx/thread.h
+listen.o: listen.c $(I)emx/syscalls.h
+recv.o: recv.c $(I)emx/syscalls.h
+recvfrom.o: recvfrom.c $(I)emx/syscalls.h
+send.o: send.c $(I)emx/syscalls.h
+sendto.o: sendto.c $(I)emx/syscalls.h
+setsocko.o: setsocko.c $(I)emx/syscalls.h
+shutdown.o: shutdown.c $(I)emx/syscalls.h
+socket.o: socket.c $(I)emx/syscalls.h $(ERRNO) $(FCNTL) $(I)emx/io.h
+swapl.o: swapl.s
+swaps.o: swaps.s
+
+$(LIBSOCKET): accept.o bind.o connect.o gethosti.o gethostn.o getpeern.o \
+    getsockh.o getsockn.o getsocko.o ghostbya.o ghostbyn.o gnetbyad.o \
+    gnetbyna.o gprotbna.o gprotbnu.o gservbyn.o gservbyp.o herror.o herrno.o \
+    impsockh.o inetaddr.o inetlnao.o inetmkad.o inetneto.o inetnetw.o \
+    inetntoa.o listen.o recv.o recvfrom.o send.o sendto.o setsocko.o \
+    shutdown.o socket.o swapl.o swaps.o ../tcp32dll.imp
+	emximp -o $(LIBSOCKET) ../tcp32dll.imp
+	$(AR) r $(LIBSOCKET) *.o
Index: trunk/src/emx/src/lib/socket/recv.c
===================================================================
--- trunk/src/emx/src/lib/socket/recv.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/recv.c	(revision 18)
@@ -0,0 +1,8 @@
+/* recv.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int recv (int handle, void *buf, int len, unsigned flags)
+{
+  return __recv (handle, buf, len, flags);
+}
Index: trunk/src/emx/src/lib/socket/recvfrom.c
===================================================================
--- trunk/src/emx/src/lib/socket/recvfrom.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/recvfrom.c	(revision 18)
@@ -0,0 +1,17 @@
+/* recvfrom.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int recvfrom (int handle, void *buf, int len, unsigned flags,
+              struct sockaddr *from, int *pfromlen)
+{
+  struct _recvfrom args;
+
+  args.handle   = handle;
+  args.buf      = buf;
+  args.len      = len;
+  args.flags    = flags;
+  args.from     = from;
+  args.pfromlen = pfromlen;
+  return __recvfrom (&args);
+}
Index: trunk/src/emx/src/lib/socket/send.c
===================================================================
--- trunk/src/emx/src/lib/socket/send.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/send.c	(revision 18)
@@ -0,0 +1,8 @@
+/* send.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int send (int handle, const void *buf, int len, unsigned flags)
+{
+  return __send (handle, buf, len, flags);
+}
Index: trunk/src/emx/src/lib/socket/sendto.c
===================================================================
--- trunk/src/emx/src/lib/socket/sendto.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/sendto.c	(revision 18)
@@ -0,0 +1,17 @@
+/* sendto.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int sendto (int handle, const void *buf, int len, unsigned flags,
+            const struct sockaddr *to, int tolen)
+{
+  struct _sendto args;
+
+  args.handle = handle;
+  args.buf    = buf;
+  args.len    = len;
+  args.flags  = flags;
+  args.to     = to;
+  args.tolen  = tolen;
+  return __sendto (&args);
+}
Index: trunk/src/emx/src/lib/socket/setsocko.c
===================================================================
--- trunk/src/emx/src/lib/socket/setsocko.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/setsocko.c	(revision 18)
@@ -0,0 +1,9 @@
+/* setsocko.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int setsockopt (int handle, int level, int optname, const void *optval,
+                int optlen)
+{
+  return __setsockopt (handle, level, optname, optval, optlen);
+}
Index: trunk/src/emx/src/lib/socket/shutdown.c
===================================================================
--- trunk/src/emx/src/lib/socket/shutdown.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/shutdown.c	(revision 18)
@@ -0,0 +1,8 @@
+/* shutdown.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int shutdown (int handle, int how)
+{
+  return __shutdown (handle, how);
+}
Index: trunk/src/emx/src/lib/socket/socket.c
===================================================================
--- trunk/src/emx/src/lib/socket/socket.c	(revision 18)
+++ trunk/src/emx/src/lib/socket/socket.c	(revision 18)
@@ -0,0 +1,23 @@
+/* socket.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int socket (int domain, int type, int protocol)
+{
+  int s, *pflags;
+
+  s = __socket (domain, type, protocol);
+  if (s < 0)
+    return -1;
+  if ((pflags = _fd_init (s)) == NULL)
+    {
+      __close (s);
+      errno = EMFILE;
+      return -1;
+    }
+  *pflags = O_RDWR | F_SOCKET;
+  return s;
+}
Index: trunk/src/emx/src/lib/socket/tcp32dll.imp
===================================================================
--- trunk/src/emx/src/lib/socket/tcp32dll.imp	(revision 18)
+++ trunk/src/emx/src/lib/socket/tcp32dll.imp	(revision 18)
@@ -0,0 +1,23 @@
+;
+; tcp32dll.imp
+;
+dn_comp                 tcp32dll  32 5
+dn_expand               tcp32dll  31 5
+dn_skipname             tcp32dll  33 2
+endhostent              tcp32dll  29 0
+endnetent               tcp32dll  16 0
+endprotoent             tcp32dll  19 0
+endservent              tcp32dll  26 0
+gethostent              tcp32dll  30 0
+getnetent               tcp32dll  17 0
+getprotoent             tcp32dll  20 0
+getservent              tcp32dll  27 0
+putlong                 tcp32dll  38 2
+putshort                tcp32dll  37 2
+res_init                tcp32dll  39 0
+res_mkquery             tcp32dll  40 9
+res_send                tcp32dll  41 4
+sethostent              tcp32dll  28 1
+setnetent               tcp32dll  15 1
+setprotoent             tcp32dll  18 1
+setservent              tcp32dll  25 1
Index: trunk/src/emx/src/lib/startup/386/crt0.s
===================================================================
--- trunk/src/emx/src/lib/startup/386/crt0.s	(revision 18)
+++ trunk/src/emx/src/lib/startup/386/crt0.s	(revision 18)
@@ -0,0 +1,105 @@
+/ crt0.s (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes
+
+        .globl  __text
+        .globl  ___syscall
+        .globl  __data
+        .globl  __heap_base
+        .globl  __heap_brk
+        .globl  __heap_end
+        .globl  __init
+
+        .text
+
+__text:
+        push    $__data
+#if defined (OMF)
+        call    __emx_init
+#else
+        call    __dos_init
+#endif
+        jmp     __init
+
+___syscall:
+#if defined (OMF)
+        call    __emx_syscall
+#else
+        call    __dos_syscall
+#endif
+        ret
+
+        .space  6, 0x90                 /* Patch area for rsx */
+
+__init: cld
+        call    __entry1
+        call    __entry2
+#if defined (MCRT0)
+        pushl   $__mcleanup
+        call    _atexit
+        addl    $4, %esp
+        pushl   $__etext
+        pushl   $__text
+        call    _monstartup
+        addl    $2*4, %esp
+#endif
+        call    __startup
+        call    _main
+        addl    $3*4, %esp
+        pushl   %eax
+        call    _exit
+2:      jmp     2b
+
+        .data
+
+/ The data segment starts with a table containing the start and end
+/ addresses of the text, data and bss segments
+
+__data:
+#if defined (OMF)
+        .long   0
+        .long   0
+        .long   0
+        .long   0
+        .long   0
+        .long   0
+#else
+        .long   __text
+        .long   __etext
+        .long   __data
+        .long   __edata
+        .long   __edata
+        .long   __end
+#endif
+__heap_base:
+        .long   0                       /* heap base address */
+__heap_end:
+        .long   0                       /* heap end address */
+__heap_brk:
+        .long   0                       /* heap brk address */
+        .long   0                       /* heap offset */
+        .long   __os2dll                /* list of OS/2 DLL references */
+        .long   0                       /* stack base address */
+        .long   0                       /* stack end address */
+#if defined (OMF)
+        .long   0x02000002              /* flags: application, OMF */
+#else
+        .long   0x02000000              /* flags: application */
+#endif
+        .long   0                       /* reserved */
+        .long   0                       /* reserved */
+        .byte   0                       /* options */
+        .space  63, 0
+
+/ first element of vector (N_SETA|N_EXT == 21)
+
+#if defined (OMF)
+__os2dll:
+        .long   0, 0
+#else
+        .stabs  "__os2dll", 21, 0, 0, 0xffffffff
+#endif
+
+        .stabs  "___CTOR_LIST__", 21, 0, 0, 0xffffffff
+        .stabs  "___DTOR_LIST__", 21, 0, 0, 0xffffffff
+        .stabs  "___crtinit1__", 21, 0, 0, 0xffffffff
+        .stabs  "___crtexit1__", 21, 0, 0, 0xffffffff
+        .stabs  "___eh_frame__", 21, 0, 0, 0xffffffff
Index: trunk/src/emx/src/lib/startup/386/crt1.s
===================================================================
--- trunk/src/emx/src/lib/startup/386/crt1.s	(revision 18)
+++ trunk/src/emx/src/lib/startup/386/crt1.s	(revision 18)
@@ -0,0 +1,54 @@
+/ crt1.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+/ This module is used by the following types of executables:
+/
+/ - Statically linked application programs
+/ - Custom C runtime DLLs
+/ - Stand-alone DLLs
+
+
+        .globl  __entry2
+#if !defined (__MT__)
+        .globl  _errno
+#endif
+        .globl  __osmode
+        .globl  __emx_env
+        .globl  __emx_vcmp
+        .globl  __emx_vprt
+        .globl  __emx_rev
+        .globl  __osmajor
+        .globl  __osminor
+
+        .text
+
+__entry2:
+        call    ___os_version
+        movb    %al, __osmajor
+        movb    %ah, __osminor
+        call    ___emx_version
+        movl    %eax, __emx_vcmp
+        movl    %ecx, __emx_rev
+        movl    %edx, __emx_env
+        xchgb   %al, %ah
+        rorl    $16, %eax
+        xchgb   %al, %ah
+        movl    %eax, __emx_vprt
+        movb    $0, __emx_vprt+4
+        testl   $0x200, %edx
+        setne   __osmode
+        EPILOGUE(_entry2)
+
+        .data
+
+#if !defined (__MT__)
+_errno: .long   0
+#endif
+__osmode:       .byte 1                         /* OS2_MODE = 1 */
+        .comm   __emx_rev, 4
+        .comm   __emx_env, 4
+        .comm   __emx_vcmp, 4
+        .comm   __emx_vprt, 5
+        .comm   __osmajor, 1
+        .comm   __osminor, 1
Index: trunk/src/emx/src/lib/startup/386/dll0.s
===================================================================
--- trunk/src/emx/src/lib/startup/386/dll0.s	(revision 18)
+++ trunk/src/emx/src/lib/startup/386/dll0.s	(revision 18)
@@ -0,0 +1,86 @@
+/ dll0.s (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes
+
+        .globl  __text
+        .globl  ___syscall
+        .globl  __data
+        .globl  __heap_base
+        .globl  __heap_brk
+        .globl  __heap_end
+        .globl  __init
+
+        .text
+
+__text:
+        push    $__data
+#if defined (OMF)
+        call    __emx_init
+#else
+        call    __dos_init
+#endif
+        jmp     __init
+
+
+___syscall:
+#if defined (OMF)
+        call    __emx_syscall
+#else
+        call    __dos_syscall
+#endif
+        ret
+
+__init: cld
+        pushl   %ebp
+        movl    %esp, %ebp
+        pushl   12(%ebp)
+        pushl   8(%ebp)
+        call    __DLL_InitTerm
+        addl    $8, %esp
+        popl    %ebp
+        ret
+
+        .data
+
+/ The data segment starts with a table containing the start and end
+/ addresses of the text, data and bss segments
+
+__data:
+        .long   __text
+        .long   __etext
+        .long   __data
+        .long   __edata
+        .long   __edata
+        .long   __end
+__heap_base:
+        .long   0                       /* heap base address */
+__heap_end:
+        .long   0                       /* heap end address */
+__heap_brk:
+        .long   0                       /* heap brk address */
+        .long   0                       /* heap offset */
+        .long   __os2dll                /* list of OS/2 DLL references */
+        .long   0                       /* stack base address */
+        .long   0                       /* stack end address */
+#if defined (OMF)
+        .long   0x02000003              /* flags: DLL, OMF */
+#else
+        .long   0x02000001              /* flags: DLL */
+#endif
+        .long   0                       /* reserved */
+        .long   0                       /* reserved */
+        .byte   0                       /* options */
+        .space  63, 0
+
+/ first element of vector (N_SETA|N_EXT == 21)
+
+#if defined (OMF)
+__os2dll:
+        .long   0, 0
+#else
+        .stabs  "__os2dll", 21, 0, 0, 0xffffffff
+#endif
+
+        .stabs  "___CTOR_LIST__", 21, 0, 0, 0xffffffff
+        .stabs  "___DTOR_LIST__", 21, 0, 0, 0xffffffff
+        .stabs  "___crtinit1__", 21, 0, 0, 0xffffffff
+        .stabs  "___crtexit1__", 21, 0, 0, 0xffffffff
+        .stabs  "___eh_frame__", 21, 0, 0, 0xffffffff
Index: trunk/src/emx/src/lib/startup/386/res0.s
===================================================================
--- trunk/src/emx/src/lib/startup/386/res0.s	(revision 18)
+++ trunk/src/emx/src/lib/startup/386/res0.s	(revision 18)
@@ -0,0 +1,9 @@
+/ res0.s (emx+gcc) -- Copyright (c) 1993-1994 by Eberhard Mattes
+
+        .globl  __text
+
+        .text
+
+__text:
+        movl    $1, %eax
+        ret
Index: trunk/src/emx/src/lib/startup/_exit.c
===================================================================
--- trunk/src/emx/src/lib/startup/_exit.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/_exit.c	(revision 18)
@@ -0,0 +1,12 @@
+/* _exit.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/syscalls.h>
+
+void _exit (int ret)
+{
+  if (ret < 0 || ret > 255)
+    ret = 255;
+  for (;;)
+    __exit (ret);
+}
Index: trunk/src/emx/src/lib/startup/cleanup.c
===================================================================
--- trunk/src/emx/src/lib/startup/cleanup.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/cleanup.c	(revision 18)
@@ -0,0 +1,11 @@
+/* cleanup.c (emx+gcc) */
+
+#include <stdio.h>
+
+extern int __crtexit1__;
+extern void __ctordtorTerm1 (int *ptr);
+
+void _cleanup (void)
+{
+  __ctordtorTerm1 (&__crtexit1__);
+}
Index: trunk/src/emx/src/lib/startup/crtinit.c
===================================================================
--- trunk/src/emx/src/lib/startup/crtinit.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/crtinit.c	(revision 18)
@@ -0,0 +1,19 @@
+/* crtinit.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+extern void _entry2 (void);
+extern void _startup (void);
+extern void __main (void);
+
+
+int _CRT_init (void)
+{
+  static int done;
+
+  if (!done)
+    {
+      done = 1;
+      _entry2 ();
+      _startup ();
+    }
+  return 0;                     /* Success */
+}
Index: trunk/src/emx/src/lib/startup/crtterm.c
===================================================================
--- trunk/src/emx/src/lib/startup/crtterm.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/crtterm.c	(revision 18)
@@ -0,0 +1,15 @@
+/* crtterm.c (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes */
+
+extern void _cleanup (void);
+
+
+void _CRT_term (void)
+{
+  static int done;
+
+  if (!done)
+    {
+      done = 1;
+      _cleanup ();
+    }
+}
Index: trunk/src/emx/src/lib/startup/ctor.c
===================================================================
--- trunk/src/emx/src/lib/startup/ctor.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/ctor.c	(revision 18)
@@ -0,0 +1,30 @@
+/* ctor.c (emx+gcc) -- Copyright (c) 1993-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+struct object
+{
+  void *pc_begin;
+  void *pc_end;
+  void *fde_begin;
+  void *fde_array;
+  size_t count;
+  struct object *next;
+};
+
+extern int __CTOR_LIST__, __eh_frame__;
+extern void __ctordtorInit1 (int *ptr);
+extern void __eh_frame_init (int *ptr, struct object *ob);
+
+void __ctordtorInit (void)
+{
+  static int done;
+  static struct object ob;
+
+  if (!done)
+    {
+      done = 1;
+      __eh_frame_init (&__eh_frame__, &ob);
+      __ctordtorInit1 (&__CTOR_LIST__);
+    }
+}
Index: trunk/src/emx/src/lib/startup/ctor1.c
===================================================================
--- trunk/src/emx/src/lib/startup/ctor1.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/ctor1.c	(revision 18)
@@ -0,0 +1,21 @@
+/* ctor1.c (emx+gcc) -- Copyright (c) 1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+void __ctordtorInit1 (int *ptr)
+{
+  int n;
+  void (**ppf)();
+
+  if (*ptr == -2)                 /* emxomf */
+    for (ppf = (void (**)()) (ptr + 1); *ppf != NULL; ++ppf)
+      (**ppf)();
+  else
+    {
+      if (*ptr == -1) --ptr;      /* Fix GNU ld bug */
+      n = *ptr++;                 /* Get size of vector */
+      if (*ptr == -1)             /* First element must be -1, see crt0.s */
+        for (ppf = (void (**)()) (ptr + 1); n > 1; ++ppf, --n)
+          (**ppf)();
+    }
+}
Index: trunk/src/emx/src/lib/startup/dtor.c
===================================================================
--- trunk/src/emx/src/lib/startup/dtor.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/dtor.c	(revision 18)
@@ -0,0 +1,21 @@
+/* dtor.c (emx+gcc) -- Copyright (c) 1993-1998 by Eberhard Mattes */
+
+extern int __DTOR_LIST__, __eh_frame__;
+extern void __ctordtorTerm1 (int *ptr);
+extern void __eh_frame_term (int *ptr);
+
+void __ctordtorTerm (void)
+{
+  static int done;
+
+  if (!done)
+    {
+      done = 1;
+      __ctordtorTerm1 (&__DTOR_LIST__);
+#if 0
+      /* OS/2 doesn't guarantee correct unloading sequence of DLLs,
+         therefore we cannot do this. */
+      __eh_frame_term (&__eh_frame__);
+#endif
+    }
+}
Index: trunk/src/emx/src/lib/startup/dtor1.c
===================================================================
--- trunk/src/emx/src/lib/startup/dtor1.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/dtor1.c	(revision 18)
@@ -0,0 +1,25 @@
+/* dtor1.c (emx+gcc) -- Copyright (c) 1993 by Eberhard Mattes */
+
+#include <stdlib.h>
+
+void __ctordtorTerm1 (int *ptr)
+{
+  int n;
+  void (**ppf)();
+
+  if (*ptr == -2)                 /* emxomf */
+    {
+      for (ppf = (void (**)()) (ptr + 1); *ppf != NULL; ++ppf)
+        ;
+      for (--ppf; ppf > (void (**)()) ptr; --ppf)
+        (**ppf)();
+    }
+  else
+    {
+      if (*ptr == -1) --ptr;      /* Fix GNU ld bug */
+      n = *ptr++ - 1;             /* Get size of vector */
+      if (*ptr == -1)             /* First element must be -1, see crt0.s */
+        for (ppf = (void (**)()) ptr; n > 0; --n)
+          (*ppf[n])();
+    }
+}
Index: trunk/src/emx/src/lib/startup/exit.c
===================================================================
--- trunk/src/emx/src/lib/startup/exit.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/exit.c	(revision 18)
@@ -0,0 +1,17 @@
+/* exit.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <emx/startup.h>
+
+void (*_atexit_v[64])(void);
+int _atexit_n = 0;
+
+void exit (int ret)
+{
+  int i;
+
+  for (i = _atexit_n-1; i >= 0; --i)
+    _atexit_v[i]();
+  _cleanup ();
+  _exit (ret);
+}
Index: trunk/src/emx/src/lib/startup/gmon.c
===================================================================
--- trunk/src/emx/src/lib/startup/gmon.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/gmon.c	(revision 18)
@@ -0,0 +1,347 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)gmon.c	5.3 (Berkeley) 5/22/91";
+#endif /* not lint */
+
+#if 0
+#include <unistd.h>
+
+#endif
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#ifdef EMX
+#include <stdlib.h>
+#include <fcntl.h>
+#endif /* EMX */
+
+#include "gmon.h"
+
+#ifndef EMX
+extern mcount() asm ("mcount");
+extern char *minbrk asm ("minbrk");
+#endif /* not EMX */
+
+    /*
+     *	froms is actually a bunch of unsigned shorts indexing tos
+     */
+static int		profiling = 3;
+static unsigned short	*froms;
+static struct tostruct	*tos = 0;
+static long		tolimit = 0;
+static char		*s_lowpc = 0;
+static char		*s_highpc = 0;
+static unsigned long	s_textsize = 0;
+
+static int	ssiz;
+static char	*sbuf;
+static int	s_scale;
+    /* see profil(2) where this is describe (incorrectly) */
+#define		SCALE_1_TO_1	0x10000L
+
+#define	MSG "No space for profiling buffer(s)\n"
+
+monstartup(lowpc, highpc)
+    char	*lowpc;
+    char	*highpc;
+{
+    int			monsize;
+    char		*buffer;
+    register int	o;
+
+	/*
+	 *	round lowpc and highpc to multiples of the density we're using
+	 *	so the rest of the scaling (here and in gprof) stays in ints.
+	 */
+    lowpc = (char *)
+	    ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
+    s_lowpc = lowpc;
+    highpc = (char *)
+	    ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
+    s_highpc = highpc;
+    s_textsize = highpc - lowpc;
+    monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
+    buffer = sbrk( monsize );
+    if ( buffer == (char *) -1 ) {
+	write( 2 , MSG , sizeof(MSG) );
+	return;
+    }
+    froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
+    if ( froms == (unsigned short *) -1 ) {
+	write( 2 , MSG , sizeof(MSG) );
+	froms = 0;
+	return;
+    }
+    tolimit = s_textsize * ARCDENSITY / 100;
+    if ( tolimit < MINARCS ) {
+	tolimit = MINARCS;
+    } else if ( tolimit > 65534 ) {
+	tolimit = 65534;
+    }
+    tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
+    if ( tos == (struct tostruct *) -1 ) {
+	write( 2 , MSG , sizeof(MSG) );
+	froms = 0;
+	tos = 0;
+	return;
+    }
+#ifndef EMX
+    minbrk = sbrk(0);
+#endif /* not EMX */
+    tos[0].link = 0;
+    sbuf = buffer;
+    ssiz = monsize;
+    ( (struct phdr *) buffer ) -> lpc = lowpc;
+    ( (struct phdr *) buffer ) -> hpc = highpc;
+    ( (struct phdr *) buffer ) -> ncnt = ssiz;
+    monsize -= sizeof(struct phdr);
+    if ( monsize <= 0 )
+	return;
+    o = highpc - lowpc;
+    if( monsize < o )
+#ifndef hp300
+	s_scale = ( (float) monsize / o ) * SCALE_1_TO_1;
+#else /* avoid floating point */
+    {
+	int quot = o / monsize;
+
+	if (quot >= 0x10000)
+		s_scale = 1;
+	else if (quot >= 0x100)
+		s_scale = 0x10000 / quot;
+	else if (o >= 0x800000)
+		s_scale = 0x1000000 / (o / (monsize >> 8));
+	else
+		s_scale = 0x1000000 / ((o << 8) / monsize);
+    }
+#endif
+    else
+	s_scale = SCALE_1_TO_1;
+    moncontrol(1);
+}
+
+_mcleanup()
+{
+    int			fd;
+    int			fromindex;
+    int			endfrom;
+    char		*frompc;
+    int			toindex;
+    struct rawarc	rawarc;
+
+    moncontrol(0);
+    fd = creat( "gmon.out" , 0666 );
+    if ( fd < 0 ) {
+	perror( "mcount: gmon.out" );
+	return;
+    }
+#ifdef EMX
+    setmode (fd, O_BINARY);
+#endif /* EMX */
+#   ifdef DEBUG
+	fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
+#   endif DEBUG
+    write( fd , sbuf , ssiz );
+    endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
+    for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
+	if ( froms[fromindex] == 0 ) {
+	    continue;
+	}
+	frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
+	for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
+#	    ifdef DEBUG
+		fprintf( stderr ,
+			"[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
+			frompc , tos[toindex].selfpc , tos[toindex].count );
+#	    endif DEBUG
+	    rawarc.raw_frompc = (unsigned long) frompc;
+	    rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
+	    rawarc.raw_count = tos[toindex].count;
+	    write( fd , &rawarc , sizeof rawarc );
+	}
+    }
+    close( fd );
+}
+
+#ifdef EMX
+_mcount()
+#else /* not EMX */
+mcount()
+#endif /* not EMX */
+{
+	register char			*selfpc;
+	register unsigned short		*frompcindex;
+	register struct tostruct	*top;
+	register struct tostruct	*prevtop;
+	register long			toindex;
+
+	/*
+	 *	find the return address for mcount,
+	 *	and the return address for mcount's caller.
+	 */
+
+	/* selfpc = pc pushed by mcount call.
+	   This identifies the function that was just entered.  */
+	selfpc = (void *) __builtin_return_address (0);
+	/* frompcindex = pc in preceding frame.
+	   This identifies the caller of the function just entered.  */
+	frompcindex = (void *) __builtin_return_address (1);
+	/*
+	 *	check that we are profiling
+	 *	and that we aren't recursively invoked.
+	 */
+	if (profiling) {
+		goto out;
+	}
+#ifdef EMX
+	/* Profile thread 1 only. */
+	if (_gettid () != 1)
+		goto out;
+#endif /* EMX */
+	profiling++;
+	/*
+	 *	check that frompcindex is a reasonable pc value.
+	 *	for example:	signal catchers get called from the stack,
+	 *			not from text space.  too bad.
+	 */
+	frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
+	if ((unsigned long)frompcindex > s_textsize) {
+		goto done;
+	}
+	frompcindex =
+	    &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
+	toindex = *frompcindex;
+	if (toindex == 0) {
+		/*
+		 *	first time traversing this arc
+		 */
+		toindex = ++tos[0].link;
+		if (toindex >= tolimit) {
+			goto overflow;
+		}
+		*frompcindex = toindex;
+		top = &tos[toindex];
+		top->selfpc = selfpc;
+		top->count = 1;
+		top->link = 0;
+		goto done;
+	}
+	top = &tos[toindex];
+	if (top->selfpc == selfpc) {
+		/*
+		 *	arc at front of chain; usual case.
+		 */
+		top->count++;
+		goto done;
+	}
+	/*
+	 *	have to go looking down chain for it.
+	 *	top points to what we are looking at,
+	 *	prevtop points to previous top.
+	 *	we know it is not at the head of the chain.
+	 */
+	for (; /* goto done */; ) {
+		if (top->link == 0) {
+			/*
+			 *	top is end of the chain and none of the chain
+			 *	had top->selfpc == selfpc.
+			 *	so we allocate a new tostruct
+			 *	and link it to the head of the chain.
+			 */
+			toindex = ++tos[0].link;
+			if (toindex >= tolimit) {
+				goto overflow;
+			}
+			top = &tos[toindex];
+			top->selfpc = selfpc;
+			top->count = 1;
+			top->link = *frompcindex;
+			*frompcindex = toindex;
+			goto done;
+		}
+		/*
+		 *	otherwise, check the next arc on the chain.
+		 */
+		prevtop = top;
+		top = &tos[top->link];
+		if (top->selfpc == selfpc) {
+			/*
+			 *	there it is.
+			 *	increment its count
+			 *	move it to the head of the chain.
+			 */
+			top->count++;
+			toindex = prevtop->link;
+			prevtop->link = top->link;
+			top->link = *frompcindex;
+			*frompcindex = toindex;
+			goto done;
+		}
+
+	}
+done:
+	profiling--;
+	/* and fall through */
+out:
+	return;		/* normal return restores saved registers */
+
+overflow:
+	profiling++; /* halt further profiling */
+#   define	TOLIMIT	"mcount: tos overflow\n"
+	write(2, TOLIMIT, sizeof(TOLIMIT));
+	goto out;
+}
+
+/*
+ * Control profiling
+ *	profiling is what mcount checks to see if
+ *	all the data structures are ready.
+ */
+moncontrol(mode)
+    int mode;
+{
+    if (mode) {
+	/* start */
+	profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
+		(int)s_lowpc, s_scale);
+	profiling = 0;
+    } else {
+	/* stop */
+	profil((char *)0, 0, 0, 0);
+	profiling = 3;
+    }
+}
+
Index: trunk/src/emx/src/lib/startup/makefile
===================================================================
--- trunk/src/emx/src/lib/startup/makefile	(revision 18)
+++ trunk/src/emx/src/lib/startup/makefile	(revision 18)
@@ -0,0 +1,66 @@
+#
+# /emx/src/lib/startup/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+.PHONY: o-crt o-crt-bsd obj-crt
+
+ASM=gcc -c -Wall -x assembler-with-cpp
+GCC_BSD=gcc -O2 -mprobe -fstack-check -DEMX $(LIBC_CCFLAGS) $(MT_CCFLAGS)
+
+o-crt: $(L)crt0.o $(L)dll0.o $(L)mcrt0.o
+
+o-crt-bsd: $(L)gcrt0.o
+
+obj-crt: $(L)crt0.obj $(L)dll0.obj $(L)mcrt0.obj $(L)res0.obj
+
+local: ;
+
+cleanup.o: cleanup.c $(I)stdio.h
+crt1.o: crt1.s $(ASM386H)
+crtinit.o: crtinit.c
+crtterm.o: crtterm.c
+ctor.o: ctor.c $(I)stdlib.h
+ctor1.o: ctor1.c $(I)stdlib.h
+dtor.o: dtor.c
+dtor1.o: dtor1.c $(I)stdlib.h
+exit.o: exit.c $(I)stdlib.h $(I)emx/startup.h
+startup.o: startup.c $(I)stdlib.h $(I)stdio.h $(I)emx/syscalls.h \
+		$(FCNTL) $(ERRNO) $(I)sys/ioctl.h $(I)emx/io.h
+_exit.o: _exit.c $(I)stdlib.h $(I)emx/syscalls.h
+
+$(DSTLIB): crt1.o crtinit.o crtterm.o cleanup.o ctor.o \
+    ctor1.o dtor.o dtor1.o exit.o startup.o _exit.o
+	$(AR) r $(DSTLIB) *.o
+
+$(L)crt0.o: $(CPU)/crt0.s
+	$(ASM) -o $(L)crt0.o $(CPU)/crt0.s
+
+$(L)dll0.o: $(CPU)/dll0.s
+	$(ASM) -o $(L)dll0.o $(CPU)/dll0.s
+
+$(L)mcrt0.o: $(CPU)/crt0.s
+	$(ASM) -DMCRT0 -o $(L)mcrt0.o $(CPU)/crt0.s
+
+$(L)gcrt0.o: $(CPU)/crt0.s gmon.c $(I)gmon.h
+	$(ASM) -DMCRT0 -o $(CPU)/tmp1.o $(CPU)/crt0.s
+	$(GCC_BSD) -c -o $(CPU)/tmp2.o gmon.c
+	ld -r -o $(L)gcrt0.o $(CPU)/tmp1.o $(CPU)/tmp2.o
+	-del $(CPU)\tmp1.o
+	-del $(CPU)\tmp2.o
+
+$(L)crt0.obj: $(CPU)/crt0.s
+	$(ASM) -DOMF -o crt0omf.o $(CPU)/crt0.s
+	emxomf -m_text -ds -o $(L)crt0.obj crt0omf.o
+
+$(L)mcrt0.obj: $(CPU)/crt0.s
+	$(ASM) -DOMF -DMCRT0 -o mcrt0omf.o $(CPU)/crt0.s
+	emxomf -m_text -ds -o $(L)mcrt0.obj mcrt0omf.o
+
+$(L)dll0.obj: $(CPU)/dll0.s
+	$(ASM) -DOMF -o dll0omf.o $(CPU)/dll0.s
+	emxomf -l_text -ds -o $(L)dll0.obj dll0omf.o
+
+$(L)res0.obj: $(CPU)/res0.s
+	$(ASM) -DOMF -o res0omf.o $(CPU)/res0.s
+	emxomf -l_text -ds -o $(L)res0.obj res0omf.o
Index: trunk/src/emx/src/lib/startup/startup.c
===================================================================
--- trunk/src/emx/src/lib/startup/startup.c	(revision 18)
+++ trunk/src/emx/src/lib/startup/startup.c	(revision 18)
@@ -0,0 +1,117 @@
+/* startup.c (emx+gcc) -- Copyright (c) 1990-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+/* See app/iodata.c. */
+
+extern int _nfiles;
+extern int _files[];
+extern int _lookahead[];
+
+extern int __crtinit1__;
+extern void __ctordtorInit1 (int *ptr);
+
+/* The version of this libc. */
+static const char _libc_version[] =
+  " libc for emx 0.9d";
+
+/* Display this warning if emx.dll or emx.exe is out of date. */
+static const char _version_warning[] =
+  "WARNING: emx 0.9d or later required\r\n";
+
+
+static void init_files (void);
+
+
+/* Initialize the C run-time library.  This function is called from
+   crt0.s. */
+
+void _startup (void)
+{
+  static int startup_flag;
+
+  /* Protect against multiple calls (for instance, by _CRT_init() in a
+     _DLL_InitTerm() and by the application program's startup code). */
+
+  if (startup_flag)
+    return;
+  startup_flag = 1;
+
+  /* Print a warning message on handle 2 (stderr) if emx.dll or
+     emx.exe is out of date. */
+
+  if (_emx_vcmp < 0x302e3964)   /* 0.9d */
+    __write (2, _version_warning, sizeof (_version_warning) - 1);
+
+  /* Initialize the file handles. */
+
+  init_files ();
+
+  /* Initialize streams etc. if required. */
+
+  __ctordtorInit1 (&__crtinit1__);
+
+  /* ANSI X3.159-1989, 4.1.3: "The value of errno is zero at program
+     startup..."
+
+     The above code usually sets errno to EBADF, therefore we reset
+     errno to zero before calling main(). */
+
+  errno = 0;
+}
+
+
+/* Initialize the file handles. */
+
+static void init_files (void)
+{
+  int i, ht, fl;
+
+  for (i = 0; i < _nfiles; ++i)
+    {
+      _files[i] = 0;
+      _lookahead[i] = -1;
+
+      /* Get the handle type.  If this fails, the handle is not open. */
+
+      if (i < _io_ninherit && __ioctl2 (i, FGETHTYPE, (int)&ht) == 0)
+        {
+          /* init_streams() depends on _files[] being non-zero for
+             open file handles.  When omitting O_TEXT, don't forget to
+             set another bit. */
+
+          _files[i] |= O_TEXT;
+          if (HT_ISDEV (ht))
+            _files[i] |= F_DEV;
+          if (ht == HT_UPIPE || ht == HT_NPIPE)
+            {
+              _files[i] |= F_PIPE;
+              fl = __fcntl (i, F_GETFL, 0);
+              if (fl >= 0)
+                _files[i] |= fl & O_NDELAY;
+            }
+          switch (i)
+            {
+            case 0:
+              _files[0] |= O_RDONLY;
+              break;
+
+            case 1:
+            case 2:
+              _files[i] |= O_WRONLY;
+              break;
+
+            default:
+              /* All other handles can be read and written. */
+              _files[i] |= O_RDWR;
+              break;
+            }
+        }
+    }
+}
Index: trunk/src/emx/src/lib/static/dllinit.c
===================================================================
--- trunk/src/emx/src/lib/static/dllinit.c	(revision 18)
+++ trunk/src/emx/src/lib/static/dllinit.c	(revision 18)
@@ -0,0 +1,22 @@
+/* static/dllinit.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+int _CRT_init (void);
+void __ctordtorInit (void);
+void __ctordtorTerm (void);
+
+unsigned long _DLL_InitTerm (unsigned long mod_handle, unsigned long flag)
+{
+  switch (flag)
+    {
+    case 0:
+      if (_CRT_init () != 0)
+        return 0;
+      __ctordtorInit ();
+      return 1;
+    case 1:
+      __ctordtorTerm ();
+      return 1;
+    default:
+      return 0;
+    }
+}
Index: trunk/src/emx/src/lib/static/makefile
===================================================================
--- trunk/src/emx/src/lib/static/makefile	(revision 18)
+++ trunk/src/emx/src/lib/static/makefile	(revision 18)
@@ -0,0 +1,37 @@
+#
+# /emx/src/lib/static/makefile
+#
+.INCLUDE: /emx/src/lib/lib0.mak
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+.SOURCE.s: ..
+
+.PHONY: clean default dstlib static
+
+LIBSTATIC=$(L)c_static.a
+
+default: static
+
+static .SETDIR=$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN)
+
+dstlib: $(LIBSTATIC)
+
+clean:
+	-del $(CPU)\*.o $(DELOPT)
+
+dllinit.o: dllinit.c
+
+main.o:    ../../gcc/main.c
+	$(GCC) -c ../../gcc/main.c
+
+
+ctor.o:    ../../startup/ctor.c $(I)stdlib.h
+	$(GCC) -c ../../startup/ctor.c
+
+dtor.o:    ../../startup/dtor.c
+	$(GCC) -c ../../startup/dtor.c
+
+$(LIBSTATIC): main.o dllinit.o ctor.o dtor.o
+	$(AR) r $(LIBSTATIC) *.o
Index: trunk/src/emx/src/lib/str/386/bcmp.s
===================================================================
--- trunk/src/emx/src/lib/str/386/bcmp.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/bcmp.s	(revision 18)
@@ -0,0 +1,38 @@
+/ bcmp.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __bcmp
+
+/ int _bcmp (const void *s1, const void *s2, size_t n)
+/ {
+/   size_t i;
+/
+/   for (i = 0; i < n; ++i)
+/     if (s1[i] != s2[i])
+/       return 1;
+/   return 0;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+__bcmp:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %edi         /* s1 */
+        movl    4*4(%esp), %esi         /* s2 */
+        movl    5*4(%esp), %ecx         /* n */
+        xorl    %eax, %eax
+        jecxz   1f                      /* return 0 */
+        repe
+        cmpsb
+        je      1f
+        incl    %eax                    /* return 1 */
+1:      popl    %edi
+        popl    %esi
+        EPILOGUE(_bcmp)
Index: trunk/src/emx/src/lib/str/386/bcopy.s
===================================================================
--- trunk/src/emx/src/lib/str/386/bcopy.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/bcopy.s	(revision 18)
@@ -0,0 +1,62 @@
+/ bcopy.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __bcopy
+
+/ void _bcopy (const void *s1, void *s2, size_t n)
+/ {
+/   size_t i;
+/ 
+/   if ((size_t)s1 < (size_t)s2)
+/     for (i = n; i > 0; --i)
+/       ((char *)s2)[i-1] = ((char *)s1)[i-1];
+/   else
+/     for (i = 0; i < n; ++i)
+/       ((char *)s2)[i] = ((char *)s1)[i];
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+__bcopy:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %esi         /* s1 */
+        movl    4*4(%esp), %edi         /* s2 */
+        movl    5*4(%esp), %ecx         /* n */
+        jecxz   Lreturn
+        cmpl    %edi, %esi
+        jb      2f
+        shrl    $2, %ecx
+        rep
+        movsl
+        movl    5*4(%esp), %ecx         /* n */
+        andl    $3, %ecx
+        rep
+        movsb
+        jmp     Lreturn
+
+        ALIGN
+2:      addl    %ecx, %esi
+        addl    %ecx, %edi
+        subl    $4, %esi
+        subl    $4, %edi
+        std
+        shrl    $2, %ecx
+        rep
+        movsl
+        addl    $3, %esi
+        addl    $3, %edi
+        movl    5*4(%esp), %ecx         /* n */
+        andl    $3, %ecx
+        rep
+        movsb
+        cld
+Lreturn:popl    %edi
+        popl    %esi
+        EPILOGUE(_bcopy)
Index: trunk/src/emx/src/lib/str/386/bzero.s
===================================================================
--- trunk/src/emx/src/lib/str/386/bzero.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/bzero.s	(revision 18)
@@ -0,0 +1,35 @@
+/ bzero.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __bzero
+
+/ void _bzero (void *s, size_t n)
+/ {
+/   size_t i;
+/ 
+/   for (i = 0; i < n; ++i)
+/     ((char *)s)[i] = 0;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+__bzero:
+        PROFILE_NOFRAME
+        pushl   %edi
+        movl    2*4(%esp), %edi         /* s */
+        movl    3*4(%esp), %ecx         /* n */
+        xorl    %eax, %eax
+        shrl    $2, %ecx
+        rep
+        stosl
+        movl    3*4(%esp), %ecx         /* n */
+        andl    $3, %ecx
+        rep
+        stosb
+        popl    %edi
+        EPILOGUE(_bzero)
Index: trunk/src/emx/src/lib/str/386/ffs.s
===================================================================
--- trunk/src/emx/src/lib/str/386/ffs.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/ffs.s	(revision 18)
@@ -0,0 +1,32 @@
+/ ffs.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  __ffs
+
+/ int _ffs (int i)
+/ {
+/   int j;
+/
+/   if (i == 0)
+/     return (0);
+/   for (j = 1; !(i & 1); ++j)
+/     i >>= 1;
+/   return j;
+/ }
+
+        .text
+
+        ALIGN
+
+__ffs:
+        PROFILE_NOFRAME
+        movl    1*4(%esp), %edx         /* i */
+        bsfl    %edx, %eax
+        jz      Lzero
+        incl    %eax
+        jmp     Lreturn
+        ALIGN
+Lzero:  xorl    %eax, %eax
+        ALIGN
+Lreturn:EPILOGUE(_ffs)
Index: trunk/src/emx/src/lib/str/386/index.s
===================================================================
--- trunk/src/emx/src/lib/str/386/index.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/index.s	(revision 18)
@@ -0,0 +1,50 @@
+/ index.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __index
+
+/ char *_index (const char *string, int c)
+/ {
+/   do
+/     {
+/       if (*string == (char)c)
+/         return (char *)string;
+/     } while (*string++ != 0);
+/   return NULL;
+/ }
+
+        .text
+
+        ALIGN
+
+__index:
+        PROFILE_NOFRAME
+        pushl   %esi
+        movl    2*4(%esp), %esi         /* string */
+        movb    3*4(%esp), %ah          /* c */
+        testb   %ah, %ah
+        jz      2f
+        ALIGN
+1:      lodsb
+        cmpb    %ah, %al
+        jz      3f
+        testb   %al, %al
+        jnz     1b
+        xorl    %eax, %eax
+        jmp     Ldone
+
+/ Special case: search for 0 character
+
+        ALIGN
+2:      xchgl   %esi, %edi
+        movl    $-1, %ecx
+        xorb    %al, %al
+        repne
+        scasb
+        xchgl   %esi, %edi
+
+        ALIGN
+3:      lea     -1(%esi), %eax
+Ldone:  popl    %esi
+        EPILOGUE(_index)
Index: trunk/src/emx/src/lib/str/386/memchr.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memchr.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memchr.s	(revision 18)
@@ -0,0 +1,42 @@
+/ memchr.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _memchr
+
+/ void *memchr (const void *s, int c, size_t n)
+/ {
+/   size_t i;
+/   const char *p;
+/
+/   p = s;
+/   for (i = 0; i < n; ++i)
+/       if (p[i] == (char)c)
+/           return (void *)(p+i);
+/   return NULL;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_memchr:
+        PROFILE_NOFRAME
+        pushl   %edi
+        movl    2*4(%esp), %edi         /* s */
+        movb    3*4(%esp), %al          /* c */
+        movl    4*4(%esp), %ecx         /* n */
+        jecxz   Lnull                   /* not found */
+        repne
+        scasb
+        jne     Lnull                   /* not found */
+        lea     -1(%edi), %eax
+        jmp     Ldone
+
+        ALIGN
+Lnull:  xorl    %eax, %eax              /* return NULL */
+        ALIGN
+Ldone:  popl    %edi
+        EPILOGUE(memchr)
Index: trunk/src/emx/src/lib/str/386/memcmp.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memcmp.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memcmp.s	(revision 18)
@@ -0,0 +1,43 @@
+/ memcmp.s (emx+gcc) -- Copyright (c) 1990-1994 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _memcmp
+
+/ int memcmp (const void *s1, const void *s2, size_t n)
+/ {
+/   size_t i;
+/   int d;
+/     
+/   for (i = 0; i < n; ++i)
+/     {
+/       d = (int)((unsigned char *)s1)[i] - (int)((unsigned char *)s2)[i];
+/       if (d != 0)
+/         return d;
+/     }
+/   return 0;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_memcmp:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %edi         /* s1 */
+        movl    4*4(%esp), %esi         /* s2 */
+        movl    5*4(%esp), %ecx         /* n */
+        xorl    %eax, %eax
+        jecxz   Ldone
+        repe
+        cmpsb
+        movb    -1(%edi), %al
+        movzbl  -1(%esi), %ecx
+        subl    %ecx, %eax
+Ldone:  popl    %edi
+        popl    %esi
+        EPILOGUE(memcmp)
Index: trunk/src/emx/src/lib/str/386/memcount.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memcount.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memcount.s	(revision 18)
@@ -0,0 +1,43 @@
+/ memcount.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __memcount
+
+/ size_t _memcount (const void *mem, int c, size_t n)
+/ {
+/   size_t i;
+/ 
+/   i = 0;
+/   while (n > 0)
+/     {
+/       if (*mem == c) ++i;
+/       ++mem; --n;
+/     }
+/   return i;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+__memcount:
+        PROFILE_NOFRAME
+        pushl   %edi
+        movl    2*4(%esp), %edi         /* mem */
+        movl    3*4(%esp), %eax         /* c */
+        movl    4*4(%esp), %ecx         /* n */
+        xorl    %edx, %edx
+        jecxz   Ldone
+         ALIGN
+1:      repne
+        scasb
+        jne     Ldone
+        incl    %edx
+        testl   %ecx, %ecx
+        jne     1b
+Ldone:  movl    %edx, %eax
+        popl    %edi
+        EPILOGUE(_memcount)
Index: trunk/src/emx/src/lib/str/386/memcpy.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memcpy.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memcpy.s	(revision 18)
@@ -0,0 +1,39 @@
+/ memcpy.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _memcpy
+
+/ void *memcpy (void *s1, const void *s2, size_t n)
+/ {
+/   size_t i;
+/   
+/   for (i = 0; i < n; ++i)
+/     ((char *)s1)[i] = ((char *)s2)[i];
+/   return s1;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_memcpy:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %edi         /* s1 */
+        movl    4*4(%esp), %esi         /* s2 */
+        movl    5*4(%esp), %ecx         /* n */
+        shrl    $2, %ecx
+        rep
+        movsl
+        movl    5*4(%esp), %ecx         /* n */
+        andl    $3, %ecx
+        rep
+        movsb
+        movl    3*4(%esp), %eax         /* s1 */
+        popl    %edi
+        popl    %esi
+        EPILOGUE(memcpy)
Index: trunk/src/emx/src/lib/str/386/memdif.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memdif.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memdif.s	(revision 18)
@@ -0,0 +1,44 @@
+/ memdif.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __memdif
+
+/ size_t _memdif (const void *mem1, const void *mem2, size_t n)
+/ {
+/   size_t i;
+/     
+/   for (i = 0; i < n; ++i)
+/     if (((char *)mem1)[i] != ((char *)mem2)[i])
+/       return i;
+/   return _MEMDIF_EQ;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+__memdif:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %edi         /* mem1 */
+        movl    4*4(%esp), %esi         /* mem2 */
+        movl    5*4(%esp), %ecx         /* n */
+        xorl    %eax, %eax
+        jecxz   Lequal
+        repe
+        cmpsb
+        je      Lequal
+        decl    %edi
+        subl    3*4(%esp), %edi
+        movl    %edi, %eax
+        jmp     Ldone
+
+        ALIGN
+Lequal: movl    $-1, %eax               /* _MEMDIF_EQ */
+Ldone:  popl    %edi
+        popl    %esi
+        EPILOGUE(_memdif)
Index: trunk/src/emx/src/lib/str/386/memmove.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memmove.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memmove.s	(revision 18)
@@ -0,0 +1,65 @@
+/ memmove.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _memmove
+
+/ void *memmove (void *s1, const void *s2, size_t n)
+/ {
+/   size_t i;
+/   
+/   if ((size_t)s1 < (size_t)s2)
+/     for (i = 0; i < n; ++i)
+/       ((char *)s1)[i] = ((char *)s2)[i];
+/   else
+/     for (i = n; i > 0; --i)                          /* i is unsigned! */
+/       ((char *)s1)[i-1] = ((char *)s2)[i-1];
+/   return s1;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_memmove:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %edi         /* s1 */
+        movl    4*4(%esp), %esi         /* s2 */
+        movl    5*4(%esp), %ecx         /* n */
+        jecxz   Lreturn
+        cmpl    %edi, %esi
+        jb      2f
+        shrl    $2, %ecx
+        rep
+        movsl
+        movl    5*4(%esp), %ecx         /* n */
+        andl    $3, %ecx
+        rep
+        movsb
+        jmp     Lreturn
+
+        ALIGN
+
+2:      addl    %ecx, %esi
+        addl    %ecx, %edi
+        subl    $4, %esi
+        subl    $4, %edi
+        std
+        shrl    $2, %ecx
+        rep
+        movsl
+        addl    $3, %esi
+        addl    $3, %edi
+        movl    5*4(%esp), %ecx         /* n */
+        andl    $3, %ecx
+        rep
+        movsb
+        cld
+Lreturn:movl    3*4(%esp), %eax         /* s1 */
+        popl    %edi
+        popl    %esi
+        EPILOGUE(memmove)
Index: trunk/src/emx/src/lib/str/386/memrchr.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memrchr.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memrchr.s	(revision 18)
@@ -0,0 +1,45 @@
+/ memrchr.s (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __memrchr
+
+/ void *_memrchr (const void *s, int c, size_t n)
+/ {
+/   size_t i;
+/   const char *p;
+/
+/   p = s;
+/   for (i = n; i != 0; --i)
+/       if (p[i-1] == (char)c)
+/           return (void *)(p+i-1);
+/   return NULL;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+__memrchr:
+        PROFILE_NOFRAME
+        pushl   %edi
+        movl    2*4(%esp), %edi         /* s */
+        movb    3*4(%esp), %al          /* c */
+        movl    4*4(%esp), %ecx         /* n */
+        jecxz   Lnull                   /* not found */
+        addl    %ecx, %edi
+        decl    %edi
+        std
+        repne
+        scasb
+        cld
+        jne     Lnull                   /* not found */
+        lea     1(%edi), %eax
+        jmp     Lreturn
+
+        ALIGN
+Lnull:  xorl    %eax, %eax              /* return NULL */
+Lreturn:popl    %edi
+        EPILOGUE(_memrchr)
Index: trunk/src/emx/src/lib/str/386/memset.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memset.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memset.s	(revision 18)
@@ -0,0 +1,41 @@
+/ memset.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _memset
+
+/ void *memset (void *s, int c, size_t n)
+/ {
+/   size_t i;
+/ 
+/   for (i = 0; i < n; ++i)
+/     ((char *)s)[i] = (char)c;
+/   return s;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_memset:
+        PROFILE_NOFRAME
+        pushl   %edi
+        movl    2*4(%esp), %edi         /* s */
+        movl    3*4(%esp), %eax         /* c */
+        movl    4*4(%esp), %ecx         /* n */
+        movb    %al, %ah
+        movl    %eax, %edx
+        shll    $16, %eax
+        movw    %dx, %ax
+        shrl    $2, %ecx
+        rep
+        stosl
+        movl    4*4(%esp), %ecx         /* n */
+        andl    $3, %ecx
+        rep
+        stosb
+        movl    2*4(%esp), %eax         /* s */
+        popl    %edi
+        EPILOGUE(memset)
Index: trunk/src/emx/src/lib/str/386/memswap.s
===================================================================
--- trunk/src/emx/src/lib/str/386/memswap.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/memswap.s	(revision 18)
@@ -0,0 +1,58 @@
+/ memswap.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __memswap
+
+/ void _memswap (void *s1, void *s2, size_t n)
+/ {
+/   char *c1, *c2, c;
+/   int *i1, *i2, i;
+/ 
+/   i1 = s1; i2 = s2;
+/   while (n >= sizeof (int))
+/     {
+/       i = *i1; *i1++ = *i2; *i2++ = i;
+/       n -= sizeof (int);
+/       }
+/   c1 = (char *)i1; c2 = (char *)i2;
+/   while (n >= 1)
+/     {
+/       c = *c1; *c1++ = *c2; *c2++ = c;
+/       --n;
+/     }
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+__memswap:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %edi         /* s1 */
+        movl    4*4(%esp), %esi         /* s2 */
+        movl    5*4(%esp), %ecx         /* n */
+        shrl    $2, %ecx
+        jz      2f
+        ALIGN
+1:      movl    (%edi), %eax
+        xchgl   (%esi), %eax
+        stosl
+        addl    $4, %esi
+        loop    1b
+2:      movl    5*4(%esp), %ecx         /* n */
+        andl    $3, %ecx
+        jz      Lreturn
+        ALIGN
+3:      movb    (%edi), %al
+        xchgb   (%esi), %al
+        stosb
+        incl    %esi
+        loop    3b
+Lreturn:popl    %edi
+        popl    %esi
+        EPILOGUE(_memswap)
Index: trunk/src/emx/src/lib/str/386/rindex.s
===================================================================
--- trunk/src/emx/src/lib/str/386/rindex.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/rindex.s	(revision 18)
@@ -0,0 +1,47 @@
+/ rindex.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __rindex
+  
+/ char *_rindex (const char *string, int c)
+/ {
+/   int i;
+/   
+/   i = 0;
+/   while (string[i] != 0) ++i;
+/   while (i >= 0)
+/     if (string[i] == (char)c)
+/       return ((char *)(string+i));
+/     else
+/       --i;
+/   return NULL;
+/ }
+
+        .text
+
+        ALIGN
+
+__rindex:
+        PROFILE_NOFRAME
+        pushl   %edi
+        movl    2*4(%esp), %edi         /* string */
+        movl    $-1, %ecx
+        xorb    %al, %al
+        repne
+        scasb
+        notl    %ecx                    /* ecx = strlen (string) + 1 */
+        decl    %edi                    /* edi = string + strlen (string) */
+        movb    3*4(%esp), %al          /* c */
+        std
+        repne
+        scasb
+        cld
+        jne     Lnull
+        lea     1(%edi), %eax
+        jmp     Lreturn
+
+        ALIGN
+Lnull:  xorl    %eax, %eax
+Lreturn:popl    %edi
+        EPILOGUE(_rindex)
Index: trunk/src/emx/src/lib/str/386/strcat.s
===================================================================
--- trunk/src/emx/src/lib/str/386/strcat.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/strcat.s	(revision 18)
@@ -0,0 +1,44 @@
+/ strcat.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _strcat
+
+/ char *strcat (char *string1, const char *string2)
+/ {
+/   char *dst;
+/ 
+/   dst = string1;
+/   while (*dst != 0)
+/     ++dst;
+/   while ((*dst = *string2) != 0)
+/     ++dst, ++string2;
+/   return string1;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_strcat:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %edi         /* string1 */
+        movl    $-1, %ecx
+        movb    $0, %al
+        repne
+        scasb
+        decl    %edi
+        movl    4*4(%esp), %esi         /* string2 */
+        ALIGN
+1:      lodsb
+        stosb
+        testb   %al, %al
+        jnz     1b
+        movl    3*4(%esp), %eax         /* string1 */
+        popl    %edi
+        popl    %esi
+        EPILOGUE(strcat)
Index: trunk/src/emx/src/lib/str/386/strchr.s
===================================================================
--- trunk/src/emx/src/lib/str/386/strchr.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/strchr.s	(revision 18)
@@ -0,0 +1,50 @@
+/ strchr.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _strchr
+
+/ char *strchr (const char *string, int c)
+/ {
+/   do
+/     {
+/       if (*string == (char)c)
+/         return (char *)string;
+/     } while (*string++ != 0);
+/   return NULL;
+/ }
+
+        .text
+
+        ALIGN
+
+_strchr:
+        PROFILE_NOFRAME
+        pushl   %esi
+        movl    2*4(%esp), %esi         /* string */
+        movb    3*4(%esp), %ah          /* c */
+        testb   %ah, %ah
+        jz      Lstrlen
+        ALIGN
+1:      lodsb
+        cmpb    %ah, %al
+        jz      Lfound
+        testb   %al, %al
+        jnz     1b
+        xorl    %eax, %eax
+        jmp     Lreturn
+
+/ Special case: search for 0 character
+
+        ALIGN
+Lstrlen:xchgl   %esi, %edi
+        movl    $-1, %ecx
+        xorb    %al, %al
+        repne
+        scasb
+        xchgl   %esi, %edi
+
+        ALIGN
+Lfound: lea     -1(%esi), %eax
+Lreturn:popl    %esi
+        EPILOGUE(strchr)
Index: trunk/src/emx/src/lib/str/386/strcmp.s
===================================================================
--- trunk/src/emx/src/lib/str/386/strcmp.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/strcmp.s	(revision 18)
@@ -0,0 +1,46 @@
+/ strcmp.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _strcmp
+
+/ int strcmp (const char *string1, const char *string2)
+/ {
+/   int d;
+/   
+/   for (;;)
+/     {
+/       d = (int)(unsigned char)*string1 - (int)(unsigned char)*string2;
+/       if (d != 0 || *string1 == 0 || *string2 == 0)
+/         return d;
+/       ++string1; ++string2;
+/     }
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_strcmp:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %esi         /* string1 */
+        movl    4*4(%esp), %edi         /* string2 */
+        xorl    %eax, %eax
+        ALIGN
+1:      lodsb
+        scasb
+        jne     Ldiff
+        testb   %al, %al
+        jne     1b
+        jmp     Lreturn
+
+        ALIGN
+Ldiff:  movzbl  -1(%edi), %ecx
+        subl    %ecx, %eax
+Lreturn:popl    %edi
+        popl    %esi
+        EPILOGUE(strcmp)
Index: trunk/src/emx/src/lib/str/386/strcpy.s
===================================================================
--- trunk/src/emx/src/lib/str/386/strcpy.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/strcpy.s	(revision 18)
@@ -0,0 +1,37 @@
+/ strcpy.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _strcpy
+
+/ char *strcpy (char *string1, const char *string2)
+/ {
+/   char *dst;
+/ 
+/   dst = string1;
+/   while ((*dst = *string2) != 0)
+/     ++dst, ++string2;
+/   return string1;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_strcpy:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %edi         /* string1 */
+        movl    4*4(%esp), %esi         /* string2 */
+        ALIGN
+1:      lodsb
+        stosb
+        testb   %al, %al
+        jnz     1b
+        movl    3*4(%esp), %eax         /* string1 */
+        popl    %edi
+        popl    %esi
+        EPILOGUE(strcpy)
Index: trunk/src/emx/src/lib/str/386/strlen.s
===================================================================
--- trunk/src/emx/src/lib/str/386/strlen.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/strlen.s	(revision 18)
@@ -0,0 +1,33 @@
+/ strlen.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _strlen
+
+/ size_t strlen (const char *string)
+/ {
+/   size_t i;
+/ 
+/   i = 0;
+/   while (string[i] != 0) ++i;
+/   return i;
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+_strlen:
+        PROFILE_NOFRAME
+        pushl   %edi
+        movl    2*4(%esp), %edi         /* string */
+        movl    $-1, %ecx
+        xorb    %al, %al
+        repne
+        scasb
+        movl    $-2, %eax
+        subl    %ecx, %eax
+        popl    %edi
+        EPILOGUE(strlen)
Index: trunk/src/emx/src/lib/str/386/strrchr.s
===================================================================
--- trunk/src/emx/src/lib/str/386/strrchr.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/strrchr.s	(revision 18)
@@ -0,0 +1,47 @@
+/ strrchr.s (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl _strrchr
+  
+/ char *strrchr (const char *string, int c)
+/ {
+/   int i;
+/   
+/   i = 0;
+/   while (string[i] != 0) ++i;
+/   while (i >= 0)
+/     if (string[i] == (char)c)
+/       return (char *)(string+i);
+/     else
+/       --i;
+/   return NULL;
+/ }
+
+        .text
+
+        ALIGN
+
+_strrchr:
+        PROFILE_NOFRAME
+        pushl   %edi
+        movl    2*4(%esp), %edi         /* string */
+        movl    $-1, %ecx
+        xorb    %al, %al
+        repne
+        scasb
+        notl    %ecx                    /* ecx = strlen (string) + 1 */
+        decl    %edi                    /* edi = string + strlen (string) */
+        movb    3*4(%esp), %al          /* c */
+        std
+        repne
+        scasb
+        cld
+        jne     Lnull
+        lea     1(%edi), %eax
+        jmp     Lreturn
+
+        ALIGN
+Lnull:  xorl    %eax, %eax
+Lreturn:popl    %edi
+        EPILOGUE(strrchr)
Index: trunk/src/emx/src/lib/str/386/swab.s
===================================================================
--- trunk/src/emx/src/lib/str/386/swab.s	(revision 18)
+++ trunk/src/emx/src/lib/str/386/swab.s	(revision 18)
@@ -0,0 +1,43 @@
+/ swab.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl __swab
+
+/ void _swab (const void *src, void *dst, size_t n)
+/ {
+/   char *s, *d;
+/ 
+/   if (n & 1) return;
+/   while (n > 0)
+/     {
+/       d[0] = s[1];
+/       d[1] = s[0];
+/       d += 2; s += 2; n -= 2;
+/     }
+/ }
+
+/ assumes ds=es!
+
+        .text
+
+        ALIGN
+
+__swab:
+        PROFILE_NOFRAME
+        pushl   %esi
+        pushl   %edi
+        movl    3*4(%esp), %esi         /* src */
+        movl    4*4(%esp), %edi         /* dst */
+        movl    5*4(%esp), %ecx         /* n */
+        shrl    $1, %ecx
+        jc      Lreturn
+        jz      Lreturn
+        ALIGN
+1:      lodsw
+        xchgb   %al, %ah
+        stosw
+        loop    1b
+Lreturn:popl    %edi
+        popl    %esi
+        EPILOGUE(_swab)
Index: trunk/src/emx/src/lib/str/_strncpy.c
===================================================================
--- trunk/src/emx/src/lib/str/_strncpy.c	(revision 18)
+++ trunk/src/emx/src/lib/str/_strncpy.c	(revision 18)
@@ -0,0 +1,17 @@
+/* _strncpy.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+char *_strncpy (char *string1, const char *string2, size_t size)
+{
+  if (size > 0)
+    {
+      while (size > 1 && *string2 != 0)
+        {
+          *string1++ = *string2++;
+          --size;
+        }
+      *string1 = 0;
+    }
+  return string1;
+}
Index: trunk/src/emx/src/lib/str/makefile
===================================================================
--- trunk/src/emx/src/lib/str/makefile	(revision 18)
+++ trunk/src/emx/src/lib/str/makefile	(revision 18)
@@ -0,0 +1,59 @@
+#
+# /emx/src/lib/str/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+bcmp.o: bcmp.s $(ASM386H)
+bcopy.o: bcopy.s $(ASM386H)
+bzero.o: bzero.s $(ASM386H)
+ffs.o: ffs.s $(ASM386H)
+index.o: index.s $(ASM386H)
+memccpy.o: memccpy.c $(I)memory.h $(I)string.h
+memchr.o: memchr.s $(ASM386H)
+memcmp.o: memcmp.s $(ASM386H)
+memcpy.o: memcpy.s $(ASM386H)
+memcount.o: memcount.s $(ASM386H)
+memdif.o: memdif.s $(ASM386H)
+memicmp.o: memicmp.c $(I)memory.h $(I)string.h $(I)ctype.h
+memmove.o: memmove.s $(ASM386H)
+memrchr.o: memrchr.s $(ASM386H)
+memset.o: memset.s $(ASM386H)
+memswap.o: memswap.s $(ASM386H)
+rindex.o: rindex.s $(ASM386H)
+strcat.o: strcat.s $(ASM386H)
+strchr.o: strchr.s $(ASM386H)
+strcmp.o: strcmp.s $(ASM386H)
+strcoll.o: strcoll.c $(I)string.h
+strcpy.o: strcpy.s $(ASM386H)
+strcspn.o: strcspn.c $(I)string.h
+strdup.o: strdup.c $(I)string.h $(I)stdlib.h
+strerror.o: strerror.c $(I)string.h $(I)stdlib.h $(I)emx/thread.h
+stricmp.o: stricmp.c $(I)string.h $(I)ctype.h
+strlen.o: strlen.s $(ASM386H)
+strlwr.o: strlwr.c $(I)string.h $(I)ctype.h
+strncat.o: strncat.c $(I)string.h
+strncmp.o: strncmp.c $(I)string.h
+strncpy.o: strncpy.c $(I)string.h
+strnicmp.o: strnicmp.c $(I)string.h $(I)ctype.h
+strnset.o: strnset.c $(I)string.h
+strpbrk.o: strpbrk.c $(I)string.h
+strrchr.o: strrchr.s $(ASM386H)
+strrev.o: strrev.c $(I)string.h
+strset.o: strset.c $(I)string.h
+strspn.o: strspn.c $(I)string.h
+strstr.o: strstr.c $(I)string.h
+strtok.o: strtok.c $(I)string.h $(I)emx/thread.h
+strupr.o: strupr.c $(I)string.h $(I)ctype.h
+strxfrm.o: strxfrm.c $(I)string.h
+swab.o: swab.s $(ASM386H)
+_strncpy.o: _strncpy.c $(I)string.h
+
+$(DSTLIB): memset.o memchr.o memcpy.o memccpy.o memcmp.o memmove.o memicmp.o \
+    strlen.o strchr.o strrchr.o strstr.o strcpy.o strcat.o strset.o strtok.o \
+    strdup.o strrev.o strspn.o strcspn.o strcmp.o stricmp.o strerror.o \
+    strlwr.o strupr.o strpbrk.o strncpy.o strncat.o strnset.o strncmp.o \
+    strnicmp.o _strncpy.o strcoll.o strxfrm.o memcount.o memswap.o memdif.o \
+    memrchr.o bcmp.o bcopy.o bzero.o ffs.o index.o rindex.o swab.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/str/memccpy.c
===================================================================
--- trunk/src/emx/src/lib/str/memccpy.c	(revision 18)
+++ trunk/src/emx/src/lib/str/memccpy.c	(revision 18)
@@ -0,0 +1,15 @@
+/* memccpy.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+void *_memccpy (void *s1, const void *s2, int c, size_t n)
+{
+  size_t i;
+  
+  for (i = 0; i < n; ++i)
+    {
+      if ((((char *)s1)[i] = ((char *)s2)[i]) == (char)c)
+        return (char *)s1+i+1;
+    }
+  return NULL;
+}
Index: trunk/src/emx/src/lib/str/memicmp.c
===================================================================
--- trunk/src/emx/src/lib/str/memicmp.c	(revision 18)
+++ trunk/src/emx/src/lib/str/memicmp.c	(revision 18)
@@ -0,0 +1,24 @@
+/* memicmp.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <ctype.h>
+
+int _memicmp (const void *s1, const void *s2, size_t n)
+{
+  size_t i;
+  int d;
+    
+  for (i = 0; i < n; ++i)
+    {
+      d = tolower (((unsigned char *)s1)[i])
+        - tolower (((unsigned char *)s2)[i]);
+      if (d != 0)
+        {
+          if (d > 0)
+            return 1;
+          else
+            return -1;
+        }
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/str/strcoll.c
===================================================================
--- trunk/src/emx/src/lib/str/strcoll.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strcoll.c	(revision 18)
@@ -0,0 +1,10 @@
+/* strcoll.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+/* Ignore the current locale for now. */
+
+int strcoll (const char *string1, const char *string2)
+{
+  return strcmp (string1, string2);
+}
Index: trunk/src/emx/src/lib/str/strcspn.c
===================================================================
--- trunk/src/emx/src/lib/str/strcspn.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strcspn.c	(revision 18)
@@ -0,0 +1,18 @@
+/* strcspn.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+size_t strcspn (const char *string1, const char *string2)
+{
+  char table[256];
+  size_t i;
+
+  memset (table, 1, 256);
+  while (*string2 != 0)
+    table[(unsigned char)*string2++] = 0;
+  table[0] = 0;
+  i = 0;
+  while (table[(unsigned char)string1[i]])
+    ++i;
+  return i;
+}
Index: trunk/src/emx/src/lib/str/strdup.c
===================================================================
--- trunk/src/emx/src/lib/str/strdup.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strdup.c	(revision 18)
@@ -0,0 +1,16 @@
+/* strdup.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <stdlib.h>
+
+char *_strdup (const char *string)
+{
+  char *p;
+  size_t n;
+
+  n = strlen (string) + 1;
+  p = malloc (n);
+  if (p != NULL)
+    memcpy (p, string, n);
+  return p;
+}
Index: trunk/src/emx/src/lib/str/strerror.c
===================================================================
--- trunk/src/emx/src/lib/str/strerror.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strerror.c	(revision 18)
@@ -0,0 +1,24 @@
+/* strerror.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <emx/thread.h>
+
+char *strerror (int errnum)
+{
+  if (errnum >= 0 && errnum < _sys_nerr)
+    return (char *)_sys_errlist [errnum];
+  else
+    {
+      static char msg[] = "Unknown error ";
+#if defined (__MT__)
+      struct _thread *tp = _thread();
+#define result (tp->_th_error)
+#else
+      static char result[32];
+#endif
+      memcpy (result, msg, sizeof (msg) - 1);
+      _itoa (errnum, result + sizeof (msg) - 1, 10);
+      return result;
+    }
+}
Index: trunk/src/emx/src/lib/str/stricmp.c
===================================================================
--- trunk/src/emx/src/lib/str/stricmp.c	(revision 18)
+++ trunk/src/emx/src/lib/str/stricmp.c	(revision 18)
@@ -0,0 +1,18 @@
+/* stricmp.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <ctype.h>
+
+int _stricmp (const char *string1, const char *string2)
+{
+  int d;
+
+  for (;;)
+    {
+      d = tolower ((unsigned char)*string1)
+        - tolower ((unsigned char)*string2);
+      if (d != 0 || *string1 == 0 || *string2 == 0)
+        return d;
+      ++string1; ++string2;
+    }
+}
Index: trunk/src/emx/src/lib/str/strlwr.c
===================================================================
--- trunk/src/emx/src/lib/str/strlwr.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strlwr.c	(revision 18)
@@ -0,0 +1,14 @@
+/* strlwr.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <ctype.h>
+
+char *_strlwr (char *string)
+{
+  unsigned char *p;
+
+  for (p = (unsigned char *)string; *p != 0; ++p)
+    if (isupper (*p))
+      *p = (unsigned char)_tolower (*p);
+  return string;
+}
Index: trunk/src/emx/src/lib/str/strncat.c
===================================================================
--- trunk/src/emx/src/lib/str/strncat.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strncat.c	(revision 18)
@@ -0,0 +1,19 @@
+/* strncat.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+char *strncat (char *string1, const char *string2, size_t count)
+{
+  char *dst;
+
+  dst = string1;
+  while (*dst != 0)
+    ++dst;
+  while (count > 0 && *string2 != 0)
+    {
+      *dst++ = *string2++;
+      --count;
+    }
+  *dst = 0;
+  return string1;
+}
Index: trunk/src/emx/src/lib/str/strncmp.c
===================================================================
--- trunk/src/emx/src/lib/str/strncmp.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strncmp.c	(revision 18)
@@ -0,0 +1,18 @@
+/* strncmp.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+int strncmp (const char *string1, const char *string2, size_t count)
+{
+  int d;
+
+  while (count != 0)
+    {
+      d = (int)(unsigned char)*string1 - (int)(unsigned char)*string2;
+      if (d != 0 || *string1 == 0 || *string2 == 0)
+        return d;
+      ++string1; ++string2;
+      --count;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/str/strncpy.c
===================================================================
--- trunk/src/emx/src/lib/str/strncpy.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strncpy.c	(revision 18)
@@ -0,0 +1,21 @@
+/* strncpy.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+char *strncpy (char *string1, const char *string2, size_t count)
+{
+  char *dst;
+
+  dst = string1;
+  while (count > 0 && *string2 != 0)
+    {
+      *dst++ = *string2++;
+      --count;
+    }
+  while (count > 0)
+    {
+      *dst++ = 0;
+      --count;
+    }
+  return string1;
+}
Index: trunk/src/emx/src/lib/str/strnicmp.c
===================================================================
--- trunk/src/emx/src/lib/str/strnicmp.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strnicmp.c	(revision 18)
@@ -0,0 +1,20 @@
+/* strnicmp.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <ctype.h>
+
+int _strnicmp (const char *string1, const char *string2, size_t count)
+{
+  int d;
+
+  while (count != 0)
+    {
+      d = tolower ((unsigned char)*string1)
+        - tolower ((unsigned char)*string2);
+      if (d != 0 || *string1 == 0 || *string2 == 0)
+        return d;
+      ++string1; ++string2;
+      --count;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/str/strnset.c
===================================================================
--- trunk/src/emx/src/lib/str/strnset.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strnset.c	(revision 18)
@@ -0,0 +1,16 @@
+/* strnset.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+char *_strnset (char *string, int c, size_t count)
+{
+  char *dst;
+
+  dst = string;
+  while (count > 0 && *dst != 0)
+    {
+      *dst++ = (char)c;
+      --count;
+    }
+  return string;
+}
Index: trunk/src/emx/src/lib/str/strpbrk.c
===================================================================
--- trunk/src/emx/src/lib/str/strpbrk.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strpbrk.c	(revision 18)
@@ -0,0 +1,16 @@
+/* strpbrk.c (emx+gcc) -- Copyright (c) 1990-1993 by Eberhard Mattes */
+
+#include <string.h>
+
+char *strpbrk (const char *string1, const char *string2)
+{
+  char table[256];
+
+  memset (table, 1, 256);
+  while (*string2 != 0)
+    table[(unsigned char)*string2++] = 0;
+  table[0] = 0;
+  while (table[(unsigned char)*string1])
+    ++string1;
+  return (*string1 == 0 ? NULL : (char *)string1);
+}
Index: trunk/src/emx/src/lib/str/strrev.c
===================================================================
--- trunk/src/emx/src/lib/str/strrev.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strrev.c	(revision 18)
@@ -0,0 +1,19 @@
+/* strrev.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+char *_strrev (char *string)
+{
+  char *p, *q, c;
+
+  p = q = string;
+  while (*q != 0)
+    ++q;
+  --q;                                  /* Benign, as string must be != 0 */
+  while ((size_t)q > (size_t)p)
+    {
+      c = *p; *p = *q; *q = c;
+      ++p; --q;
+    }
+  return string;
+}
Index: trunk/src/emx/src/lib/str/strset.c
===================================================================
--- trunk/src/emx/src/lib/str/strset.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strset.c	(revision 18)
@@ -0,0 +1,13 @@
+/* strset.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+char *_strset (char *string, int c)
+{
+  char *dst;
+
+  dst = string;
+  while (*dst != 0)
+    *dst++ = (char)c;
+  return string;
+}
Index: trunk/src/emx/src/lib/str/strspn.c
===================================================================
--- trunk/src/emx/src/lib/str/strspn.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strspn.c	(revision 18)
@@ -0,0 +1,18 @@
+/* strspn.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+size_t strspn (const char *string1, const char *string2)
+{
+  char table[256];
+  size_t i;
+
+  memset (table, 0, 256);
+  while (*string2 != 0)
+    table[(unsigned char)*string2++] = 1;
+  table[0] = 0;
+  i = 0;
+  while (table[(unsigned char)string1[i]])
+    ++i;
+  return i;
+}
Index: trunk/src/emx/src/lib/str/strstr.c
===================================================================
--- trunk/src/emx/src/lib/str/strstr.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strstr.c	(revision 18)
@@ -0,0 +1,30 @@
+/* strstr.c (emx+gcc) -- Copyright (c) 1990-1999 by Eberhard Mattes */
+
+#include <string.h>
+
+char *strstr (const char *string1, const char *string2)
+{
+  int len1, len2, i;
+  char first;
+
+  if (*string2 == 0)
+    return (char *)string1;
+  len1 = 0;
+  while (string1[len1] != 0) ++len1;
+  len2 = 0;
+  while (string2[len2] != 0) ++len2;
+  first = *string2;
+  while (len1 >= len2)
+    {
+      if (*string1 == first)
+        {
+          for (i = 1; i < len2; ++i)
+            if (string1[i] != string2[i])
+              break;
+          if (i >= len2)
+            return (char *)string1;
+        }
+      ++string1; --len1;
+    }
+  return NULL;
+}
Index: trunk/src/emx/src/lib/str/strtok.c
===================================================================
--- trunk/src/emx/src/lib/str/strtok.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strtok.c	(revision 18)
@@ -0,0 +1,46 @@
+/* strtok.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <emx/thread.h>
+
+char *strtok (char *string1, const char *string2)
+{
+  char table[256];
+  unsigned char *p, *result;
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#define next (tp->_th_strtok_ptr)
+#else
+    static unsigned char *next = NULL;
+#endif
+  if (string1 != NULL)
+    p = (unsigned char *)string1;
+  else
+    {
+      if (next == NULL)
+        return NULL;
+      p = next;
+    }
+  memset (table, 0, 256);
+  while (*string2 != 0)
+    table[(unsigned char)*string2++] = 1;
+  table[0] = 0;
+  while (table[*p])
+    ++p;
+  result = p;
+  table[0] = 1;
+  while (!table[*p])
+    ++p;
+  if (*p == 0)
+    {
+      if (p == result)
+        {
+          next = NULL;
+          return NULL;
+        }
+    }
+  else
+    *p++ = 0;
+  next = p;
+  return (char *)result;
+}
Index: trunk/src/emx/src/lib/str/strupr.c
===================================================================
--- trunk/src/emx/src/lib/str/strupr.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strupr.c	(revision 18)
@@ -0,0 +1,14 @@
+/* strupr.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <string.h>
+#include <ctype.h>
+
+char *_strupr (char *string)
+{
+  unsigned char *p;
+
+  for (p = (unsigned char *)string; *p != 0; ++p)
+    if (islower (*p))
+      *p = (unsigned char)_toupper (*p);
+  return string;
+}
Index: trunk/src/emx/src/lib/str/strxfrm.c
===================================================================
--- trunk/src/emx/src/lib/str/strxfrm.c	(revision 18)
+++ trunk/src/emx/src/lib/str/strxfrm.c	(revision 18)
@@ -0,0 +1,25 @@
+/* strxfrm.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <string.h>
+
+/* Ignore the current locale for now. */
+
+size_t strxfrm (char *string1, const char *string2, size_t count)
+{
+  size_t result;
+
+  result = 0;
+  while (*string2 != 0)
+    {
+      if (count != 0)
+        {
+          *string1++ = *string2;
+          --count;
+        }
+      ++result;
+      ++string2;
+    }
+  if (count != 0)
+    *string1 = 0;
+  return result;
+}
Index: trunk/src/emx/src/lib/sub.cmd
===================================================================
--- trunk/src/emx/src/lib/sub.cmd	(revision 18)
+++ trunk/src/emx/src/lib/sub.cmd	(revision 18)
@@ -0,0 +1,47 @@
+/* sub.cmd */
+
+parse arg prog
+'@echo off'
+call sub1 'alias'
+call sub1 'app'
+call sub1 'cdll'
+call sub1 'conv'
+call sub1 'ctype'
+call sub1 'dllnrt'
+call sub1 'dllrt'
+call sub1 'dllso'
+call sub1 'emx_386'
+call sub1 'emxload'
+call sub1 'end'
+call sub1 'gcc'
+call sub1 'graph'
+call sub1 'io'
+call sub1 'locale'
+call sub1 'malloc'
+call sub1 'malloc1'
+call sub1 'math'
+call sub1 'mbyte'
+call sub1 'misc'
+call sub1 'moddef'
+call sub1 'nls'
+call sub1 'omflib'
+call sub1 'os2_386'
+call sub1 'process'
+call sub1 'socket'
+call sub1 'static'
+call sub1 'startup'
+call sub1 'str'
+call sub1 'sys'
+call sub1 'termios'
+call sub1 'time'
+call sub1 'tmalloc'
+call sub1 'video'
+exit
+
+sub1:
+  parse arg dir
+  'cd '||dir
+  say dir
+  prog
+  'cd ..'
+  return
Index: trunk/src/emx/src/lib/sys/386/emx_ver.s
===================================================================
--- trunk/src/emx/src/lib/sys/386/emx_ver.s	(revision 18)
+++ trunk/src/emx/src/lib/sys/386/emx_ver.s	(revision 18)
@@ -0,0 +1,13 @@
+/ emx_ver.s (emx+gcc) -- Copyright (c) 1993-1998 by Eberhard Mattes
+
+        .globl  ___emx_version
+
+        .text
+
+        .align  2, 0x90
+
+___emx_version:
+        movl    $0x302e3964, %eax       /* version: 0.9d */
+        movl    $0x00000000, %ecx       /* revision: 0 */
+        movl    $0x00000220, %edx       /* flags: OS/2 and 387 */
+        ret
Index: trunk/src/emx/src/lib/sys/386/emxinit.s
===================================================================
--- trunk/src/emx/src/lib/sys/386/emxinit.s	(revision 18)
+++ trunk/src/emx/src/lib/sys/386/emxinit.s	(revision 18)
@@ -0,0 +1,24 @@
+/ sys/emxinit.s (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes
+
+        .globl  __emx_init
+        .globl  __emx_syscall
+        .globl  ___init_ret
+
+        .data
+
+L_ret:  .long   0
+
+        .text
+
+__emx_init:
+        popl    L_ret
+        call    ___init
+        add     $4, %esp
+        jmp     *L_ret
+
+___init_ret:
+        movl    4(%esp), %esp
+        jmp     *L_ret
+
+__emx_syscall:
+        jmp     __emx_syscall
Index: trunk/src/emx/src/lib/sys/386/systhrea.s
===================================================================
--- trunk/src/emx/src/lib/sys/386/systhrea.s	(revision 18)
+++ trunk/src/emx/src/lib/sys/386/systhrea.s	(revision 18)
@@ -0,0 +1,30 @@
+/ systhrea.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
+
+#if defined (__MT__)
+
+        .globl  __sys_thread
+
+        .text
+
+        .align  2, 0x90
+
+__sys_thread:
+        fs
+        movl    12, %eax                /* ptib2 */
+        movl    0(%eax), %edx           /* TID */
+        movl    __sys_thread_table(,%edx,4), %eax
+        testl   %eax, %eax
+        jz      1f
+        ret
+
+        .align  2, 0x90
+1:      pushl   %edx
+        pushl   $0                      /* errnop */
+        pushl   %edx                    /* tid */
+        call    ___sys_newthread
+        addl    $4, %esp
+        popl    %edx
+        movl    __sys_thread_table(,%edx,4), %eax
+        ret
+
+#endif
Index: trunk/src/emx/src/lib/sys/386/thunk0.asm
===================================================================
--- trunk/src/emx/src/lib/sys/386/thunk0.asm	(revision 18)
+++ trunk/src/emx/src/lib/sys/386/thunk0.asm	(revision 18)
@@ -0,0 +1,34 @@
+; thunk0.asm (emx+gcc) -- Copyright (c) 1992-1993 by Eberhard Mattes
+
+                .386
+
+                .MODEL  FLAT
+
+                PUBLIC  _emx_16to32
+                PUBLIC  _emx_32to16
+
+TEXT32          SEGMENT DWORD PUBLIC FLAT 'CODE'
+
+                EXTRN   DosFlatToSel:PROC
+                EXTRN   DosSelToFlat:PROC
+;
+;
+;
+                ALIGN  4
+_emx_32to16     PROC
+                MOV     EAX, [ESP+4]
+                JMP     DosFlatToSel
+_emx_32to16     ENDP
+
+;
+;
+;
+                ALIGN  4
+_emx_16to32     PROC
+                MOV     EAX, [ESP+4]
+                JMP     DosSelToFlat
+_emx_16to32     ENDP
+
+TEXT32          ENDS
+
+                END
Index: trunk/src/emx/src/lib/sys/386/thunk1.asm
===================================================================
--- trunk/src/emx/src/lib/sys/386/thunk1.asm	(revision 18)
+++ trunk/src/emx/src/lib/sys/386/thunk1.asm	(revision 18)
@@ -0,0 +1,168 @@
+; thunk1.asm (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes
+
+                .386
+
+                .MODEL  FLAT
+
+                PUBLIC  _emx_thunk1
+
+TEXT32          SEGMENT DWORD PUBLIC FLAT 'CODE'
+
+;
+; unsigned long _emx_thunk1 (void *args, void *fun)
+;
+; Call 16-bit code
+;
+; In:   ARGS    Pointer to argument list. The first DWORD contains the
+;               number of argument bytes, excluding that DWORD. The
+;               remaining values are packed appropriately for calling
+;               a 16-bit function. Pointers have been converted to
+;               sel:offset format
+;
+;       FUN     16:16 address of 16-bit function to be called. Both
+;               `pascal' and `cdecl' calling conventions are supported.
+;               The function must not change the DI register
+;
+; Out:  EAX     Return value (DX:AX) of 16-bit function
+;
+; Stack on entry (1):
+;
+;       ...
+;       FUN
+;       ARGS
+; ESP-> return address
+; ---------------------------------------------------------------------------
+;
+; Stack after setting up stack frame (2):
+;
+;       ...
+;       FUN
+;       ARGS
+;       return address
+; EBP-> caller's EBP
+;       caller's ESI
+;       caller's EDI
+;       caller's EBX
+;       caller's ES
+; ---------------------------------------------------------------------------
+;
+; Stack before jumping to 16-bit code (3):
+;
+;       ...
+;       FUN
+;       ARGS
+;       return address
+; EBP-> caller's EBP
+;       caller's ESI
+;       caller's EDI
+;       caller's EBX
+;       caller's ES
+;       padding                                 (0 to 1000H-4 bytes)
+; DI->  SS:ESP -> caller's EBP                  (2 DWORDs, DWORD-aligned)
+; SP->  arguments                               (WORD aligned)
+; ---------------------------------------------------------------------------
+;
+; Stack after return from 16-bit code (4):
+;
+;       ...
+;       FUN
+;       ARGS
+;       return address
+;       caller's EBP
+;       caller's ESI
+;       caller's EDI
+;       caller's EBX
+;       caller's ES
+;       padding                                 (0 to 1000H-4 bytes)
+; DI->  SS:ESP -> caller's EBP                  (2 DWORDs, DWORD-aligned)
+; SP->  arguments                               (for cdecl functions)
+; ---------------------------------------------------------------------------
+;
+                ALIGN  4
+ARGS            EQU     (DWORD PTR [EBP+2*4])
+FUN             EQU     (DWORD PTR [EBP+3*4])
+_emx_thunk1     PROC                            ; (1)
+                PUSH    EBP                     ; Set up stack frame
+                MOV     EBP, ESP
+                PUSH    ESI                     ; Save ESI
+                PUSH    EDI                     ; Save EDI
+                PUSH    EBX                     ; Save EBX
+                PUSH    ES                      ; (2) Save ES
+                MOV     DX, SS                  ; Prepare conversion of
+                AND     DL, 3                   ; ESP to SS:SP
+                OR      DL, 4                   ; LDT
+                MOV     EAX, ESP                ; Check stack
+                CMP     AX, 1000H               ; 1000H bytes left in this 64K
+                JAE     SHORT THUNK1_1          ; segment? Yes => skip
+                XOR     AX, AX                  ; Move ESP down to next 64K seg
+                MOV     BYTE PTR [EAX], 0       ; Stack probe
+                XCHG    ESP, EAX                ; Set new ESP, EAX := old ESP
+THUNK1_1:       PUSH    SS                      ; Save original SS:ESP on
+                PUSH    EAX                     ; stack (points to saved EBX)
+;
+; Copy arguments
+;
+                MOV     ESI, ARGS
+                LODSD
+                MOV     ECX, EAX
+                SUB     ESP, ECX
+                MOV     EDI, ESP
+                SHR     ECX, 2
+                REP     MOVSD
+                MOV     ECX, EAX
+                AND     ECX, 03H
+                REP     MOVSB                   ; EDI now points to SS:ESP
+                LEA     ESI, FUN
+;
+; Convert ESP to SS:SP
+;
+                MOV     EAX, ESP
+                ROL     EAX, 16
+                SHL     AX, 3
+                OR      AL, DL
+                PUSH    EAX                     ; Push new SS
+                SHR     EAX, 16
+                PUSH    EAX                     ; Push new ESP
+                LSS     ESP, [ESP]              ; Switch to new SS:SP
+                JMP     FAR PTR TEXT16:THUNK16_CALL ; (3)
+;
+; Jump to 16-bit code
+;
+                RETF
+
+                ALIGN  4
+THUNK1_RET::    MOVZX   ESP, DI                 ; (4) Remove arguments
+                LSS     ESP, [ESP]              ; Get 32-bit stack pointer
+                POP     ES                      ; Restore ES
+                POP     EBX                     ; Restore EBX
+                POP     EDI                     ; Restore EDI
+                POP     ESI                     ; Restore ESI
+                POP     EBP                     ; Restore EBP
+                MOVZX   EAX, AX                 ; Compute return value
+                MOVZX   EDX, DX
+                SHL     EDX, 16
+                OR      EAX, EDX
+                RET                             ; Return to 32-bit code
+
+_emx_thunk1     ENDP
+
+TEXT32          ENDS
+
+;
+;
+;
+
+TEXT16          SEGMENT DWORD PUBLIC USE16 'CODE'
+
+;
+; Call 16-bit function
+;
+; In:    ESI    Points to 16:16 function address
+;
+                ALIGN  4
+THUNK16_CALL:   CALL    DWORD PTR [ESI]
+                JMP     FAR PTR FLAT:THUNK1_RET
+
+TEXT16          ENDS
+
+                END
Index: trunk/src/emx/src/lib/sys/386/unwind.s
===================================================================
--- trunk/src/emx/src/lib/sys/386/unwind.s	(revision 18)
+++ trunk/src/emx/src/lib/sys/386/unwind.s	(revision 18)
@@ -0,0 +1,14 @@
+/ sys/unwind.s (emx+gcc) -- Copyright (c) 1992-1994 by Eberhard Mattes */
+
+        .globl  ___unwind2
+
+/ void __unwind2 (void *xcpt_reg_ptr)
+
+___unwind2:
+        movl    1*4(%esp), %eax         /* xcpt_reg_ptr */
+        pushl   $0
+        pushl   $L_cont
+        pushl   %eax
+        call    _DosUnwindException
+L_cont: addl    $3*4, %esp
+        ret
Index: trunk/src/emx/src/lib/sys/__chdir.c
===================================================================
--- trunk/src/emx/src/lib/sys/__chdir.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__chdir.c	(revision 18)
@@ -0,0 +1,19 @@
+/* sys/chdir.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+
+int __chdir (const char *name)
+{
+  ULONG rc;
+
+  rc = DosSetCurrentDir (name);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__chmod.c
===================================================================
--- trunk/src/emx/src/lib/sys/__chmod.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__chmod.c	(revision 18)
@@ -0,0 +1,41 @@
+/* sys/chmod.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <errno.h>
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __chmod (const char *name, int flag, int attr)
+{
+  ULONG rc;
+  FILESTATUS3 info;
+
+  if (flag < 0 || flag > 1)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if ((name[0] == '/' || name[0] == '\\') && strlen (name) >= 6 &&
+      memicmp (name+1, "pipe", 4) == 0 && (name[5] == '/' || name[5] == '\\'))
+    {
+      errno = ENOENT;
+      return -1;
+    }
+  rc = DosQueryPathInfo (name, FIL_STANDARD, &info, sizeof (info));
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  if (flag == 0)
+    return info.attrFile;
+  info.attrFile = attr;
+  rc = DosSetPathInfo (name, FIL_STANDARD, &info, sizeof (info), 0);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__chsize.c
===================================================================
--- trunk/src/emx/src/lib/sys/__chsize.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__chsize.c	(revision 18)
@@ -0,0 +1,18 @@
+/* sys/chsize.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __chsize (int handle, long length)
+{
+  ULONG rc;
+
+  rc = DosSetFileSize (handle, length);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__close.c
===================================================================
--- trunk/src/emx/src/lib/sys/__close.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__close.c	(revision 18)
@@ -0,0 +1,19 @@
+/* sys/close.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __close (int handle)
+{
+  ULONG rc;
+
+  rc = DosClose (handle);
+  if (rc == 0)
+    return 0;
+  else
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/sys/__dup.c
===================================================================
--- trunk/src/emx/src/lib/sys/__dup.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__dup.c	(revision 18)
@@ -0,0 +1,20 @@
+/* sys/dup.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __dup (int handle)
+{
+  ULONG rc;
+  HFILE new;
+
+  new = 0xffffffff;
+  rc = DosDupHandle (handle, &new);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return new;
+}
Index: trunk/src/emx/src/lib/sys/__dup2.c
===================================================================
--- trunk/src/emx/src/lib/sys/__dup2.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__dup2.c	(revision 18)
@@ -0,0 +1,23 @@
+/* sys/dup2.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __dup2 (int handle1, int handle2)
+{
+  ULONG rc, state;
+  HFILE new;
+
+  new = handle2;
+  if (handle1 == handle2)
+    rc = DosQueryFHState (handle1, &state); /* Check HANDLE */
+  else
+    rc = DosDupHandle (handle1, &new);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return new;
+}
Index: trunk/src/emx/src/lib/sys/__endthread.c
===================================================================
--- trunk/src/emx/src/lib/sys/__endthread.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__endthread.c	(revision 18)
@@ -0,0 +1,25 @@
+/* sys/endthrea.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#if defined (__MT__)
+
+#define INCL_DOS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __endthread (int tid)
+{
+  thread_data *tp;
+
+  if (tid < MAX_THREADS && _sys_thread_table[tid] != NULL)
+    {
+      tp = _sys_thread_table[tid];
+      if (tp->fd.find_handle != HDIR_CREATE)
+        DosFindClose (tp->fd.find_handle);
+      DosSubFreeMem (_sys_private_heap, tp, sizeof (thread_data));
+      _sys_thread_table[tid] = NULL;
+    }
+  return 0;
+}
+
+#endif
Index: trunk/src/emx/src/lib/sys/__exit.c
===================================================================
--- trunk/src/emx/src/lib/sys/__exit.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__exit.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sys/exit.c (emx+gcc) -- Copyright (c) 1992-1993 by Eberhard Mattes */
+
+#include <os2emx.h>
+
+void __exit (int rc)
+{
+  while (1)
+    DosExit (EXIT_PROCESS, rc);
+}
Index: trunk/src/emx/src/lib/sys/__fcntl.c
===================================================================
--- trunk/src/emx/src/lib/sys/__fcntl.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__fcntl.c	(revision 18)
@@ -0,0 +1,52 @@
+/* sys/fcntl.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __fcntl (int handle, int request, int arg)
+{
+  ULONG rc;
+  ULONG state, new_state;
+
+  switch (request)
+    {
+    case F_SETFL:
+      return 0;
+    case F_GETFD:
+      rc = DosQueryFHState (handle, &state);
+      if (rc != 0)
+        {
+          _sys_set_errno (rc);
+          return -1;
+        }
+      return ((state & OPEN_FLAGS_NOINHERIT) ? 1 : 0);
+    case F_SETFD:
+      rc = DosQueryFHState (handle, &state);
+      if (rc != 0)
+        {
+          _sys_set_errno (rc);
+          return -1;
+        }
+      if (arg & 1)
+        new_state = state | OPEN_FLAGS_NOINHERIT;
+      else
+        new_state = state & ~OPEN_FLAGS_NOINHERIT;
+      if (new_state != state)
+        {
+          new_state &= 0x7f88;
+          rc = DosSetFHState (handle, new_state);
+          if (rc != 0)
+            {
+              _sys_set_errno (rc);
+              return -1;
+            }
+        }
+      return 0;
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/sys/__fstat.c
===================================================================
--- trunk/src/emx/src/lib/sys/__fstat.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__fstat.c	(revision 18)
@@ -0,0 +1,85 @@
+/* sys/fstat.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __fstat (int handle, struct stat *buf)
+{
+  ULONG rc;
+  ULONG htype, hflags;
+  FILESTATUS3 info;
+
+  memset (buf, 0, sizeof (*buf));
+  rc = DosQueryHType (handle, &htype, &hflags);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  switch (htype & 0xff)
+    {
+    case 1:
+      buf->st_mode = S_IFCHR;
+      break;
+    case 2:
+      buf->st_mode = S_IFSOCK;
+      break;
+    default:
+      buf->st_mode = S_IFREG;
+      break;
+    }
+  if (buf->st_mode == S_IFREG)
+    {
+      rc = DosQueryFileInfo (handle, FIL_STANDARD, &info, sizeof (info));
+      if (rc != 0)
+        {
+          _sys_set_errno (rc);
+          return -1;
+        }
+      buf->st_attr = info.attrFile;
+      buf->st_size = info.cbFile;
+      buf->st_reserved = 0;
+      buf->st_mtime = _sys_p2t (info.ftimeLastWrite, info.fdateLastWrite);
+      if (FTIMEZEROP (info.ftimeCreation) &&
+          FDATEZEROP (info.fdateCreation))
+        buf->st_ctime = buf->st_mtime;
+      else
+        buf->st_ctime = _sys_p2t (info.ftimeCreation, info.fdateCreation);
+      if (FTIMEZEROP (info.ftimeLastAccess) &&
+          FDATEZEROP (info.fdateLastAccess))
+        buf->st_atime = buf->st_mtime;
+      else
+        buf->st_atime = _sys_p2t (info.ftimeLastAccess, info.fdateLastAccess);
+      if (info.attrFile & 1)
+        buf->st_mode |= (S_IREAD >> 6) * 0111;
+      else
+        buf->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
+    }
+  else
+    {
+      buf->st_size = 0;
+      rc = DosQueryFHState (handle, &hflags);
+      if (rc != 0)
+        {
+          _sys_set_errno (rc);
+          return -1;
+        }
+      if ((hflags & 7) == 0)
+        buf->st_mode |= (S_IREAD >> 6) * 0111;
+      else
+        buf->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
+    }
+  buf->st_uid = 0;
+  buf->st_gid = 0;
+  buf->st_ino = _sys_ino++;
+  if (_sys_ino == 0)
+    _sys_ino = 1;
+  buf->st_dev = 0;
+  buf->st_rdev = 0;
+  buf->st_nlink = 1;
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__ftime.c
===================================================================
--- trunk/src/emx/src/lib/sys/__ftime.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__ftime.c	(revision 18)
@@ -0,0 +1,27 @@
+/* sys/ftime.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <sys/timeb.h>
+#include <time.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+void __ftime (struct timeb *ptr)
+{
+  DATETIME now;
+  struct tm tm;
+
+  DosGetDateTime (&now);
+  tm.tm_sec = now.seconds;
+  tm.tm_min = now.minutes;
+  tm.tm_hour = now.hours;
+  tm.tm_mday = now.day;
+  tm.tm_mon = now.month - 1;
+  tm.tm_year = now.year - 1900;
+  tm.tm_isdst = -1;             /* unknown */
+  ptr->time = (time_t)_mktime (&tm);
+  ptr->millitm = now.hundredths * 10;
+  ptr->timezone = now.timezone;
+  ptr->dstflag = 0;
+}
Index: trunk/src/emx/src/lib/sys/__ftruncate.c
===================================================================
--- trunk/src/emx/src/lib/sys/__ftruncate.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__ftruncate.c	(revision 18)
@@ -0,0 +1,28 @@
+/* sys/ftruncat.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __ftruncate (int handle, long length)
+{
+  ULONG rc;
+  FILESTATUS3 info;
+
+  rc = DosQueryFileInfo (handle, FIL_STANDARD, &info, sizeof (info));
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  if (info.cbFile > length)
+    {
+      rc = DosSetFileSize (handle, length);
+      if (rc != 0)
+        {
+          _sys_set_errno (rc);
+          return -1;
+        }
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__getcwd.c
===================================================================
--- trunk/src/emx/src/lib/sys/__getcwd.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__getcwd.c	(revision 18)
@@ -0,0 +1,22 @@
+/* sys/getcwd.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __getcwd (char *buffer, char drive)
+{
+  ULONG rc;
+  ULONG size;
+
+  if (drive != 0)
+    drive -= 'A' - 1;
+  size =512;
+  rc = DosQueryCurrentDir (drive, buffer, &size);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__getdrive.c
===================================================================
--- trunk/src/emx/src/lib/sys/__getdrive.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__getdrive.c	(revision 18)
@@ -0,0 +1,21 @@
+/* sys/getdrive.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+char __getdrive (void)
+{
+  ULONG rc;
+  ULONG drive, map;
+
+  rc = DosQueryCurrentDisk (&drive, &map);
+  if (rc == 0)
+    return drive - 1 + 'A';
+  else
+    {
+      _sys_set_errno (rc);
+      return 0;
+    }
+}
+
Index: trunk/src/emx/src/lib/sys/__imphandle.c
===================================================================
--- trunk/src/emx/src/lib/sys/__imphandle.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__imphandle.c	(revision 18)
@@ -0,0 +1,8 @@
+/* imphandl.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int __imphandle (int handle)
+{
+  return handle;
+}
Index: trunk/src/emx/src/lib/sys/__init.c
===================================================================
--- trunk/src/emx/src/lib/sys/__init.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__init.c	(revision 18)
@@ -0,0 +1,507 @@
+/* sys/init.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOS
+#include <os2emx.h>
+#include <string.h>
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <emx/startup.h>
+#include <emx/syscalls.h>
+
+#define SYS_PRIVATE_HEAP_SIZE 0x100000
+
+#define EXTERN
+#define INIT(x) = x
+
+#include "syscalls.h"
+
+static int arg_size;
+static int argc;
+static int envc;
+static char **vec;
+static char *pool;
+
+extern void volatile __init_ret (void *stack);
+static void parse_args (const char *src);
+static void parse_env (char *src);
+
+#define PUTC(c) BEGIN ++arg_size; if (pool != NULL) *pool++ = (c); END
+#define PUTV    BEGIN ++argc; if (vec != NULL) *vec++ = pool; END
+
+#define WHITE(c) ((c) == ' ' || (c) == '\t')
+
+static void parse_args (const char *src)
+{
+  int bs, quote;
+  char *flag_ptr;
+
+  argc = 0; arg_size = 0;
+  /* argv[0] */
+  PUTC (_ARG_NONZERO);
+  PUTV;
+  for (;;)
+    {
+      PUTC (*src);
+      if (*src == 0)
+        break;
+      ++src;
+    }
+  ++src;
+  for (;;)
+    {
+      while (WHITE (*src))
+        ++src;
+      if (*src == 0)
+        break;
+      flag_ptr = pool;
+      PUTC (_ARG_NONZERO);
+      PUTV;
+      bs = 0; quote = 0;
+      for (;;)
+        {
+          if (*src == '"')
+            {
+              while (bs >= 2)
+                {
+                  PUTC ('\\');
+                  bs -= 2;
+                }
+              if (bs & 1)
+                PUTC ('"');
+              else
+                {
+                  quote = !quote;
+                  if (flag_ptr != NULL)
+                    *flag_ptr |= _ARG_DQUOTE;
+                }
+              bs = 0;
+            }
+          else if (*src == '\\')
+            ++bs;
+          else
+            {
+              while (bs != 0)
+                {
+                  PUTC ('\\');
+                  --bs;
+                }
+              if (*src == 0 || (WHITE (*src) && !quote))
+                break;
+              PUTC (*src);
+            }
+          ++src;
+        }
+      PUTC (0);
+    }
+}
+
+
+static void parse_env (char *src)
+{
+  envc = 0;
+  while (*src != 0)
+    {
+      ++envc;
+      if (vec != NULL)
+        *vec++ = src;
+      while (*src != 0)
+        ++src;
+      ++src;
+    }
+}
+
+
+struct layout
+{
+  ULONG text_base;
+  ULONG text_end;
+  ULONG data_base;
+  ULONG data_end;
+  ULONG bss_base;
+  ULONG bss_end;
+  ULONG heap_base;
+  ULONG heap_end;
+  ULONG heap_brk;
+  ULONG heap_off;
+  ULONG os2_dll;
+  ULONG stack_base;
+  ULONG stack_end;
+  ULONG flags;
+  ULONG reserved[2];
+  UCHAR options[64];
+};
+
+
+void __init (struct layout *layout)
+{
+  ULONG rc;
+  PTIB ptib;
+  PPIB ppib;
+  void *stack;
+  int n;
+  ULONG times;
+  static char init_level;
+
+  /* In a custom C runtime DLL, this function is called at least
+     twice, once from the startup code of this DLL, once from the
+     startup code of the application, and once from each DLL using
+     this DLL.  init_level indicates which initializations have been
+     performed.  Initially init_level is 0, meaning no initializations
+     have been done.  init_level 1 indicates that initializations
+     common to DLLs and applications have been performed.  init_level
+     2 indicates that initializations specific to applications have
+     been done as well as initializations of init_level 1. */
+
+  if (init_level == 0)
+    {
+      init_level = 1;
+
+      /* Initialize the heap.  Here, we only create the semaphore
+         (while having only one thread).  The heap will be created by
+         __sbrk(). */
+
+#if defined (__MT__)
+      if (_fmutex_create (&_sys_heap_fmutex, 0) != 0)
+        DosExit (EXIT_PROCESS, 255);
+#endif
+
+      /* Get the process ID and parent process ID.  This is also
+         required for (stand-alone) DLLs.  At least, we need ptib and
+         ppib. */
+
+      rc = DosGetInfoBlocks (&ptib, &ppib);
+      if (rc != 0)
+        DosExit (EXIT_PROCESS, 255);
+      _sys_pid = ppib->pib_ulpid;
+      _sys_ppid = ppib->pib_ulppid;
+
+      /* Initialize threads.  This is also required for (stand-alone)
+         DLLs as these may call _beginthread(). */
+#if defined (__MT__)
+      rc = DosAllocMem (&_sys_private_heap, SYS_PRIVATE_HEAP_SIZE,
+                        PAG_READ | PAG_WRITE);
+      if (rc != 0)
+        DosExit (EXIT_PROCESS, 255);
+      rc = DosSubSetMem (_sys_private_heap,
+                         DOSSUB_INIT | DOSSUB_SPARSE_OBJ | DOSSUB_SERIALIZE,
+                         SYS_PRIVATE_HEAP_SIZE);
+      if (rc != 0)
+        DosExit (EXIT_PROCESS, 255);
+      for (n = 0; n < MAX_THREADS; ++n)
+        _sys_thread_table[n] = NULL;
+      __newthread (ptib->tib_ptib2->tib2_ultid);
+#else
+      _sys_init_thread (&_sys_thread_one);
+#endif
+
+      /* Get current time for clock().  We do this also for
+         (stand-alone) DLLs. */
+
+      _sys_get_clock (&_sys_clock0_ms);
+    }
+
+  /* Stop here if called from the startup code of a DLL.  The
+     remaining code is used only if this function has been called from
+     the startup code of an application. */
+
+  if (layout->flags & 1)
+    return;
+
+  /* Avoid performing the following initializations more than once. */
+
+  if (init_level == 2)
+    return;
+  init_level = 2;
+
+  /* Get ptib and ppib again, in case __init() has already been called
+     for a DLL. */
+
+  rc = DosGetInfoBlocks (&ptib, &ppib);
+  if (rc != 0)
+    DosExit (EXIT_PROCESS, 255);
+
+  /* Copy command line arguments and environment. */
+
+  vec = NULL; pool = NULL;
+  parse_env (ppib->pib_pchenv);
+  parse_args (ppib->pib_pchcmd);
+  n = arg_size + (argc+1+envc+1) * sizeof (char *);
+  if (n & 3)
+    n = (n | 3) + 1;            /* alignment for EXCEPTIONREGISTRATIONRECORD */
+  stack = alloca (n + sizeof (EXCEPTIONREGISTRATIONRECORD));
+  _sys_xreg = stack + n;
+  vec = stack;
+  pool = (char *)(vec + argc+1+envc+1);
+  parse_env (ppib->pib_pchenv);
+  *vec++ = NULL;               /* empty environment */
+  parse_args (ppib->pib_pchcmd);
+  *vec++ = NULL;
+
+  /* Initialize exception handling. */
+
+  _sys_xreg->prev_structure = (void *)0xffffffff;
+  _sys_xreg->ExceptionHandler = _sys_exception;
+  rc = DosSetExceptionHandler (_sys_xreg);
+  if (rc != 0)
+    DosExit (EXIT_PROCESS, 255);
+  /* DosSetSignalExceptionFocus fails for PM programs, error code 303 */
+  DosSetSignalExceptionFocus (SIG_SETFOCUS, &times);
+
+  /* Return to the program. */
+
+  __init_ret (stack);
+}
+
+
+char const _sys_sig_valid[NSIG] =
+{
+  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1
+};
+
+struct sig_descr const sig_info[NSIG] =
+{
+  {"SIG0",     ST_TERM,   ST_TERM},
+  {"SIGHUP",   ST_TERM,   ST_IGNORE},
+  {"SIGINT",   ST_TERM,   ST_IGNORE},
+  {"SIGQUIT",  ST_TERM,   ST_IGNORE},
+  {"SIGILL",   ST_NEXT,   ST_NEXT},
+  {"SIGTRAP",  ST_NEXT,   ST_NEXT},
+  {"SIGABRT",  ST_TERM,   ST_TERM},
+  {"SIGEMT",   ST_TERM,   ST_TERM},
+  {"SIGFPE",   ST_NEXT,   ST_NEXT},
+  {"SIGKILL",  ST_TERM,   ST_TERM},
+  {"SIGBUS",   ST_TERM,   ST_TERM},
+  {"SIGSEGV",  ST_NEXT,   ST_NEXT},
+  {"SIGSYS",   ST_TERM,   ST_TERM},
+  {"SIGPIPE",  ST_TERM,   ST_IGNORE},
+  {"SIGALRM",  ST_TERM,   ST_IGNORE},
+  {"SIGTERM",  ST_NEXT,   ST_IGNORE},
+  {"SIGUSR1",  ST_IGNORE, ST_IGNORE},
+  {"SIGUSR2",  ST_IGNORE, ST_IGNORE},
+  {"SIGCLD",   ST_IGNORE, ST_IGNORE},
+  {"SIG19",    ST_TERM,   ST_TERM},
+  {"SIG20",    ST_TERM,   ST_TERM},
+  {"SIGBREAK", ST_TERM,   ST_IGNORE}
+};
+
+
+static void say (const char *msg)
+{
+  __write (2, msg, strlen (msg));
+};
+
+
+static void _sys_terminate (int signo)
+{
+  if (signo == SIGABRT)
+    say ("\r\nAbnormal program termination\r\n");
+  else
+    {
+      say ("\r\nProcess terminated by ");
+      say (sig_info[signo].name);
+      say ("\r\n");
+    }
+  while (1)
+    DosExit (EXIT_PROCESS, 3);
+}
+
+
+static void _sys_signal_acknowledge (int signo)
+{
+  switch (signo)
+    {
+    case SIGINT:
+      DosAcknowledgeSignalException (XCPT_SIGNAL_INTR);
+      break;
+    case SIGTERM:
+      DosAcknowledgeSignalException (XCPT_SIGNAL_KILLPROC);
+      break;
+    case SIGBREAK:
+      DosAcknowledgeSignalException (XCPT_SIGNAL_BREAK);
+      break;
+    }
+}
+
+
+/* Called from OS/2 exception handler for signal exceptions. */
+
+static ULONG _sys_signal (int signo)
+{
+  thread_data *tp;
+
+  tp = SYS_THREAD;
+  if (tp == NULL)
+    return XCPT_CONTINUE_SEARCH;
+  __sigaddset (&tp->sig_pending, signo);
+  _sys_signal_acknowledge (signo);
+  _sys_deliver_pending_signals (tp);
+  switch (sig_info[signo].fun_action)
+    {
+    case ST_TERM:
+      _sys_terminate (signo);
+    case ST_NEXT:
+      return XCPT_CONTINUE_SEARCH;
+    case ST_IGNORE:
+      return XCPT_CONTINUE_EXECUTION;
+    }
+  return XCPT_CONTINUE_SEARCH;  /* Keep the optimizer happy */
+}
+
+
+/* Called from OS/2 exception handler for traps. */
+
+static ULONG _sys_trap (int signo)
+{
+  thread_data *tp;
+  void (*handler)(int signo);
+
+  tp = SYS_THREAD;
+  if (tp == NULL)
+    return XCPT_CONTINUE_SEARCH;
+  handler = tp->signals[signo].sa_handler;
+  if (handler != SIG_IGN && handler != SIG_DFL)
+    handler (signo);
+  switch (sig_info[signo].fun_action)
+    {
+    case ST_TERM:
+      _sys_terminate (signo);
+    case ST_NEXT:
+      return XCPT_CONTINUE_SEARCH;
+    case ST_IGNORE:
+      return XCPT_CONTINUE_EXECUTION;
+    }
+  return XCPT_CONTINUE_SEARCH;  /* Keep the optimizer happy */
+}
+
+
+static void _sys_deliver_signal (thread_data *tp, int signo)
+{
+  struct sigaction *p;
+  void (*handler)(int signo);
+  sigset_t mask, old_blocked;
+
+  /* TODO: Critical section */
+
+  mask = _SIGMASK (signo);
+  p = &tp->signals[signo];
+
+  tp->sig_pending &= ~mask;
+  handler = p->sa_handler;
+
+  if (handler == SIG_IGN)
+    {
+      /* Ignore the signal. */
+    }
+  else if (handler == SIG_DFL)
+    {
+      if (sig_info[signo].dfl_action != ST_IGNORE)
+        _sys_terminate (signo);
+    }
+  else
+    {
+      if (p->sa_flags & SA_SYSV)
+        {
+          p->sa_handler = SIG_DFL;
+          handler (signo);
+        }
+      else if (p->sa_flags & SA_ACK)
+        {
+          tp->sig_blocked |= mask;
+          handler (signo);
+        }
+      else
+        {
+          old_blocked = tp->sig_blocked;
+          SET_BLOCKED (tp, tp->sig_blocked | mask | p->sa_mask);
+          handler (signo);
+          tp->sig_blocked = old_blocked;
+        }
+    }
+}
+
+
+void _sys_deliver_pending_signals (thread_data *tp)
+{
+  int signo;
+
+  /* TODO: Critical section */
+  while ((tp->sig_pending & ~tp->sig_blocked) != 0)
+    {
+      for (signo = 1; signo < NSIG; ++signo)
+        if (tp->sig_pending & ~tp->sig_blocked & _SIGMASK (signo))
+          _sys_deliver_signal (tp, signo);
+    }
+}
+
+
+ULONG _sys_exception (PEXCEPTIONREPORTRECORD report,
+                      PEXCEPTIONREGISTRATIONRECORD registration,
+                      PCONTEXTRECORD context,
+                      PVOID whatever)
+{
+  __asm__ ("cld");              /* Don't trust */
+  if (report->fHandlerFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
+    return XCPT_CONTINUE_SEARCH;
+  switch (report->ExceptionNum)
+    {
+    case XCPT_SIGNAL:
+      if (report->cParameters >= 1)
+        {
+          if (report->ExceptionInfo[0] == XCPT_SIGNAL_INTR)
+            return _sys_signal (SIGINT);
+          else if (report->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC)
+            return _sys_signal (SIGTERM);
+          else if (report->ExceptionInfo[0] == XCPT_SIGNAL_BREAK)
+            return _sys_signal (SIGBREAK);
+        }
+      break;
+    case XCPT_ACCESS_VIOLATION:
+    case XCPT_DATATYPE_MISALIGNMENT:
+      return _sys_trap (SIGSEGV);
+
+    case XCPT_INTEGER_DIVIDE_BY_ZERO:
+    case XCPT_INTEGER_OVERFLOW:
+    case XCPT_ARRAY_BOUNDS_EXCEEDED:
+    case XCPT_FLOAT_DENORMAL_OPERAND:
+    case XCPT_FLOAT_DIVIDE_BY_ZERO:
+    case XCPT_FLOAT_INEXACT_RESULT:
+    case XCPT_FLOAT_INVALID_OPERATION:
+    case XCPT_FLOAT_OVERFLOW:
+    case XCPT_FLOAT_STACK_CHECK:
+    case XCPT_FLOAT_UNDERFLOW:
+      return _sys_trap (SIGFPE);
+
+    case XCPT_ILLEGAL_INSTRUCTION:
+    case XCPT_INVALID_LOCK_SEQUENCE:
+    case XCPT_PRIVILEGED_INSTRUCTION:
+      return _sys_trap (SIGILL);
+    }
+  return XCPT_CONTINUE_SEARCH;
+}
+
+
+void _sys_get_clock (unsigned long *ms)
+{
+  ULONG val_ms;
+
+  DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &val_ms, sizeof (val_ms));
+  *ms = val_ms;
+}
+
+
+void _sys_init_thread (thread_data *tp)
+{
+  int n;
+
+  __sigemptyset (&tp->sig_blocked);
+  __sigemptyset (&tp->sig_pending);
+  for (n = 0; n < NSIG; ++n)
+    {
+      tp->signals[n].sa_handler = SIG_DFL;
+      tp->signals[n].sa_flags   = SA_ACK;
+      __sigemptyset (&tp->signals[n].sa_mask);
+    }
+  tp->fd.find_handle = HDIR_CREATE;
+  tp->fd.find_next = NULL;
+  tp->fd.find_count = 0;
+}
Index: trunk/src/emx/src/lib/sys/__initthread.c
===================================================================
--- trunk/src/emx/src/lib/sys/__initthread.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__initthread.c	(revision 18)
@@ -0,0 +1,19 @@
+/* sys/initthre.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#if defined (__MT__)
+
+#include <errno.h>
+#define INCL_DOS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __initthread (void *preg)
+{
+  ((PEXCEPTIONREGISTRATIONRECORD)preg)->prev_structure = NULL;
+  ((PEXCEPTIONREGISTRATIONRECORD)preg)->ExceptionHandler = _sys_exception;
+  DosSetExceptionHandler (preg);
+  return 0;
+}
+
+#endif
Index: trunk/src/emx/src/lib/sys/__ioctl1.c
===================================================================
--- trunk/src/emx/src/lib/sys/__ioctl1.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__ioctl1.c	(revision 18)
@@ -0,0 +1,28 @@
+/* sys/ioctl1.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <errno.h>
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+
+int __ioctl1 (int handle, int code)
+{
+  ULONG rc;
+  ULONG htype, hflags;
+
+  if (code != 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  rc = DosQueryHType (handle, &htype, &hflags);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  if ((htype & 0xff) == 0)
+    return 0;
+  return (hflags & 0x0f) | 0x80;
+}
Index: trunk/src/emx/src/lib/sys/__ioctl2.c
===================================================================
--- trunk/src/emx/src/lib/sys/__ioctl2.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__ioctl2.c	(revision 18)
@@ -0,0 +1,59 @@
+/* sys/ioctl2.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <sys/ioctl.h>
+#include <errno.h>
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __ioctl2 (int handle, int request, int arg)
+{
+  ULONG rc;
+  ULONG type, flags;
+  int *int_ptr;
+
+  switch (request)
+    {
+    case FGETHTYPE:
+      int_ptr = (int *)arg;
+      rc = DosQueryHType (handle, &type, &flags);
+      if (rc != 0)
+        {
+          _sys_set_errno (rc);
+          return -1;
+        }
+      switch (type & 0xff)
+        {
+        case 0:                 /* File */
+          *int_ptr = HT_FILE;
+          break;
+        case 1:                 /* Character device */
+          if (flags & 3)
+            *int_ptr = HT_DEV_CON;
+          else if (flags & 4)
+            *int_ptr = HT_DEV_NUL;
+          else if (flags & 8)
+            *int_ptr = HT_DEV_CLK;
+          else
+            *int_ptr = HT_DEV_OTHER;
+          break;
+        case 2:                 /* Pipe */
+          rc = DosQueryNPHState (handle, &flags);
+          if (rc == 0 || rc == ERROR_PIPE_NOT_CONNECTED)
+            *int_ptr = HT_NPIPE;
+          else
+            *int_ptr = HT_UPIPE;
+          break;
+        default:
+          errno = EINVAL;
+          return -1;
+        }
+      return 0;
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+
+}
Index: trunk/src/emx/src/lib/sys/__lseek.c
===================================================================
--- trunk/src/emx/src/lib/sys/__lseek.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__lseek.c	(revision 18)
@@ -0,0 +1,20 @@
+/* sys/lseek.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __lseek (int handle, long offset, int origin)
+{
+  ULONG rc;
+  ULONG new;
+
+  rc = DosSetFilePtr (handle, offset, origin, &new);
+  if (rc == 0)
+    return (int)new;
+  else
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/sys/__memaccess.c
===================================================================
--- trunk/src/emx/src/lib/sys/__memaccess.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__memaccess.c	(revision 18)
@@ -0,0 +1,11 @@
+/* sys/memacces.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+void *__memaccess (unsigned first, unsigned last, int flag)
+{
+  errno = EACCES;
+  return NULL;
+}
Index: trunk/src/emx/src/lib/sys/__memavail.c
===================================================================
--- trunk/src/emx/src/lib/sys/__memavail.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__memavail.c	(revision 18)
@@ -0,0 +1,8 @@
+/* sys/memavail.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int __memavail (void)
+{
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__mkdir.c
===================================================================
--- trunk/src/emx/src/lib/sys/__mkdir.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__mkdir.c	(revision 18)
@@ -0,0 +1,19 @@
+/* sys/mkdir.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+
+int __mkdir (const char *name)
+{
+  ULONG rc;
+
+  rc = DosCreateDir (name, NULL);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__newthread.c
===================================================================
--- trunk/src/emx/src/lib/sys/__newthread.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__newthread.c	(revision 18)
@@ -0,0 +1,41 @@
+/* sys/newthrea.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#if defined (__MT__)
+
+#include <errno.h>
+#define INCL_DOS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+/* Also used by 386/systhrea.s */
+
+int __sys_newthread (int tid, int *errnop)
+{
+  ULONG rc;
+  void *data;
+
+  if (tid >= MAX_THREADS)
+    {
+      if (errnop != NULL)
+        *errnop = EAGAIN;
+      return -1;
+    }
+  rc = DosSubAllocMem (_sys_private_heap, &data, sizeof (thread_data));
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  _sys_thread_table[tid] = data;
+  _sys_init_thread (data);
+  return 0;
+}
+
+
+int __newthread (int tid)
+{
+  return __sys_newthread (tid, &errno);
+}
+
+#endif
Index: trunk/src/emx/src/lib/sys/__nls_ctype.c
===================================================================
--- trunk/src/emx/src/lib/sys/__nls_ctype.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__nls_ctype.c	(revision 18)
@@ -0,0 +1,42 @@
+/* sys/nls_ctyp.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#define INCL_DOSNLS
+#include <os2emx.h>
+#include <sys/nls.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __nls_ctype (unsigned char *buf)
+{
+  ULONG rc;
+  COUNTRYCODE cc;
+  BYTE lead[12];
+  unsigned i, j;
+
+  /* Get DBCS lead bytes. */
+
+  cc.country = 0;
+  cc.codepage = 0;
+  rc = DosQueryDBCSEnv (sizeof (lead), &cc, (PCHAR)lead);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+
+  /* Clear _NLS_DBCS_LEAD for all bytes. */
+
+  for (j = 0; j < 256; ++j)
+    buf[j] &= ~_NLS_DBCS_LEAD;
+
+  /* Set _NLS_DBCS_LEAD for DBCS lead bytes. */
+
+  for (i = 0; i <= sizeof (lead) - 2; i += 2)
+    {
+      if (lead[i+0] == 0 && lead[i+1] == 0)
+        break;
+      for (j = lead[i+0]; j <= lead[i+1]; ++j)
+        buf[j] |= _NLS_DBCS_LEAD;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__nls_memupr.c
===================================================================
--- trunk/src/emx/src/lib/sys/__nls_memupr.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__nls_memupr.c	(revision 18)
@@ -0,0 +1,15 @@
+/* sys/nls_memu.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOSNLS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+void __nls_memupr (unsigned char *buf, size_t size)
+{
+  COUNTRYCODE cc;
+
+  cc.country = 0;
+  cc.codepage = 0;
+  DosMapCase (size, &cc, buf);
+}
Index: trunk/src/emx/src/lib/sys/__open.c
===================================================================
--- trunk/src/emx/src/lib/sys/__open.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__open.c	(revision 18)
@@ -0,0 +1,85 @@
+/* sys/open.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include <string.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __open (const char *name, int flags, unsigned long size)
+{
+  ULONG rc;
+  ULONG open_mode, attr, action, open_flag;
+  HFILE handle;
+  int fail_errno;
+
+  /* Interpret "/dev/null" as the name of the null device "NUL".
+     Interpret "/dev/tty" as the name of the console device "CON". */
+
+  if (strcmp (name, "/dev/null") == 0)
+    name = "nul";
+  else if (strcmp (name, "/dev/tty") == 0)
+    name = "con";
+
+  /* Extract the access mode and sharing mode bits. */
+
+  open_mode = flags & 0x77;
+
+  /* Handle O_NOINHERIT and O_SYNC. */
+
+  if (flags & _SO_NOINHERIT)
+    open_mode |= OPEN_FLAGS_NOINHERIT;
+  if (flags & _SO_SYNC)
+    open_mode |= OPEN_FLAGS_WRITE_THROUGH;
+
+  /* Extract the file attribute bits. */
+
+  attr = (flags >> 8) & 0xff;
+  if (_sys_umask & 0200)
+    attr |= 1;
+
+  /* Translate ERROR_OPEN_FAILED to ENOENT unless O_EXCL is set (see
+     below). */
+
+  fail_errno = ENOENT;
+
+  /* Compute `open_flag' depending on `flags'.  Note that _SO_CREAT is
+     set for O_CREAT. */
+
+  if (flags & _SO_CREAT)
+    {
+      if (flags & _SO_EXCL)
+        {
+          open_flag = OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
+          fail_errno = EEXIST;
+        }
+      else if (flags & _SO_TRUNC)
+        open_flag = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
+      else
+        open_flag = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
+    }
+  else if (flags & _SO_TRUNC)
+    open_flag = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
+  else
+    open_flag = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
+
+  if (!(flags & _SO_SIZE))
+    size = 0;
+
+  /* Try to open the file and handle errors. */
+
+  rc = DosOpen (name, &handle, &action, size, attr, open_flag, open_mode,
+                NULL);
+  if (rc == ERROR_OPEN_FAILED)
+    {
+      errno = fail_errno;
+      return -1;
+    }
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return handle;
+}
Index: trunk/src/emx/src/lib/sys/__os_version.c
===================================================================
--- trunk/src/emx/src/lib/sys/__os_version.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__os_version.c	(revision 18)
@@ -0,0 +1,14 @@
+/* sys/os_ver.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#define INCL_DOSMISC
+#include <os2emx.h>
+
+int __os_version (void)
+{
+  LONG maj, min;
+
+  maj = 0; min = 0;             /* In case DosQuerySysInfo fails... */
+  DosQuerySysInfo (QSV_VERSION_MAJOR, QSV_VERSION_MAJOR, &maj, sizeof (maj));
+  DosQuerySysInfo (QSV_VERSION_MINOR, QSV_VERSION_MINOR, &min, sizeof (min));
+  return ((min & 0xff) << 8) | (maj & 0xff) | 0x6d650000;
+}
Index: trunk/src/emx/src/lib/sys/__pipe.c
===================================================================
--- trunk/src/emx/src/lib/sys/__pipe.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__pipe.c	(revision 18)
@@ -0,0 +1,20 @@
+/* sys/pipe.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOSQUEUES
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __pipe (int *two_handles, int pipe_size)
+{
+  ULONG rc;
+
+  rc = DosCreatePipe ((PHFILE)&two_handles[0], (PHFILE)&two_handles[1],
+                      pipe_size);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__read.c
===================================================================
--- trunk/src/emx/src/lib/sys/__read.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__read.c	(revision 18)
@@ -0,0 +1,20 @@
+/* sys/read.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __read (int handle, void *buf, size_t nbyte)
+{
+  ULONG rc;
+  ULONG n;
+
+  rc = DosRead (handle, buf, nbyte, &n);
+  if (rc == 0)
+    return n;
+  else
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/sys/__read_kbd.c
===================================================================
--- trunk/src/emx/src/lib/sys/__read_kbd.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__read_kbd.c	(revision 18)
@@ -0,0 +1,75 @@
+/* sys/read_kbd.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#define INCL_DOSFILEMGR
+#define INCL_KBD
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+static KBDINFO info;
+static KBDKEYINFO key;
+
+int __read_kbd (int echo, int wait, int sig)
+{
+  USHORT info_rc, rc;
+  USHORT info_mask;
+  ULONG n;
+  int ret;
+  char c;
+  static int more = -1;
+
+  if (more >= 0)
+    {
+      ret = more;
+      more = -1;
+      return ret;
+    }
+  info_mask = 0;                /* Keep the compiler happy */
+  info.cb = sizeof (info);
+  info_rc = KbdGetStatus (&info, 0);
+  if (info_rc == 0)
+    {
+      info_mask = info.fsMask;
+      info.fsMask &= ~0x7f;
+      if (sig)
+        info.fsMask |= KEYBOARD_ASCII_MODE;
+      else
+        info.fsMask |= KEYBOARD_BINARY_MODE;
+      info.cb = sizeof (info);
+      KbdSetStatus (&info, 0);
+    }
+
+again:
+  rc = KbdCharIn (&key, (wait ? IO_WAIT : IO_NOWAIT), 0);
+  if (rc != 0)
+    ret = -1;
+  else if (!(key.fbStatus & KBDTRF_FINAL_CHAR_IN))
+    {
+      if (wait)
+        goto again;
+      ret = -1;
+    }
+  else if ((key.chChar == 0 || key.chChar == 0xe0)
+           && key.fbStatus & KBDTRF_EXTENDED_CODE)
+    {
+      more = key.chScan;
+      ret = 0;
+    }
+  else
+    {
+      ret = key.chChar;
+      if (echo)
+        {
+          c = (char)ret;
+          DosWrite (1, &c, 1, &n);
+        }
+    }
+
+  if (info_rc == 0)
+    {
+      info.cb = sizeof (info);
+      info.fsMask = info_mask;
+      KbdSetStatus (&info, 0);
+    }
+  return ret;
+}
Index: trunk/src/emx/src/lib/sys/__rmdir.c
===================================================================
--- trunk/src/emx/src/lib/sys/__rmdir.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__rmdir.c	(revision 18)
@@ -0,0 +1,19 @@
+/* sys/rmdir.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+
+int __rmdir (const char *name)
+{
+  ULONG rc;
+
+  rc = DosDeleteDir (name);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__stat.c
===================================================================
--- trunk/src/emx/src/lib/sys/__stat.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__stat.c	(revision 18)
@@ -0,0 +1,66 @@
+/* sys/stat.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __stat (const char *name, struct stat *buf)
+{
+  ULONG rc;
+  FILESTATUS3 info;
+
+  memset (buf, 0, sizeof (*buf));
+  if ((name[0] == '/' || name[0] == '\\') && strlen (name) >= 6 &&
+      memicmp (name+1, "pipe", 4) == 0 && (name[5] == '/' || name[5] == '\\'))
+    {
+      errno = ENOENT;
+      return -1;
+    }
+  rc = DosQueryPathInfo (name, FIL_STANDARD, &info, sizeof (info));
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  buf->st_attr = info.attrFile;
+  buf->st_reserved = 0;
+  buf->st_mtime = _sys_p2t (info.ftimeLastWrite, info.fdateLastWrite);
+  if (FTIMEZEROP (info.ftimeCreation) &&
+      FDATEZEROP (info.fdateCreation))
+    buf->st_ctime = buf->st_mtime;
+  else
+    buf->st_ctime = _sys_p2t (info.ftimeCreation, info.fdateCreation);
+  if (FTIMEZEROP (info.ftimeLastAccess) &&
+      FDATEZEROP (info.fdateLastAccess))
+    buf->st_atime = buf->st_mtime;
+  else
+    buf->st_atime = _sys_p2t (info.ftimeLastAccess, info.fdateLastAccess);
+  if (info.attrFile & 0x10)     /* directory */
+    {
+      buf->st_mode = S_IFDIR;
+      buf->st_mode |= ((S_IREAD|S_IWRITE|S_IEXEC) >> 6) * 0111;
+      buf->st_size = 0;
+    }
+  else
+    {
+      buf->st_size = info.cbFile;
+      buf->st_mode = S_IFREG;
+      if (info.attrFile & 1)
+        buf->st_mode |= (S_IREAD >> 6) * 0111;
+      else
+        buf->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
+    }
+  buf->st_uid = 0;
+  buf->st_gid = 0;
+  buf->st_ino = _sys_ino++;
+  if (_sys_ino == 0)
+    _sys_ino = 1;
+  buf->st_dev = 0;
+  buf->st_rdev = 0;
+  buf->st_nlink = 1;
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__swchar.c
===================================================================
--- trunk/src/emx/src/lib/sys/__swchar.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__swchar.c	(revision 18)
@@ -0,0 +1,8 @@
+/* sys/swchar.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int __swchar (int flag, int new)
+{
+  return 0xff;
+}
Index: trunk/src/emx/src/lib/sys/__ulimit.c
===================================================================
--- trunk/src/emx/src/lib/sys/__ulimit.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__ulimit.c	(revision 18)
@@ -0,0 +1,25 @@
+/* sys/ulimit.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <sys/ulimit.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+long __ulimit (int cmd, long new_limit)
+{
+  switch (cmd)
+    {
+    case UL_GMEMLIM:
+      /* Note: As this is the limit for brk(), not for sbrk(), we
+         don't return 512M. */
+      return _sys_top_heap_obj != NULL ? _sys_top_heap_obj->end : 0;
+
+    case UL_OBJREST:
+      return (_sys_top_heap_obj != NULL
+              ? _sys_top_heap_obj->end - _sys_top_heap_obj->brk : 0);
+
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/sys/__utimes.c
===================================================================
--- trunk/src/emx/src/lib/sys/__utimes.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__utimes.c	(revision 18)
@@ -0,0 +1,59 @@
+/* sys/utimes.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+static void _sys_t2p (long sec, PFTIME time, PFDATE date)
+{
+  struct tm *p;
+  USHORT tmp;
+
+  p = gmtime (&sec);
+#if 0                           /* This didn't work in GCC versions <= 2.4 */
+  time->twosecs = p->tm_sec / 2;
+  time->minutes = p->tm_min;
+  time->hours = p->tm_hour;
+  date->day = p->tm_mday;
+  date->month = p->tm_mon + 1;
+  date->year = p->tm_year - 1980 + 1900;
+#else
+  tmp = (p->tm_sec / 2) + (p->tm_min << 5) + (p->tm_hour << 11);
+  *(USHORT *)time = tmp;
+  tmp = p->tm_mday + ((p->tm_mon + 1) << 5) + ((p->tm_year - 80) << 9);
+  *(USHORT *)date = tmp;
+#endif
+}
+
+
+int __utimes (const char *name, const struct timeval *tvp)
+{
+  ULONG rc;
+  FILESTATUS3 info;
+
+  if ((name[0] == '/' || name[0] == '\\') && strlen (name) >= 6 &&
+      memicmp (name+1, "pipe", 4) == 0 && (name[5] == '/' || name[5] == '\\'))
+    {
+      errno = ENOENT;
+      return -1;
+    }
+  rc = DosQueryPathInfo (name, FIL_STANDARD, &info, sizeof (info));
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  _sys_t2p (tvp[0].tv_sec, &info.ftimeLastAccess, &info.fdateLastAccess);
+  _sys_t2p (tvp[1].tv_sec, &info.ftimeLastWrite, &info.fdateLastWrite);
+  rc = DosSetPathInfo (name, FIL_STANDARD, &info, sizeof (info), 0);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/__wait.c
===================================================================
--- trunk/src/emx/src/lib/sys/__wait.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__wait.c	(revision 18)
@@ -0,0 +1,34 @@
+/* sys/wait.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOSPROCESS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __wait (int *status)
+{
+  ULONG rc;
+  RESULTCODES res;
+  PID pid;
+
+  rc = DosWaitChild (DCWA_PROCESS, DCWW_WAIT, &res, &pid, 0);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  switch (res.codeTerminate)
+    {
+    case TC_EXIT:
+      *status = res.codeResult << 8;
+      break;
+    case TC_HARDERROR:
+    case TC_KILLPROCESS:
+      *status = SIGTERM;
+      break;
+    default:
+      *status = SIGSEGV;
+      break;
+    }
+  return pid;
+}
Index: trunk/src/emx/src/lib/sys/__waitpid.c
===================================================================
--- trunk/src/emx/src/lib/sys/__waitpid.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__waitpid.c	(revision 18)
@@ -0,0 +1,24 @@
+/* sys/waitpid.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#define INCL_DOSPROCESS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __waitpid (int pid, int *status, int options)
+{
+  ULONG rc;
+  RESULTCODES res;
+  PID pid2;
+
+  if (pid == -1)
+    pid = 0;
+  rc = DosWaitChild (DCWA_PROCESS, DCWW_WAIT, &res, &pid2, pid);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  *status = res.codeResult << 8;
+  return pid2;
+}
Index: trunk/src/emx/src/lib/sys/__write.c
===================================================================
--- trunk/src/emx/src/lib/sys/__write.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/__write.c	(revision 18)
@@ -0,0 +1,20 @@
+/* sys/write.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __write (int handle, const void *buf, size_t nbyte)
+{
+  ULONG rc;
+  ULONG n;
+
+  rc = DosWrite (handle, buf, nbyte, &n);
+  if (rc == 0)
+    return n;
+  else
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/sys/brk.c
===================================================================
--- trunk/src/emx/src/lib/sys/brk.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/brk.c	(revision 18)
@@ -0,0 +1,41 @@
+/* sys/brk.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <errno.h>
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+void *__brk (void *brkp)
+{
+  ULONG base;
+
+#ifdef __MT__
+  if (_fmutex_request (&_sys_heap_fmutex, _FMR_IGNINT) != 0)
+    return (void *)-1;
+#endif
+
+  if (_sys_heap_obj_count == 0)
+    base = 0;
+  else if ((ULONG)brkp >= _sys_top_heap_obj->brk
+           && (ULONG)brkp <= _sys_top_heap_obj->end)
+    base = _sys_expand_heap_obj_by ((ULONG)brkp - _sys_top_heap_obj->brk);
+  else if ((ULONG)brkp >= _sys_top_heap_obj->base
+           && (ULONG)brkp < _sys_top_heap_obj->brk)
+    base = _sys_shrink_heap_obj_by (_sys_top_heap_obj->brk - (ULONG)brkp);
+  else
+    base = _sys_shrink_heap_to ((ULONG)brkp);
+
+#ifdef __MT__
+  if (_fmutex_release (&_sys_heap_fmutex) != 0)
+    return (void *)-1;
+#endif
+
+  if (base == 0)
+    {
+      errno = ENOMEM;
+      return (void *)-1;
+    }
+  return (void *)0;
+}
Index: trunk/src/emx/src/lib/sys/chdrive.c
===================================================================
--- trunk/src/emx/src/lib/sys/chdrive.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/chdrive.c	(revision 18)
@@ -0,0 +1,13 @@
+/* sys/chdrive.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __chdrive (char drive)
+{
+  if (drive >= 'a')
+    drive -= 0x20;
+  DosSetDefaultDisk (drive - 'A' + 1);
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/clock.c
===================================================================
--- trunk/src/emx/src/lib/sys/clock.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/clock.c	(revision 18)
@@ -0,0 +1,19 @@
+/* sys/clock.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+/* This function no longer tries to use QSV_TIME_LOW and QSV_TIME_HIGH
+   to increase the time before the return value wraps around.  Now, it
+   will wrap around after 49 days. */
+
+long long __clock (void)
+{
+  ULONG val_ms;
+  long long result;
+
+  _sys_get_clock (&val_ms);
+  result = (long long)((val_ms - _sys_clock0_ms) / 10);
+  return result;
+}
Index: trunk/src/emx/src/lib/sys/execname.c
===================================================================
--- trunk/src/emx/src/lib/sys/execname.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/execname.c	(revision 18)
@@ -0,0 +1,32 @@
+/* sys/execname.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#define INCL_DOS
+#include <os2emx.h>
+#include <string.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __execname (char *dst, size_t size)
+{
+  ULONG rc;
+  PTIB ptib;
+  PPIB ppib;
+
+  if (size == 0)
+    return -1;
+
+  rc = DosGetInfoBlocks (&ptib, &ppib);
+  if (rc != 0)
+    {
+      *dst = 0;
+      return -1;
+    }
+
+  rc = DosQueryModuleName (ppib->pib_hmte, size, dst);
+  if (rc != 0)
+    {
+      *dst = 0;
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/filefind.c
===================================================================
--- trunk/src/emx/src/lib/sys/filefind.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/filefind.c	(revision 18)
@@ -0,0 +1,122 @@
+/* sys/filefind.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <errno.h>
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+/* Close the directory handle. */
+
+static void find_close (struct find_data *fd)
+{
+  if (fd->find_handle != HDIR_CREATE)
+    {
+      DosFindClose (fd->find_handle);
+      fd->find_handle = HDIR_CREATE;
+    }
+  fd->find_count = 0;
+  fd->find_next = NULL;
+}
+
+/* Build a `struct _find' structure from a FILEFINDBUF3 structure and
+   move to the next one. */
+
+static int find_conv (struct find_data *fd, struct _find *fp)
+{
+  const FILEFINDBUF3 *src;
+
+  /* Check if there are any entries.  Close the handle and return
+     ENOENT if there are no entries.  (Checking SRC is redundant.) */
+
+  src = fd->find_next;
+  if (fd->find_count < 1 || src == NULL)
+    {
+      find_close (fd);
+      errno = ENOENT;
+      return -1;
+    }
+
+  /* Fill-in target object. */
+
+  fp->attr = (unsigned char)src->attrFile;
+  fp->time = XUSHORT (src->ftimeLastWrite);
+  fp->date = XUSHORT (src->fdateLastWrite);
+  fp->size_lo = (unsigned short)(src->cbFile & 0xffff);
+  fp->size_hi = (unsigned short)(src->cbFile >> 16);
+  strcpy (fp->name, src->achName);
+
+  /* Move to the next entry. */
+
+  if (src->oNextEntryOffset == 0)
+    {
+      fd->find_next = NULL;
+      fd->find_count = 0;
+    }
+  else
+    {
+      fd->find_next = (FILEFINDBUF3 *)((char *)src + src->oNextEntryOffset);
+      fd->find_count -= 1;
+    }
+
+  return 0;
+}
+
+
+int __findfirst (const char *name, int attr, struct _find *fp)
+{
+  ULONG rc;
+  struct find_data *fd;
+
+  fd = &SYS_THREAD->fd;
+
+  if (fd->find_handle != HDIR_CREATE)
+    {
+      /* Closing the handle is not strictly required as DosFindFirst
+         can reuse an open handle.  However, this simplifies error
+         handling below (will DosFindFirst close the handle on error
+         if it is open?). */
+
+      DosFindClose (fd->find_handle);
+      fd->find_handle = HDIR_CREATE;
+    }
+
+  fd->find_count = FIND_COUNT;
+  rc = DosFindFirst (name, &fd->find_handle, attr & 0x37,
+                     &fd->find_buf[0], sizeof (fd->find_buf),
+                     &fd->find_count, FIL_STANDARD);
+  if (rc != 0)
+    {
+      fd->find_handle = HDIR_CREATE; /* Perhaps modified by DosFindFirst */
+      fd->find_count = 0;
+      fd->find_next = NULL;
+      _sys_set_errno (rc);
+      return -1;
+    }
+  fd->find_next = &fd->find_buf[0];
+  return find_conv (fd, fp);
+}
+
+
+int __findnext (struct _find *fp)
+{
+  ULONG rc;
+  struct find_data *fd;
+
+  fd = &SYS_THREAD->fd;
+  if (fd->find_count < 1)
+    {
+      fd->find_count = FIND_COUNT;
+      rc = DosFindNext (fd->find_handle, &fd->find_buf[0],
+                        sizeof (fd->find_buf), &fd->find_count);
+      if (rc != 0)
+        {
+          find_close (fd);
+          _sys_set_errno (rc);
+          return -1;
+        }
+      fd->find_next = &fd->find_buf[0];
+    }
+
+  return find_conv (fd, fp);
+}
Index: trunk/src/emx/src/lib/sys/filesys.c
===================================================================
--- trunk/src/emx/src/lib/sys/filesys.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/filesys.c	(revision 18)
@@ -0,0 +1,37 @@
+/* sys/filesys.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <errno.h>
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+#define QFSA_SIZE 256
+
+int __filesys (const char *drive, char *name, size_t size)
+{
+  ULONG rc;
+  ULONG len;
+  FSQBUFFER2 *buf;
+
+  len = sizeof (FSQBUFFER2) + QFSA_SIZE;
+  buf = alloca (len);
+  rc = DosQueryFSAttach (drive, 1, FSAIL_QUERYNAME, buf, &len);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  if (buf->iType != FSAT_LOCALDRV && buf->iType != FSAT_REMOTEDRV)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (buf->cbFSDName >= size)
+    {
+      errno = E2BIG;
+      return -1;
+    }
+  strcpy (name, buf->szFSDName + buf->cbName);
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/fsync.c
===================================================================
--- trunk/src/emx/src/lib/sys/fsync.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/fsync.c	(revision 18)
@@ -0,0 +1,18 @@
+/* sys/fsync.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __fsync (int handle)
+{
+  ULONG rc;
+
+  rc = DosResetBuffer (handle);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/getpid.c
===================================================================
--- trunk/src/emx/src/lib/sys/getpid.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/getpid.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sys/getpid.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include "syscalls.h"
+
+int __getpid (void)
+{
+  return _sys_pid;
+}
Index: trunk/src/emx/src/lib/sys/getppid.c
===================================================================
--- trunk/src/emx/src/lib/sys/getppid.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/getppid.c	(revision 18)
@@ -0,0 +1,9 @@
+/* sys/getppid.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include "syscalls.h"
+
+int __getppid (void)
+{
+  return _sys_ppid;
+}
Index: trunk/src/emx/src/lib/sys/heap.c
===================================================================
--- trunk/src/emx/src/lib/sys/heap.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/heap.c	(revision 18)
@@ -0,0 +1,303 @@
+/* sys/heap.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include <errno.h>
+#include <sys/uflags.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+
+/* Allocate a memory object of SIZE bytes which is not located below
+   MIN_ADDR.  Return the address of the memory object.  Return 0 on
+   error. */
+
+static ULONG alloc_above (ULONG size, ULONG min_addr)
+{
+  ULONG ret;
+  void *p;
+
+  if (DosAllocMem (&p, size, PAG_READ | PAG_WRITE) != 0)
+    return 0;
+  if ((ULONG)p > min_addr)
+    return (ULONG)p;
+
+  /* The memory object is located below MIN_ADDR.  Recurse until we
+     get an appropriate object or until we run out of memory. */
+
+  ret = alloc_above (size, min_addr);
+
+  /* We got a suitable object.  Free the bad one. */
+
+  DosFreeMem (p);
+  return ret;
+}
+
+
+/* Expand the top heap object by INCR bytes.  INCR is a positive
+   number.  Return the previous break address or 0 (error). */
+
+ULONG _sys_expand_heap_obj_by (ULONG incr)
+{
+  ULONG rc, old_brk, new_brk, addr, size, rest;
+
+  old_brk = _sys_top_heap_obj->brk;
+  new_brk = old_brk + incr;
+
+  if (new_brk < _sys_top_heap_obj->base || new_brk > _sys_top_heap_obj->end)
+    return 0;
+
+  addr = old_brk;
+  size = incr;
+  if (addr & 0xfff)
+    {
+      rest = 0x1000 - (addr & 0xfff);
+      if (rest >= size)
+        size = 0;
+      else
+        {
+          size -= rest;
+          addr += rest;
+        }
+    }
+  if (size != 0)
+    {
+      rc = DosSetMem ((void *)addr, size, PAG_DEFAULT | PAG_COMMIT);
+      if (rc != 0)
+        return 0;
+    }
+  _sys_top_heap_obj->brk = new_brk;
+  return old_brk;
+}
+
+
+/* Shrink the top heap object by DECR bytes.  DECR is a positive
+   number.  Return the previous break address or 0 (error). */
+
+ULONG _sys_shrink_heap_obj_by (ULONG decr)
+{
+  ULONG rc, old_brk, new_brk, addr, high;
+
+  old_brk = _sys_top_heap_obj->brk;
+  new_brk = old_brk - decr;
+
+  if (new_brk < _sys_top_heap_obj->base || new_brk > _sys_top_heap_obj->end)
+    return 0;
+
+  addr = (new_brk + 0xfff) & ~0xfff;
+  high = (_sys_top_heap_obj->brk + 0xfff) & ~0xfff;
+  if (high > addr)
+    {
+      rc = DosSetMem ((void *)addr, high - addr, PAG_DECOMMIT);
+      if (rc != 0)
+        return 0;
+    }
+  _sys_top_heap_obj->brk = new_brk;
+  return old_brk;
+}
+
+
+/* Expand the heap by INCR bytes.  INCR is a positive number.  Return
+   the base address of the expansion or 0 (error). */
+
+ULONG _sys_expand_heap_by (ULONG incr, ULONG sbrk_model)
+{
+  unsigned old_obj_count;
+  ULONG base, size;
+
+  old_obj_count = _sys_heap_obj_count;
+
+  /* Allocate the first object if not yet done. */
+
+  if (_sys_heap_obj_count == 0)
+    {
+      size = _sys_heap_size;
+      if (incr > size)
+        size = (incr + 0xffff) & ~0xffff;
+      base = alloc_above (size, 0);
+      if (base == 0)
+        return 0;
+      _sys_heap_objs[0].base = base;
+      _sys_heap_objs[0].brk = base;
+      _sys_heap_objs[0].end = base + size;
+      _sys_heap_obj_count = 1;
+      _sys_top_heap_obj = &_sys_heap_objs[0];
+    }
+
+  /* Now we have at least one heap object.  Check for arithmetic
+     overflow. */
+
+  if (_sys_top_heap_obj->brk + incr < _sys_top_heap_obj->base)
+    {
+      /* Overflow.  If we've just allocated the first heap object,
+         deallocate it again unless memory must be allocated
+         contiguously. */
+
+      if (old_obj_count == 0 && sbrk_model != _UF_SBRK_CONTIGUOUS)
+        {
+          DosFreeMem ((void *)_sys_heap_objs[0].base);
+          _sys_heap_obj_count = 0;
+          _sys_top_heap_obj = NULL;
+        }
+      return 0;                 /* Failure */
+    }
+
+  /* Check whether we need another heap object.  Allocate one if we
+     need one and are allowed to allocate one.  This should not happen
+     if we just allocated the first one above. */
+
+  if (_sys_top_heap_obj->brk + incr > _sys_top_heap_obj->end)
+    {
+      /* We need another heap object.  Fail if we are not allowed to
+         allocate non-contiguous memory or if we already have the
+         maximum number of heap objects. */
+
+      if (sbrk_model == _UF_SBRK_CONTIGUOUS
+          || _sys_heap_obj_count >= MAX_HEAP_OBJS)
+        return 0;
+
+      /* Allocate at least _sys_heap_size bytes.  The new object must
+         be located above the currently top one. */
+
+      size = _sys_heap_size;
+      if (incr > size)
+        size = (incr + 0xffff) & ~0xffff;
+
+      for (;;)
+        {
+          if (sbrk_model == _UF_SBRK_ARBITRARY)
+            base = alloc_above (size, 0);
+          else
+            base = alloc_above (size, _sys_top_heap_obj->end);
+          if (base != 0)
+            break;
+
+          /* If we're out of virtual address space, halve the size and
+             try again until allocation succeeds.  Of course, don't
+             attempt to allocate less than INCR bytes. */
+
+          size /= 2;
+          if (size < incr)
+            return 0;
+        }
+
+      _sys_top_heap_obj = &_sys_heap_objs[_sys_heap_obj_count++];
+      _sys_top_heap_obj->base = base;
+      _sys_top_heap_obj->brk = base;
+      _sys_top_heap_obj->end = base + size;
+    }
+
+  /* Now _sys_top_heap_obj points to an object which has enough space.
+     Commit memory as required.  _sys_expand_heap_obj() returns the
+     top object's break address, which is the base address of the
+     expansion as an object might have been added. */
+
+  return _sys_expand_heap_obj_by (incr);
+}
+
+
+/* Shrink the heap to the new break address NEW_BRK.  Return the
+   previous break address or 0 (error). */
+
+ULONG _sys_shrink_heap_to (ULONG new_brk)
+{
+  unsigned obj;
+  ULONG old_brk;
+
+  /* Find the heap object containing the new break address.  Fail if
+     there is no such heap object.  Note that the new break address
+     must not be beyond the heap object current break address, that
+     is, we cannot shrink the heap (by deallocating objects) and grow
+     a heap object in one step. */
+
+  for (obj = 0; obj < _sys_heap_obj_count; ++obj)
+    if (_sys_heap_objs[obj].base <= new_brk
+        && _sys_heap_objs[obj].brk >= new_brk)
+      break;
+
+  if (obj >= _sys_heap_obj_count)
+    return 0;
+
+  /* We have at least one heap object, OBJ, so this is safe. */
+
+  old_brk = _sys_top_heap_obj->brk;
+
+  /* Free objects which are between the new break address and the old
+     one.  Fail if there are such objects and _UF_SBRK_CONTIGUOUS is
+     selected. */
+
+  if (obj != _sys_heap_obj_count - 1)
+    {
+      if ((_sys_uflags & _UF_SBRK_MODEL) == _UF_SBRK_CONTIGUOUS)
+        return 0;
+      while (_sys_heap_obj_count - 1 > obj)
+        {
+          _sys_heap_obj_count -= 1;
+          DosFreeMem ((void *)_sys_heap_objs[_sys_heap_obj_count].base);
+          _sys_heap_objs[_sys_heap_obj_count].base = 0;
+        }
+      _sys_top_heap_obj = &_sys_heap_objs[_sys_heap_obj_count-1];
+    }
+
+  if (new_brk == _sys_top_heap_obj->base)
+    {
+      /* The top object is shrunk to zero bytes, deallocate it and
+         bump NEW_BRK back to the previous object.  If
+         _UF_SBRK_CONTIGUOUS is selected and the (only) object is
+         shrunk to 0 bytes, it will be kept anyway to avoid breaking
+         programs which depend on the object keeping its address:
+
+            p = sbrk (1000);
+            sbrk (-1000);
+            assert (sbrk (1000) == p);
+
+         The assertion should not fail.  However, programs which
+         select _UF_SBRK_MONOTONOUS or _UF_SBRK_ARBITRARY should be
+         prepared for failure of the assertion.  Consider the
+         following code:
+
+            sbrk (1000);
+            p = sbrk (0);
+            sbrk (-1000);
+            brk (p);
+
+         Here, brk() may fail due to deallocation of the top
+         object. */
+
+      if (obj != 0 || (_sys_uflags & _UF_SBRK_MODEL) != _UF_SBRK_CONTIGUOUS)
+        {
+          _sys_heap_obj_count -= 1;
+          DosFreeMem ((void *)_sys_heap_objs[_sys_heap_obj_count].base);
+          _sys_heap_objs[_sys_heap_obj_count].base = 0;
+
+          if (_sys_heap_obj_count == 0)
+            _sys_top_heap_obj = NULL;
+          else
+            {
+              _sys_top_heap_obj = &_sys_heap_objs[_sys_heap_obj_count-1];
+              new_brk = _sys_top_heap_obj->brk;
+            }
+        }
+    }
+
+  /* Now decommit unused pages of the top heap object, if there is
+     one. */
+
+  if (_sys_heap_obj_count > 0
+      && _sys_shrink_heap_obj_by (_sys_top_heap_obj->brk - new_brk) == 0)
+    return 0;
+  return old_brk;
+}
+
+
+/* Shrink the heap by DECR bytes.  DECR is a positive number.  Return
+   the previous break address or 0 (error). */
+
+ULONG _sys_shrink_heap_by (ULONG decr, ULONG sbrk_model)
+{
+  if (_sys_heap_obj_count == 0)
+    return 0;
+  if (_sys_top_heap_obj->brk - decr < _sys_top_heap_obj->base)
+    return 0;
+  return _sys_shrink_heap_to (_sys_top_heap_obj->brk - decr);
+}
Index: trunk/src/emx/src/lib/sys/heapdump.c
===================================================================
--- trunk/src/emx/src/lib/sys/heapdump.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/heapdump.c	(revision 18)
@@ -0,0 +1,18 @@
+/* sys/heapdump.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include "syscalls.h"
+#include <stdio.h>
+
+
+void _sys_dump_heap_objs (FILE *f)
+{
+  unsigned i;
+
+  fprintf (f, "base     brk      end\n");
+  for (i = 0; i < _sys_heap_obj_count; ++i)
+    fprintf (f, "%.8lx %.8lx %.8lx%s\n",
+             _sys_heap_objs[i].base,
+             _sys_heap_objs[i].brk,
+             _sys_heap_objs[i].end,
+             _sys_top_heap_obj == &_sys_heap_objs[i] ? " top" : "");
+}
Index: trunk/src/emx/src/lib/sys/heapsize.c
===================================================================
--- trunk/src/emx/src/lib/sys/heapsize.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/heapsize.c	(revision 18)
@@ -0,0 +1,3 @@
+/* sys/heapsize.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+unsigned _sys_heap_size = HEAPSIZE;
Index: trunk/src/emx/src/lib/sys/kill.c
===================================================================
--- trunk/src/emx/src/lib/sys/kill.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/kill.c	(revision 18)
@@ -0,0 +1,36 @@
+/* sys/kill.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __kill (int pid, int sig)
+{
+  ULONG rc;
+  ULONG n;
+
+  if (pid == __getpid ())
+    {
+      if (sig == 0)
+        return 0;
+      return __raise (sig);
+    }
+  else if (sig == SIGINT || sig == SIGBREAK)
+    {
+      if (sig == SIGINT)
+        n = XCPT_SIGNAL_INTR;
+      else
+        n = XCPT_SIGNAL_BREAK;
+      rc = DosSendSignalException (pid, n);
+      if (rc != 0)
+        {
+          _sys_set_errno (rc);
+          return -1;
+        }
+      return 0;
+    }
+  errno = EINVAL;
+  return -1;
+}
Index: trunk/src/emx/src/lib/sys/makefile
===================================================================
--- trunk/src/emx/src/lib/sys/makefile	(revision 18)
+++ trunk/src/emx/src/lib/sys/makefile	(revision 18)
@@ -0,0 +1,171 @@
+#
+# /emx/src/lib/sys/makefile
+#
+GCC=gcc -O -I/emx/include -I.. -Wall -mprobe -fstack-check $(MT_CCFLAGS)
+AR=ar
+I=/emx/include/
+L=\emx\lib\ #
+SYSCALLS=syscalls.h $(I)sys/signal.h
+ERRNO=$(I)errno.h $(I)sys/errno.h
+FMUTEX=$(I)sys/builtin.h $(I)sys/fmutex.h
+
+PASSDOWN=CPU=$(CPU) DELOPT=$(DELOPT)
+
+.SUFFIXES: .obj .s .asm
+
+.SOURCE.c: ../$(CPU)
+.SOURCE.s: ../$(CPU)
+.SOURCE.asm: ../$(CPU)
+
+.SOURCE.c: ..
+.SOURCE.h: ..
+.SOURCE.s: ..
+.SOURCE.asm: ..
+
+.PHONY: clean default dstlib sys sysmt sysst
+
+DSTLIB=$(L)$(DIRNAME)\sys.lib
+
+.c.obj:
+	$(GCC) -c -s -Zomf $<
+
+.s.obj:
+	$(GCC) -c -s -Zomf -x assembler-with-cpp $<
+
+#
+# Requires MASM 6.0
+#
+# Without -Fo, MASM writes the output file to the directory of the source file
+#
+.asm.obj:
+	ml -c -nologo -Cx -Fo$@ $<
+
+default:    sys
+
+sys .SEQUENTIAL: sysst sysmt
+
+sysmt .SETDIR=mt_$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN) DIRNAME=mt MT_CCFLAGS=-Zmt
+
+sysst .SETDIR=st_$(CPU):
+	$(MAKE) -f ../makefile dstlib $(PASSDOWN) DIRNAME=st MT_CCFLAGS=
+
+dstlib: $(DSTLIB)
+
+clean:
+	-del mt_$(CPU)\*.obj $(DELOPT)
+	-del st_$(CPU)\*.obj $(DELOPT)
+
+brk.obj: brk.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(FMUTEX) $(I)emx/syscalls.h
+chdir.obj: chdir.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+chdrive.obj: chdrive.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+chmod.obj: chmod.c $(SYSCALLS) $(ERRNO) $(I)os2emx.h $(I)string.h \
+		$(I)emx/syscalls.h
+chsize.obj: chsize.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+clock.obj: clock.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+close.obj: close.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+dup.obj: dup.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+dup2.obj: dup2.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+emxinit.obj: emxinit.s
+emx_ver.obj: emx_ver.s
+endthrea.obj: endthrea.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+execname.obj: execname.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+exit.obj: exit.c $(I)os2emx.h
+fcntl.obj: fcntl.c $(I)os2emx.h $(ERRNO) $(SYSCALLS) $(I)emx/syscalls.h \
+		$(I)fcntl.h $(I)sys/fcntl.h
+filefind.obj: filefind.c $(I)os2emx.h $(I)string.h $(ERRNO) $(SYSCALLS) \
+		$(I)emx/syscalls.h
+filesys.obj: filesys.c $(I)os2emx.h $(ERRNO) $(I)string.h $(SYSCALLS) \
+		$(I)emx/syscalls.h
+fstat.obj: fstat.c $(SYSCALLS) $(I)os2emx.h $(I)string.h $(I)sys/types.h \
+		$(I)sys/stat.h $(I)emx/syscalls.h
+fsync.obj: fsync.c $(I)os2emx.h $(SYSCALLS) $(I)emx/syscalls.h
+ftime.obj: ftime.c $(I)os2emx.h $(SYSCALLS) $(I)sys/timeb.h $(I)time.h \
+		$(I)emx/syscalls.h $(I)emx/time.h
+ftruncat.obj: ftruncat.c $(I)os2emx.h $(SYSCALLS) $(I)emx/syscalls.h
+getcwd.obj: getcwd.c $(I)os2emx.h $(SYSCALLS) $(I)emx/syscalls.h
+getdrive.obj: getdrive.c $(I)os2emx.h $(SYSCALLS) $(I)emx/syscalls.h
+getpid.obj: getpid.c $(I)os2emx.h $(SYSCALLS)
+getppid.obj: getppid.c $(I)os2emx.h $(SYSCALLS)
+heap.obj: heap.c $(SYSCALLS) $(I)os2emx.h $(I)sys/uflags.h $(I)emx/syscalls.h
+heapdump.obj: heapdump.c $(SYSCALLS) $(I)os2emx.h $(I)sys/uflags.h \
+		$(I)stdio.h $(I)emx/syscalls.h
+imphandl.obj: imphandl.c $(I)emx/syscalls.h
+init.obj: init.c $(I)os2emx.h $(SYSCALLS) $(I)string.h $(FMUTEX) \
+		$(I)emx/syscalls.h $(I)emx/startup.h
+initthre.obj: initthre.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+ioctl1.obj: ioctl1.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(I)emx/syscalls.h
+ioctl2.obj: ioctl2.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(I)sys/ioctl.h \
+		$(I)emx/syscalls.h
+kill.obj: kill.c $(SYSCALLS) $(ERRNO) $(I)os2emx.h $(I)emx/syscalls.h
+lseek.obj: lseek.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+memacces.obj: memacces.c $(SYSCALLS) $(I)emx/syscalls.h $(ERRNO)
+memavail.obj: memavail.c $(I)emx/syscalls.h
+mkdir.obj: mkdir.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+newthrea.obj: newthrea.c $(SYSCALLS) $(ERRNO) $(I)os2emx.h $(I)emx/syscalls.h
+nls_memu.obj: nls_memu.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+nls_ctyp.obj: nls_ctyp.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h \
+		$(I)sys/nls.h
+open.obj: open.c $(SYSCALLS) $(I)os2emx.h $(I)string.h $(ERRNO) \
+		$(I)emx/syscalls.h
+os_ver.obj: os_ver.c $(I)emx/syscalls.h
+p2t.obj: p2t.c $(SYSCALLS) $(I)os2emx.h $(I)time.h $(I)emx/syscalls.h \
+		$(I)emx/time.h
+pause.obj: pause.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+pipe.obj: pipe.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+portacce.obj: portacce.c $(SYSCALLS) $(I)emx/syscalls.h
+raise.obj: raise.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(I)string.h \
+		$(I)emx/syscalls.h
+read.obj: read.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+read_kbd.obj: read_kbd.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+remove.obj: remove.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+rename.obj: rename.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+rmdir.obj: rmdir.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+sbrk.obj: sbrk.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(FMUTEX) \
+		$(I)sys/uflags.h $(I)emx/syscalls.h
+scrsize.obj: scrsize.c $(I)os2emx.h $(I)os2thunk.h $(I)emx/syscalls.h
+sigactio.obj: sigactio.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(I)emx/syscalls.h
+signal.obj: signal.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(I)emx/syscalls.h
+sigpendi.obj: sigpendi.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(I)emx/syscalls.h
+sigprocm.obj: sigprocm.c $(SYSCALLS) $(ERRNO) $(I)os2emx.h $(I)emx/syscalls.h
+sigsuspe.obj: sigsuspe.c $(SYSCALLS) $(I)os2emx.h $(ERRNO) $(I)emx/syscalls.h
+sleep.obj: sleep.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+sleep2.obj: sleep2.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+seterrno.obj: seterrno.c $(SYSCALLS) $(ERRNO)
+spawnve.obj: spawnve.c $(SYSCALLS) $(I)stdlib.h $(PROCESS) $(I)string.h \
+		$(ERRNO) $(I)os2emx.h $(I)emx/syscalls.h
+stat.obj: stat.c $(SYSCALLS) $(I)os2emx.h $(I)string.h $(I)sys/types.h \
+		$(I)sys/stat.h $(ERRNO) $(I)emx/syscalls.h
+swchar.obj: swchar.c $(SYSCALLS)
+systhrea.obj: systhrea.s
+thunk0.obj: thunk0.asm
+thunk1.obj: thunk1.asm
+uflags.obj: uflags.c $(SYSCALLS)
+ulimit.obj: ulimit.c $(I)sys/ulimit.h $(SYSCALLS) $(ERRNO) $(I)emx/syscalls.h
+umask.obj: umask.c $(SYSCALLS) $(I)emx/syscalls.h
+utimes.obj: utimes.c $(SYSCALLS) $(I)os2emx.h $(I)time.h $(I)sys/time.h \
+		$(I)string.h $(ERRNO) $(I)emx/syscalls.h
+unwind.obj: unwind.s
+wait.obj: wait.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+waitpid.obj: waitpid.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+write.obj: write.c $(SYSCALLS) $(I)os2emx.h $(I)emx/syscalls.h
+
+heapsize.obj: ../heapsize.c $(SYSCALLS)
+	$(GCC) -c -s -Zomf -DHEAPSIZE=0x2000000 ../heapsize.c
+
+$(DSTLIB):  brk.obj chdir.obj chdrive.obj chmod.obj chsize.obj \
+    clock.obj close.obj dup.obj dup2.obj emxinit.obj emx_ver.obj \
+    endthrea.obj execname.obj exit.obj fcntl.obj filefind.obj filesys.obj \
+    fstat.obj fsync.obj ftime.obj ftruncat.obj getcwd.obj \
+    getdrive.obj getpid.obj getppid.obj heap.obj heapdump.obj heapsize.obj \
+    imphandl.obj init.obj initthre.obj ioctl1.obj \
+    ioctl2.obj kill.obj lseek.obj memacces.obj memavail.obj mkdir.obj \
+    newthrea.obj nls_ctyp.obj nls_memu.obj open.obj os_ver.obj p2t.obj \
+    pause.obj pipe.obj portacce.obj raise.obj read.obj read_kbd.obj \
+    remove.obj rename.obj rmdir.obj sbrk.obj scrsize.obj seterrno.obj \
+    sigactio.obj signal.obj sigpendi.obj sigprocm.obj sigsuspe.obj \
+    sleep.obj sleep2.obj spawnve.obj stat.obj swchar.obj \
+    systhrea.obj thunk0.obj thunk1.obj uflags.obj ulimit.obj umask.obj \
+    unwind.obj utimes.obj wait.obj waitpid.obj write.obj
+	-del $(DSTLIB)
+	emxomfar rc $(DSTLIB) *.obj
Index: trunk/src/emx/src/lib/sys/p2t.c
===================================================================
--- trunk/src/emx/src/lib/sys/p2t.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/p2t.c	(revision 18)
@@ -0,0 +1,21 @@
+/* sys/p2t.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <time.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+long _sys_p2t (FTIME t, FDATE d)
+{
+  struct tm tm;
+
+  tm.tm_sec = t.twosecs * 2;
+  tm.tm_min = t.minutes;
+  tm.tm_hour = t.hours;
+  tm.tm_mday = d.day;
+  tm.tm_mon = d.month - 1;
+  tm.tm_year = d.year + 1980 - 1900;
+  tm.tm_isdst = -1;             /* unknown */
+  return _mktime (&tm);
+}
Index: trunk/src/emx/src/lib/sys/pause.c
===================================================================
--- trunk/src/emx/src/lib/sys/pause.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/pause.c	(revision 18)
@@ -0,0 +1,12 @@
+/* sys/pause.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#define INCL_DOSPROCESS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+void __pause (void)
+{
+  while (DosSleep (0xffffffff) == 0)
+    ;
+}
Index: trunk/src/emx/src/lib/sys/portacce.c
===================================================================
--- trunk/src/emx/src/lib/sys/portacce.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/portacce.c	(revision 18)
@@ -0,0 +1,10 @@
+/* sys/portacce.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __portaccess (unsigned first, unsigned last)
+{
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/raise.c
===================================================================
--- trunk/src/emx/src/lib/sys/raise.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/raise.c	(revision 18)
@@ -0,0 +1,31 @@
+/* sys/raise.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+#include <string.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __raise (int signo)
+{
+  thread_data *tp;
+
+  if (signo < 1 || signo >= NSIG || !_sys_sig_valid[signo])
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  tp = SYS_THREAD;
+  if (tp == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (tp->signals[signo].sa_handler != SIG_IGN)
+    {
+      __sigaddset (&tp->sig_pending, signo);
+      _sys_deliver_pending_signals (tp);
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/remove.c
===================================================================
--- trunk/src/emx/src/lib/sys/remove.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/remove.c	(revision 18)
@@ -0,0 +1,19 @@
+/* sys/remove.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __remove (const char *name)
+{
+  ULONG rc;
+
+  rc = DosDelete (name);
+  if (rc == 0)
+    return 0;
+  else
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/sys/rename.c
===================================================================
--- trunk/src/emx/src/lib/sys/rename.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/rename.c	(revision 18)
@@ -0,0 +1,18 @@
+/* sys/rename.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __rename (const char *old_name, const char *new_name)
+{
+  ULONG rc;
+
+  rc = DosMove (old_name, new_name);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/sbrk.c
===================================================================
--- trunk/src/emx/src/lib/sys/sbrk.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/sbrk.c	(revision 18)
@@ -0,0 +1,36 @@
+/* sys/sbrk.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <os2emx.h>
+#include <errno.h>
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/uflags.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+void *__sbrk (int incr)
+{
+  ULONG base;
+
+#ifdef __MT__
+  if (_fmutex_request (&_sys_heap_fmutex, _FMR_IGNINT) != 0)
+    return (void *)-1;
+#endif
+
+  if (incr >= 0)
+    base = _sys_expand_heap_by (incr, _sys_uflags & _UF_SBRK_MODEL);
+  else
+    base = _sys_shrink_heap_by (-incr, _sys_uflags & _UF_SBRK_MODEL);
+
+#ifdef __MT__
+  if (_fmutex_release (&_sys_heap_fmutex) != 0)
+    return (void *)-1;
+#endif
+
+  if (base == 0)
+    {
+      errno = ENOMEM;
+      return (void *)-1;
+    }
+  return (void *)base;
+}
Index: trunk/src/emx/src/lib/sys/scrsize.c
===================================================================
--- trunk/src/emx/src/lib/sys/scrsize.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/scrsize.c	(revision 18)
@@ -0,0 +1,20 @@
+/* sys/scrsize.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_VIO
+#include <os2emx.h>
+#include <os2thunk.h>
+#include <emx/syscalls.h>
+
+void __scrsize (int *dst)
+{
+  VIOMODEINFO vmi1, vmi2, *pvmi;
+
+  /* At most one of vmi1, vmi2 crosses a 64Kbyte boundary.  Use one
+     which doesn't. */
+
+  pvmi = _THUNK_PTR_STRUCT_OK (&vmi1) ? &vmi1 : &vmi2;
+  pvmi->cb = sizeof (*pvmi);
+  VioGetMode (pvmi, 0);
+  dst[0] = pvmi->col;
+  dst[1] = pvmi->row;
+}
Index: trunk/src/emx/src/lib/sys/seterrno.c
===================================================================
--- trunk/src/emx/src/lib/sys/seterrno.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/seterrno.c	(revision 18)
@@ -0,0 +1,86 @@
+/* sys/seterrno.c (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes */
+
+#include <errno.h>
+#include "syscalls.h"
+
+extern int errno;
+
+static unsigned char const errno_tab[] =
+{
+  EINVAL, EINVAL, ENOENT, ENOENT, EMFILE,  /* 0..4 */
+  EACCES, EBADF,  EIO,    ENOMEM, EIO,     /* 5..9 */
+  EINVAL, ENOEXEC,EINVAL, EINVAL, EINVAL,  /* 10..14 */
+  ENOENT, EBUSY,  EXDEV,  ENOENT, EROFS,   /* 15..19 */
+  EIO,    EIO,    EIO,    EIO,    EIO,     /* 20..24 */
+  EIO,    EIO,    EIO,    ENOSPC, EIO,     /* 25..29 */
+  EIO,    EIO,    EACCES, EACCES, EIO,     /* 30..34 */
+  EIO,    EIO,    EIO,    EIO,    ENOSPC,  /* 35..39 */
+  EIO,    EIO,    EIO,    EIO,    EIO,     /* 40..44 */
+  EIO,    EIO,    EIO,    EIO,    EIO,     /* 45..49 */
+  EIO,    EIO,    EIO,    EIO,    EBUSY,   /* 50..54 */
+  EIO,    EIO,    EIO,    EIO,    EIO,     /* 55..59 */
+  EIO,    ENOSPC, ENOSPC, EIO,    EIO,     /* 60..64 */
+  EACCES, EIO,    EIO,    EIO,    EIO,     /* 65..69 */
+  EIO,    EIO,    EIO,    EROFS,  EIO,     /* 70..74 */
+  EIO,    EIO,    EIO,    EIO,    EIO,     /* 75..79 */
+  EEXIST, EIO,    ENOENT, EIO,    EIO,     /* 80..84 */
+  EIO,    EIO,    EINVAL, EIO,    EAGAIN,  /* 85..89 */
+  EIO,    EIO,    EIO,    EIO,    EIO,     /* 90..94 */
+  EINTR,  EIO,    EIO,    EIO,    EACCES,  /* 95..99 */
+  ENOMEM, EINVAL, EINVAL, ENOMEM, EINVAL,  /* 100..104 */
+  EINVAL, ENOMEM, EIO,    EACCES, EPIPE,   /* 105..109 */
+  ENOENT, E2BIG,  ENOSPC, ENOMEM, EBADF,   /* 110..114 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 115..119 */
+  EINVAL, EINVAL, EINVAL, ENOENT, EINVAL,  /* 120..124 */
+  ENOENT, ENOENT, ENOENT, ECHILD, ECHILD,  /* 125..129 */
+  EACCES, EINVAL, ESPIPE, EINVAL, EINVAL,  /* 130..134 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 135..139 */
+  EINVAL, EINVAL, EBUSY,  EINVAL, EINVAL,  /* 140..144 */
+  EINVAL, EINVAL, EINVAL, EBUSY,  EINVAL,  /* 145..149 */
+  EINVAL, EINVAL, ENOMEM, EINVAL, EINVAL,  /* 150..154 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 155..159 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EAGAIN,  /* 160..164 */
+  EINVAL, EINVAL, EACCES, EINVAL, EINVAL,  /* 165..169 */
+  EBUSY,  EINVAL, EINVAL, EINVAL, EINVAL,  /* 170..174 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 175..179 */
+  EINVAL, EINVAL, EINVAL, EINVAL, ECHILD,  /* 180..184 */
+  EINVAL, EINVAL, ENOENT, EINVAL, EINVAL,  /* 185..189 */
+  ENOEXEC,ENOEXEC,ENOEXEC,ENOEXEC,ENOEXEC, /* 190..194 */
+  ENOEXEC,ENOEXEC,ENOEXEC,ENOEXEC,ENOEXEC, /* 195..199 */
+  ENOEXEC,ENOEXEC,ENOEXEC,ENOENT, EINVAL,  /* 200..204 */
+  EINVAL, ENAMETOOLONG, EINVAL, EINVAL, EINVAL,  /* 205..209 */
+  EINVAL, EINVAL, EACCES, ENOEXEC,ENOEXEC, /* 210..214 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 215..219 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 220..224 */
+  EINVAL, EINVAL, EINVAL, ECHILD, EINVAL,  /* 225..229 */
+  EINVAL, EBUSY,  EAGAIN, ENOTCONN, EINVAL, /* 230..234 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 235..239 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 240..244 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 245..249 */
+  EACCES, EACCES, EINVAL, ENOENT, EINVAL,  /* 250..254 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 255..259 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 260..264 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 265..269 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 270..274 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 275..279 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EEXIST,  /* 280..284 */
+  EEXIST, EINVAL, EINVAL, EINVAL, EINVAL,  /* 285..289 */
+  ENOMEM, EMFILE, EINVAL, EINVAL, EINVAL,  /* 290..294 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EINVAL,  /* 295..299 */
+  EINVAL, EBUSY,  EINVAL, ESRCH,  EINVAL,  /* 300..304 */
+  ESRCH,  EINVAL, EINVAL, EINVAL, ESRCH,   /* 305..309 */
+  EINVAL, ENOMEM, EINVAL, EINVAL, EINVAL,  /* 310..314 */
+  EINVAL, E2BIG,  ENOENT, EIO,    EIO,     /* 315..319 */
+  EINVAL, EINVAL, EINVAL, EINVAL, EAGAIN,  /* 320..324 */
+  EINVAL, EINVAL, EINVAL, EIO,    ENOENT,  /* 325..329 */
+  EACCES, EACCES, EACCES, ENOENT, ENOMEM   /* 330..334 */
+};
+
+
+void _sys_set_errno (unsigned long rc)
+{
+  if (rc >= sizeof (errno_tab))
+    errno = EINVAL;
+  else
+    errno = errno_tab[rc];
+}
Index: trunk/src/emx/src/lib/sys/sigaction.c
===================================================================
--- trunk/src/emx/src/lib/sys/sigaction.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/sigaction.c	(revision 18)
@@ -0,0 +1,46 @@
+/* sys/sigactio.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+
+int __sigaction (int signo, const struct sigaction *iact,
+                 struct sigaction *oact)
+{
+  struct sigaction output, *s;
+  thread_data *tp;
+
+  if (signo < 1 || signo >= NSIG || signo == SIGKILL || !_sys_sig_valid[signo])
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (signo == SIGKILL && iact != NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  tp = SYS_THREAD;
+  if (tp == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  s = &tp->signals[signo];
+  output = *s;
+  if (iact != NULL)
+    {
+      *s = *iact;
+      if ((s->sa_handler == SIG_DFL
+           && sig_info[signo].dfl_action != ST_IGNORE)
+          || s->sa_handler == SIG_IGN)
+        __sigdelset (&tp->sig_pending, signo);
+    }
+
+  if (oact != NULL)
+    *oact = output;
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/signal.c
===================================================================
--- trunk/src/emx/src/lib/sys/signal.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/signal.c	(revision 18)
@@ -0,0 +1,41 @@
+/* sys/signal.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+typedef void sigfun (int sig);
+
+sigfun *__signal (int sig, sigfun *handler)
+{
+  if (handler == SIG_ACK)
+    {
+      thread_data *tp;
+
+      if (sig < 1 || sig >= NSIG || sig == SIGKILL || !_sys_sig_valid[sig])
+        {
+          errno = EINVAL;
+          return SIG_ERR;
+        }
+      tp = SYS_THREAD;
+      if (tp == NULL)
+        return SIG_ERR;
+      __sigdelset (&tp->sig_blocked, sig);
+      _sys_deliver_pending_signals (tp);
+      return tp->signals[sig].sa_handler;
+    }
+  else
+    {
+      struct sigaction isa, osa;
+
+      isa.sa_handler = handler;
+      isa.sa_mask = 0;
+      isa.sa_flags = SA_ACK;
+      if (__sigaction (sig, &isa, &osa) != 0)
+        return SIG_ERR;
+      else
+        return osa.sa_handler;
+    }
+}
Index: trunk/src/emx/src/lib/sys/sigpending.c
===================================================================
--- trunk/src/emx/src/lib/sys/sigpending.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/sigpending.c	(revision 18)
@@ -0,0 +1,16 @@
+/* sys/sigpendi.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __sigpending (sigset_t *set)
+{
+  thread_data *tp;
+
+  /* TODO: Critical section */
+  tp = SYS_THREAD;
+  *set = tp->sig_blocked & tp->sig_pending;
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/sigprocmask.c
===================================================================
--- trunk/src/emx/src/lib/sys/sigprocmask.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/sigprocmask.c	(revision 18)
@@ -0,0 +1,41 @@
+/* sys/sigprocm.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __sigprocmask (int how, const sigset_t *iset, sigset_t *oset)
+{
+  thread_data *tp;
+  sigset_t temp, output;
+
+  tp = SYS_THREAD;
+  output = tp->sig_blocked;
+  if (iset != NULL)
+    {
+      switch (how)
+        {
+        case SIG_BLOCK:
+          temp = tp->sig_blocked | *iset;
+          break;
+        case SIG_UNBLOCK:
+          temp = tp->sig_blocked & ~*iset;
+          break;
+        case SIG_SETMASK:
+          temp = *iset;
+          break;
+        default:
+          errno = EINVAL;
+          return -1;
+        }
+      SET_BLOCKED (tp, temp);
+    }
+
+  if (oset != NULL)
+    *oset = output;
+
+  _sys_deliver_pending_signals (tp);
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/sigsuspend.c
===================================================================
--- trunk/src/emx/src/lib/sys/sigsuspend.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/sigsuspend.c	(revision 18)
@@ -0,0 +1,22 @@
+/* sys/sigsuspe.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#define INCL_DOSEXCEPTIONS
+#include <os2emx.h>
+#include <errno.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+int __sigsuspend (const sigset_t *mask)
+{
+  sigset_t old_blocked;
+  thread_data *tp;
+
+  /* TODO: Critical section */
+  tp = SYS_THREAD;
+  old_blocked = tp->sig_blocked;
+  SET_BLOCKED (tp, *mask);
+  __pause ();
+  tp->sig_blocked = old_blocked;
+  errno = EINTR;
+  return -1;
+}
Index: trunk/src/emx/src/lib/sys/sleep.c
===================================================================
--- trunk/src/emx/src/lib/sys/sleep.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/sleep.c	(revision 18)
@@ -0,0 +1,29 @@
+/* sys/sleep.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#define INCL_DOSMISC
+#define INCL_DOSPROCESS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+unsigned __sleep (unsigned sec)
+{
+  if (sec == 0)
+    {
+      DosSleep (0);
+      return 0;
+    }
+  else
+    {
+      ULONG start, stop, elapsed;
+
+      DosQuerySysInfo (QSV_TIME_LOW, QSV_TIME_LOW, &start, sizeof (start));
+      if (DosSleep (1000 * sec) == 0)
+        return 0;
+      DosQuerySysInfo (QSV_TIME_LOW, QSV_TIME_LOW, &stop, sizeof (stop));
+      elapsed = stop - start;
+      if (sec < elapsed)
+        return 0;
+      return sec - elapsed;
+    }
+}
Index: trunk/src/emx/src/lib/sys/sleep2.c
===================================================================
--- trunk/src/emx/src/lib/sys/sleep2.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/sleep2.c	(revision 18)
@@ -0,0 +1,12 @@
+/* sys/sleep2.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#define INCL_DOSPROCESS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+unsigned __sleep2 (unsigned millisec)
+{
+  DosSleep (millisec);
+  return 0;
+}
Index: trunk/src/emx/src/lib/sys/spawnve.c
===================================================================
--- trunk/src/emx/src/lib/sys/spawnve.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/spawnve.c	(revision 18)
@@ -0,0 +1,163 @@
+/* sys/spawnve.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <errno.h>
+#define INCL_DOSPROCESS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+/* Note: We are allowed to call _trealloc() as this module is not used
+   in an .a library. */
+
+#define ADD(n) do { \
+  while (arg_size + n > arg_alloc) \
+    { \
+      arg_alloc += 512; \
+      arg_buf = _trealloc (arg_buf, arg_alloc); \
+      if (arg_buf == NULL) \
+        { \
+          errno = ENOMEM; \
+          return -1; \
+        } \
+      arg_ptr = arg_buf + arg_size; \
+    } \
+  arg_size += n; } while (0)
+
+
+int __spawnve (struct _new_proc *np)
+{
+  ULONG rc;
+  ULONG exec_flag, mode;
+  RESULTCODES res;
+  char obj[40], *arg_ptr, *arg_buf;
+  char *pgm_name, *base;
+  const char *src, *s;
+  size_t arg_size, arg_alloc, len;
+  int i, quote, bs, method;
+
+  arg_buf = NULL; arg_alloc = 0; arg_size = 0; arg_ptr = NULL;
+
+  mode = np->mode;
+  if (np->mode & 0x8000)
+    mode |= np->mode2 << 16;
+
+  switch (mode & 0xff)
+    {
+    case P_WAIT:
+      exec_flag = EXEC_SYNC;
+      break;
+    case P_NOWAIT:
+      exec_flag = EXEC_ASYNCRESULT;
+      break;
+    case P_OVERLAY:
+      exec_flag = EXEC_ASYNC;
+      break;
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+  pgm_name = alloca (strlen ((const char *)np->fname_off) + 5);
+  strcpy (pgm_name, (const char *)np->fname_off);
+  _defext (pgm_name, "exe");
+  base = _getname (pgm_name);
+  method = 0;
+  if (stricmp (base, "cmd.exe") == 0 || stricmp (base, "4os2.exe") == 0)
+    method = 1;
+  src = (const char *)np->arg_off;
+  if (np->arg_count > 0)
+    {
+      ++src;                    /* skip flags byte */
+      len = strlen (src) + 1;
+      ADD (len);
+      memcpy (arg_ptr, src, len);
+      arg_ptr += len; src += len;
+    }
+  for (i = 1; i < np->arg_count; ++i)
+    {
+      if (i > 1)
+        {
+          ADD (1);
+          *arg_ptr++ = ' ';
+        }
+      ++src;                    /* skip flags byte */
+      quote = FALSE;
+      if (*src == 0)
+        quote = TRUE;
+      else if (mode & P_QUOTE)
+        {
+          if (src[0] == '@' && src[1] != 0)
+            quote = TRUE;
+          else
+            for (s = src; *s != 0; ++s)
+              if (*s == '?' || *s == '*')
+                {
+                  quote = TRUE;
+                  break;
+                }
+        }
+      if (!quote)
+        for (s = src; *s != 0; ++s)
+          if (*s == ' ' || *s == '\t' || (*s == '"' && method == 1))
+            {
+              quote = TRUE;
+              break;
+            }
+      if (quote)
+        {
+          ADD (1);
+          *arg_ptr++ = '"';
+        }
+      bs = 0;
+      while (*src != 0)
+        {
+          if (*src == '"' && method == 0)
+            {
+              ++bs;
+              ADD (bs);
+              memset (arg_ptr, '\\', bs); arg_ptr += bs;
+              bs = 0;
+            }
+          else if (*src == '\\' && method == 0)
+            ++bs;
+          else
+            bs = 0;
+          ADD (1);
+          *arg_ptr++ = *src;
+          ++src;
+        }
+      if (quote)
+        {
+          ADD (1+bs);
+          memset (arg_ptr, '\\', bs); arg_ptr += bs;
+          *arg_ptr++ = '"';
+        }
+      ++src;
+    }
+  ADD (1);
+  *arg_ptr++ = 0;
+  rc = DosExecPgm (obj, sizeof (obj), exec_flag, arg_buf,
+                   (const char *)np->env_off, &res, pgm_name);
+  if (arg_buf != NULL)
+    _tfree (arg_buf);
+  if (rc != 0)
+    {
+      _sys_set_errno (rc);
+      return -1;
+    }
+  switch (mode & 0xff)
+    {
+    case P_WAIT:
+      return res.codeResult;
+    case P_NOWAIT:
+      return res.codeTerminate;
+    case P_OVERLAY:
+      while (1)
+        DosExit (EXIT_PROCESS, 0);
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+}
Index: trunk/src/emx/src/lib/sys/syscalls.h
===================================================================
--- trunk/src/emx/src/lib/sys/syscalls.h	(revision 18)
+++ trunk/src/emx/src/lib/sys/syscalls.h	(revision 18)
@@ -0,0 +1,152 @@
+/* sys/syscalls.h (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <sys/signal.h>
+
+#if !defined (NULL)
+#define NULL ((void *)0)
+#endif
+
+#if !defined (INIT)
+#define EXTERN extern
+#define INIT(x)
+#endif
+
+#define BEGIN do {
+#define END   } while (0)
+
+#if !defined (_OS2EMX_H)
+typedef unsigned long ULONG;
+#endif
+
+/* This macro is used for accessing FDATE or FTIME values as
+   USHORT. */
+
+#define XUSHORT(x) (*(USHORT *)&(x))
+
+/* Fetch this many FILEFINDBUF3 entries at once with DosFindFirst and
+   DosFindNext. */
+
+#define FIND_COUNT      4
+
+/* Maximum number of heap objects (16 = 512 / 32). */
+
+#define MAX_HEAP_OBJS   16
+
+/* This structure describes one heap object. */
+
+struct heap_obj
+{
+  ULONG base;                   /* Base address */
+  ULONG end;                    /* End address */
+  ULONG brk;                    /* Address of first unused byte */
+};
+
+EXTERN int _sys_umask INIT (0022);
+EXTERN unsigned _sys_uflags INIT (0);
+EXTERN unsigned long _sys_clock0_ms INIT (0);
+EXTERN long _sys_ino INIT (0x100000);
+EXTERN int _sys_pid;
+EXTERN int _sys_ppid;
+
+/* The top heap object.  This points into _sys_heap_objs[] or is NULL.
+   While this variable is NULL, no memory has been allocated. */
+
+struct heap_obj *_sys_top_heap_obj;
+
+/* This array holds information on all the heap objects.  The heap
+   objects are managed in LIFO fashion. */
+
+struct heap_obj _sys_heap_objs[MAX_HEAP_OBJS];
+
+/* This is the number of heap objects. */
+
+EXTERN unsigned _sys_heap_obj_count;
+
+/* This variable can be initialized by the application to control the
+   size of the heap object(s). */
+
+extern unsigned _sys_heap_size;
+
+
+#if defined (_OS2EMX_H)
+
+#define FTIMEZEROP(x) (*(USHORT *)&(x) == 0)
+#define FDATEZEROP(x) (*(USHORT *)&(x) == 0)
+
+struct find_data
+{
+  HDIR find_handle;
+  ULONG find_count;
+  FILEFINDBUF3 find_buf[FIND_COUNT];
+  const FILEFINDBUF3 *find_next;
+};
+
+typedef struct
+{
+  struct find_data fd;
+  sigset_t sig_blocked;
+  sigset_t sig_pending;
+  struct sigaction signals[NSIG];
+} thread_data;
+
+#if defined (INCL_DOSEXCEPTIONS)
+EXTERN PEXCEPTIONREGISTRATIONRECORD _sys_xreg INIT (NULL);
+ULONG _sys_exception (PEXCEPTIONREPORTRECORD report,
+    PEXCEPTIONREGISTRATIONRECORD registration, PCONTEXTRECORD context,
+    PVOID whatever);
+#endif /* defined (INCL_DOSEXCEPTIONS) */
+
+/* TODO: SIGSTOP */
+#define SET_BLOCKED(tp,set) ((tp)->sig_blocked = (set) & ~_SIGMASK (SIGKILL))
+
+enum sig_type
+{
+  ST_TERM,                      /* Terminate process (SIGINT for instance) */
+  ST_NEXT,                      /* Pass on to next exception handler */
+  ST_IGNORE                     /* Ignore exception and continue thread */
+};
+
+struct sig_descr
+{
+  const char *name;             /* Name of the signal */
+  enum sig_type dfl_action;     /* Default action */
+  enum sig_type fun_action;     /* Action taken after calling handler */
+};
+
+extern char const _sys_sig_valid[NSIG];
+extern struct sig_descr const sig_info[NSIG];
+
+long _sys_p2t (FTIME t, FDATE d);
+void _sys_init_thread (thread_data *tp);
+void _sys_deliver_pending_signals (thread_data *tp);
+
+#if defined (__MT__)
+
+#define MAX_THREADS 1024
+
+/* This mutex semaphore protects the heap. */
+#ifdef _FMC_SHARED
+EXTERN _fmutex _sys_heap_fmutex;
+#endif
+EXTERN void *_sys_private_heap INIT (NULL);
+EXTERN thread_data *_sys_thread_table[MAX_THREADS];
+
+thread_data *_sys_thread (void);
+#define SYS_THREAD (_sys_thread ())
+
+#else /* !defined (_MT) */
+
+EXTERN thread_data _sys_thread_one;
+#define SYS_THREAD (&_sys_thread_one)
+
+#endif /* !defined (_MT) */
+
+#endif /* _OS2EMX_H */
+
+void _sys_set_errno (unsigned long rc);
+void _sys_get_clock (unsigned long *ms);
+ULONG _sys_expand_heap_obj_by (ULONG incr);
+ULONG _sys_expand_heap_by (ULONG incr, ULONG sbrk_model);
+ULONG _sys_shrink_heap_to (ULONG new_brk);
+ULONG _sys_shrink_heap_by (ULONG decr, ULONG sbrk_model);
+ULONG _sys_shrink_heap_obj_by (ULONG decr);
Index: trunk/src/emx/src/lib/sys/uflags.c
===================================================================
--- trunk/src/emx/src/lib/sys/uflags.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/uflags.c	(revision 18)
@@ -0,0 +1,12 @@
+/* sys/uflags.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include "syscalls.h"
+
+int __uflags (int mask, int new_flags)
+{
+  int ret;
+
+  ret = _sys_uflags;
+  _sys_uflags = (_sys_uflags & ~mask) | (new_flags & mask);
+  return ret;
+}
Index: trunk/src/emx/src/lib/sys/umask.c
===================================================================
--- trunk/src/emx/src/lib/sys/umask.c	(revision 18)
+++ trunk/src/emx/src/lib/sys/umask.c	(revision 18)
@@ -0,0 +1,14 @@
+/* sys/umask.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+#include "syscalls.h"
+
+
+int __umask (int pmode)
+{
+  int old;
+
+  old = _sys_umask;
+  _sys_umask = pmode;
+  return old;
+}
Index: trunk/src/emx/src/lib/termios/cfgetisp.c
===================================================================
--- trunk/src/emx/src/lib/termios/cfgetisp.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/cfgetisp.c	(revision 18)
@@ -0,0 +1,9 @@
+/* cfgetisp.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <sys/termio.h>         /* CBAUD */
+
+speed_t _cfgetispeed (const struct termios *ptermios)
+{
+  return ptermios->c_cflag & CBAUD;
+}
Index: trunk/src/emx/src/lib/termios/cfgetosp.c
===================================================================
--- trunk/src/emx/src/lib/termios/cfgetosp.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/cfgetosp.c	(revision 18)
@@ -0,0 +1,9 @@
+/* cfgetosp.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <sys/termio.h>         /* CBAUD */
+
+speed_t _cfgetospeed (const struct termios *ptermios)
+{
+  return ptermios->c_cflag & CBAUD;
+}
Index: trunk/src/emx/src/lib/termios/cfsetisp.c
===================================================================
--- trunk/src/emx/src/lib/termios/cfsetisp.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/cfsetisp.c	(revision 18)
@@ -0,0 +1,11 @@
+/* cfsetisp.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <errno.h>
+
+int _cfsetspeed (struct termios *ptermios, speed_t speed);
+
+int _cfsetispeed (struct termios *ptermios, speed_t speed)
+{
+  return _cfsetspeed (ptermios, speed);
+}
Index: trunk/src/emx/src/lib/termios/cfsetosp.c
===================================================================
--- trunk/src/emx/src/lib/termios/cfsetosp.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/cfsetosp.c	(revision 18)
@@ -0,0 +1,10 @@
+/* cfsetosp.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+
+int _cfsetspeed (struct termios *ptermios, speed_t speed);
+
+int _cfsetospeed (struct termios *ptermios, speed_t speed)
+{
+  return _cfsetspeed (ptermios, speed);
+}
Index: trunk/src/emx/src/lib/termios/cfsetspe.c
===================================================================
--- trunk/src/emx/src/lib/termios/cfsetspe.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/cfsetspe.c	(revision 18)
@@ -0,0 +1,19 @@
+/* cfsetspe.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <errno.h>
+#include <sys/termio.h>         /* CBAUD */
+
+int _cfsetspeed (struct termios *ptermios, speed_t speed)
+{
+  /* speed is always >= B0 as speed_t is unsigned and B0 is zero. */
+
+  if (speed > B38400)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  ptermios->c_cflag &= ~CBAUD;
+  ptermios->c_cflag |= speed & CBAUD;
+  return 0;
+}
Index: trunk/src/emx/src/lib/termios/makefile
===================================================================
--- trunk/src/emx/src/lib/termios/makefile	(revision 18)
+++ trunk/src/emx/src/lib/termios/makefile	(revision 18)
@@ -0,0 +1,25 @@
+#
+# /emx/src/lib/termios/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+cfgetisp.o: cfgetisp.c $(I)termios.h $(S)termio.h
+cfgetosp.o: cfgetosp.c $(I)termios.h $(S)termio.h
+cfsetisp.o: cfgetisp.c $(I)termios.h
+cfsetosp.o: cfsetosp.c $(I)termios.h
+cfsetspe.o: cfsetspe.c $(I)termios.h $(S)termio.h $(ERRNO)
+tcdrain.o:  tcdrain.c $(I)termios.h
+tcflow.o:   tcflow.c $(I)termios.h
+tcflush.o:  tcflush.c $(I)termios.h
+tcgetatt.o: tcgetatt.c $(I)termios.h
+tcgetpgr.o: tcgetpgr.c $(I)unistd.h $(S)types.h $(ERRNO)
+tcsendbr.o: tcsendbr.c $(I)termios.h
+tcsetatt.o: tcsetatt.c $(I)termios.h $(ERRNO)
+tcsetpgr.o: tcsetpgr.c $(I)unistd.h $(S)types.h $(ERRNO)
+
+$(DSTLIB):  cfgetisp.o cfgetosp.o cfsetisp.o cfsetosp.o cfsetspe.o \
+    tcdrain.o tcflow.o tcflush.o \
+    tcgetatt.o tcgetpgr.o tcsendbr.o tcsetatt.o tcsetpgr.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/termios/tcdrain.c
===================================================================
--- trunk/src/emx/src/lib/termios/tcdrain.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/tcdrain.c	(revision 18)
@@ -0,0 +1,9 @@
+/* tcdrain.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int _tcdrain (int handle)
+{
+  return _ioctl (handle, TCSBRK, 1);
+}
Index: trunk/src/emx/src/lib/termios/tcflow.c
===================================================================
--- trunk/src/emx/src/lib/termios/tcflow.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/tcflow.c	(revision 18)
@@ -0,0 +1,9 @@
+/* tcflow.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int _tcflow (int handle, int action)
+{
+  return _ioctl (handle, TCXONC, action);
+}
Index: trunk/src/emx/src/lib/termios/tcflush.c
===================================================================
--- trunk/src/emx/src/lib/termios/tcflush.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/tcflush.c	(revision 18)
@@ -0,0 +1,9 @@
+/* tcflush.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int _tcflush (int handle, int queue)
+{
+  return _ioctl (handle, TCFLSH, queue);
+}
Index: trunk/src/emx/src/lib/termios/tcgetatt.c
===================================================================
--- trunk/src/emx/src/lib/termios/tcgetatt.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/tcgetatt.c	(revision 18)
@@ -0,0 +1,9 @@
+/* tcgetatt.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <sys/ioctl.h>
+
+int _tcgetattr (int handle, struct termios *ptermios)
+{
+  return _ioctl (handle, _TCGA, ptermios);
+}
Index: trunk/src/emx/src/lib/termios/tcgetpgr.c
===================================================================
--- trunk/src/emx/src/lib/termios/tcgetpgr.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/tcgetpgr.c	(revision 18)
@@ -0,0 +1,11 @@
+/* tcgetpgr.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+
+pid_t _tcgetpgrp (int fd)
+{
+  errno = ENOSYS;
+  return -1;
+}
Index: trunk/src/emx/src/lib/termios/tcsendbr.c
===================================================================
--- trunk/src/emx/src/lib/termios/tcsendbr.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/tcsendbr.c	(revision 18)
@@ -0,0 +1,10 @@
+/* tcsendbr.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+int _tcsendbreak (int handle, int duration)
+{
+  return _ioctl (handle, TCSBRK, duration);
+}
Index: trunk/src/emx/src/lib/termios/tcsetatt.c
===================================================================
--- trunk/src/emx/src/lib/termios/tcsetatt.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/tcsetatt.c	(revision 18)
@@ -0,0 +1,27 @@
+/* tcsetatt.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <termios.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+int _tcsetattr (int handle, int options, const struct termios *ptermios)
+{
+  int request;
+
+  switch (options)
+    {
+    case TCSANOW:
+      request = _TCSANOW;
+      break;
+    case TCSADRAIN:
+      request = _TCSADRAIN;
+      break;
+    case TCSAFLUSH:
+      request = _TCSAFLUSH;
+      break;
+    default:
+      errno = EINVAL;
+      return -1;
+    }
+  return _ioctl (handle, request, ptermios);
+}
Index: trunk/src/emx/src/lib/termios/tcsetpgr.c
===================================================================
--- trunk/src/emx/src/lib/termios/tcsetpgr.c	(revision 18)
+++ trunk/src/emx/src/lib/termios/tcsetpgr.c	(revision 18)
@@ -0,0 +1,11 @@
+/* tcsetpgr.c (emx+gcc) -- Copyright (c) 1994-1995 by Eberhard Mattes */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+
+int _tcsetpgrp (int fd, pid_t pgrp)
+{
+  errno = ENOSYS;
+  return -1;
+}
Index: trunk/src/emx/src/lib/time/asctime.c
===================================================================
--- trunk/src/emx/src/lib/time/asctime.c	(revision 18)
+++ trunk/src/emx/src/lib/time/asctime.c	(revision 18)
@@ -0,0 +1,45 @@
+/* asctime.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <string.h>
+#include <time.h>
+#include <emx/thread.h>
+
+static char const months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+static char const wdays[] = "SunMonTueWedThuFriSat";
+
+#define digit(i) (char)(((i)%10)+'0')
+
+char *asctime (const struct tm *t)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread();
+#define result (tp->_th_asctime_buf)
+#else
+  static char result[26];
+#endif
+
+  memcpy (result+0, wdays+t->tm_wday*3, 3);
+  result[3] = ' ';
+  memcpy (result+4, months+t->tm_mon*3, 3);
+  result[7] = ' ';
+  result[8] = digit (t->tm_mday / 10);
+  result[9] = digit (t->tm_mday / 1);
+  result[10] = ' ';
+  result[11] = digit (t->tm_hour / 10);
+  result[12] = digit (t->tm_hour / 1);
+  result[13] = ':';
+  result[14] = digit (t->tm_min / 10);
+  result[15] = digit (t->tm_min / 1);
+  result[16] = ':';
+  result[17] = digit (t->tm_sec / 10);
+  result[18] = digit (t->tm_sec / 1);
+  result[19] = ' ';
+  result[20] = digit ((t->tm_year+1900) / 1000);
+  result[21] = digit ((t->tm_year+1900) / 100);
+  result[22] = digit ((t->tm_year+1900) / 10);
+  result[23] = digit ((t->tm_year+1900) / 1);
+  result[24] = '\n';
+  result[25] = '\0';
+  if (result[8] == '0') result[8] = ' ';
+  return result;
+}
Index: trunk/src/emx/src/lib/time/clock.c
===================================================================
--- trunk/src/emx/src/lib/time/clock.c	(revision 18)
+++ trunk/src/emx/src/lib/time/clock.c	(revision 18)
@@ -0,0 +1,13 @@
+/* clock.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <time.h>
+#include <emx/syscalls.h>
+
+#if CLOCKS_PER_SEC != 100
+emx must be changed!
+#endif
+
+clock_t clock (void)
+{
+  return (clock_t)__clock ();
+}
Index: trunk/src/emx/src/lib/time/ctime.c
===================================================================
--- trunk/src/emx/src/lib/time/ctime.c	(revision 18)
+++ trunk/src/emx/src/lib/time/ctime.c	(revision 18)
@@ -0,0 +1,15 @@
+/* ctime.c (emx+gcc) -- Copyright (c) 1990-1999 by Eberhard Mattes */
+
+#include <time.h>
+#include <emx/time.h>
+
+char *ctime (const time_t *t)
+{
+  struct tm tmp, *x;
+
+  x = _localtime (&tmp, t);
+  if (x == NULL)
+    return NULL;
+  else
+    return asctime (x);
+}
Index: trunk/src/emx/src/lib/time/difftime.c
===================================================================
--- trunk/src/emx/src/lib/time/difftime.c	(revision 18)
+++ trunk/src/emx/src/lib/time/difftime.c	(revision 18)
@@ -0,0 +1,8 @@
+/* difftime.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <time.h>
+
+double difftime (time_t t1, time_t t0)
+{
+  return (double)t1 - (double)t0;
+}
Index: trunk/src/emx/src/lib/time/ftime.c
===================================================================
--- trunk/src/emx/src/lib/time/ftime.c	(revision 18)
+++ trunk/src/emx/src/lib/time/ftime.c	(revision 18)
@@ -0,0 +1,17 @@
+/* ftime.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <sys/timeb.h>
+#include <time.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+void _ftime (struct timeb *ptr)
+{
+  time_t t_loc;
+
+  if (!_tzset_flag) _tzset ();
+  __ftime (ptr);
+  t_loc = ptr->time;
+  ptr->dstflag = _loc2gmt (&ptr->time, -1);
+  ptr->timezone = (int)(ptr->time - t_loc) / 60;
+}
Index: trunk/src/emx/src/lib/time/gettimeo.c
===================================================================
--- trunk/src/emx/src/lib/time/gettimeo.c	(revision 18)
+++ trunk/src/emx/src/lib/time/gettimeo.c	(revision 18)
@@ -0,0 +1,30 @@
+/* gettimeo.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+#include <sys/timeb.h>
+#include <time.h>
+#include <sys/time.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+int _gettimeofday (struct timeval *tp, struct timezone *tzp)
+{
+  struct timeb tb;
+  time_t t_loc;
+  int dst;
+
+  if (!_tzset_flag) _tzset ();
+  __ftime (&tb);
+  t_loc = tb.time;
+  dst = _loc2gmt (&tb.time, -1);
+  if (tp != NULL)
+    {
+      tp->tv_sec = tb.time;
+      tp->tv_usec = tb.millitm * 1000;
+    }
+  if (tzp != NULL)
+    {
+      tzp->tz_minuteswest = (int)(tb.time - t_loc) / 60;
+      tzp->tz_dsttime = dst;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/lib/time/gmtime.c
===================================================================
--- trunk/src/emx/src/lib/time/gmtime.c	(revision 18)
+++ trunk/src/emx/src/lib/time/gmtime.c	(revision 18)
@@ -0,0 +1,65 @@
+/* gmtime.c (emx+gcc) -- Copyright (c) 1990-1999 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <time.h>
+#include <emx/thread.h>
+#include <emx/time.h>
+
+struct tm *gmtime (const time_t *t)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#define result (tp->_th_gmtime_buf)
+#else
+  static struct tm result;
+#endif
+  return _gmtime (&result, t);
+}
+
+struct tm *_gmtime (struct tm *dst, const time_t *t)
+{
+  time_t t0;
+  _uldiv_t q;
+
+  t0 = *t;
+
+  q = _uldiv (t0, 60); dst->tm_sec = q.rem; t0 = q.quot;
+  q = _uldiv (t0, 60); dst->tm_min = q.rem; t0 = q.quot;
+  q = _uldiv (t0, 24); dst->tm_hour = q.rem; t0 = q.quot;
+  dst->tm_wday = (t0+4) % 7;  /* 01-Jan-1970 was Thursday, ie, 4 */
+
+  {
+    int lo, hi, i;
+
+    /* Find an i such that _year_day[i] <= t0 < _year_day[i+1]. */
+
+    lo = 0; hi = _YEARS - 1;
+    for (;;)
+      {
+        i = (lo + hi) / 2;
+        if (_year_day[i] > (int)t0)
+          hi = i - 1;
+        else if (_year_day[i+1] <= (int)t0)
+          lo = i + 1;
+        else
+          break;
+      }
+    dst->tm_year = i + 70;
+    t0 -= _year_day[i];
+    dst->tm_yday = t0;
+  }
+
+  {
+    int i;
+    const int *p;
+
+    p = (_leap_year (dst->tm_year + 1900)
+         ? _month_day_leap : _month_day_non_leap);
+    for (i = 0; (int)t0 >= p[i+1]; ++i)
+      ;
+    dst->tm_mon = i;
+    dst->tm_mday = t0 - p[i] + 1;
+  }
+  dst->tm_isdst = -1;
+  return dst;
+}
Index: trunk/src/emx/src/lib/time/gmtloc.c
===================================================================
--- trunk/src/emx/src/lib/time/gmtloc.c	(revision 18)
+++ trunk/src/emx/src/lib/time/gmtloc.c	(revision 18)
@@ -0,0 +1,264 @@
+/* gmtloc.c (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes */
+
+#include <time.h>
+#include <limits.h>
+#include <assert.h>
+#include <emx/time.h>
+
+/* Return true iff adding A to T does not overflow time_t. */
+
+#define ADD_OK(t,a) \
+    ((a) < 0 ? (t) >= (time_t)(-(a)) \
+   : (a) > 0 ? (t) <= TIME_T_MAX - (a) \
+   : 1)
+
+struct _dstswitch
+{
+  time_t time;                  /* UTC */
+  int shift;
+};
+
+static struct _dstswitch _dstsw[2*_YEARS+2] = {{0,0}, {TIME_T_MAX, 0}};
+static int _dstsw_count = 2;
+
+
+/* Compute the day of the year on which DST switching occurs. */
+
+static int switch_day (int month, int week, int day, int ywday,
+                       const int *month_table)
+{
+  int d, wday;
+
+  if (week > 0)
+    {
+      d = month_table[month-1];
+      wday = (d + ywday) % 7;   /* Wekkday of the first day the month */
+      if (wday != 0)
+        d += 7 - wday;          /* d is the first Sunday of the month */
+      d += day;                 /* First DAY in `first week' */
+      d += 7 * (week - 1);
+    }
+  else if (week < 0)
+    {
+      if (month == 12)
+        d = month_table[11] + 31 - 1;
+      else
+        d = month_table[month] - 1;
+      wday = (d + ywday) % 7;   /* Weekday of the last day of the month */
+      if (wday != 0)
+        d -= wday;              /* d is the last Sunday of the month */
+      d += day;                 /* First DAY in `last week' */
+      d -= 7 * (week + 1);
+    }
+  else
+    d = month_table[month-1] + day - 1;
+  return d;
+}
+
+
+void _compute_dst_table (void)
+{
+  int y, i, ywday, d_year, d_start, d_end;
+  const int *month_table;
+  time_t t_year, t_start, t_end;
+
+  if (!_tzi.dst)
+    {
+      _dstsw[0].time = 0;
+      _dstsw[0].shift = 0;
+      _dstsw[1].time = TIME_T_MAX;
+      _dstsw[1].shift = 0;
+      _dstsw_count = 2;
+      return;
+    }
+
+  i = 0;
+  for (y = 0; _year_day[y] != INT_MAX; ++y)
+    {
+      month_table = (_leap_year (y + 1970)
+                     ? _month_day_leap : _month_day_non_leap);
+      d_year = _year_day[y];
+      ywday = d_year + 4;       /* 01-Jan-1970 was a Thursday, ie, 4 */
+      t_year = d_year * 24 * 60 * 60;
+
+      d_start = switch_day (_tzi.sm, _tzi.sw, _tzi.sd, ywday, month_table);
+      t_start = d_start * 24 * 60 * 60 + _tzi.st + _tzi.tz;
+      if (ADD_OK (t_start, t_year))
+        t_start += t_year;
+      else
+        t_start = TIME_T_MAX;
+
+      d_end = switch_day (_tzi.em, _tzi.ew, _tzi.ed, ywday, month_table);
+      t_end = d_end * 24 * 60 * 60 + _tzi.et + _tzi.tz - _tzi.shift;
+      if (ADD_OK (t_end, t_year))
+        t_end += t_year;
+      else
+        t_end = TIME_T_MAX;
+
+      if (d_start < d_end || (d_start == d_end && _tzi.st <= _tzi.et))
+        {
+          /* Northern hemisphere. */
+
+          if (i == 0)
+            {
+              _dstsw[i].time = 0;
+              _dstsw[i].shift = 0;
+              ++i;
+            }
+          _dstsw[i].time = t_start;
+          _dstsw[i].shift = _tzi.shift;
+          ++i;
+          _dstsw[i].time = t_end;
+          _dstsw[i].shift = 0;
+          ++i;
+        }
+      else
+        {
+          /* Southern hemisphere. */
+
+          if (i == 0)
+            {
+              _dstsw[i].time = 0;
+              _dstsw[i].shift = _tzi.shift;
+              ++i;
+            }
+          _dstsw[i].time = t_end;
+          _dstsw[i].shift = 0;
+          ++i;
+          _dstsw[i].time = t_start;
+          _dstsw[i].shift = _tzi.shift;
+          ++i;
+        }
+    }
+  _dstsw[i].time = TIME_T_MAX;
+  _dstsw[i].shift = TIME_T_MAX;
+  ++i;
+  _dstsw_count = i;
+
+  assert (_dstsw_count == sizeof (_dstsw) / sizeof (_dstsw[0]));
+}
+
+
+static struct _dstswitch *find_switch (time_t t)
+{
+  int lo, hi, i;
+
+  if (t == TIME_T_MAX)
+    {
+      i = _dstsw_count - 2;
+      assert (_dstsw[i].time <= t);
+      assert (t <= _dstsw[i+1].time);
+    }
+  else
+    {
+      lo = 0; hi = _dstsw_count - 2;
+      for (;;)
+        {
+          i = (lo + hi) / 2;
+          if (_dstsw[i].time > t)
+            hi = i - 1;
+          else if (_dstsw[i+1].time <= t)
+            lo = i + 1;
+          else
+            break;
+        }
+      assert (_dstsw[i].time <= t);
+      assert (t < _dstsw[i+1].time);
+    }
+  return &_dstsw[i];
+}
+
+
+/* Note that this function returns -1 on error.  Previously, it
+   returned -1 if it could not determine whether daylight saving
+   applies or not. */
+
+int _gmt2loc (time_t *p)
+{
+  struct _dstswitch *sw;
+
+  sw = find_switch (*p);
+  if (!ADD_OK (*p, _tzi.tz - sw->shift))
+    return -1;
+  *p -= _tzi.tz - sw->shift;
+  return sw->shift != 0;
+}
+
+
+/* Note that this function returns -1 on error (overflow).
+   Previously, it returned -1 if it could not determine whether
+   daylight saving applies or not. */
+
+int _loc2gmt (time_t *p, int is_dst)
+{
+  time_t x;
+  struct _dstswitch *sw;
+  int count;
+
+  if (is_dst > 0)
+    {
+      /* Our caller says that *P is specified as DST.  Compute UTC
+         from *P, assuming that daylight saving applies. */
+
+      if (!ADD_OK (*p, _tzi.tz - _tzi.shift))
+        return -1;
+      x = *p + _tzi.tz - _tzi.shift;
+      sw = find_switch (x);
+      *p = x;
+      return sw->shift != 0;
+    }
+  else if (is_dst == 0)
+    {
+      /* Our caller says that *P is specified as standard time.
+         Compute UTC from *P, assuming that daylight saving does not
+         apply. */
+
+      if (!ADD_OK (*p, _tzi.tz))
+        return -1;
+      x = *p + _tzi.tz;
+      sw = find_switch (x);
+      *p = x;
+      return sw->shift != 0;
+    }
+  else
+    {
+      /* Our caller does not know whether *P is specified as DST or
+         standard time.  Try to find out.  First try DST. */
+
+      count = 0;
+      if (ADD_OK (*p, _tzi.tz - _tzi.shift))
+        {
+          x = *p + _tzi.tz - _tzi.shift;
+          sw = find_switch (x);
+          if (sw->shift != 0)
+            {
+              *p = x;
+              return 1;         /* DST */
+            }
+          ++count;
+        }
+
+      if (ADD_OK (*p, _tzi.tz))
+        {
+          x = *p + _tzi.tz;
+          sw = find_switch (x);
+          if (sw->shift == 0)
+            {
+              *p = x;
+              return 0;         /* Not DST */
+            }
+          ++count;
+        }
+
+      if (count != 2)
+        return -1;              /* Overflow */
+
+      /* Assume that DST does not apply in the gap.  This makes moving
+         into the gap from below work, but breaks moving into the gap
+         from above.  The advantage of this choice is that ftime()
+         works correctly in the gap if the clock is not adjusted. */
+
+      *p += _tzi.tz;
+      return 0;                 /* Not DST */
+    }
+}
Index: trunk/src/emx/src/lib/time/localtim.c
===================================================================
--- trunk/src/emx/src/lib/time/localtim.c	(revision 18)
+++ trunk/src/emx/src/lib/time/localtim.c	(revision 18)
@@ -0,0 +1,30 @@
+/* localtim.c (emx+gcc) -- Copyright (c) 1990-1999 by Eberhard Mattes */
+
+#include <time.h>
+#include <emx/thread.h>
+#include <emx/time.h>
+
+struct tm *localtime (const time_t *t)
+{
+#if defined (__MT__)
+  struct _thread *tp = _thread ();
+#define result (tp->_th_gmtime_buf)
+#else
+  static struct tm result;
+#endif
+  return _localtime (&result, t);
+}
+
+struct tm *_localtime (struct tm *dst, const time_t *t)
+{
+  time_t lt;
+  int isdst;
+  struct tm *p;
+
+  if (!_tzset_flag) _tzset ();
+  lt = *t;
+  isdst = _gmt2loc (&lt);
+  p = _gmtime (dst, &lt);
+  p->tm_isdst = isdst;
+  return p;
+}
Index: trunk/src/emx/src/lib/time/makefile
===================================================================
--- trunk/src/emx/src/lib/time/makefile	(revision 18)
+++ trunk/src/emx/src/lib/time/makefile	(revision 18)
@@ -0,0 +1,35 @@
+#
+# /emx/src/lib/time/makefile
+#
+.INCLUDE: /emx/src/lib/libc.mak
+
+local: ;
+
+asctime.o: asctime.c $(I)time.h $(I)string.h $(I)emx/thread.h
+clock.o: clock.c $(I)emx/syscalls.h
+ctime.o: ctime.c $(I)time.h $(I)emx/time.h
+difftime.o: difftime.c $(I)time.h
+ftime.o: ftime.c $(I)emx/syscalls.h $(I)sys/timeb.h $(I)time.h $(I)emx/time.h
+gettimeo.o: gettimeo.c $(I)emx/syscalls.h $(I)sys/time.h $(I)time.h \
+		$(I)sys/timeb.h $(I)emx/time.h
+gmtime.o: gmtime.c $(I)time.h $(I)stdlib.h $(I)emx/thread.h $(I)emx/time.h
+gmtloc.o: gmtloc.c $(I)time.h $(I)limits.h $(I)assert.h $(I)emx/time.h
+localtim.o: localtim.c $(I)time.h $(I)emx/thread.h $(I)emx/time.h
+mktime.o: mktime.c $(I)time.h $(I)limits.h $(I)emx/time.h
+settimeo.o: settimeo.c $(I)emx/syscalls.h $(I)sys/time.h $(I)time.h \
+		$(ERRNO) $(I)emx/time.h
+strftime.o: strftime.c $(I)time.h $(I)stdlib.h $(I)limits.h $(I)string.h \
+		$(I)emx/locale.h $(I)emx/time.h
+strptime.o: strptime.c $(I)time.h $(I)stdlib.h $(I)ctype.h $(I)string.h \
+		$(I)emx/locale.h
+time.o: time.c $(I)sys/timeb.h $(I)time.h
+times.o: times.c $(I)time.h $(I)sys/time.h $(I)sys/times.h
+timetabs.o: timetabs.c $(I)limits.h $(I)emx/time.h
+tzset.o: tzset.c $(I)time.h $(I)string.h $(I)stdlib.h $(I)sys/timeb.h \
+		$(I)emx/time.h $(I)emx/syscalls.h
+tzsetfla.o: tzsetfla.c
+
+$(DSTLIB): asctime.o clock.o ctime.o difftime.o ftime.o gettimeo.o gmtime.o \
+    gmtloc.o localtim.o mktime.o settimeo.o strftime.o strptime.o time.o \
+    times.o timetabs.o tzset.o tzsetfla.o
+	$(AR) r $(DSTLIB) *.o
Index: trunk/src/emx/src/lib/time/mktime.c
===================================================================
--- trunk/src/emx/src/lib/time/mktime.c	(revision 18)
+++ trunk/src/emx/src/lib/time/mktime.c	(revision 18)
@@ -0,0 +1,86 @@
+/* mktime.c (emx+gcc) -- Copyright (c) 1990-1999 by Eberhard Mattes */
+
+#include <time.h>
+#include <limits.h>
+#include <emx/time.h>
+
+time_t mktime (struct tm *t)
+{
+  time_t t1, t2;
+  struct tm tmp;
+  int dst;
+
+  if (!_tzset_flag) _tzset ();
+
+  /* _mktime() requires that tm_mon is in range.  The other members
+     are not restricted. */
+
+  if (t->tm_mon < 0)
+    {
+      /* Avoid applying the `/' and `%' operators to negative numbers
+         as the results are implementation-defined for negative
+         numbers. */
+
+      t->tm_year -= 1 + ((-t->tm_mon) / 12);
+      t->tm_mon = 12 - ((-t->tm_mon) % 12);
+    }
+  if (t->tm_mon >= 12)
+    {
+      t->tm_year += (t->tm_mon / 12);
+      t->tm_mon %= 12;
+    }
+
+  t1 = (time_t)_mktime (t);
+  if (t1 == (time_t)-1)
+    return (time_t)-1;
+  dst = _loc2gmt (&t1, t->tm_isdst);
+  if (dst == -1)
+    return (time_t)-1;
+  t2 = t1;
+  dst = _gmt2loc (&t2);
+  if (dst == -1)
+    return (time_t)-1;
+  
+  if (_gmtime (&tmp, &t2) == NULL)
+    return (time_t)-1;
+  *t = tmp;
+  t->tm_isdst = dst;
+  return t1;
+}
+
+
+/* year >= 1582, 1 <= month <= 12, 1 <= day <= 31 */
+
+int _day (int year, int month, int day)
+{
+  int result;
+
+  if (year < 1582 || year >= INT_MAX / 365)
+    return -1;
+  result = 365 * year + day + 31 * (month - 1);
+  if (month <= 2)
+    --year;
+  else
+    result -= (4 * month + 23) / 10;
+  result += year / 4 - (3 * (year / 100 + 1)) / 4;
+  return result;
+}
+
+
+unsigned long _mktime (struct tm *t)
+{
+  long x;
+  long long r;
+
+  x = _day (t->tm_year+1900, t->tm_mon+1, t->tm_mday);
+  /* 719528 = day (1970, 1, 1) */
+  r = (long long)(x - 719528) * 24 * 60 * 60;
+
+  /* This expression is not checked for overflow. */
+  x = t->tm_sec + 60*t->tm_min + 60*60*t->tm_hour;
+
+  r += x;
+  if (r < 0 || r > ULONG_MAX || r == (time_t)-1)
+    return (time_t)-1;
+  return (time_t)r;
+}
Index: trunk/src/emx/src/lib/time/settimeo.c
===================================================================
--- trunk/src/emx/src/lib/time/settimeo.c	(revision 18)
+++ trunk/src/emx/src/lib/time/settimeo.c	(revision 18)
@@ -0,0 +1,24 @@
+/* settimeo.c (emx+gcc) -- Copyright (c) 1995-1996 by Eberhard Mattes */
+
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+int _settimeofday (const struct timeval *tp, const struct timezone *tzp)
+{
+  struct timeval local;
+  time_t t;
+
+  if (tzp != NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (!_tzset_flag) _tzset ();
+  t = tp->tv_sec;
+  local.tv_sec = _gmt2loc (&t);
+  local.tv_usec = tp->tv_usec;
+  return __settime (tp);
+}
Index: trunk/src/emx/src/lib/time/strftime.c
===================================================================
--- trunk/src/emx/src/lib/time/strftime.c	(revision 18)
+++ trunk/src/emx/src/lib/time/strftime.c	(revision 18)
@@ -0,0 +1,247 @@
+/* strftime.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <limits.h>
+#include <emx/locale.h>
+#include <emx/time.h>
+
+static int ins (char *string, size_t *n, size_t size, const char *s,
+    size_t len);
+static int num2 (char *string, size_t *n, size_t size, int x);
+static int num3 (char *string, size_t *n, size_t size, int x);
+static int week (const struct tm *t, int first);
+
+#define INS(STR,LEN) if (!ins (string, &n, size, (STR), (LEN))) return 0;
+#define NUM2(X) if (!num2 (string, &n, size, (X))) return 0;
+#define NUM3(X) if (!num3 (string, &n, size, (X))) return 0;
+#define FMT(F) \
+    i = strftime (string + n, size - n, (F), t); \
+    if (i == 0) \
+      return 0; \
+    else \
+      n += i;
+#define CHR(C) \
+    if (n < size) \
+      string[n++] = C; \
+    else \
+      return 0;
+
+
+static int ins (char *string, size_t *n, size_t size, const char *s,
+                size_t len)
+{
+  size_t i;
+
+  i = *n;
+  if (len < size - i)
+    {
+      memcpy (string + i, s, len);
+      *n += len;
+      return 1;
+    }
+  else
+    return 0;
+}
+
+
+static int num2 (char *string, size_t *n, size_t size, int x)
+{
+  int i;
+
+  i = *n;
+  if (2 < size - i)
+    {
+      string[i++] = (char)('0' + (x / 10) % 10);
+      string[i++] = (char)('0' + (x % 10));
+      *n = i;
+      return 1;
+    }
+  else
+    return 0;
+}
+
+
+static int num3 (char *string, size_t *n, size_t size, int x)
+{
+  int i;
+
+  i = *n;
+  if (3 < size - i)
+    {
+      string[i++] = (char)('0' + (x / 100) % 10);
+      string[i++] = (char)('0' + (x / 10) % 10);
+      string[i++] = (char)('0' + (x % 10));
+      *n = i;
+      return 1;
+    }
+  else
+    return 0;
+}
+
+
+static int week (const struct tm *t, int first)
+{
+  int wd, tmp;
+
+  wd = t->tm_wday - first;    /* wd = relative day in week (w.r.t. first) */
+  if (wd < 0) wd += 7;
+  tmp = t->tm_yday - wd;      /* Start of current week */
+  if (tmp <= 0) return 0;     /* In partial first week */
+  return (tmp + 6) / 7;       /* Week number */
+}
+
+
+size_t strftime (char *string, size_t size, const char *format,
+                 const struct tm *t)
+{
+  size_t i, n;
+  char *p, tmp[40];
+  unsigned char c;
+  int mbn, shift;
+
+  if (!_tzset_flag) _tzset ();
+  shift = 0; n = 0;
+  while ((c = *format) != 0)
+    {
+      if (c == '%')
+        {
+          ++format; p = NULL;
+          switch (*format)
+            {
+            case 0:
+            case '%':
+              CHR ('%');
+              if (*format == 0)
+                --format;
+              break;
+            case 'a':
+              p = _cur_lcf_time.wdays1[t->tm_wday];
+              INS (p, strlen (p));
+              break;
+            case 'A':
+              p = _cur_lcf_time.wdays2[t->tm_wday];
+              INS (p, strlen (p));
+              break;
+            case 'b':
+            case 'h':
+              p = _cur_lcf_time.months1[t->tm_mon];
+              INS (p, strlen (p));
+              break;
+            case 'B':
+              p = _cur_lcf_time.months2[t->tm_mon];
+              INS (p, strlen (p));
+              break;
+            case 'c':
+              FMT (_cur_lcf_time.date_time_fmt);
+              break;
+            case 'd':
+              NUM2 (t->tm_mday);
+              break;
+            case 'D':
+              FMT ("%m/%d/%y");
+              break;
+            case 'e':
+              NUM2 (t->tm_mday);
+              if (string[n-2] == '0')
+                string[n-2] = ' ';
+              break;
+            case 'H':
+              NUM2 (t->tm_hour);
+              break;
+            case 'I':
+              NUM2 ((t->tm_hour + 11) % 12 + 1);
+              break;
+            case 'j':
+              NUM3 (t->tm_yday + 1);
+              break;
+            case 'm':
+              NUM2 (t->tm_mon + 1);
+              break;
+            case 'M':
+              NUM2 (t->tm_min);
+              break;
+            case 'n':
+              CHR ('\n');
+              break;
+            case 'p':
+              p = (t->tm_hour >= 12 ? _cur_lcf_time.pm : _cur_lcf_time.am);
+              INS (p, strlen (p));
+              break;
+            case 'r':
+              FMT ("%I:%M:%S %p");
+              break;
+            case 'S':
+              NUM2 (t->tm_sec);
+              break;
+            case 't':
+              CHR ('\t');
+              break;
+            case 'T':
+              FMT ("%H:%M:%S");
+              break;
+            case 'U':
+              NUM2 (week (t, 0));
+              break;
+            case 'w':
+              NUM2 (t->tm_wday);
+              break;
+            case 'W':
+              NUM2 (week (t, 1));
+              break;
+            case 'x':
+              FMT (_cur_lcf_time.date_fmt);
+              break;
+            case 'X':
+              FMT (_cur_lcf_time.time_fmt);
+              break;
+            case 'y':
+              NUM2 (t->tm_year % 100);
+              break;
+            case 'Y':
+              p = _itoa (t->tm_year + 1900, tmp, 10);
+              INS (p, strlen (p));
+              break;
+            case 'Z':
+              if (t->tm_isdst >= 0)
+                {
+                  p = _tzname[(t->tm_isdst ? 1 : 0)];
+                  INS (p, strlen (p));
+                }
+              break;
+            default:
+              break;
+            }
+        }
+      else if (c <= 127 || _cur_mbyte.mode == _MB_8BITS)
+        {
+          if (n < size)
+            string[n++] = c;
+          else
+            return 0;
+        }
+      else
+        {
+          mbn = _mbtowc (NULL, format, MB_LEN_MAX, &shift);
+          if (mbn < 1)
+            mbn = 1;
+          if (n + mbn > size)
+            return 0;
+          while (mbn > 0)
+            {
+              string[n++] = *format++;
+              --mbn;
+            }
+          --format;
+        }
+      ++format;
+    }
+  if (n < size)
+    {
+      string[n] = 0;
+      return n;
+    }
+  else
+    return 0;
+}
Index: trunk/src/emx/src/lib/time/strptime.c
===================================================================
--- trunk/src/emx/src/lib/time/strptime.c	(revision 18)
+++ trunk/src/emx/src/lib/time/strptime.c	(revision 18)
@@ -0,0 +1,271 @@
+/* strptime.c (emx+gcc) -- Copyright (c) 1994-1998 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <emx/locale.h>
+
+#define RECURSE(FMT)  parse_fmt (s, FMT, tm)
+#define NUMBER(DST,MIN,MAX,ADD)  parse_number (s, DST, MIN, MAX, ADD)
+#define STRING(STR)  parse_string (s, STR)
+#define TABLE(DST,TAB,N)  parse_table (s, DST, TAB, N)
+
+static const unsigned char *parse_number (const unsigned char *s, int *dst,
+                                          int min, int max, int add)
+{
+  int n;
+
+  while (*s != 0 && isspace (*s))
+    ++s;
+  if (*s == 0 || !isdigit (*s))
+    return NULL;
+  n = 0;
+  while (isdigit (*s))
+    n = n * 10 + (*s++ - '0');  /* TODO: check for overflow */
+  if (n < min || (max >= 0 && n > max))
+    return NULL;
+  *dst = n + add;
+  return s;
+}
+
+
+static const unsigned char *parse_string (const unsigned char *s,
+                                          const char *str)
+{
+  size_t len;
+
+  while (*s != 0 && isspace (*s))
+    ++s;
+  len = strlen (str);
+  if (len == 0 || _strnicmp (s, str, len) != 0)
+    return NULL;
+  return s + len;
+}
+
+
+static const unsigned char *parse_table (const unsigned char *s, int *dst,
+                                         char **tab, int n)
+{
+  int i;
+  size_t len;
+
+  while (*s != 0 && isspace (*s))
+    ++s;
+  for (i = 0; i < n; ++i)
+    {
+      len = strlen (tab[i]);
+      if (_strnicmp (s, tab[i], len) == 0)
+        {
+          *dst = i;
+          return s + len;
+        }
+    }
+  return NULL;
+}
+
+
+static const unsigned char *parse_fmt (const unsigned char *s,
+                                       const unsigned char *f, struct tm *tm)
+{
+  const unsigned char *t;
+  int week = -1;
+
+  while (*f != 0)
+    {
+      if (isspace (*f))
+        {
+          while (*s != 0 && isspace (*s))
+            ++s;
+          ++f;
+        }
+      else if (*f != '%')
+        {
+          if (*s != *f)
+            return NULL;
+          ++s; ++f;
+        }
+      else
+        {
+          ++f;
+          switch (*f++)
+            {
+            case 0:
+              if (*s != '%')
+                return NULL;
+              return s + 1;
+              break;
+
+            case '%':
+              if (*s != '%')
+                return NULL;
+              ++s;
+              break;
+
+            case 'a':
+              s = TABLE (&tm->tm_wday, _cur_lcf_time.wdays1, 7);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'A':
+              s = TABLE (&tm->tm_wday, _cur_lcf_time.wdays2, 7);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'b':
+            case 'h':
+              s = TABLE (&tm->tm_mon, _cur_lcf_time.months1, 12);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'B':
+              s = TABLE (&tm->tm_mon, _cur_lcf_time.months2, 12);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'c':
+              s = RECURSE (_cur_lcf_time.date_time_fmt);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'C':
+              s = RECURSE ("%x %X");
+              if (s == NULL) return NULL;
+              break;
+
+            case 'd':
+            case 'e':
+              s = NUMBER (&tm->tm_mday, 1, 31, 0);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'D':
+              s = RECURSE ("%m/%d/%y");
+              if (s == NULL) return NULL;
+              break;
+
+            case 'H':
+            case 'k':
+              s = NUMBER (&tm->tm_hour, 0, 23, 0);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'I':
+            case 'l':
+              s = NUMBER (&tm->tm_hour, 1, 12, 0);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'j':
+              s = NUMBER (&tm->tm_yday, 1, 366, -1);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'm':
+              s = NUMBER (&tm->tm_mon, 1, 12, -1);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'M':
+              s = NUMBER (&tm->tm_min, 0, 59, 0);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'n':
+              if (*s != '\n')
+                return NULL;
+              ++s;
+              break;
+
+            case 'p':
+              if (tm->tm_hour < 1 || tm->tm_hour > 12)
+                return NULL;
+              if ((t = STRING (_cur_lcf_time.am)) != NULL)
+                {
+                  if (tm->tm_hour == 12)
+                    tm->tm_hour = 0;
+                }
+              else if ((t = STRING (_cur_lcf_time.pm)) != NULL)
+                {
+                  if (tm->tm_hour != 12)
+                    tm->tm_hour += 12;
+                }
+              else
+                return NULL;
+              s = t;
+              break;
+
+            case 'r':
+              s = RECURSE ("%I:%M:%S %p");
+              if (s == NULL) return NULL;
+              break;
+
+            case 'R':
+              s = RECURSE ("%H:%M");
+              if (s == NULL) return NULL;
+              break;
+
+            case 'S':
+              s = NUMBER (&tm->tm_sec, 0, 61, 0);
+              if (s == NULL) return NULL;
+              break;
+
+            case 't':
+              if (*s != '\t')
+                return NULL;
+              ++s;
+              break;
+
+            case 'T':
+              s = RECURSE ("%H:%M:%S");
+              if (s == NULL) return NULL;
+              break;
+
+            case 'w':
+              s = NUMBER (&tm->tm_wday, 0, 6, 0);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'U':
+            case 'W':
+              /* %U and %W are currently ignored. */
+              s = NUMBER (&week, 0, 53, 0);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'x':
+              s = RECURSE (_cur_lcf_time.date_fmt);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'X':
+              s = RECURSE (_cur_lcf_time.time_fmt);
+              if (s == NULL) return NULL;
+              break;
+
+            case 'y':
+              s = NUMBER (&tm->tm_year, 0, 99, 0);
+              if (s == NULL) return NULL;
+              if (tm->tm_year < 69)
+                tm->tm_year += 100;
+              break;
+
+            case 'Y':
+              s = NUMBER (&tm->tm_year, 1900, -1, -1900);
+              if (s == NULL) return NULL;
+              break;
+
+            default:
+              return NULL;
+            }
+        }
+    }
+  return s;
+}
+
+
+char *_strptime (const char *buf, const char *format, struct tm *tm)
+{
+  return (char *)parse_fmt ((const unsigned char *)buf,
+                            (const unsigned char *)format, tm);
+}
Index: trunk/src/emx/src/lib/time/time.c
===================================================================
--- trunk/src/emx/src/lib/time/time.c	(revision 18)
+++ trunk/src/emx/src/lib/time/time.c	(revision 18)
@@ -0,0 +1,13 @@
+/* time.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+
+#include <sys/timeb.h>
+#include <time.h>
+
+time_t time (time_t *t)
+{
+  struct timeb tb;
+
+  _ftime (&tb);
+  if (t != NULL) *t = tb.time;
+  return tb.time;
+}
Index: trunk/src/emx/src/lib/time/times.c
===================================================================
--- trunk/src/emx/src/lib/time/times.c	(revision 18)
+++ trunk/src/emx/src/lib/time/times.c	(revision 18)
@@ -0,0 +1,20 @@
+/* times.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
+
+#include <time.h>
+#include <sys/time.h>
+#include <sys/times.h>
+
+/* Note: return value overflows */
+
+long _times (struct tms *buffer)
+{
+  struct timeval tv;
+
+  buffer->tms_utime = clock ();  /* clock () * HZ / CLOCKS_PER_SEC */
+  buffer->tms_stime = 0;
+  buffer->tms_cutime = 0;
+  buffer->tms_cstime = 0;
+  if (_gettimeofday (&tv, NULL) != 0)
+    return -1;
+  return CLK_TCK * tv.tv_sec + (CLK_TCK * tv.tv_usec) / 1000000;
+}
Index: trunk/src/emx/src/lib/time/timetabs.c
===================================================================
--- trunk/src/emx/src/lib/time/timetabs.c	(revision 18)
+++ trunk/src/emx/src/lib/time/timetabs.c	(revision 18)
@@ -0,0 +1,36 @@
+/* timetabs.c (emx+gcc) -- Copyright (c) 1996 by Eberhard Mattes */
+
+#include <limits.h>
+#include <emx/time.h>
+
+/* Day number, relative to 01-Jan-1970, of 01-Jan for the years 1970
+   through 2106 */
+
+int const _year_day[_YEARS+1] =
+{
+  0, 365, 730, 1096, 1461, 1826, 2191, 2557, 2922, 3287, 3652, 4018,
+  4383, 4748, 5113, 5479, 5844, 6209, 6574, 6940, 7305, 7670, 8035,
+  8401, 8766, 9131, 9496, 9862, 10227, 10592, 10957, 11323, 11688,
+  12053, 12418, 12784, 13149, 13514, 13879, 14245, 14610, 14975,
+  15340, 15706, 16071, 16436, 16801, 17167, 17532, 17897, 18262,
+  18628, 18993, 19358, 19723, 20089, 20454, 20819, 21184, 21550,
+  21915, 22280, 22645, 23011, 23376, 23741, 24106, 24472, 24837,
+  25202, 25567, 25933, 26298, 26663, 27028, 27394, 27759, 28124,
+  28489, 28855, 29220, 29585, 29950, 30316, 30681, 31046, 31411,
+  31777, 32142, 32507, 32872, 33238, 33603, 33968, 34333, 34699,
+  35064, 35429, 35794, 36160, 36525, 36890, 37255, 37621, 37986,
+  38351, 38716, 39082, 39447, 39812, 40177, 40543, 40908, 41273,
+  41638, 42004, 42369, 42734, 43099, 43465, 43830, 44195, 44560,
+  44926, 45291, 45656, 46021, 46387, 46752, 47117, 47482, 47847,
+  48212, 48577, 48942, 49308, 49673, INT_MAX
+};
+
+
+/* Day number, relative to 01-Jan, of day 01 for January through
+   December. */
+
+int const _month_day_non_leap[] = 
+  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, INT_MAX};
+
+int const _month_day_leap[] = 
+  {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, INT_MAX};
Index: trunk/src/emx/src/lib/time/tzset.c
===================================================================
--- trunk/src/emx/src/lib/time/tzset.c	(revision 18)
+++ trunk/src/emx/src/lib/time/tzset.c	(revision 18)
@@ -0,0 +1,205 @@
+/* tzset.c (emx+gcc) -- Copyright (c) 1992-1996 by Kai Uwe Rommel */
+/*                      Copyright (c) 1996 by Eberhard Mattes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/timeb.h>
+#include <emx/time.h>
+#include <emx/syscalls.h>
+
+int _daylight = 0;
+long _timezone = 0;
+char *_tzname[2] = {"GMT", ""};
+
+struct _tzinfo _tzi = {"GMT", "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+
+/* Parse a decimal number.  Return a non-zero value if successful,
+   zero on error. */
+
+static int dnum (int *dst, char **pp, int min, int max, int opt_sign,
+                 int delim)
+{
+  char *p;
+  int n, sign, amax;
+
+  p = *pp; n = 0; sign = 1;
+
+  /* Optional sign. */
+
+  if (opt_sign)
+    {
+      if (*p == '+')
+        ++p;
+      else if (*p == '-')
+        sign = -1, ++p;
+    }
+
+  /* There must be at least one digit. */
+
+  if (!(*p >= '0' && *p <= '9'))
+    return 0;
+
+  /* Compute the maximum absolute value of the number.  This is used
+     to detect overflow. */
+
+  amax = max;
+  if (-min > amax) amax = -min;
+  do
+    {
+      n = n * 10 + *p - '0';
+      if (n > amax) return 0;   /* Overflow */
+      ++p;
+    } while (*p >= '0' && *p <= '9');
+
+  /* Check the delimiter if DELIM is not -1. */
+
+  if (delim != -1 && *p++ != delim)
+    return 0;
+
+  /* Apply the sign. */
+
+  if (sign == -1)
+    n = -n;
+
+  /* Check the range. */
+
+  if (n < min || n > max)
+    return 0;
+
+  /* Return the result. */
+
+  *dst = n;
+  *pp = p;
+  return 1;
+}
+
+
+/* Copy a timezone name.  Return a non-zero value if successful, zero
+   on error. */
+
+static int copy_tzname (char *dst, char **pp)
+{
+  char *p;
+  int i;
+
+  p = *pp;
+
+  /* Check the supposed timezone name for validity.  See ISO 9945-1,
+     8.1.1 for details. */
+
+  if (*p == ':' || (*p >= '0' && *p <= '9'))
+    return 0;
+  for (i = 0; i < 3; ++i)
+    if (p[i] == 0 || p[i] == ',' || p[i] == '-' || p[i] == '+')
+      return 0;
+
+  /* The timezone name is valid. */
+
+  memcpy (dst, p, 3);
+  dst[3] = 0;
+  *pp = p + 3;
+  return 1;
+}
+
+
+void _tzset (void)
+{
+  struct _tzinfo ntz;
+  struct timeb tb;
+  char *p;
+  int sign, offset, temp;
+  time_t t_loc;
+
+  p = getenv ("TZ");
+  if (p == NULL)
+    p = "GMT0";                 /* Our best approximation :-) */
+  if (*p == 0)
+    p = "GMT0";
+
+  if (!copy_tzname (ntz.tzname, &p))
+    return;
+
+  if (*p == 0)
+    offset = sign = 0;          /* TZ=XYZ is valid (in contrast to POSIX.1) */
+  else
+    {
+      if (!dnum (&offset, &p, -24, 24, 1, -1))
+        return;
+      if (offset < 0)
+        sign = -1, offset = -offset;
+      else
+        sign = 1;
+
+      offset *= 60;
+      if (*p == ':')            /* Minutes specified? */
+        {
+          ++p;
+          if (!dnum (&temp, &p, 0, 59, 0, -1))
+            return;
+          offset += temp;
+        }
+
+      offset *= 60;
+      if (*p == ':')            /* Seconds specified? */
+        {
+          ++p;
+          if (!dnum (&temp, &p, 0, 59, 0, -1))
+            return;
+          offset += temp;
+        }
+    }
+
+  ntz.tz = sign > 0 ? offset : -offset;
+
+  ntz.dst = 0;
+  ntz.dstzname[0] = 0;
+
+  if (*p != 0)
+    {
+      ntz.dst = 1;
+      if (!copy_tzname (ntz.dstzname, &p))
+        return ;
+      if (*p == ',')
+        {
+          ++p;
+          if (!dnum (&ntz.sm, &p, 1, 12, 0, ',')
+              || !dnum (&ntz.sw, &p, -4, 4, 1, ',')
+              || !dnum (&ntz.sd, &p, ntz.sw ? 0 : 1, ntz.sw ? 6 : 31, 0, ',')
+              || !dnum (&ntz.st, &p, 0, 86399, 0, ',')
+              || !dnum (&ntz.em, &p, 1, 12, 0, ',')
+              || !dnum (&ntz.ew, &p, -4, 4, 1, ',')
+              || !dnum (&ntz.ed, &p, ntz.ew ? 0 : 1, ntz.ew ? 6 : 31, 0, ',')
+              || !dnum (&ntz.et, &p, 0, 86399, 0, ',')
+              || !dnum (&ntz.shift, &p, 0, 86400, 0, 0))
+            return;
+        }
+      else if (*p == 0)
+        {
+          /* VAC++ default values */
+
+          ntz.sm = 4;  ntz.sw =  1; ntz.sd = 0; ntz.st = 3600;
+          ntz.em = 10; ntz.ew = -1; ntz.ed = 0; ntz.et = 7200;
+          ntz.shift = 3600;
+        }
+      else
+        {
+          /* TODO: POSIX.1 */
+          return;
+        }
+    }
+
+  /* TODO: Make this thread-safe! */
+  _tzi = ntz;
+  _tzname[0] = _tzi.tzname;
+  _tzname[1] = _tzi.dstzname;
+  _compute_dst_table ();
+
+  __ftime (&tb);
+  t_loc = tb.time;
+  _daylight = _loc2gmt (&tb.time, -1);
+  _timezone = (int)(tb.time - t_loc);
+
+  _tzset_flag = 1;
+}
Index: trunk/src/emx/src/lib/time/tzsetfla.c
===================================================================
--- trunk/src/emx/src/lib/time/tzsetfla.c	(revision 18)
+++ trunk/src/emx/src/lib/time/tzsetfla.c	(revision 18)
@@ -0,0 +1,3 @@
+/* tzsetfla.c (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes */
+
+int _tzset_flag = 0;
Index: trunk/src/emx/src/libend/386/edata.asm
===================================================================
--- trunk/src/emx/src/libend/386/edata.asm	(revision 18)
+++ trunk/src/emx/src/libend/386/edata.asm	(revision 18)
@@ -0,0 +1,11 @@
+; edata.asm (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes
+
+                .386
+
+                PUBLIC  _edata
+
+________DATA    SEGMENT PUBLIC USE32 'DATA'
+_edata          LABEL BYTE
+________DATA    ENDS
+
+                END
Index: trunk/src/emx/src/libend/386/end.asm
===================================================================
--- trunk/src/emx/src/libend/386/end.asm	(revision 18)
+++ trunk/src/emx/src/libend/386/end.asm	(revision 18)
@@ -0,0 +1,16 @@
+; end.asm (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes
+
+                .386
+
+                PUBLIC  _end
+
+c_common        SEGMENT PUBLIC USE32 'BSS'
+c_common        ENDS
+
+________BSS     SEGMENT PUBLIC USE32 'BSS'
+_end            LABEL BYTE
+________BSS     ENDS
+
+DGROUP          GROUP   c_common, ________BSS
+
+                END
Index: trunk/src/emx/src/libend/386/etext.asm
===================================================================
--- trunk/src/emx/src/libend/386/etext.asm	(revision 18)
+++ trunk/src/emx/src/libend/386/etext.asm	(revision 18)
@@ -0,0 +1,11 @@
+; etext.asm (emx+gcc) -- Copyright (c) 1995 by Eberhard Mattes
+
+                .386
+
+                PUBLIC  _etext
+
+________TEXT    SEGMENT PUBLIC USE32 'CODE'
+_etext          LABEL BYTE
+________TEXT    ENDS
+
+                END
Index: trunk/src/emx/src/libend/386/weakzero.asm
===================================================================
--- trunk/src/emx/src/libend/386/weakzero.asm	(revision 18)
+++ trunk/src/emx/src/libend/386/weakzero.asm	(revision 18)
@@ -0,0 +1,10 @@
+; weakzero.asm (emx+gcc) -- Copyright (c) 1998 by Eberhard Mattes
+
+                .386
+
+                PUBLIC  WEAK$ZERO
+
+WEAK$ZERO       =       0
+
+                END
+
Index: trunk/src/emx/src/libmoddef/moddef1.c
===================================================================
--- trunk/src/emx/src/libmoddef/moddef1.c	(revision 18)
+++ trunk/src/emx/src/libmoddef/moddef1.c	(revision 18)
@@ -0,0 +1,300 @@
+/* moddef1.c (emx+gcc) -- Copyright (c) 1992-1998 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <share.h>
+#include <errno.h>
+#include <sys/moddef.h>
+
+#define ERRNO (*_errno ())
+
+#define MDF_OPEN 0x0001
+
+struct _md
+{
+  _md_token token;
+  FILE *file;
+  long number;
+  long linenumber;
+  unsigned flags;
+  const char *ptr;
+  char string[512];
+  char buffer[512];
+};
+
+/* An entry of the keywords table associates a keyword string with a
+   token index. */
+
+struct keyword
+{
+  char *name;
+  _md_token token;
+};
+
+/* This table contains all the keywords.  Some of the keywords are not
+   (officially) used. */
+
+static struct keyword keywords[] =
+{
+  {"ALIAS",           _MD_ALIAS},
+  {"BASE",            _MD_BASE},
+  {"CLASS",           _MD_CLASS},
+  {"CODE",            _MD_CODE},
+  {"CONFORMING",      _MD_CONFORMING},
+  {"CONTIGUOUS",      _MD_CONTIGUOUS},
+  {"DATA",            _MD_DATA},
+  {"DESCRIPTION",     _MD_DESCRIPTION},
+  {"DEV386",          _MD_DEV386},
+  {"DEVICE",          _MD_DEVICE},
+  {"DISCARDABLE",     _MD_DISCARDABLE},
+  {"DOS4",            _MD_DOS4},
+  {"DYNAMIC",         _MD_DYNAMIC},
+  {"EXECUTEONLY",     _MD_EXECUTEONLY},
+  {"EXECUTE-ONLY",    _MD_EXECUTEONLY},
+  {"EXECUTEREAD",     _MD_EXECUTEREAD},
+  {"EXETYPE",         _MD_EXETYPE},
+  {"EXPANDDOWN",      _MD_EXPANDDOWN},
+  {"EXPORTS",         _MD_EXPORTS},
+  {"FIXED",           _MD_FIXED},
+  {"HEAPSIZE",        _MD_HEAPSIZE},
+  {"HUGE",            _MD_HUGE},
+  {"IMPORTS",         _MD_IMPORTS},
+  {"IMPURE",          _MD_IMPURE},
+  {"INCLUDE",         _MD_INCLUDE},
+  {"INITGLOBAL",      _MD_INITGLOBAL},
+  {"INITINSTANCE",    _MD_INITINSTANCE},
+  {"INVALID",         _MD_INVALID},
+  {"IOPL",            _MD_IOPL},
+  {"LIBRARY",         _MD_LIBRARY},
+  {"LOADONCALL",      _MD_LOADONCALL},
+  {"LONGNAMES",       _MD_NEWFILES},
+  {"MAXVAL",          _MD_MAXVAL},
+  {"MIXED1632",       _MD_MIXED1632},
+  {"MOVABLE",         _MD_MOVEABLE},
+  {"MOVEABLE",        _MD_MOVEABLE},
+  {"MULTIPLE",        _MD_MULTIPLE},
+  {"NAME",            _MD_NAME},
+  {"NEWFILES",        _MD_NEWFILES},
+  {"NODATA",          _MD_NODATA},
+  {"NOEXPANDDOWN",    _MD_NOEXPANDDOWN},
+  {"NOIOPL",          _MD_NOIOPL},
+  {"NONAME",          _MD_NONAME},
+  {"NONCONFORMING",   _MD_NONCONFORMING},
+  {"NONDISCARDABLE",  _MD_NONDISCARDABLE},
+  {"NONE",            _MD_NONE},
+  {"NONPERMANENT",    _MD_NONPERMANENT},
+  {"NONSHARED",       _MD_NONSHARED},
+  {"NOTWINDOWCOMPAT", _MD_NOTWINDOWCOMPAT},
+  {"OBJECTS",         _MD_OBJECTS},
+  {"OLD",             _MD_OLD},
+  {"ORDER",           _MD_ORDER},
+  {"OS2",             _MD_OS2},
+  {"PERMANENT",       _MD_PERMANENT},
+  {"PHYSICAL",        _MD_PHYSICAL},
+  {"PRELOAD",         _MD_PRELOAD},
+  {"PRIVATE",         _MD_PRIVATE},
+  {"PRIVATELIB",      _MD_PRIVATELIB},
+  {"PROTECT",         _MD_PROTECT},
+  {"PROTMODE",        _MD_PROTMODE},
+  {"PURE",            _MD_PURE},
+  {"READONLY",        _MD_READONLY},
+  {"READWRITE",       _MD_READWRITE},
+  {"REALMODE",        _MD_REALMODE},
+  {"RESIDENT",        _MD_RESIDENT},
+  {"RESIDENTNAME",    _MD_RESIDENTNAME},
+  {"SEGMENTS",        _MD_SEGMENTS},
+  {"SHARED",          _MD_SHARED},
+  {"SINGLE",          _MD_SINGLE},
+  {"STACKSIZE",       _MD_STACKSIZE},
+  {"STUB",            _MD_STUB},
+  {"SWAPPABLE",       _MD_SWAPPABLE},
+  {"TERMGLOBAL",      _MD_TERMGLOBAL},
+  {"TERMINSTANCE",    _MD_TERMINSTANCE},
+  {"UNKNOWN",         _MD_UNKNOWN},
+  {"VIRTUAL",         _MD_VIRTUAL},
+  {"WINDOWAPI",       _MD_WINDOWAPI},
+  {"WINDOWCOMPAT",    _MD_WINDOWCOMPAT},
+  {"WINDOWS",         _MD_WINDOWS},
+  {NULL,              _MD_word}
+};
+
+
+_md_token _md_get_token (const struct _md *md)
+{
+  return md->token;
+}
+
+
+long _md_get_number (const struct _md *md)
+{
+  return md->number;
+}
+
+
+const char *_md_get_string (const struct _md *md)
+{
+  return md->string;
+}
+
+
+long _md_get_linenumber (const struct _md *md)
+{
+  return md->linenumber;
+}
+
+
+/* Read a line from the module definition file to md->buffer.  Set
+   md->token and return -1 on error or if the end of the file is
+   reached.  Otherwise, return 0, increment the line number and move
+   md->ptr to the start of the line. */
+
+static int get_line (struct _md *md)
+{
+  char *p;
+  
+  if (fgets (md->buffer, sizeof (md->buffer), md->file) == NULL)
+    {
+      md->token = (ferror (md->file) ? _MD_ioerror : _MD_eof);
+      return -1;
+    }
+  p = strchr (md->buffer, '\n');
+  if (p != NULL) *p = 0;
+  md->ptr = md->buffer;
+  ++md->linenumber;
+  return 0;
+}
+
+
+_md_token _md_next_token (struct _md *md)
+{
+  const char *start, *end;
+  char *p, quote_char;
+  long n;
+  int i;
+
+  md->number = 0;
+  md->string[0] = 0;
+  for (;;)
+    {
+      if (*md->ptr == ' ' || *md->ptr == '\t')
+        ++md->ptr;
+      else if (*md->ptr == 0 || *md->ptr == ';')
+        {
+          if (get_line (md) != 0)
+            return md->token;
+        }
+      else
+        break;
+    }
+  if (*md->ptr == '\'' || *md->ptr == '\"')
+    {
+      quote_char = *md->ptr;
+      md->token = _MD_quote;
+      start = ++md->ptr;
+      while (*md->ptr != 0 &&
+             (*md->ptr != quote_char || md->ptr[1] == quote_char))
+        ++md->ptr;
+      if (*md->ptr != quote_char)
+        {
+          md->token = _MD_missingquote;
+          return md->token;
+        }
+      end = md->ptr++;
+    }
+  else if (*md->ptr == '=')
+    {
+      md->token = _MD_equal;
+      start = md->ptr++; end = md->ptr;
+    }
+  else if (*md->ptr == '@')
+    {
+      md->token = _MD_at;
+      start = md->ptr++; end = md->ptr;
+    }
+  else if (*md->ptr == '.')
+    {
+      md->token = _MD_dot;
+      start = md->ptr++; end = md->ptr;
+    }
+  else
+    {
+      md->token = _MD_word;
+      start = md->ptr++;
+      md->ptr += strcspn (md->ptr, " \t=@.");
+      end = md->ptr;
+    }
+  _strncpy (md->string, start, end+1-start);
+  if (md->token == _MD_word)
+    for (i = 0; keywords[i].name != NULL; ++i)
+      if (stricmp (md->string, keywords[i].name) == 0)
+        {
+          md->token = keywords[i].token;
+          break;
+        }
+  if (md->token == _MD_word)
+    {
+      if (isdigit ((unsigned char)md->string[0]))
+        {
+          ERRNO = 0;
+          n = strtol (md->string, &p, 0);
+          if (p != md->string && *p == 0 && ERRNO == 0)
+            {
+              md->token = _MD_number;
+              md->number = n;
+            }
+        }
+    }
+  return md->token;
+}
+
+
+struct _md *_md_use_file (FILE *f)
+{
+  struct _md *p;
+
+  p = malloc (sizeof (*p));
+  if (p == NULL)
+    {
+      ERRNO = ENOMEM;
+      return NULL;
+    }
+  p->token = _MD_eof;
+  p->string[0] = 0;
+  p->buffer[0] = 0;
+  p->ptr = p->buffer;
+  p->number = 0;
+  p->linenumber = 0;
+  p->file = f;
+  p->flags = 0;
+  return p;
+}
+
+
+struct _md *_md_open (const char *fname)
+{
+  FILE *f;
+  struct _md *p;
+
+  f = _fsopen (fname, "rt", SH_DENYWR);
+  if (f == NULL)
+    return NULL;
+  p = _md_use_file (f);
+  if (p == NULL)
+    fclose (f);
+  else
+    p->flags |= MDF_OPEN;
+  return p;
+}
+
+
+int _md_close (struct _md *md)
+{
+  int result = 0;
+
+  if (md->flags & MDF_OPEN)
+    result = fclose (md->file);
+  free (md);
+  return result;
+}
Index: trunk/src/emx/src/libmoddef/moddef2.c
===================================================================
--- trunk/src/emx/src/libmoddef/moddef2.c	(revision 18)
+++ trunk/src/emx/src/libmoddef/moddef2.c	(revision 18)
@@ -0,0 +1,639 @@
+/* moddef2.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/moddef.h>
+
+#define FALSE 0
+#define TRUE  1
+
+typedef int _md_callback (struct _md *md, const _md_stmt *stmt,
+                          _md_token token, void *arg);
+
+static int error (struct _md *md, _md_callback *callback, _md_stmt *stmt,
+                  _md_token stmt_token, _md_error code, void *arg)
+{
+  stmt->error.code = code;
+  stmt->error.stmt = stmt_token;
+  return callback (md, stmt, _MD_parseerror, arg);
+}
+
+static _md_token sync (struct _md *md)
+{
+  _md_token token;
+
+  token = _md_get_token (md);
+  for (;;)
+    switch (token)
+      {
+      case _MD_BASE:
+      case _MD_CODE:
+      case _MD_DATA:
+      case _MD_DESCRIPTION:
+      case _MD_EXETYPE:
+      case _MD_EXPORTS:
+      case _MD_HEAPSIZE:
+      case _MD_IMPORTS:
+      case _MD_OLD:
+      case _MD_PROTMODE:
+      case _MD_REALMODE:
+      case _MD_SEGMENTS:
+      case _MD_STACKSIZE:
+      case _MD_STUB:
+      case _MD_eof:
+      case _MD_ioerror:
+      case _MD_missingquote:
+        return token;
+      default:
+        token = _md_next_token (md);
+        break;
+      }
+}
+
+
+#define ERROR(CODE) \
+  do { result = error (md, callback, &stmt, stmt_token, (CODE), arg); \
+       if (result != 0) return result; \
+       token = sync (md); goto next_stmt;} while (FALSE)
+
+#define CALLBACK \
+  do { result = callback (md, &stmt, stmt_token, arg); \
+       if (result != 0) return result; } while (FALSE)
+
+int _md_parse (struct _md *md, _md_callback *callback, void *arg)
+{
+  _md_token token, stmt_token;
+  _md_stmt stmt;
+  const char *s;
+  long n;
+  int ok, result;
+
+  token = _md_get_token (md);
+  stmt_token = token;
+  switch (stmt_token)
+    {
+    case _MD_eof:
+      ERROR (_MDE_EMPTY);
+      break;
+
+    case _MD_NAME:
+      token = _md_next_token (md);
+      stmt.name.name[0] = 0;
+      if (token == _MD_quote || token == _MD_word)
+        {
+          _strncpy (stmt.name.name, _md_get_string (md),
+                    sizeof (stmt.name.name));
+          token = _md_next_token (md);
+        }
+      switch (token)
+        {
+        case _MD_WINDOWAPI:
+          stmt.name.pmtype = _MDT_WINDOWAPI;
+          token = _md_next_token (md);
+          break;
+        case _MD_WINDOWCOMPAT:
+          stmt.name.pmtype = _MDT_WINDOWCOMPAT;
+          token = _md_next_token (md);
+          break;
+        case _MD_NOTWINDOWCOMPAT:
+          stmt.name.pmtype = _MDT_NOTWINDOWCOMPAT;
+          token = _md_next_token (md);
+          break;
+        default:
+          stmt.name.pmtype = _MDT_DEFAULT;
+          break;
+        }
+      stmt.name.newfiles = FALSE;
+      if (token == _MD_NEWFILES)
+        {
+          stmt.name.newfiles = TRUE;
+          token = _md_next_token (md);
+        }
+      CALLBACK;
+      break;
+
+    case _MD_LIBRARY:
+      token = _md_next_token (md);
+      if (token == _MD_quote || token == _MD_word)
+        {
+          _strncpy (stmt.library.name, _md_get_string (md),
+                    sizeof (stmt.library.name));
+          token = _md_next_token (md);
+        }
+      switch (token)
+        {
+        case _MD_INITGLOBAL:
+          stmt.library.init = _MDIT_GLOBAL;
+          token = _md_next_token (md);
+          break;
+        case _MD_INITINSTANCE:
+          stmt.library.init = _MDIT_INSTANCE;
+          token = _md_next_token (md);
+          break;
+        default:
+          stmt.library.init = _MDIT_DEFAULT;
+          break;
+        }
+      switch (token)
+        {
+        case _MD_TERMGLOBAL:
+          stmt.library.term = _MDIT_GLOBAL;
+          token = _md_next_token (md);
+          break;
+        case _MD_TERMINSTANCE:
+          stmt.library.term = _MDIT_INSTANCE;
+          token = _md_next_token (md);
+          break;
+        default:
+          stmt.library.term = _MDIT_DEFAULT;
+          break;
+        }
+      if (token == _MD_PRIVATELIB)
+        token = _md_next_token (md);
+      CALLBACK;
+      break;
+
+    case _MD_VIRTUAL:
+    case _MD_PHYSICAL:
+      token = _md_next_token (md);
+      if (token != _MD_DEVICE)
+        ERROR (_MDE_DEVICE_EXPECTED);
+      token = _md_next_token (md);
+      stmt.device.name[0] = 0;
+      if (token == _MD_quote || token == _MD_word)
+        {
+          _strncpy (stmt.device.name, _md_get_string (md),
+                    sizeof (stmt.device.name));
+          token = _md_next_token (md);
+        }
+      CALLBACK;
+      break;
+
+    default:
+      break;
+    }
+
+next_stmt:
+  while (token != _MD_eof)
+    {
+      stmt_token = token;
+      switch (stmt_token)
+        {
+        case _MD_BASE:
+          token = _md_next_token (md);
+          if (token != _MD_equal)
+            ERROR (_MDE_EQUAL_EXPECTED);
+          token = _md_next_token (md);
+          if (token != _MD_number)
+            ERROR (_MDE_NUMBER_EXPECTED);
+          stmt.base.addr = _md_get_number (md);
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_CODE:
+          token = _md_next_token (md);
+          stmt.segment.segname[0] = 0;
+          stmt.segment.classname[0] = 0;
+          stmt.segment.attr = 0;
+          ok = TRUE;
+          while (ok)
+            {
+              switch (token)
+                {
+                case _MD_CONFORMING:
+                  stmt.segment.attr |= _MDS_CONFORMING;
+                  break;
+                case _MD_DISCARDABLE:
+                  stmt.segment.attr |= _MDS_DISCARDABLE;
+                  break;
+                case _MD_EXECUTEONLY:
+                  stmt.segment.attr |= _MDS_EXECUTEONLY;
+                  break;
+                case _MD_EXECUTEREAD:
+                  stmt.segment.attr |= _MDS_EXECUTEREAD;
+                  break;
+                case _MD_FIXED:
+                  stmt.segment.attr |= _MDS_FIXED;
+                  break;
+                case _MD_IOPL:
+                  stmt.segment.attr |= _MDS_IOPL;
+                  break;
+                case _MD_LOADONCALL:
+                  stmt.segment.attr |= _MDS_LOADONCALL;
+                  break;
+                case _MD_MOVEABLE:
+                  stmt.segment.attr |= _MDS_MOVEABLE;
+                  break;
+                case _MD_NOIOPL:
+                  stmt.segment.attr |= _MDS_NOIOPL;
+                  break;
+                case _MD_NONCONFORMING:
+                  stmt.segment.attr |= _MDS_NONCONFORMING;
+                  break;
+                case _MD_NONDISCARDABLE:
+                  stmt.segment.attr |= _MDS_NONDISCARDABLE;
+                  break;
+                case _MD_NONSHARED:
+                case _MD_IMPURE:
+                  stmt.segment.attr |= _MDS_NONSHARED;
+                  break;
+                case _MD_PRELOAD:
+                  stmt.segment.attr |= _MDS_PRELOAD;
+                  break;
+                case _MD_SHARED:
+                case _MD_PURE:
+                  stmt.segment.attr |= _MDS_SHARED;
+                  break;
+                default:
+                  ok = FALSE;
+                  break;
+                }
+              if (ok)
+                token = _md_next_token (md);
+            }
+          CALLBACK;
+          break;
+
+        case _MD_DATA:
+          token = _md_next_token (md);
+          stmt.segment.segname[0] = 0;
+          stmt.segment.classname[0] = 0;
+          stmt.segment.attr = 0;
+          ok = TRUE;
+          while (ok)
+            {
+              switch (token)
+                {
+                case _MD_FIXED:
+                  stmt.segment.attr |= _MDS_FIXED;
+                  break;
+                case _MD_IOPL:
+                  stmt.segment.attr |= _MDS_IOPL;
+                  break;
+                case _MD_LOADONCALL:
+                  stmt.segment.attr |= _MDS_LOADONCALL;
+                  break;
+                case _MD_MOVEABLE:
+                  stmt.segment.attr |= _MDS_MOVEABLE;
+                  break;
+                case _MD_MULTIPLE:
+                  stmt.segment.attr |= _MDS_MULTIPLE;
+                  break;
+                case _MD_NOIOPL:
+                  stmt.segment.attr |= _MDS_NOIOPL;
+                  break;
+                case _MD_NONE:
+                  stmt.segment.attr |= _MDS_NONE;
+                  break;
+                case _MD_NONSHARED:
+                case _MD_IMPURE:
+                  stmt.segment.attr |= _MDS_NONSHARED;
+                  break;
+                case _MD_PRELOAD:
+                  stmt.segment.attr |= _MDS_PRELOAD;
+                  break;
+                case _MD_READONLY:
+                  stmt.segment.attr |= _MDS_READONLY;
+                  break;
+                case _MD_READWRITE:
+                  stmt.segment.attr |= _MDS_READWRITE;
+                  break;
+                case _MD_SHARED:
+                case _MD_PURE:
+                  stmt.segment.attr |= _MDS_SHARED;
+                  break;
+                case _MD_SINGLE:
+                  stmt.segment.attr |= _MDS_SINGLE;
+                  break;
+                default:
+                  ok = FALSE;
+                  break;
+                }
+              if (ok)
+                token = _md_next_token (md);
+            }
+          CALLBACK;
+          break;
+
+        case _MD_DESCRIPTION:
+          token = _md_next_token (md);
+          if (token != _MD_quote)
+            ERROR (_MDE_STRING_EXPECTED);
+          s = _md_get_string (md);
+          if (*s == 0 || strlen (s) > 255)
+            ERROR (_MDE_STRING_TOO_LONG);
+          _strncpy (stmt.descr.string, s, sizeof (stmt.descr.string));
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_EXETYPE:
+          token = _md_next_token (md);
+          switch (token)
+            {
+            case _MD_OS2:
+              stmt.exetype.type = _MDX_OS2;
+              token = _md_next_token (md);
+              break;
+            case _MD_UNKNOWN:
+              stmt.exetype.type = _MDX_UNKNOWN;
+              token = _md_next_token (md);
+              break;
+            case _MD_WINDOWS:
+              stmt.exetype.type = _MDX_WINDOWS;
+              stmt.exetype.major_version = 0;
+              stmt.exetype.minor_version = 0;
+              token = _md_next_token (md);
+              if (token == _MD_number)
+                {
+                  stmt.exetype.major_version = _md_get_number (md);
+                  token = _md_next_token (md);
+                  if (token == _MD_dot)
+                    {
+                      token = _md_next_token (md);
+                      if (token == _MD_number)
+                        {
+                          stmt.exetype.minor_version = _md_get_number (md);
+                          token = _md_next_token (md);
+                        }
+                    }
+                }
+              break;
+            default:
+              stmt.exetype.type = _MDX_DEFAULT;
+              break;
+            }
+          CALLBACK;
+          break;
+
+        case _MD_EXPORTS:
+          token = _md_next_token (md);
+          while (token == _MD_quote || token == _MD_word)
+            {
+              stmt.export.ordinal = 0;
+              stmt.export.pwords = 0;
+              stmt.export.flags = 0;
+              stmt.export.internalname[0] = 0;
+              _strncpy (stmt.export.entryname, _md_get_string (md),
+                        sizeof (stmt.export.entryname));
+              token = _md_next_token (md);
+              if (token == _MD_equal)
+                {
+                  token = _md_next_token (md);
+                  if (token != _MD_quote && token != _MD_word)
+                    ERROR (_MDE_NAME_EXPECTED);
+                  _strncpy (stmt.export.internalname, _md_get_string (md),
+                            sizeof (stmt.export.internalname));
+                  token = _md_next_token (md);
+                }
+              if (token == _MD_at)
+                {
+                  stmt.export.flags |= _MDEP_ORDINAL;
+                  token = _md_next_token (md);
+                  if (token != _MD_number)
+                    ERROR (_MDE_NUMBER_EXPECTED);
+                  n = _md_get_number (md);
+                  if (n < 1 || n > 65535)
+                    ERROR (_MDE_INVALID_ORDINAL);
+                  stmt.export.ordinal = n;
+                  token = _md_next_token (md);
+                  if (token == _MD_NONAME)
+                    {
+                      stmt.export.flags |= _MDEP_NONAME;
+                      token = _md_next_token (md);
+                    }
+                  else if (token == _MD_RESIDENTNAME)
+                    {
+                      stmt.export.flags |= _MDEP_RESIDENTNAME;
+                      token = _md_next_token (md);
+                    }
+                }
+              if (token == _MD_NODATA)
+                {
+                  stmt.export.flags |= _MDEP_NODATA;
+                  token = _md_next_token (md);
+                }
+              if (token == _MD_number)
+                {
+                  stmt.export.flags |= _MDEP_PWORDS;
+                  stmt.export.pwords = _md_get_number (md);
+                  token = _md_next_token (md);
+                }
+              CALLBACK;
+            }
+          break;
+
+        case _MD_HEAPSIZE:
+          token = _md_next_token (md);
+          if (token == _MD_number)
+            {
+              stmt.heapsize.maxval = FALSE;
+              stmt.heapsize.size = _md_get_number (md);
+            }
+          else if (token == _MD_MAXVAL)
+            {
+              stmt.heapsize.size = 0;
+              stmt.heapsize.maxval = TRUE;
+            }
+          else
+            ERROR (_MDE_NUMBER_EXPECTED);
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_IMPORTS:
+          token = _md_next_token (md);
+          while (token == _MD_quote || token == _MD_word)
+            {
+              _strncpy (stmt.import.modulename, _md_get_string (md),
+                        sizeof (stmt.import.modulename));
+              stmt.import.entryname[0] = 0;
+              stmt.import.internalname[0] = 0;
+              stmt.import.ordinal = 0;
+              stmt.import.flags = 0;
+              token = _md_next_token (md);
+              if (token == _MD_equal)
+                {
+                  _strncpy (stmt.import.internalname, stmt.import.modulename,
+                            sizeof (stmt.import.internalname));
+                  token = _md_next_token (md);
+                  if (token != _MD_quote && token != _MD_word)
+                    ERROR (_MDE_NAME_EXPECTED);
+                  _strncpy (stmt.import.modulename, _md_get_string (md),
+                            sizeof (stmt.import.modulename));
+                  token = _md_next_token (md);
+                }
+              if (token != _MD_dot)
+                ERROR (_MDE_DOT_EXPECTED);
+              token = _md_next_token (md);
+              if (token == _MD_word)
+                _strncpy (stmt.import.entryname, _md_get_string (md),
+                          sizeof (stmt.import.entryname));
+              else if (token == _MD_number)
+                {
+                  stmt.import.flags |= _MDIP_ORDINAL;
+                  n = _md_get_number (md);
+                  if (n < 1 || n > 65535)
+                    ERROR (_MDE_INVALID_ORDINAL);
+                  stmt.import.ordinal = n;
+                }
+              else
+                ERROR (_MDE_NUMBER_EXPECTED);
+              token = _md_next_token (md);
+              CALLBACK;
+            }
+          break;
+
+        case _MD_OLD:
+          token = _md_next_token (md);
+          if (token != _MD_quote)
+            ERROR (_MDE_STRING_EXPECTED);
+          _strncpy (stmt.old.name, _md_get_string (md),
+                    sizeof (stmt.old.name));
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_PROTMODE:
+        case _MD_REALMODE:
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_SEGMENTS:
+          token = _md_next_token (md);
+          while (token == _MD_quote || token == _MD_word)
+            {
+              _strncpy (stmt.segment.segname, _md_get_string (md),
+                        sizeof (stmt.segment.segname));
+              token = _md_next_token (md);
+              if (token == _MD_CLASS)
+                {
+                  token = _md_next_token (md);
+                  if (token != _MD_quote && token != _MD_word)
+                    ERROR (_MDE_NAME_EXPECTED);
+                  _strncpy (stmt.segment.classname, _md_get_string (md),
+                            sizeof (stmt.segment.classname));
+                  token = _md_next_token (md);
+                }
+              else
+                stmt.segment.classname[0] = 0;
+              stmt.segment.attr = 0;
+              ok = TRUE;
+              while (ok)
+                {
+                  switch (token)
+                    {
+                    case _MD_ALIAS:
+                      stmt.segment.attr |= _MDS_ALIAS;
+                      break;
+                    case _MD_CONFORMING:
+                      stmt.segment.attr |= _MDS_CONFORMING;
+                      break;
+                    case _MD_DISCARDABLE:
+                      stmt.segment.attr |= _MDS_DISCARDABLE;
+                      break;
+                    case _MD_EXECUTEONLY:
+                      stmt.segment.attr |= _MDS_EXECUTEONLY;
+                      break;
+                    case _MD_EXECUTEREAD:
+                      stmt.segment.attr |= _MDS_EXECUTEREAD;
+                      break;
+                    case _MD_FIXED:
+                      stmt.segment.attr |= _MDS_FIXED;
+                      break;
+                    case _MD_INVALID:
+                      stmt.segment.attr |= _MDS_INVALID;
+                      break;
+                    case _MD_IOPL:
+                      stmt.segment.attr |= _MDS_IOPL;
+                      break;
+                    case _MD_LOADONCALL:
+                      stmt.segment.attr |= _MDS_LOADONCALL;
+                      break;
+                    case _MD_MIXED1632:
+                      stmt.segment.attr |= _MDS_MIXED1632;
+                      break;
+                    case _MD_MOVEABLE:
+                      stmt.segment.attr |= _MDS_MOVEABLE;
+                      break;
+                    case _MD_NOIOPL:
+                      stmt.segment.attr |= _MDS_NOIOPL;
+                      break;
+                    case _MD_NONCONFORMING:
+                      stmt.segment.attr |= _MDS_NONCONFORMING;
+                      break;
+                    case _MD_NONDISCARDABLE:
+                      stmt.segment.attr |= _MDS_NONDISCARDABLE;
+                      break;
+                    case _MD_NONSHARED:
+                    case _MD_IMPURE:
+                      stmt.segment.attr |= _MDS_NONSHARED;
+                      break;
+                    case _MD_PRELOAD:
+                      stmt.segment.attr |= _MDS_PRELOAD;
+                      break;
+                    case _MD_READONLY:
+                      stmt.segment.attr |= _MDS_READONLY;
+                      break;
+                    case _MD_READWRITE:
+                      stmt.segment.attr |= _MDS_READWRITE;
+                      break;
+                    case _MD_SHARED:
+                    case _MD_PURE:
+                      stmt.segment.attr |= _MDS_SHARED;
+                      break;
+                    default:
+                      ok = FALSE;
+                      break;
+                    }
+                  if (ok)
+                    token = _md_next_token (md);
+                }
+              CALLBACK;
+            }
+          break;
+
+        case _MD_STACKSIZE:
+          token = _md_next_token (md);
+          if (token != _MD_number)
+            ERROR (_MDE_NUMBER_EXPECTED);
+          stmt.stacksize.size = _md_get_number (md);
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_STUB:
+          token = _md_next_token (md);
+          if (token == _MD_quote)
+            {
+              _strncpy (stmt.stub.name, _md_get_string (md),
+                        sizeof (stmt.stub.name));
+              stmt.stub.none = FALSE;
+            }
+          else if (token == _MD_NONE)
+            {
+              stmt.stub.name[0] = 0;
+              stmt.stub.none = TRUE;
+            }
+          else
+            ERROR (_MDE_STRING_EXPECTED);
+          token = _md_next_token (md);
+          CALLBACK;
+          break;
+
+        case _MD_ioerror:
+          ERROR (_MDE_IO_ERROR);
+          break;
+
+        case _MD_missingquote:
+          ERROR (_MDE_MISSING_QUOTE);
+          break;
+
+        default:
+          ERROR (_MDE_INVALID_STMT);
+        }
+    }
+  return 0;
+}
Index: trunk/src/emx/src/libmoddef/moddef3.c
===================================================================
--- trunk/src/emx/src/libmoddef/moddef3.c	(revision 18)
+++ trunk/src/emx/src/libmoddef/moddef3.c	(revision 18)
@@ -0,0 +1,35 @@
+/* moddef3.c (emx+gcc) -- Copyright (c) 1992-1995 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <sys/moddef.h>
+
+const char *_md_errmsg (_md_error code)
+{
+  switch (code)
+    {
+    case _MDE_IO_ERROR:
+      return "Cannot read";
+    case _MDE_MISSING_QUOTE:
+      return "Missing quote";
+    case _MDE_EMPTY:
+      return "Empty file";
+    case _MDE_NAME_EXPECTED:
+      return "Name expected";
+    case _MDE_STRING_EXPECTED:
+      return "String expected";
+    case _MDE_NUMBER_EXPECTED:
+      return "Number expected";
+    case _MDE_EQUAL_EXPECTED:
+      return "`=' expected";
+    case _MDE_DOT_EXPECTED:
+      return "`.' expected";
+    case _MDE_STRING_TOO_LONG:
+      return "String too long";
+    case _MDE_INVALID_ORDINAL:
+      return "Invalid ordinal number";
+    case _MDE_INVALID_STMT:
+      return "Invalid statement";
+    default:
+      return "Unknown error";
+    }
+}
Index: trunk/src/emx/src/libomflib/omflib0.h
===================================================================
--- trunk/src/emx/src/libomflib/omflib0.h	(revision 18)
+++ trunk/src/emx/src/libomflib/omflib0.h	(revision 18)
@@ -0,0 +1,96 @@
+/* omflib0.h (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Private header file for the emx OMFLIB library. */
+
+#define FALSE 0
+#define TRUE  1
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+
+#define FLAG_DELETED  0x0001
+
+enum omf_state
+{
+  OS_EMPTY,                     /* Empty module */
+  OS_SIMPLE,                    /* Alias or import definition only */
+  OS_OTHER,                     /* Any other records present */
+};
+
+struct omfmod
+{
+  char *name;
+  word page;
+  word flags;
+};
+
+struct pubsym
+{
+  word page;
+  char *name;
+};
+
+struct omflib
+{
+  FILE *f;
+  long dict_offset;
+  int page_size;
+  int dict_blocks;
+  int flags;
+  struct omfmod *mod_tab;
+  int mod_alloc;
+  int mod_count;
+  byte *dict;
+  int block_index;
+  int block_index_delta;
+  int bucket_index;
+  int bucket_index_delta;
+  struct pubsym *pub_tab;
+  int pub_alloc;
+  int pub_count;
+  char output;
+  word mod_page;
+  enum omf_state state;
+  char mod_name[256+1];
+};
+
+struct ptr
+{
+  byte *ptr;
+  int len;
+};
+
+#pragma pack(1)
+
+struct omf_rec
+{
+  byte rec_type;
+  word rec_len;
+};
+
+struct lib_header
+{
+  byte rec_type;
+  word rec_len;
+  dword dict_offset;
+  word dict_blocks;
+  byte flags;
+};
+
+#pragma pack()
+
+int omflib_set_error (char *error);
+int omflib_read_dictionary (struct omflib *p, char *error);
+void omflib_hash (struct omflib *p, const byte *name);
+int omflib_pad (FILE *f, int size, int force, char *error);
+int omflib_copy_module (struct omflib *dst_lib, FILE *dst_file,
+    struct omflib *src_lib, FILE *src_file, const char *mod_name, char *error);
+int omflib_make_mod_tab (struct omflib *p, char *error);
+int omflib_pubdef (struct omf_rec *rec, byte *buf, word page,
+    int (*walker)(const char *name, char *error), char *error);
+int omflib_impdef (struct omf_rec *rec, byte *buf, word page,
+    int (*walker)(const char *name, char *error), char *error);
+int omflib_alias (struct omf_rec *rec, byte *buf, word page,
+    int (*walker)(const char *name, char *error), char *error);
Index: trunk/src/emx/src/libomflib/omflibam.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibam.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibam.c	(revision 18)
@@ -0,0 +1,27 @@
+/* omflibam.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Add an OBJ module to an OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+int omflib_add_module (struct omflib *p, const char *fname, char *error)
+{
+  FILE *f;
+  char name[256];
+  char obj_fname[256+4];
+  int ret;
+
+  omflib_module_name (name, fname);
+  strcpy (obj_fname, fname);
+  _defext (obj_fname, "obj");
+  f = fopen (obj_fname, "rb");
+  if (f == NULL)
+    return omflib_set_error (error);
+  ret = omflib_copy_module (p, p->f, NULL, f, name, error);
+  fclose (f);
+  return ret;
+}
Index: trunk/src/emx/src/libomflib/omflibap.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibap.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibap.c	(revision 18)
@@ -0,0 +1,42 @@
+/* omflibap.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Declare a symbol public. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+int omflib_add_pub (struct omflib *p, const char *name, word page, char *error)
+{
+  int i;
+
+  if (strncmp (name, "__POST$", 7) == 0)
+    return 0;
+
+  if (p->pub_count >= p->pub_alloc)
+    {
+      p->pub_alloc += 32;
+      p->pub_tab = realloc (p->pub_tab,
+                            p->pub_alloc * sizeof (struct pubsym));
+      if (p->pub_tab == NULL)
+        {
+          errno = ENOMEM;
+          strcpy (error, strerror (errno));
+          p->pub_alloc = 0;
+          p->pub_count = 0;
+          return -1;
+        }
+    }
+  i = p->pub_count;
+  if ((p->pub_tab[i].name = strdup (name)) == NULL)
+    {
+      errno = ENOMEM;
+      return omflib_set_error (error);
+    }
+  p->pub_tab[i].page = page;
+  ++p->pub_count;
+  return 0;
+}
Index: trunk/src/emx/src/libomflib/omflibcl.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibcl.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibcl.c	(revision 18)
@@ -0,0 +1,99 @@
+/* omflibcl.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Copy an OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+int omflib_copy_lib (struct omflib *dst, struct omflib *src, char *error)
+{
+  int i, rc, *reverse;
+  long long_page;
+  struct omf_rec rec;
+
+  if (src->mod_count == -1 && omflib_make_mod_tab (src, error) != 0)
+    return -1;
+
+  /* Build a vector which maps page numbers to module table
+     entries. */
+
+  reverse = malloc (65536 * sizeof (*reverse));
+  if (reverse == NULL)
+    {
+      errno = ENOMEM;
+      return omflib_set_error (error);
+    }
+
+  for (i = 0; i < 65536; ++i)
+    reverse[i] = -1;
+  for (i = 0; i < src->mod_count; ++i)
+    reverse[src->mod_tab[i].page] = i;
+
+  /* Now read the source library sequentially, starting on page 1. */
+
+  fseek (src->f, src->page_size, SEEK_SET);
+  for (;;)
+    {
+      long_page = ftell (src->f) / src->page_size;
+      if (long_page == -1)
+        {
+          omflib_set_error (error);
+          free (reverse);
+          return -1;
+        }
+      if (long_page > 65535)
+        {
+          strcpy (error, "Source library too big");
+          free (reverse);
+          return -1;
+        }
+      if (fread (&rec, sizeof (rec), 1, src->f) != 1)
+        {
+          if (ferror (src->f))
+            omflib_set_error (error);
+          else
+            strcpy (error, "Unexpected end of file");
+          free (reverse);
+          return -1;
+        }
+      if (rec.rec_type == LIBEND)
+        break;
+      if (rec.rec_type != THEADR)
+        {
+          strcpy (error, "THEADR or LIBEND expected");
+          free (reverse);
+          return -1;
+        }
+      fseek (src->f, -sizeof (rec), SEEK_CUR);
+      i = reverse[long_page];
+      if (i == -1)
+        {
+          /* Unknown module, perhaps an import definition.  Copy the
+             module. */
+          rc = omflib_copy_module (dst, dst->f, src, src->f, NULL, error);
+        }
+      else if (src->mod_tab[i].flags & FLAG_DELETED)
+        {
+          /* Module marked for deletion.  Skip it. */
+          rc = omflib_copy_module (NULL, NULL, src, src->f, NULL, error);
+        }
+      else
+        {
+          /* Copy the module. */
+          rc = omflib_copy_module (dst, dst->f, src, src->f,
+                                   src->mod_tab[i].name, error);
+        }
+      if (rc != 0)
+        {
+          free (reverse);
+          return rc;
+        }
+    }
+  free (reverse);
+  return 0;
+}
Index: trunk/src/emx/src/libomflib/omflibcp.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibcp.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibcp.c	(revision 18)
@@ -0,0 +1,203 @@
+/* omflibcp.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Copy a module from one OMFLIB to another OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+static struct omflib *pubdef_dst_lib;
+static word pubdef_page;
+
+
+static int add_pubdef (const char *name, char *error);
+
+
+int omflib_copy_module (struct omflib *dst_lib, FILE *dst_file,
+                        struct omflib *src_lib, FILE *src_file,
+                        const char *mod_name, char *error)
+{
+  struct omf_rec rec;
+  word page;
+  long long_page, pos;
+  char theadr_name[256];
+  char libmod_name[256];
+  char caller_name[256];
+  byte buf[1024], buf2[256+6];
+  enum omf_state state;
+  enum {RT_THEADR, RT_OTHER} cur_rt, prev_rt;
+  int copy;
+
+  theadr_name[0] = 0; libmod_name[0] = 0;
+  if (mod_name == NULL)
+    caller_name[0] = 0;
+  else
+    omflib_module_name (caller_name, mod_name);
+  if (dst_lib != NULL)
+    {
+      long_page = ftell (dst_file) / dst_lib->page_size;
+      if (long_page > 65535)
+        {
+          strcpy (error, "Library too big -- increase page size");
+          return -1;
+        }
+      page = (word)long_page;
+    }
+  else
+    page = 0;
+  state = OS_EMPTY; prev_rt = RT_OTHER;
+  do
+    {
+      if (fread (&rec, sizeof (rec), 1, src_file) != 1)
+        goto failure_src;
+      if (rec.rec_len > sizeof (buf))
+        {
+          strcpy (error, "Record too long");
+          return -1;
+        }
+      if (fread (buf, rec.rec_len, 1, src_file) != 1)
+        goto failure_src;
+      copy = TRUE; cur_rt = RT_OTHER;
+      switch (rec.rec_type)
+        {
+        case THEADR:
+          if (rec.rec_len == 0 || buf[0] + 1 > rec.rec_len)
+            {
+              strcpy (error, "Truncated THEADR record");
+              return -1;
+            }
+          buf[1+buf[0]] = 0;
+          omflib_module_name (theadr_name, buf + 1);
+          state = OS_EMPTY; cur_rt = RT_THEADR;
+          break;
+
+        case PUBDEF:
+        case PUBDEF|REC32:
+          if (dst_lib != NULL)
+            {
+              pubdef_dst_lib = dst_lib;
+              pubdef_page = page;
+              if (omflib_pubdef (&rec, buf, page, add_pubdef, error) != 0)
+                return -1;
+            }
+          state = OS_OTHER;
+          break;
+
+        case ALIAS:
+          if (dst_lib != NULL)
+            {
+              pubdef_dst_lib = dst_lib;
+              pubdef_page = page;
+              if (omflib_alias (&rec, buf, page, add_pubdef, error) != 0)
+                return -1;
+            }
+          state = (state == OS_EMPTY ? OS_SIMPLE : OS_OTHER);
+          break;
+
+        case COMENT:
+          if (rec.rec_len >= 3 && buf[1] == IMPDEF_CLASS
+              && buf[2] == IMPDEF_SUBTYPE)
+            {
+              if (dst_lib != NULL)
+                {
+                  pubdef_dst_lib = dst_lib;
+                  pubdef_page = page;
+                  if (omflib_impdef (&rec, buf, page, add_pubdef, error) != 0)
+                    return -1;
+                }
+              state = (state == OS_EMPTY ? OS_SIMPLE : OS_OTHER);
+            }
+          else if (rec.rec_len >= 2 && buf[1] == LIBMOD_CLASS)
+            {
+              if (dst_lib == NULL || mod_name != NULL)
+                copy = FALSE;
+              if (rec.rec_len < 3 || buf[2] + 3 > rec.rec_len)
+                {
+                  strcpy (error, "Truncated LIBMOD record");
+                  return -1;
+                }
+              buf[3+buf[2]] = 0;
+              omflib_module_name (libmod_name, buf + 3);
+              state = OS_OTHER;
+            }
+          else
+            state = OS_OTHER;
+          break;
+
+        case MODEND:
+        case MODEND|REC32:
+          /* Don't change STATE. */
+          break;
+
+        default:
+          state = OS_OTHER;
+        }
+
+      if (prev_rt == RT_THEADR && dst_lib != NULL && mod_name != NULL)
+        {
+          if (state == OS_SIMPLE)
+            cur_rt = RT_THEADR; /* Check again after next record */
+          else if (strcmp (caller_name, theadr_name) != 0)
+            {
+              buf2[0] = 0;
+              buf2[1] = LIBMOD_CLASS;
+              buf2[2] = strlen (caller_name);
+              memcpy (buf2 + 3, caller_name, buf2[2]);
+              if (omflib_write_record (dst_lib, COMENT, buf2[2] + 3, buf2,
+                                       TRUE, error) != 0)
+                return -1;
+            }
+        }
+      if (copy && dst_file != NULL)
+        {
+          if (fwrite (&rec, sizeof (rec), 1, dst_file) != 1
+              || fwrite (buf, rec.rec_len, 1, dst_file) != 1)
+            return omflib_set_error (error);
+        }
+      prev_rt = cur_rt;
+    } while (rec.rec_type != MODEND && rec.rec_type != (MODEND|REC32));
+  if (src_lib != NULL)
+    {
+      pos = ftell (src_file);
+      if (pos % src_lib->page_size != 0)
+        fseek (src_file, src_lib->page_size - pos % src_lib->page_size,
+               SEEK_CUR);
+    }
+  if (dst_lib != NULL)
+    {
+      /* Don't use PUBDEF for the module name for modules that contain
+         only an alias or an import definition. */
+
+      if (state != OS_SIMPLE)
+        {
+          if (caller_name[0] != 0)
+            strcpy (buf2, caller_name);
+          else if (libmod_name[0] != 0)
+            strcpy (buf2, libmod_name);
+          else
+            strcpy (buf2, theadr_name);
+          strcat (buf2, "!");
+          if (omflib_add_pub (dst_lib, buf2, page, error) != 0)
+            return -1;
+        }
+      if (dst_file != NULL
+          && omflib_pad (dst_file, dst_lib->page_size, FALSE, error) != 0)
+        return -1;
+    }
+  return 0;
+  
+failure_src:
+  if (ferror (src_file))
+    return omflib_set_error (error);
+  strcpy (error, "Unexpected end of file");
+  return -1;
+}
+
+
+static int add_pubdef (const char *name, char *error)
+{
+  return omflib_add_pub (pubdef_dst_lib, name, pubdef_page, error);
+}
Index: trunk/src/emx/src/libomflib/omflibcr.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibcr.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibcr.c	(revision 18)
@@ -0,0 +1,285 @@
+/* omflibcr.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Create a new OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+struct omflib *omflib_create (const char *fname, int page_size, char *error)
+{
+  struct omflib *p;
+  FILE *f;
+
+  if (page_size < 16 || page_size > 32768
+      || (page_size & (page_size - 1)) != 0)
+    {
+      strcpy (error, "Invalid page size");
+      return NULL;
+    }
+  f = fopen (fname, "wb");
+  if (f == NULL)
+    {
+      strcpy (error, strerror (errno));
+      return NULL;
+    }
+  p = malloc (sizeof (struct omflib));
+  if (p == NULL)
+    {
+      errno = ENOMEM;
+      strcpy (error, strerror (errno));
+      fclose (f);
+      remove (fname);
+      return NULL;
+    }
+  p->f = f;
+  p->page_size = page_size;
+  p->dict_offset = 0;
+  p->dict_blocks = 0;
+  p->flags = 1;
+  p->mod_tab = NULL;
+  p->mod_alloc = 0;
+  p->mod_count = -1;
+  p->dict = NULL;
+  p->pub_tab = NULL;
+  p->pub_alloc = 0;
+  p->pub_count = 0;
+  p->output = TRUE;
+  p->state = OS_EMPTY;
+  p->mod_page = 0;
+  p->mod_name[0] = 0;
+  return p;
+}
+
+
+int omflib_header (struct omflib *p, char *error)
+{
+  fseek (p->f, 0, SEEK_SET);
+  return omflib_pad (p->f, p->page_size, TRUE, error);
+}
+
+
+static int omflib_add_dict (struct omflib *p, const char *name, int page,
+                            char *error)
+{
+  int block_index, bucket_index;
+  int bv, len, bucket_count;
+  byte *block, *ptr;
+  byte buf[257];
+  int (*compare)(const void *s1, const void *s2, size_t n);
+
+  len = strlen (name);
+  if (len > 255)
+    {
+      strcpy (error, "Symbol name too long");
+      return -1;
+    }
+  buf[0] = (byte)len;
+  memcpy (buf+1, name, len);
+  omflib_hash (p, buf);
+  block_index = p->block_index;
+  bucket_index = p->bucket_index;
+  compare = (p->flags & 1 ? memcmp : memicmp);
+  bucket_count = 37;
+  block = p->dict + 512 * block_index;
+  for (;;)
+    {
+      bv = block[bucket_index];
+      if (bv == 0)
+        {
+          if (block[37] == 0xff)
+            bucket_count = 0;
+          else if (2 * block[37] + len + 4 > 512)
+            {
+              block[37] = 0xff;
+              bucket_count = 0;
+            }
+          else
+            {
+              block[bucket_index] = block[37];
+              ptr = block + 2 * block[37];
+              memcpy (ptr, buf, len+1);
+              ptr[len+1] = (byte)page;
+              ptr[len+2] = (byte)(page >> 8);
+              block[37] = (2 * block[37] + len + 3 + 1) / 2;
+              if (block[37] == 0) block[37] = 0xff;
+              return 0;
+            }
+        }
+      else
+        {
+          ptr = block + 2 * bv;
+          if (*ptr == len && compare (ptr+1, buf+1, len) == 0)
+            {
+              strcpy (error, "Symbol multiply defined: ");
+              strcat (error, name);
+              return -1;
+            }
+        }
+      if (bucket_count != 0)
+        {
+          bucket_index += p->bucket_index_delta;
+          if (bucket_index >= 37)
+            bucket_index -= 37;
+          --bucket_count;
+        }
+      if (bucket_count == 0)
+        {
+          block_index += p->block_index_delta;
+          if (block_index >= p->dict_blocks)
+            block_index -= p->dict_blocks;
+          if (block_index == p->block_index)
+            return 1;
+          bucket_count = 37;
+          block = p->dict + 512 * block_index;
+        }
+    }
+}
+
+
+static int omflib_build_dict (struct omflib *p, char *error)
+{
+  int i, ret;
+
+  p->dict = realloc (p->dict, p->dict_blocks * 512);
+  if (p->dict == NULL)
+    {
+      errno = ENOMEM;
+      return omflib_set_error (error);
+    }
+  memset (p->dict, 0, p->dict_blocks * 512);
+  for (i = 0; i < p->dict_blocks; ++i)
+    p->dict[i * 512 + 37] = 38 / 2;
+  for (i = 0; i < p->pub_count; ++i)
+    {
+      ret = omflib_add_dict (p, p->pub_tab[i].name, p->pub_tab[i].page, error);
+      if (ret != 0)
+        return ret;
+    }
+  return 0;
+}
+
+
+static unsigned isqrt (unsigned x)
+{
+  unsigned a, r, e, i;
+
+  a = r = e = 0;
+  for (i = 0; i < 32 / 2; ++i)
+    {
+      r = (r << 2) | (x >> (32-2));
+      x <<= 2; a <<= 1;
+      e = (a << 1) | 1;
+      if (r >= e)
+        {
+          r -= e;
+          a |= 1;
+        }
+    }
+  return a;
+}
+
+
+/* Speed doesn't matter here. */
+
+static int is_prime (unsigned n)
+{
+  unsigned i, q;
+
+  q = isqrt (n);
+  for (i = 3; i <= q; i += 2)
+    if (n % i == 0)
+      return 0;
+  return 1;
+}
+
+
+static unsigned next_prime (unsigned n)
+{
+  if (n <= 1)
+    return 2;
+  if (n % 2 == 0)
+    --n;
+  do
+    {
+      n += 2;
+    } while (!is_prime (n));
+  return n;
+}
+
+
+int omflib_finish (struct omflib *p, char *error)
+{
+  struct lib_header hdr;
+  int len, i, blocks;
+  unsigned prime;
+  long pos;
+  struct omf_rec rec;
+
+  if (!p->output)
+    return 0;
+  len = 0;
+  for (i = 0; i < p->pub_count; ++i)
+    len += strlen (p->pub_tab[i].name) + 3;
+  blocks = (len + 511) / 512;
+  blocks += (blocks * 128) / 512;
+  ++blocks;
+  prime = blocks;
+  for (;;)
+    {
+      prime = next_prime (prime);
+      if (prime > 65535)
+        {
+          strcpy (error, "Too many dictionary blocks");
+          return -1;
+        }
+      p->dict_blocks = prime;
+      i = omflib_build_dict (p, error);
+      if (i < 0)
+        return i;
+      if (i == 0)
+        break;
+    }
+  pos = ftell (p->f) + 3;
+  rec.rec_type = LIBEND;
+  if ((pos & 511) == 0)
+    rec.rec_len = 0;
+  else
+    rec.rec_len = (word)(((pos | 511) + 1) - pos);
+  if (fwrite (&rec, sizeof (rec), 1, p->f) != 1)
+    return omflib_set_error (error);
+  if (omflib_pad (p->f, 512, FALSE, error) != 0)
+    return -1;
+  hdr.rec_type = LIBHDR;
+  hdr.rec_len = p->page_size - 3;
+  hdr.dict_offset = ftell (p->f);
+  hdr.dict_blocks = p->dict_blocks;
+  hdr.flags = (byte)p->flags;
+  fseek (p->f, 0, SEEK_SET);
+  if (fwrite (&hdr, sizeof (hdr), 1, p->f) != 1)
+    return omflib_set_error (error);
+  fseek (p->f, hdr.dict_offset, SEEK_SET);
+  if (fwrite (p->dict, 512, p->dict_blocks, p->f) != p->dict_blocks)
+    return omflib_set_error (error);
+  return 0;
+}
+
+
+int omflib_pad (FILE *f, int size, int force, char *error)
+{
+  long pos;
+
+  pos = ftell (f);
+  while ((pos & (size-1)) != 0 || force)
+    {
+      force = FALSE;
+      if (fputc (0, f) != 0)
+        return omflib_set_error (error);
+      ++pos;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/libomflib/omflibdl.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibdl.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibdl.c	(revision 18)
@@ -0,0 +1,31 @@
+/* omflibdl.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+/* Mark a module of an OMFLIB as deleted. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+int omflib_mark_deleted (struct omflib *p, const char *name, char *error)
+{
+  char buf[256];
+  int (*compare)(const char *s1, const char *s2);
+  int i;
+
+  if (p->mod_count == -1 && omflib_make_mod_tab (p, error) != 0)
+    return -1;
+  omflib_module_name (buf, name);
+  compare = (p->flags & 1 ? strcmp : stricmp);
+  for (i = 0; i < p->mod_count; ++i)
+    if (compare (p->mod_tab[i].name, buf) == 0)
+      {
+        p->mod_tab[i].flags |= FLAG_DELETED;
+        return 0;
+      }
+  strcpy (error, "Module not found: ");
+  strcat (error, buf);
+  return 0;
+}
Index: trunk/src/emx/src/libomflib/omflibex.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibex.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibex.c	(revision 18)
@@ -0,0 +1,41 @@
+/* omflibex.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+/* Extract a module of an OMFLIB into an OBJ file. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+int omflib_extract (struct omflib *p, const char *name, char *error)
+{
+  char buf[256+4];
+  int page;
+  FILE *f;
+
+  if (p->dict == NULL && omflib_read_dictionary (p, error) != 0)
+    return -1;
+  page = omflib_find_module (p, name, error);
+  if (page == 0)
+    {
+      strcpy (error, "Module not found");
+      return -1;
+    }
+  _strncpy (buf, name, 255);
+  _defext (buf, "obj");
+  f = fopen (buf, "wb");
+  if (f == NULL)
+    return omflib_set_error (error);
+  fseek (p->f, page * p->page_size, SEEK_SET);
+  if (omflib_copy_module (NULL, f, p, p->f, NULL, error) != 0)
+    {
+      fclose (f);
+      remove (buf);
+      return -1;
+    }
+  if (fflush (f) != 0 || fclose (f) != 0)
+    return omflib_set_error (error);
+  return 0;
+}
Index: trunk/src/emx/src/libomflib/omflibpb.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibpb.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibpb.c	(revision 18)
@@ -0,0 +1,181 @@
+/* omflibpb.c (emx+gcc) -- Copyright (c) 1993-1995 by Eberhard Mattes */
+
+/* Call a function for all the PUBDEF, IMPDEF, and ALIAS records of an
+   OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+static int omflib_get_index (struct ptr *p, int *dst, char *error);
+
+
+int omflib_pubdef_walk (struct omflib *p, word page,
+                        int (*walker)(const char *name, char *error),
+                        char *error)
+{
+  struct omf_rec rec;
+  byte buf[1024];
+  int ret;
+
+  fseek (p->f, page * p->page_size, SEEK_SET);
+  do
+    {
+      if (fread (&rec, sizeof (rec), 1, p->f) != 1)
+        goto failure;
+      if (rec.rec_len > sizeof (buf))
+        {
+          strcpy (error, "Record too long");
+          return -1;
+        }
+      if (fread (buf, rec.rec_len, 1, p->f) != 1)
+        goto failure;
+      if (rec.rec_type == PUBDEF || rec.rec_type == (PUBDEF|REC32))
+        {
+          ret = omflib_pubdef (&rec, buf, page, walker, error);
+          if (ret != 0) return ret;
+        }
+      else if (rec.rec_type == ALIAS)
+        {
+          ret = omflib_alias (&rec, buf, page, walker, error);
+          if (ret != 0) return ret;
+        }
+      else if (rec.rec_type == COMENT && rec.rec_len >= 2 &&
+               buf[1] == IMPDEF_CLASS && buf[2] == IMPDEF_SUBTYPE)
+        {
+          ret = omflib_impdef (&rec, buf, page, walker, error);
+          if (ret != 0) return ret;
+        }
+    } while (rec.rec_type != MODEND && rec.rec_type != (MODEND|REC32));
+  return 0;
+
+failure:
+  if (ferror (p->f))
+    return omflib_set_error (error);
+  strcpy (error, "Unexpected end of file");
+  return -1;
+}
+
+
+int omflib_pubdef (struct omf_rec *rec, byte *buf, word page,
+                   int (*walker)(const char *name, char *error),
+                   char *error)
+{
+  int group_index, segment_index, type_index;
+  struct ptr ptr;
+  int len, i, ret;
+  char name[256];
+
+  ptr.ptr = buf;
+  ptr.len = rec->rec_len - 1;
+  if (omflib_get_index (&ptr, &group_index, error) != 0)
+    return -1;
+  if (omflib_get_index (&ptr, &segment_index, error) != 0)
+    return -1;
+  if (segment_index == 0)
+    {
+      if (ptr.len < 2)
+        goto too_short;
+      ptr.ptr += 2; ptr.len -= 2;
+    }
+
+  while (ptr.len > 0)
+    {
+      if (ptr.len < 1)
+        goto too_short;
+      len = ptr.ptr[0];
+      ++ptr.ptr; --ptr.len;
+      if (ptr.len < len)
+        goto too_short;
+      memcpy (name, ptr.ptr, len);
+      name[len] = 0;
+      ptr.ptr += len; ptr.len -= len;
+      i = (rec->rec_type == (PUBDEF|REC32) ? 4 : 2);
+      if (ptr.len < i) goto too_short;
+      ptr.ptr += i; ptr.len -= i;
+      if (omflib_get_index (&ptr, &type_index, error) != 0)
+        return -1;
+      ret = walker (name, error);
+      if (ret != 0) return ret;
+    }
+  if (ptr.len != 0)
+    {
+      strcpy (error, "Invalid PUBDEF record");
+      return -1;
+    }
+  return 0;
+
+too_short:
+  strcpy (error, "PUBDEF record too short");
+  return -1;
+}
+
+
+int omflib_impdef (struct omf_rec *rec, byte *buf, word page,
+                   int (*walker)(const char *name, char *error),
+                   char *error)
+{
+  int len;
+  char name[256];
+
+  if (rec->rec_len < 5) goto too_short;
+  len = buf[4];
+  if (len + 5 > rec->rec_len) goto too_short;
+  memcpy (name, buf+5, len);
+  name[len] = 0;
+  return walker (name, error);
+
+too_short:
+  strcpy (error, "IMPDEF record too short");
+  return -1;
+}
+
+
+int omflib_alias (struct omf_rec *rec, byte *buf, word page,
+                  int (*walker)(const char *name, char *error),
+                  char *error)
+{
+  int len;
+  char name[256];
+
+  if (rec->rec_len < 1) goto too_short;
+  len = buf[0];
+  if (len + 2 > rec->rec_len) goto too_short;
+  memcpy (name, buf+1, len);
+  name[len] = 0;
+  return walker (name, error);
+
+too_short:
+  strcpy (error, "ALIAS record too short");
+  return -1;
+}
+
+
+static int omflib_get_index (struct ptr *p, int *dst, char *error)
+{
+  if (p->len < 1)
+    goto too_short;
+  if (p->ptr[0] <= 0x7f)
+    {
+      *dst = p->ptr[0];
+      ++p->ptr;
+      --p->len;
+      return 0;
+    }
+  else if (p->len < 2)
+    goto too_short;
+  else
+    {
+      *dst = ((p->ptr[0] & 0x7f) << 8) | p->ptr[1];
+      p->ptr += 2;
+      p->len -= 2;
+      return 0;
+    }
+
+too_short:
+  strcpy (error, "Record too short");
+  return -1;
+}
Index: trunk/src/emx/src/libomflib/omflibrd.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibrd.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibrd.c	(revision 18)
@@ -0,0 +1,261 @@
+/* omflibrd.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Read an OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+struct omflib *omflib_open (const char *fname, char *error)
+{
+  FILE *f;
+  struct omflib *p;
+  struct lib_header hdr;
+
+  f = fopen (fname, "rb");
+  if (f == NULL)
+    goto failure;
+  if (fread (&hdr, sizeof (hdr), 1, f) != 1)
+    {
+      if (ferror (f))
+        goto failure;
+      strcpy (error, "Invalid library header");
+      fclose (f);
+      return NULL;
+    }
+  if (hdr.rec_type != LIBHDR || hdr.rec_len < 7)
+    {
+      strcpy (error, "Invalid library header");
+      fclose (f);
+      return NULL;
+    }
+  p = malloc (sizeof (struct omflib));
+  if (p == NULL)
+    {
+      errno = ENOMEM;
+      goto failure;
+    }
+  p->f = f;
+  p->page_size = hdr.rec_len + 3;
+  p->dict_offset = hdr.dict_offset;
+  p->dict_blocks = hdr.dict_blocks;
+  p->flags = hdr.flags;
+  p->mod_tab = NULL;
+  p->mod_alloc = 0;
+  p->mod_count = -1;
+  p->dict = NULL;
+  p->pub_tab = NULL;
+  p->pub_alloc = 0;
+  p->pub_count = 0;
+  p->output = FALSE;
+  p->state = OS_EMPTY;
+  p->mod_page = 0;
+  p->mod_name[0] = 0;
+  return p;
+
+failure:
+  strcpy (error, strerror (errno));
+  if (f != NULL)
+    fclose (f);
+  return NULL;
+}
+
+
+int omflib_read_dictionary (struct omflib *p, char *error)
+{
+  if (p->output)
+    {
+      strcpy (error, "Not implemented for output library");
+      return -1;
+    }
+  p->dict = malloc (512 * p->dict_blocks);
+  if (p->dict == NULL)
+    {
+      errno = ENOMEM;
+      return omflib_set_error (error);
+    }
+  fseek (p->f, p->dict_offset, SEEK_SET);
+  if (fread (p->dict, 512, p->dict_blocks, p->f) != p->dict_blocks)
+    {
+      if (ferror (p->f))
+        strcpy (error, strerror (errno));
+      else
+        strcpy (error, "Dictionary truncated");
+      free (p->dict);
+      p->dict = NULL;
+      return -1;
+    }
+  return 0;
+}
+
+
+static int mod_compare (const void *x1, const void *x2)
+{
+  word page1, page2;
+
+  page1 = ((const struct omfmod *)x1)->page;
+  page2 = ((const struct omfmod *)x2)->page;
+  if (page1 < page2)
+    return -1;
+  else if (page1 > page2)
+    return 1;
+  else
+    return 0;
+}
+
+
+int omflib_make_mod_tab (struct omflib *p, char *error)
+{
+  int block, bucket, bv, len;
+  char string[256];
+  struct omfmod *mod;
+  byte *d, *s;
+
+  if (p->dict == NULL && omflib_read_dictionary (p, error) != 0)
+    return -1;
+  p->mod_count = 0;
+  d = p->dict;
+  for (block = 0; block < p->dict_blocks; ++block, d += 512)
+    for (bucket = 0; bucket < 37; ++bucket)
+      {
+        bv = d[bucket];
+        if (bv != 0)
+          {
+            s = d + bv * 2;
+            len = *s;
+            if (s[len] == '!')
+              {
+                memcpy (string, s+1, len-1);
+                string[len-1] = 0;
+                if (p->mod_count >= p->mod_alloc)
+                  {
+                    p->mod_alloc += 16;
+                    p->mod_tab = realloc (p->mod_tab, p->mod_alloc
+                                          * sizeof (struct omfmod));
+                    if (p->mod_tab == NULL)
+                      {
+                        p->mod_count = -1;
+                        p->mod_alloc = 0;
+                        errno = ENOMEM;
+                        return omflib_set_error (error);
+                      }
+                  }
+                mod = &p->mod_tab[p->mod_count];
+                mod->page = s[len+1] | (s[len+2] << 8);
+                mod->name = strdup (string);
+                mod->flags = 0;
+                if (mod->name == NULL)
+                  {
+                    errno = ENOMEM;
+                    return omflib_set_error (error);
+                  }
+                ++p->mod_count;
+              }
+          }
+      }
+  qsort (p->mod_tab, p->mod_count, sizeof (p->mod_tab[0]), mod_compare);
+  return 0;
+}
+
+
+int omflib_module_count (struct omflib *p, char *error)
+{
+  if (p->mod_count == -1 && omflib_make_mod_tab (p, error) != 0)
+    return -1;
+  return p->mod_count;
+}
+
+
+int omflib_module_info (struct omflib *p, int n, char *name, int *page,
+                        char *error)
+{
+  if (p->mod_count == -1 && omflib_make_mod_tab (p, error) != 0)
+      return -1;
+  if (n < 0 || n >= p->mod_count)
+    {
+      strcpy (error, "Module number out of range");
+      return -1;
+    }
+  strcpy (name, p->mod_tab[n].name);
+  *page = p->mod_tab[n].page;
+  return 0;
+}
+
+
+int omflib_find_symbol (struct omflib *p, const char *name, char *error)
+{
+  int block_index, bucket_index;
+  int bv, len, bucket_count;
+  byte *ptr, *block, buf[257];
+  int (*compare)(const void *s1, const void *s2, size_t n);
+
+  if (p->dict == NULL && omflib_read_dictionary (p, error) != 0)
+    return -1;
+  len = strlen (name);
+  if (len > 255)
+    {
+      strcpy (error, "Symbol name too long");
+      return -1;
+    }
+  buf[0] = (byte)len;
+  memcpy (buf+1, name, len);
+  omflib_hash (p, buf);
+  block_index = p->block_index;
+  bucket_index = p->bucket_index;
+  bucket_count = 37;
+  compare = (p->flags & 1 ? memcmp : memicmp);
+  for (;;)
+    {
+      block = p->dict + 512 * block_index;
+      bv = block[bucket_index];
+      if (bv == 0)
+        {
+          if (block[37] != 0xff)
+            return 0;
+          bucket_count = 0;     /* Keep bucket_index! */
+        }
+      else
+        {
+          ptr = block + 2 * bv;
+          if (*ptr == len && compare (ptr+1, buf+1, len) == 0)
+            return ptr[len+1] + (ptr[len+2] << 8);
+          bucket_index += p->bucket_index_delta;
+          if (bucket_index >= 37)
+            bucket_index -= 37;
+          --bucket_count;
+        }
+      if (bucket_count == 0)
+        {
+          block_index += p->block_index_delta;
+          if (block_index >= p->dict_blocks)
+            block_index -= p->dict_blocks;
+          if (block_index == p->block_index)
+            return 0;
+          bucket_count = 37;
+        }
+    }
+}
+
+
+int omflib_find_module (struct omflib *p, const char *name, char *error)
+{
+  char buf[256+1];
+
+  if (omflib_module_name (buf, name) != 0)
+    {
+      strcpy (error, "Module name too long");
+      return -1;
+    }
+  strcat (buf, "!");
+  return omflib_find_symbol (p, buf, error);
+}
+
+
+long omflib_page_pos (struct omflib *p, int page)
+{
+  return page * p->page_size;
+}
Index: trunk/src/emx/src/libomflib/omflibut.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibut.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibut.c	(revision 18)
@@ -0,0 +1,100 @@
+/* omflibut.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Utility functions for dealing with OMFLIBs. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+int omflib_set_error (char *error)
+{
+  strcpy (error, strerror (errno));
+  return -1;
+}
+
+
+int omflib_close (struct omflib *p, char *error)
+{
+  int i;
+
+  fclose (p->f);
+  if (p->dict != NULL)
+    free (p->dict);
+  if (p->mod_tab != NULL)
+    {
+      for (i = 0; i < p->mod_count; ++i)
+        free (p->mod_tab[i].name);
+      free (p->mod_tab);
+    }
+  if (p->pub_tab != NULL)
+    {
+      for (i = 0; i < p->pub_count; ++i)
+        free (p->pub_tab[i].name);
+      free (p->pub_tab);
+    }
+  free (p);
+  return 0;
+}
+
+
+#define ROL2(x) (((unsigned)(x) << 2) | ((unsigned)(x) >> 14))
+#define ROR2(x) (((unsigned)(x) >> 2) | ((unsigned)(x) << 14))
+
+void omflib_hash (struct omflib *p, const byte *name)
+{
+  int i, len;
+  word block_index, bucket_index, block_index_delta, bucket_index_delta;
+  byte c;
+
+  len = name[0];
+  block_index = 0;
+  block_index_delta = 0;
+  bucket_index = 0;
+  bucket_index_delta = 0;
+  for (i = 0; i < len; ++i)
+    {
+      c = name[i] | 0x20;
+      block_index = ROL2 (block_index) ^ c;
+      bucket_index_delta = ROR2 (bucket_index_delta) ^ c;
+      c = name[len-i] | 0x20;
+      bucket_index = ROR2 (bucket_index) ^ c;
+      block_index_delta = ROL2 (block_index_delta) ^ c;
+    }
+  p->block_index = block_index % p->dict_blocks;
+  p->block_index_delta = block_index_delta % p->dict_blocks;
+  if (p->block_index_delta == 0)
+    p->block_index_delta = 1;
+  p->bucket_index = bucket_index % 37;
+  p->bucket_index_delta = bucket_index_delta % 37;
+  if (p->bucket_index_delta == 0)
+    p->bucket_index_delta = 1;
+}
+
+
+int omflib_module_name (char *dst, const char *src)
+{
+  const char *base;
+  char *s;
+  int len;
+
+  base = _getname (src);
+  s = strchr (base, '.');
+  if (s != NULL)
+    len = s - base;
+  else
+    len = strlen (base);
+  if (len > 255)
+    {
+      memcpy (dst, base, 255);
+      dst[255] = 0;
+      return -1;
+    }
+  else
+    {
+      memcpy (dst, base, len);
+      dst[len] = 0;
+      return 0;
+    }
+}
Index: trunk/src/emx/src/libomflib/omflibwr.c
===================================================================
--- trunk/src/emx/src/libomflib/omflibwr.c	(revision 18)
+++ trunk/src/emx/src/libomflib/omflibwr.c	(revision 18)
@@ -0,0 +1,102 @@
+/* omflibwr.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+
+/* Write an OMFLIB. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "omflib0.h"
+#include <sys/omflib.h>
+
+
+int omflib_write_record (struct omflib *p, byte rec_type, word rec_len,
+                         const byte *buffer, int chksum, char *error)
+{
+  struct omf_rec rec;
+  byte sum;
+  int i, len;
+  char name[256];
+
+  rec.rec_type = rec_type;
+  rec.rec_len = (chksum ? rec_len + 1 : rec_len);
+  if (fwrite (&rec, sizeof (rec), 1, p->f) != 1
+      || fwrite (buffer, rec_len, 1, p->f) != 1)
+    return omflib_set_error (error);
+  if (chksum)
+    {
+      sum = rec_type + (rec.rec_len & 0xff) + (rec.rec_len >> 8);
+      for (i = 0; i < rec_len; ++i)
+        sum += buffer[i];
+      sum = (byte)(256 - sum);
+      if (fputc (sum, p->f) == EOF)
+        return omflib_set_error (error);
+    }
+  switch (rec_type)
+    {
+    case MODEND:
+    case MODEND|REC32:
+      if (omflib_pad (p->f, p->page_size, FALSE, error) != 0)
+        return -1;
+      if (p->state != OS_SIMPLE)
+        {
+          len = strlen (p->mod_name);
+          if (len < 255)
+            {
+              memcpy (name, p->mod_name, len);
+              name[len] = '!';
+              name[len+1] = 0;
+              if (omflib_add_pub (p, name, p->mod_page, error) != 0)
+                return -1;
+            }
+        }
+      break;
+
+    case THEADR:
+      p->state = OS_EMPTY;
+      break;
+
+    case ALIAS:
+      p->state = (p->state == OS_EMPTY ? OS_SIMPLE : OS_OTHER);
+      break;
+
+    case COMENT:
+      if (p->state == OS_EMPTY && rec_len >= 3
+          && buffer[1] == IMPDEF_CLASS && buffer[2] == IMPDEF_SUBTYPE)
+        p->state = OS_SIMPLE;
+      else
+        p->state = OS_OTHER;
+      break;
+
+    default:
+      p->state = OS_OTHER;
+      break;
+    }
+  return 0;
+}
+
+
+int omflib_write_module (struct omflib *p, const char *name, word *pagep,
+                         char *error)
+{
+  byte buf[256];
+  long long_page;
+  int len;
+
+  p->state = OS_EMPTY;
+  if (omflib_module_name (p->mod_name, name) != 0)
+    {
+      strcpy (error, "Module name too long");
+      return -1;
+    }
+  long_page = ftell (p->f) / p->page_size;
+  if (long_page > 65535)
+    {
+      strcpy (error, "Library too big -- increase page size");
+      return -1;
+    }
+  *pagep = p->mod_page = (word)long_page;
+  len = strlen (name);
+  memcpy (buf+1, name, len);
+  buf[0] = (byte)len;
+  return omflib_write_record (p, THEADR, len + 1, buf, TRUE, error);
+}
Index: trunk/src/emx/src/libos2/code2.s
===================================================================
--- trunk/src/emx/src/libos2/code2.s	(revision 18)
+++ trunk/src/emx/src/libos2/code2.s	(revision 18)
@@ -0,0 +1,24 @@
+/ code2.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  _DosGetMessage
+        .globl  __msgseg32
+
+__msgseg32:
+        .byte   0xff
+        .asciz  "MSGSEG32"
+        .byte   0x01, 0x80, 0x00, 0x00
+        .long   L_tab
+
+        .align  2, 0x90
+
+_DosGetMessage:
+        PROFILE_NOFRAME
+        popl    %ecx                    /* return address */
+        pushl   $__msgseg32
+        pushl   %ecx
+        jmp     _DosTrueGetMessage
+
+L_tab:  .short  0x0000
+        .short  0xffff
Index: trunk/src/emx/src/libos2/code3.s
===================================================================
--- trunk/src/emx/src/libos2/code3.s	(revision 18)
+++ trunk/src/emx/src/libos2/code3.s	(revision 18)
@@ -0,0 +1,16 @@
+/ code3.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
+
+#include <emx/asm386.h>
+
+        .globl  _DosQueryMessageCP
+
+_DosQueryMessageCP:
+        PROFILE_NOFRAME
+        pushl   0(%esp)
+        movl    $__msgseg32, %eax
+        xchgl   20(%esp), %eax
+        xchgl   16(%esp), %eax
+        xchgl   12(%esp), %eax
+        xchgl   8(%esp), %eax
+        movl    %eax, 4(%esp)
+        jmp     _DosIQueryMessageCP
Index: trunk/src/emx/src/libos2/ctls.imp
===================================================================
--- trunk/src/emx/src/libos2/ctls.imp	(revision 18)
+++ trunk/src/emx/src/libos2/ctls.imp	(revision 18)
@@ -0,0 +1,9 @@
+;
+; ctls.imp
+;
+WinDefFileDlgProc               pmctls  5 4
+WinDefFontDlgProc               pmctls  3 4
+WinFileDlg                      pmctls  4 3
+WinFontDlg                      pmctls  2 3
+WinFreeFileDlgList              pmctls  6 1
+WinRegisterCircularSlider       pmctls 24 ?
Index: trunk/src/emx/src/libos2/dos.imp
===================================================================
--- trunk/src/emx/src/libos2/dos.imp	(revision 18)
+++ trunk/src/emx/src/libos2/dos.imp	(revision 18)
@@ -0,0 +1,195 @@
+;
+; dos.imp
+;
+DosAcknowledgeSignalException   doscalls 418 1
+DosAddMuxWaitSem                doscalls 341 2
+DosAllocMem                     doscalls 299 3
+DosAllocSharedMem               doscalls 300 4
+DosAllocThreadLocalMemory       doscalls 454 2
+DosAsyncTimer                   doscalls 350 3
+DosBeep                         doscalls 286 2
+DosCallNPipe                    doscalls 240 7
+DosCancelLockRequest            doscalls 429 2
+DosClose                        doscalls 257 1
+DosCloseChangeNotify            doscalls 442 ?
+DosCloseEventSem                doscalls 326 1
+DosCloseMutexSem                doscalls 333 1
+DosCloseMuxWaitSem              doscalls 339 1
+DosCloseVDD                     doscalls 310 1
+DosConnectNPipe                 doscalls 241 1
+DosCopy                         doscalls 258 3
+DosCreateDir                    doscalls 270 2
+DosCreateEventSem               doscalls 324 4
+DosCreateMutexSem               doscalls 331 4
+DosCreateMuxWaitSem             doscalls 337 5
+DosCreateNPipe                  doscalls 243 7
+DosCreatePipe                   doscalls 239 3
+DosCreateThread                 doscalls 311 5
+DosDebug                        doscalls 317 1
+DosDelete                       doscalls 259 1
+DosDeleteDir                    doscalls 226 1
+DosDeleteMuxWaitSem             doscalls 342 2
+DosDevConfig                    doscalls 231 2
+DosDevIOCtl                     doscalls 284 9
+DosDisConnectNPipe              doscalls 242 1
+DosDumpProcess                  doscalls 113 3
+DosDupHandle                    doscalls 260 2
+DosDynamicTrace                 doscalls 316 ?
+DosEditName                     doscalls 261 5
+DosEnterCritSec                 doscalls 232 0
+DosEnterMustComplete            doscalls 380 1
+DosEnumAttribute                doscalls 372 7
+DosErrClass                     doscalls 211 4
+DosError                        doscalls 212 1
+DosExecPgm                      doscalls 283 7
+DosExit                         doscalls 234 2
+DosExitCritSec                  doscalls 233 0
+DosExitList                     doscalls 296 2
+DosExitMustComplete             doscalls 381 1
+DosFlatToSel                    doscalls 425 R
+DosFreeThreadLocalMemory        doscalls 455 1
+DosFSAttach                     doscalls 269 5
+DosFSCtl                        doscalls 285 10
+DosFindClose                    doscalls 263 1
+DosFindFirst                    doscalls 264 7
+DosFindNext                     doscalls 265 4
+DosForceDelete                  doscalls 110 1
+DosForceSystemDump              doscalls 444 1
+DosFreeMem                      doscalls 304 1
+DosFreeModule                   doscalls 322 1
+DosFreeResource                 doscalls 353 1
+DosGetDateTime                  doscalls 230 1
+DosGetInfoBlocks                doscalls 312 2
+DosGetNamedSharedMem            doscalls 301 3
+DosGetResource                  doscalls 352 4
+DosGetSharedMem                 doscalls 302 2
+DosGiveSharedMem                doscalls 303 3
+DosInitializePorthole           doscalls 580 ?
+DosKillProcess                  doscalls 235 2
+DosKillThread                   doscalls 111 1
+DosLoadModule                   doscalls 318 4
+DosMove                         doscalls 271 2
+DosOpen                         doscalls 273 8
+DosOpenChangeNotify             doscalls 440 ?
+DosOpenEventSem                 doscalls 325 2
+DosOpenMutexSem                 doscalls 332 2
+DosOpenMuxWaitSem               doscalls 338 2
+DosOpenVDD                      doscalls 308 2
+DosPM16SemChk                   doscalls 596 ?
+DosPM16SemRst                   doscalls 875 ?
+DosPMPostEventSem               doscalls 590 ?
+DosPMRequestMutexSem            doscalls 593 ?
+DosPMWaitEventSem               doscalls 591 ?
+DosPMWaitMuxWaitSem             doscalls 595 ?
+DosPeekNPipe                    doscalls 244 6
+DosPhysicalDisk                 doscalls 287 5
+DosPostEventSem                 doscalls 328 1
+DosProfile                      doscalls 377 4
+DosProtectClose                 doscalls 638 2
+DosProtectEnumAttribute         doscalls 636 8
+DosProtectOpen                  doscalls 637 9
+DosProtectQueryFHState          doscalls 645 3
+DosProtectQueryFileInfo         doscalls 646 5
+DosProtectRead                  doscalls 641 5
+DosProtectSetFHState            doscalls 644 3
+DosProtectSetFileInfo           doscalls 643 5
+DosProtectSetFileLocks          doscalls 639 6
+DosProtectSetFilePtr            doscalls 621 5
+DosProtectSetFileSize           doscalls 640 3
+DosProtectWrite                 doscalls 642 5
+DosQueryABIOSSupport            doscalls 371 0
+DosQueryAppType                 doscalls 323 2
+DosQueryCp                      doscalls 291 3
+DosQueryCurrentDir              doscalls 274 3
+DosQueryCurrentDisk             doscalls 275 2
+DosQueryDOSProperty             doscalls 373 4
+DosQueryEventSem                doscalls 330 2
+DosQueryExtLIBPATH              doscalls 874 2
+DosQueryFHState                 doscalls 276 2
+DosQueryFSAttach                doscalls 277 5
+DosQueryFSInfo                  doscalls 278 4
+DosQueryFileInfo                doscalls 279 4
+DosQueryHeaderInfo              doscalls 582 ?
+DosQueryHType                   doscalls 224 3
+DosQueryMem                     doscalls 306 3
+DosQueryModFromEIP              doscalls 360 6
+DosQueryModuleHandle            doscalls 319 2
+DosQueryModuleName              doscalls 320 3
+DosQueryMutexSem                doscalls 336 4
+DosQueryMuxWaitSem              doscalls 343 4
+DosQueryNPHState                doscalls 245 2
+DosQueryNPipeInfo               doscalls 248 4
+DosQueryNPipeSemState           doscalls 249 3
+DosQueryPathInfo                doscalls 223 4
+DosQueryProcAddr                doscalls 321 4
+DosQueryProcType                doscalls 586 4
+DosQueryRASInfo                 doscalls 112 2
+DosQueryResourceSize            doscalls 572 4
+DosQuerySysInfo                 doscalls 348 4
+DosQuerySysState                doscalls 368 6
+DosQueryThreadContext           doscalls 877 3
+DosQueryVerify                  doscalls 225 1
+DosRaiseException               doscalls 356 1
+DosRawReadNPipe                 doscalls 246 4
+DosRawWriteNPipe                doscalls 247 2
+DosRead                         doscalls 281 4
+DosRegisterPerfCtrs             doscalls 367 3
+DosReleaseMutexSem              doscalls 335 1
+DosReplaceModule                doscalls 417 3
+DosRequestMutexSem              doscalls 334 2
+DosRequestVDD                   doscalls 309 7
+DosResetBuffer                  doscalls 254 1
+DosResetChangeNotify            doscalls 441 ?
+DosResetEventSem                doscalls 327 2
+DosResumeThread                 doscalls 237 1
+DosScanEnv                      doscalls 227 2
+DosSearchPath                   doscalls 228 5
+DosSelToFlat                    doscalls 426 R
+DosSendSignalException          doscalls 379 2
+DosSetCp                        doscalls 288 ?
+DosSetCurrentDir                doscalls 255 1
+DosSetDOSProperty               doscalls 374 4
+DosSetDateTime                  doscalls 292 1
+DosSetDefaultDisk               doscalls 220 1
+DosSetExceptionHandler          doscalls 354 1
+DosSetExtLIBPATH                doscalls 873 2
+DosSetFHState                   doscalls 221 2
+DosSetFSInfo                    doscalls 222 4
+DosSetFileInfo                  doscalls 218 4
+DosSetFileLocks                 doscalls 428 5
+DosSetFilePtr                   doscalls 256 4
+DosSetFileSize                  doscalls 272 2
+DosSetMaxFH                     doscalls 209 1
+DosSetMem                       doscalls 305 3
+DosSetNPHState                  doscalls 250 2
+DosSetNPipeSem                  doscalls 251 3
+DosSetPathInfo                  doscalls 219 5
+DosSetProcessCp                 doscalls 289 1
+DosSetRelMaxFH                  doscalls 382 2
+DosSetSignalExceptionFocus      doscalls 378 2
+DosSetVerify                    doscalls 210 1
+DosShutdown                     doscalls 415 1
+DosSleep                        doscalls 229 1
+DosStartTimer                   doscalls 351 3
+DosStopTimer                    doscalls 290 1
+DosSysCtl                       doscalls 876 ?
+DosSubAllocMem                  doscalls 345 3
+DosSubFreeMem                   doscalls 346 3
+DosSubSetMem                    doscalls 344 3
+DosSubUnsetMem                  doscalls 347 1
+DosSuppressPopUps               doscalls 114 2
+DosSuspendThread                doscalls 238 1
+DosTib                          doscalls 419 ?
+DosTmrQueryFreq                 doscalls 362 1
+DosTmrQueryTime                 doscalls 363 1
+DosSetPriority                  doscalls 236 4
+DosTransactNPipe                doscalls 252 6
+DosUnsetExceptionHandler        doscalls 355 1
+DosUnwindException              doscalls 357 3
+DosVerifyPidTid                 doscalls 460 2
+DosWaitChild                    doscalls 280 5
+DosWaitEventSem                 doscalls 329 2
+DosWaitMuxWaitSem               doscalls 340 3
+DosWaitNPipe                    doscalls 253 2
+DosWaitThread                   doscalls 349 2
+DosWrite                        doscalls 282 4
Index: trunk/src/emx/src/libos2/dos16.imp
===================================================================
--- trunk/src/emx/src/libos2/dos16.imp	(revision 18)
+++ trunk/src/emx/src/libos2/dos16.imp	(revision 18)
@@ -0,0 +1,182 @@
+;
+; dos16.imp
+;
+Dos16AllocHuge                  doscalls  40 F
+Dos16AllocSeg                   doscalls  34 F
+Dos16AllocShrSeg                doscalls  35 F
+Dos16Beep                       doscalls  50 F
+Dos16BufReset                   doscalls  56 F
+Dos16CLIAccess                  doscalls  51 F
+Dos16CWait                      doscalls   2 F
+Dos16Callback                   doscalls 157 F
+Dos16ChDir                      doscalls  57 F
+Dos16ChgFilePtr                 doscalls  58 F
+Dos16Close                      doscalls  59 F
+Dos16CloseChangeNotify          doscalls 439 F
+Dos16CloseSem                   doscalls  23 F
+Dos16CloseVDD                   doscalls 268 F
+Dos16Copy                       doscalls 201 F
+Dos16CreateCSAlias              doscalls  43 F
+Dos16CreateSem                  doscalls  24 F
+Dos16CreateThread               doscalls 145 F
+Dos16Delete                     doscalls  60 F
+Dos16DevConfig                  doscalls  52 F
+Dos16DevIOCtl                   doscalls  53 F
+Dos16DevIOCtl2                  doscalls  99 F
+Dos16DupHandle                  doscalls  61 F
+Dos16DynamicTrace               doscalls 165 F
+Dos16EditName                   doscalls 191 F
+Dos16EnterCritSec               doscalls   3 F
+Dos16EnumAttribute              doscalls 204 F
+Dos16ErrClass                   doscalls 139 F
+Dos16Error                      doscalls 120 F
+Dos16ExecPgm                    doscalls 144 F
+Dos16Exit                       doscalls   5 F
+Dos16ExitCritSec                doscalls   6 F
+Dos16ExitList                   doscalls   7 F
+Dos16FSAttach                   doscalls 181 F
+Dos16FSCtl                      doscalls 183 F
+Dos16FSRamSemClear              doscalls 162 F
+Dos16FSRamSemRequest            doscalls 161 F
+Dos16FileIO                     doscalls 186 F
+Dos16FileLocks                  doscalls  62 F
+Dos16FindClose                  doscalls  63 F
+Dos16FindFirst                  doscalls  64 F
+Dos16FindFirst2                 doscalls 184 F
+Dos16FindNext                   doscalls  65 F
+Dos16FindNotifyClose            doscalls 187 F
+Dos16FindNotifyFirst            doscalls 188 F
+Dos16FindNotifyNext             doscalls 189 F
+Dos16FlagProcess                doscalls  15 F
+Dos16FlatToSel                  doscalls 423 F
+Dos16ForceDelete                doscalls 203 F
+Dos16FreeModule                 doscalls  46 F
+Dos16FreeResource               doscalls 208 F
+Dos16FreeSeg                    doscalls  39 F
+Dos16GetCp                      doscalls 130 F
+Dos16GetDateTime                doscalls  33 F
+Dos16GetEnv                     doscalls  91 F
+Dos16GetHugeShift               doscalls  41 F
+Dos16GetInfoSeg                 doscalls   8 F
+Dos16GetMachineMode             doscalls  49 F
+Dos16GetModHandle               doscalls  47 F
+Dos16GetModName                 doscalls  48 F
+Dos16GetPID                     doscalls  94 F
+Dos16GetPPID                    doscalls 156 F
+Dos16GetProcAddr                doscalls  45 F
+Dos16GetPrty                    doscalls   9 F
+Dos16GetResource                doscalls 155 F
+Dos16GetResource2               doscalls 207 F
+Dos16GetSeg                     doscalls 121 F
+Dos16GetShrSeg                  doscalls  36 F
+Dos16GetVersion                 doscalls  92 F
+Dos16GiveSeg                    doscalls  37 F
+Dos16GlobalInfo                 doscalls 217 F
+Dos16HoldSignal                 doscalls  13 F
+Dos16HugeIncr                   doscalls 136 F
+Dos16Hugeshift                  doscalls 135 F
+Dos16InitializePortHole         doscalls 583 F
+Dos16KillProcess                doscalls  10 F
+Dos16LibInit                    doscalls  96 F
+Dos16LoadModule                 doscalls  44 F
+Dos16LocalInfo                  doscalls 216 F
+Dos16LockSeg                    doscalls 122 F
+Dos16MakePipe                   doscalls  16 F
+Dos16MaxPathLen                 doscalls 214 F
+Dos16MemAvail                   doscalls 127 F
+Dos16MkDir                      doscalls  66 F
+Dos16MkDir2                     doscalls 185 F
+Dos16Move                       doscalls  67 F
+Dos16MuxSemWait                 doscalls  22 F
+Dos16NewSize                    doscalls  68 F
+Dos16Open                       doscalls  70 F
+Dos16Open2                      doscalls  95 F
+Dos16OpenChangeNotify           doscalls 437 F
+Dos16OpenSem                    doscalls  25 F
+Dos16OpenVDD                    doscalls 266 F
+DOs16PMMuxSemWait               doscalls 575 F
+Dos16PMSemWait                  doscalls 574 F
+Dos16PageSize                   doscalls 215 F
+Dos16PhysicalDisk               doscalls 129 F
+Dos16PortAccess                 doscalls  69 F
+Dos16ProtectChgFilePtr          doscalls 634 F
+Dos16ProtectClose               doscalls 622 F
+Dos16ProtectEnumAttribute       doscalls 635 F
+Dos16ProtectFileLocks           doscalls 624 F
+Dos16ProtectFileio              doscalls 623 F
+Dos16ProtectNewSize             doscalls 627 F
+Dos16ProtectOpen                doscalls 628 F
+Dos16ProtectQFHandState         doscalls 629 F
+Dos16ProtectQFileInfo           doscalls 631 F
+Dos16ProtectSetFHandState       doscalls 630 F
+Dos16ProtectSetFileInfo         doscalls 632 F
+Dos16QAppType                   doscalls 163 F
+Dos16QCurDir                    doscalls  71 F
+Dos16QCurDisk                   doscalls  72 F
+Dos16QFHandState                doscalls  73 F
+Dos16QFSAttach                  doscalls 182 F
+Dos16QFSInfo                    doscalls  76 F
+Dos16QFileInfo                  doscalls  74 F
+Dos16QFileMode                  doscalls  75 F
+Dos16QHandType                  doscalls  77 F
+Dos16QPathInfo                  doscalls  98 F
+Dos16QProcStatus                doscalls 154 F
+Dos16QSysInfo                   doscalls 166 F
+Dos16QVerify                    doscalls  78 F
+Dos16QueryDosProperty           doscalls 375 F
+Dos16QueryExtLIBPATH            doscalls 999 F
+Dos16QueryHeaderInfo            doscalls 584 F
+Dos16QueryResourceSize          doscalls 573 F
+Dos16Queryproctype              doscalls 587 F
+Dos16R2StackRealloc             doscalls 160 F
+Dos16Read                       doscalls 137 F
+Dos16ReadAsync                  doscalls 149 F
+Dos16ReallocHuge                doscalls  42 F
+Dos16ReallocSeg                 doscalls  38 F
+Dos16RegisterPerfCtrs           doscalls 422 F
+Dos16RequestVDD                 doscalls 267 F
+Dos16ResetChangeNotify          doscalls 438 F
+Dos16ResumeThread               doscalls  26 F
+Dos16RmDir                      doscalls  80 F
+Dos16ScanEnv                    doscalls 152 F
+Dos16SearchPath                 doscalls 151 F
+Dos16SelToFlat                  doscalls 424 F
+Dos16SelectDisk                 doscalls  81 F
+Dos16SemClear                   doscalls 141 F
+Dos16SemRequest                 doscalls 140 F
+Dos16SemSet                     doscalls 143 F
+Dos16SemSetWait                 doscalls  20 F
+Dos16SemWait                    doscalls 142 F
+Dos16SendSignal                 doscalls 134 F
+Dos16SetCp                      doscalls 153 F
+Dos16SetDateTime                doscalls  28 F
+Dos16SetDosProperty             doscalls 376 F
+Dos16SetExtLIBPATH              doscalls 998 F
+Dos16SetFHandState              doscalls  82 F
+Dos16SetFSInfo                  doscalls  97 F
+Dos16SetFileInfo                doscalls  83 F
+Dos16SetFileMode                doscalls  84 F
+Dos16SetMaxFH                   doscalls  85 F
+Dos16SetPathInfo                doscalls 104 F
+Dos16SetProcCp                  doscalls 164 F
+Dos16SetPrty                    doscalls  11 F
+Dos16SetSigHandler              doscalls  14 F
+Dos16SetVec                     doscalls  89 F
+Dos16SetVerify                  doscalls  86 F
+Dos16Shutdown                   doscalls 206 F
+Dos16SizeSeg                    doscalls 126 F
+Dos16Sleep                      doscalls  32 F
+Dos16SubAlloc                   doscalls 147 F
+Dos16SubFree                    doscalls 148 F
+Dos16SubSet                     doscalls 146 F
+Dos16SuspendThread              doscalls  27 F
+Dos16SysTrace                   doscalls  90 F
+Dos16SystemService              doscalls  88 F
+Dos16TimerAsync                 doscalls  29 F
+Dos16TimerStart                 doscalls  30 F
+Dos16TimerStop                  doscalls  31 F
+Dos16TmrQueryFreq               doscalls 420 F
+Dos16TmrQueryTime               doscalls 421 F
+Dos16UnlockSeg                  doscalls 123 F
+Dos16Write                      doscalls 138 F
+Dos16WriteAsync                 doscalls 150 F
Index: trunk/src/emx/src/libos2/drag.imp
===================================================================
--- trunk/src/emx/src/libos2/drag.imp	(revision 18)
+++ trunk/src/emx/src/libos2/drag.imp	(revision 18)
@@ -0,0 +1,44 @@
+;
+; drag.imp
+;
+DrgAcceptDroppedFiles           pmdrag 66 5
+DrgAccessDraginfo               pmdrag 32 1
+DrgAddStrHandle                 pmdrag 33 1
+DrgAllocDraginfo                pmdrag 34 1
+DrgAllocDragtransfer            pmdrag 35 1
+DrgCancelLazyDrag               pmdrag 68 0
+DrgDeleteDraginfoStrHandles     pmdrag 36 1
+DrgDeleteStrHandle              pmdrag 37 1
+DrgDrag                         pmdrag 38 6
+DrgDragFiles                    pmdrag 65 9
+DrgFreeDraginfo                 pmdrag 39 1
+DrgFreeDragtransfer             pmdrag 40 1
+DrgGetPS                        pmdrag 41 1
+DrgLazyDrag                     pmdrag 67 5
+DrgLazyDrop                     pmdrag 69 3
+DrgPostTransferMsg              pmdrag 42 6
+DrgPushDraginfo                 pmdrag 43 2
+DrgQueryDragStatus              pmdrag 73 0
+DrgQueryDraginfoPtr             pmdrag 70 1
+DrgQueryDraginfoPtrFromDragitem pmdrag 72 1
+DrgQueryDraginfoPtrFromHwnd     pmdrag 71 1
+DrgQueryDragitem                pmdrag 44 4
+DrgQueryDragitemCount           pmdrag 45 1
+DrgQueryDragitemPtr             pmdrag 46 2
+DrgQueryNativeRMF               pmdrag 47 3
+DrgQueryNativeRMFLen            pmdrag 48 1
+DrgQueryStrName                 pmdrag 49 3
+DrgQueryStrNameLen              pmdrag 50 1
+DrgQueryTrueType                pmdrag 51 3
+DrgQueryTrueTypeLen             pmdrag 52 1
+DrgReallocDraginfo              pmdrag 74 2
+DrgReleasePS                    pmdrag 53 1
+DrgSendTransferMsg              pmdrag 54 4
+DrgSetDragImage                 pmdrag 56 4
+DrgSetDragPointer               pmdrag 55 2
+DrgSetDragitem                  pmdrag 57 4
+DrgVerifyNativeRMF              pmdrag 58 2
+DrgVerifyRMF                    pmdrag 59 3
+DrgVerifyTrueType               pmdrag 60 2
+DrgVerifyType                   pmdrag 61 2
+DrgVerifyTypeSet                pmdrag 62 4
Index: trunk/src/emx/src/libos2/emxwrap.def
===================================================================
--- trunk/src/emx/src/libos2/emxwrap.def	(revision 18)
+++ trunk/src/emx/src/libos2/emxwrap.def	(revision 18)
@@ -0,0 +1,122 @@
+;
+; emxwrap.def
+;
+LIBRARY EMXWRAP INITINSTANCE
+DESCRIPTION 'emxwrap.dll 0.9d -- Copyright (c) 1993-1998 by Eberhard Mattes'
+DATA
+   SINGLE NONSHARED
+EXPORTS
+  EMX_REVISION = emx_revision @1 RESIDENTNAME
+
+  WinDefAVioWindowProc        @30
+
+  VioEndPopUp                 @101
+  VioGetPhysBuf               @102
+  VioGetAnsi                  @103
+  VioSetAnsi                  @105
+  VioDeRegister               @106
+  VioScrollUp                 @107
+  VioPrtSc                    @108
+  VioGetCurPos                @109
+  VioWrtCellStr               @110
+  VioPopUp                    @111
+  VioScrollRt                 @112
+  VioWrtCharStr               @113
+  VioSetCurPos                @115
+  VioScrUnLock                @118
+  VioWrtTTY                   @119
+  VioGetMode                  @121
+  VioSetMode                  @122
+  VioScrLock                  @123
+  VioReadCellStr              @124
+  VioSavRedrawWait            @125
+  VioWrtNAttr                 @126
+  VioGetCurType               @127
+  VioSavRedrawUndo            @128
+  VioGetFont                  @129
+  VioReadCharStr              @130
+  VioGetBuf                   @131
+  VioSetCurType               @132
+  VioSetFont                  @133
+  VioModeUndo                 @135
+  VioModeWait                 @137
+  VioGetCp                    @140
+  VioSetCp                    @142
+  VioShowBuf                  @143
+  VioScrollLf                 @144
+  VioRegister                 @145
+  VioGetConfig                @146
+  VioScrollDn                 @147
+  VioWrtCharStrAtt            @148
+  VioGetState                 @149
+  VioPrtScToggle              @150
+  VioSetState                 @151
+  VioWrtNCell                 @152
+  VioWrtNChar                 @153
+  VioAssociate                @155
+  VioCreatePS                 @156
+  VioDeleteSetId              @157
+  VioGetDeviceCellSize        @158
+  VioGetOrg                   @159
+  VioCreateLogFont            @160
+  VioDestroyPS                @161
+  VioQuerySetIds              @162
+  VioSetOrg                   @163
+  VioQueryFonts               @164
+  VioSetDeviceCellSize        @165
+  VioShowPS                   @166
+  VioGlobalReg                @170
+  VioCheckCharType            @175
+
+  KbdSetCustXt                @201
+  KbdGetCp                    @203
+  KbdCharIn                   @204
+  KbdSetCp                    @205
+  KbdSynch                    @207
+  KbdRegister                 @208
+  KbdStringIn                 @209
+  KbdGetStatus                @210
+  KbdSetStatus                @211
+  KbdGetFocus                 @212
+  KbdFlushBuffer              @213
+  KbdXlate                    @214
+  KbdClose                    @217
+  KbdFreeFocus                @218
+  KbdDeRegister               @220
+  KbdSetFgnd                  @221
+  KbdPeek                     @222
+  KbdOpen                     @223
+  KbdGetHWID                  @224
+  KbdSetHWID                  @225
+
+  MouGetPtrShape              @301
+  MouSetPtrShape              @302
+  MouGetNumMickeys            @303
+  MouGetScaleFact             @306
+  MouFlushQue                 @307
+  MouGetNumButtons            @308
+  MouClose                    @309
+  MouSetScaleFact             @311
+  MouGetNumQueEl              @313
+  MouDeRegister               @314
+  MouGetEventMask             @315
+  MouSetEventMask             @316
+  MouOpen                     @317
+  MouRemovePtr                @318
+  MouGetPtrPos                @319
+  MouReadEventQue             @320
+  MouSetPtrPos                @321
+  MouGetDevStatus             @322
+  MouSynch                    @323
+  MouRegister                 @324
+  MouSetDevStatus             @325
+  MouDrawPtr                  @326
+  MouInitReal                 @327
+  MouSetThreshold             @329
+  MouGetThreshold             @330
+
+  DosMonWrite                 @401
+  DosMonRead                  @402
+  DosMonClose                 @403
+  DosMonOpen                  @404
+  DosMonReg                   @405
Index: trunk/src/emx/src/libos2/gpi.imp
===================================================================
--- trunk/src/emx/src/libos2/gpi.imp	(revision 18)
+++ trunk/src/emx/src/libos2/gpi.imp	(revision 18)
@@ -0,0 +1,277 @@
+;
+; gpi.imp
+;
+DevCloseDC                      pmgpi 604 1
+DevEscape                       pmgpi 605 6
+DevOpenDC                       pmgpi 610 6
+DevPostDeviceModes              pmgpi 609 6
+DevQueryCaps                    pmgpi 606 4
+DevQueryDeviceNames             pmgpi 607 7
+DevQueryHardcopyCaps            pmgpi 608 4
+DevStdOpen                      pmgpi 625 ?
+GpiAnimatePalette               pmgpi 595 5
+GpiAssociate                    pmgpi 351 2
+GpiBeginArea                    pmgpi 352 2
+GpiBeginElement                 pmgpi 353 3
+GpiBeginInkPath                 pmgpi 670 3
+GpiBeginPath                    pmgpi 354 2
+GpiBitBlt                       pmgpi 355 6
+GpiBox                          pmgpi 356 5
+GpiCallSegmentMatrix            pmgpi 357 5
+GpiCharString                   pmgpi 358 3
+GpiCharStringAt                 pmgpi 359 4
+GpiCharStringPos                pmgpi 580 6
+GpiCharStringPosAt              pmgpi 581 7
+GpiCloseFigure                  pmgpi 360 1
+GpiCloseSegment                 pmgpi 361 1
+GpiCombineRegion                pmgpi 362 5
+GpiComment                      pmgpi 363 3
+GpiConvert                      pmgpi 364 5
+GpiConvertWithMatrix            pmgpi 618 5
+GpiCopyMetaFile                 pmgpi 365 1
+GpiCorrelateChain               pmgpi 366 6
+GpiCorrelateFrom                pmgpi 367 8
+GpiCorrelateSegment             pmgpi 582 7
+GpiCreateBitmap                 pmgpi 598 5
+GpiCreateLogColorTable          pmgpi 592 6
+GpiCreateLogFont                pmgpi 368 4
+GpiCreatePS                     pmgpi 369 4
+GpiCreatePalette                pmgpi 594 5
+GpiCreateRegion                 pmgpi 370 3
+GpiDeleteBitmap                 pmgpi 371 1
+GpiDeleteElement                pmgpi 372 1
+GpiDeleteElementRange           pmgpi 373 3
+GpiDeleteElementsBetweenLabels  pmgpi 374 3
+GpiDeleteMetaFile               pmgpi 375 1
+GpiDeletePalette                pmgpi 577 1
+GpiDeleteSegment                pmgpi 376 2
+GpiDeleteSegments               pmgpi 377 3
+GpiDeleteSetId                  pmgpi 378 2
+GpiDestroyPS                    pmgpi 379 1
+GpiDestroyRegion                pmgpi 611 2
+GpiDrawBits                     pmgpi 603 7
+GpiDrawChain                    pmgpi 380 1
+GpiDrawDynamics                 pmgpi 381 1
+GpiDrawFrom                     pmgpi 382 3
+GpiDrawSegment                  pmgpi 383 2
+GpiElement                      pmgpi 384 5
+GpiEndArea                      pmgpi 385 1
+GpiEndElement                   pmgpi 386 1
+GpiEndInkPath                   pmgpi 671 2
+GpiEndPath                      pmgpi 387 1
+GpiEqualRegion                  pmgpi 388 3
+GpiErase                        pmgpi 389 1
+GpiErrorSegmentData             pmgpi 390 3
+GpiExcludeClipRectangle         pmgpi 391 2
+GpiFillPath                     pmgpi 392 3
+GpiFloodFill                    pmgpi 560 3
+GpiFrameRegion                  pmgpi 617 3
+GpiFullArc                      pmgpi 393 3
+GpiGetData                      pmgpi 394 6
+GpiImage                        pmgpi 395 5
+GpiIntersectClipRectangle       pmgpi 396 2
+GpiLabel                        pmgpi 397 2
+GpiLine                         pmgpi 398 2
+GpiLoadBitmap                   pmgpi 399 5
+GpiLoadFonts                    pmgpi 400 2
+GpiLoadMetaFile                 pmgpi 401 2
+GpiLoadPublicFonts              pmgpi 622 2
+GpiMarker                       pmgpi 402 2
+GpiModifyPath                   pmgpi 403 3
+GpiMove                         pmgpi 404 2
+GpiOffsetClipRegion             pmgpi 405 2
+GpiOffsetElementPointer         pmgpi 406 2
+GpiOffsetRegion                 pmgpi 407 3
+GpiOpenSegment                  pmgpi 408 2
+GpiOutlinePath                  pmgpi 563 3
+GpiPaintRegion                  pmgpi 409 2
+GpiPartialArc                   pmgpi 612 5
+GpiPathToRegion                 pmgpi 559 3
+GpiPlayMetaFile                 pmgpi 411 7
+GpiPointArc                     pmgpi 412 2
+GpiPolyFillet                   pmgpi 413 3
+GpiPolyFilletSharp              pmgpi 414 4
+GpiPolyLine                     pmgpi 415 3
+GpiPolyLineDisjoint             pmgpi 558 3
+GpiPolyMarker                   pmgpi 416 3
+GpiPolySpline                   pmgpi 417 3
+GpiPolygons                     pmgpi 650 5
+GpiPop                          pmgpi 418 2
+GpiPtInRegion                   pmgpi 419 3
+GpiPtVisible                    pmgpi 420 2
+GpiPutData                      pmgpi 421 4
+GpiQueryArcParams               pmgpi 422 2
+GpiQueryAttrMode                pmgpi 423 1
+GpiQueryAttrs                   pmgpi 583 4
+GpiQueryBackColor               pmgpi 424 1
+GpiQueryBackMix                 pmgpi 425 1
+GpiQueryBitmapBits              pmgpi 599 5
+GpiQueryBitmapDimension         pmgpi 426 2
+GpiQueryBitmapHandle            pmgpi 427 2
+GpiQueryBitmapInfoHeader        pmgpi 601 2
+GpiQueryBitmapParameters        pmgpi 573 2
+GpiQueryBoundaryData            pmgpi 428 2
+GpiQueryCharAngle               pmgpi 429 2
+GpiQueryCharBox                 pmgpi 430 2
+GpiQueryCharBreakExtra          pmgpi 615 2
+GpiQueryCharDirection           pmgpi 431 1
+GpiQueryCharExtra               pmgpi 613 2
+GpiQueryCharMode                pmgpi 432 1
+GpiQueryCharSet                 pmgpi 433 1
+GpiQueryCharShear               pmgpi 434 2
+GpiQueryCharStringPos           pmgpi 584 6
+GpiQueryCharStringPosAt         pmgpi 585 7
+GpiQueryClipBox                 pmgpi 435 2
+GpiQueryClipRegion              pmgpi 436 1
+GpiQueryColor                   pmgpi 437 1
+GpiQueryColorData               pmgpi 438 3
+GpiQueryColorIndex              pmgpi 439 3
+GpiQueryCp                      pmgpi 440 1
+GpiQueryCurrentPosition         pmgpi 441 2
+GpiQueryDefArcParams            pmgpi 567 2
+GpiQueryDefAttrs                pmgpi 590 4
+GpiQueryDefCharBox              pmgpi 442 2
+GpiQueryDefTag                  pmgpi 568 2
+GpiQueryDefViewingLimits        pmgpi 569 2
+GpiQueryDefaultViewMatrix       pmgpi 443 3
+GpiQueryDevice                  pmgpi 444 1
+GpiQueryDeviceBitmapFormats     pmgpi 445 3
+GpiQueryDrawControl             pmgpi 446 2
+GpiQueryDrawingMode             pmgpi 447 1
+GpiQueryEditMode                pmgpi 448 1
+GpiQueryElement                 pmgpi 449 4
+GpiQueryElementPointer          pmgpi 450 1
+GpiQueryElementType             pmgpi 451 4
+GpiQueryFaceString              pmgpi 575 5
+GpiQueryFontAction              pmgpi 576 2
+GpiQueryFontFileDescriptions    pmgpi 452 4
+GpiQueryFontMetrics             pmgpi 453 3
+GpiQueryFonts                   pmgpi 586 6
+GpiQueryFullFontFileDescs       pmgpi 657 5
+GpiQueryGraphicsField           pmgpi 454 2
+GpiQueryInitialSegmentAttrs     pmgpi 455 2
+GpiQueryKerningPairs            pmgpi 456 3
+GpiQueryLineEnd                 pmgpi 457 1
+GpiQueryLineJoin                pmgpi 458 1
+GpiQueryLineType                pmgpi 459 1
+GpiQueryLineWidth               pmgpi 460 1
+GpiQueryLineWidthGeom           pmgpi 461 1
+GpiQueryLogColorTable           pmgpi 593 5
+GpiQueryLogicalFont             pmgpi 574 5
+GpiQueryMarker                  pmgpi 462 1
+GpiQueryMarkerBox               pmgpi 463 2
+GpiQueryMarkerSet               pmgpi 464 1
+GpiQueryMetaFileBits            pmgpi 465 4
+GpiQueryMetaFileLength          pmgpi 466 1
+GpiQueryMix                     pmgpi 467 1
+GpiQueryModelTransformMatrix    pmgpi 468 3
+GpiQueryNearestColor            pmgpi 469 3
+GpiQueryNumberSetIds            pmgpi 470 1
+GpiQueryPS                      pmgpi 471 2
+GpiQueryPageViewport            pmgpi 472 2
+GpiQueryPalette                 pmgpi 579 1
+GpiQueryPaletteInfo             pmgpi 597 5
+GpiQueryPattern                 pmgpi 473 1
+GpiQueryPatternRefPoint         pmgpi 474 2
+GpiQueryPatternSet              pmgpi 475 1
+GpiQueryPel                     pmgpi 476 2
+GpiQueryPickAperturePosition    pmgpi 477 2
+GpiQueryPickApertureSize        pmgpi 478 2
+GpiQueryRGBColor                pmgpi 479 3
+GpiQueryRealColors              pmgpi 480 5
+GpiQueryRegionBox               pmgpi 481 3
+GpiQueryRegionRects             pmgpi 587 5
+GpiQuerySegmentAttrs            pmgpi 482 3
+GpiQuerySegmentNames            pmgpi 483 5
+GpiQuerySegmentPriority         pmgpi 484 3
+GpiQuerySegmentTransformMatrix  pmgpi 485 4
+GpiQuerySetIds                  pmgpi 486 5
+GpiQueryStopDraw                pmgpi 487 1
+GpiQueryTag                     pmgpi 488 2
+GpiQueryTextAlignment           pmgpi 648 3
+GpiQueryTextBox                 pmgpi 489 5
+GpiQueryViewingLimits           pmgpi 490 2
+GpiQueryViewingTransformMatrix  pmgpi 491 3
+GpiQueryWidthTable              pmgpi 492 4
+GpiRectInRegion                 pmgpi 494 3
+GpiRectVisible                  pmgpi 495 2
+GpiRemoveDynamics               pmgpi 496 3
+GpiResetBoundaryData            pmgpi 497 1
+GpiResetPS                      pmgpi 498 2
+GpiRestorePS                    pmgpi 499 2
+GpiResumePlay                   pmgpi 562 ?
+GpiRotate                       pmgpi 566 5
+GpiSaveMetaFile                 pmgpi 500 2
+GpiSavePS                       pmgpi 501 1
+GpiScale                        pmgpi 565 5
+GpiSelectPalette                pmgpi 578 2
+GpiSetArcParams                 pmgpi 502 2
+GpiSetAttrMode                  pmgpi 503 2
+GpiSetAttrs                     pmgpi 588 5
+GpiSetBackColor                 pmgpi 504 2
+GpiSetBackMix                   pmgpi 505 2
+GpiSetBitmap                    pmgpi 506 2
+GpiSetBitmapBits                pmgpi 602 5
+GpiSetBitmapDimension           pmgpi 507 2
+GpiSetBitmapId                  pmgpi 508 3
+GpiSetCharAngle                 pmgpi 509 2
+GpiSetCharBox                   pmgpi 510 2
+GpiSetCharBreakExtra            pmgpi 616 2
+GpiSetCharDirection             pmgpi 511 2
+GpiSetCharExtra                 pmgpi 614 2
+GpiSetCharMode                  pmgpi 512 2
+GpiSetCharSet                   pmgpi 513 2
+GpiSetCharShear                 pmgpi 514 2
+GpiSetClipPath                  pmgpi 515 3
+GpiSetClipRegion                pmgpi 516 3
+GpiSetColor                     pmgpi 517 2
+GpiSetCp                        pmgpi 518 2
+GpiSetCurrentPosition           pmgpi 519 2
+GpiSetDefArcParams              pmgpi 570 2
+GpiSetDefAttrs                  pmgpi 591 4
+GpiSetDefTag                    pmgpi 571 2
+GpiSetDefViewingLimits          pmgpi 572 2
+GpiSetDefaultViewMatrix         pmgpi 520 4
+GpiSetDrawControl               pmgpi 521 3
+GpiSetDrawingMode               pmgpi 522 2
+GpiSetEditMode                  pmgpi 523 2
+GpiSetElementPointer            pmgpi 524 2
+GpiSetElementPointerAtLabel     pmgpi 525 2
+GpiSetGraphicsField             pmgpi 526 2
+GpiSetInitialSegmentAttrs       pmgpi 527 3
+GpiSetLineEnd                   pmgpi 528 2
+GpiSetLineJoin                  pmgpi 529 2
+GpiSetLineType                  pmgpi 530 2
+GpiSetLineWidth                 pmgpi 531 2
+GpiSetLineWidthGeom             pmgpi 532 2
+GpiSetMarker                    pmgpi 533 2
+GpiSetMarkerBox                 pmgpi 534 2
+GpiSetMarkerSet                 pmgpi 535 2
+GpiSetMetaFileBits              pmgpi 536 4
+GpiSetMix                       pmgpi 537 2
+GpiSetModelTransformMatrix      pmgpi 538 4
+GpiSetPS                        pmgpi 539 3
+GpiSetPageViewport              pmgpi 540 2
+GpiSetPaletteEntries            pmgpi 596 5
+GpiSetPattern                   pmgpi 541 2
+GpiSetPatternRefPoint           pmgpi 542 2
+GpiSetPatternSet                pmgpi 543 2
+GpiSetPel                       pmgpi 544 2
+GpiSetPickAperturePosition      pmgpi 545 2
+GpiSetPickApertureSize          pmgpi 589 3
+GpiSetRegion                    pmgpi 546 4
+GpiSetSegmentAttrs              pmgpi 547 4
+GpiSetSegmentPriority           pmgpi 548 4
+GpiSetSegmentTransformMatrix    pmgpi 549 5
+GpiSetStopDraw                  pmgpi 550 2
+GpiSetTag                       pmgpi 551 2
+GpiSetTextAlignment             pmgpi 649 3
+GpiSetViewingLimits             pmgpi 552 2
+GpiSetViewingTransformMatrix    pmgpi 553 4
+GpiStrokeInkPath                pmgpi 672 5
+GpiStrokePath                   pmgpi 554 3
+GpiSuspendPlay                  pmgpi 561 ?
+GpiTranslate                    pmgpi 564 4
+GpiUnloadFonts                  pmgpi 555 2
+GpiUnloadPublicFonts            pmgpi 623 2
+GpiWCBitBlt                     pmgpi 557 6
Index: trunk/src/emx/src/libos2/help.imp
===================================================================
--- trunk/src/emx/src/libos2/help.imp	(revision 18)
+++ trunk/src/emx/src/libos2/help.imp	(revision 18)
@@ -0,0 +1,24 @@
+;
+; help.imp
+;
+DdfBeginList                    helpmgr  82 4
+DdfBitmap                       helpmgr  88 3
+DdfEndList                      helpmgr  84 1
+DdfHyperText                    helpmgr  81 4
+DdfInform                       helpmgr  79 3
+DdfInitialize                   helpmgr  74 3
+DdfListItem                     helpmgr  83 3
+DdfMetafile                     helpmgr  86 3
+DdfPara                         helpmgr  75 1
+DdfSetColor                     helpmgr  78 3
+DdfSetFont                      helpmgr  87 4
+DdfSetFontStyle                 helpmgr  80 2
+DdfSetFormat                    helpmgr  76 2
+DdfSetTextAlign                 helpmgr  77 2
+DdfText                         helpmgr  85 2
+WinAssociateHelpInstance        helpmgr  54 2
+WinCreateHelpInstance           helpmgr  51 2
+WinCreateHelpTable              helpmgr  56 2
+WinDestroyHelpInstance          helpmgr  52 1
+WinLoadHelpTable                helpmgr  55 3
+WinQueryHelpInstance            helpmgr  53 1
Index: trunk/src/emx/src/libos2/kbd1.c
===================================================================
--- trunk/src/emx/src/libos2/kbd1.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd1.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd1.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetCustXt) ();
+
+USHORT KbdSetCustXt (PUSHORT pusCodePage, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pusCodePage);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16SetCustXt)));
+}
Index: trunk/src/emx/src/libos2/kbd10.c
===================================================================
--- trunk/src/emx/src/libos2/kbd10.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd10.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd10.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16GetStatus) ();
+
+USHORT KbdGetStatus (PKBDINFO pkbdinfo, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdinfo);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16GetStatus)));
+}
Index: trunk/src/emx/src/libos2/kbd11.c
===================================================================
--- trunk/src/emx/src/libos2/kbd11.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd11.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd11.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetStatus) ();
+
+USHORT KbdSetStatus (PKBDINFO pkbdinfo, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdinfo);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16SetStatus)));
+}
Index: trunk/src/emx/src/libos2/kbd12.c
===================================================================
--- trunk/src/emx/src/libos2/kbd12.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd12.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd12.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16GetFocus) ();
+
+USHORT KbdGetFocus (USHORT fWait, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2);
+           _THUNK_SHORT (fWait);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16GetFocus)));
+}
Index: trunk/src/emx/src/libos2/kbd13.c
===================================================================
--- trunk/src/emx/src/libos2/kbd13.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd13.c	(revision 18)
@@ -0,0 +1,14 @@
+/* kbd13.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16FlushBuffer) ();
+
+USHORT KbdFlushBuffer (HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16FlushBuffer)));
+}
Index: trunk/src/emx/src/libos2/kbd14.c
===================================================================
--- trunk/src/emx/src/libos2/kbd14.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd14.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd14.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Xlate) ();
+
+USHORT KbdXlate (PKBDTRANS pkbdtrans, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdtrans);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16Xlate)));
+}
Index: trunk/src/emx/src/libos2/kbd16.imp
===================================================================
--- trunk/src/emx/src/libos2/kbd16.imp	(revision 18)
+++ trunk/src/emx/src/libos2/kbd16.imp	(revision 18)
@@ -0,0 +1,23 @@
+;
+; kbd16.imp
+;
+Kbd16CharIn                     kbdcalls   4 F
+Kbd16Close                      kbdcalls  17 F
+Kbd16DeRegister                 kbdcalls  20 F
+Kbd16FlushBuffer                kbdcalls  13 F
+Kbd16FreeFocus                  kbdcalls  18 F
+Kbd16GetCp                      kbdcalls   3 F
+Kbd16GetFocus                   kbdcalls  12 F
+Kbd16GetHWID                    kbdcalls  24 F
+Kbd16GetStatus                  kbdcalls  10 F
+Kbd16Open                       kbdcalls  23 F
+Kbd16Peek                       kbdcalls  22 F
+Kbd16Register                   kbdcalls   8 F
+Kbd16SetCp                      kbdcalls   5 F
+Kbd16SetCustXt                  kbdcalls   1 F
+Kbd16SetFgnd                    kbdcalls  21 F
+Kbd16SetHWID                    kbdcalls  25 F
+Kbd16SetStatus                  kbdcalls  11 F
+Kbd16StringIn                   kbdcalls   9 F
+Kbd16Synch                      kbdcalls   7 F
+Kbd16Xlate                      kbdcalls  14 F
Index: trunk/src/emx/src/libos2/kbd17.c
===================================================================
--- trunk/src/emx/src/libos2/kbd17.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd17.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd17.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Close) ();
+
+
+USHORT KbdClose (HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16Close)));
+}
Index: trunk/src/emx/src/libos2/kbd18.c
===================================================================
--- trunk/src/emx/src/libos2/kbd18.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd18.c	(revision 18)
@@ -0,0 +1,14 @@
+/* kbd18.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16FreeFocus) ();
+
+USHORT KbdFreeFocus (HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16FreeFocus)));
+}
Index: trunk/src/emx/src/libos2/kbd20.c
===================================================================
--- trunk/src/emx/src/libos2/kbd20.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd20.c	(revision 18)
@@ -0,0 +1,13 @@
+/* kbd20.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16DeRegister) ();
+
+USHORT KbdDeRegister (VOID)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (0);
+           _THUNK_CALL (Kbd16DeRegister)));
+}
Index: trunk/src/emx/src/libos2/kbd21.c
===================================================================
--- trunk/src/emx/src/libos2/kbd21.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd21.c	(revision 18)
@@ -0,0 +1,13 @@
+/* kbd21.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetFgnd) ();
+
+USHORT KbdSetFgnd (VOID)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (0);
+           _THUNK_CALL (Kbd16SetFgnd)));
+}
Index: trunk/src/emx/src/libos2/kbd22.c
===================================================================
--- trunk/src/emx/src/libos2/kbd22.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd22.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd22.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Peek) ();
+
+USHORT KbdPeek (PKBDKEYINFO pkbci, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbci);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16Peek)));
+}
Index: trunk/src/emx/src/libos2/kbd23.c
===================================================================
--- trunk/src/emx/src/libos2/kbd23.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd23.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd23.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Open) ();
+
+
+USHORT KbdOpen (PHKBD phkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4);
+           _THUNK_FLAT (phkbd);
+           _THUNK_CALL (Kbd16Open)));
+}
Index: trunk/src/emx/src/libos2/kbd24.c
===================================================================
--- trunk/src/emx/src/libos2/kbd24.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd24.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd24.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16GetHWID) ();
+
+USHORT KbdGetHWID (PKBDHWID pkbdhwid, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdhwid);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16GetHWID)));
+}
Index: trunk/src/emx/src/libos2/kbd25.c
===================================================================
--- trunk/src/emx/src/libos2/kbd25.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd25.c	(revision 18)
@@ -0,0 +1,15 @@
+/* kbd25.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetHWID) ();
+
+USHORT KbdSetHWID (PKBDHWID pkbdhwid, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pkbdhwid);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16SetHWID)));
+}
Index: trunk/src/emx/src/libos2/kbd3.c
===================================================================
--- trunk/src/emx/src/libos2/kbd3.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd3.c	(revision 18)
@@ -0,0 +1,16 @@
+/* kbd3.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16GetCp) ();
+
+USHORT KbdGetCp (ULONG ulReserved, PUSHORT pidCP, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_LONG (ulReserved);
+           _THUNK_FLAT (pidCP);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16GetCp)));
+}
Index: trunk/src/emx/src/libos2/kbd4.c
===================================================================
--- trunk/src/emx/src/libos2/kbd4.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd4.c	(revision 18)
@@ -0,0 +1,16 @@
+/* kbd4.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16CharIn) ();
+
+USHORT KbdCharIn (PKBDKEYINFO pkbci, USHORT fWait, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2);
+           _THUNK_FLAT (pkbci);
+           _THUNK_SHORT (fWait);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16CharIn)));
+}
Index: trunk/src/emx/src/libos2/kbd5.c
===================================================================
--- trunk/src/emx/src/libos2/kbd5.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd5.c	(revision 18)
@@ -0,0 +1,16 @@
+/* kbd5.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16SetCp) ();
+
+USHORT KbdSetCp (USHORT usReserved, USHORT idCP, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usReserved);
+           _THUNK_SHORT (idCP);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16SetCp)));
+}
Index: trunk/src/emx/src/libos2/kbd7.c
===================================================================
--- trunk/src/emx/src/libos2/kbd7.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd7.c	(revision 18)
@@ -0,0 +1,14 @@
+/* kbd7.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Synch) ();
+
+USHORT KbdSynch (USHORT fWait)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (fWait);
+           _THUNK_CALL (Kbd16Synch)));
+}
Index: trunk/src/emx/src/libos2/kbd8.c
===================================================================
--- trunk/src/emx/src/libos2/kbd8.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd8.c	(revision 18)
@@ -0,0 +1,16 @@
+/* kbd8.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16Register) ();
+
+USHORT KbdRegister (PCSZ pszModName, PCSZ pszEntryName, ULONG ulFunMask)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4);
+           _THUNK_FLAT ((PSZ)pszModName);
+           _THUNK_FLAT ((PSZ)pszEntryName);
+           _THUNK_LONG (ulFunMask);
+           _THUNK_CALL (Kbd16Register)));
+}
Index: trunk/src/emx/src/libos2/kbd9.c
===================================================================
--- trunk/src/emx/src/libos2/kbd9.c	(revision 18)
+++ trunk/src/emx/src/libos2/kbd9.c	(revision 18)
@@ -0,0 +1,17 @@
+/* kbd9.c */
+
+#define INCL_KBD
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Kbd16StringIn) ();
+
+USHORT KbdStringIn (PCH pch, PSTRINGINBUF pchIn, USHORT fWait, HKBD hkbd)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2+2);
+           _THUNK_FLAT (pch);
+           _THUNK_FLAT (pchIn);
+           _THUNK_SHORT (fWait);
+           _THUNK_SHORT (hkbd);
+           _THUNK_CALL (Kbd16StringIn)));
+}
Index: trunk/src/emx/src/libos2/mon1.c
===================================================================
--- trunk/src/emx/src/libos2/mon1.c	(revision 18)
+++ trunk/src/emx/src/libos2/mon1.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mon1.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonWrite) ();
+
+USHORT DosMonWrite (PBYTE pbOutBuf, PBYTE pbDataBuf, USHORT cbData)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pbOutBuf);
+           _THUNK_FLAT (pbDataBuf);
+           _THUNK_SHORT (cbData);
+           _THUNK_CALL (Dos16MonWrite)));
+}
Index: trunk/src/emx/src/libos2/mon16.imp
===================================================================
--- trunk/src/emx/src/libos2/mon16.imp	(revision 18)
+++ trunk/src/emx/src/libos2/mon16.imp	(revision 18)
@@ -0,0 +1,8 @@
+;
+; mon16.imp
+;
+Dos16MonWrite                   moncalls  1 F
+Dos16MonRead                    moncalls  2 F
+Dos16MonClose                   moncalls  3 F
+Dos16MonOpen                    moncalls  4 F
+Dos16MonReg                     moncalls  5 F
Index: trunk/src/emx/src/libos2/mon2.c
===================================================================
--- trunk/src/emx/src/libos2/mon2.c	(revision 18)
+++ trunk/src/emx/src/libos2/mon2.c	(revision 18)
@@ -0,0 +1,18 @@
+/* mon2.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonRead) ();
+
+USHORT DosMonRead (PBYTE pbInBuf, USHORT fWait, PBYTE pbDataBuf,
+                   PUSHORT pcbData)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+4+4);
+           _THUNK_FLAT (pbInBuf);
+           _THUNK_SHORT (fWait);
+           _THUNK_FLAT (pbDataBuf);
+           _THUNK_FLAT (pcbData);
+           _THUNK_CALL (Dos16MonRead)));
+}
Index: trunk/src/emx/src/libos2/mon3.c
===================================================================
--- trunk/src/emx/src/libos2/mon3.c	(revision 18)
+++ trunk/src/emx/src/libos2/mon3.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mon3.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonClose) ();
+
+USHORT DosMonClose (HMONITOR hmon)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hmon);
+           _THUNK_CALL (Dos16MonClose)));
+}
Index: trunk/src/emx/src/libos2/mon4.c
===================================================================
--- trunk/src/emx/src/libos2/mon4.c	(revision 18)
+++ trunk/src/emx/src/libos2/mon4.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mon4.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonOpen) ();
+
+USHORT DosMonOpen (PSZ pszDevName, PHMONITOR phmon)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4);
+           _THUNK_FLAT (pszDevName);
+           _THUNK_FLAT (phmon);
+           _THUNK_CALL (Dos16MonOpen)));
+}
Index: trunk/src/emx/src/libos2/mon5.c
===================================================================
--- trunk/src/emx/src/libos2/mon5.c	(revision 18)
+++ trunk/src/emx/src/libos2/mon5.c	(revision 18)
@@ -0,0 +1,19 @@
+/* mon5.c */
+
+#define INCL_DOSMONITORS
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Dos16MonReg) ();
+
+USHORT DosMonReg (HMONITOR hmon, PBYTE pbInBuf, PBYTE pbOutBuf,
+		  USHORT fPosition, USHORT usIndex)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+4+2+2);
+           _THUNK_SHORT (hmon);
+           _THUNK_FLAT (pbInBuf);
+           _THUNK_FLAT (pbOutBuf);
+           _THUNK_SHORT (fPosition);
+           _THUNK_SHORT (usIndex);
+           _THUNK_CALL (Dos16MonReg)));
+}
Index: trunk/src/emx/src/libos2/mou1.c
===================================================================
--- trunk/src/emx/src/libos2/mou1.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou1.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mou1.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetPtrShape) ();
+
+USHORT MouGetPtrShape (PBYTE pBuf, PPTRSHAPE pmoupsInfo, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pBuf);
+           _THUNK_FLAT (pmoupsInfo);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetPtrShape)));
+}
Index: trunk/src/emx/src/libos2/mou11.c
===================================================================
--- trunk/src/emx/src/libos2/mou11.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou11.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou11.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetScaleFact) ();
+
+USHORT MouSetScaleFact (PSCALEFACT pmouscFactors, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmouscFactors);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetScaleFact)));
+}
Index: trunk/src/emx/src/libos2/mou13.c
===================================================================
--- trunk/src/emx/src/libos2/mou13.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou13.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou13.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetNumQueEl) ();
+
+USHORT MouGetNumQueEl (PMOUQUEINFO qmouqi, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (qmouqi);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetNumQueEl)));
+}
Index: trunk/src/emx/src/libos2/mou14.c
===================================================================
--- trunk/src/emx/src/libos2/mou14.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou14.c	(revision 18)
@@ -0,0 +1,13 @@
+/* mou14.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16DeRegister) ();
+
+USHORT MouDeRegister (VOID)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (0);
+           _THUNK_CALL (Mou16DeRegister)));
+}
Index: trunk/src/emx/src/libos2/mou15.c
===================================================================
--- trunk/src/emx/src/libos2/mou15.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou15.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou15.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetEventMask) ();
+
+USHORT MouGetEventMask (PUSHORT pfsEvents, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfsEvents);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetEventMask)));
+}
Index: trunk/src/emx/src/libos2/mou16.c
===================================================================
--- trunk/src/emx/src/libos2/mou16.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou16.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou16.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetEventMask) ();
+
+USHORT MouSetEventMask (PUSHORT pfsEvents, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfsEvents);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetEventMask)));
+}
Index: trunk/src/emx/src/libos2/mou16.imp
===================================================================
--- trunk/src/emx/src/libos2/mou16.imp	(revision 18)
+++ trunk/src/emx/src/libos2/mou16.imp	(revision 18)
@@ -0,0 +1,30 @@
+;
+; Mou16.imp
+;
+Mou16Close                      moucalls   9 F
+Mou16DeRegister                 moucalls  14 F
+Mou16DrawPtr                    moucalls  26 F
+Mou16FlushQue                   moucalls   7 F
+Mou16GetDevStatus               moucalls  22 F
+Mou16GetEventMask               moucalls  15 F
+Mou16GetHotKey                  moucalls   4 F
+Mou16GetNumButtons              moucalls   8 F
+Mou16GetNumMickeys              moucalls   3 F
+Mou16GetNumQueEl                moucalls  13 F
+Mou16GetPtrPos                  moucalls  19 F
+Mou16GetPtrShape                moucalls   1 F
+Mou16GetScaleFact               moucalls   6 F
+Mou16GetThreshold               moucalls  29 F
+Mou16InitReal                   moucalls  27 F
+Mou16Open                       moucalls  17 F
+Mou16ReadEventQue               moucalls  20 F
+Mou16Register                   moucalls  24 F
+Mou16RemovePtr                  moucalls  18 F
+Mou16SetDevStatus               moucalls  25 F
+Mou16SetEventMask               moucalls  16 F
+Mou16SetHotKey                  moucalls  10 F
+Mou16SetPtrPos                  moucalls  21 F
+Mou16SetPtrShape                moucalls   2 F
+Mou16SetScaleFact               moucalls  11 F
+Mou16SetThreshold               moucalls  30 F
+Mou16Synch                      moucalls  23 F
Index: trunk/src/emx/src/libos2/mou17.c
===================================================================
--- trunk/src/emx/src/libos2/mou17.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou17.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou17.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16Open) ();
+
+USHORT MouOpen (PCSZ pszDvrName, PHMOU phmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4);
+           _THUNK_FLAT ((PSZ)pszDvrName);
+           _THUNK_FLAT (phmou);
+           _THUNK_CALL (Mou16Open)));
+}
Index: trunk/src/emx/src/libos2/mou18.c
===================================================================
--- trunk/src/emx/src/libos2/mou18.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou18.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou18.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16RemovePtr) ();
+
+USHORT MouRemovePtr (PNOPTRRECT pmourtRect, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmourtRect);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16RemovePtr)));
+}
Index: trunk/src/emx/src/libos2/mou19.c
===================================================================
--- trunk/src/emx/src/libos2/mou19.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou19.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou19.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetPtrPos) ();
+
+USHORT MouGetPtrPos (PPTRLOC pmouLoc, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmouLoc);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetPtrPos)));
+}
Index: trunk/src/emx/src/libos2/mou2.c
===================================================================
--- trunk/src/emx/src/libos2/mou2.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou2.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mou2.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetPtrShape) ();
+
+USHORT MouSetPtrShape (PBYTE pBuf, PPTRSHAPE pmoupsInfo, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pBuf);
+           _THUNK_FLAT (pmoupsInfo);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetPtrShape)));
+}
Index: trunk/src/emx/src/libos2/mou20.c
===================================================================
--- trunk/src/emx/src/libos2/mou20.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou20.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mou20.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16ReadEventQue) ();
+
+USHORT MouReadEventQue (PMOUEVENTINFO pmouevEvent, PUSHORT pfWait, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pmouevEvent);
+           _THUNK_FLAT (pfWait);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16ReadEventQue)));
+}
Index: trunk/src/emx/src/libos2/mou21.c
===================================================================
--- trunk/src/emx/src/libos2/mou21.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou21.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou21.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetPtrPos) ();
+
+USHORT MouSetPtrPos (PPTRLOC pmouLoc, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmouLoc);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetPtrPos)));
+}
Index: trunk/src/emx/src/libos2/mou22.c
===================================================================
--- trunk/src/emx/src/libos2/mou22.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou22.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou22.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetDevStatus) ();
+
+USHORT MouGetDevStatus (PUSHORT pfsDevStatus, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfsDevStatus);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetDevStatus)));
+}
Index: trunk/src/emx/src/libos2/mou23.c
===================================================================
--- trunk/src/emx/src/libos2/mou23.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou23.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou23.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16Synch) ();
+
+USHORT MouSynch (USHORT fWait)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (fWait);
+           _THUNK_CALL (Mou16Synch)));
+}
Index: trunk/src/emx/src/libos2/mou24.c
===================================================================
--- trunk/src/emx/src/libos2/mou24.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou24.c	(revision 18)
@@ -0,0 +1,16 @@
+/* mou24.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16Register) ();
+
+USHORT MouRegister (PCSZ pszModName, PCSZ pszEntryName, ULONG ulFunMask)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4);
+           _THUNK_FLAT ((PSZ)pszModName);
+           _THUNK_FLAT ((PSZ)pszEntryName);
+           _THUNK_LONG (ulFunMask);
+           _THUNK_CALL (Mou16Register)));
+}
Index: trunk/src/emx/src/libos2/mou25.c
===================================================================
--- trunk/src/emx/src/libos2/mou25.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou25.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou25.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetDevStatus) ();
+
+USHORT MouSetDevStatus (PUSHORT pfsDevStatus, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfsDevStatus);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetDevStatus)));
+}
Index: trunk/src/emx/src/libos2/mou26.c
===================================================================
--- trunk/src/emx/src/libos2/mou26.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou26.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou26.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16DrawPtr) ();
+
+USHORT MouDrawPtr (HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16DrawPtr)));
+}
Index: trunk/src/emx/src/libos2/mou27.c
===================================================================
--- trunk/src/emx/src/libos2/mou27.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou27.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou27.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16InitReal) ();
+
+USHORT MouInitReal (PCSZ pszDriverName)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4);
+           _THUNK_FLAT ((PSZ)pszDriverName);
+           _THUNK_CALL (Mou16InitReal)));
+}
Index: trunk/src/emx/src/libos2/mou29.c
===================================================================
--- trunk/src/emx/src/libos2/mou29.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou29.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou29.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16SetThreshold) ();
+
+USHORT MouSetThreshold (PTHRESHOLD pthreshold, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pthreshold);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16SetThreshold)));
+}
Index: trunk/src/emx/src/libos2/mou3.c
===================================================================
--- trunk/src/emx/src/libos2/mou3.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou3.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou3.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetNumMickeys) ();
+
+USHORT MouGetNumMickeys (PUSHORT pcMickeys, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pcMickeys);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetNumMickeys)));
+}
Index: trunk/src/emx/src/libos2/mou30.c
===================================================================
--- trunk/src/emx/src/libos2/mou30.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou30.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou30.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetThreshold) ();
+
+USHORT MouGetThreshold (PTHRESHOLD pthreshold, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pthreshold);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetThreshold)));
+}
Index: trunk/src/emx/src/libos2/mou6.c
===================================================================
--- trunk/src/emx/src/libos2/mou6.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou6.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou6.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetScaleFact) ();
+
+USHORT MouGetScaleFact (PSCALEFACT pmouscFactors, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pmouscFactors);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetScaleFact)));
+}
Index: trunk/src/emx/src/libos2/mou7.c
===================================================================
--- trunk/src/emx/src/libos2/mou7.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou7.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou7.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16FlushQue) ();
+
+USHORT MouFlushQue (HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16FlushQue)));
+}
Index: trunk/src/emx/src/libos2/mou8.c
===================================================================
--- trunk/src/emx/src/libos2/mou8.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou8.c	(revision 18)
@@ -0,0 +1,15 @@
+/* mou8.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16GetNumButtons) ();
+
+USHORT MouGetNumButtons (PUSHORT pcButtons, HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pcButtons);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16GetNumButtons)));
+}
Index: trunk/src/emx/src/libos2/mou9.c
===================================================================
--- trunk/src/emx/src/libos2/mou9.c	(revision 18)
+++ trunk/src/emx/src/libos2/mou9.c	(revision 18)
@@ -0,0 +1,14 @@
+/* mou9.c */
+
+#define INCL_MOU
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Mou16Close) ();
+
+USHORT MouClose (HMOU hmou)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hmou);
+           _THUNK_CALL (Mou16Close)));
+}
Index: trunk/src/emx/src/libos2/msg.imp
===================================================================
--- trunk/src/emx/src/libos2/msg.imp	(revision 18)
+++ trunk/src/emx/src/libos2/msg.imp	(revision 18)
@@ -0,0 +1,7 @@
+;
+; msg.imp
+;
+DosInsertMessage        msg 4 7
+DosPutMessage           msg 5 3
+DosTrueGetMessage       msg 6 8
+DosIQueryMessageCP      msg 8 5
Index: trunk/src/emx/src/libos2/nls.imp
===================================================================
--- trunk/src/emx/src/libos2/nls.imp	(revision 18)
+++ trunk/src/emx/src/libos2/nls.imp	(revision 18)
@@ -0,0 +1,7 @@
+;
+; nls.imp
+;
+DosMapCase              nls        7 3
+DosQueryCollate         nls        8 4
+DosQueryCtryInfo        nls        5 4
+DosQueryDBCSEnv         nls        6 3
Index: trunk/src/emx/src/libos2/pic.imp
===================================================================
--- trunk/src/emx/src/libos2/pic.imp	(revision 18)
+++ trunk/src/emx/src/libos2/pic.imp	(revision 18)
@@ -0,0 +1,6 @@
+;
+; pic.imp
+;
+PicIchg                         pmpic 12 4
+PicPrint                        pmpic 11 4
+PrfPif2Met                      pmpic 13 ?
Index: trunk/src/emx/src/libos2/pmmerge.imp
===================================================================
--- trunk/src/emx/src/libos2/pmmerge.imp	(revision 18)
+++ trunk/src/emx/src/libos2/pmmerge.imp	(revision 18)
@@ -0,0 +1,5 @@
+;
+; pmmerge.imp
+;
+WinQueryControlColors           pmmerge 5470 5
+WinSetControlColors             pmmerge 5471 5
Index: trunk/src/emx/src/libos2/pmviop16.imp
===================================================================
--- trunk/src/emx/src/libos2/pmviop16.imp	(revision 18)
+++ trunk/src/emx/src/libos2/pmviop16.imp	(revision 18)
@@ -0,0 +1,4 @@
+;
+; pmviop16.imp
+;
+Win16DefAVioWindowProc          pmviop    30 F
Index: trunk/src/emx/src/libos2/pmviop30.c
===================================================================
--- trunk/src/emx/src/libos2/pmviop30.c	(revision 18)
+++ trunk/src/emx/src/libos2/pmviop30.c	(revision 18)
@@ -0,0 +1,17 @@
+/* pmviop30.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Win16DefAVioWindowProc) ();
+
+MRESULT WinDefAVioWindowProc (HWND hwnd, USHORT msg, ULONG mp1, ULONG mp2)
+{
+  return ((MRESULT)
+          (_THUNK_PROLOG (4+2+4+4);
+           _THUNK_LONG ((ULONG)hwnd);
+           _THUNK_SHORT (msg);
+           _THUNK_LONG (mp1);
+           _THUNK_LONG (mp2);
+           _THUNK_CALL (Win16DefAVioWindowProc)));
+}
Index: trunk/src/emx/src/libos2/que.imp
===================================================================
--- trunk/src/emx/src/libos2/que.imp	(revision 18)
+++ trunk/src/emx/src/libos2/que.imp	(revision 18)
@@ -0,0 +1,11 @@
+;
+; que.imp
+;
+DosCloseQueue           quecalls  11 1
+DosCreateQueue          quecalls  16 3
+DosOpenQueue            quecalls  15 3
+DosPeekQueue            quecalls  13 8
+DosPurgeQueue           quecalls  10 1
+DosQueryQueue           quecalls  12 2
+DosReadQueue            quecalls   9 8
+DosWriteQueue           quecalls  14 5
Index: trunk/src/emx/src/libos2/revision.c
===================================================================
--- trunk/src/emx/src/libos2/revision.c	(revision 18)
+++ trunk/src/emx/src/libos2/revision.c	(revision 18)
@@ -0,0 +1,19 @@
+/* revision.c (emx+gcc) -- Copyright (c) 1993-1999 by Eberhard Mattes */
+
+#define INCL_REXXSAA
+#include <os2emx.h>
+
+static char const revision[] = "60";
+
+ULONG emx_revision (PCSZ name, LONG argc, const RXSTRING *argv,
+                    PCSZ queuename, PRXSTRING retstr)
+{
+  int i;
+
+  if (argc != 0)
+    return 1;
+  for (i = 0; revision[i] != 0; ++i)
+    retstr->strptr[i] = revision[i];
+  retstr->strlength = i;
+  return 0;
+}
Index: trunk/src/emx/src/libos2/rexx.imp
===================================================================
--- trunk/src/emx/src/libos2/rexx.imp	(revision 18)
+++ trunk/src/emx/src/libos2/rexx.imp	(revision 18)
@@ -0,0 +1,8 @@
+;
+; rexx.imp
+;
+RexxStart               rexx       1 9
+RexxVariablePool        rexx       2 1
+RexxSetHalt             rexx       3 2
+RexxSetTrace            rexx       4 2
+RexxResetTrace          rexx       5 2
Index: trunk/src/emx/src/libos2/rexxapi.imp
===================================================================
--- trunk/src/emx/src/libos2/rexxapi.imp	(revision 18)
+++ trunk/src/emx/src/libos2/rexxapi.imp	(revision 18)
@@ -0,0 +1,32 @@
+;
+; rexxapi.imp
+;
+RexxAddMacro                    rexxapi   22 3
+RexxAddQueue                    rexxapi    3 ?
+RexxCallExit                    rexxapi   15 ?
+RexxCallFunction                rexxapi   21 ?
+RexxCallSubcom                  rexxapi   16 ?
+RexxClearMacroSpace             rexxapi   24 0
+RexxCreateQueue                 rexxapi    1 ?
+RexxDeleteQueue                 rexxapi    2 ?
+RexxDeregisterExit              rexxapi   13 2
+RexxDeregisterFunction          rexxapi   19 1
+RexxDeregisterSubcom            rexxapi    9 2
+RexxDropMacro                   rexxapi   23 1
+RexxExecuteMacroFunction        rexxapi   29 ?
+RexxLoadMacroSpace              rexxapi   25 3
+RexxLoadSubcom                  rexxapi   10 ?
+RexxPullQueue                   rexxapi    4 ?
+RexxQueryExit                   rexxapi   14 4
+RexxQueryFunction               rexxapi   20 1
+RexxQueryMacro                  rexxapi   26 2
+RexxQueryQueue                  rexxapi    5 ?
+RexxQuerySubcom                 rexxapi    8 4
+RexxRegisterExitDll             rexxapi   11 5
+RexxRegisterExitExe             rexxapi   12 3
+RexxRegisterFunctionDll         rexxapi   17 3
+RexxRegisterFunctionExe         rexxapi   18 2
+RexxRegisterSubcomDll           rexxapi    6 5
+RexxRegisterSubcomExe           rexxapi    7 3
+RexxReorderMacro                rexxapi   27 2
+RexxSaveMacroSpace              rexxapi   28 3
Index: trunk/src/emx/src/libos2/ses.imp
===================================================================
--- trunk/src/emx/src/libos2/ses.imp	(revision 18)
+++ trunk/src/emx/src/libos2/ses.imp	(revision 18)
@@ -0,0 +1,7 @@
+;
+; ses.imp
+;
+DosSelectSession        sesmgr    38 1
+DosSetSession           sesmgr    39 2
+DosStartSession         sesmgr    37 3
+DosStopSession          sesmgr    40 2
Index: trunk/src/emx/src/libos2/shl.imp
===================================================================
--- trunk/src/emx/src/libos2/shl.imp	(revision 18)
+++ trunk/src/emx/src/libos2/shl.imp	(revision 18)
@@ -0,0 +1,32 @@
+;
+; shl.imp
+;
+PrfAddProgram                   pmshapi 109 3
+PrfChangeProgram                pmshapi 110 3
+PrfCloseProfile                 pmshapi 103 1
+PrfDestroyGroup                 pmshapi 106 2
+PrfOpenProfile                  pmshapi 102 2
+PrfQueryDefinition              pmshapi 111 4
+PrfQueryProfile                 pmshapi 107 2
+PrfQueryProfileData             pmshapi 117 5
+PrfQueryProfileInt              pmshapi 114 4
+PrfQueryProfileSize             pmshapi 101 4
+PrfQueryProfileString           pmshapi 115 6
+PrfQueryProgramTitles           pmshapi 113 5
+PrfRemoveProgram                pmshapi 104 2
+PrfReset                        pmshapi 108 2
+PrfWriteProfileData             pmshapi 118 5
+PrfWriteProfileString           pmshapi 116 4
+WinAddSwitchEntry               pmshapi 120 1
+WinChangeSwitchEntry            pmshapi 123 2
+WinCreateSwitchEntry            pmshapi 121 2
+WinQuerySessionTitle            pmshapi 122 4
+WinQuerySwitchEntry             pmshapi 124 2
+WinQuerySwitchHandle            pmshapi 125 2
+WinQuerySwitchList              pmshapi 126 3
+WinQueryTaskSizePos             pmshapi 127 3
+WinQueryTaskTitle               pmshapi 128 3
+WinRemoveSwitchEntry            pmshapi 129 1
+WinStartApp                     pmshapi 119 5
+WinSwitchToProgram              pmshapi 131 1
+WinTerminateApp                 pmshapi 130 1
Index: trunk/src/emx/src/libos2/som.imp
===================================================================
--- trunk/src/emx/src/libos2/som.imp	(revision 18)
+++ trunk/src/emx/src/libos2/som.imp	(revision 18)
@@ -0,0 +1,50 @@
+;
+; som.imp
+;
+SOMCalloc                       som        1 ?
+SOMClassCClassData              som        2 ?
+SOMClassClassData               som        3 ?
+SOMClassInitFuncName            som        4 ?
+SOMClassMgrCClassData           som        5 ?
+SOMClassMgrClassData            som        6 ?
+SOMClassMgrNewClass             som       20 ?
+SOMClassMgrObject               som        7 ?
+SOMClassNewClass                som       21 ?
+SOMDeleteModule                 som        8 ?
+SOMError                        som        9 ?
+SOMFree                         som       10 ?
+SOMLoadModule                   som       11 ?
+SOMMalloc                       som       12 ?
+SOMObjectCClassData             som       13 ?
+SOMObjectClassData              som       14 ?
+SOMObjectNewClass               som       22 ?
+SOMOutCharRoutine               som       15 ?
+SOMRealloc                      som       16 ?
+SOM_AssertLevel                 som       17 ?
+SOM_TraceLevel                  som       18 ?
+SOM_WarnLevel                   som       19 ?
+somAssert                       som       23 5
+somBeginPersistentIds           som       24 0
+somCheckArgs                    som       25 ?
+somCheckId                      som       26 1
+somCompareIds                   som       27 2
+somConstructClass               som       28 4
+somDataResolve                  som       47 2
+somEndPersistentIds             som       29 0
+somEnvironmentNew               som       30 0
+somIdFromString                 som       31 1
+somLPrintf                      som       32 ?
+somParentResolve                som       33 2
+somPrefixLevel                  som       34 1
+somPrintf                       som       35 ?
+somRegisterId                   som       36 1
+somResolve                      som       37 2
+somSaveMetrics                  som       38 ?
+somSetExpectedIds               som       39 2
+somStringFromId                 som       40 1
+somTest                         som       41 5
+somTestCls                      som       42 4
+somTotalRegIds                  som       43 0
+somUniqueKey                    som       44 1
+somVprintf                      som       45 2
+somWriteMetrics                 som       46 ?
Index: trunk/src/emx/src/libos2/spl.imp
===================================================================
--- trunk/src/emx/src/libos2/spl.imp	(revision 18)
+++ trunk/src/emx/src/libos2/spl.imp	(revision 18)
@@ -0,0 +1,60 @@
+;
+; spl.imp
+;
+PrtAbort                        pmspl 375 1
+PrtClose                        pmspl 373 1
+PrtDevIOCtl                     pmspl 372 5
+PrtOpen                         pmspl 370 8
+PrtWrite                        pmspl 371 4
+SplControlDevice                pmspl 380 3
+SplCopyJob                      pmspl 442 6
+SplCreateDevice                 pmspl 401 4
+SplCreatePort                   pmspl 413 6
+SplCreateQueue                  pmspl 393 4
+SplDeleteDevice                 pmspl 403 2
+SplDeleteJob                    pmspl 386 3
+SplDeletePort                   pmspl 414 2
+SplDeleteQueue                  pmspl 396 2
+SplEnumDevice                   pmspl 382 8
+SplEnumDriver                   pmspl 406 8
+SplEnumJob                      pmspl 392 9
+SplEnumPort                     pmspl 408 8
+SplEnumPrinter                  pmspl 441 9
+SplEnumQueue                    pmspl 399 8
+SplEnumQueueProcessor           pmspl 407 8
+SplHoldJob                      pmspl 385 3
+SplHoldQueue                    pmspl 394 2
+SplInit                         pmspl 320 ?
+SplMessageBox                   pmspl 307 7
+SplPurgeQueue                   pmspl 404 2
+SplQmAbort                      pmspl 305 1
+SplQmAbortDoc                   pmspl 308 1
+SplQmClose                      pmspl 306 1
+SplQmEndDoc                     pmspl 303 1
+SplQmGetJobID                   pmspl 608 5
+SplQmNewPage                    pmspl 607 2
+SplQmOpen                       pmspl 301 3
+SplQmSetup                      pmspl 443 ?
+SplQmStartDoc                   pmspl 302 2
+SplQmWrite                      pmspl 304 3
+SplQueryDevice                  pmspl 381 6
+SplQueryDriver                  pmspl 446 7
+SplQueryJob                     pmspl 390 7
+SplQueryJobId                   pmspl 405 ?
+SplQueryPath                    pmspl 412 ?
+SplQueryPort                    pmspl 410 6
+SplQueryQueue                   pmspl 397 6
+SplReleaseJob                   pmspl 384 3
+SplReleaseQueue                 pmspl 395 2
+SplSetDevice                    pmspl 402 6
+SplSetDriver                    pmspl 447 7
+SplSetJob                       pmspl 391 7
+SplSetPort                      pmspl 411 6
+SplSetQueue                     pmspl 398 6
+SplStdClose                     pmspl 351 1
+SplStdDelete                    pmspl 354 1
+SplStdGetBits                   pmspl 355 4
+SplStdOpen                      pmspl 350 1
+SplStdQueryLength               pmspl 356 1
+SplStdStart                     pmspl 352 1
+SplStdStop                      pmspl 353 1
Index: trunk/src/emx/src/libos2/vio1.c
===================================================================
--- trunk/src/emx/src/libos2/vio1.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio1.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio1.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16EndPopUp) ();
+
+USHORT VioEndPopUp (HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16EndPopUp)));
+}
Index: trunk/src/emx/src/libos2/vio10.c
===================================================================
--- trunk/src/emx/src/libos2/vio10.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio10.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio10.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtCellStr) ();
+
+USHORT VioWrtCellStr (PCCH pchCellStr, USHORT cb, USHORT usRow,
+                      USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PCH)pchCellStr);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtCellStr)));
+}
Index: trunk/src/emx/src/libos2/vio11.c
===================================================================
--- trunk/src/emx/src/libos2/vio11.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio11.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio11.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16PopUp) ();
+
+USHORT VioPopUp (PUSHORT pfWait, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfWait);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16PopUp)));
+}
Index: trunk/src/emx/src/libos2/vio12.c
===================================================================
--- trunk/src/emx/src/libos2/vio12.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio12.c	(revision 18)
@@ -0,0 +1,21 @@
+/* vio12.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrollRt) ();
+
+USHORT VioScrollRt (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbCol, PBYTE pCell, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2+2+4+2);
+           _THUNK_SHORT (usTopRow);
+           _THUNK_SHORT (usLeftCol);
+           _THUNK_SHORT (usBotRow);
+           _THUNK_SHORT (usRightCol);
+           _THUNK_SHORT (cbCol);
+           _THUNK_FLAT (pCell);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrollRt)));
+}
Index: trunk/src/emx/src/libos2/vio13.c
===================================================================
--- trunk/src/emx/src/libos2/vio13.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio13.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio13.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtCharStr) ();
+
+USHORT VioWrtCharStr (PCCH pch, USHORT cb, USHORT usRow, USHORT usColumn,
+                      HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PCH)pch);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtCharStr)));
+}
Index: trunk/src/emx/src/libos2/vio15.c
===================================================================
--- trunk/src/emx/src/libos2/vio15.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio15.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio15.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetCurPos) ();
+
+USHORT VioSetCurPos (USHORT usRow, USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetCurPos)));
+}
Index: trunk/src/emx/src/libos2/vio16.imp
===================================================================
--- trunk/src/emx/src/libos2/vio16.imp	(revision 18)
+++ trunk/src/emx/src/libos2/vio16.imp	(revision 18)
@@ -0,0 +1,61 @@
+;
+; vio16.imp
+;
+Vio16Associate                  viocalls  55 F
+Vio16CheckCharType              viocalls  75 F
+Vio16CreateLogFont              viocalls  60 F
+Vio16CreatePS                   viocalls  56 F
+Vio16DeleteSetId                viocalls  57 F
+Vio16DeRegister                 viocalls   6 F
+Vio16DestroyPS                  viocalls  61 F
+Vio16EndPopUp                   viocalls   1 F
+Vio16GetAnsi                    viocalls   3 F
+Vio16GetBuf                     viocalls  31 F
+Vio16GetConfig                  viocalls  46 F
+Vio16GetCp                      viocalls  40 F
+Vio16GetCurPos                  viocalls   9 F
+Vio16GetCurType                 viocalls  27 F
+Vio16GetDeviceCellSize          viocalls  58 F
+Vio16GetFont                    viocalls  29 F
+Vio16GetMode                    viocalls  21 F
+Vio16GetOrg                     viocalls  59 F
+Vio16GetPhysBuf                 viocalls   2 F
+Vio16GetPSAddress               viocalls  67 F
+Vio16GetState                   viocalls  49 F
+Vio16GlobalReg                  viocalls  70 F
+Vio16ModeUndo                   viocalls  35 F
+Vio16ModeWait                   viocalls  37 F
+Vio16PopUp                      viocalls  11 F
+Vio16PrtSc                      viocalls   8 F
+Vio16PrtScToggle                viocalls  50 F
+Vio16QueryFonts                 viocalls  64 F
+Vio16QuerySetIds                viocalls  62 F
+Vio16ReadCellStr                viocalls  24 F
+Vio16ReadCharStr                viocalls  30 F
+Vio16Register                   viocalls  45 F
+Vio16SavRedrawUndo              viocalls  28 F
+Vio16SavRedrawWait              viocalls  25 F
+Vio16ScrLock                    viocalls  23 F
+Vio16ScrollDn                   viocalls  47 F
+Vio16ScrollLf                   viocalls  44 F
+Vio16ScrollRt                   viocalls  12 F
+Vio16ScrollUp                   viocalls   7 F
+Vio16ScrUnLock                  viocalls  18 F
+Vio16SetAnsi                    viocalls   5 F
+Vio16SetCp                      viocalls  42 F
+Vio16SetCurPos                  viocalls  15 F
+Vio16SetCurType                 viocalls  32 F
+Vio16SetDeviceCellSize          viocalls  65 F
+Vio16SetFont                    viocalls  33 F
+Vio16SetMode                    viocalls  22 F
+Vio16SetOrg                     viocalls  63 F
+Vio16SetState                   viocalls  51 F
+Vio16ShowBuf                    viocalls  43 F
+Vio16ShowPS                     viocalls  66 F
+Vio16WrtCellStr                 viocalls  10 F
+Vio16WrtCharStr                 viocalls  13 F
+Vio16WrtCharStrAtt              viocalls  48 F
+Vio16WrtNAttr                   viocalls  26 F
+Vio16WrtNCell                   viocalls  52 F
+Vio16WrtNChar                   viocalls  53 F
+Vio16WrtTTY                     viocalls  19 F
Index: trunk/src/emx/src/libos2/vio18.c
===================================================================
--- trunk/src/emx/src/libos2/vio18.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio18.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio18.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrUnLock) ();
+
+USHORT VioScrUnLock (HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrUnLock)));
+}
Index: trunk/src/emx/src/libos2/vio19.c
===================================================================
--- trunk/src/emx/src/libos2/vio19.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio19.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio19.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtTTY) ();
+
+USHORT VioWrtTTY (PCCH pch, USHORT cb, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2);
+           _THUNK_FLAT ((PCH)pch);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtTTY)));
+}
Index: trunk/src/emx/src/libos2/vio2.c
===================================================================
--- trunk/src/emx/src/libos2/vio2.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio2.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio2.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetPhysBuf) ();
+
+USHORT VioGetPhysBuf (PVIOPHYSBUF pvioPhysBuf, USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioPhysBuf);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16GetPhysBuf)));
+}
Index: trunk/src/emx/src/libos2/vio21.c
===================================================================
--- trunk/src/emx/src/libos2/vio21.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio21.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio21.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetMode) ();
+
+USHORT VioGetMode (PVIOMODEINFO pvioModeInfo, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioModeInfo);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetMode)));
+}
Index: trunk/src/emx/src/libos2/vio22.c
===================================================================
--- trunk/src/emx/src/libos2/vio22.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio22.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio22.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetMode) ();
+
+USHORT VioSetMode (PVIOMODEINFO pvioModeInfo, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioModeInfo);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetMode)));
+}
Index: trunk/src/emx/src/libos2/vio23.c
===================================================================
--- trunk/src/emx/src/libos2/vio23.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio23.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio23.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrLock) ();
+
+USHORT VioScrLock (USHORT fWait, PUCHAR pfNotLocked, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (fWait);
+           _THUNK_FLAT (pfNotLocked);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrLock)));
+}
Index: trunk/src/emx/src/libos2/vio24.c
===================================================================
--- trunk/src/emx/src/libos2/vio24.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio24.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio24.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ReadCellStr) ();
+
+USHORT VioReadCellStr (PCH pchCellStr, PUSHORT pcb, USHORT usRow,
+                       USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2+2+2);
+           _THUNK_FLAT (pchCellStr);
+           _THUNK_FLAT (pcb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ReadCellStr)));
+}
Index: trunk/src/emx/src/libos2/vio25.c
===================================================================
--- trunk/src/emx/src/libos2/vio25.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio25.c	(revision 18)
@@ -0,0 +1,17 @@
+/* vio25.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SavRedrawWait) ();
+
+USHORT VioSavRedrawWait (USHORT usRedrawInd, PUSHORT pusNotifyType,
+                         USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (usRedrawInd);
+           _THUNK_FLAT (pusNotifyType);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16SavRedrawWait)));
+}
Index: trunk/src/emx/src/libos2/vio26.c
===================================================================
--- trunk/src/emx/src/libos2/vio26.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio26.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio26.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtNAttr) ();
+
+USHORT VioWrtNAttr (const BYTE *pAttr, USHORT cb, USHORT usRow,
+                    USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PBYTE)pAttr);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtNAttr)));
+}
Index: trunk/src/emx/src/libos2/vio27.c
===================================================================
--- trunk/src/emx/src/libos2/vio27.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio27.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio27.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetCurType) ();
+
+USHORT VioGetCurType (PVIOCURSORINFO pvioCursorInfo, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioCursorInfo);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetCurType)));
+}
Index: trunk/src/emx/src/libos2/vio28.c
===================================================================
--- trunk/src/emx/src/libos2/vio28.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio28.c	(revision 18)
@@ -0,0 +1,17 @@
+/* vio28.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SavRedrawUndo) ();
+
+USHORT VioSavRedrawUndo (USHORT usOwnerInd, USHORT usKillInd,
+                         USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usOwnerInd);
+           _THUNK_SHORT (usKillInd);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16SavRedrawUndo)));
+}
Index: trunk/src/emx/src/libos2/vio29.c
===================================================================
--- trunk/src/emx/src/libos2/vio29.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio29.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio29.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetFont) ();
+
+USHORT VioGetFont (PVIOFONTINFO pviofi, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pviofi);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetFont)));
+}
Index: trunk/src/emx/src/libos2/vio3.c
===================================================================
--- trunk/src/emx/src/libos2/vio3.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio3.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio3.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetAnsi) ();
+
+USHORT VioGetAnsi (PUSHORT pfAnsi, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pfAnsi);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetAnsi)));
+}
Index: trunk/src/emx/src/libos2/vio30.c
===================================================================
--- trunk/src/emx/src/libos2/vio30.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio30.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio30.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ReadCharStr) ();
+
+USHORT VioReadCharStr (PCH pch, PUSHORT pcb, USHORT usRow, USHORT usColumn,
+                       HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2+2+2);
+           _THUNK_FLAT (pch);
+           _THUNK_FLAT (pcb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ReadCharStr)));
+}
Index: trunk/src/emx/src/libos2/vio31.c
===================================================================
--- trunk/src/emx/src/libos2/vio31.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio31.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio31.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetBuf) ();
+
+USHORT VioGetBuf (PULONG pLVB, PUSHORT pcbLVB, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pLVB);
+           _THUNK_FLAT (pcbLVB);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetBuf)));
+}
Index: trunk/src/emx/src/libos2/vio32.c
===================================================================
--- trunk/src/emx/src/libos2/vio32.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio32.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio32.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetCurType) ();
+
+USHORT VioSetCurType (PVIOCURSORINFO pvioCursorInfo, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioCursorInfo);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetCurType)));
+}
Index: trunk/src/emx/src/libos2/vio33.c
===================================================================
--- trunk/src/emx/src/libos2/vio33.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio33.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio33.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetFont) ();
+
+USHORT VioSetFont (PVIOFONTINFO pviofi, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pviofi);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetFont)));
+}
Index: trunk/src/emx/src/libos2/vio35.c
===================================================================
--- trunk/src/emx/src/libos2/vio35.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio35.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio35.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ModeUndo) ();
+
+USHORT VioModeUndo (USHORT usOwnerInd, USHORT usKillInd, USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usOwnerInd);
+           _THUNK_SHORT (usKillInd);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16ModeUndo)));
+}
Index: trunk/src/emx/src/libos2/vio37.c
===================================================================
--- trunk/src/emx/src/libos2/vio37.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio37.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio37.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ModeWait) ();
+
+USHORT VioModeWait (USHORT usReqType, PUSHORT pNotifyType, USHORT usReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (usReqType);
+           _THUNK_FLAT (pNotifyType);
+           _THUNK_SHORT (usReserved);
+           _THUNK_CALL (Vio16ModeWait)));
+}
Index: trunk/src/emx/src/libos2/vio40.c
===================================================================
--- trunk/src/emx/src/libos2/vio40.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio40.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio40.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetCp) ();
+
+USHORT VioGetCp (USHORT usReserved, PUSHORT pusCodePage, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (usReserved);
+           _THUNK_FLAT (pusCodePage);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetCp)));
+}
Index: trunk/src/emx/src/libos2/vio42.c
===================================================================
--- trunk/src/emx/src/libos2/vio42.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio42.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio42.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetCp) ();
+
+USHORT VioSetCp (USHORT usReserved, USHORT usCodePage, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (usReserved);
+           _THUNK_SHORT (usCodePage);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetCp)));
+}
Index: trunk/src/emx/src/libos2/vio43.c
===================================================================
--- trunk/src/emx/src/libos2/vio43.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio43.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio43.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ShowBuf) ();
+
+USHORT VioShowBuf (USHORT offLVB, USHORT cb, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (offLVB);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ShowBuf)));
+}
Index: trunk/src/emx/src/libos2/vio44.c
===================================================================
--- trunk/src/emx/src/libos2/vio44.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio44.c	(revision 18)
@@ -0,0 +1,21 @@
+/* vio44.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrollLf) ();
+
+USHORT VioScrollLf (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbCol, PBYTE pCell, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2+2+4+2);
+           _THUNK_SHORT (usTopRow);
+           _THUNK_SHORT (usLeftCol);
+           _THUNK_SHORT (usBotRow);
+           _THUNK_SHORT (usRightCol);
+           _THUNK_SHORT (cbCol);
+           _THUNK_FLAT (pCell);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrollLf)));
+}
Index: trunk/src/emx/src/libos2/vio45.c
===================================================================
--- trunk/src/emx/src/libos2/vio45.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio45.c	(revision 18)
@@ -0,0 +1,18 @@
+/* vio45.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16Register) ();
+
+USHORT VioRegister (PCSZ pszModName, PCSZ pszEntryName,
+                    ULONG ulFunMask1, ULONG ulFunMask2)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+4);
+           _THUNK_FLAT ((PSZ)pszModName);
+           _THUNK_FLAT ((PSZ)pszEntryName);
+           _THUNK_LONG (ulFunMask1);
+           _THUNK_LONG (ulFunMask2);
+           _THUNK_CALL (Vio16Register)));
+}
Index: trunk/src/emx/src/libos2/vio46.c
===================================================================
--- trunk/src/emx/src/libos2/vio46.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio46.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio46.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetConfig) ();
+
+USHORT VioGetConfig (USHORT usConfigId, PVIOCONFIGINFO pvioin, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+4+2);
+           _THUNK_SHORT (usConfigId);
+           _THUNK_FLAT (pvioin);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetConfig)));
+}
Index: trunk/src/emx/src/libos2/vio47.c
===================================================================
--- trunk/src/emx/src/libos2/vio47.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio47.c	(revision 18)
@@ -0,0 +1,21 @@
+/* vio47.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrollDn) ();
+
+USHORT VioScrollDn (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+                    USHORT usRightCol, USHORT cbLines, PBYTE pCell, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2+2+4+2);
+           _THUNK_SHORT (usTopRow);
+           _THUNK_SHORT (usLeftCol);
+           _THUNK_SHORT (usBotRow);
+           _THUNK_SHORT (usRightCol);
+           _THUNK_SHORT (cbLines);
+           _THUNK_FLAT (pCell);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrollDn)));
+}
Index: trunk/src/emx/src/libos2/vio48.c
===================================================================
--- trunk/src/emx/src/libos2/vio48.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio48.c	(revision 18)
@@ -0,0 +1,20 @@
+/* vio48.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtCharStrAtt) ();
+
+USHORT VioWrtCharStrAtt (PCCH pch, USHORT cb, USHORT usRow,
+                         USHORT usColumn, PBYTE pAttr, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+4+2);
+           _THUNK_FLAT ((PCH)pch);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_FLAT (pAttr);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtCharStrAtt)));
+}
Index: trunk/src/emx/src/libos2/vio49.c
===================================================================
--- trunk/src/emx/src/libos2/vio49.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio49.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio49.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetState) ();
+
+USHORT VioGetState (PVOID pvioState, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT (pvioState);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetState)));
+}
Index: trunk/src/emx/src/libos2/vio5.c
===================================================================
--- trunk/src/emx/src/libos2/vio5.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio5.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio5.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetAnsi) ();
+
+USHORT VioSetAnsi (USHORT fAnsi, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2);
+           _THUNK_SHORT (fAnsi);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetAnsi)));
+}
Index: trunk/src/emx/src/libos2/vio50.c
===================================================================
--- trunk/src/emx/src/libos2/vio50.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio50.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio50.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16PrtScToggle) ();
+
+USHORT VioPrtScToggle (HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16PrtScToggle)));
+}
Index: trunk/src/emx/src/libos2/vio51.c
===================================================================
--- trunk/src/emx/src/libos2/vio51.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio51.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio51.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetState) ();
+
+USHORT VioSetState (CPVOID pvioState, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_FLAT ((PVOID)pvioState);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16SetState)));
+}
Index: trunk/src/emx/src/libos2/vio52.c
===================================================================
--- trunk/src/emx/src/libos2/vio52.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio52.c	(revision 18)
@@ -0,0 +1,20 @@
+/* vio52.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtNCell) ();
+
+USHORT VioWrtNCell (const BYTE *pCell, USHORT cb, USHORT usRow,
+                    USHORT usColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PBYTE)pCell);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtNCell)));
+}
+
Index: trunk/src/emx/src/libos2/vio53.c
===================================================================
--- trunk/src/emx/src/libos2/vio53.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio53.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio52.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16WrtNChar) ();
+
+USHORT VioWrtNChar (PCCH pch, USHORT cb, USHORT usRow, USHORT usColumn,
+                    HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2);
+           _THUNK_FLAT ((PCH)pch);
+           _THUNK_SHORT (cb);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16WrtNChar)));
+}
Index: trunk/src/emx/src/libos2/vio55.c
===================================================================
--- trunk/src/emx/src/libos2/vio55.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio55.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio55.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16Associate) ();
+
+USHORT VioAssociate (HDC hdc, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_LONG ((ULONG)hdc);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16Associate)));
+}
Index: trunk/src/emx/src/libos2/vio56.c
===================================================================
--- trunk/src/emx/src/libos2/vio56.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio56.c	(revision 18)
@@ -0,0 +1,20 @@
+/* vio56.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16CreatePS) ();
+
+USHORT VioCreatePS (PHVPS phvps, SHORT sDepth, SHORT sWidth, SHORT sFormat,
+                    SHORT sAttrs, HVPS hvpsReserved)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2+2+2);
+           _THUNK_FLAT (phvps);
+           _THUNK_SHORT (sDepth);
+           _THUNK_SHORT (sWidth);
+           _THUNK_SHORT (sFormat);
+           _THUNK_SHORT (sAttrs);
+           _THUNK_SHORT (hvpsReserved);
+           _THUNK_CALL (Vio16CreatePS)));
+}
Index: trunk/src/emx/src/libos2/vio57.c
===================================================================
--- trunk/src/emx/src/libos2/vio57.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio57.c	(revision 18)
@@ -0,0 +1,15 @@
+/* vio57.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16DeleteSetId) ();
+
+USHORT VioDeleteSetId (LONG llcid, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2);
+           _THUNK_LONG (llcid);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16DeleteSetId)));
+}
Index: trunk/src/emx/src/libos2/vio58.c
===================================================================
--- trunk/src/emx/src/libos2/vio58.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio58.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio58.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetDeviceCellSize) ();
+
+USHORT VioGetDeviceCellSize (PSHORT psHeight, PSHORT psWidth, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (psHeight);
+           _THUNK_FLAT (psWidth);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16GetDeviceCellSize)));
+}
Index: trunk/src/emx/src/libos2/vio59.c
===================================================================
--- trunk/src/emx/src/libos2/vio59.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio59.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio59.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetOrg) ();
+
+USHORT VioGetOrg (PSHORT psRow, PSHORT psColumn, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (psRow);
+           _THUNK_FLAT (psColumn);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16GetOrg)));
+}
Index: trunk/src/emx/src/libos2/vio6.c
===================================================================
--- trunk/src/emx/src/libos2/vio6.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio6.c	(revision 18)
@@ -0,0 +1,13 @@
+/* vio6.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16DeRegister) ();
+
+USHORT VioDeRegister (VOID)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (0);
+           _THUNK_CALL (Vio16DeRegister)));
+}
Index: trunk/src/emx/src/libos2/vio60.c
===================================================================
--- trunk/src/emx/src/libos2/vio60.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio60.c	(revision 18)
@@ -0,0 +1,18 @@
+/* vio60.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16CreateLogFont) ();
+
+USHORT VioCreateLogFont (PFATTRS pfatattrs, LONG llcid, PSTR8 pName,
+                         HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+2);
+           _THUNK_FLAT (pfatattrs);
+           _THUNK_LONG (llcid);
+           _THUNK_FLAT (pName);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16CreateLogFont)));
+}
Index: trunk/src/emx/src/libos2/vio61.c
===================================================================
--- trunk/src/emx/src/libos2/vio61.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio61.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio61.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16DestroyPS) ();
+
+USHORT VioDestroyPS (HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16DestroyPS)));
+}
Index: trunk/src/emx/src/libos2/vio62.c
===================================================================
--- trunk/src/emx/src/libos2/vio62.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio62.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio62.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16QuerySetIds) ();
+
+USHORT VioQuerySetIds (PLONG allcids, PSTR8 pNames, PLONG alTypes, LONG lcount,
+                       HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+4+2);
+           _THUNK_FLAT (allcids);
+           _THUNK_FLAT (pNames);
+           _THUNK_FLAT (alTypes);
+           _THUNK_LONG (lcount);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16QuerySetIds)));
+}
Index: trunk/src/emx/src/libos2/vio63.c
===================================================================
--- trunk/src/emx/src/libos2/vio63.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio63.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio63.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetOrg) ();
+
+USHORT VioSetOrg (SHORT sRow, SHORT sColumn, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (sRow);
+           _THUNK_SHORT (sColumn);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16SetOrg)));
+}
Index: trunk/src/emx/src/libos2/vio64.c
===================================================================
--- trunk/src/emx/src/libos2/vio64.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio64.c	(revision 18)
@@ -0,0 +1,22 @@
+/* vio64.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16QueryFonts) ();
+
+USHORT VioQueryFonts (PLONG plRemfonts, PFONTMETRICS afmMetrics,
+                      LONG lMetricsLength, PLONG plFonts, PSZ pszFacename,
+                      ULONG flOptions, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+4+4+4+2);
+           _THUNK_FLAT (plRemfonts);
+           _THUNK_FLAT (afmMetrics);
+           _THUNK_LONG (lMetricsLength);
+           _THUNK_FLAT (plFonts);
+           _THUNK_FLAT (pszFacename);
+           _THUNK_LONG (flOptions);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16QueryFonts)));
+}
Index: trunk/src/emx/src/libos2/vio65.c
===================================================================
--- trunk/src/emx/src/libos2/vio65.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio65.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio65.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16SetDeviceCellSize) ();
+
+USHORT VioSetDeviceCellSize (SHORT sHeight, SHORT sWidth, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2);
+           _THUNK_SHORT (sHeight);
+           _THUNK_SHORT (sWidth);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16SetDeviceCellSize)));
+}
Index: trunk/src/emx/src/libos2/vio66.c
===================================================================
--- trunk/src/emx/src/libos2/vio66.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio66.c	(revision 18)
@@ -0,0 +1,17 @@
+/* vio66.c */
+
+#define INCL_AVIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ShowPS) ();
+
+USHORT VioShowPS (SHORT sDepth, SHORT sWidth, SHORT soffCell, HVPS hvps)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2);
+           _THUNK_SHORT (sDepth);
+           _THUNK_SHORT (sWidth);
+           _THUNK_SHORT (soffCell);
+           _THUNK_SHORT (hvps);
+           _THUNK_CALL (Vio16ShowPS)));
+}
Index: trunk/src/emx/src/libos2/vio7.c
===================================================================
--- trunk/src/emx/src/libos2/vio7.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio7.c	(revision 18)
@@ -0,0 +1,21 @@
+/* vio7.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16ScrollUp) ();
+
+USHORT VioScrollUp (USHORT usTopRow, USHORT usLeftCol, USHORT usBotRow,
+    USHORT usRightCol, USHORT cbLines, PBYTE pCell, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2+2+4+2);
+           _THUNK_SHORT (usTopRow);
+           _THUNK_SHORT (usLeftCol);
+           _THUNK_SHORT (usBotRow);
+           _THUNK_SHORT (usRightCol);
+           _THUNK_SHORT (cbLines);
+           _THUNK_FLAT (pCell);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16ScrollUp)));
+}
Index: trunk/src/emx/src/libos2/vio70.c
===================================================================
--- trunk/src/emx/src/libos2/vio70.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio70.c	(revision 18)
@@ -0,0 +1,19 @@
+/* vio70.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GlobalReg) ();
+
+USHORT VioGlobalReg (PCSZ pszModName, PCSZ pszEntryName,
+                     ULONG ulFunMask1, ULONG ulFunMask2, USHORT usReturn)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+4+2);
+           _THUNK_FLAT ((PSZ)pszModName);
+           _THUNK_FLAT ((PSZ)pszEntryName);
+           _THUNK_LONG (ulFunMask1);
+           _THUNK_LONG (ulFunMask2);
+           _THUNK_SHORT (usReturn);
+           _THUNK_CALL (Vio16GlobalReg)));
+}
Index: trunk/src/emx/src/libos2/vio75.c
===================================================================
--- trunk/src/emx/src/libos2/vio75.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio75.c	(revision 18)
@@ -0,0 +1,18 @@
+/* vio75.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16CheckCharType) ();
+
+USHORT VioCheckCharType (PUSHORT pType, USHORT usRow, USHORT usColumn,
+                         HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+2+2+2);
+           _THUNK_FLAT (pType);
+           _THUNK_SHORT (usRow);
+           _THUNK_SHORT (usColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16CheckCharType)));
+}
Index: trunk/src/emx/src/libos2/vio8.c
===================================================================
--- trunk/src/emx/src/libos2/vio8.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio8.c	(revision 18)
@@ -0,0 +1,14 @@
+/* vio8.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16PrtSc) ();
+
+USHORT VioPrtSc (HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16PrtSc)));
+}
Index: trunk/src/emx/src/libos2/vio9.c
===================================================================
--- trunk/src/emx/src/libos2/vio9.c	(revision 18)
+++ trunk/src/emx/src/libos2/vio9.c	(revision 18)
@@ -0,0 +1,16 @@
+/* vio9.c */
+
+#define INCL_VIO
+#include <os2.h>
+
+USHORT _THUNK_FUNCTION (Vio16GetCurPos) ();
+
+USHORT VioGetCurPos (PUSHORT pusRow, PUSHORT pusColumn, HVIO hvio)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+2);
+           _THUNK_FLAT (pusRow);
+           _THUNK_FLAT (pusColumn);
+           _THUNK_SHORT (hvio);
+           _THUNK_CALL (Vio16GetCurPos)));
+}
Index: trunk/src/emx/src/libos2/win.imp
===================================================================
--- trunk/src/emx/src/libos2/win.imp	(revision 18)
+++ trunk/src/emx/src/libos2/win.imp	(revision 18)
@@ -0,0 +1,264 @@
+;
+; win.imp
+;
+WinAddAtom                      pmwin  700 2
+WinAlarm                        pmwin  701 2
+WinBeginEnumWindows             pmwin  702 1
+WinBeginPaint                   pmwin  703 3
+WinBroadcastMsg                 pmwin  901 5
+WinCalcFrameRect                pmwin  704 3
+WinCallMsgFilter                pmwin  905 3
+WinCancelShutdown               pmwin  705 2
+WinCheckInput                   pmwin  998 1
+WinCloseClipbrd                 pmwin  707 1
+WinCompareStrings               pmwin  708 6
+WinCopyAccelTable               pmwin  709 3
+WinCopyRect                     pmwin  710 3
+WinCpTranslateChar              pmwin  711 4
+WinCpTranslateString            pmwin  712 6
+WinCreateAccelTable             pmwin  713 2
+WinCreateAtomTable              pmwin  714 2
+WinCreateCursor                 pmwin  715 7
+WinCreateDlg                    pmwin  922 5
+WinCreateFrameControls          pmwin  906 3
+WinCreateMenu                   pmwin  907 2
+WinCreateMsgQueue               pmwin  716 2
+WinCreatePointer                pmwin  717 5
+WinCreatePointerIndirect        pmwin  942 2
+WinCreateStdWindow              pmwin  908 9
+WinCreateWindow                 pmwin  909 13
+WinDdeInitiate                  pmwin  718 4
+WinDdePostMsg                   pmwin  719 5
+WinDdeRespond                   pmwin  720 5
+WinDefDlgProc                   pmwin  910 4
+WinDefWindowProc                pmwin  911 4
+WinDeleteAtom                   pmwin  721 2
+WinDeleteLibrary                pmwin  722 2
+WinDeleteProcedure              pmwin  987 2
+WinDestroyAccelTable            pmwin  723 1
+WinDestroyAtomTable             pmwin  724 1
+WinDestroyCursor                pmwin  725 1
+WinDestroyMsgQueue              pmwin  726 1
+WinDestroyPointer               pmwin  727 1
+WinDestroyWindow                pmwin  728 1
+WinDismissDlg                   pmwin  729 2
+WinDispatchMsg                  pmwin  912 2
+WinDlgBox                       pmwin  923 6
+WinDrawBitmap                   pmwin  730 7
+WinDrawBorder                   pmwin  731 7
+WinDrawPointer                  pmwin  732 5
+WinDrawText                     pmwin  913 7
+WinEmptyClipbrd                 pmwin  733 1
+WinEnablePhysInput              pmwin  734 2
+WinEnableWindow                 pmwin  735 2
+WinEnableWindowUpdate           pmwin  736 2
+WinEndEnumWindows               pmwin  737 1
+WinEndPaint                     pmwin  738 1
+WinEnumClipbrdFmts              pmwin  739 2
+WinEnumDlgItem                  pmwin  740 3
+WinEqualRect                    pmwin  741 3
+WinExcludeUpdateRegion          pmwin  742 2
+WinFillRect                     pmwin  743 3
+WinFindAtom                     pmwin  744 2
+WinFlashWindow                  pmwin  745 2
+WinFocusChange                  pmwin  746 3
+WinFreeErrorInfo                pmwin  748 1
+WinGetClipPS                    pmwin  749 3
+WinGetCurrentTime               pmwin  750 1
+WinGetDlgMsg                    pmwin  914 2
+WinGetErasePS                   pmwin  952 ?
+WinGetErrorInfo                 pmwin  751 1
+WinGetKeyState                  pmwin  752 2
+WinGetLastError                 pmwin  753 1
+WinGetMaxPosition               pmwin  754 2
+WinGetMinPosition               pmwin  755 3
+WinGetMsg                       pmwin  915 5
+WinGetNextWindow                pmwin  756 1
+WinGetPS                        pmwin  757 1
+WinGetPhysKeyState              pmwin  758 2
+WinGetScreenPS                  pmwin  759 1
+WinGetSysBitmap                 pmwin  760 2
+WinInSendMsg                    pmwin  761 1
+WinInflateRect                  pmwin  762 4
+WinInitialize                   pmwin  763 1
+WinIntersectRect                pmwin  764 4
+WinInvalidateRect               pmwin  765 3
+WinInvalidateRegion             pmwin  766 3
+WinInvertRect                   pmwin  767 2
+WinIsChild                      pmwin  768 2
+WinIsPhysInputEnabled           pmwin  769 1
+WinIsRectEmpty                  pmwin  770 2
+WinIsThreadActive               pmwin  771 1
+WinIsWindow                     pmwin  772 2
+WinIsWindowEnabled              pmwin  773 1
+WinIsWindowShowing              pmwin  774 1
+WinIsWindowVisible              pmwin  775 1
+WinLoadAccelTable               pmwin  776 3
+WinLoadDlg                      pmwin  924 6
+WinLoadLibrary                  pmwin  777 2
+WinLoadMenu                     pmwin  778 3
+WinLoadMessage                  pmwin  779 5
+WinLoadPointer                  pmwin  780 3
+WinLoadProcedure                pmwin  986 3
+WinLoadString                   pmwin  781 5
+WinLockPointerUpdate            pmwin  997 3
+WinLockInput                    pmwin  995 2
+WinLockVisRegions               pmwin  782 2
+WinLockWindowUpdate             pmwin  784 2
+WinMakePoints                   pmwin  785 3
+WinMakeRect                     pmwin  786 2
+WinMapDlgPoints                 pmwin  787 4
+WinMapWindowPoints              pmwin  788 4
+WinMessageBox                   pmwin  789 6
+WinMessageBox2                  pmwin 1015 6
+WinMsgMuxSemWait                pmwin  916 3
+WinMsgSemWait                   pmwin  790 2
+WinMultWindowFromIDs            pmwin  917 4
+WinNextChar                     pmwin  791 4
+WinOffsetRect                   pmwin  792 4
+WinOpenClipbrd                  pmwin  793 1
+WinOpenWindowDC                 pmwin  794 1
+WinPeekMsg                      pmwin  918 6
+WinPopupMenu                    pmwin  937 7
+WinPostMsg                      pmwin  919 4
+WinPostQueueMsg                 pmwin  902 4
+WinPrevChar                     pmwin  795 5
+WinProcessDlg                   pmwin  796 1
+WinPtInRect                     pmwin  797 3
+WinQueueFromID                  pmwin  993 3
+WinQueryAccelTable              pmwin  798 2
+WinQueryActiveWindow            pmwin  799 1
+WinQueryAnchorBlock             pmwin  800 1
+WinQueryAtomLength              pmwin  801 2
+WinQueryAtomName                pmwin  802 4
+WinQueryAtomUsage               pmwin  803 2
+WinQueryCapture                 pmwin  804 1
+WinQueryClassInfo               pmwin  925 3
+WinQueryClassName               pmwin  805 3
+WinQueryClassThunkProc          pmwin  931 1
+WinQueryClipbrdData             pmwin  806 2
+WinQueryClipbrdFmtInfo          pmwin  807 3
+WinQueryClipbrdOwner            pmwin  808 1
+WinQueryClipbrdViewer           pmwin  809 1
+WinQueryCp                      pmwin  810 1
+WinQueryCpList                  pmwin  811 3
+WinQueryCursorInfo              pmwin  812 2
+WinQueryDesktopBkgnd            pmwin  936 2
+WinQueryDesktopWindow           pmwin  813 2
+WinQueryDlgItemShort            pmwin  814 4
+WinQueryDlgItemText             pmwin  815 4
+WinQueryDlgItemTextLength       pmwin  816 2
+WinQueryFocus                   pmwin  817 1
+WinQueryMsgPos                  pmwin  818 2
+WinQueryMsgTime                 pmwin  819 1
+WinQueryObjectWindow            pmwin  820 1
+WinQueryPointer                 pmwin  821 1
+WinQueryPointerInfo             pmwin  822 2
+WinQueryPointerPos              pmwin  823 2
+WinQueryPresParam               pmwin  939 7
+WinQueryQueueInfo               pmwin  824 3
+WinQueryQueueStatus             pmwin  825 1
+WinQuerySendMsg                 pmwin  990 4
+WinQuerySysColor                pmwin  826 3
+WinQuerySysModalWindow          pmwin  827 1
+WinQuerySysPointer              pmwin  828 3
+WinQuerySysPointerData          pmwin 1003 3
+WinQuerySysValue                pmwin  829 2
+WinQuerySystemAtomTable         pmwin  830 0
+WinQueryUpdateRect              pmwin  831 2
+WinQueryUpdateRegion            pmwin  832 2
+WinQueryVersion                 pmwin  833 1
+WinQueryVisibleRegion           pmwin 1000 2
+WinQueryWindow                  pmwin  834 2
+WinQueryWindowDC                pmwin  835 1
+WinQueryWindowModel             pmwin  934 1
+WinQueryWindowPos               pmwin  837 2
+WinQueryWindowProcess           pmwin  838 3
+WinQueryWindowPtr               pmwin  839 2
+WinQueryWindowRect              pmwin  840 2
+WinQueryWindowText              pmwin  841 3
+WinQueryWindowTextLength        pmwin  842 1
+WinQueryWindowThunkProc         pmwin  933 1
+WinQueryWindowULong             pmwin  843 2
+WinQueryWindowUShort            pmwin  844 2
+WinRealizePalette               pmwin  941 3
+WinRegisterClass                pmwin  926 5
+WinRegisterUserDatatype         pmwin  845 4
+WinRegisterUserMsg              pmwin  846 7
+WinReleaseErasePS               pmwin  953 ?
+WinReleaseHook                  pmwin  927 5
+WinReleasePS                    pmwin  848 1
+WinRemovePresParam              pmwin  940 2
+WinReplyMsg                     pmwin  991 4
+WinRequestMutexSem              pmwin  979 2
+WinSaveWindowPos                pmwin  943 3
+WinScrollWindow                 pmwin  849 8
+WinSendDlgItemMsg               pmwin  903 5
+WinSendMsg                      pmwin  920 4
+WinSetAccelTable                pmwin  850 3
+WinSetActiveWindow              pmwin  851 2
+WinSetCapture                   pmwin  852 2
+WinSetClassMsgInterest          pmwin  853 4
+WinSetClassThunkProc            pmwin  930 2
+WinSetClipbrdData               pmwin  854 4
+WinSetClipbrdOwner              pmwin  855 2
+WinSetClipbrdViewer             pmwin  856 2
+WinSetCp                        pmwin  857 2
+WinSetDesktopBkgnd              pmwin  935 2
+WinSetDlgItemShort              pmwin  858 4
+WinSetDlgItemText               pmwin  859 3
+WinSetErrorInfo                 pmwin  977 ?
+WinSetFocus                     pmwin  860 2
+WinSetHook                      pmwin  928 5
+WinSetKeyboardStateTable        pmwin  921 3
+WinSetMsgInterest               pmwin  861 3
+WinSetMsgMode                   pmwin  862 3
+WinSetMultWindowPos             pmwin  863 3
+WinSetOwner                     pmwin  864 2
+WinSetParent                    pmwin  865 3
+WinSetPointer                   pmwin  866 2
+WinSetPointerOwner              pmwin  971 3
+WinSetPointerPos                pmwin  867 3
+WinSetPresParam                 pmwin  938 4
+WinSetRect                      pmwin  868 6
+WinSetRectEmpty                 pmwin  869 2
+WinSetSynchroMode               pmwin  870 2
+WinSetSysColors                 pmwin  871 6
+WinSetSysModalWindow            pmwin  872 2
+WinSetSysPointerData            pmwin 1002 3
+WinSetSysValue                  pmwin  873 3
+WinSetVisibleRegionNotify       pmwin 1001 2
+WinSetWindowBits                pmwin  874 4
+WinSetWindowPos                 pmwin  875 7
+WinSetWindowPtr                 pmwin  876 3
+WinSetWindowText                pmwin  877 2
+WinSetWindowThunkProc           pmwin  932 2
+WinSetWindowULong               pmwin  878 3
+WinSetWindowUShort              pmwin  879 3
+WinShowCursor                   pmwin  880 2
+WinShowPointer                  pmwin  881 2
+WinShowTrackRect                pmwin  882 2
+WinShowWindow                   pmwin  883 2
+WinStartTimer                   pmwin  884 4
+WinStopTimer                    pmwin  885 3
+WinStretchPointer               pmwin  968 ?
+WinSubclassWindow               pmwin  929 2
+WinSubstituteStrings            pmwin  886 4
+WinSubtractRect                 pmwin  887 4
+WinTerminate                    pmwin  888 1
+WinThreadAssocQueue             pmwin  304 2
+WinTrackRect                    pmwin  890 3
+WinTranslateAccel               pmwin  904 4
+WinUnionRect                    pmwin  891 4
+WinUpdateWindow                 pmwin  892 1
+WinUpper                        pmwin  893 4
+WinUpperChar                    pmwin  894 4
+WinValidateRect                 pmwin  895 3
+WinValidateRegion               pmwin  896 3
+WinWaitEventSem                 pmwin  978 2
+WinWaitMsg                      pmwin  897 3
+WinWaitMuxWaitSem               pmwin  980 3
+WinWakeThread                   pmwin  992 1
+WinWindowFromDC                 pmwin  898 1
+WinWindowFromID                 pmwin  899 2
+WinWindowFromPoint              pmwin  900 3
Index: trunk/src/emx/src/libos2/wp.imp
===================================================================
--- trunk/src/emx/src/libos2/wp.imp	(revision 18)
+++ trunk/src/emx/src/libos2/wp.imp	(revision 18)
@@ -0,0 +1,209 @@
+;
+; wp.imp
+;
+
+M_WPAbstractCClassData          pmwp     325 ?
+M_WPAbstractClassData           pmwp     326 ?
+M_WPAbstractNewClass            pmwp     327 ?
+M_WPBitmapCClassData            pmwp     367 ?
+M_WPBitmapClassData             pmwp     368 ?
+M_WPBitmapNewClass              pmwp     369 ?
+M_WPCommandFileCClassData       pmwp     385 ?
+M_WPCommandFileClassData        pmwp     386 ?
+M_WPCommandFileNewClass         pmwp     387 ?
+M_WPDataFileCClassData          pmwp     316 ?
+M_WPDataFileClassData           pmwp     317 ?
+M_WPDataFileNewClass            pmwp     318 ?
+M_WPDesktopCClassData           pmwp     355 ?
+M_WPDesktopClassData            pmwp     356 ?
+M_WPDesktopNewClass             pmwp     357 ?
+M_WPDiskCClassData              pmwp     331 ?
+M_WPDiskClassData               pmwp     332 ?
+M_WPDiskNewClass                pmwp     333 ?
+M_WPDrivesCClassData            pmwp     340 ?
+M_WPDrivesClassData             pmwp     341 ?
+M_WPDrivesNewClass              pmwp     342 ?
+M_WPFileSystemCClassData        pmwp     310 ?
+M_WPFileSystemClassData         pmwp     311 ?
+M_WPFileSystemNewClass          pmwp     312 ?
+M_WPFolderCClassData            pmwp     313 ?
+M_WPFolderClassData             pmwp     314 ?
+M_WPFolderNewClass              pmwp     315 ?
+M_WPIconCClassData              pmwp     361 ?
+M_WPIconClassData               pmwp     362 ?
+M_WPIconNewClass                pmwp     363 ?
+M_WPLaunchPadCClassData         pmwp     470 ?
+M_WPLaunchPadClassData          pmwp     471 ?
+M_WPLaunchPadNewClass           pmwp     472 ?
+M_WPMetCClassData               pmwp     406 ?
+M_WPMetClassData                pmwp     407 ?
+M_WPMetNewClass                 pmwp     408 ?
+M_WPMinWinViewerNewClass        pmwp     459 ?
+M_WPNetLinkCClassData           pmwp     400 ?
+M_WPNetLinkClassData            pmwp     401 ?
+M_WPNetLinkNewClass             pmwp     402 ?
+M_WPNetgrpCClassData            pmwp     391 ?
+M_WPNetgrpClassData             pmwp     392 ?
+M_WPNetgrpNewClass              pmwp     393 ?
+M_WPNetworkCClassData           pmwp     388 ?
+M_WPNetworkClassData            pmwp     389 ?
+M_WPNetworkNewClass             pmwp     390 ?
+M_WPObjectCClassData            pmwp     322 ?
+M_WPObjectClassData             pmwp     323 ?
+M_WPObjectNewClass              pmwp     324 ?
+M_WPPifCClassData               pmwp     403 ?
+M_WPPifClassData                pmwp     404 ?
+M_WPPifNewClass                 pmwp     405 ?
+M_WPPointerCClassData           pmwp     364 ?
+M_WPPointerClassData            pmwp     365 ?
+M_WPPointerNewClass             pmwp     366 ?
+M_WPProgramCClassData           pmwp     343 ?
+M_WPProgramClassData            pmwp     344 ?
+M_WPProgramFileCClassData       pmwp     346 ?
+M_WPProgramFileClassData        pmwp     347 ?
+M_WPProgramFileNewClass         pmwp     348 ?
+M_WPProgramNewClass             pmwp     345 ?
+M_WPRootFolderCClassData        pmwp     358 ?
+M_WPRootFolderClassData         pmwp     359 ?
+M_WPRootFolderNewClass          pmwp     360 ?
+M_WPServerCClassData            pmwp     394 ?
+M_WPServerClassData             pmwp     395 ?
+M_WPServerNewClass              pmwp     396 ?
+M_WPShadowCClassData            pmwp     328 ?
+M_WPShadowClassData             pmwp     329 ?
+M_WPShadowNewClass              pmwp     330 ?
+M_WPSharedDirCClassData         pmwp     397 ?
+M_WPSharedDirClassData          pmwp     398 ?
+M_WPSharedDirNewClass           pmwp     399 ?
+M_WPShredderCClassData          pmwp     349 ?
+M_WPShredderClassData           pmwp     350 ?
+M_WPShredderNewClass            pmwp     351 ?
+M_WPStartupCClassData           pmwp     334 ?
+M_WPStartupClassData            pmwp     335 ?
+M_WPStartupNewClass             pmwp     336 ?
+M_WPTemplatesCClassData         pmwp     319 ?
+M_WPTemplatesClassData          pmwp     320 ?
+M_WPTemplatesNewClass           pmwp     321 ?
+M_WPTransientCClassData         pmwp     337 ?
+M_WPTransientClassData          pmwp     338 ?
+M_WPTransientNewClass           pmwp     339 ?
+OldWinCreateObject              pmwp     202 ?
+ShlGetUserWordPtr               pmwp     224 2
+WPAbstractCClassData            pmwp      25 ?
+WPAbstractClassData             pmwp      26 ?
+WPAbstractNewClass              pmwp      27 ?
+WPBitmapCClassData              pmwp      67 ?
+WPBitmapClassData               pmwp      68 ?
+WPBitmapNewClass                pmwp      69 ?
+WPClassManagerCClassData        pmwp      88 ?
+WPClassManagerClassData         pmwp      89 ?
+WPClassManagerNewClass          pmwp      90 ?
+WPCommandFileCClassData         pmwp      85 ?
+WPCommandFileClassData          pmwp      86 ?
+WPCommandFileNewClass           pmwp      87 ?
+WPDataFileCClassData            pmwp      16 ?
+WPDataFileClassData             pmwp      17 ?
+WPDataFileNewClass              pmwp      18 ?
+WPDesktopCClassData             pmwp      55 ?
+WPDesktopClassData              pmwp      56 ?
+WPDesktopNewClass               pmwp      57 ?
+WPDiskCClassData                pmwp      34 ?
+WPDiskClassData                 pmwp      35 ?
+WPDiskNewClass                  pmwp      36 ?
+WPDrivesCClassData              pmwp      43 ?
+WPDrivesClassData               pmwp      44 ?
+WPDrivesNewClass                pmwp      45 ?
+WPFileSystemCClassData          pmwp      10 ?
+WPFileSystemClassData           pmwp      11 ?
+WPFileSystemNewClass            pmwp      12 ?
+WPFolderCClassData              pmwp      13 ?
+WPFolderClassData               pmwp      14 ?
+WPFolderNewClass                pmwp      15 ?
+WPIconCClassData                pmwp      61 ?
+WPIconClassData                 pmwp      62 ?
+WPIconNewClass                  pmwp      63 ?
+WPLaunchPadCClassData           pmwp     467 ?
+WPLaunchPadClassData            pmwp     468 ?
+WPLaunchPadNewClass             pmwp     469 ?
+WPMetCClassData                 pmwp      94 ?
+WPMetClassData                  pmwp      95 ?
+WPMetNewClass                   pmwp      96 ?
+WPMinWinViewerCClassData        pmwp     456 ?
+WPMinWinViewerClassData         pmwp     457 ?
+WPMinWinViewerNewClass          pmwp     458 ?
+WPNetLinkCClassData             pmwp     418 ?
+WPNetLinkClassData              pmwp     419 ?
+WPNetLinkNewClass               pmwp     420 ?
+WPNetgrpCClassData              pmwp     421 ?
+WPNetgrpClassData               pmwp     422 ?
+WPNetgrpNewClass                pmwp     423 ?
+WPNetworkCClassData             pmwp     409 ?
+WPNetworkClassData              pmwp     410 ?
+WPNetworkNewClass               pmwp     411 ?
+WPObjectCClassData              pmwp      22 ?
+WPObjectClassData               pmwp      23 ?
+WPObjectNewClass                pmwp      24 ?
+WPPifCClassData                 pmwp      91 ?
+WPPifClassData                  pmwp      92 ?
+WPPifNewClass                   pmwp      93 ?
+WPPointerCClassData             pmwp      64 ?
+WPPointerClassData              pmwp      65 ?
+WPPointerNewClass               pmwp      66 ?
+WPProgramCClassData             pmwp      46 ?
+WPProgramClassData              pmwp      47 ?
+WPProgramFileCClassData         pmwp      49 ?
+WPProgramFileClassData          pmwp      50 ?
+WPProgramFileNewClass           pmwp      51 ?
+WPProgramNewClass               pmwp      48 ?
+WPRootFolderCClassData          pmwp      58 ?
+WPRootFolderClassData           pmwp      59 ?
+WPRootFolderNewClass            pmwp      60 ?
+WPServerCClassData              pmwp     415 ?
+WPServerClassData               pmwp     416 ?
+WPServerNewClass                pmwp     417 ?
+WPShadowCClassData              pmwp      31 ?
+WPShadowClassData               pmwp      32 ?
+WPShadowNewClass                pmwp      33 ?
+WPSharedDirCClassData           pmwp     412 ?
+WPSharedDirClassData            pmwp     413 ?
+WPSharedDirNewClass             pmwp     414 ?
+WPShredderCClassData            pmwp      52 ?
+WPShredderClassData             pmwp      53 ?
+WPShredderNewClass              pmwp      54 ?
+WPStartupCClassData             pmwp      37 ?
+WPStartupClassData              pmwp      38 ?
+WPStartupNewClass               pmwp      39 ?
+WPTemplatesCClassData           pmwp      28 ?
+WPTemplatesClassData            pmwp      29 ?
+WPTemplatesNewClass             pmwp      30 ?
+WPTransientCClassData           pmwp      40 ?
+WPTransientClassData            pmwp      41 ?
+WPTransientNewClass             pmwp      42 ?
+WinCopyObject                   pmwp     288 3
+WinCreateObject                 pmwp     281 5
+WinCreateShadow                 pmwp     289 3
+WinDeregisterObjectClass        pmwp     201 1
+WinDestroyObject                pmwp     251 1
+WinEnumObjectClasses            pmwp     205 2
+WinFreeFileIcon                 pmwp     216 1
+WinIsSOMDDReady                 pmwp     480 0
+WinIsWPDServerReady             pmwp     465 0
+WinLoadFileIcon                 pmwp     209 2
+WinLockupSystem                 pmwp     283 1
+WinMoveObject                   pmwp     287 3
+WinOpenObject                   pmwp     286 3
+WinQueryActiveDesktopPathname   pmwp     262 2
+WinQueryObject                  pmwp     252 1
+WinQueryObjectPath              pmwp     263 3
+WinRegisterObjectClass          pmwp     200 2
+WinReplaceObjectClass           pmwp     219 3
+WinRestartSOMDD                 pmwp     464 1
+WinRestartWPDServer             pmwp     463 1
+WinRestartWorkplace             pmwp     221 ?
+WinRestoreWindowPos             pmwp     208 3
+WinSaveObject                   pmwp     285 2
+WinSetFileIcon                  pmwp     210 2
+WinSetObjectData                pmwp     250 2
+WinShutdownSystem               pmwp     149 2
+WinStoreWindowPos               pmwp     207 3
+WinUnlockSystem                 pmwp     282 2
Index: trunk/src/emx/src/libsocket/386/swapl.s
===================================================================
--- trunk/src/emx/src/libsocket/386/swapl.s	(revision 18)
+++ trunk/src/emx/src/libsocket/386/swapl.s	(revision 18)
@@ -0,0 +1,14 @@
+/ swapl.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+        .globl  __swapl
+
+        .text
+
+        .align  2, 0x90
+
+__swapl:
+        movl    1*4(%esp), %eax         /* x */
+        xchgb   %al, %ah
+        roll    $16, %eax
+        xchgb   %al, %ah
+        ret
Index: trunk/src/emx/src/libsocket/386/swaps.s
===================================================================
--- trunk/src/emx/src/libsocket/386/swaps.s	(revision 18)
+++ trunk/src/emx/src/libsocket/386/swaps.s	(revision 18)
@@ -0,0 +1,12 @@
+/ swaps.s (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes
+
+        .globl  __swaps
+
+        .text
+
+        .align  2, 0x90
+
+__swaps:
+        movl    1*4(%esp), %eax         /* x */
+        xchgb   %al, %ah
+        ret
Index: trunk/src/emx/src/libsocket/accept.c
===================================================================
--- trunk/src/emx/src/libsocket/accept.c	(revision 18)
+++ trunk/src/emx/src/libsocket/accept.c	(revision 18)
@@ -0,0 +1,23 @@
+/* accept.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int accept (int handle, struct sockaddr *addr, int *paddrlen)
+{
+  int s, *pflags;
+
+  s = __accept (handle, addr, paddrlen);
+  if (s < 0)
+    return -1;
+  if ((pflags = _fd_init (s)) == NULL)
+    {
+      __close (s);
+      errno = EMFILE;
+      return -1;
+    }
+  *pflags = O_RDWR | F_SOCKET;
+  return s;
+}
Index: trunk/src/emx/src/libsocket/bind.c
===================================================================
--- trunk/src/emx/src/libsocket/bind.c	(revision 18)
+++ trunk/src/emx/src/libsocket/bind.c	(revision 18)
@@ -0,0 +1,8 @@
+/* bind.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int bind (int handle, struct sockaddr *addr, int addrlen)
+{
+  return __bind (handle, addr, addrlen);
+}
Index: trunk/src/emx/src/libsocket/connect.c
===================================================================
--- trunk/src/emx/src/libsocket/connect.c	(revision 18)
+++ trunk/src/emx/src/libsocket/connect.c	(revision 18)
@@ -0,0 +1,8 @@
+/* connect.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int connect (int handle, struct sockaddr *addr, int addrlen)
+{
+  return __connect (handle, addr, addrlen);
+}
Index: trunk/src/emx/src/libsocket/herror.c
===================================================================
--- trunk/src/emx/src/libsocket/herror.c	(revision 18)
+++ trunk/src/emx/src/libsocket/herror.c	(revision 18)
@@ -0,0 +1,42 @@
+/* herror.c (emx+gcc) -- Copyright (c) 1994 by Eberhard Mattes */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+extern int h_errno;
+
+void herror (const char *string)
+{
+  int e = h_errno;
+  const char *msg;
+
+  if (string != NULL && *string != 0)
+    {
+      fputs (string, stderr);
+      fputs (": ", stderr);
+    }
+  switch (e)
+    {
+    case 0:
+      msg = "Error 0";
+      break;
+    case HOST_NOT_FOUND:
+      msg = "Host not found";
+      break;
+    case TRY_AGAIN:
+      msg = "Host name lookup failure";
+      break;
+    case NO_RECOVERY:
+      msg = "Unknown server error";
+      break;
+    case NO_DATA:
+      msg = "No address associated with name";
+      break;
+    default:
+      fprintf (stderr, "Unknown error %d\n", e);
+      return;
+    }
+  fputs (msg, stderr);
+  fputc ('\n', stderr);
+}
Index: trunk/src/emx/src/libsocket/listen.c
===================================================================
--- trunk/src/emx/src/libsocket/listen.c	(revision 18)
+++ trunk/src/emx/src/libsocket/listen.c	(revision 18)
@@ -0,0 +1,8 @@
+/* listen.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int listen (int handle, int backlog)
+{
+  return __listen (handle, backlog);
+}
Index: trunk/src/emx/src/libsocket/recv.c
===================================================================
--- trunk/src/emx/src/libsocket/recv.c	(revision 18)
+++ trunk/src/emx/src/libsocket/recv.c	(revision 18)
@@ -0,0 +1,8 @@
+/* recv.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int recv (int handle, void *buf, int len, unsigned flags)
+{
+  return __recv (handle, buf, len, flags);
+}
Index: trunk/src/emx/src/libsocket/recvfrom.c
===================================================================
--- trunk/src/emx/src/libsocket/recvfrom.c	(revision 18)
+++ trunk/src/emx/src/libsocket/recvfrom.c	(revision 18)
@@ -0,0 +1,17 @@
+/* recvfrom.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int recvfrom (int handle, void *buf, int len, unsigned flags,
+              struct sockaddr *from, int *pfromlen)
+{
+  struct _recvfrom args;
+
+  args.handle   = handle;
+  args.buf      = buf;
+  args.len      = len;
+  args.flags    = flags;
+  args.from     = from;
+  args.pfromlen = pfromlen;
+  return __recvfrom (&args);
+}
Index: trunk/src/emx/src/libsocket/send.c
===================================================================
--- trunk/src/emx/src/libsocket/send.c	(revision 18)
+++ trunk/src/emx/src/libsocket/send.c	(revision 18)
@@ -0,0 +1,8 @@
+/* send.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int send (int handle, const void *buf, int len, unsigned flags)
+{
+  return __send (handle, buf, len, flags);
+}
Index: trunk/src/emx/src/libsocket/sendto.c
===================================================================
--- trunk/src/emx/src/libsocket/sendto.c	(revision 18)
+++ trunk/src/emx/src/libsocket/sendto.c	(revision 18)
@@ -0,0 +1,17 @@
+/* sendto.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int sendto (int handle, const void *buf, int len, unsigned flags,
+            const struct sockaddr *to, int tolen)
+{
+  struct _sendto args;
+
+  args.handle = handle;
+  args.buf    = buf;
+  args.len    = len;
+  args.flags  = flags;
+  args.to     = to;
+  args.tolen  = tolen;
+  return __sendto (&args);
+}
Index: trunk/src/emx/src/libsocket/shutdown.c
===================================================================
--- trunk/src/emx/src/libsocket/shutdown.c	(revision 18)
+++ trunk/src/emx/src/libsocket/shutdown.c	(revision 18)
@@ -0,0 +1,8 @@
+/* shutdown.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <emx/syscalls.h>
+
+int shutdown (int handle, int how)
+{
+  return __shutdown (handle, how);
+}
Index: trunk/src/emx/src/libsocket/socket.c
===================================================================
--- trunk/src/emx/src/libsocket/socket.c	(revision 18)
+++ trunk/src/emx/src/libsocket/socket.c	(revision 18)
@@ -0,0 +1,23 @@
+/* socket.c (emx+gcc) -- Copyright (c) 1994-1996 by Eberhard Mattes */
+
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <emx/io.h>
+#include <emx/syscalls.h>
+
+int socket (int domain, int type, int protocol)
+{
+  int s, *pflags;
+
+  s = __socket (domain, type, protocol);
+  if (s < 0)
+    return -1;
+  if ((pflags = _fd_init (s)) == NULL)
+    {
+      __close (s);
+      errno = EMFILE;
+      return -1;
+    }
+  *pflags = O_RDWR | F_SOCKET;
+  return s;
+}
Index: trunk/src/emx/src/libsocket/tcp32dll.imp
===================================================================
--- trunk/src/emx/src/libsocket/tcp32dll.imp	(revision 18)
+++ trunk/src/emx/src/libsocket/tcp32dll.imp	(revision 18)
@@ -0,0 +1,23 @@
+;
+; tcp32dll.imp
+;
+dn_comp                 tcp32dll  32 5
+dn_expand               tcp32dll  31 5
+dn_skipname             tcp32dll  33 2
+endhostent              tcp32dll  29 0
+endnetent               tcp32dll  16 0
+endprotoent             tcp32dll  19 0
+endservent              tcp32dll  26 0
+gethostent              tcp32dll  30 0
+getnetent               tcp32dll  17 0
+getprotoent             tcp32dll  20 0
+getservent              tcp32dll  27 0
+putlong                 tcp32dll  38 2
+putshort                tcp32dll  37 2
+res_init                tcp32dll  39 0
+res_mkquery             tcp32dll  40 9
+res_send                tcp32dll  41 4
+sethostent              tcp32dll  28 1
+setnetent               tcp32dll  15 1
+setprotoent             tcp32dll  18 1
+setservent              tcp32dll  25 1
Index: trunk/src/emx/src/os2/COPYING
===================================================================
--- trunk/src/emx/src/os2/COPYING	(revision 18)
+++ trunk/src/emx/src/os2/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/os2/clib.h
===================================================================
--- trunk/src/emx/src/os2/clib.h	(revision 18)
+++ trunk/src/emx/src/os2/clib.h	(revision 18)
@@ -0,0 +1,47 @@
+/* clib.h -- Header file for emx.dll's minimal C run-time library
+   Copyright (c) 1992-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#if !defined (_SIZE_T)
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif
+
+#define	offsetof(type, member)  ((size_t)&((type *)0)->member)
+
+void _defext (char *dst, const char *ext);
+char *_getname (const char *path);
+void *memcpy (void *dst, const void *src, size_t count);
+size_t strlen (const char *s);
+int strcmp (const char *string1, const char *string2);
+char *strcpy (char *dst, const char *src);
+int stricmp (const char *string1, const char *string2);
+void *memset (void *dst, int c, size_t n);
+int strncmp (const char *string1, const char *string2, size_t n);
+
+static inline int tolower (int c)
+{
+  return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c);
+}
Index: trunk/src/emx/src/os2/core.c
===================================================================
--- trunk/src/emx/src/os2/core.c	(revision 18)
+++ trunk/src/emx/src/os2/core.c	(revision 18)
@@ -0,0 +1,488 @@
+/* core.c -- Dump core
+   Copyright (c) 1994-1996 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSMODULEMGR
+#define INCL_DOSPROCESS
+#include <os2emx.h>
+#include "emxdll.h"
+#include <sys/user.h>
+#include "reg.h"
+#include "clib.h"
+
+/* This is the header of the core dump file. */
+
+static struct user u_hdr;
+
+/* If there are two or more heap objects, this structure will describe
+   the heap objects, except for the first one. */
+
+static struct _user_heapobjs u_heap_hdr;
+
+/* Current size of the core dump file. */
+
+static ULONG core_size;
+
+
+/* Write SIZE bytes from from SRC to the core dump file HANDLE.
+   Return the errno code. */
+
+static ULONG core_write (ULONG handle, const void *src, ULONG size)
+{
+  ULONG rc, cbwritten;
+
+  core_size += size;
+  rc = DosWrite (handle, src, size, &cbwritten);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Pad the core dump file HANDLE with zeros, up to offset OFF.  Return
+   the errno code. */
+
+static ULONG core_fill (ULONG handle, ULONG off)
+{
+  ULONG rc, n;
+  char buffer[0x1000];
+
+  if (off <= core_size)
+    return 0;
+  memset (buffer, 0, sizeof (buffer));
+  while (off > core_size)
+    {
+      n = off - core_size;
+      if (n > sizeof (buffer))
+        n = sizeof (buffer);
+      rc = core_write (handle, buffer, n);
+      if (rc != 0)
+        return rc;
+    }
+  return 0;
+}
+
+
+/* Dump a region of memory to the core dump file, at offset OFF.  BASE
+   and END are the base and end addresses, respectively, of the
+   region.  Return the errno code. */
+
+static ULONG core_mem (ULONG handle, ULONG off, ULONG base, ULONG end)
+{
+  ULONG rc;
+
+  rc = core_fill (handle, off);
+  if (rc == 0 && base <= end)
+    {
+      /* The heap may be loaded from the EXE file by the guard page
+         exception handler.  As DosRead doesn't work when invoked from
+         inside DosWrite (in the exception handler), we force the
+         pages to be read into (virtual) memory before writing them to
+         the core dump file. */
+
+      if (exe_heap)
+        touch ((void *)base, end - base);
+      rc = core_write (handle, (void *)base, end - base);
+    }
+  return rc;
+}
+
+
+/* Write core dump file.  HANDLE is the file handle of the core dump
+   file.  Return an errno code.  Note that this function assumes that
+   the file has been rewound.  Call either core_regs_e() or
+   core_regs_i() before calling core_main(). */
+
+ULONG core_main (ULONG handle)
+{
+  ULONG rc;
+
+  /* Reset the size of the file, for core_fill(). */
+
+  core_size = 0;
+
+  /* Write the header. */
+
+  rc = core_write (handle, &u_hdr, sizeof (u_hdr));
+  if (rc != 0) return rc;
+
+  /* Dump the data segment. */
+
+  rc = core_mem (handle, u_hdr.u_data_off,
+                 u_hdr.u_data_base, u_hdr.u_data_end);
+  if (rc != 0) return rc;
+
+  /* Dump the heap. */
+
+  rc = core_mem (handle, u_hdr.u_heap_off,
+                 u_hdr.u_heap_base, u_hdr.u_heap_brk);
+  if (rc != 0) return rc;
+
+  /* Dump the stack. */
+
+  rc = core_mem (handle, u_hdr.u_stack_off,
+                 u_hdr.u_stack_low, u_hdr.u_stack_end);
+  if (rc != 0) return rc;
+
+  /* Dump additional heap objects. */
+
+  if (u_hdr.u_heapobjs_off != 0)
+    {
+      ULONG i;
+
+      rc = core_fill (handle, u_hdr.u_heapobjs_off);
+      if (rc != 0) return rc;
+      rc = core_write (handle, &u_heap_hdr, sizeof (u_heap_hdr));
+      if (rc != 0) return rc;
+      for (i = 0; i < u_heap_hdr.u_count; ++i)
+        {
+          rc = core_mem (handle, u_heap_hdr.u_objs[i].u_off,
+                         u_heap_hdr.u_objs[i].u_base,
+                         u_heap_hdr.u_objs[i].u_brk);
+          if (rc != 0) return rc;
+        }
+    }
+
+  /* Truncate the file to the current position. */
+
+  rc = DosSetFileSize (handle, core_size);
+  return rc;
+}
+
+
+/* Return the size of the "core" image file to be written.  The return
+   value need not be exact. */
+
+static ULONG core_file_size (void)
+{
+  if (u_hdr.u_heapobjs_off == 0)
+    return u_hdr.u_stack_off + u_hdr.u_stack_end - u_hdr.u_stack_low;
+  else
+    {
+      int i = (int)u_heap_hdr.u_count - 1;
+      return (u_heap_hdr.u_objs[i].u_off
+              + u_heap_hdr.u_objs[i].u_brk - u_heap_hdr.u_objs[i].u_base);
+    }
+}
+
+
+/* Write "core" image file and say "core dumped".  You should either
+   call core_regs_e() or core_regs_i() before calling core_dump(). */
+
+void core_dump (void)
+{
+  ULONG rc, action;
+  HFILE handle;
+
+  if (layout_flags & L_FLAG_LINK386)
+    return;
+
+  rc = DosOpen ("core", &handle, &action, core_file_size (), 0,
+                OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
+                OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE,
+                (void *)0);
+  if (rc != 0)
+    return;
+  core_main (handle);
+  DosClose (handle);
+  otext ("core dumped\r\n");
+}
+
+
+/* Set structure members for core_regs_e() and core_regs_i(). */
+
+static void core_set_header (void)
+{
+  ULONG rc, sp;
+  PTIB ptib;
+  PPIB ppib;
+  unsigned i;
+
+  u_hdr.u_magic = UMAGIC;
+  u_hdr.u_ar0 = (int *)(offsetof (struct user, u_regs) + KERNEL_U_ADDR);
+  u_hdr.u_data_base = layout->data_base;
+  u_hdr.u_data_end = layout->bss_end;
+  if (heap_obj_count == 0)
+    {
+      u_hdr.u_heap_base = 0;
+      u_hdr.u_heap_end = 0;
+      u_hdr.u_heap_brk = 0;
+    }
+  else
+    {
+      u_hdr.u_heap_base = heap_objs[0].base;
+      u_hdr.u_heap_end = heap_objs[0].end;
+      u_hdr.u_heap_brk = heap_objs[0].brk;
+    }
+
+  /* Set the stack base and end addresses. */
+
+  rc = DosGetInfoBlocks (&ptib, &ppib);
+  if (rc != 0)
+    {
+      u_hdr.u_stack_base = stack_base;
+      u_hdr.u_stack_end = stack_end;
+    }
+  else
+    {
+      u_hdr.u_stack_base = (ULONG)ptib->tib_pstack;
+      u_hdr.u_stack_end = (ULONG)ptib->tib_pstacklimit;
+    }
+
+  /* Find the low end of the stack. */
+
+  sp = (ULONG)&sp;
+  if (sp >= u_hdr.u_stack_base && sp <= u_hdr.u_stack_end)
+    u_hdr.u_stack_low = sp & ~0xfff;
+  else
+    u_hdr.u_stack_low = u_hdr.u_stack_end;
+
+  /* Set offsets. */
+
+  u_hdr.u_data_off = U_OFFSET;
+  u_hdr.u_heap_off = (u_hdr.u_data_off
+                      + ROUND_PAGE (u_hdr.u_data_end - u_hdr.u_data_base));
+  u_hdr.u_stack_off = (u_hdr.u_heap_off
+                       + ROUND_PAGE (u_hdr.u_heap_brk - u_hdr.u_heap_base));
+  if (heap_obj_count > 1)
+    {
+      memset (&u_heap_hdr, 0, sizeof (u_heap_hdr));
+      u_hdr.u_heapobjs_off
+        = u_hdr.u_stack_off + ROUND_PAGE (u_hdr.u_stack_end
+                                          - u_hdr.u_stack_low);
+      u_heap_hdr.u_objs[0].u_off
+        = u_hdr.u_heapobjs_off + ROUND_PAGE (sizeof (u_heap_hdr));
+      u_heap_hdr.u_count = heap_obj_count - 1;
+      for (i = 0; i < u_heap_hdr.u_count; ++i)
+        {
+          u_heap_hdr.u_objs[i].u_base = heap_objs[i+1].base;
+          u_heap_hdr.u_objs[i].u_end = heap_objs[i+1].end;
+          u_heap_hdr.u_objs[i].u_brk = heap_objs[i+1].brk;
+          if (i != 0)
+            u_heap_hdr.u_objs[i].u_off
+              = (u_heap_hdr.u_objs[i-1].u_off
+                 + ROUND_PAGE (u_heap_hdr.u_objs[i-1].u_brk
+                               - u_heap_hdr.u_objs[i-1].u_base));
+        }
+    }
+}
+
+
+/* Copy registers from the stack to the u_hdr structure for
+   core_main(). This is used by __raise(), __signal(), and __core().
+   F points to the emx_syscall stack frame (for retrieving the values
+   of the registers). */
+
+void core_regs_i (syscall_frame *f)
+{
+  BYTE *ip, **sp;
+  USHORT sel;
+
+  /* Zero all bytes of the header structure. */
+
+  memset (&u_hdr, 0, sizeof (u_hdr));
+
+  /* Copy registers from the stack frame to the header. */
+
+  u_hdr.u_regs[R_EFL] = f->e.eflags;
+  u_hdr.u_regs[R_EAX] = f->e.eax;
+  u_hdr.u_regs[R_EBX] = f->e.ebx;
+  u_hdr.u_regs[R_ECX] = f->e.ecx;
+  u_hdr.u_regs[R_EDX] = f->e.edx;
+  u_hdr.u_regs[R_ESI] = f->e.esi;
+  u_hdr.u_regs[R_EDI] = f->e.edi;
+  u_hdr.u_regs[R_EBP] = f->e.ebp;
+
+  /* Copy current values of the segment registers to the header. */
+
+  __asm__ ("movw %%cs, %0" : "=g"(sel) : /**/); u_hdr.u_regs[R_CS] = sel;
+  __asm__ ("movw %%ds, %0" : "=g"(sel) : /**/); u_hdr.u_regs[R_DS] = sel;
+  __asm__ ("movw %%es, %0" : "=g"(sel) : /**/); u_hdr.u_regs[R_ES] = sel;
+  __asm__ ("movw %%fs, %0" : "=g"(sel) : /**/); u_hdr.u_regs[R_FS] = sel;
+  __asm__ ("movw %%gs, %0" : "=g"(sel) : /**/); u_hdr.u_regs[R_GS] = sel;
+  __asm__ ("movw %%ss, %0" : "=g"(sel) : /**/); u_hdr.u_regs[R_SS] = sel;
+
+  /* Fetch the instruction pointer and the stack pointer.  We add 4 to
+     the stack pointer to compensate for the PUSHFD of emx_syscall. */
+
+  ip = (BYTE *)f->e.eip;
+  sp = (BYTE **)(f->e.esp + 4);
+
+  /* Check whether we have been called from __syscall().  That should
+     always be the case, but... We check only the lower 16 bits
+     because we don't know the address of __syscall() in a DLL such as
+     emxlibcs.dll. */
+
+  if ((f->e.eip & 0xffff) == 12 + 5)
+    {
+
+      /* We have been called from __syscall() (see crt0.s for
+         details).  Rewind the stack to the function which called
+         __syscall(), to get better stack backtraces from the
+         debugger. */
+
+      ++sp;                     /* Remove CALL emx_syscall */
+      ip = *sp++;               /* Get and remove EIP */
+
+      /* EIP is now in the function which called __syscall().  This is
+         one of the following functions:
+ 
+         Name          ³  AL   ³ PUSH
+         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ
+         __core        ³  11H  ³ 1 (EBX)
+         __raise       ³  0EH  ³ 0
+         __signal      ³  0CH  ³ 0
+         __sigprocmask ³  37H  ³ 1 (EBX)
+      
+         Note that this information has not changed since emx 0.8b.
+      
+         We look at the instructions to find out what to do:
+      
+         EIP-9: MOV     AL, syscall_no
+         EIP-7: MOV     AH, 7FH
+         EIP-5: CALL    __syscall
+      
+         Perhaps we should consult the layout table first to avoid
+         accessing memory outside the text segment. */
+
+      if (ip[-9] == 0xb0          /* MOV AL,          */
+          && (ip[-8] == 0x0c      /*         __signal */
+              || ip[-8] == 0x0e   /*         __raise  */
+              || ip[-8] == 0x11   /*         __core   */
+              || ip[-8] == 0x37)  /*         __sigprocmask */
+          && ip[-7] == 0xb4       /* MOV AH,          */
+          && ip[-6] == 0x7f       /*         7FH      */
+          && ip[-5] == 0xe8)      /* CALL             */
+        {
+          /* Undo the PUSH of EBX for __core() and __sigprocmask(). */
+
+          if (ip[-8] == 0x11 || ip[-8] == 0x37)
+            ++sp;
+
+          /* OK, we are in one of the syscall interface functions.
+             Rewind the stack to the function which called the
+             interface function (after that, EIP is supposed to point
+             to a C function; this will keep GDB happy). */
+
+          ip = *sp++;           /* Fetch next EIP */
+        }
+    }
+
+  /* Put the stack pointer and the instruction pointer into the
+     header. */
+
+  u_hdr.u_regs[R_ESP] = (ULONG)sp;
+  u_hdr.u_regs[R_UESP] = (ULONG)sp;
+  u_hdr.u_regs[R_EIP] = (ULONG)ip;
+
+  /* TODO: 387 state */
+
+  core_set_header ();
+}
+
+
+/* Copy registers from the exception context record to the u_hdr
+   structure for core_main().  CONTEXT points to the exception context
+   record. */
+
+void core_regs_e (CONTEXTRECORD *context)
+{
+  ULONG (*p_DosQueryModFromEIP) (HMODULE *, ULONG *, ULONG, PCHAR, ULONG *,
+                                 ULONG);
+  HMODULE hmod_doscall1, hmod_eip;
+  char obj[9];
+  ULONG obj_eip, off_eip;
+
+  /* Zero all bytes of the header structure. */
+
+  memset (&u_hdr, 0, sizeof (u_hdr));
+
+  /* If the control registers are available, copy their values to the
+     header. */
+
+  if (context->ContextFlags & CONTEXT_CONTROL)
+    {
+      u_hdr.u_regs[R_CS] = context->ctx_SegCs;
+      u_hdr.u_regs[R_SS] = context->ctx_SegSs;
+      u_hdr.u_regs[R_EIP] = context->ctx_RegEip;
+      u_hdr.u_regs[R_ESP] = context->ctx_RegEsp;
+      u_hdr.u_regs[R_EBP] = context->ctx_RegEbp;
+      u_hdr.u_regs[R_EFL] = context->ctx_EFlags;
+    }
+
+  /* If the segment registers are available, copy their values to the
+     header. */
+
+  if (context->ContextFlags & CONTEXT_SEGMENTS)
+    {
+      u_hdr.u_regs[R_DS] = context->ctx_SegDs;
+      u_hdr.u_regs[R_ES] = context->ctx_SegEs;
+      u_hdr.u_regs[R_FS] = context->ctx_SegFs;
+      u_hdr.u_regs[R_GS] = context->ctx_SegGs;
+    }
+
+  /* If the integer registers are available, copy their values to the
+     header. */
+
+  if (context->ContextFlags & CONTEXT_INTEGER)
+    {
+      u_hdr.u_regs[R_EAX] = context->ctx_RegEax;
+      u_hdr.u_regs[R_EBX] = context->ctx_RegEbx;
+      u_hdr.u_regs[R_ECX] = context->ctx_RegEcx;
+      u_hdr.u_regs[R_EDX] = context->ctx_RegEdx;
+      u_hdr.u_regs[R_ESI] = context->ctx_RegEsi;
+      u_hdr.u_regs[R_EDI] = context->ctx_RegEdi;
+    }
+
+  /* Set UESP from ESP. */
+
+  u_hdr.u_regs[R_UESP] = u_hdr.u_regs[R_ESP];
+
+  /* Store the coprocessor state. */
+
+  if (context->ContextFlags & CONTEXT_FLOATING_POINT)
+    {
+      u_hdr.u_fpvalid = 0xff;
+      memcpy (&u_hdr.u_fpstate.state, &context->ctx_env,
+              sizeof (u_hdr.u_fpstate.state));
+    }
+
+  /* Find the module name for EIP.  Note that DosQueryModFromEIP API
+     wasn't available in plain OS/2 2.0. */
+
+  if (DosLoadModule (obj, sizeof (obj), "DOSCALL1", &hmod_doscall1) == 0)
+    {
+      memset (obj, 0, sizeof (obj));
+      if (DosQueryProcAddr (hmod_doscall1, 360, NULL,
+                            (PPFN)&p_DosQueryModFromEIP) == 0
+          && p_DosQueryModFromEIP (&hmod_eip, &obj_eip, sizeof (obj),
+                                   obj, &off_eip, context->ctx_RegEip) == 0)
+        memcpy (u_hdr.u_module, obj, sizeof (u_hdr.u_module));
+      DosFreeModule (hmod_doscall1);
+    }
+
+  core_set_header ();
+}
Index: trunk/src/emx/src/os2/doscall.c
===================================================================
--- trunk/src/emx/src/os2/doscall.c	(revision 18)
+++ trunk/src/emx/src/os2/doscall.c	(revision 18)
@@ -0,0 +1,432 @@
+/* doscall.c -- DOS-compatible system calls
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSMISC
+#define INCL_KBD
+#include <os2emx.h>
+#include <sys/errno.h>
+#include "emxdll.h"
+#include "clib.h"
+
+static void bad_func (syscall_frame *f);
+static void do_get_date (syscall_frame *f);
+static void do_get_time (syscall_frame *f);
+static void do_get_version (syscall_frame *f);
+
+
+void dos_call (syscall_frame *f)
+{
+  int err_no, i;
+
+  if (debug_flags & DEBUG_SYSCALL)
+    oprintf ("%u: syscall %.2x\r\n", my_pid, (unsigned)f->b.ah);
+
+  f->e.eflags &= ~(FLAG_C | FLAG_Z);
+
+  switch (f->b.ah)
+    {
+    case 0x01:
+
+      /* Read keyboard with echo. */
+
+      kbd_input (&f->b.al, FALSE, TRUE, TRUE, FALSE);
+      break;
+
+    case 0x02:
+
+      /* Display character. */
+
+      conout (f->b.dl);
+      break;
+
+    case 0x06:
+
+      /* Direct console I/O. */
+
+      if (f->b.dl != 0xff)
+        conout (f->b.dl);
+      else
+        {
+          if (!kbd_input (&f->b.al, TRUE, FALSE, FALSE, FALSE))
+            f->e.eflags |= FLAG_Z;
+        }
+      break;
+
+    case 0x07:
+
+      /* Direct console input. */
+
+      kbd_input (&f->b.al, TRUE, FALSE, TRUE, FALSE);
+      break;
+
+    case 0x08:
+
+      /* Read keyboard. */
+
+      kbd_input (&f->b.al, FALSE, FALSE, TRUE, FALSE);
+      break;
+
+    case 0x0a:
+
+      /* Buffered keyboard input. */
+
+      conin_string ((char *)f->e.edx);
+      break;
+
+    case 0x0b:
+
+      /* Check keyboard status. */
+
+      f->b.al = kbd_input (NULL, FALSE, FALSE, FALSE, TRUE);
+      break;
+
+    case 0x0d:
+
+      /* Reset disk. */
+
+      break;
+
+    case 0x0e:
+
+      /* Select disk. */
+
+      do_selectdisk (f->b.dl);
+      f->b.al = 0;
+      break;
+
+    case 0x19:
+
+      /* Get current disk. */
+
+      f->b.al = do_getdrive ();
+      break;
+
+    case 0x2a:
+
+      /* Get date. */
+
+      do_get_date (f);
+      break;
+
+    case 0x2c:
+
+      /* Get time. */
+
+      do_get_time (f);
+      break;
+
+    case 0x30:
+
+      /* Get version number. */
+
+      do_get_version (f);
+      break;
+
+    case 0x37:
+
+      /* Get or set the switch character. */
+
+      f->b.al = 0xff;           /* No switch character defined. */
+      break;
+
+    case 0x39:
+
+      /* Create directory. */
+
+      f->e.eax = do_mkdir ((const char *)f->e.edx);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x3a:
+
+      /* Remove directory. */
+
+      f->e.eax = do_rmdir ((const char *)f->e.edx);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x3b:
+
+      /* Change current directory. */
+
+      f->e.eax = do_chdir ((const char *)f->e.edx);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x3c:
+
+      /* Create handle. */
+
+      i = old_creat ((const char *)f->e.edx, f->e.ecx, &err_no);
+      if (i != -1)
+        f->e.eax = i;
+      else
+        {
+          f->e.eax = err_no;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x3d:
+
+      /* Open handle. */
+
+      i = old_open ((const char *)f->e.edx, f->b.al, &err_no);
+      if (i != -1)
+        f->e.eax = i;
+      else
+        {
+          f->e.eax = err_no;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x3e:
+
+      /* Close handle. */
+
+      f->e.eax = do_close (f->e.ebx);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x3f:
+
+      /* Read handle. */
+
+      f->e.eax = do_read (f->e.ebx, (void *)f->e.edx, f->e.ecx, &err_no);
+      if (err_no != 0)
+        {
+          f->e.eax = err_no;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x40:
+
+      /* Write handle. */
+
+      f->e.eax = do_write (f->e.ebx, (void *)f->e.edx, f->e.ecx, &err_no);
+      if (err_no != 0)
+        {
+          f->e.eax = err_no;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x41:
+
+      /* Delete directory entry. */
+
+      f->e.eax = do_delete ((const char *)f->e.edx);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x42:
+
+      /* Move file pointer. */
+
+      f->e.eax = do_seek (f->e.ebx, f->b.al, f->e.edx, &err_no);
+      if (err_no != 0)
+        {
+          f->e.eax = err_no;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x43:
+
+      /* Get/set file attributes. */
+
+      if (f->b.al == 0)
+        {
+          f->e.ecx = get_attr ((const char *)f->e.edx, &err_no);
+          f->e.eax = err_no;
+          if (err_no != 0)
+            f->e.eflags |= FLAG_C;
+        }
+      else if (f->b.al == 1)
+        {
+          f->e.eax = set_attr ((const char *)f->e.edx, f->e.ecx);
+          if (f->e.eax != 0)
+            f->e.eflags |= FLAG_C;
+        }
+      else
+        bad_func (f);
+      break;
+
+    case 0x44:
+
+      /* IOCTL */
+
+      if (f->b.al != 0)
+        bad_func (f);
+      f->e.edx = do_ioctl1 (f->e.ebx, (int *)&f->e.eax);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x45:
+
+      /* Duplicate file handle. */
+
+      f->e.eax = do_dup (f->e.ebx, (ULONG)(-1), &err_no);
+      if (err_no != 0)
+        {
+          f->e.eax = err_no;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x46:
+
+      /* Force duplicate file handle. */
+
+      f->e.eax = do_dup (f->e.ebx, f->e.ecx, &err_no);
+      if (err_no != 0)
+        {
+          f->e.eax = err_no;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x47:
+
+      /* Get current directory. */
+
+      f->e.eax = do_getcwd ((char *)f->e.esi, f->b.dl);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x4c:
+
+      /* End process. */
+
+      quit (f->b.al);
+      break;
+
+    case 0x4e:
+
+      f->e.eax = do_find_first ((const char *)f->e.edx, f->e.ecx & 0x37,
+                                (struct _find *)f->e.esi);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x4f:
+
+      f->e.eax = do_find_next ((struct _find *)f->e.esi);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x56:
+
+      /* Change directory entry. */
+
+      f->e.eax = do_rename ((const char *)f->e.edx, (const char *)f->e.edi);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x57:
+
+      /* Get/set time/date of file. */
+
+      if (f->b.al == 0)
+        {
+          f->e.eax = do_get_timestamp (f->e.ebx, &f->e.ecx, &f->e.edx);
+          if (f->e.eax != 0)
+            f->e.eflags |= FLAG_C;
+        }
+      else if (f->b.al == 1)
+        {
+          f->e.eax = do_set_timestamp (f->e.ebx, f->e.ecx, f->e.edx);
+          if (f->e.eax != 0)
+            f->e.eflags |= FLAG_C;
+        }
+      else
+        {
+          f->e.eax = EINVAL;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    default:
+      bad_func (f);
+    }
+}
+
+
+static void bad_func (syscall_frame *f)
+{
+  oprintf ("Invalid syscall function code: %.2x\r\n", (unsigned)f->b.ah);
+  quit (255);
+}
+
+
+/* Get date. */
+
+static void do_get_date (syscall_frame *f)
+{
+  DATETIME dt;
+
+  DosGetDateTime (&dt);
+  f->x.cx = dt.year;
+  f->b.dh = dt.month;
+  f->b.dl = dt.day;
+  f->b.al = dt.weekday;
+}
+
+
+/* Get time. */
+
+static void do_get_time (syscall_frame *f)
+{
+  DATETIME dt;
+
+  DosGetDateTime (&dt);
+  f->b.ch = dt.hours;
+  f->b.cl = dt.minutes;
+  f->b.dh = dt.seconds;
+  f->b.dl = dt.hundredths;
+}
+
+
+/* Get version number. */
+
+static void do_get_version (syscall_frame *f)
+{
+  f->e.eax = ((version_major & 0xff) | ((version_minor & 0xff) << 8)
+              | 0x6d650000);
+  f->x.bx = 0;
+  f->x.cx = 0;
+}
Index: trunk/src/emx/src/os2/emxdll.asm
===================================================================
--- trunk/src/emx/src/os2/emxdll.asm	(revision 18)
+++ trunk/src/emx/src/os2/emxdll.asm	(revision 18)
@@ -0,0 +1,602 @@
+;
+; EMXDLL.ASM
+;
+; Copyright (c) 1992-1996 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; As special exception, emx.dll can be distributed without source code
+; unless it has been changed.  If you modify emx.dll, this exception
+; no longer applies and you must remove this paragraph from all source
+; files for emx.dll.
+;
+
+                .386
+
+                INCLUDE EMXDLL.INC
+
+;
+; IBM TCP/IP's socket handles are < 2048.  See also emxdll.h.
+;
+MAX_SOCKETS     =       2048
+
+; ----------------------------------------------------------------------------
+; Structures
+; ----------------------------------------------------------------------------
+
+;
+; emx_syscall puts all the registers of the client process into the stack
+; using PUSHAD.  This structure matches the layout of the registers in
+; the stack.
+;
+SYSCALL_FRAME   STRUCT
+SC_EDI          DWORD   ?
+SC_ESI          DWORD   ?
+SC_EBP          DWORD   ?
+SC_ESP          DWORD   ?
+SC_EBX          DWORD   ?
+SC_EDX          DWORD   ?
+SC_ECX          DWORD   ?
+SC_EAX          DWORD   ?
+SC_EFLAGS       DWORD   ?
+SC_EIP          DWORD   ?
+SYSCALL_FRAME   ENDS
+
+;
+; Thread data block.  Fields at the end of the structure are omitted.
+; In consequence, the size of the structure is wrong and must not be
+; used.
+;
+THREAD_DATA     STRUCT
+LAST_SYS_ERRNO  DWORD   ?                       ; Error code for last syscall
+PREV_SYS_ERRNO  DWORD   ?                       ; Previous value of the above
+; ...and other fields, which are omitted here
+THREAD_DATA     ENDS
+
+; ----------------------------------------------------------------------------
+; Data
+; ----------------------------------------------------------------------------
+
+BSS32           SEGMENT
+
+;
+; The following variables are imported from other modules
+;
+                EXTRN   stack_end:DWORD
+                EXTRN   layout:DWORD
+                EXTRN   threads:DWORD
+                EXTRN   env_count:DWORD
+                EXTRN   arg_size:DWORD
+                EXTRN   arg_count:DWORD
+                EXTRN   fork_flag:BYTE
+                EXTRN   fork_stack_page:DWORD
+                EXTRN   fork_ebp:DWORD
+                EXTRN   exc_reg_ptr:DWORD
+                EXTRN   errout_handle:DWORD
+
+;
+; Private data of this module
+;
+RET_ADDR        DWORD   ?                       ; Return address
+
+BSS32           ENDS
+
+; ----------------------------------------------------------------------------
+; Solo data
+; ----------------------------------------------------------------------------
+
+COMMON32        SEGMENT
+pipe_number     DWORD   ?
+queue_number    DWORD   ?
+sock_proc_count DWORD   MAX_SOCKETS DUP (?)
+COMMON32        ENDS
+
+
+; ----------------------------------------------------------------------------
+; The code segment
+; ----------------------------------------------------------------------------
+
+TEXT32          SEGMENT
+
+                ASSUME  DS:FLAT, ES:FLAT
+
+;
+; emx.dll exports the following functions of this module:
+;
+                PUBLIC  emx_init
+                PUBLIC  emx_syscall
+
+;
+; The following functions are exported to other modules
+;
+                PUBLIC  get_thread
+                PUBLIC  get_tid
+                PUBLIC  init_signal16
+                PUBLIC  sig16_handler
+                PUBLIC  touch
+                PUBLIC  unwind
+
+;
+; The following variables are exported to other modules
+;
+                PUBLIC  pipe_number
+                PUBLIC  queue_number
+                PUBLIC  sock_proc_count
+                PUBLIC  old_sig16_handler
+
+;
+; The following functions are imported from other modules
+;
+                EXTRN   build_arg_env:PROC
+                EXTRN   copy_fork:PROC
+                EXTRN   count_arg_env:PROC
+                EXTRN   dos_call:PROC
+                EXTRN   initialize1:PROC
+                EXTRN   initialize2:PROC
+                EXTRN   raise_from_16:PROC
+                EXTRN   sys_call:PROC
+                EXTRN   dll_init:PROC
+                EXTRN   _DLL_InitTerm:PROC
+                EXTRN   new_thread:PROC
+
+;
+; Import OS/2 API
+;
+                EXTRN   DosUnwindException:PROC
+
+
+; ----------------------------------------------------------------------------
+; Macros
+; ----------------------------------------------------------------------------
+
+;
+; REG := pointer to thread data block
+;
+GET_THREAD      MACRO   REG
+                MOV     REG, (TIB PTR FS:[0]).TIB_SYS_PTR
+                MOV     REG, (TIB2 PTR [REG]).TID
+                MOV     REG, threads[REG*4]
+                ENDM
+
+
+; ----------------------------------------------------------------------------
+; Code
+; ----------------------------------------------------------------------------
+
+;
+; This procedure is called by the startup code, see crt0.s.  A pointer
+; to the layout table is passed on the stack.
+;
+; Doing this in C would be hard because we play dirty tricks with the stack.
+;
+emx_init:       POP     RET_ADDR                ; Remove return address
+                POP     EAX                     ; Pointer to layout table
+                MOV     errout_handle, 2        ; Use stderr unless -!1 given
+                TEST    (LAYOUT_TABLE PTR [EAX]).L_FLAGS, L_FLAG_DLL
+                JNZ     DLL_INIT_1              ; Called by DLL startup code
+                MOV     layout, EAX
+                CALL    initialize1             ; First part of initialization
+              .IF fork_flag
+                MOV     ESP, fork_stack_page
+                CALL    copy_fork
+              .ENDIF
+                CALL    USE_STACK               ; Switch to new stack
+                CALL    initialize2             ; Second part of initialization
+              .IF fork_flag
+                MOV     EBP, fork_ebp
+                MOV     I_EAX, 0                ; Make fork() return 0
+                MOV     I_ECX, 0                ; Keep errno
+                JMP     SYSCALL_RET
+              .ENDIF
+;
+; Compute number of bytes to be allocated for argv[] and envp[] and strings
+;
+                CALL    count_arg_env
+;
+; Allocate space in the stack for the environment pointers and the arguments
+;
+                MOV     ESI, ESP
+                SUB     ESI, arg_size           ; Argument strings are put here
+                MOV     EDI, ESI
+                MOV     EAX, arg_count
+                ADD     EAX, env_count
+                ADD     EAX, 2                  ; Two NULL pointers
+                SHL     EAX, 2
+                SUB     EDI, EAX                ; Tables are put here
+                AND     EDI, NOT 3              ; Alignment
+                MOV     BYTE PTR [EDI], 0       ; Stack probe
+                MOV     ESP, EDI
+;
+; Build envp[] and argv[]
+;
+                PUSH    EDI                     ; vec
+                PUSH    ESI                     ; str
+                CALL    build_arg_env           ; build_arg_env (str, vec)
+                ADD     ESP, 2 * 4
+;
+; Return to startup code
+;
+                JMP     RET_ADDR
+
+;
+; We have been called by the DLL startup code, see dll0.s
+;
+                TALIGN  4
+DLL_INIT_1:     CMP     DWORD PTR [ESP+8], 0    ; Initialization?
+                JNE     SHORT DLL_INIT_2        ; No  -> skip
+                PUSH    EAX
+                CALL    dll_init
+                ADD     ESP, 4
+DLL_INIT_2:     JMP     RET_ADDR
+
+
+;
+; Allocate space for the exception registration record on the stack.
+; If this is a forked process, adjust the stack pointer.
+;
+                TALIGN  4
+USE_STACK       PROC
+                POP     ECX                     ; Retrieve the return address
+                MOV     ESI, stack_end          ; EXC_REGISTER buffer must be
+                SUB     ESI, SIZE EXC_REGISTER  ; be in the stack
+                AND     ESI, NOT 3              ; Align the stack pointer
+                MOV     exc_reg_ptr, ESI
+                MOV     AL, [ESI]               ; Stack probe
+              .IF fork_flag
+                MOV     ESI, fork_ebp
+              .ENDIF
+                MOV     ESP, ESI                ; Allocate space
+                JMP     ECX
+                RET                             ; Avoid warning
+USE_STACK       ENDP
+
+;
+; emx_syscall puts all the registers of the client process into the stack
+; using PUSHAD.  The registers in the stack can then be accessed using the
+; following names.  This can be used both for input and output.
+;
+I_EDI           EQU     (SYSCALL_FRAME PTR [EBP]).SC_EDI
+I_ESI           EQU     (SYSCALL_FRAME PTR [EBP]).SC_ESI
+I_EBP           EQU     (SYSCALL_FRAME PTR [EBP]).SC_EBP
+I_ESP           EQU     (SYSCALL_FRAME PTR [EBP]).SC_ESP
+I_EBX           EQU     (SYSCALL_FRAME PTR [EBP]).SC_EBX
+I_EDX           EQU     (SYSCALL_FRAME PTR [EBP]).SC_EDX
+I_ECX           EQU     (SYSCALL_FRAME PTR [EBP]).SC_ECX
+I_EAX           EQU     (SYSCALL_FRAME PTR [EBP]).SC_EAX
+I_EFLAGS        EQU     (SYSCALL_FRAME PTR [EBP]).SC_EFLAGS
+I_EIP           EQU     (SYSCALL_FRAME PTR [EBP]).SC_EIP
+
+I_AL            EQU     (BYTE PTR I_EAX+0)
+I_AH            EQU     (BYTE PTR I_EAX+1)
+I_CL            EQU     (BYTE PTR I_ECX+0)
+I_CH            EQU     (BYTE PTR I_ECX+1)
+I_DL            EQU     (BYTE PTR I_EDX+0)
+I_DH            EQU     (BYTE PTR I_EDX+1)
+
+;
+; syscall entry point.  AH contains the function number, the other registers
+; contain arguments.  Usually, CY will be set on return though not required
+; for all functions.  The function numbers are somewhat similar to PC-DOS
+; function numbers -- it's simpler to use those numbers than inventing and
+; *remembering* new numbers (or using the(?) Unix syscall function numbers).
+; Using function names would be much more complex.  In fact, even OS/2 uses
+; numbers (import by ordinal).  See system.doc for details.
+;
+; As arguments are passed in registers (which may have been a bad idea),
+; this cannot be done in C.
+;
+                TALIGN  4
+emx_syscall:    PUSHFD
+                PUSHAD                          ; Save all the registers
+                MOV     EBP, ESP                ; Make stack frame
+                CLD                             ; Don't trust anyone
+                GET_THREAD ESI                  ; ESI := pointer to thread data
+                TEST    ESI, ESI                ; Pointer valid?
+                JZ      SHORT SYSCALL_ERRNO_1   ; No  -> skip
+                ASSUME  ESI:PTR THREAD_DATA
+                MOV     EAX, [ESI].LAST_SYS_ERRNO;  Get old error code
+                MOV     [ESI].PREV_SYS_ERRNO, EAX ; Save it for __syserrno()
+                MOV     [ESI].LAST_SYS_ERRNO, 0 ; Clear error code
+                ASSUME  ESI:NOTHING
+SYSCALL_ERRNO_1:MOVZX   EAX, I_AH               ; Get function number
+                CMP     AL, 7FH                 ; Special function?
+                JE      SHORT SPECIAL           ; Yes -> function code in AL
+                PUSH    EBP                     ; f
+                CALL    dos_call                ; dos_call (f)
+                ADD     ESP, 1 * 4
+SYSCALL_RET:    POPAD                           ; Restore registers
+                POPFD
+                RET                             ; Return to user program
+
+                TALIGN  4
+SPECIAL:        PUSH    EBP                     ; f
+                CALL    sys_call                ; sys_call (f)
+                ADD     ESP, 1 * 4
+                JMP     SYSCALL_RET             ; Restore registers and return
+
+;
+; Unwind exception handlers.  Doing this in C would be hairy due to
+; DosUnwindException not returning and stack pointer adjustments done
+; or not done by the C compiler.
+;
+; void unwind (EXCEPTIONREGISTRATIONRECORD *registration,
+;              EXCEPTIONREPORTRECORD *report);
+;
+;
+REGISTRATION    EQU     (DWORD PTR [EBP+2*4])
+REPORT          EQU     (DWORD PTR [EBP+3*4])
+                TALIGN  4
+unwind          PROC
+                PUSH    EBP                     ; Set up stack frame
+                MOV     EBP, ESP
+                PUSH    EBX                     ; Save registers
+                PUSH    ESI
+                PUSH    EDI
+                PUSH    REPORT                  ; Report
+                PUSH    OFFSET FLAT:UNWIND_1    ; Target address (jump there)
+                PUSH    REGISTRATION            ; Handler
+                MOV     AL, 3
+                CALL    DosUnwindException      ; Does not return
+                TALIGN  4
+UNWIND_1:       ADD     ESP, 3 * 4              ; Remove arguments
+                POP     EDI                     ; Restore registers
+                POP     ESI
+                POP     EBX
+                POP     EBP
+                RET
+unwind          ENDP
+
+
+;
+; Get pointer to thread data block.  In assembler, we can do much better
+; (by using FS:0) than in C (using DosGetInfoBlocks).
+;
+                TALIGN  4
+get_thread      PROC
+                GET_THREAD EAX
+                TEST    EAX, EAX
+                JZ      SHORT gt_new
+                RET
+
+; new_thread (tid, NULL)
+gt_new:         CALL    get_tid
+                PUSH    0                       ; errnop
+                PUSH    EAX                     ; tid
+                CALL    new_thread
+                ADD     ESP, 2*4
+                GET_THREAD EAX
+                RET
+get_thread      ENDP
+
+
+;
+; Return the thread ID of the current thread.
+;
+                TALIGN  4
+get_tid         PROC
+                MOV     EAX, (TIB PTR FS:[0]).TIB_SYS_PTR
+                MOV     EAX, (TIB2 PTR [EAX]).TID
+                RET
+get_tid         ENDP
+
+
+;
+; Initialize variables for the 16-bit signal handler.
+;
+                TALIGN  4
+init_signal16   PROC
+                MOV     SS32, SS
+                MOV     FS32, FS
+                MOV     DS32, DS
+                MOV     ES32, ES
+                RET
+init_signal16   ENDP
+
+
+;
+; Touch each page in a range of addresses
+;
+; void touch (void *base, ULONG count);
+;
+; In: BASE      Start address
+;     COUNT     Number of bytes
+;
+; This is required because DosRead seems not to be reentrant enough --
+; if it's used to read data into a page to be loaded from the .EXE file
+; (dumped heap), it's recursively called by the guard pageexception handler.
+; This call seems to disturb the first call, which will return a strange
+; `error code' (ESP plus some constant).
+;
+
+BASE            EQU     (DWORD PTR [EBP+2*4])
+COUNT           EQU     (DWORD PTR [EBP+3*4])
+                TALIGN  4
+touch           PROC
+                PUSH    EBP                     ; Make stack frame
+                MOV     EBP, ESP
+                PUSH    EBX                     ; Save register
+                MOV     ECX, COUNT
+                JECXZ   TOUCH_RET
+                MOV     EBX, BASE
+                MOV     AL, [EBX]               ; Touch first page
+                MOV     EAX, EBX                ; Save start address
+                OR      EBX, 0FFFH              ; Move pointer to
+                INC     EBX                     ; start of next page
+                SUB     EBX, EAX                ; Number of bytes skipped
+                SUB     ECX, EBX                ; Adjust counter
+                JBE     SHORT TOUCH_RET         ; Done -> return
+                ADD     EBX, EAX                ; Recompute pointer
+                TALIGN  4
+TOUCH_1:        MOV     AL, [EBX]               ; Touch a page
+                ADD     EBX, 1000H              ; Move pointer to next page
+                SUB     ECX, 1000H              ; Adjust counter
+                JA      SHORT TOUCH_1           ; More -> repeat
+TOUCH_RET:      POP     EBX                     ; Restore register
+                POP     EBP                     ; Remove stack frame
+                RET                             ; Done
+touch           ENDP
+
+
+;
+; 32-bit code called from 16-bit code: Raise signal CX
+;
+                TALIGN  4
+CALL32:         MOVZX   EAX, CX                 ; Signal number to EAX
+                PUSH    EAX                     ; signo
+;
+; Raise signal (by calling)
+;
+                CALL    raise_from_16           ; raise_from_16 (signo)
+                ADD     ESP, 1 * 4
+;
+; Return to 16-bit code
+;
+                LSS     SP, [ESP]               ; Restore 16-bit stack
+                MOVZX   ESP, SP                 ; Don't trust
+                JMP     FAR PTR TEXT16:MODE32_RET
+
+TEXT32          ENDS
+
+; ----------------------------------------------------------------------------
+; 16-bit section
+; ----------------------------------------------------------------------------
+
+;
+; Import OS/2 API
+;
+
+                EXTRN   _16_Dos16SetSigHandler:FAR16
+
+; ----------------------------------------------------------------------------
+; 16-bit data
+; ----------------------------------------------------------------------------
+
+BSS16           SEGMENT
+
+old_sig16_handler DWORD ?
+
+OLD_SIG_ACTION  DWORD   ?
+
+;
+; Saved segment registers of 32-bit mode, used for switching from
+; a 16-bit signal handler to 32-bit mode.
+;
+DS32            WORD    ?               ; The DS register of 32-bit mode
+ES32            WORD    ?               ; The ES register of 32-bit mode
+SS32            WORD    ?               ; The SS register of 32-bit mode
+FS32            WORD    ?               ; The FS register of 32-bit mode
+
+BSS16           ENDS
+
+; ----------------------------------------------------------------------------
+; 16-bit code
+; ----------------------------------------------------------------------------
+
+TEXT16          SEGMENT
+
+                ASSUME  CS:TEXT16, DS:NOTHING, ES:NOTHING
+
+;
+; The 16-bit signal handler
+;
+SH_SIGNUM       EQU     (WORD PTR [BP+6])       ; Signal number
+SH_SIGARG       EQU     (WORD PTR [BP+8])       ; User-defined argument
+
+                ASSUME  DS:NOTHING
+                TALIGN  4
+sig16_handler   PROC    FAR
+                PUSH    BP                      ; Make stack frame
+                MOV     BP, SP
+                PUSH    DS                      ; Save DS
+                MOV     AX, BSS16
+                MOV     DS, AX                  ; Access our data segment
+                ASSUME  DS:BSS16
+                PUSH    CS                      ; Signal handler function
+                PUSH    OFFSET TEXT16:sig16_handler
+                PUSH    BSS16                   ; Old signal handler function
+                PUSH    OFFSET BSS16:old_sig16_handler
+                PUSH    BSS16                   ; Old signal handler action
+                PUSH    OFFSET BSS16:OLD_SIG_ACTION
+                PUSH    SIGA_ACKNOWLEDGE        ; Action
+                PUSH    SH_SIGNUM               ; Signal
+                CALL    _16_Dos16SetSigHandler  ; Acknowledge signal
+                MOV     CX, SH_SIGARG
+                CALL    MODE32                  ; Raise 32-bit signal
+                POP     DS                      ; Restore DS
+                ASSUME  DS:NOTHING
+                POP     BP                      ; Remove stack frame
+                RET     4                       ; Remove arguments
+sig16_handler   ENDP
+
+                ASSUME  DS:BSS16
+;
+; Call 32-bit code from 16-bit code
+;
+                TALIGN  4
+MODE32          PROC    NEAR
+                PUSH    FS
+                PUSH    BP
+                MOV     BP, SP
+                SUB     SP, 4
+                AND     SP, NOT 3               ; Align SP on a DWORD
+                MOV     [BP-4], EAX
+                MOV     AX, SP
+                PUSH    SS
+                PUSH    AX
+                MOV     AX, SS
+                SHR     AX, 3
+                SHL     EAX, 16
+                MOV     AX, SP
+                PUSH    SS32
+                PUSH    EAX
+                MOVZX   ESP, SP
+;
+; Restore the FS register of 32-bit mode.  FS:0 points to the TIB.
+; Fortunately, the selector seems to be the same for all the threads.
+; If each thread had its own selector, we would have a problem.  The
+; only solution for this case I can think of is to store the FS register
+; in the thread-specific data block.
+;
+                MOV     FS, FS32
+;
+; Restore the DS and ES registers of 32-bit mode.
+;
+                MOV     ES, ES32
+                MOV     DS, DS32
+                ASSUME  DS:NOTHING
+                MOV     EAX, [BP-4]
+                LSS     ESP, [ESP]
+                JMP     FAR PTR FLAT:CALL32
+;
+; Return here from CALL32.
+;
+                TALIGN  4
+MODE32_RET::    PUSH    AX
+                MOV     AX, BSS16
+                MOV     DS, AX
+                ASSUME  DS:BSS16
+                POP     AX
+                MOV     SP, BP
+                POP     BP
+                POP     FS
+                RET
+MODE32          ENDP
+
+TEXT16          ENDS
+
+                END     _DLL_InitTerm
Index: trunk/src/emx/src/os2/emxdll.def
===================================================================
--- trunk/src/emx/src/os2/emxdll.def	(revision 18)
+++ trunk/src/emx/src/os2/emxdll.def	(revision 18)
@@ -0,0 +1,48 @@
+;
+; emxdll.def
+;
+; Copyright (c) 1992-1998 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; As special exception, emx.dll can be distributed without source code
+; unless it has been changed.  If you modify emx.dll, this exception
+; no longer applies and you must remove this paragraph from all source
+; files for emx.dll.
+;
+
+LIBRARY EMX INITINSTANCE TERMINSTANCE
+DESCRIPTION 'emx.dll 0.9d -- Copyright (c) 1992-1998 by Eberhard Mattes'
+DATA
+   MULTIPLE NONSHARED
+SEGMENTS
+  TEXT16   CLASS 'CODE'   ALIAS
+  _TEXT    CLASS 'CODE'   ALIAS
+  DATA32   CLASS 'DATA'   ALIAS MIXED1632
+  BSS16    CLASS 'BSS'    ALIAS
+  BSS32    CLASS 'BSS'    ALIAS MIXED1632
+  c_common CLASS 'BSS'    ALIAS MIXED1632
+  COMMON32 CLASS 'COMMON' SHARED
+EXPORTS
+  EMX_INIT     = emx_init      @1 RESIDENTNAME
+  EMX_SYSCALL  = emx_syscall   @2 RESIDENTNAME
+  EMX_16TO32   = _emx_16to32   @3 RESIDENTNAME
+  EMX_32TO16   = _emx_32to16   @4 RESIDENTNAME
+  EMX_THUNK1   = _emx_thunk1   @5 RESIDENTNAME
+  EMX_EXCEPTION = exception    @6 RESIDENTNAME
+  EMX_REVISION = emx_revision  @128 RESIDENTNAME
Index: trunk/src/emx/src/os2/emxdll.h
===================================================================
--- trunk/src/emx/src/os2/emxdll.h	(revision 18)
+++ trunk/src/emx/src/os2/emxdll.h	(revision 18)
@@ -0,0 +1,574 @@
+/* emxdll.h -- Global header file for emx.dll
+   Copyright (c) 1992-2000 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define STR(X)  #X
+#define XSTR(X) STR(X)
+
+/* Round up to the next integral multiple of the page size. */
+
+#define ROUND_PAGE(x)  ((((x) - 1) & ~0xfff) + 0x1000)
+
+/* IBM TCP/IP's socket handles are < 2048.  See also emxdll.asm. */
+
+#define MAX_SOCKETS     2048
+
+/* Maximum number of file handles created by sock_init().  As of
+   TCP/IP 2.0, sock_init() creates two handles. */
+
+#define MAXFH_SOCK_INIT 2
+
+/* Maximum number of heap objects (16 = 512 / 32). */
+
+#define MAX_HEAP_OBJS   16
+
+/* This is the default heap object size. */
+
+#define HEAP_OBJ_SIZE   (32 * 1024 * 1024)
+
+#define ENTRY_POINT     0x10000
+#define U_OFFSET        0x0400
+#define KERNEL_U_ADDR   0x0e0000000
+
+/* Bits in `handle_flags[]' and `files[].flags' */
+
+#define HF_FILE         0x0001
+#define HF_DEV          0x0002
+#define HF_UPIPE        0x0004
+#define HF_NPIPE        0x0008
+#define HF_CON          0x0010
+#define HF_NUL          0x0040
+#define HF_CLK          0x0080
+#define HF_ASYNC        0x0100
+#define HF_SOCKET       0x0200
+#define HF_XF86SUP      0x0400
+#define HF_OPEN         0x1000
+#define HF_APPEND       0x2000
+#define HF_NDELAY       0x4000
+#define HF_NOINHERIT    0x80000000 /* Temporarily used while forking */
+
+#define L_FLAG_DLL              0x0001
+#define L_FLAG_LINK386          0x0002
+
+#define FORK_REQ_DONE           0
+#define FORK_REQ_INIT           1
+#define FORK_REQ_DLL            2
+#define FORK_REQ_MEM            3
+
+#define FORK_OBJ_SIZE           0x20000 /* 128KB */
+
+#define DEBUG_STDERR    0x0001  /* Open CON device, don't use handle 2 */
+#define DEBUG_STACK     0x0002  /* Unused */
+#define DEBUG_SETMEM    0x0004  /* Show setmem() arguments */
+#define DEBUG_SYSCALL   0x0008  /* Show syscalls */
+#define DEBUG_TERMIO    0x0010  /* Unused */
+#define DEBUG_FIND1     0x0020  /* Fetch only 1 entry with DosFindFirst/Next */
+#define DEBUG_QPINFO2   0x0040  /* Call DosQueryPathInfo twice */
+#define DEBUG_NOXF86SUP 0x0080  /* Don't check for xf86sup devices */
+#define DEBUG_NOINHSIG  0x0100  /* Don't inherit signal actions */
+#define DEBUG_NOFDZERO  0x0200  /* Don't fix select()'s missing FD_ZERO bug */
+#define DEBUG_NOFORKDLL 0x0400  /* Don't load DLLs in forked process */
+#define DEBUG_SOCLOSE   0x0800  /* Don't mind socket closed behind our back */
+
+#define NSIG            29
+
+#define FIND_COUNT      4
+
+#define FLAG_C          0x0001
+#define FLAG_Z          0x0040
+
+/* TRUNC_DRV() is defined for 'A' through 'Z', 'a' through 'z', and 1
+   through 26. */
+
+#define TRUNC_UNC       (1 << 0)
+#define TRUNC_DRV(c)    (1 << ((c) & 0x1f))
+#define TRUNC_ALL       (~0)
+
+typedef void (sigfun)(int signo);
+
+struct select_data;
+struct stat;
+struct termio;
+struct termios;
+struct timeb;
+struct timeval;
+struct _find;
+struct _new_proc;
+struct _profil;
+struct _select;
+
+struct signal_entry
+{
+  sigfun *handler;              /* Signal handler, SIG_DFL, or SIG_IGN */
+  ULONG sa_mask;                /* Signals to be blocked */
+  ULONG sa_flags;               /* Flags */
+};
+
+typedef struct
+{
+  ULONG text_base;
+  ULONG text_end;
+  ULONG data_base;
+  ULONG data_end;
+  ULONG bss_base;
+  ULONG bss_end;
+  ULONG heap_base;
+  ULONG heap_end;
+  ULONG heap_brk;
+  ULONG heap_off;
+  ULONG os2_dll;
+  ULONG stack_base;
+  ULONG stack_end;
+  ULONG flags;
+  ULONG reserved[2];
+  char options[64];
+} layout_table;
+
+typedef struct
+{
+  ULONG last_sys_errno;         /* Error code for last syscall */
+  ULONG prev_sys_errno;         /* Previous value of the above */
+  ULONG find_handle;
+  ULONG find_count;
+  ULONG sig_blocked;            /* Blocked signals */
+  ULONG sig_pending;            /* Pending signals */
+  ULONG sig_prev_blocked;       /* Previous signal mask */
+  FILEFINDBUF3 find_buf[FIND_COUNT];
+  const FILEFINDBUF3 *find_next;
+  struct signal_entry sig_table[NSIG];
+} thread_data;
+
+typedef union
+{
+  struct
+    {
+      ULONG edi;
+      ULONG esi;
+      ULONG ebp;
+      ULONG esp;
+      ULONG ebx;
+      ULONG edx;
+      ULONG ecx;
+      ULONG eax;
+      ULONG eflags;
+      ULONG eip;
+    } e;
+  struct
+    {
+      USHORT di;
+      USHORT edi_hi;
+      USHORT si;
+      USHORT esi_hi;
+      USHORT bp;
+      USHORT ebp_hi;
+      USHORT sp;
+      USHORT esp_hi;
+      USHORT bx;
+      USHORT ebx_hi;
+      USHORT dx;
+      USHORT edx_hi;
+      USHORT cx;
+      USHORT ecx_hi;
+      USHORT ax;
+      USHORT eax_hi;
+      USHORT flags;
+      USHORT eflags_hi;
+      USHORT ip;
+      USHORT eip_hi;
+    } x;
+  struct
+    {
+      ULONG edi;
+      ULONG esi;
+      ULONG ebp;
+      ULONG esp;
+      UCHAR bl;
+      UCHAR bh;
+      USHORT ebx_hi;
+      UCHAR dl;
+      UCHAR dh;
+      USHORT edx_hi;
+      UCHAR cl;
+      UCHAR ch;
+      USHORT ecx_hi;
+      UCHAR al;
+      UCHAR ah;
+      USHORT eax_hi;
+      ULONG eflags;
+      ULONG eip;
+    } b;
+} syscall_frame;
+
+struct fork_data_dll
+{
+  ULONG req_code;               /* Request code */
+  HMODULE hmod;                 /* Module handle */
+  char path[CCHMAXPATH+1];      /* File name */
+};
+
+struct fork_data_mem
+{
+  ULONG req_code;               /* Request code */
+  ULONG address;
+  ULONG count;
+  HMODULE hmod;
+  void *shared;
+  char buf[1];
+};
+
+struct fork_data_init
+{
+  ULONG req_code;               /* Request code */
+  ULONG msize;                  /* Size of shared memory object */
+  ULONG brk;
+  ULONG stack_base;
+  ULONG stack_page;
+  ULONG reg_ebp;
+  ULONG umask;
+  ULONG umask1;
+  ULONG uflags;                 /* User flags */
+  HEV req_sem;
+  HEV ack_sem;
+};
+
+struct fork_sock
+{
+  int f;                    /* File handle */
+  int s;                    /* Socket handle */
+};
+
+struct fork_data_done
+{
+  ULONG req_code;               /* Request code */
+  ULONG size;                   /* Number of bytes used for this structure */
+  struct signal_entry sig_actions[NSIG];
+  ULONG handle_count;           /* Number of file handles */
+  ULONG *fd_flags_array;        /* FD_CLOEXEC */
+  ULONG sock_init_count;        /* Number of handles created by sock_init() */
+  ULONG sock_init_array[MAXFH_SOCK_INIT];
+  ULONG sock_count;             /* Number of sockets */
+  struct fork_sock *sock_array; /* File and socket handles */
+};
+
+typedef union
+{
+  ULONG req_code;
+  struct fork_data_dll dll;
+  struct fork_data_mem mem;
+  struct fork_data_init init;
+  struct fork_data_done done;
+} fork_data;
+
+
+struct my_datetime
+{
+  ULONG seconds;
+  ULONG minutes;
+  ULONG hours;
+  ULONG day;
+  ULONG month;
+  ULONG year;
+};
+
+/* This structure describes one heap object. */
+
+struct heap_obj
+{
+  ULONG base;                   /* Base address */
+  ULONG end;                    /* End address */
+  ULONG brk;                    /* Address of first unused byte */
+};
+
+extern BYTE opt_drive;
+extern ULONG opt_trunc;
+extern BYTE opt_expand;
+extern BYTE opt_quote;
+extern ULONG debug_flags;
+extern HMTX common_mutex;
+extern BYTE debug_same_sess;
+extern HFILE errout_handle;
+extern HEV signal_sem;
+extern HEV kbd_sem_new;
+extern ULONG stack_base;
+extern ULONG stack_end;
+extern BYTE exe_name[];
+extern HFILE exe_fhandle;
+extern BYTE exe_heap;
+extern BYTE nocore_flag;
+extern BYTE no_popup;
+extern thread_data *threads[];
+extern ULONG layout_flags;
+extern BYTE interface;
+extern ULONG umask_bits;
+extern ULONG umask_bits1;
+extern char *startup_env;
+extern layout_table *layout;
+extern char kbd_started;
+extern ULONG my_pid;
+extern BYTE fork_flag;
+extern ULONG fork_exec_pid;
+extern char const signal_valid[NSIG];
+extern ULONG uflags;
+extern int zombie_count;
+extern char sig_flag;
+extern BYTE dont_doskillthread;
+extern ULONG version_major;
+extern ULONG version_minor;
+extern ULONG heap_obj_size;
+extern unsigned heap_obj_count;
+extern char first_heap_obj_fixed;
+extern ULONG heap_off;
+extern struct heap_obj *top_heap_obj;
+extern struct heap_obj heap_objs[MAX_HEAP_OBJS];
+extern BYTE ptrace_forking;
+extern ULONG ptrace_fork_addr;
+
+#if defined (INCL_DOSPROCESS)
+extern PIB *init_pib_ptr;
+#endif
+
+#if defined (INCL_DOSEXCEPTIONS)
+extern EXCEPTIONREGISTRATIONRECORD *exc_reg_ptr;
+#endif
+
+/* The following variables reside in a shared data object and are
+   defined in emxdll.asm. */
+
+/* Counter for creating unique names for named pipes. */
+
+extern ULONG pipe_number;
+
+/* Counter for creating unique names for queues. */
+
+extern ULONG queue_number;
+
+/* This array holds reference counts for socket handles:
+   sock_proc_count[S] is the number of processes referencing socket
+   handle S.  The per-process reference count is maintained in *files,
+   see files.h.  Fortunately, the range of socket handles of IBM
+   TCP/IP is bound: all socket handles are less than 2048; see
+   FD_SETSIZE in IBM's <sys/socket.h>. */
+
+extern ULONG sock_proc_count[MAX_SOCKETS];
+
+
+/* Access to shared data should be enclosed in LOCK_COMMON and
+   UNLOCK_COMMON. */
+
+#define LOCK_COMMON    do_lock_common ()
+#define UNLOCK_COMMON  DosReleaseMutexSem (common_mutex)
+
+
+/* Prototypes. */
+
+void truncate_name (char *dst, const char *src);
+ULONG set_error (ULONG rc);
+int xlate_errno (int e);
+void child_started (void);
+void start_cwait_thread (void);
+ULONG kbd_avail (void);
+int termio_read (ULONG handle, char *dst, unsigned count, int *errnop);
+void otext (const char *msg);
+void odword (ULONG x);
+void core_dump (void);
+ULONG core_main (ULONG handle);
+void core_regs_i (syscall_frame *frame);
+void generate_signal (thread_data *td, int signo);
+thread_data *get_thread (void);
+int get_tid (void);
+int proc_check (int pid);
+ULONG querysysinfo (ULONG index);
+unsigned long long get_clock (int init_flag);
+void init_signal16 (void);
+void touch (void *base, ULONG count);
+void conout (UCHAR chr);
+ULONG load_module (const char *mod_name, HMODULE *phmod);
+int verify_memory (ULONG start, ULONG size);
+
+#if defined (INCL_DOSEXCEPTIONS)
+void core_regs_e (CONTEXTRECORD *context);
+int initthread (EXCEPTIONREGISTRATIONRECORD *registration);
+void unwind (EXCEPTIONREGISTRATIONRECORD *registration,
+    EXCEPTIONREPORTRECORD *report);
+int deliver_pending_signals (thread_data *td, syscall_frame *frame,
+    CONTEXTRECORD *context_record);
+#endif
+
+void init_fileio (void);
+void init_process (void);
+void init_fork (const char *s);
+void init_exceptions (void);
+void initialize1 (void);
+void initialize2 (void);
+void init2_signal (void);
+void term_process (void);
+void term_memory (void);
+void term_semaphores (void);
+void term_tcpip (void);
+void term_signal (void);
+ULONG setmem (ULONG base, ULONG size, ULONG flags, ULONG error);
+ULONG setmem_error (ULONG rc);
+void *checked_private_alloc (ULONG size);
+ULONG private_alloc (void **mem, ULONG size);
+ULONG private_free (void *mem);
+void error (ULONG rc, const char *msg);
+int conv_hex8 (const char *s, ULONG *dst);
+void receive_signals (void);
+ULONG reset_event_sem (HEV sem);
+sigfun *do_signal (ULONG signo, sigfun *handler, syscall_frame *frame);
+void do_raise (int signo, syscall_frame *frame);
+int do_kill (int signo, int pid, syscall_frame *frame, int *errnop);
+void sig_block_start (void);
+void sig_block_end (void);
+ULONG set_alarm (ULONG value);
+void stop_alarm (void);
+ULONG do_wait (ULONG *ptermstatus, ULONG *errnop);
+ULONG do_waitpid (ULONG pid, ULONG opt, ULONG *ptermstatus,
+    ULONG *errnop);
+void init_heap (void);
+long do_sbrk (long incr);
+long do_brk (ULONG brkp);
+int do_fcntl (ULONG handle, ULONG request, ULONG arg, int *errnop);
+int do_ioctl1 (ULONG handle, int *errnop);
+int do_ioctl2 (ULONG handle, ULONG request, ULONG arg, int *errnop);
+int do_dup (ULONG handle, ULONG target, int *errnop);
+int do_close (ULONG handle);
+ULONG do_read (ULONG handle, void *dst, ULONG count, int *errnop);
+ULONG do_write (ULONG handle, void *src, ULONG count, int *errnop);
+ULONG do_seek (ULONG handle, ULONG origin, LONG distance, int *errnop);
+int do_pipe (int *dst, ULONG pipesize);
+int do_ftruncate (ULONG handle, ULONG fsize);
+int do_chsize (ULONG handle, ULONG fsize);
+int do_fsync (ULONG handle, int *errnop);
+int do_filesys (char *dst, ULONG dst_size, const char *drv_name, int *errnop);
+int do_mkdir (const char *path);
+int do_rmdir (const char *path);
+int do_chdir (const char *path);
+int do_delete (const char *path);
+int do_rename (const char *old_path, const char *new_path);
+UCHAR do_getdrive (void);
+ULONG do_selectdisk (ULONG drv);
+int old_creat (const char *path, ULONG attr, int *errnop);
+int old_open (const char *path, ULONG mode, int *errnop);
+int sys_open (const char *path, unsigned flags, unsigned long size,
+    int *errnop);
+int do_stat (const char *path, struct stat *dst, int *errnop);
+int do_fstat (ULONG handle, struct stat *dst, int *errnop);
+int do_utimes (const char *path, const struct timeval *tv, int *errnop);
+int do_ttyname (char *dst, ULONG dst_size, ULONG handle, int *errnop);
+void do_lock_common (void);
+ULONG create_event_sem (HEV *psem, ULONG attr);
+void close_event_sem (HEV sem);
+ULONG create_mutex_sem (HMTX *psem);
+void request_mutex (HMTX sem);
+ULONG create_muxwait_sem (HMUX *psem, ULONG count, SEMRECORD *array,
+    ULONG attr);
+void close_muxwait_sem (HMUX sem);
+ULONG get_attr (const char *path, int *errnop);
+ULONG set_attr (const char *path, ULONG attr);
+ULONG do_getcwd (char *dst, int drive);
+ULONG do_find_first (const char *path, ULONG attr, struct _find *dst);
+ULONG do_find_next (struct _find *dst);
+ULONG do_get_timestamp (ULONG handle, ULONG *time, ULONG *date);
+ULONG do_set_timestamp (ULONG handle, ULONG time, ULONG date);
+ULONG do_imphandle (ULONG handle, int *errnop);
+int check_npipe (const char *s);
+int set_ttyname (char *dst, ULONG dst_size, const char *name, int *errnop);
+void fork_register_mem (ULONG start, ULONG end, HMODULE hmod);
+void fork_register_dll (HMODULE hmod);
+int fork_dll_registered (HMODULE hmod);
+void copy_fork (void);
+void fileio_fork_parent_init (void);
+void fileio_fork_parent_fillin (struct fork_data_done *p);
+void fileio_fork_parent_restore (void);
+void fileio_fork_child (struct fork_data_done *p);
+ULONG new_thread (ULONG tid, int *errnop);
+ULONG end_thread (ULONG tid, int *errnop);
+void kbd_stop (void);
+void kbd_init (void);
+void kbd_restart (void);
+void quit (ULONG rc) __attribute__ ((noreturn));
+void do_ftime (struct timeb *dst);
+int do_settime (const struct timeval *tp, int *errnop);
+ULONG do_spawn (struct _new_proc *np, ULONG *result);
+void do_pause (void);
+int do_ptrace (ULONG request, ULONG pid, ULONG addr, ULONG data,
+    ULONG *errnop);
+ULONG spawn_debug (ULONG pid, ULONG sid);
+int do_fork (syscall_frame *frame, ULONG *errnop);
+int do_select (struct _select *args, int *errnop);
+int execname (char *buf, ULONG bufsize);
+void debug_set_wait (ULONG pid, ULONG tid, ULONG wait_ret, ULONG end);
+ULONG proc_add_attach (ULONG pid);
+void proc_remove_attach (ULONG pid);
+void unix2time (struct my_datetime *dst, ULONG src);
+ULONG packed2unix (FDATE date, FTIME time);
+int kbd_input (UCHAR *dst, int binary_p, int echo_p, int wait_p,
+    int check_avail_p);
+void conin_string (UCHAR *buf);
+int sprintf (char *dst, const char *fmt, ...);
+void oprintf (const char *fmt, ...);
+ULONG get_dbcs_lead (void);
+ULONG query_async (ULONG handle);
+ULONG translate_async (ULONG handle);
+void init_termio (ULONG handle);
+void termio_set (ULONG handle, const struct termio *tio);
+void termio_get (ULONG handle, struct termio *tio);
+void termios_set (ULONG handle, const struct termios *tio);
+void termios_get (ULONG handle, struct termios *tio);
+void termio_flush (ULONG handle);
+ULONG termio_avail (ULONG handle);
+ULONG async_avail (ULONG handle);
+ULONG async_writable (ULONG handle);
+int do_profil (const struct _profil *p, int *errnop);
+
+void exit_tcpip (void);
+int tcpip_init_fork (const struct fork_data_done *p);
+void copy_fork_sock (const struct fork_data_done *p);
+void tcpip_fork_sock (struct fork_data_done *p);
+void tcpip_undo_fork_sock (const struct fork_data_done *p);
+
+int pm_init (void);
+void pm_term (void);
+void pm_message_box (PCSZ text);
+
+#if defined (_SIGSET_T)
+int do_sigaction (int sig, const struct sigaction *iact,
+    struct sigaction *oact);
+int do_sigpending (sigset_t *set);
+int do_sigprocmask (int how, const sigset_t *iset, sigset_t *oset,
+    syscall_frame *frame);
+int do_sigsuspend (const sigset_t *mask);
+#endif
+
+ULONG xf86sup_query (ULONG handle, ULONG *pflags);
+int xf86sup_avail (ULONG handle, int *errnop);
+int xf86sup_ioctl (ULONG handle, ULONG request, ULONG arg, int *errnop);
+int xf86sup_fcntl (ULONG handle, ULONG request, ULONG arg, int *errnop);
+int xf86sup_select_add_read (struct select_data *d, int fd);
+int xf86sup_ttyname (char *dst, ULONG dst_size, ULONG handle, int *errnop);
+ULONG xf86sup_uncond_enadup (ULONG handle, ULONG on);
+ULONG xf86sup_maybe_enadup (ULONG handle, ULONG on);
+void xf86sup_all_enadup (ULONG on);
Index: trunk/src/emx/src/os2/emxdll.inc
===================================================================
--- trunk/src/emx/src/os2/emxdll.inc	(revision 18)
+++ trunk/src/emx/src/os2/emxdll.inc	(revision 18)
@@ -0,0 +1,141 @@
+;
+; EMXDLL.INC
+;
+; Copyright (c) 1992-1995 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; As special exception, emx.dll can be distributed without source code
+; unless it has been changed.  If you modify emx.dll, this exception
+; no longer applies and you must remove this paragraph from all source
+; files for emx.dll.
+;
+
+                OPTION  PROC:PRIVATE
+
+; ----------------------------------------------------------------------------
+; Segments
+; ----------------------------------------------------------------------------
+
+TEXT32          SEGMENT DWORD FLAT PUBLIC 'CODE'
+TEXT32          ENDS
+
+TEXT16          SEGMENT DWORD USE16 PUBLIC 'CODE'
+TEXT16          ENDS
+
+BSS16           SEGMENT DWORD USE16 PUBLIC 'BSS'
+BSS16           ENDS
+
+BSS32           SEGMENT DWORD FLAT PUBLIC 'BSS'
+BSS32           ENDS
+
+c_common        SEGMENT DWORD FLAT PUBLIC 'BSS'
+c_common        ENDS
+
+COMMON32        SEGMENT DWORD FLAT PUBLIC 'COMMON'
+COMMON32        ENDS
+
+DGROUP          GROUP c_common
+
+; ----------------------------------------------------------------------------
+; Constants
+; ----------------------------------------------------------------------------
+
+;
+; NOT FALSE will be used instead of TRUE to avoid size problems
+;
+FALSE           =       0
+
+__EMXDOS        =       FALSE
+
+SIGA_KILL               = 0
+SIGA_IGNORE             = 1
+SIGA_ACCEPT             = 2
+SIGA_ERROR              = 3
+SIGA_ACKNOWLEDGE        = 4
+
+L_FLAG_DLL              = 0001H                 ; Executable is a DLL
+L_FLAG_LINK386          = 0002H                 ; Linked by LINK386
+
+; ----------------------------------------------------------------------------
+; Structures
+; ----------------------------------------------------------------------------
+
+LAYOUT_TABLE    STRUC
+L_TEXT_BASE     DD      ?
+L_TEXT_END      DD      ?
+L_DATA_BASE     DD      ?
+L_DATA_END      DD      ?
+L_BSS_BASE      DD      ?
+L_BSS_END       DD      ?
+L_HEAP_BASE     DD      ?
+L_HEAP_END      DD      ?
+L_HEAP_BRK      DD      ?
+L_HEAP_OFF      DD      ?
+L_OS2_DLL       DD      ?
+L_STACK_BASE    DD      ?
+L_STACK_END     DD      ?
+L_FLAGS         DD      ?
+L_RESERVED      DD      2 DUP (?)
+L_OPTIONS       DB      64 DUP (?)
+LAYOUT_TABLE    ENDS
+
+EXC_REGISTER    STRUCT
+ES_PREV         DD      ?
+ES_HANDLER      DD      ?
+EXC_REGISTER    ENDS
+
+TIB             STRUCT
+TIB_EXC_CHAIN   DD      ?
+TIB_STACK_BASE  DD      ?
+TIB_STACK_END   DD      ?
+TIB_SYS_PTR     DD      ?
+TIB_VERSION     DD      ?
+TIB_USER_DATA   DD      ?
+TIB             ENDS
+
+TIB2            STRUCT
+TID             DWORD   ?
+PRIORITY        DWORD   ?
+VERSION         DWORD   ?
+MC_COUNT        WORD    ?
+MC_FORCE_FLAG   WORD    ?
+TIB2            ENDS
+
+;
+; A REXX string (used by emxio.asm)
+;
+RXSTRING        STRUCT
+RXSTRLEN        DWORD   ?
+RXSTRPTR        DWORD   ?
+RXSTRING        ENDS
+
+
+; ----------------------------------------------------------------------------
+; Macros
+; ----------------------------------------------------------------------------
+
+DALIGN          MACRO   VAL:REQ
+                ALIGN   VAL
+                ENDM
+
+TALIGN          MACRO   VAL:REQ
+                ALIGN   VAL
+                ENDM
+
+; End of EMXDLL.INC
Index: trunk/src/emx/src/os2/emxio.asm
===================================================================
--- trunk/src/emx/src/os2/emxio.asm	(revision 18)
+++ trunk/src/emx/src/os2/emxio.asm	(revision 18)
@@ -0,0 +1,598 @@
+;
+; EMXIO.ASM
+;
+; Copyright (c) 1992-1998 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; As special exception, emxio.dll can be distributed without source code
+; unless it has been changed.  If you modify emxio.dll, this exception
+; no longer applies and you must remove this paragraph from all source
+; files for emxio.dll.
+;
+
+
+                .386
+
+IMPORT_OS2      =       0
+                INCLUDE EMXDLL.INC
+
+                PUBLIC  emx_revision
+
+
+REV_INDEX_TXT   EQU     <"60">                  ; Revision index (as text)
+REV_INDEX_BIN   =       60                      ; Revision index (as number)
+
+
+TEXT32          SEGMENT
+
+                ASSUME  DS:FLAT, ES:FLAT
+
+$REV_INDEX      BYTE    REV_INDEX_TXT, 0
+
+;
+; This REXX-callable entrypoint returns a string indicating the
+; version and revision of emxio.dll as integer. The number will be
+; incremented for each revision and is used only for comparing.
+;
+
+                TALIGN  4
+emx_revision    PROC    C PUBLIC USES EBX ESI EDI,
+                        PROCNAME:PTR BYTE, NUMARGS:DWORD, ARGS:PTR RXSTRING,
+                        QUEUENAME:PTR BYTE, RETSTR:PTR RXSTRING
+              .IF     NUMARGS != 0              ; Arguments given?
+                MOV     EAX, 1                  ; Yes: error
+              .ELSE
+                MOV     EBX, RETSTR             ; Return value
+                ASSUME  EBX:PTR RXSTRING
+                LEA     ESI, $REV_INDEX
+                MOV     EDI, [EBX].RXSTRPTR
+REV1:           LODSB
+                STOSB
+                OR      AL, AL
+                JNZ     REV1
+                MOV     EAX, EDI
+                DEC     EAX
+                SUB     EAX, [EBX].RXSTRPTR     ; Compute length of string
+                MOV     [EBX].RXSTRLEN, EAX     ; Set string length
+                ASSUME  EBX:NOTHING
+                XOR     EAX, EAX                ; Successful
+              .ENDIF
+                RET
+
+                MOV     EAX, PROCNAME           ; Avoid warning
+                MOV     EAX, ARGS               ; Avoid warning
+                MOV     EAX, QUEUENAME          ; Avoid warning
+emx_revision    ENDP
+
+;
+; unsigned _inp8 (unsigned port)
+;
+                TALIGN  4
+emx_inp8        PROC    C PUBLIC, PORT:DWORD
+                MOV     EDX, PORT
+                MOV     EAX, 0
+                CALL    MODE16
+                RET
+emx_inp8        ENDP
+
+;
+; void _outp8 (unsigned port, unsigned value)
+;
+                TALIGN  4
+emx_outp8       PROC    C PUBLIC, PORT:DWORD, VALUE:DWORD
+                MOV     EDX, PORT
+                MOV     ECX, VALUE
+                MOV     EAX, 1
+                CALL    MODE16
+                RET
+emx_outp8       ENDP
+
+;
+; unsigned _inp16 (unsigned port)
+;
+                TALIGN  4
+emx_inp16       PROC    C PUBLIC, PORT:DWORD
+                MOV     EDX, PORT
+                MOV     EAX, 2
+                CALL    MODE16
+                RET
+emx_inp16       ENDP
+
+;
+; void _outp16 (unsigned port, unsigned value)
+;
+                TALIGN  4
+emx_outp16      PROC    C PUBLIC, PORT:DWORD, VALUE:DWORD
+                MOV     EDX, PORT
+                MOV     ECX, VALUE
+                MOV     EAX, 3
+                CALL    MODE16
+                RET
+emx_outp16      ENDP
+
+;
+; unsigned _inp32 (unsigned port)
+;
+                TALIGN  4
+emx_inp32       PROC    C PUBLIC, PORT:DWORD
+                MOV     EDX, PORT
+                MOV     EAX, 4
+                CALL    MODE16
+                RET
+emx_inp32       ENDP
+
+;
+; void _outp32 (unsigned port, unsigned value)
+;
+                TALIGN  4
+emx_outp32      PROC    C PUBLIC, PORT:DWORD, VALUE:DWORD
+                MOV     EDX, PORT
+                MOV     ECX, VALUE
+                MOV     EAX, 5
+                CALL    MODE16
+                RET
+emx_outp32      ENDP
+
+
+;
+; void _inps8 (unsigned port, unsigned char *dst, unsigned count)
+;
+                TALIGN  4
+emx_inps8       PROC    C PUBLIC USES EDI, PORT:DWORD, DST:PTR BYTE, COUNT:DWORD
+                MOV     EDI, DST
+                MOV     EDX, PORT
+                MOV     ECX, COUNT
+                MOV     EAX, 6
+                CALL    MODE16
+                RET
+emx_inps8       ENDP
+
+;
+; void _outps8 (unsigned port, const unsigned char *src, unsigned count)
+;
+                TALIGN  4
+emx_outps8      PROC    C PUBLIC USES ESI, PORT:DWORD, SRC:PTR BYTE, COUNT:DWORD
+                MOV     ESI, SRC
+                MOV     EDX, PORT
+                MOV     ECX, COUNT
+                MOV     EAX, 7
+                CALL    MODE16
+                RET
+emx_outps8      ENDP
+
+;
+; void _outpt (const void *table);
+;
+                TALIGN  4
+emx_outpt       PROC    C PUBLIC USES ESI, TABLE:PTR DWORD
+                MOV     ESI, TABLE
+                MOV     EAX, 8
+                CALL    MODE16
+                RET
+emx_outpt       ENDP
+
+;
+; void _inps16 (unsigned port, unsigned short *dst, unsigned count);
+;
+                TALIGN  4
+emx_inps16      PROC    C PUBLIC USES EDI, PORT:DWORD, DST:PTR BYTE, COUNT:DWORD
+                MOV     EDI, DST
+                MOV     EDX, PORT
+                MOV     ECX, COUNT
+                MOV     EAX, 9
+                CALL    MODE16
+                RET
+emx_inps16      ENDP
+
+;
+; void _outps16 (unsigned port, const unsigned short *src, unsigned count)
+;
+                TALIGN  4
+emx_outps16     PROC    C PUBLIC USES ESI, PORT:DWORD, SRC:PTR BYTE, COUNT:DWORD
+                MOV     ESI, SRC
+                MOV     EDX, PORT
+                MOV     ECX, COUNT
+                MOV     EAX, 10
+                CALL    MODE16
+                RET
+emx_outps16     ENDP
+
+;
+; void _inps32 (unsigned port, unsigned long *dst, unsigned count);
+;
+                TALIGN  4
+emx_inps32      PROC    C PUBLIC USES EDI, PORT:DWORD, DST:PTR BYTE, COUNT:DWORD
+                MOV     EDI, DST
+                MOV     EDX, PORT
+                MOV     ECX, COUNT
+                MOV     EAX, 11
+                CALL    MODE16
+                RET
+emx_inps32      ENDP
+
+;
+; void _outps32 (unsigned port, const unsigned long *src, unsigned count)
+;
+                TALIGN  4
+emx_outps32     PROC    C PUBLIC USES ESI, PORT:DWORD, SRC:PTR BYTE, COUNT:DWORD
+                MOV     ESI, SRC
+                MOV     EDX, PORT
+                MOV     ECX, COUNT
+                MOV     EAX, 12
+                CALL    MODE16
+                RET
+emx_outps32     ENDP
+
+;
+; void _wait01 (unsigned port, unsigned mask)
+;
+                TALIGN  4
+emx_wait01      PROC    C PUBLIC, PORT:DWORD, BITS:DWORD
+                MOV     EDX, PORT
+                MOV     ECX, BITS
+                MOV     EAX, 13
+                CALL    MODE16
+                RET
+emx_wait01      ENDP
+
+;
+; void _wait10 (unsigned port, unsigned mask)
+;
+                TALIGN  4
+emx_wait10      PROC    C PUBLIC, PORT:DWORD, BITS:DWORD
+                MOV     EDX, PORT
+                MOV     ECX, BITS
+                MOV     EAX, 14
+                CALL    MODE16
+                RET
+emx_wait10      ENDP
+
+
+;
+; void _wait0 (unsigned port, unsigned mask)
+;
+                TALIGN  4
+emx_wait0       PROC    C PUBLIC, PORT:DWORD, BITS:DWORD
+                MOV     EDX, PORT
+                MOV     ECX, BITS
+                MOV     EAX, 15
+                CALL    MODE16
+                RET
+emx_wait0       ENDP
+
+;
+; void _wait1 (unsigned port, unsigned mask)
+;
+                TALIGN  4
+emx_wait1       PROC    C PUBLIC, PORT:DWORD, BITS:DWORD
+                MOV     EDX, PORT
+                MOV     ECX, BITS
+                MOV     EAX, 16
+                CALL    MODE16
+                RET
+emx_wait1       ENDP
+
+
+;
+; void _outps8dac (unsigned port, const unsigned char *src, unsigned count)
+;
+                TALIGN  4
+emx_outps8dac   PROC    C PUBLIC USES ESI, PORT:DWORD, SRC:PTR BYTE, COUNT:DWORD
+                MOV     ESI, SRC
+                MOV     EDX, PORT
+                MOV     ECX, COUNT
+                MOV     EAX, 17
+                CALL    MODE16
+                RET
+emx_outps8dac   ENDP
+
+;
+; Call 16-bit code
+;
+; In:   AL      Function number
+;
+                TALIGN  4
+MODE16          PROC
+                PUSH    EBP
+                MOV     EBP, ESP
+                SUB     ESP, 2 * 4
+                MOV     [EBP-2*4], ECX
+                MOV     [EBP-1*4], EDX
+                MOV     ECX, ESP
+                MOV     DX, SS
+                AND     DL, 3
+                OR      DL, 4
+                CMP     CX, 1000H
+                JAE     SHORT MODE16_1
+                XOR     CX, CX
+                MOV     BYTE PTR [ECX], 0       ; Stack probe
+                XCHG    ESP, ECX
+                TALIGN  4
+MODE16_1:       PUSH    SS
+                PUSH    ECX                     ; Save stack pointer
+;
+; Convert ESP to SS:SP
+;
+                MOV     ECX, ESP
+                ROL     ECX, 16
+                SHL     CX, 3
+                OR      CL, DL
+                PUSH    ECX                     ; Push new SS
+                SHR     ECX, 16
+                PUSH    ECX                     ; Push new ESP
+                MOV     ECX, [EBP-2*4]
+                MOV     EDX, [EBP-1*4]
+                LSS     ESP, [ESP]              ; Switch to new stack
+;
+; Call 16-bit code
+;
+                JMP     FAR PTR TEXT16:CALL16
+                TALIGN  4
+MODE16_RET::    MOVZX   ESP, SP                 ; Don't trust...
+                LSS     ESP, [ESP]              ; Get 32-bit stack pointer
+                ADD     ESP, 2*4                ; Remove local variables
+                POP     EBP                     ; Restore EBP
+                RET                             ; Return to 32-bit code
+
+MODE16          ENDP
+
+TEXT32          ENDS
+
+
+TEXT16          SEGMENT
+
+                ASSUME  DS:NOTHING, ES:NOTHING
+
+                TALIGN  4
+CALL16_TAB      DWORD   FAR16 PTR iopl_inp8     ; 0
+                DWORD   FAR16 PTR iopl_outp8    ; 1
+                DWORD   FAR16 PTR iopl_inp16    ; 2
+                DWORD   FAR16 PTR iopl_outp16   ; 3
+                DWORD   FAR16 PTR iopl_inp32    ; 4
+                DWORD   FAR16 PTR iopl_outp32   ; 5
+                DWORD   FAR16 PTR iopl_inps8    ; 6
+                DWORD   FAR16 PTR iopl_outps8   ; 7
+                DWORD   FAR16 PTR iopl_outpt    ; 8
+                DWORD   FAR16 PTR iopl_inps16   ; 9
+                DWORD   FAR16 PTR iopl_outps16  ; 10
+                DWORD   FAR16 PTR iopl_inps32   ; 11
+                DWORD   FAR16 PTR iopl_outps32  ; 12
+                DWORD   FAR16 PTR iopl_wait01   ; 13
+                DWORD   FAR16 PTR iopl_wait10   ; 14
+                DWORD   FAR16 PTR iopl_wait0    ; 15
+                DWORD   FAR16 PTR iopl_wait1    ; 15
+                DWORD   FAR16 PTR iopl_outps8dac; 16
+
+;
+; Entry point from 32-bit code
+;
+                TALIGN  4
+CALL16          PROC    FAR
+                CALL    CALL16_TAB[EAX*4]
+                JMP     FAR32 PTR FLAT:MODE16_RET
+                RET                             ; Avoid warning
+
+CALL16          ENDP
+
+TEXT16          ENDS
+
+IOPL16          SEGMENT DWORD USE16 PUBLIC 'CODE'
+
+;
+; The upper 24 bits of EAX are zero on entry (function number!)
+;
+                TALIGN  4
+iopl_inp8       PROC    FAR16 PUBLIC
+                IN      AL, DX
+                RET
+iopl_inp8       ENDP
+
+                TALIGN  4
+iopl_outp8      PROC    FAR16 PUBLIC
+                MOV     AL, CL
+                OUT     DX, AL
+                RET
+iopl_outp8      ENDP
+
+                TALIGN  4
+iopl_inp16      PROC    FAR16 PUBLIC
+                IN      AX, DX
+                RET
+iopl_inp16      ENDP
+
+                TALIGN  4
+iopl_outp16     PROC    FAR16 PUBLIC
+                MOV     AX, CX
+                OUT     DX, AX
+                RET
+iopl_outp16     ENDP
+
+                TALIGN  4
+iopl_inp32      PROC    FAR16 PUBLIC
+                IN      EAX, DX
+                RET
+iopl_inp32      ENDP
+
+                TALIGN  4
+iopl_outp32     PROC    FAR16 PUBLIC
+                MOV     EAX, ECX
+                OUT     DX, EAX
+                RET
+iopl_outp32     ENDP
+
+                TALIGN  4
+iopl_inps8      PROC    FAR16 PUBLIC
+                REP INS BYTE PTR [EDI], DX
+; Note: EDI and ECX can be incorrect now due to a bug in the 386
+                RET
+iopl_inps8      ENDP
+
+;
+;
+;
+                TALIGN  4
+iopl_outps8     PROC    FAR16 PUBLIC
+                REP OUTS DX, BYTE PTR [ESI]
+                RET
+iopl_outps8     ENDP
+
+
+;
+;
+;
+                TALIGN  4
+iopl_outpt      PROC    FAR16 PUBLIC
+                TALIGN  4
+OUTPT1:         MOV     ECX, [ESI+0]
+                JECXZ   OUTPT9
+                MOV     EDX, [ESI+4]
+                MOV     EAX, [ESI+8]
+                ADD     ESI, 12
+                TEST    EAX, EAX
+                JZ      SHORT OUTPT_B
+                DEC     EAX
+                JZ      SHORT OUTPT_W
+                DEC     EAX
+                JNZ     SHORT OUTPT9
+                REP OUTS DX, DWORD PTR [ESI]
+                JMP     SHORT OUTPT1
+
+                TALIGN  4
+OUTPT_B:        REP OUTS DX, BYTE PTR [ESI]
+                JMP     SHORT OUTPT1
+
+                TALIGN  4
+OUTPT_W:        REP OUTS DX, WORD PTR [ESI]
+                JMP     SHORT OUTPT1
+
+                TALIGN  4
+OUTPT9:         RET
+iopl_outpt      ENDP
+
+;
+;
+;
+                TALIGN  4
+iopl_inps16     PROC    FAR16 PUBLIC
+                REP INS WORD PTR [EDI], DX
+; Note: EDI and ECX can be incorrect now due to a bug in the 386
+                RET
+iopl_inps16     ENDP
+
+;
+;
+;
+                TALIGN  4
+iopl_outps16    PROC    FAR16 PUBLIC
+                REP OUTS DX, WORD PTR [ESI]
+                RET
+iopl_outps16    ENDP
+
+
+;
+;
+;
+                TALIGN  4
+iopl_inps32     PROC    FAR16 PUBLIC
+                REP INS DWORD PTR [EDI], DX
+; Note: EDI and ECX can be incorrect now due to a bug in the 386
+                RET
+iopl_inps32     ENDP
+
+;
+;
+;
+                TALIGN  4
+iopl_outps32    PROC    FAR16 PUBLIC
+                REP OUTS DX, DWORD PTR [ESI]
+                RET
+iopl_outps32    ENDP
+
+
+;
+;
+;
+                TALIGN  4
+iopl_wait01     PROC    FAR16 PUBLIC
+WAIT01_1:       IN      AL, DX
+                TEST    AL, CL
+                JNZ     WAIT01_1
+                TALIGN  4
+WAIT01_2:       IN      AL, DX
+                TEST    AL, CL
+                JZ      WAIT01_2
+                RET
+iopl_wait01     ENDP
+
+;
+;
+;
+                TALIGN  4
+iopl_wait10     PROC    FAR16 PUBLIC
+WAIT10_1:       IN      AL, DX
+                TEST    AL, CL
+                JZ      WAIT10_1
+                TALIGN  4
+WAIT10_2:       IN      AL, DX
+                TEST    AL, CL
+                JNZ     WAIT10_2
+                RET
+iopl_wait10     ENDP
+
+;
+;
+;
+                TALIGN  4
+iopl_wait0      PROC    FAR16 PUBLIC
+WAIT0_1:        IN      AL, DX
+                TEST    AL, CL
+                JNZ     WAIT0_1
+                RET
+iopl_wait0      ENDP
+
+;
+;
+;
+                TALIGN  4
+iopl_wait1      PROC    FAR16 PUBLIC
+WAIT1_1:        IN      AL, DX
+                TEST    AL, CL
+                JZ      WAIT1_1
+                RET
+iopl_wait1      ENDP
+
+;
+;
+;
+                TALIGN  4
+iopl_outps8dac  PROC    FAR16 PUBLIC
+                JCXZ    OUTPS8DAC_9
+                TALIGN  4                       ; Avoid timing surprises
+OUTPS8DAC_1:    MOV     AL, [ESI]
+                INC     ESI
+                NOP
+                OUT     DX, AL
+                LOOP    OUTPS8DAC_1
+OUTPS8DAC_9:    RET
+iopl_outps8dac  ENDP
+
+
+IOPL16          ENDS
+
+                END
Index: trunk/src/emx/src/os2/emxio.def
===================================================================
--- trunk/src/emx/src/os2/emxio.def	(revision 18)
+++ trunk/src/emx/src/os2/emxio.def	(revision 18)
@@ -0,0 +1,73 @@
+;
+; emxio.def
+;
+; Copyright (c) 1992-1998 by Eberhard Mattes
+;
+; This file is part of emx.
+;
+; emx is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; emx is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with emx; see the file COPYING.  If not, write to
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+; As special exception, emxio.dll can be distributed without source code
+; unless it has been changed.  If you modify emxio.dll, this exception
+; no longer applies and you must remove this paragraph from all source
+; files for emxio.dll.
+;
+
+LIBRARY EMXIO INITGLOBAL
+DESCRIPTION 'emxio.dll 0.9d -- Copyright (c) 1992-1998 by Eberhard Mattes'
+DATA
+   SHARED
+SEGMENTS
+  TEXT16 CLASS 'CODE' ALIAS
+  IOPL16 CLASS 'CODE' ALIAS IOPL
+EXPORTS
+  emx_inp8      = _emx_inp8      @1
+  emx_outp8     = _emx_outp8     @2
+  emx_inp16     = _emx_inp16     @3
+  emx_outp16    = _emx_outp16    @4
+  emx_inp32     = _emx_inp32     @5
+  emx_outp32    = _emx_outp32    @6
+  emx_inps8     = _emx_inps8     @7
+  emx_outps8    = _emx_outps8    @8
+  emx_outpt     = _emx_outpt     @9
+  emx_inps16    = _emx_inps16    @10
+  emx_outps16   = _emx_outps16   @11
+  emx_inps32    = _emx_inps32    @12
+  emx_outps32   = _emx_outps32   @13
+  emx_wait01    = _emx_wait01    @14
+  emx_wait10    = _emx_wait10    @15
+  emx_wait0     = _emx_wait0     @16
+  emx_wait1     = _emx_wait1     @17
+  emx_outps8dac = _emx_outps8dac @18
+  emx_revision  = _emx_revision  @128 RESIDENTNAME
+  ___inp8       = iopl_inp8      @192 0
+  ___outp8      = iopl_outp8     @193 0
+  ___inp16      = iopl_inp16     @194 0
+  ___outp16     = iopl_outp16    @195 0
+  ___inp32      = iopl_inp32     @196 0
+  ___outp32     = iopl_outp32    @197 0
+  ___inps8      = iopl_inps8     @198 0
+  ___outpt      = iopl_outpt     @199 0
+  ___outps8     = iopl_outps8    @200 0
+  ___inps16     = iopl_inps16    @201 0
+  ___outps16    = iopl_outps16   @202 0
+  ___inps32     = iopl_inps32    @203 0
+  ___outps32    = iopl_outps32   @204 0
+  ___wait01     = iopl_wait01    @205 0
+  ___wait10     = iopl_wait10    @206 0
+  ___wait0      = iopl_wait0     @207 0
+  ___wait1      = iopl_wait1     @208 0
+  ___outps8dac  = iopl_outps8dac @209 0
Index: trunk/src/emx/src/os2/errors.c
===================================================================
--- trunk/src/emx/src/os2/errors.c	(revision 18)
+++ trunk/src/emx/src/os2/errors.c	(revision 18)
@@ -0,0 +1,250 @@
+/* errors.c -- Translate OS/2 error codes to errno codes
+   Copyright (c) 1994-1998 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#include <os2emx.h>
+#include <sys/errno.h>
+#include "emxdll.h"
+
+/* This table is used for converting OS/2 error codes to errno values.
+   Currently, there are too few errno values.  Therefore, some entries
+   are suspect.
+
+   Mapping ERROR_NOT_READY (21) to EIO is required for opening
+   ptys. */
+
+static const UCHAR errno_table[] =
+{
+  EINVAL,  EINVAL,       ENOENT,  ENOENT,  EMFILE,  /* 0..4 */
+  EACCES,  EBADF,        EIO,     ENOMEM,  EIO,     /* 5..9 */
+  EINVAL,  ENOEXEC,      EINVAL,  EINVAL,  EINVAL,  /* 10..14 */
+  ENOENT,  EBUSY,        EXDEV,   ENOENT,  EROFS,   /* 15..19 */
+  EIO,     EIO,          EIO,     EIO,     EIO,     /* 20..24 */
+  EIO,     EIO,          EIO,     ENOSPC,  EIO,     /* 25..29 */
+  EIO,     EIO,          EACCES,  EACCES,  EIO,     /* 30..34 */
+  EIO,     EIO,          EIO,     EIO,     ENOSPC,  /* 35..39 */
+  EIO,     EIO,          EIO,     EIO,     EIO,     /* 40..44 */
+  EIO,     EIO,          EIO,     EIO,     EIO,     /* 45..49 */
+  EIO,     EIO,          EIO,     EIO,     EBUSY,   /* 50..54 */
+  EIO,     EIO,          EIO,     EIO,     EIO,     /* 55..59 */
+  EIO,     ENOSPC,       ENOSPC,  EIO,     EIO,     /* 60..64 */
+  EACCES,  EIO,          EIO,     EIO,     EIO,     /* 65..69 */
+  EIO,     EIO,          EIO,     EROFS,   EIO,     /* 70..74 */
+  EIO,     EIO,          EIO,     EIO,     EIO,     /* 75..79 */
+  EEXIST,  EIO,          ENOENT,  EIO,     EIO,     /* 80..84 */
+  EIO,     EIO,          EINVAL,  EIO,     EAGAIN,  /* 85..89 */
+  EIO,     EIO,          EIO,     EIO,     EIO,     /* 90..94 */
+  EINTR,   EIO,          EIO,     EIO,     EACCES,  /* 95..99 */
+  ENOMEM,  EINVAL,       EINVAL,  ENOMEM,  EINVAL,  /* 100..104 */
+  EINVAL,  ENOMEM,       EIO,     EACCES,  EPIPE,   /* 105..109 */
+  ENOENT,  E2BIG,        ENOSPC,  ENOMEM,  EBADF,   /* 110..114 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 115..119 */
+  EINVAL,  EINVAL,       EINVAL,  ENOENT,  EINVAL,  /* 120..124 */
+  ENOENT,  ENOENT,       ENOENT,  ECHILD,  ECHILD,  /* 125..129 */
+  EACCES,  EINVAL,       ESPIPE,  EINVAL,  EINVAL,  /* 130..134 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 135..139 */
+  EINVAL,  EINVAL,       EBUSY,   EINVAL,  EINVAL,  /* 140..144 */
+  EINVAL,  EINVAL,       EINVAL,  EBUSY,   EINVAL,  /* 145..149 */
+  EINVAL,  EINVAL,       ENOMEM,  EINVAL,  EINVAL,  /* 150..154 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 155..159 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EAGAIN,  /* 160..164 */
+  EINVAL,  EINVAL,       EACCES,  EINVAL,  EINVAL,  /* 165..169 */
+  EBUSY,   EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 170..174 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 175..179 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  ECHILD,  /* 180..184 */
+  EINVAL,  EINVAL,       ENOENT,  EINVAL,  EINVAL,  /* 185..189 */
+  ENOEXEC, ENOEXEC,      ENOEXEC, ENOEXEC, ENOEXEC, /* 190..194 */
+  ENOEXEC, ENOEXEC,      ENOEXEC, ENOEXEC, ENOEXEC, /* 195..199 */
+  ENOEXEC, ENOEXEC,      ENOEXEC, ENOENT,  EINVAL,  /* 200..204 */
+  EINVAL,  ENAMETOOLONG, EINVAL,  EINVAL,  EINVAL,  /* 205..209 */
+  EINVAL,  EINVAL,       EACCES,  ENOEXEC, ENOEXEC, /* 210..214 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 215..219 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 220..224 */
+  EINVAL,  EINVAL,       EINVAL,  ECHILD,  EINVAL,  /* 225..229 */
+  EINVAL,  EBUSY,        EAGAIN,  ENOTCONN, EINVAL, /* 230..234 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 235..239 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 240..244 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 245..249 */
+  EACCES,  EACCES,       EINVAL,  ENOENT,  EINVAL,  /* 250..254 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 255..259 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 260..264 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 265..269 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 270..274 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 275..279 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EEXIST,  /* 280..284 */
+  EEXIST,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 285..289 */
+  ENOMEM,  EMFILE,       EINVAL,  EINVAL,  EINVAL,  /* 290..294 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EINVAL,  /* 295..299 */
+  EINVAL,  EBUSY,        EINVAL,  ESRCH,   EINVAL,  /* 300..304 */
+  ESRCH,   EINVAL,       EINVAL,  EINVAL,  ESRCH,   /* 305..309 */
+  EINVAL,  ENOMEM,       EINVAL,  EINVAL,  EINVAL,  /* 310..314 */
+  EINVAL,  E2BIG,        ENOENT,  EIO,     EIO,     /* 315..319 */
+  EINVAL,  EINVAL,       EINVAL,  EINVAL,  EAGAIN,  /* 320..324 */
+  EINVAL,  EINVAL,       EINVAL,  EIO,     ENOENT,  /* 325..329 */
+  EACCES,  EACCES,       EACCES,  ENOENT,  ENOMEM   /* 330..334 */
+};
+
+
+/* This table translates errno values for `interface 0'.  Changed
+   entries are marked (*). */
+
+static const UCHAR errno_interface_0[] =
+{
+
+  0,                            /* 0:  0            */
+  EACCES,                       /* 1:  EPERM (*)    */
+  ENOENT,                       /* 2:  ENOENT       */
+  ESRCH,                        /* 3:  ESRCH        */
+  EINTR,                        /* 4:  EINTR        */
+  EIO,                          /* 5:  EIO          */
+  EINVAL,                       /* 6:  ENXIO (*)    */
+  E2BIG,                        /* 7:  E2BIG        */
+  ENOEXEC,                      /* 8:  ENOEXEC      */
+  EBADF,                        /* 9:  EBADF        */
+  ECHILD,                       /* 10: ECHILD       */
+  EAGAIN,                       /* 11: EAGAIN       */
+  ENOMEM,                       /* 12: ENOMEM       */
+  EACCES,                       /* 13: EACCES       */
+  EINVAL,                       /* 14: EFAULT (*)   */
+  EINVAL,                       /* 15: ENOLCK (*)   */
+  EACCES,                       /* 16: EBUSY (*)    */
+  EEXIST,                       /* 17: EEXIST       */
+  EXDEV,                        /* 18: EXDEV        */
+  EINVAL,                       /* 19: ENODEV (*)   */
+  EACCES,                       /* 20: ENOTDIR (*)  */
+  EACCES,                       /* 21: EISDIR (*)   */
+  EINVAL,                       /* 22: EINVAL       */
+  EMFILE,                       /* 23: ENFILE (*)   */
+  EMFILE,                       /* 24: EMFILE       */
+  EINVAL,                       /* 25: ENOTTY (*)   */
+  EINVAL,                       /* 26: EDEADLK (*)  */
+  EINVAL,                       /* 27: EFBIG (*)    */
+  ENOSPC,                       /* 28: ENOSPC       */
+  EINVAL,                       /* 29: ESPIPE (*)   */
+  EACCES,                       /* 30: EROFS (*)    */
+  EINVAL,                       /* 31: EMLINK (*)   */
+  EPIPE,                        /* 32: EPIPE        */
+  EINVAL,                       /* 33: EDOM (*)     */
+  ERANGE,                       /* 34: ERANGE       */
+  EACCES,                       /* 35: ENOTEMPTY (*)    */
+  EINVAL,                       /* 36: EINPROGRESS (*)  */
+  ENOSYS,                       /* 37: ENOSYS           */
+  EINVAL                        /* 38: ENAMETOOLONG (*) */
+};
+
+
+/* This table translates errno values for `interface 1' (up to and
+   including 0.8h).  Changed entries are marked (*). */
+
+static const UCHAR errno_interface_1[] =
+{
+
+  0,                            /* 0:  0            */
+  EPERM,                        /* 1:  EPERM        */
+  ENOENT,                       /* 2:  ENOENT       */
+  ESRCH,                        /* 3:  ESRCH        */
+  EINTR,                        /* 4:  EINTR        */
+  EIO,                          /* 5:  EIO          */
+  EINVAL,                       /* 6:  ENXIO (*)    */
+  E2BIG,                        /* 7:  E2BIG        */
+  ENOEXEC,                      /* 8:  ENOEXEC      */
+  EBADF,                        /* 9:  EBADF        */
+  ECHILD,                       /* 10: ECHILD       */
+  EAGAIN,                       /* 11: EAGAIN       */
+  ENOMEM,                       /* 12: ENOMEM       */
+  EACCES,                       /* 13: EACCES       */
+  EINVAL,                       /* 14: EFAULT (*)   */
+  EINVAL,                       /* 15: ENOLCK (*)   */
+  EACCES,                       /* 16: EBUSY (*)    */
+  EEXIST,                       /* 17: EEXIST       */
+  EXDEV,                        /* 18: EXDEV        */
+  EINVAL,                       /* 19: ENODEV (*)   */
+  ENOTDIR,                      /* 20: ENOTDIR      */
+  EISDIR,                       /* 21: EISDIR       */
+  EINVAL,                       /* 22: EINVAL       */
+  EMFILE,                       /* 23: ENFILE (*)   */
+  EMFILE,                       /* 24: EMFILE       */
+  EINVAL,                       /* 25: ENOTTY (*)   */
+  EINVAL,                       /* 26: EDEADLK (*)  */
+  EINVAL,                       /* 27: EFBIG (*)    */
+  ENOSPC,                       /* 28: ENOSPC       */
+  ESPIPE,                       /* 29: ESPIPE       */
+  EROFS,                        /* 30: EROFS        */
+  EINVAL,                       /* 31: EMLINK (*)   */
+  EPIPE,                        /* 32: EPIPE        */
+  EDOM,                         /* 33: EDOM         */
+  ERANGE,                       /* 34: ERANGE       */
+  EACCES,                       /* 35: ENOTEMPTY (*)   */
+  EINVAL,                       /* 36: EINPROGRESS (*) */
+  ENOSYS,                       /* 37: ENOSYS       */
+  ENAMETOOLONG                  /* 38: ENAMETOOLONG */
+};
+
+
+/* Set last_sys_errno according to RC and return an errno value. */
+
+ULONG set_error (ULONG rc)
+{
+  thread_data *td;
+
+  td = get_thread ();
+  if (td != NULL)
+    td->last_sys_errno = rc;
+
+  if (rc >= sizeof (errno_table))
+    return EINVAL;
+
+  switch (interface)
+    {
+    case 0:
+      return errno_interface_0[errno_table[rc]];
+    case 1:
+      return errno_interface_1[errno_table[rc]];
+    default:
+      return errno_table[rc];
+    }
+}
+
+
+/* Translate an errno value according to the interface.  This function
+   should be called when returning an errno value marked (*) in the
+   errno_interface_0 table. */
+
+int xlate_errno (int e)
+{
+  switch (interface)
+    {
+    case 0:
+      if ((unsigned)e >= sizeof (errno_interface_0))
+        return EINVAL;
+      return errno_interface_0[e];
+    case 1:
+      if ((unsigned)e >= sizeof (errno_interface_1))
+        return EINVAL;
+      return errno_interface_1[e];
+    default:
+      return e;
+    }
+}
Index: trunk/src/emx/src/os2/fileio.c
===================================================================
--- trunk/src/emx/src/os2/fileio.c	(revision 18)
+++ trunk/src/emx/src/os2/fileio.c	(revision 18)
@@ -0,0 +1,2327 @@
+/* fileio.c -- Managing files, pipes, and such
+   Copyright (c) 1994-1998 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSDEVIOCTL
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/nls.h>
+#include <sys/termio.h>
+#include <sys/errno.h>
+#include "emxdll.h"
+#include "files.h"
+#include "tcpip.h"
+#include "clib.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+/* Evaluate to true if P points to the path name of a pty.
+   xf86sup.sys currently supports 32 ptys, /dev/ptyp0 through
+   /dev/ptyqf. */
+
+#define IS_PTY_NAME(p)                          \
+    (strncmp ((p), "/dev/pty", 8) == 0          \
+     && ((p)[8] == 'p' || (p)[8] == 'q')        \
+     && (((p)[9] >= '0' && (p)[9] <= '9')       \
+         || ((p)[9] >= 'a' && (p)[9] <= 'f'))   \
+     && (p)[10] == 0)
+
+/* The first implementation of umask() was quite broken; to avoid
+   breaking old programs using that broken version of umask(), we keep
+   (and ignore) a separate umask value for __umask1(). */
+
+ULONG umask_bits1;
+
+/* This is the current umask.  Only the 0200 bit is used. */
+
+ULONG umask_bits;
+
+/* Number of file handles. */
+
+ULONG handle_count;
+
+/* Array of handle flags. */
+
+ULONG *handle_flags;
+
+/* This array maps file handles to file descriptions (index into
+   files[]). */
+
+ULONG *handle_file;
+
+/* This array contains file descriptions.  Multiple file handles may
+   point to one file descriptions if dup() is used.  Unfortunately, we
+   cannot (efficiently, or at all, for devices) find out whether two
+   inherited file handles refer to the same file.  Therefore, every
+   inherited file handle has its own file description. */
+
+my_file *files;
+
+/* This macro is used for accessing FDATE or FTIME values as
+   USHORT. */
+
+#define XUSHORT(x) (*(USHORT *)&(x))
+
+/* We fake inode numbers by assigning a `unique' inode number every
+   time an inode number is fetched.  When querying the inode number of
+   a file twice, you'll get two different numbers.  This variable
+   holds the inode number to be used for the next file.  After using
+   the value, it will be incremented.  When wrapping around to 0, skip
+   to 1 (0 seems to be a reserved value). */
+
+long ino_number;
+
+/* `handle_flags' is protected by this Mutex semaphore. */
+
+HMTX files_access;
+
+
+/* Prototypes. */
+
+static ULONG new_handle (ULONG handle);
+
+
+/* Initialize the data structures related to file handles, and other
+   variables. */
+
+void init_fileio (void)
+{
+  LONG req_count;
+  ULONG rc, i;
+
+  create_mutex_sem (&files_access);
+
+  /* Retrieve the maximum number of file handles. */
+
+  req_count = 0;
+  rc = DosSetRelMaxFH (&req_count, &handle_count);
+  if (rc != 0)
+    error (rc, "DosSetRelMaxFH");
+
+  /* Allocate an array which holds a word of flag bits for each
+     handle, including inactive handles.  Allocate an array of file
+     descriptions, and an array which maps file handles to file
+     descriptions. */
+
+  handle_flags = checked_private_alloc (handle_count * sizeof (*handle_flags));
+  handle_file = checked_private_alloc (handle_count * sizeof (*handle_file));
+  files = checked_private_alloc (handle_count * sizeof (*files));
+
+  /* Initialize the file descriptions. */
+
+  for (i = 0; i < handle_count; ++i)
+    {
+      files[i].flags = 0;
+      files[i].ref_count = 0;
+      files[i].tio_buf = NULL;
+      SET_INVALID_FILE (i);
+    }
+
+  /* Initialize the flag bits and the file descripions for all
+     handles.  Unfortunately, we cannot find out (efficiently, or at
+     all, for devices) whether two inherited file handles refer to the
+     same file.  Therefore, every inherited file handle has its own
+     file description. */
+
+  for (i = 0; i < handle_count; ++i)
+    new_handle (i);
+
+  /* Initialize other variables. */
+
+  umask_bits = 0022;
+  umask_bits1 = 0644;
+  ino_number = 0x100000;
+}
+
+
+/* Set HANDLE's OPEN_FLAGS_NOINHERIT iff FD_FLAGS contains FD_CLOEXEC.
+   Return zero or the OS/2 error code. */
+
+static ULONG set_no_inherit (ULONG handle, ULONG fd_flags)
+{
+  ULONG rc, state, new_state;
+
+  rc = DosQueryFHState (handle, &state);
+  if (rc != 0) return rc;
+  if (fd_flags & FD_CLOEXEC)
+    new_state = state | OPEN_FLAGS_NOINHERIT;
+  else
+    new_state = state & ~OPEN_FLAGS_NOINHERIT;
+  if (new_state != state)
+    rc = DosSetFHState (handle, new_state & 0x7f88);
+  return rc;
+}
+
+
+/* Make all user file handles inheritable and save the original
+   FD_CLOEXEC state in the HF_NOINHERIT bit. */
+
+void fileio_fork_parent_init (void)
+{
+  ULONG i, state;
+
+  for (i = 0; i < handle_count; ++i)
+    if ((handle_flags[i] & (HF_OPEN|HF_SOCKET)) == HF_OPEN
+        && DosQueryFHState (i, &state) == 0
+        && (state & OPEN_FLAGS_NOINHERIT))
+      {
+        handle_flags[i] |= HF_NOINHERIT;
+        set_no_inherit (i, 0);
+      }
+    else
+      handle_flags[i] &= ~HF_NOINHERIT;
+}
+
+
+/* Undo fileio_fork_parent_init(), that is, restore the file handle
+   state from the HF_NOINHERIT bit. */
+
+void fileio_fork_parent_restore (void)
+{
+  ULONG i;
+
+  for (i = 0; i < handle_count; ++i)
+    if ((handle_flags[i] & (HF_OPEN|HF_SOCKET|HF_NOINHERIT))
+        == (HF_OPEN|HF_NOINHERIT))
+      set_no_inherit (i, FD_CLOEXEC);
+}
+
+
+/* Fill-in file-related fields of structure for the child process. */
+
+void fileio_fork_parent_fillin (struct fork_data_done *p)
+{
+  ULONG i, f;
+
+  if (p->size + handle_count * sizeof (ULONG) <= FORK_OBJ_SIZE)
+    p->handle_count = handle_count;
+  else
+    p->handle_count = (FORK_OBJ_SIZE - p->size) / sizeof (ULONG);
+  p->fd_flags_array = (ULONG *)((char *)p + p->size);
+  p->size += p->handle_count * sizeof (ULONG);
+
+  for (i = 0; i < p->handle_count; ++i)
+    {
+      f = 0;
+      if (IS_SOCKET (i))
+        {
+          if (IS_VALID_FILE (i))
+            f = (ULONG)GET_FILE (i)->x.socket.fd_flags;
+        }
+      else if ((handle_flags[i] & (HF_OPEN|HF_NOINHERIT))
+               == (HF_OPEN|HF_NOINHERIT))
+        f = FD_CLOEXEC;
+      p->fd_flags_array[i] = f;
+    }
+}
+
+
+/* Initialize file handles in a forked process. */
+
+void fileio_fork_child (struct fork_data_done *p)
+{
+  ULONG i, n;
+
+  n = (p->handle_count < handle_count ? p->handle_count : handle_count);
+  for (i = 0; i < n; ++i)
+    if ((p->fd_flags_array[i] & FD_CLOEXEC) && IS_VALID_FILE (i))
+      {
+        if (IS_SOCKET (i))
+          GET_FILE (i)->x.socket.fd_flags = (int)p->fd_flags_array[i];
+        else
+          set_no_inherit (i, FD_CLOEXEC);
+      }
+}
+
+
+/* Call this function instead of DosQueryPathInfo, to be able to work
+   around OS/2 bugs.
+
+   If DEBUG_QPINFO2 is set (-!64), DosQueryPathInfo will be called
+   twice: Sometimes, DosQueryPathInfo reports directories on CDROMs as
+   files.  Calling DosQueryPathInfo seems to help.  We don't call
+   DosQueryPathInfo twice if ulInfoLevel is not FIL_STANDARD, as
+   pInfoBuffer is an input/output parameter if ulInfoLevel is
+   FIL_QUERYEASFROMLIST.  (Currently, ulInfoLevel is always
+   FIL_STANDARD.) */
+
+ULONG query_path_info (PCSZ pszPathName, ULONG ulInfoLevel,
+                       PVOID pInfoBuffer, ULONG ulInfoLength)
+{
+  ULONG rc;
+
+  rc = DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuffer, ulInfoLength);
+  if (ulInfoLevel == FIL_STANDARD && (debug_flags & DEBUG_QPINFO2))
+    rc = DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuffer,
+                           ulInfoLength);
+  return rc;
+}
+
+
+/* Compare the first element of the path PATH to DIR.  DIR must not
+   contain upper case letters. */
+
+static int dir_check (const char *path, const char *dir)
+{
+  while (*path != 0 && *dir != 0 && tolower (*path) == *dir)
+    ++path, ++dir;
+  return *dir == 0 && (*path == '/' || *path == '\\');
+}
+
+
+/* Avoid OS/2 internal processing error: If the path name S starts
+   with \pipe\ or /pipe/, return true.  */
+
+int check_npipe (const char *s)
+{
+  return (*s == '/' || *s == '\\') && dir_check (s + 1, "pipe");
+}
+
+
+/* Truncate the path name SRC, placing the result into the buffer
+   pointed to by DST.  At most 512 characters (including the
+   terminating null character) are copied to DST. */
+
+void truncate_name (char *dst, const char *src)
+{
+  int dst_count;
+  ULONG trunc_bit;
+
+  dst_count = 512 - 1;          /* Buffer size sans null character */
+
+  /* Prepend drive letter if the -r option is used, the path name
+     starts with a slash but is not a UNC path, and the first path
+     element is not `dev' or `pipe'.  */
+
+  trunc_bit = TRUNC_ALL;
+  if (src[0] == '/' || src[0] == '\\')
+    {
+      if (src[1] == '/' || src[1] == '\\')
+        {
+          /* It's a UNC path: don't prepend drive letter; check
+             `-t/'. */
+          trunc_bit = TRUNC_UNC;
+        }
+      else if (dir_check (src + 1, "dev") || dir_check (src + 1, "pipe"))
+        {
+          /* It's a device or pipe name.  Do not prepend drive letter;
+             do not truncate. */
+          trunc_bit = 0;
+        }
+      else if (opt_drive != 0)
+        {
+          /* Prepend drive letter; check `-t' for that drive
+             letter. */
+          *dst++ = opt_drive;
+          *dst++ = ':';
+          dst_count -= 2;
+          trunc_bit = TRUNC_DRV (opt_drive);
+        }
+    }
+  else if (((src[0] >= 'A' && src[0] <= 'Z')
+            || (src[0] >= 'a' && src[0] <= 'z'))
+           && src[1] == ':')
+    trunc_bit = TRUNC_DRV (src[0]);
+
+  if (trunc_bit == TRUNC_ALL && opt_trunc != 0 && opt_trunc != TRUNC_ALL)
+    {
+      ULONG drv, map;
+
+      DosQueryCurrentDisk (&drv, &map);
+      trunc_bit = TRUNC_DRV (drv);
+    }
+
+  if (opt_trunc & trunc_bit)
+    {
+      unsigned char rest, dot;
+
+      /* The -t option applies; truncate all elements of the pathname
+         to 8.3 format. */
+
+      rest = 8; dot = FALSE;
+      while (*src != 0 && dst_count != 0)
+        {
+          if (_nls_is_dbcs_lead ((unsigned char)*src) && src[1] != 0)
+            {
+              /* We encountered a valid DBCS character (note that a
+                 DBCS lead byte followed by zero is invalid and will
+                 be handled as an ordinary character).  Avoid
+                 truncating between the two bytes. */
+
+              if (rest >= 2 && dst_count >= 2)
+                {
+                  *dst++ = *src++;
+                  *dst++ = *src;
+                  dst_count -= 2; rest -= 2;
+                }
+              else
+                ++src;
+            }
+          else if (*src == ':' || *src == '/' || *src == '\\')
+            {
+              *dst++ = *src;
+              --dst_count;
+              rest = 8; dot = FALSE;
+            }
+          else if (*src == '.')
+            {
+              if (rest == 8)
+                {
+                  /* An element starts with a dot -- process it like
+                     an ordinary character.  This makes ".." work.
+                     ".emacs", for instance, is left alone. */
+
+                  for (;;)
+                    {
+                      *dst++ = *src;
+                      --dst_count; --rest;
+                      if (src[1] != '.' || dst_count == 0)
+                        break;
+                      ++src;
+                    }
+                }
+              else if (dot)
+                {
+                  /* If the element has two or more dots, truncate at
+                     the second dot.  This does not apply to ".."
+                     which is handled above. */
+
+                  rest = 0;
+                }
+              else
+                {
+                  /* Start of a suffix. */
+
+                  rest = 3; dot = TRUE;
+                  *dst++ = *src;
+                  --dst_count;
+                }
+            }
+          else if (rest != 0)
+            {
+              /* Copy an ordinary character unless the truncation
+                 limit (8 or 3 characters) has been reached. */
+
+              *dst++ = *src;
+              --dst_count; --rest;
+            }
+          ++src;
+        }
+    }
+  else
+    {
+      /* The -t option is not used, don't truncate the file name to
+         8.3 format (however, truncate it to avoid overflowing the
+         destination buffer. */
+
+      while (*src != 0 && dst_count != 0)
+        {
+          *dst++ = *src++;
+          --dst_count;
+        }
+    }
+
+  /* Add the terminating null character. */
+
+  *dst = 0;
+}
+
+
+/* Update the flag bits of file handle HANDLE, the new value is FLAGS.
+   Don't crash if HANDLE is out of range. */
+
+void set_handle_flags (ULONG handle, ULONG flags)
+{
+  if (handle < handle_count)
+    {
+      handle_flags[handle] = flags;
+      if (IS_VALID_FILE (handle))
+        GET_FILE (handle)->flags = flags;
+    }
+}
+
+
+/* Allocate a file description for HANDLE. */
+
+void alloc_file_description (ULONG handle)
+{
+  ULONG i;
+
+  LOCK_FILES;
+
+  /* File 0 is reserved for the CON device. */
+
+  for (i = 1; i < handle_count; ++i)
+    if (files[i].ref_count == 0)
+      {
+        handle_file[handle] = i;
+        files[i].ref_count = 1;
+        UNLOCK_FILES;
+        return;
+      }
+  SET_INVALID_FILE (handle);
+  UNLOCK_FILES;
+}
+
+
+/* Relocate the OS/2 file handle HANDLE if there is already a socket
+   with that handle; then, if CALL_NEW_HANDLE is true, apply
+   new_handle().  Update the object pointed to by TARGET with the new
+   handle.  Return errno. */
+
+static int reloc_handle (HFILE handle, HFILE *target, int call_new_handle)
+{
+  ULONG i, rc, htype, hflags;
+
+  *target = handle;
+  if (!IS_SOCKET (handle))
+    return (call_new_handle ? new_handle (handle) : 0);
+
+  LOCK_FILES;
+  for (i = 0; i < handle_count; ++i)
+    if (!(handle_flags[i] & HF_OPEN)
+        && DosQueryHType (i, &htype, &hflags) == ERROR_INVALID_HANDLE)
+      break;
+  if (i >= handle_count)
+    {
+      UNLOCK_FILES;
+      return EMFILE;
+    }
+  *target = i;
+  xf86sup_maybe_enadup (handle, TRUE);
+  rc = DosDupHandle (handle, &i);
+  xf86sup_maybe_enadup (handle, FALSE);
+  if (rc != 0)
+    {
+      UNLOCK_FILES;
+      return set_error (rc);
+    }
+  if (i != *target)             /* Can this happen? */
+    {
+      UNLOCK_FILES;
+      DosClose (i);
+      return EMFILE;
+    }
+  rc = (call_new_handle ? new_handle (i) : 0);
+  UNLOCK_FILES;
+  if (rc != 0)
+    {
+      DosClose (i);
+      return rc;
+    }
+  DosClose (handle);
+  return 0;
+}
+
+
+/* Update our tables when closing a file handle. */
+
+void close_handle (ULONG handle)
+{
+  if (handle >= handle_count) return;
+  if (IS_VALID_FILE (handle))
+    {
+      my_file *d;
+
+      LOCK_FILES;
+      d = GET_FILE (handle);
+      SET_INVALID_FILE (handle);
+      if (d->ref_count != 0)
+        {
+          --d->ref_count;
+          if (d->ref_count == 0)
+            {
+              /* File description no longer referenced. */
+              if (d->tio_buf != NULL)
+                {
+                  private_free (d->tio_buf);
+                  d->tio_buf = NULL;
+                }
+            }
+        }
+      UNLOCK_FILES;
+    }
+  handle_flags[handle] = 0;
+}
+
+
+/* Find out the type of the new file handle HANDLE, update the flag
+   bits in `handle_flags', and add a file description.  Return the
+   OS/2 error code. */
+
+static ULONG new_handle (ULONG handle)
+{
+  ULONG rc, htype, hflags, pstate, flags;
+
+  if (handle >= handle_count) return ERROR_INVALID_HANDLE;
+  close_handle (handle);
+  rc = DosQueryHType (handle, &htype, &hflags);
+  if (rc != 0)
+    return rc;
+
+  switch (htype & 0xff)       /* Class */
+    {
+    case HANDTYPE_DEVICE:
+      if (hflags & 3)         /* KBD or VIO */
+        {
+          /* All handles for the CON device (KBD and VIO) share the
+             same file description: file table entry 0.  Do not use
+             alloc_file_description(). */
+
+          ++files[0].ref_count;
+          handle_file[handle] = 0;
+          flags = HF_OPEN | HF_DEV | HF_CON;
+          init_termio (handle);
+        }
+      else
+        {
+          alloc_file_description (handle);
+          if (hflags & 4)
+            flags = HF_OPEN | HF_DEV | HF_NUL;
+          else if (hflags & 8)
+            flags = HF_OPEN | HF_DEV | HF_CLK;
+          else if (!IS_VALID_FILE (handle))
+            flags = HF_OPEN | HF_DEV;
+          else if (!(debug_flags & DEBUG_NOXF86SUP)
+                   && xf86sup_query (handle, &flags) == 0)
+            flags |= HF_OPEN | HF_DEV;
+          else if (query_async (handle) == 0
+                   && translate_async (handle) == 0)
+            flags = HF_OPEN | HF_DEV | HF_ASYNC;
+          else
+            flags = HF_OPEN | HF_DEV;
+        }
+      break;
+
+    case HANDTYPE_PIPE:
+      alloc_file_description (handle);
+      rc = DosQueryNPHState (handle, &pstate);
+      if (rc == ERROR_PIPE_NOT_CONNECTED)
+        flags = HF_OPEN | HF_NPIPE;
+      else if (rc != 0)       /* Unnamed pipe */
+        flags = HF_OPEN | HF_UPIPE;
+      else if (pstate & NP_NOWAIT)
+        flags = HF_OPEN | HF_NPIPE | HF_NDELAY;
+      else
+        flags = HF_OPEN | HF_NPIPE;
+      break;
+
+    case HANDTYPE_FILE:
+      alloc_file_description (handle);
+      flags = HF_OPEN | HF_FILE;
+      break;
+
+    default:
+      /* Future extension. */
+      alloc_file_description (handle);
+      flags = HF_OPEN;
+      break;
+    }
+  set_handle_flags (handle, flags);
+  return 0;
+}
+
+
+/* Return the number of bytes available for reading from pipe HANDLE.
+   Return -1 and set *ERRNOP on error.  Set *ERRNOP to zero on
+   success. */
+
+static int npipe_avail (ULONG handle, int *errnop)
+{
+  ULONG rc, state, nread;
+  AVAILDATA avail;
+  char buffer;
+
+  rc = DosPeekNPipe (handle, &buffer, 0, &nread, &avail, &state);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  *errnop = 0;
+  return avail.cbpipe;
+}
+
+
+/* Find the COUNT lowest numbered, unused file handles and store them
+   to the array pointed to by DST, in increasing order.  Return the
+   number of unused file handles found. */
+
+int find_unused_handles (ULONG *dst, int count)
+{
+  ULONG i, htype, hflags;
+  int n;
+
+  n = 0;
+  for (i = 0; i < handle_count && n < count; ++i)
+    if (DosQueryHType (i, &htype, &hflags) == ERROR_INVALID_HANDLE)
+      dst[n++] = i;
+  return n;
+}
+
+
+/* This function implements the __open() system call of emx 0.8e and
+   later.  Return the file handle, or -1 on error. */
+
+int sys_open (const char *path, unsigned flags, unsigned long size,
+              int *errnop)
+{
+  char fname[512];
+  ULONG rc;
+  ULONG open_mode, attr, action, open_flag;
+  HFILE handle, nh;
+  int fail_errno, e;
+  char is_pty;
+
+  /* Interpret "/dev/null" and "/dev/tty" as the name of the null
+     device "NUL" or of the console "CON", respectively.  Copy the
+     path name to `fname', with modifications according to the -r and
+     -t options. */
+
+  is_pty = FALSE;
+  if (strcmp (path, "/dev/null") == 0)
+    strcpy (fname, "nul");
+  else if (strcmp (path, "/dev/tty") == 0)
+    strcpy (fname, "con");
+  else if (!(debug_flags & DEBUG_NOXF86SUP) && IS_PTY_NAME (path))
+    {
+      is_pty = TRUE;
+      strcpy (fname, path);
+    }
+  else
+    truncate_name (fname, path);
+
+  /* Extract the access mode and sharing mode bits. */
+
+  open_mode = flags & 0x77;
+
+  /* Handle O_NOINHERIT and O_SYNC. */
+
+  if (flags & _SO_NOINHERIT)
+    open_mode |= OPEN_FLAGS_NOINHERIT;
+  if (flags & _SO_SYNC)
+    open_mode |= OPEN_FLAGS_WRITE_THROUGH;
+
+  /* Set OPEN_FLAGS_FAIL_ON_ERROR for /dev/ptyXX as otherwise opening
+     such a device would generate an error popup if the pty is already
+     in use.  With OPEN_FLAGS_FAIL_ON_ERROR, we'll get return code
+     ERROR_NOT_READY, which will be translated to EIO. */
+
+  if (is_pty)
+    open_mode |= OPEN_FLAGS_FAIL_ON_ERROR;
+
+  /* Extract the file attribute bits. */
+
+  attr = (flags >> 8) & 0xff;
+  if (umask_bits & 0200)
+    attr |= 1;
+
+  /* Translate ERROR_OPEN_FAILED to ENOENT unless O_EXCL is set (see
+     below). */
+
+  fail_errno = ENOENT;
+
+  /* Compute `open_flag' depending on `flags'.  Note that _SO_CREAT is
+     set for O_CREAT. */
+
+  if (flags & _SO_CREAT)
+    {
+      if (flags & _SO_EXCL)
+        {
+          open_flag = OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
+          fail_errno = EEXIST;
+        }
+      else if (flags & _SO_TRUNC)
+        open_flag = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
+      else
+        open_flag = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
+    }
+  else if (flags & _SO_TRUNC)
+    open_flag = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
+  else
+    open_flag = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
+
+  /* Ignore SIZE unless _SO_SIZE is set. */
+
+  if (!(flags & _SO_SIZE))
+    size = 0;
+
+  /* Try to open the file and handle errors. */
+
+  rc = DosOpen (fname, &handle, &action, size, attr, open_flag, open_mode,
+                NULL);
+  if (rc == ERROR_OPEN_FAILED)
+    {
+      set_error (rc);
+      *errnop = fail_errno;
+      return -1;
+    }
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* Relocate the handle and update the flag bits and the file
+     description for the new file handle. */
+
+  e = reloc_handle (handle, &nh, TRUE);
+  if (e != 0)
+    {
+      DosClose (handle);
+      *errnop = e;
+      return -1;
+    }
+
+  /* Return the handle and tell the caller not to modify `errno'. */
+
+  *errnop = 0;
+  return nh;
+}
+
+
+/* This function emulates DOS function 0x3c.  That function may still
+   be used by ancient programs. */
+
+int old_creat (const char *path, ULONG attr, int *errnop)
+{
+  char fname[512];
+  ULONG rc, action;
+  HFILE hf, nh;
+  int e;
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Extract the file attribute bits. */
+
+  attr &= 0x27;
+  if (umask_bits & S_IWRITE)
+    attr |= 1;                  /* Set read-only attribute */
+
+  /* Try to open the file and handle errors. */
+
+  rc = DosOpen (fname, &hf, &action, 0, attr,
+                OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
+                OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
+                NULL);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* Relocate the handle and update the flag bits and the file
+     description for the new file handle. */
+
+  e = reloc_handle (hf, &nh, TRUE);
+  if (e != 0)
+    {
+      DosClose (hf);
+      *errnop = e;
+      return -1;
+    }
+
+  /* Return the handle and tell the caller not to modify `errno'. */
+
+  *errnop = 0;
+  return nh;
+}
+
+
+/* This function emulates DOS function 0x3d.  That function may still
+   be used by ancient programs. */
+
+int old_open (const char *path, ULONG mode, int *errnop)
+{
+  char fname[512];
+  ULONG rc, action, new_mode;
+  HFILE hf, nh;
+  int e;
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Extract the access mode and the sharing mode. */
+
+  if (mode & 0x70)              /* Sharing mode */
+    new_mode = mode & 0x70;
+  else
+    new_mode = 0x40;            /* Compatibility -> DENYNONE */
+  new_mode |= mode & 0x83;      /* Inheritance, access code */
+
+  /* Try to open the file and handle errors. */
+
+  rc = DosOpen (fname, &hf, &action, 0, FILE_NORMAL,
+                OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+                new_mode, NULL);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* Relocate the handle and update the flag bits and the file
+     description for the new file handle. */
+
+  e = reloc_handle (hf, &nh, TRUE);
+  if (e != 0)
+    {
+      DosClose (hf);
+      *errnop = e;
+      return -1;
+    }
+
+  /* Return the handle and tell the caller not to modify `errno'. */
+
+  *errnop = 0;
+  return nh;
+}
+
+
+/* This function implements the __fcntl() system call. */
+
+int do_fcntl (ULONG handle, ULONG request, ULONG arg, int *errnop)
+{
+  ULONG rc, ht, diff, state;
+  int result;
+
+  switch (request)
+    {
+    case F_GETFD:
+
+      /* Return the close-on-exec flag.  It's the complement of OS/2's
+         OPEN_FLAGS_NOINHERIT bit.  For sockets, the flag is stored in
+         the `my_file' structure. */
+
+      if (IS_SOCKET (handle))
+        {
+          if (!IS_VALID_FILE (handle))
+            {
+              *errnop = EBADF;
+              return -1;
+            }
+          *errnop = 0;
+          return GET_FILE (handle)->x.socket.fd_flags;
+        }
+        
+      rc = DosQueryFHState (handle, &state);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      *errnop = 0;
+      return ((state & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0);
+
+    case F_SETFD:
+
+      /* Set the close-on-exec flag. */
+
+      if (IS_SOCKET (handle))
+        {
+          if (!IS_VALID_FILE (handle))
+            {
+              *errnop = EBADF;
+              return -1;
+            }
+          GET_FILE (handle)->x.socket.fd_flags = arg;
+          *errnop = 0;
+          return 0;
+        }
+
+      rc = set_no_inherit (handle, arg);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      break;
+
+    case F_GETFL:
+
+      /* Return O_APPEND and/or O_NDELAY. */
+
+      if (handle >= handle_count || !(handle_flags[handle] & HF_OPEN))
+        {
+          *errnop = EBADF;
+          return -1;
+        }
+      ht = handle_flags[handle];
+      result = 0;
+      if (ht & HF_NDELAY)
+        result |= O_NDELAY;
+      if (ht & HF_APPEND)
+        result |= O_APPEND;
+      *errnop = 0;
+      return result;
+
+    case F_SETFL:
+
+      /* Copy O_NDELAY and O_APPEND as HF_NDELAY and HF_APPEND to
+         `handle_flags'.  If O_NDELAY changed for a named pipe, change
+         pipe state.  If O_NDELAY is changed for a socket or pty,
+         perform a FIONBIO ioctl. */
+
+      if (arg & ~(O_NDELAY | O_APPEND))
+        {
+          *errnop = EINVAL;
+          return -1;
+        }
+      if (handle >= handle_count || !(handle_flags[handle] & HF_OPEN))
+        {
+          *errnop = EBADF;
+          return -1;
+        }
+      ht = handle_flags[handle];
+      ht &= ~(HF_NDELAY | HF_APPEND);
+      if (arg & O_NDELAY)
+        ht |= HF_NDELAY;
+      if (arg & O_APPEND)
+        ht |= HF_APPEND;
+
+      diff = handle_flags[handle] ^ ht; /* Changed flags */
+      handle_flags[handle] = ht;
+
+      /* Change the handle state if HF_NDELAY changed for a named
+         pipe. */
+
+      if ((diff & HF_NDELAY) && (ht & HF_NPIPE))
+        {
+          state = 0;
+          if (ht & HF_NDELAY)
+            state |= NP_NOWAIT;
+          rc = DosSetNPHState (handle, state);
+          if (rc != 0)
+            {
+              *errnop = set_error (rc);
+              return -1;
+            }
+        }
+
+      /* Change the handle state if HF_NDELAY changed for a socket. */
+
+      if ((diff & HF_NDELAY) && (ht & HF_SOCKET))
+        if (tcpip_fcntl (handle, F_SETFL, arg, errnop) != 0)
+          return -1;
+
+      /* Change the handle state if HF_NDELAY changed for a xf86sup
+         device. */
+
+      if ((diff & HF_NDELAY) && (ht & HF_XF86SUP))
+        if (xf86sup_fcntl (handle, F_SETFL, arg, errnop) != 0)
+          return -1;
+      break;
+
+    default:
+
+      /* Set errno to EINVAL for unknown request codes. */
+
+      *errnop = EINVAL;
+      return -1;
+    }
+
+  /* Function successfully completed. */
+
+  *errnop = 0;
+  return 0;
+}
+
+
+/* This function emulates the DOS function 0x4400 (IOCTL, get device
+   data). */
+
+int do_ioctl1 (ULONG handle, int *errnop)
+{
+  ULONG rc, htype, hflags;
+  int result;
+
+  /* This function is not implemented for sockets. */
+
+  if (IS_SOCKET (handle))
+    {
+      *errnop = EINVAL;
+      return -1;
+    }
+
+  /* First, get the type of the file handle (pipe, device, or
+     file). */
+
+  rc = DosQueryHType (handle, &htype, &hflags);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* Set `result' depending on the file type. */
+
+  result = 0;
+  switch (htype & 0xff)
+    {
+    case HANDTYPE_PIPE:
+      result = 0x80;            /* Device or pipe */
+      break;
+
+    case HANDTYPE_DEVICE:
+      result = (hflags & 0x0f) | 0x80; /* kbd, scr, nul, clock */
+      break;
+
+    case HANDTYPE_FILE:
+      /* Insert drive letter (not implemented). */
+      break;
+
+    default:
+      /* Future extension. */
+      break;
+    }
+
+  *errnop = 0;
+  return result;
+}
+
+
+/* This function implements the __ioctl2() system call. */
+
+int do_ioctl2 (ULONG handle, ULONG request, ULONG arg, int *errnop)
+{
+  ULONG ht;
+  int n;
+
+  /* This function is the first one called by the startup code which
+     requires init_fileio().  If emx.dll is used by a DLL which is
+     used by a program that does not use emx.dll, init_fileio() has
+     not yet been called.  Do that now. */
+
+  if (handle_flags == NULL)
+    init_fileio ();
+
+  /* Reject invalid handles and handles which are not open. */
+
+  if (handle >= handle_count || !(handle_flags[handle] & HF_OPEN))
+    {
+      *errnop = EBADF;
+      return -1;
+    }
+
+  /* Get the flag bits for the handle. */
+
+  ht = handle_flags[handle];
+
+  /* Handle sockets specially. */
+
+  if (ht & HF_SOCKET)
+    return tcpip_ioctl (handle, request, arg, errnop);
+
+  /* Handle xf86sup devices specially. */
+
+  if (ht & HF_XF86SUP)
+    return xf86sup_ioctl (handle, request, arg, errnop);
+
+  switch (request)
+    {
+    case TCGETA:
+
+      /* Get `struct termio' of the file handle. */
+
+      if (!(ht & (HF_CON|HF_ASYNC)) || !IS_VALID_FILE (handle))
+        {
+          *errnop = EINVAL;
+          return -1;
+        }
+      termio_get (handle, (void *)arg);
+      break;
+
+    case TCSETA:
+    case TCSETAF:
+    case TCSETAW:
+
+      /* Set `struct termio' of the file handle. */
+
+      if (!(ht & (HF_CON|HF_ASYNC)) || !IS_VALID_FILE (handle))
+        {
+          *errnop = EINVAL;
+          return -1;
+        }
+      if (request == TCSETAF)
+        termio_flush (handle);
+      termio_set (handle, (void *)arg);
+      break;
+
+    case TCFLSH:
+
+      /* Flush the input and/or output queues. */
+
+      if (!(ht & (HF_CON|HF_ASYNC)) || !IS_VALID_FILE (handle) || arg > 2)
+        {
+          *errnop = EINVAL;
+          return -1;
+        }
+      if (arg == 0 || arg == 2)
+        termio_flush (handle);  /* Flush input queue. */
+#if 0
+      if (arg == 1 || arg == 2)
+        {
+          /* Flush output queue; not implemented. */
+        }
+#endif
+      break;
+
+    case TCSBRK:
+
+      /* Send break. */
+
+      *errnop = 0;
+      return 0;
+
+    case TCXONC:
+
+      /* Flow control. */
+
+      *errnop = 0;
+      return 0;
+
+    case _TCGA:
+
+      /* Get `struct termios' of the file handle, for tcgetattr(). */
+
+      if (!(ht & (HF_CON|HF_ASYNC)) || !IS_VALID_FILE (handle))
+        {
+          *errnop = xlate_errno (ENOTTY);
+          return -1;
+        }
+      termios_get (handle, (void *)arg);
+      break;
+
+    case _TCSANOW:
+    case _TCSADRAIN:
+    case _TCSAFLUSH:
+
+      /* Set `struct termios' of the file handle, for tcsetattr(). */
+
+      if (!(ht & (HF_CON|HF_ASYNC)) || !IS_VALID_FILE (handle))
+        {
+          *errnop = xlate_errno (ENOTTY);
+          return -1;
+        }
+      if (request == _TCSAFLUSH)
+        termio_flush (handle);
+      termios_set (handle, (void *)arg);
+      break;
+
+    case FIONREAD:
+
+      /* Get the number of characters available for reading. */
+
+      if ((ht & (HF_CON|HF_ASYNC)) && IS_VALID_FILE (handle))
+        n = termio_avail (handle);
+      else if (ht & HF_NPIPE)
+        {
+          n = npipe_avail (handle, errnop);
+          if (n == -1)
+            return -1;
+        }
+      else
+        {
+          *errnop = EINVAL;
+          return -1;
+        }
+      *(int *)arg = n;
+      break;
+
+    case FGETHTYPE:
+
+      /* Get the file type. */
+
+      if (ht & HF_UPIPE)
+        n = HT_UPIPE;
+      else if (ht & HF_NPIPE)
+        n = HT_NPIPE;
+      else if (ht & HF_SOCKET)
+        n = HT_SOCKET;
+      else if (!(ht & HF_DEV))
+        n = HT_FILE;
+      else if (ht & HF_CON)
+        n = HT_DEV_CON;
+      else if (ht & HF_NUL)
+        n = HT_DEV_NUL;
+      else if (ht & HF_CLK)
+        n = HT_DEV_CLK;
+      else
+        n = HT_DEV_OTHER;
+      *(int *)arg = n;
+      break;
+
+    default:
+      *errnop = EINVAL;
+      return -1;
+    }
+
+  /* Function successfully completed. */
+
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Duplicate a file handle. */
+
+int do_dup (ULONG src_fd, ULONG req_target, int *errnop)
+{
+  ULONG rc, state, new_fd;
+
+  /* Handle socket handles specially. */
+
+  if (IS_SOCKET (src_fd))
+    return tcpip_dup (src_fd, req_target, errnop);
+
+  if (src_fd == req_target)
+    {
+      rc = DosQueryFHState (src_fd, &state); /* Check SRC_FD */
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      *errnop = 0;
+      return req_target;
+    }
+
+  new_fd = req_target;
+  LOCK_FILES;
+  xf86sup_maybe_enadup (src_fd, TRUE);
+  rc = DosDupHandle (src_fd, &new_fd);
+  xf86sup_maybe_enadup (src_fd, FALSE);
+  if (rc != 0)
+    {
+      UNLOCK_FILES;
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* Reject handles which are out of the supported range. */
+
+  if (new_fd >= handle_count)
+    {
+      DosClose (new_fd);
+      set_error (0);
+      UNLOCK_FILES;
+      *errnop = EMFILE;
+      return -1;
+    }
+
+  /* A successful dup2() call closes the target handle.  Update our
+     tables. */
+
+  if (new_fd == req_target)
+    {
+      /* DosDupHandle doesn't know about sockets, so we have to close
+         sockets here.  tcpip_close() calls close_handle(). */
+
+      if (IS_SOCKET (new_fd))
+        tcpip_close (new_fd);
+      else
+        close_handle (new_fd);
+    }
+
+  /* If the new handle hit a faked socket handle, relocate the new
+     handle.  This can happen only for dup(), not for dup2(), because
+     the target handle of dup2() has been closed above. */
+
+  if (handle_flags[new_fd] & HF_SOCKET)
+    {
+      ULONG nf;
+
+      if (reloc_handle (new_fd, &nf, FALSE) != 0)
+        {
+          DosClose (new_fd);
+          UNLOCK_FILES;
+          set_error (0);
+          *errnop = EMFILE;
+          return -1;
+        }
+      new_fd = nf;
+    }
+
+  /* Copy the source file handle's data to the new handle. */
+
+  handle_file[new_fd] = handle_file[src_fd];
+  handle_flags[new_fd] = handle_flags[src_fd];
+
+  if (IS_VALID_FILE (src_fd))
+    GET_FILE (src_fd)->ref_count += 1;
+  else
+    {
+      SET_INVALID_FILE (new_fd);
+      new_handle (new_fd);
+    }
+  UNLOCK_FILES;
+  *errnop = 0;
+  return new_fd;
+}
+
+
+/* Close a file handle. */
+
+int do_close (ULONG handle)
+{
+  ULONG rc;
+
+  if (IS_SOCKET (handle))
+    return tcpip_close (handle);
+
+  close_handle (handle);
+  rc = DosClose (handle);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Read from a file handle. */
+
+ULONG do_read (ULONG handle, void *dst, ULONG count, int *errnop)
+{
+  ULONG hflags, rc, nread;
+
+  hflags = (handle < handle_count ? handle_flags[handle] : 0);
+  if ((hflags & (HF_CON|HF_ASYNC)) && IS_VALID_FILE (handle)
+      && !(GET_FILE (handle)->c_lflag & IDEFAULT))
+    return termio_read (handle, dst, count, errnop);
+  else if ((hflags & HF_SOCKET) && IS_VALID_FILE (handle))
+    return tcpip_read (handle, dst, count, errnop);
+  else
+    {
+      if (exe_heap)
+        touch (dst, count);
+      rc = DosRead (handle, dst, count, &nread);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return (ULONG)-1;
+        }
+      *errnop = 0;
+      return nread;
+    }
+}
+
+
+/* Write to a file handle. */
+
+ULONG do_write (ULONG handle, void *src, ULONG count, int *errnop)
+{
+  ULONG rc, nwritten;
+
+  if (IS_SOCKET (handle) && IS_VALID_FILE (handle))
+    return tcpip_write (handle, src, count, errnop);
+
+  if (exe_heap)
+    touch (src, count);
+  rc = DosWrite (handle, src, count, &nwritten);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return (ULONG)-1;
+    }
+  *errnop = 0;
+  return nwritten;
+}
+
+
+/* Move the file pointer of a file handle. */
+
+ULONG do_seek (ULONG handle, ULONG origin, LONG distance, int *errnop)
+{
+  ULONG rc, new_pos;
+
+  if (IS_SOCKET (handle))
+    {
+      *errnop = ESPIPE;
+      return (ULONG)-1;
+    }
+
+  rc = DosSetFilePtr (handle, distance, origin, &new_pos);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return (ULONG)-1;
+    }
+  *errnop = 0;
+  return new_pos;
+}
+
+
+/* Create a pipe.  DST points to two int's which will receive the
+   handles.  PIPESIZE is the size of the pipe.  Return errno. */
+
+int do_pipe (int *dst, ULONG pipesize)
+{
+  HPIPE r_handle, w_handle, nh;
+  ULONG rc, action, pn;
+  char fname[128];
+  int e;
+
+  /* Create unique a pipe name (unique on this system). */
+
+  LOCK_COMMON;
+  pn = ++pipe_number;
+  UNLOCK_COMMON;
+  sprintf (fname, "/pipe/emx/pipes/%.8x.pip", (unsigned)pn);
+
+  /* Create the pipe. */
+
+  rc = DosCreateNPipe (fname, &r_handle,
+                       NP_ACCESS_INBOUND,
+                       1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE,
+                       pipesize, pipesize, 0);
+  if (rc != 0)
+    return set_error (rc);
+
+  /* Connect to the pipe. */
+
+  rc = DosConnectNPipe (r_handle);
+  if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
+    {
+      DosClose (r_handle);
+      return set_error (rc);
+    }
+
+  /* Turn on NP_WAIT. */
+
+  rc = DosSetNPHState (r_handle, NP_WAIT | NP_READMODE_BYTE);
+  if (rc != 0)
+    {
+      DosClose (r_handle);
+      return set_error (rc);
+    }
+
+  /* Open the write side of the pipe. */
+
+  rc = DosOpen (fname, &w_handle, &action, 0, FILE_NORMAL,
+                OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+                OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE,
+                NULL);
+  if (rc != 0)
+    {
+      DosClose (r_handle);
+      return set_error (rc);
+    }
+
+  /* Update the file handle table. */
+
+  e = reloc_handle (r_handle, &nh, TRUE);
+  if (e != 0)
+    {
+      DosClose (r_handle);
+      DosClose (w_handle);
+      return e;
+    }
+  r_handle = nh;
+
+  e = reloc_handle (w_handle, &nh, TRUE);
+  if (e != 0)
+    {
+      DosClose (r_handle);
+      DosClose (w_handle);
+      return e;
+    }
+  w_handle = nh;
+
+  /* Set DST handles. */
+
+  dst[0] = r_handle;
+  dst[1] = w_handle;
+  return 0;
+}
+
+
+/* Truncate file HANDLE to FSIZE bytes.  Return errno. */
+
+int do_ftruncate (ULONG handle, ULONG fsize)
+{
+  FILESTATUS3 info;
+  ULONG rc;
+
+  if (IS_SOCKET (handle))
+    return EINVAL;
+
+  rc = DosQueryFileInfo (handle, FIL_STANDARD, &info, sizeof (info));
+  if (rc != 0)
+    return set_error (rc);
+  if (fsize >= info.cbFile)
+    return 0;
+  rc = DosSetFileSize (handle, fsize);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Change size of file HANDLE to FSIZE bytes.  Return errno. */
+
+int do_chsize (ULONG handle, ULONG fsize)
+{
+  ULONG rc;
+
+  if (IS_SOCKET (handle))
+    return EINVAL;
+
+  rc = DosSetFileSize (handle, fsize);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Flush the buffers of a file. */
+
+int do_fsync (ULONG handle, int *errnop)
+{
+  ULONG rc;
+
+  if (IS_SOCKET (handle))
+    return EINVAL;
+
+  rc = DosResetBuffer (handle);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Store the name of the file-system driver of drive DRV_NAME to DST
+   (up to DST_SIZE bytes, including the terminating null character).
+   Store errno to *ERRNOP.  Return 0 on success, -1 on error. */
+
+int do_filesys (char *dst, ULONG dst_size, const char *drv_name, int *errnop)
+{
+  char buf[sizeof (PFSQBUFFER2) + 128];
+  PFSQBUFFER2 pfsq = (PFSQBUFFER2)buf;
+  ULONG rc, len;
+
+  len = sizeof (buf);
+  rc = DosQueryFSAttach (drv_name, 1, FSAIL_QUERYNAME, pfsq, &len);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  if (pfsq->iType != FSAT_LOCALDRV && pfsq->iType != FSAT_REMOTEDRV)
+    {
+      *errnop = EINVAL;
+      return -1;
+    }
+  if (pfsq->cbFSDName >= dst_size)
+    {
+      *errnop = E2BIG;
+      return -1;
+    }
+  strcpy (dst, pfsq->szFSDName + pfsq->cbName);
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Create a directory. */
+
+int do_mkdir (const char *path)
+{
+  char fname[512];
+  ULONG rc;
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Create the directory and handle errors. */
+
+  rc = DosCreateDir (fname, NULL);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Remove a directory. */
+
+int do_rmdir (const char *path)
+{
+  char fname[512];
+  ULONG rc;
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Remove the directory and handle errors. */
+
+  rc = DosDeleteDir (fname);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Change the current working directory (of a disk drive). */
+
+int do_chdir (const char *path)
+{
+  char fname[512];
+  ULONG rc;
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Change the current working directory and handle errors. */
+
+  rc = DosSetCurrentDir (fname);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Delete a file. */
+
+int do_delete (const char *path)
+{
+  char fname[512];
+  ULONG rc;
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Delete the file and handle errors. */
+
+  rc = DosDelete (fname);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Rename or move a file. */
+
+int do_rename (const char *old_path, const char *new_path)
+{
+  char old_fname[512], new_fname[512];
+  ULONG rc;
+
+  /* Copy the path names to `fname1' and `fname2', respectively, with
+     modifications according to the -r and -t options. */
+
+  truncate_name (old_fname, old_path);
+  truncate_name (new_fname, new_path);
+
+  /* Rename the file handle errors. */
+
+  rc = DosMove (old_fname, new_fname);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Return the index of the current disk, 0 = A:. */
+
+UCHAR do_getdrive (void)
+{
+  ULONG drv;
+  ULONG map;
+
+  DosQueryCurrentDisk (&drv, &map);
+  return (UCHAR)(drv - 1);
+}
+
+
+/* Select disk DRV (0 = A:) as current disk. */
+
+ULONG do_selectdisk (ULONG drv)
+{
+  ULONG rc;
+
+  rc = DosSetDefaultDisk (drv + 1);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Return the file attributes of PATH. */
+
+ULONG get_attr (const char *path, int *errnop)
+{
+  char fname[512];
+  FILESTATUS3 status;
+  ULONG rc;
+
+  /* This function cannot be applied to named pipes. */
+
+  if (check_npipe (path))
+    {
+      *errnop = ENOENT;
+      return 0;
+    }
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Get the file attributes and handle errors. */
+
+  rc = query_path_info (fname, FIL_STANDARD, &status, sizeof (status));
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return 0;
+    }
+  *errnop = 0;
+  return status.attrFile;
+}
+
+
+/* Set the file attributes of PATH. */
+
+ULONG set_attr (const char *path, ULONG attr)
+{
+  char fname[512];
+  FILESTATUS3 status;
+  ULONG rc;
+
+  /* This function cannot be applied to named pipes. */
+
+  if (check_npipe (path))
+    return ENOENT;
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Get the current file attributes and handle errors. */
+
+  rc = query_path_info (fname, FIL_STANDARD, &status, sizeof (status));
+  if (rc != 0)
+    return set_error (rc);
+
+  /* Update the file attributes and handle errors. */
+
+  status.attrFile = attr;
+  rc = DosSetPathInfo (fname, FIL_STANDARD, &status, sizeof (status), 0);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Get the current working directory of disk DRIVE. */
+
+ULONG do_getcwd (char *dst, int drive)
+{
+  ULONG rc, len;
+
+  len = 512;
+  rc = DosQueryCurrentDir (drive, dst, &len);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+static ULONG find_conv (thread_data *td, struct _find *dst);
+static void find_close (thread_data *td);
+
+/* This function implements the __findfirst() system call. */
+
+ULONG do_find_first (const char *path, ULONG attr, struct _find *dst)
+{
+  char fname[512];
+  thread_data *td;
+  ULONG rc;
+
+  td = get_thread ();
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  if (td->find_handle != HDIR_CREATE)
+    {
+      /* Closing the handle is not strictly required as DosFindFirst
+         can reuse an open handle.  However, this simplifies error
+         handling below (will DosFindFirst close the handle on error
+         if it is open?). */
+
+      DosFindClose (td->find_handle);
+      td->find_handle = HDIR_CREATE;
+    }
+
+  td->find_count = ((debug_flags & DEBUG_FIND1) ? 1 : FIND_COUNT);
+  rc = DosFindFirst (fname, &td->find_handle, attr, &td->find_buf[0],
+                     sizeof (td->find_buf), &td->find_count, FIL_STANDARD);
+  if (rc != 0)
+    {
+      td->find_handle = HDIR_CREATE; /* Perhaps modified by DosFindFirst */
+      td->find_count = 0;
+      td->find_next = NULL;
+      return set_error (rc);
+    }
+  td->find_next = &td->find_buf[0];
+  return find_conv (td, dst);
+}
+
+
+/* This function implements the __findnext() system call. */
+
+ULONG do_find_next (struct _find *dst)
+{
+  thread_data *td;
+  ULONG rc;
+
+  td = get_thread ();
+  if (td->find_count < 1)
+    {
+      td->find_count = ((debug_flags & DEBUG_FIND1) ? 1 : FIND_COUNT);
+      rc = DosFindNext (td->find_handle, &td->find_buf[0],
+                        sizeof (td->find_buf), &td->find_count);
+      if (rc != 0)
+        {
+          find_close (td);
+          return set_error (rc);
+        }
+      td->find_next = &td->find_buf[0];
+    }
+
+  return find_conv (td, dst);
+}
+
+
+/* Build a `struct _find' structure from a FILEFINDBUF3 structure and
+   move to the next one. */
+
+static ULONG find_conv (thread_data *td, struct _find *dst)
+{
+  const FILEFINDBUF3 *src;
+
+  /* Check if there are any entries.  Close the handle and return
+     ENOENT if there are no entries.  (Checking SRC is redundant.) */
+
+  src = td->find_next;
+  if (td->find_count < 1 || src == NULL)
+    {
+      find_close (td);
+      return ENOENT;
+    }
+
+  /* Fill-in target object. */
+
+  dst->attr = src->attrFile;
+  dst->time = XUSHORT (src->ftimeLastWrite);
+  dst->date = XUSHORT (src->fdateLastWrite);
+  dst->size_lo = (USHORT)src->cbFile;
+  dst->size_hi = (USHORT)(src->cbFile >> 16);
+  strcpy (dst->name, src->achName);
+
+  /* Move to the next entry. */
+
+  if (src->oNextEntryOffset == 0)
+    {
+      td->find_next = NULL;
+      td->find_count = 0;
+    }
+  else
+    {
+      td->find_next = (FILEFINDBUF3 *)((char *)src + src->oNextEntryOffset);
+      td->find_count -= 1;
+    }
+  return 0;
+}
+
+
+/* Close the directory handle. */
+
+static void find_close (thread_data *td)
+{
+  if (td->find_handle != HDIR_CREATE)
+    {
+      DosFindClose (td->find_handle);
+      td->find_handle = HDIR_CREATE;
+    }
+  td->find_count = 0;
+  td->find_next = NULL;
+}
+
+
+/* Get the timestamp (last modification) of HANDLE. */
+
+ULONG do_get_timestamp (ULONG handle, ULONG *time, ULONG *date)
+{
+  FILESTATUS3 status;
+  ULONG rc;
+
+  if (IS_SOCKET (handle))
+    return EINVAL;
+
+  rc = DosQueryFileInfo (handle, FIL_STANDARD, &status, sizeof (status));
+  if (rc != 0)
+    return set_error (rc);
+  *time = XUSHORT (status.ftimeLastWrite);
+  *date = XUSHORT (status.fdateLastWrite);
+  return 0;
+}
+
+
+/* Set the timestamp (last modification) of HANDLE. */
+
+ULONG do_set_timestamp (ULONG handle, ULONG time, ULONG date)
+{
+  FILESTATUS3 status;
+  ULONG rc;
+
+  if (IS_SOCKET (handle))
+    return EINVAL;
+
+  rc = DosQueryFileInfo (handle, FIL_STANDARD, &status, sizeof (status));
+  if (rc != 0)
+    return set_error (rc);
+  XUSHORT (status.ftimeLastWrite) = (USHORT)time;
+  XUSHORT (status.fdateLastWrite) = (USHORT)date;
+  rc = DosSetFileInfo (handle, FIL_STANDARD, &status, sizeof (status));
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+/* Convert a timestamp in Unix format to DOS format. */
+
+static void unix2dosdt (FDATE *pdate, FTIME *ptime, ULONG ut)
+{
+  struct my_datetime mdt;
+
+  unix2time (&mdt, ut);
+  ptime->twosecs = mdt.seconds / 2;
+  ptime->minutes = mdt.minutes;
+  ptime->hours = mdt.hours;
+  pdate->day = mdt.day;
+  pdate->month = mdt.month;
+  pdate->year = mdt.year - 1980;
+}
+
+
+/* This function implements the __utimes() system call. */
+
+int do_utimes (const char *path, const struct timeval *tv, int *errnop)
+{
+  char fname[512];
+  FILESTATUS3 info;
+  ULONG rc;
+
+  /* This function cannot be applied to named pipes. */
+
+  if (check_npipe (path))
+    {
+      *errnop = ENOENT;
+      return -1;
+    }
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Get the file status and handle errors. */
+
+  rc = query_path_info (fname, FIL_STANDARD, &info, sizeof (info));
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* Update the modification time and date. */
+
+  unix2dosdt (&info.fdateLastAccess, &info.ftimeLastAccess, tv[0].tv_sec);
+  unix2dosdt (&info.fdateLastWrite, &info.ftimeLastWrite, tv[1].tv_sec);
+
+  /* Set the file status and handle errors. */
+
+  rc = DosSetPathInfo (fname, FIL_STANDARD, &info, sizeof (info), 0);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* Function successfully completed. */
+
+  *errnop = 0;
+  return 0;
+}
+
+
+/* This function implements the __stat() system call. */
+
+int do_stat (const char *path, struct stat *dst, int *errnop)
+{
+  FILESTATUS3 info;
+  char fname[512];
+  ULONG rc;
+
+  /* __stat() cannot be applied to named pipes. */
+
+  if (check_npipe (path))
+    {
+      *errnop = ENOENT;
+      return -1;
+    }
+
+  /* Copy the path name to `fname', with modifications according to
+     the -r and -t options. */
+
+  truncate_name (fname, path);
+
+  /* Get the file status and handle errors. */
+
+  memset (dst, 0, sizeof (struct stat));
+  rc = query_path_info (fname, FIL_STANDARD, &info, sizeof (info));
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  dst->st_attr = info.attrFile;
+  dst->st_reserved = 0;
+
+  dst->st_mtime = packed2unix (info.fdateLastWrite, info.ftimeLastWrite);
+  if (XUSHORT (info.fdateCreation) == 0 && XUSHORT (info.ftimeCreation) == 0)
+    dst->st_ctime = dst->st_mtime;
+  else
+    dst->st_ctime = packed2unix (info.fdateCreation, info.ftimeCreation);
+  if (XUSHORT (info.fdateLastAccess) == 0
+      && XUSHORT (info.ftimeLastAccess) == 0)
+    dst->st_atime = dst->st_mtime;
+  else
+    dst->st_atime = packed2unix (info.fdateLastAccess, info.ftimeLastAccess);
+
+  if (info.attrFile & 0x10)
+    {
+      /* It's a directory. */
+      dst->st_size = 0;
+      dst->st_mode = S_IFDIR | MAKEPERM (S_IREAD|S_IWRITE|S_IEXEC);
+    }
+  else
+    {
+      /* It's a regular file. */
+      dst->st_size = info.cbFile;
+      if (info.attrFile & 0x01)
+        dst->st_mode = S_IFREG | MAKEPERM (S_IREAD);
+      else
+        dst->st_mode = S_IFREG | MAKEPERM (S_IREAD|S_IWRITE);
+    }
+  dst->st_dev = 0;
+  dst->st_uid = 0;              /* root */
+  dst->st_gid = 0;              /* root */
+  dst->st_ino = ino_number;
+  if (++ino_number == 0)
+   ino_number = 1;
+  dst->st_rdev = dst->st_dev;
+  dst->st_nlink = 1;
+  *errnop = 0;
+  return 0;
+}
+
+
+/* This function implements the __fstat() system call. */
+
+int do_fstat (ULONG handle, struct stat *dst, int *errnop)
+{
+  FILESTATUS3 info;
+  ULONG rc, flags, htype, state;
+
+  if (IS_SOCKET (handle))
+    return tcpip_fstat (handle, dst, errnop);
+
+  memset (dst, 0, sizeof (struct stat));
+  rc = DosQueryHType (handle, &htype, &flags);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  switch (htype & 0xff)
+    {
+    case HANDTYPE_DEVICE:       /* Character device */
+    case HANDTYPE_PIPE:         /* Pipe */
+      rc = DosQueryFHState (handle, &state);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      if ((state & 7) == OPEN_ACCESS_READONLY)
+        dst->st_mode = MAKEPERM (S_IREAD);
+      else
+        dst->st_mode = MAKEPERM (S_IREAD|S_IWRITE);
+      if ((htype & 0xff) == HANDTYPE_DEVICE)
+        dst->st_mode |= S_IFCHR;
+      else
+        dst->st_mode |= S_IFIFO;
+      dst->st_size = 0;
+      break;
+
+    default:
+      rc = DosQueryFileInfo (handle, FIL_STANDARD, &info, sizeof (info));
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      dst->st_attr = info.attrFile;
+      dst->st_reserved = 0;
+
+      dst->st_mtime = packed2unix (info.fdateLastWrite, info.ftimeLastWrite);
+      if (XUSHORT (info.fdateCreation) == 0
+          && XUSHORT (info.ftimeCreation) == 0)
+        dst->st_ctime = dst->st_mtime;
+      else
+        dst->st_ctime = packed2unix (info.fdateCreation, info.ftimeCreation);
+      if (XUSHORT (info.fdateLastAccess) == 0
+          && XUSHORT (info.ftimeLastAccess) == 0)
+        dst->st_atime = dst->st_mtime;
+      else
+        dst->st_atime = packed2unix (info.fdateLastAccess,
+                                     info.ftimeLastAccess);
+
+      dst->st_size = info.cbFile;
+      if (info.attrFile & 0x01)
+        dst->st_mode = S_IFREG | MAKEPERM (S_IREAD);
+      else
+        dst->st_mode = S_IFREG | MAKEPERM (S_IREAD|S_IWRITE);
+      break;
+    }
+  dst->st_dev = 0;
+  dst->st_uid = 0;              /* root */
+  dst->st_gid = 0;              /* root */
+  dst->st_ino = ino_number;
+  if (++ino_number == 0)
+   ino_number = 1;
+  dst->st_rdev = dst->st_dev;
+  dst->st_nlink = 1;
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Send the character CHR to standard output. */
+
+void conout (UCHAR chr)
+{
+  ULONG written;
+
+  DosWrite (1, &chr, 1, &written);
+}
+
+
+/* This function implements the __imphandle() system call: Import an
+   OS/2 handle. */
+
+ULONG do_imphandle (ULONG handle, int *errnop)
+{
+  ULONG nh;
+  int e;
+
+  e = reloc_handle (handle, &nh, TRUE);
+  if (e != 0)
+    {
+      *errnop = e;
+      return (ULONG)-1;
+    }
+  *errnop = 0;
+  return nh;
+}
+
+
+/* Store the name of the device HANDLE to DST (up to DST_SIZE bytes,
+   including the terminating null character).  Store errno to *ERRNOP.
+   Return 0 on success, -1 on error. */
+
+int do_ttyname (char *dst, ULONG dst_size, ULONG handle, int *errnop)
+{
+  if (handle >= handle_count || !(handle_flags[handle] & HF_OPEN))
+    {
+      *errnop = EBADF;
+      return -1;
+    }
+  if (handle_flags[handle] & HF_CON)
+    return set_ttyname (dst, dst_size, "/dev/con", errnop);
+  else if (handle_flags[handle] & HF_NUL)
+    return set_ttyname (dst, dst_size, "/dev/nul", errnop);
+  else if (handle_flags[handle] & HF_CLK)
+    return set_ttyname (dst, dst_size, "/dev/clock$", errnop);
+  else if (handle_flags[handle] & HF_XF86SUP)
+    return xf86sup_ttyname (dst, dst_size, handle, errnop);
+  else
+    {
+      *errnop = ENODEV;
+      return -1;
+    }
+}
+
+
+int set_ttyname (char *dst, ULONG dst_size, const char *name, int *errnop)
+{
+  if (strlen (name) >= dst_size)
+    {
+      *errnop = ENAMETOOLONG;
+      return -1;
+    }
+  strcpy (dst, name);
+  *errnop = 0;
+  return 0;
+}
Index: trunk/src/emx/src/os2/files.h
===================================================================
--- trunk/src/emx/src/os2/files.h	(revision 18)
+++ trunk/src/emx/src/os2/files.h	(revision 18)
@@ -0,0 +1,129 @@
+/* files.h -- Header file for modules involved in file handle management
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+/* Requires INCL_DOSDEVIOCTL! */
+
+#define ASYNC_SETEXTBAUDRATE		0x0043
+#define ASYNC_GETEXTBAUDRATE		0x0063
+
+typedef struct
+{
+  ULONG ulCurrentRate;
+  BYTE  bCurrentFract;
+  ULONG ulMinimumRate;
+  BYTE  bMinimumFract;
+  ULONG ulMaximumRate;
+  BYTE  bMaximumFract;
+} GETEXTBAUDRATE;
+typedef GETEXTBAUDRATE *PGETEXTBAUDRATE;
+
+typedef struct
+{
+  ULONG ulRate;
+  BYTE  bFract;
+} SETEXTBAUDRATE;
+typedef SETEXTBAUDRATE *PSETEXTBAUDRATE;
+
+
+#define SET_INVALID_FILE(handle) (handle_file[handle] = handle_count)
+#define IS_VALID_FILE(handle) (handle_file[handle] < handle_count)
+#define GET_FILE(handle) (&files[handle_file[handle]])
+
+
+typedef struct
+{
+  ULONG flags;
+  ULONG ref_count;
+
+  /* termio interface */
+
+  ULONG c_iflag;
+  ULONG c_oflag;
+  ULONG c_cflag;
+  ULONG c_lflag;
+  UCHAR c_cc[11];                /* NCC == 8, NCCS == 11 */
+
+  /* termio implementation */
+
+  char *tio_buf;
+  unsigned tio_buf_count;
+  unsigned tio_buf_size;
+  unsigned tio_buf_idx;
+  char tio_escape;
+  ULONG tio_input_handle;
+  ULONG tio_output_handle;
+
+  /* Data which depends on the file type. */
+
+  union
+    {
+      struct
+        {
+          GETEXTBAUDRATE speed;
+          LINECONTROL lctl;
+          DCBINFO dcb;
+        } async;
+      struct
+        {
+          int handle;
+          int fd_flags;         /* FD_CLOEXEC */
+        } socket;
+      struct
+        {
+          ULONG id;             /* ID returned by XF86SUP_DRVID */
+          HEV sem;              /* Semaphore handle */
+          BYTE sem_open;        /* Semaphore handle valid */
+        } xf86sup;              /* xf86sup device */
+    } x;
+} my_file;
+
+
+extern ULONG handle_count;
+extern ULONG *handle_flags;
+extern ULONG *handle_file;
+extern my_file *files;
+extern long ino_number;
+extern HMTX files_access;
+
+
+/* Duplicate S_IREAD, S_IWRITE, and S_IEXEC bits into all three groups
+   of the permission mask. */
+
+#define MAKEPERM(x) (((x) >> 6) * 0111)
+
+#define IS_SOCKET(h) ((h) < handle_count && (handle_flags[h] & HF_SOCKET))
+
+
+/* `handle_flags' array is protected by a Mutex semaphore.  These
+   macros are used for requesting and releasing that semaphore. */
+
+#define LOCK_FILES   request_mutex (files_access)
+#define UNLOCK_FILES DosReleaseMutexSem (files_access)
+
+void alloc_file_description (ULONG handle);
+void close_handle (ULONG handle);
+void set_handle_flags (ULONG handle, ULONG flags);
+int find_unused_handles (ULONG *dst, int count);
Index: trunk/src/emx/src/os2/init.c
===================================================================
--- trunk/src/emx/src/os2/init.c	(revision 18)
+++ trunk/src/emx/src/os2/init.c	(revision 18)
@@ -0,0 +1,1277 @@
+/* init.c -- Initialization
+   Copyright (c) 1994-2000 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSPROCESS
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSMODULEMGR
+#define INCL_DOSMISC
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSERRORS
+#define INCL_REXXSAA
+#include <os2emx.h>
+#include <emx/startup.h>
+#include "emxdll.h"
+#include "clib.h"
+#include "version.h"
+
+/* Pointer to the layout table of the executable. */
+
+layout_table *layout;
+
+/* Flags from layout table. */
+
+ULONG layout_flags;
+
+/* Interface number, taken from the layout table. */
+
+BYTE interface;
+
+/* The top heap object.  This points into heap_objs[] or is NULL.
+   While this variable is NULL, no memory has been allocated. */
+
+struct heap_obj *top_heap_obj;
+
+/* This array holds information on all the heap objects.  The heap
+   objects are managed in LIFO fashion. */
+
+struct heap_obj heap_objs[MAX_HEAP_OBJS];
+
+/* This is the number of heap objects. */
+
+unsigned heap_obj_count;
+
+/* This variable is true iff the first heap object (heap_objs[0]) is
+   an object from the EXE file, that is, has not been allocated with
+   DosAllocMem. */
+
+char first_heap_obj_fixed;
+
+/* This is the default size for heap objects. */
+
+ULONG heap_obj_size;
+
+/* Address of the heap (first object) in the executable file. */
+
+ULONG heap_off;
+
+/* Base address of the stack object. */
+
+ULONG stack_base;
+
+/* End address of the stack object (address of first byte after the
+   stack object). */
+
+ULONG stack_end;
+
+/* Run debuggee in same session as the debugger. */
+
+BYTE debug_same_sess;
+
+/* Flag bits for debugging, set with the -! option. */
+
+ULONG debug_flags;
+
+/* If this variable is zero, if file names should not be truncated to
+   8.3 format.  If bit 0 is set, UNC pathnames are truncated to 8.3
+   format.  Bits 1 through 26 control truncation of file names on
+   drives A: through Z:.  The user can set this variable by putting
+   the -t option into the EMXOPT environment variable. */
+
+ULONG opt_trunc;
+
+/* Default drive: 0=none, "A".."Z", "a".."z": prepend this drive
+   letter. */
+
+BYTE opt_drive;
+
+/* The -x option is used for getting the old (0.8h) behavior of not
+   quoting arguments passed using the `MKS Korn shell' method (3rd
+   argument string starting with `~').  Expanding arguments in that
+   case was wrong. */
+
+BYTE opt_expand;
+
+/* The -q option forces quoting of all command line arguments passed
+   to child processes. */
+
+BYTE opt_quote;
+
+/* This handle is used for diagnostic output including error
+   messages. */
+
+ULONG errout_handle;
+
+/* This flag is TRUE if this is process is a forked process. */
+
+BYTE fork_flag;
+
+/* fork(): EBP of parent process. */
+
+ULONG fork_ebp;
+
+/* fork(): Low end of the stack. */
+
+ULONG fork_stack_page;
+
+/* fork(): Pointer to final data packet from parent process. */
+
+static struct fork_data_done *p_fork_done;
+
+/* Pointer to the PIB. */
+
+PIB *init_pib_ptr;
+
+/* This variable points to the main exception registration record of
+   emx.dll. */
+
+EXCEPTIONREGISTRATIONRECORD *exc_reg_ptr;
+
+/* The process ID of the process using this instance of emx.dll. */
+
+ULONG my_pid;
+
+/* Pointer to the command line. */
+
+char *startup_args;
+
+/* Pointer to the environment. */
+
+char *startup_env;
+
+/* Number of environment strings. */
+
+ULONG env_count;
+
+/* Number of arguments. */
+
+ULONG arg_count;
+
+/* Size of argument strings (bytes). */
+
+ULONG arg_size;
+
+/* The third argument string of the program. */
+
+char *argstr3;
+
+/* The name of the EXE file. */
+
+BYTE exe_name[257];
+
+/* The file handle used for reading from the EXE file if the heap is
+   being loaded from the EXE file. */
+
+HFILE exe_fhandle;
+
+/* This flag is true if the heap is loaded from the EXE file. */
+
+BYTE exe_heap;
+
+/* This flag is true if we should ignore too small a stack.  It is set
+   by the -I option. */
+
+static BYTE ignore_stack;
+
+/* Error message to be displayed by options(). */
+
+static const char *opt_errmsg;
+
+/* User flags, initially 0, set by __uflags(). */
+
+ULONG uflags;
+
+/* Set the following variable to TRUE to avoid using DosKillThread. */
+
+BYTE dont_doskillthread;
+
+/* The major and minor version numbers of OS/2. */
+
+ULONG version_major;
+ULONG version_minor;
+
+/* Define our own version of `_osmode' which is uninitialized; do not
+   use the library version which would add a non-shared page to
+   emx.dll, slowing down loading when it's already loaded. */
+
+unsigned char _osmode;
+
+
+/* Prototypes. */
+
+static void init_exit_list (void);
+static void options (const char *s, const char *errmsg);
+static void connect_fork (void);
+static void init2_fork (void);
+
+
+/* This REXX-callable entrypoint returns a string indicating the
+   revision index of emx.dll as integer. The number will be
+   incremented on each revision and is used only for comparing. */
+
+ULONG emx_revision (PCSZ name, LONG argc, const RXSTRING *argv,
+                    PCSZ queuename, PRXSTRING retstr)
+{
+  static char const revision[] = XSTR(REV_INDEX);
+
+  if (argc != 0)
+    return 1;
+  strcpy (retstr->strptr, revision);
+  retstr->strlength = strlen (revision);
+  return 0;
+}
+
+
+/* DLL initialization and termination function.  This function is
+   called by the system to initialize the DLL (if FLAG is zero) or to
+   terminate the DLL (if FLAG is one). */
+
+ULONG _DLL_InitTerm (ULONG mod_handle, ULONG flag)
+{
+  switch (flag)
+    {
+    case 0:                     /* Initialization */
+      init_heap ();
+      break;
+
+    case 1:                     /* Termination */
+#if 0
+      /* OS/2 does not terminate DLLs in the correct sequence under
+         certain circumstances.  It might happen that EMXLIBCS.DLL is
+         terminated *after* EMX.DLL, causing problems in functions of
+         EMX.DLL called by the termination code of EMXLIBCS.DLL.
+         Don't terminate EMX.DLL -- a memory leak is preferable to a
+         crash. */
+
+      pm_term ();
+      term_signal ();
+      term_process ();
+      term_tcpip ();
+      term_semaphores ();
+      term_memory ();
+#endif
+      break;
+    }
+  return 1;                     /* Success! */
+}
+
+
+/* Fetch the flags and the interface level from the layout table. */
+
+static void use_layout (void)
+{
+  layout_flags = layout->flags;
+  interface = (BYTE)(layout_flags >> 24);
+}
+
+
+/* Use the heap stored in the EXE file, if present. */
+
+static void use_heap (void)
+{
+  if (layout->heap_base == 0 || layout->heap_end == 0 || heap_obj_count != 0)
+    return;
+  heap_objs[0].base = layout->heap_base;
+  heap_objs[0].end = layout->heap_end;
+  if (layout->heap_brk != 0)
+    {
+      ULONG rc, size, flags;
+
+      /* There is a heap stored in the EXE file. */
+
+      heap_off = layout->heap_off;
+      heap_objs[0].brk = layout->heap_brk;
+
+      /* Check if the heap object maps the heap pages. */
+
+      size = 0x1000;
+      rc = DosQueryMem ((PVOID)heap_objs[0].base, &size, &flags);
+      if (rc == 0 && (flags & PAG_COMMIT))
+        {
+          ULONG next;
+
+          /* The heap pages are mapped by the heap object.  Decommit
+             those pages which are not preloaded to improve security
+             and to make sbrk() and brk() work. */
+
+          next = ROUND_PAGE (heap_objs[0].brk);
+          if (heap_objs[0].end > next)
+            setmem (next, heap_objs[0].end - next, PAG_DECOMMIT, 0);
+        }
+      else
+        {
+          ULONG action;
+
+          /* The heap pages are not mapped by the heap object.  We
+             have to use an exception handler and guard pages to load
+             the pages. */
+
+          rc = DosOpen (exe_name, &exe_fhandle, &action, 0, 0,
+                        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+                        (OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE
+                         | OPEN_FLAGS_RANDOM | OPEN_FLAGS_NOINHERIT), NULL);
+          if (rc != 0)
+            {
+              otext ("Cannot open EXE file\r\n");
+              quit (255);
+            }
+          /* Commit the guard pages. */
+          if (heap_objs[0].brk != heap_objs[0].base)
+            setmem (heap_objs[0].base, heap_objs[0].brk - heap_objs[0].base,
+                    PAG_COMMIT | PAG_GUARD | PAG_READ | PAG_WRITE, 0);
+          exe_heap = TRUE;
+        }
+    }
+  else
+    heap_objs[0].brk = heap_objs[0].base;
+  top_heap_obj = &heap_objs[0];
+  heap_obj_count = 1;
+  first_heap_obj_fixed = TRUE;
+
+  /* All dynamically heap objects will have at least the same size as
+     the heap object of the EXE file. */
+
+  heap_obj_size = heap_objs[0].end - heap_objs[0].base;
+}
+
+
+/* First part of initialization.  After return from initialize1(),
+   stacks will be switched and, if this process has been forked, data
+   will be copied from the parent process. */
+
+void initialize1 (void)
+{
+  TIB *tib_ptr;
+  ULONG rc, action;
+  PSZ str;
+  char *p;
+  size_t len;
+
+  __asm__ ("cld");
+
+  _osmode = 1;                  /* OS2_MODE */
+
+  use_layout ();
+
+  /* Get pointers to the TIB and PIB, and fetch environment pointers
+     and the PID from the PIB. */
+
+  DosGetInfoBlocks (&tib_ptr, &init_pib_ptr);
+  startup_args = init_pib_ptr->pib_pchcmd;
+  startup_env = init_pib_ptr->pib_pchenv;
+  my_pid = init_pib_ptr->pib_ulpid;
+
+  /* Get the version number of OS/2. */
+
+  version_major = querysysinfo (QSV_VERSION_MAJOR);
+  version_minor = querysysinfo (QSV_VERSION_MINOR);
+
+  /* Set `dont_doskillthread' depending on the version number of OS/2.
+     Assume that DosKillThread works in OS/2 2.11 and later. */
+
+  if (!(version_major > 20 || (version_major == 20 && version_minor >= 11)))
+    dont_doskillthread = TRUE;
+
+  /* Retrieve the name of the executable file of the application. */
+
+  rc = DosQueryModuleName (init_pib_ptr->pib_hmte,
+                           sizeof (exe_name), exe_name);
+  if (rc != 0)
+    exe_name[0] = 0;
+  exe_fhandle = (HFILE)(-1);
+
+  /* Initialize __clock(). */
+
+  get_clock (TRUE);
+
+  /* Get a pointer to the 3rd argument string.  Check whether we have
+     been forked. */
+
+  p = startup_args;
+  len = strlen (p);
+  p += len + 1;
+  len = strlen (p);
+  p += len + 1;
+  argstr3 = p;
+  if (*p == '^')
+    init_fork (p);
+
+  /* Set default values for options. */
+
+  heap_obj_size = HEAP_OBJ_SIZE;
+
+  /* Parse emx options put into the executable by emxbind. */
+
+  options (layout->options, "Invalid option in .exe file\r\n");
+
+  /* Parse emx options in the EMXOPT environment variable. */
+
+  rc = DosScanEnv ("EMXOPT", &str);
+  if (rc == 0)
+    options (str, "Invalid option in EMXOPT\r\n");
+
+  /* Get the stack base and end addresses. */
+
+  stack_base = (ULONG)tib_ptr->tib_pstack;
+  stack_end = (ULONG)tib_ptr->tib_pstacklimit;
+
+  /* Refuse to work if the stack is too small. */
+
+  if (stack_end - stack_base <= 16*1024 && !ignore_stack)
+    {
+      char buf[512];
+      ULONG written;
+
+      if (!pm_init ())
+        {
+          len = sprintf (buf, "emx.dll: Stack size too small.  Run\r\n"
+                         "  emxstack -f %s\r\n"
+                         "and try again.\r\n", exe_name);
+          DosWrite (2, buf, len, &written);
+        }
+      else
+        {
+          sprintf (buf, "Stack size too small.  Run \"emxstack -f %s\" "
+                   "and try again.", exe_name);
+          pm_message_box (buf);
+        }
+
+      quit (255);
+    }
+
+  /* Initialize errout_handle. */
+
+  if (debug_flags & DEBUG_STDERR)
+    {
+      rc = DosOpen ("con", &errout_handle, &action, 0, 0,
+                    OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+                    (OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE
+                     | OPEN_FLAGS_NOINHERIT),
+                    NULL);
+      if (rc != 0)
+        errout_handle = 2;      /* In case it was modified by DosOpen */
+    }
+
+  /* Initialize the user flags. */
+
+  uflags = 0;
+
+  /* Use the heap stored in the EXE file, if present. */
+
+  use_heap ();
+
+  /* Install the exit list procedure.  This should be done before
+     calling copy_fork() in order to be able to adjust the socket
+     reference counts if this process terminates prematurely. */
+
+  init_exit_list ();
+
+  /* If this process has been forked, connect to the parent process
+     and get the initial block of data.  Among other things, that
+     block contains a pointer to the lowest page of stack in use by
+     the parent process.  We set the stack pointer to that address
+     before copying the stack from the parent process.  As moving the
+     stack causes trouble with compiled code, initialization is split
+     into two parts, initialize1() and initialize2(), the stack being
+     switched between those parts. */
+
+  if (fork_flag)
+    connect_fork ();
+}
+
+
+/* Second part of initialization.  Here, initialization is continued
+   from initialize1(), after switching stacks and, if this process has
+   been forked, copying data from the parent process. */
+
+void initialize2 (void)
+{
+  init_exceptions ();
+  receive_signals ();
+  get_dbcs_lead ();
+  init_fileio ();
+  init_process ();
+  new_thread (1, NULL);
+  if (fork_flag)
+    init2_fork ();
+  else
+    init2_signal ();
+}
+
+
+/* This function is called from the startup code to initialize DLLs.
+   Dirty hack: We access our caller's parameters on the stack as
+   there's no space in dll0.s for pushing them. */
+
+void dll_init (layout_table *nl, ULONG ret_addr,
+               HMODULE hmod, ULONG flag)
+{
+  if (layout == NULL)
+    {
+      layout = nl;
+      use_layout ();
+    }
+
+  /* Register the DLL's data segment for fork(). */
+
+  if (nl->data_base < nl->data_end && nl->bss_base < nl->bss_end
+      && nl->bss_base == nl->data_end)
+    fork_register_mem (nl->data_base, nl->bss_end, hmod);
+  else
+    {
+      if (nl->data_base < nl->data_end)
+        fork_register_mem (nl->data_base, nl->data_end, hmod);
+      if (nl->bss_base < nl->bss_end)
+        fork_register_mem (nl->bss_base, nl->bss_end, hmod);
+    }
+  if (flag == 0)                /* Initialization */
+    fork_register_dll (hmod);
+}
+
+
+/* This is our exit list procedure. */
+
+static void APIENTRY exit_list_proc (ULONG term_code)
+{
+  exit_tcpip ();
+  DosExitList (EXLST_EXIT, exit_list_proc);
+}
+
+
+/* Install our exit list procedure.  This is always done, whether
+   sockets are used or not, to make it run after any exit list
+   procedure installed by the application.  If tcpip_init() installed
+   the exit list procedure, the invocation order would depend on
+   whether the application installs the exit list procedure before or
+   after the first call to tcpip_init(). */
+
+static void init_exit_list (void)
+{
+  ULONG rc;
+
+  /* Note: SO32DLL.DLL installs its exit list procedure with
+     invocation order 0x99.  Our exit list procedure should run before
+     SO32DLL's to be able to use SO32DLL.  Moreover, it should run
+     after any exit list procedure installed by the application, to
+     make any sockets available to that exit list procedure.  Assume
+     that the invocation orders of the application's exit list
+     procedures are less than 0x80 (0x80 through 0xff seem to be
+     reserved for OS/2). */
+
+  rc = DosExitList (EXLST_ADD | (0x7f << 8), exit_list_proc);
+  if (rc != 0)
+    error (rc, "DosExitList");
+}
+
+
+/* There's an error in an option.  Display an error message and abort.
+   `opt_errmsg' contains the error message, which depends on where the
+   options come from (emxbind or EMXOPT). */
+
+static void opt_error (void)
+{
+  otext (opt_errmsg);
+  quit (1);
+}
+
+
+/* Parse a numeric, decimal, unsigned argument for an option.  Return
+   the number and update *P which initially points to the beginning of
+   the argument to point to the first character after the number.  The
+   number must be terminated by a null character or whitespace.  On
+   error, display an error message and abort. */
+
+static ULONG opt_number (const char **p)
+{
+  const char *s;
+  ULONG n, d;
+  char flag;
+
+  s = *p;
+  flag = FALSE; n = 0;
+  if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+    {
+      /* Base 16 */
+      s += 2;
+      for (;;)
+        {
+          if (*s >= '0' && *s <= '9')
+            d = *s - '0';
+          else if (*s >= 'a' && *s <= 'f')
+            d = *s - 'a' + 10;
+          else if (*s >= 'A' && *s <= 'F')
+            d = *s - 'A' + 10;
+          else
+            break;
+          if (n >= 0x10000000)
+            opt_error ();
+          n = n * 16 + d;
+          flag = TRUE; ++s;
+        }
+    }
+  else
+    {
+      /* Base 10 */
+      while (*s >= '0' && *s <= '9')
+        {
+          /* This check for overflow isn't perfect -- it rejects some
+             valid numbers.  However, those numbers aren't valid
+             arguments, anyway. */
+
+          if (n >= 429496728)
+            opt_error ();
+          n = n * 10 + (*s - '0');
+          flag = TRUE; ++s;
+        }
+    }
+  if (!flag || (*s != 0 && *s != ' ' && *s != '\t'))
+    opt_error ();
+  *p = s;
+  return n;
+}
+
+
+#define ISLETTER(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+#define ISEND(c)    ((c) == 0 || (c) == ' ' || (c) == '\t')
+
+/* Parse options.  S points to the null-terminated string of options,
+   ERRMSG points to the error message to be used. */
+
+static void options (const char *s, const char *errmsg)
+{
+  char c;
+  ULONG n;
+
+  /* Make the pointer to the error message available to
+     opt_error(). */
+
+  opt_errmsg = errmsg;
+
+  /* Parse the options, one by one.  Options must be separated by
+     whitespace (blank or tab). */
+
+  do
+    {
+      /* Skip whitespace preceding the first option or following any
+         other option.  Return when reaching the end of the string. */
+
+      do
+        {
+          c = *s++;
+          if (c == 0)
+            return;
+        } while (c == ' ' || c == '\t');
+
+      /* All options start with `-'. */
+
+      if (c != '-')
+        opt_error ();
+
+      /* Parse the various options. */
+
+      c = *s++;
+      switch (c)
+        {
+        case 'c':
+
+          /* Suppress core dumps. */
+
+          nocore_flag = TRUE;
+          break;
+
+        case 'f':
+
+          /* This option was used for setting the maximum stack frame
+             size.  Parse the value, and discard it.  As there are
+             still some programs which have, say, -f0 set with
+             emxbind, we have to accept this option though the maximum
+             stack frame size is no longer used. */
+
+          n = opt_number (&s);
+          if (n != 0 && (n < 4 || n > 32768))
+            opt_error ();
+          break;
+
+        case 'h':
+
+          /* Set the number of file handles.  Note that DosSetMaxFH
+             cannot lower the number of file handles below the initial
+             value for this process (DosSetRelMaxFH can). */
+
+          n = opt_number (&s);
+          if (n < 10 || n > 65536)
+            opt_error ();
+          DosSetMaxFH (n);
+          break;
+
+        case 'n':
+
+          /* Don't display a harderror popup.  This is done by
+             terminating the process instead of returning
+             XCPT_CONTINUE_SEARCH from the exception handler. */
+
+          no_popup = TRUE;
+          break;
+
+        case 'q':
+
+          /* Quote all command line arguments passed to child
+             processes. */
+
+          opt_quote = TRUE;
+          break;
+
+        case 'r':
+
+          /* Set the default drive for path names starting with `/' or
+             `\'.  The argument of this option is a drive letter. */
+
+          if (ISLETTER (*s))
+            opt_drive = *s++;
+          else
+            opt_error ();
+          break;
+
+        case 't':
+
+          /* Truncate all components of certain pathnames to 8.3
+             format. `-t' enables truncation on all drives, `-t-'
+             disables truncation on all drives, `-tabc' enables
+             truncation on drives A, B, and C, `-t-abc' disables
+             truncation on drives A, B, and C.  UNC pathnames are
+             specified by the special `drive name' `/'. */
+
+          if (ISEND (*s))
+            opt_trunc = TRUNC_ALL;
+          else if (*s == '-')
+            {
+              ++s;
+              if (ISEND (*s))
+                opt_trunc = 0;
+              else
+                do
+                  {
+                    c = *s++;
+                    if (ISEND (c))
+                      break;
+                    if (ISLETTER (c))
+                      opt_trunc &= ~TRUNC_DRV (c);
+                    else if (c == '/')
+                      opt_trunc &= ~TRUNC_UNC;
+                    else
+                      opt_error ();
+                  } while (!ISEND (*s));
+            }
+          else
+            do
+              {
+                c = *s++;
+                if (ISLETTER (c))
+                  opt_trunc |= TRUNC_DRV (c);
+                else if (c == '/')
+                  opt_trunc |= TRUNC_UNC;
+                else
+                  opt_error ();
+              } while (!ISEND (*s));
+          break;
+
+        case 'x':
+
+          /* Expand all command line arguments passed with the `MKS
+             Korn shell' method to this process. */
+
+          opt_expand = TRUE;
+          break;
+
+        case 'E':
+
+          /* Run debugees in the same session as the debugger. */
+
+          debug_same_sess = TRUE;
+          break;
+
+        case 'K':
+
+          /* Don't use DosKillThread. */
+
+          dont_doskillthread = TRUE;
+          break;
+
+        case 'I':
+
+          /* Don't abort when the stack size is too small.  This is
+             required for old programs which assume that emx.dll
+             creates a private stack object if the stack size is too
+             small. */
+
+          ignore_stack = TRUE;
+          break;
+
+        case 'V':
+
+          /* Display the emx banner. */
+
+          otext ("emx " VERSION " (rev " XSTR (REV_INDEX) ")"
+                 " -- Copyright (c) 1992-2000 by Eberhard Mattes\r\n");
+          break;
+
+        case '!':
+
+          /* Set debugging flags.  The argument as a (decimal) number,
+             interpreted bitwise.  See emxdll.h for the meaning of the
+             bits (DEBUG_STDERR, for instance). */
+
+          debug_flags = opt_number (&s);
+          break;
+
+        default:
+
+          /* The option is not known, abort. */
+
+          opt_error ();
+        }
+    } while (*s == ' ' || *s == '\t');
+
+  /* If there are characters remaining after an option, complain and
+     abort. */
+
+  if (*s != 0)
+    opt_error ();
+}
+
+
+/* Parse the command line.  Store the argument strings at POOL (unless
+   POOL is NULL).  The pointers are stored at VEC (unless VEC is
+   NULL). */
+
+#define BEGIN    do {
+#define END      } while (0)
+#define WHITE(C) ((C) == ' ' || (C) == '\t')
+#define PUTC(C)  BEGIN ++arg_size; if (pool != NULL) *pool++ = (C); END
+#define PUTV     BEGIN ++arg_count; if (vec != NULL) *vec++ = pool; END
+
+static void parse_arg (char *pool, char **vec, const char *str1,
+                       const char *str3)
+{
+  const char *s;
+  char *flag_ptr;
+  int bs, quote;
+
+  arg_count = 0; arg_size = 0;
+
+  /* Look for the 3rd string -- if it starts with ~ we can get the
+     parsed argument words from that string and the following
+     strings. */
+
+  if (str3[0] == '~' && strcmp (str3 + 1, str1) == 0)
+    {
+      char flag;
+
+      if (opt_expand)
+        flag = _ARG_NONZERO;
+      else
+        flag = _ARG_NONZERO|_ARG_DQUOTE;
+      s = str3 + 1;
+      while (*s != 0)
+        {
+          if (*s == '~')
+            ++s;
+          PUTC (flag); PUTV;
+          do
+            {
+              PUTC (*s);
+            } while (*s++ != 0);
+        }
+    }
+  else
+    {
+      s = str1;
+
+      /* argv[0] contains the program name. */
+
+      PUTC (_ARG_NONZERO); PUTV;
+      do
+        {
+          PUTC (*s);
+        } while (*s++ != 0);
+
+      /* Now scan the arguments, one by one. */
+
+      for (;;)
+        {
+          /* Skip leading whitespace. */
+
+          while (WHITE (*s))
+            ++s;
+
+          /* Work is completed when reaching the end of the string. */
+
+          if (*s == 0)
+            break;
+
+          /* Flags will be stored to `*flag_ptr' while parsing the
+             current argument.  Initially, no flags are set. */
+
+          flag_ptr = pool;
+          PUTC (_ARG_NONZERO);
+          PUTV;
+          bs = 0; quote = 0;
+          for (;;)
+            {
+              if (*s == '"')
+                {
+                  /* Backslashes preceding a double quote character
+                     are treated specially: A backslash escapes either
+                     a backslash or a double quote character. */
+
+                  while (bs >= 2)
+                    {
+                      PUTC ('\\');
+                      bs -= 2;
+                    }
+                  if (bs & 1)
+                    PUTC ('"');
+                  else
+                    {
+                      /* The number of backslashes preceding the
+                         double quote character is even (including
+                         zero), therefore this double quote character
+                         starts or ends a quoted string. */
+
+                      quote = !quote;
+                      if (flag_ptr != NULL)
+                        *flag_ptr |= _ARG_DQUOTE;
+                    }
+
+                  /* We have eaten all backslashes. */
+
+                  bs = 0;
+                }
+              else if (*s == '\\')
+                {
+                  /* Instead of looking ahead to learn whether the
+                     backslash is followed by (backslashes and) a
+                     double quote character, we count the number of
+                     successive backslashes and consider them when
+                     processing another character. */
+
+                  ++bs;
+                }
+              else
+                {
+                  /* Process backslashes preceding this character. */
+
+                  while (bs != 0)
+                    {
+                      PUTC ('\\');
+                      --bs;
+                    }
+
+                  /* Whitespace ends the current argument unless we
+                     are inside a quoted string. */
+
+                  if (*s == 0 || (WHITE (*s) && !quote))
+                    break;
+                  PUTC (*s);
+                }
+              ++s;
+            }
+
+          /* Mark the end of the argument string. */
+
+          PUTC (0);
+        }
+    }
+
+  /* Mark the end of the vector of pointers to argument strings. */
+
+  if (vec != NULL)
+    *vec = NULL;
+}
+
+
+/* Build the table of environment pointers; don't store if VEC is
+   NULL. */
+
+static char **parse_env (char **vec)
+{
+  char *s;
+
+  env_count = 0;
+  s = startup_env;
+  while (*s != 0)
+    {
+      ++env_count;
+      if (vec != NULL)
+        *vec++ = s;
+      while (*s != 0)
+        ++s;
+      ++s;
+    }
+  if (vec != NULL)
+    *vec++ = NULL;
+  return vec;
+}
+
+
+/* Compute the number and size of argument strings and environment
+   strings. */
+
+void count_arg_env (void)
+{
+  parse_env (NULL);
+  parse_arg (NULL, NULL, startup_args, argstr3);
+}
+
+
+/* Build the tables of argument strings and environment strings. */
+
+void build_arg_env (char *str, char **vec)
+{
+  vec = parse_env (vec);
+  parse_arg (str, vec, startup_args, argstr3);
+}
+
+
+/* Semaphores for communicating with the parent process after a fork. */
+
+static HEV fork_req_sem;
+static HEV fork_ack_sem;
+
+/* Various values reveived from the parent process. */
+
+static ULONG fork_msize;
+static ULONG fork_addr;
+static ULONG fork_ppid;
+
+
+/* This process seems to have been forked off; parse the arguments
+   passed on the command line. */
+
+void init_fork (const char *s)
+{
+  ++s;                          /* Skip the caret */
+  if (!conv_hex8 (s, &fork_addr))
+    return;
+  s += 8;
+  if (*s != ' ')
+    return;
+  ++s;
+  if (!conv_hex8 (s, &fork_ppid))
+    return;
+  s += 8;
+  if (*s != 0)
+    return;
+  fork_flag = TRUE;
+}
+
+
+/* Final initializations for a forked process. */
+
+static void init2_fork (void)
+{
+  thread_data *td;
+
+  /* Copy the signal handlers from the shared memory object to the
+     thread data block for thread 1. */
+
+  td = threads[1];
+  memcpy (td->sig_table, p_fork_done->sig_actions, sizeof (td->sig_table));
+
+  /* Install socket handles inherited from the parent process. */
+
+  copy_fork_sock (p_fork_done);
+
+  /* Initalize other file handles.  This must be done after calling
+     copy_fork_sock()! */
+
+  fileio_fork_child (p_fork_done);
+
+  /* Now free the shared memory object, it's no longer needed. */
+
+  DosFreeMem ((void *)fork_addr);
+  p_fork_done = NULL;
+}
+
+
+/* Connect to the parent process and process the initial block of
+   data. */
+
+static void connect_fork (void)
+{
+  ULONG rc;
+  struct fork_data_init *pi;
+
+  rc = DosGetSharedMem ((void *)fork_addr, PAG_READ);
+  if (rc != 0)
+    {
+      error (rc, "DosGetSharedMem");
+      quit (255);
+    }
+
+  pi = (struct fork_data_init *)fork_addr;
+  fork_msize = pi->msize;
+
+  fork_req_sem = pi->req_sem;
+  rc = DosOpenEventSem (NULL, &fork_req_sem);
+  if (rc != 0)
+    {
+      error (rc, "DosOpenEventSem");
+      quit (255);
+    }
+
+  fork_ack_sem = pi->ack_sem;
+  rc = DosOpenEventSem (NULL, &fork_ack_sem);
+  if (rc != 0)
+    {
+      error (rc, "DosOpenEventSem");
+      quit (255);
+    }
+
+  heap_objs[0].brk = pi->brk;
+  if (heap_objs[0].brk != 0)
+    {
+      ULONG size;
+
+      size = heap_objs[0].brk - heap_objs[0].base;
+      if (size != 0)
+        setmem (heap_objs[0].base, size, PAG_DEFAULT | PAG_COMMIT, 0);
+    }
+
+  if (pi->stack_base != stack_base)
+    {
+      /* Moving the stack is no longer supported. */
+      error (0, "fork stack problem");
+      quit (255);
+    }
+  fork_stack_page = pi->stack_page;
+  fork_ebp = pi->reg_ebp;
+  umask_bits = pi->umask;
+  umask_bits1 = pi->umask1;
+  uflags = pi->uflags;
+}
+
+
+/* Copy data from the parent process. */
+
+void copy_fork (void)
+{
+  fork_data *p;
+  ULONG rc;
+  HMODULE hmod;
+  static HMODULE cache_hmod;    /* = NULLHANDLE */
+  static int cache_loaded;      /* = whatever (0) */
+
+  for (;;)
+    {
+      reset_event_sem (fork_req_sem);
+      DosPostEventSem (fork_ack_sem);
+      do
+        {
+          rc = DosWaitEventSem (fork_req_sem, 500);
+
+          /* Repeat if interrupted by a signal.  Repeat if timed out
+             and the parent process is still the same (that is, it is
+             still alive). */
+
+        } while (rc == ERROR_INTERRUPT
+                 || (rc == ERROR_TIMEOUT
+                     && init_pib_ptr->pib_ulppid == fork_ppid));
+      if (rc != 0)
+        {
+          error (rc, "DosWaitEventSem");
+          quit (255);
+        }
+
+      /* Don't move this assignment outside the loop, unless you make
+         `p' a volatile pointer. */
+
+      p = (fork_data *)fork_addr;
+
+      switch (p->req_code)
+        {
+        case FORK_REQ_DONE:
+          /* Last transaction. */
+          if (p->done.sock_count != 0)
+            {
+              /* To keep reference counts correct in case TCP/IP
+                 initialization fails, we have to initialize now. */
+
+              if (!tcpip_init_fork (&p->done))
+                quit (255);
+            }
+
+          /* Fork completed.  Don't free the shared memory object now,
+             as we need the information on signals and sockets later,
+             after proceeding with initializing. */
+
+          p_fork_done = &p->done;
+          DosPostEventSem (fork_ack_sem);
+
+          /* Note: Do not call close_event_sem() as these semaphores
+             have been opened with DosOpenEventSem, not created with
+             create_event_sem()! */
+
+          DosCloseEventSem (fork_req_sem);
+          DosCloseEventSem (fork_ack_sem);
+          return;
+
+        case FORK_REQ_DLL:
+          /* Load a DLL.  There's not much point in checking if the
+             module is already loaded (by querying the name for the
+             module handle) -- if it is already loaded, the following
+             code will be redundant. */
+
+          rc = load_module (p->dll.path, &hmod);
+          if (rc != 0)
+            {
+              error (rc, "DosLoadModule");
+              quit (255);
+            }
+          if (hmod != p->dll.hmod)
+            {
+              oprintf ("HMODULE mismatch: %u vs. %u\r\n",
+                       (unsigned)hmod, (unsigned)p->dll.hmod);
+              quit (255);
+            }
+          break;
+
+        case FORK_REQ_MEM:
+          /* Receive memory from parent process. */
+          if (p->mem.hmod != 0 && p->mem.hmod != cache_hmod)
+            {
+              cache_hmod = p->mem.hmod;
+              cache_loaded = fork_dll_registered (p->mem.hmod);
+            }
+          if (p->mem.hmod == 0 || cache_loaded)
+            memcpy ((void *)p->mem.address, p->mem.shared, p->mem.count);
+          break;
+
+        default:
+          /* Ignore unknown request codes. */
+          break;
+        }
+    }
+}
Index: trunk/src/emx/src/os2/keyboard.c
===================================================================
--- trunk/src/emx/src/os2/keyboard.c	(revision 18)
+++ trunk/src/emx/src/os2/keyboard.c	(revision 18)
@@ -0,0 +1,141 @@
+/* keyboard.c -- Read characters from the keyboard
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_KBD
+#include <os2emx.h>
+#include "emxdll.h"
+#include "clib.h"
+
+
+static UCHAR kbd_input_more;
+static UCHAR kbd_input_next;
+static KBDINFO kbd_info;        /* Must not cross a 64K boundary */
+static KBDKEYINFO kbd_inp;      /* Must not cross a 64K boundary */
+static UCHAR cgets_buf[256];    /* Must not cross a 64K boundary */
+
+
+#define MASK1 (KEYBOARD_BINARY_MODE | KEYBOARD_ASCII_MODE)
+#define MASK2 (MASK1 | KEYBOARD_ECHO_ON | KEYBOARD_ECHO_OFF)
+
+int kbd_input (UCHAR *dst, int binary_p, int echo_p, int wait_p,
+               int check_avail_p)
+{
+  int mask, old_mask = 0, status_changed, result;
+
+  if (kbd_input_more)
+    {
+      if (check_avail_p)
+        return TRUE;
+      kbd_input_more = FALSE;
+      if (dst != NULL) *dst = kbd_input_next;
+      return TRUE;
+    }
+
+  kbd_info.cb = sizeof (kbd_info);
+  status_changed = FALSE;
+  if (KbdGetStatus (&kbd_info, 0) == 0)
+    {
+      old_mask = kbd_info.fsMask;
+      mask = (binary_p ? KEYBOARD_BINARY_MODE : KEYBOARD_ASCII_MODE);
+      if ((old_mask & MASK1) != mask)
+        {
+          status_changed = TRUE;
+          kbd_info.fsMask = (kbd_info.fsMask & ~MASK2) | mask;
+          kbd_info.cb = sizeof (kbd_info);
+          KbdSetStatus (&kbd_info, 0);
+        }
+    }
+
+  do
+    {
+      if (check_avail_p)
+        KbdPeek (&kbd_inp, 0);
+      else
+        KbdCharIn (&kbd_inp, (wait_p ? IO_WAIT : IO_NOWAIT), 0);
+        break;
+    } while (!(check_avail_p || !wait_p
+               || (kbd_inp.fbStatus & KBDTRF_FINAL_CHAR_IN)));
+
+  if (kbd_inp.fbStatus & KBDTRF_FINAL_CHAR_IN)
+    {
+      result = TRUE;
+      if ((kbd_inp.chChar == 0 || kbd_inp.chChar == 0xe0)
+          && (kbd_inp.fbStatus & KBDTRF_EXTENDED_CODE))
+        {
+          kbd_inp.chChar = 0;   /* Override 0xe0 */
+          kbd_input_next = kbd_inp.chScan;
+          kbd_input_more = TRUE;
+        }
+      else if (echo_p)
+        {
+          UCHAR c;
+          ULONG nwritten;
+
+          c = kbd_inp.chChar;
+          DosWrite (1, &c, 1, &nwritten);
+        }
+      if (dst != NULL) *dst = kbd_inp.chChar;
+    }
+  else
+    result = FALSE;
+
+  if (status_changed)
+    {
+      kbd_info.cb = sizeof (kbd_info);
+      if (KbdGetStatus (&kbd_info, 0) == 0)
+        {
+          kbd_info.fsMask = (kbd_info.fsMask & ~MASK2) | (old_mask & MASK1);
+          kbd_info.cb = sizeof (kbd_info);
+          KbdSetStatus (&kbd_info, 0);
+        }
+    }
+
+  return result;
+}
+
+
+void conin_string (UCHAR *buf)
+{
+  int i, buf_len;
+  STRINGINBUF sib;
+  USHORT rc;
+
+  buf_len = buf[0];
+  memcpy (cgets_buf, buf + 2, buf_len);
+  for (i = 0; i < buf_len; ++i)
+    if (cgets_buf[i] == 0 || cgets_buf[i] == '\r')
+      break;
+  if (i >= buf_len)
+    i = 0;
+  cgets_buf[i] = '\r';
+  sib.cchIn = (USHORT)i;
+  sib.cb = (USHORT)buf_len;
+  rc = KbdStringIn (cgets_buf, &sib, IO_WAIT, 0);
+  i = (rc == 0 ? sib.cchIn : 0);
+  buf[1] = (UCHAR)i;
+  memcpy (buf + 2, cgets_buf, buf_len);
+  buf[i + 2] = '\r';
+}
Index: trunk/src/emx/src/os2/makefile
===================================================================
--- trunk/src/emx/src/os2/makefile	(revision 18)
+++ trunk/src/emx/src/os2/makefile	(revision 18)
@@ -0,0 +1,145 @@
+#
+# /emx/src/os2/makefile
+#
+# Copyright (c) 1992-1998 by Eberhard Mattes
+#
+# This file is part of emx.
+#
+# emx is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emx is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emx; see the file COPYING.  If not, write to the
+# the Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+# As special exception, emx.dll can be distributed without source code
+# unless it has been changed.  If you modify emx.dll, this exception
+# no longer applies and you must remove this paragraph from all source
+# files for emx.dll.
+#
+
+
+.SUFFIXES: .obj .asm .c
+
+DLL=\emx\dll\ #
+#DLL=\emx\test\ #
+I=d:\emx\include\ #
+MAP=d:\emx\etc\ #
+LIB=d:\emx\lib\ #
+LIBS=c.lib $(LIB)mt\sys.lib $(LIB)os2.lib
+
+ML=ml -c -Cp -W3 -WX -VM -nologo -Zi
+CC=gcc
+CFLAGS=-c -mprobe -fstack-check -O -g -Wall -Werror
+
+.asm.obj:
+	$(ML) $<
+
+.c.obj:
+	$(CC) $(CFLAGS) $<
+	emxomf -d $*.o
+
+default:	all
+all:		emx emxio
+emx:		$(DLL)emx.dll
+emxio:		$(DLL)emxio.dll
+
+c.lib:	$(LIB)mt\c.lib
+	copy $(LIB)mt\c.lib c.lib
+	emxomfar d c.lib crt1 nlsctype
+
+OBJECTS =	emxdll.obj doscall.obj syscall.obj init.obj memory.obj \
+		process.obj select.obj signal.obj time.obj fileio.obj \
+		ptrace.obj core.obj termio.obj keyboard.obj errors.obj \
+		utils.obj tcpip.obj pm.obj wrapper.obj \
+		xf86sup.obj profil.obj
+
+$(DLL)emx.dll:	$(OBJECTS) $(LIBS) emxdll.def
+	link386 /nol /noi $(OBJECTS), $(DLL)emx.dbg, $(MAP)emx /map, $(LIBS), \
+		emxdll /nod /deb
+	-emxload -qw
+	link386 /nol /noi $(OBJECTS), $(DLL)emx.dll, $(MAP)emx /map, $(LIBS), \
+		emxdll /nod
+
+emxdll.obj:	emxdll.asm emxdll.inc
+
+core.obj: core.c emxdll.h $(I)sys/user.h reg.h clib.h
+
+doscall.obj: doscall.c emxdll.h
+
+syscall.obj: syscall.c emxdll.h tcpip.h version.h $(I)sys/timeb.h \
+		$(I)sys/ulimit.h $(I)sys/nls.h
+
+fileio.obj: fileio.c emxdll.h files.h $(I)sys/fcntl.h $(I)sys/errno.h \
+		clib.h $(I)sys/types.h $(I)sys/stat.h $(I)sys/ioctl.h \
+		$(I)sys/termio.h $(I)sys/time.h $(I)emx/syscalls.h \
+		$(I)sys/nls.h
+
+init.obj: init.c emxdll.h clib.h version.h $(I)emx/startup.h
+
+memory.obj: memory.c emxdll.h $(I)sys/builtin.h $(I)sys/fmutex.h
+
+pm.obj: pm.c emxdll.h
+
+process.obj: process.c emxdll.h files.h clib.h \
+		$(I)sys/signal.h $(I)sys/errno.h $(I)sys/wait.h \
+		$(I)sys/process.h $(I)sys/ptrace.h $(I)emx/syscalls.h \
+		$(I)sys/uflags.h
+
+ptrace.obj: ptrace.c $(I)sys/signal.h $(I)sys/ptrace.h $(I)sys/user.h \
+		reg.h $(I)sys/errno.h $(I)sys/uflags.h emxdll.h clib.h
+
+select.obj: select.c emxdll.h files.h select.h tcpip.h clib.h \
+		$(I)sys/termio.h $(I)sys/errno.h $(I)sys/types.h \
+		$(I)emx/syscalls.h
+
+signal.obj: signal.c emxdll.h wrapper.h \
+		$(I)sys/signal.h $(I)sys/errno.h $(I)sys/uflags.h \
+		$(I)emx/syscalls.h
+
+tcpip.obj: tcpip.c emxdll.h files.h tcpip.h select.h clib.h $(I)sys/errno.h \
+		$(I)sys/types.h $(I)sys/stat.h $(I)sys/ioctl.h \
+		$(I)sys/fcntl.h $(I)sys/socket.h $(I)sys/so_ioctl.h \
+		$(I)emx/syscalls.h \
+		$(I)net/route.h $(I)net/if.h $(I)net/if_arp.h $(I)netdb.h
+
+termio.obj: termio.c emxdll.h files.h clib.h $(I)sys/errno.h $(I)sys/fcntl.h \
+		$(I)sys/signal.h $(I)sys/ioctl.h $(I)sys/termio.h $(I)termios.h
+
+keyboard.obj: keyboard.c emxdll.h clib.h
+
+time.obj: time.c emxdll.h $(I)limits.h $(I)sys/timeb.h $(I)sys/time.h
+
+errors.obj: errors.c emxdll.h $(I)sys/errno.h
+
+utils.obj: utils.c emxdll.h clib.h $(I)sys/nls.h
+
+xf86sup.obj: xf86sup.c xf86sup.h files.h select.h emxdll.h clib.h \
+		$(I)sys/errno.h $(I)sys/fcntl.h $(I)sys/ioctl.h \
+		$(I)sys/so_ioctl.h $(I)sys/types.h $(I)sys/termio.h \
+		$(I)termios.h
+
+profil.obj: profil.c profil.h emxdll.h clib.h $(I)emx/syscalls.h
+
+wrapper.obj: wrapper.c wrapper.h $(I)os2thunk.h
+
+$(DLL)emxio.dll: emxio.obj emxio.def
+	link386 /nol emxio, $(DLL)emxio.dll, $(MAP)emxio /map,, emxio
+
+emxio.obj: emxio.asm emxdll.inc
+
+clean:
+	-del *.obj
+	-del c.lib
+
+realclean: clean
+
+# End of /emx/src/os2/makefile
Index: trunk/src/emx/src/os2/memory.c
===================================================================
--- trunk/src/emx/src/os2/memory.c	(revision 18)
+++ trunk/src/emx/src/os2/memory.c	(revision 18)
@@ -0,0 +1,582 @@
+/* memory.c -- Memory management
+   Copyright (c) 1994-1996 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#include <sys/uflags.h>
+#include "emxdll.h"
+
+/* This is the size of one object for emx.dll's private memory
+   pool. */
+
+#define PRIVATE_OBJECT_SIZE     0x100000
+
+/* Up to this many objects of the above size will be allocated. */
+
+#define MAX_PRIVATE_OBJECTS     16
+
+/* This is the maximum number of memory objects registered with
+   register_obj(). */
+
+#define MAX_OBJECTS     (MAX_HEAP_OBJS + MAX_PRIVATE_OBJECTS)
+
+/* This header precedes blocks allocated with DosSubAllocMem. */
+
+struct subhdr
+{
+  void *object;
+  ULONG size;
+};
+
+/* Base addresses of emx.dll's private memory objects. */
+
+static void *private_objects[MAX_PRIVATE_OBJECTS];
+
+/* Number of private memory objects. */
+
+static int private_objects_count;
+
+/* Mutex semaphore for protecting the heap. */
+
+static _fmutex heap_fmutex;
+
+/* Number of memory objects registered with register_obj(). */
+
+static ULONG object_count;
+
+/* Memory objects registered with register_obj(). */
+
+static void *object_table[MAX_OBJECTS];
+
+
+/* Register a memory object. */
+
+static void register_obj (void *base)
+{
+  /* This cannot happen unless someone increases the number of
+     allocate_obj_above() and register_obj() calls and forgets to
+     update MAX_OBJECTS. */
+
+  if (object_count >= MAX_OBJECTS)
+    {
+      oprintf ("Too many memory objects\r\n");
+      quit (255);
+    }
+  object_table[object_count++] = base;
+}
+
+
+/* Allocate and register a memory object of SIZE bytes with allocation
+   flags FLAGS.  The object must not be located below MIN_ADDR.
+   Return a pointer to the memory object.  Return NULL on error. */
+
+static void *allocate_obj_above (ULONG size, ULONG flags, ULONG min_addr)
+{
+  ULONG rc;
+  void *base, *ret;
+
+  rc = DosAllocMem (&base, size, flags);
+  if (rc != 0)
+    return NULL;
+  if ((ULONG)base > min_addr)
+    {
+      register_obj (base);
+      return base;
+    }
+
+  /* The memory object is located below MIN_ADDR.  Recurse until we
+     get an appropriate object or until we run out of memory. */
+
+  ret = allocate_obj_above (size, flags, min_addr);
+
+  /* We got a suitable object.  Free the bad one. */
+
+  DosFreeMem (base);
+  return ret;
+}
+
+
+static void free_obj (void *p)
+{
+  ULONG i;
+
+  for (i = 0; i < object_count; ++i)
+    if (object_table[i] == p)
+      break;
+  if (i >= object_count)
+    {
+      oprintf ("Attempt to free unknown object %x\r\n", (ULONG)p);
+      quit (255);
+    }
+  DosFreeMem (p);
+  while (i < object_count)
+    {
+      object_table[i] = object_table[i+1];
+      ++i;
+    }
+  --object_count;
+}
+
+
+/* Free all memory objects registered with register_obj(). */
+
+void term_memory (void)
+{
+  while (object_count != 0)
+    free_obj (object_table[0]);
+}
+
+
+/* Call DosSetMem.  If ERROR is -1, return for any error code.
+   Otherwise, abort if the error code is nonzero and not equal to
+   ERROR. */
+
+ULONG setmem (ULONG base, ULONG size, ULONG flags, ULONG error)
+{
+  ULONG rc;
+
+  if (debug_flags & DEBUG_SETMEM)
+    oprintf ("Set memory: %.8x %.8x %.8x\r\n",
+             (unsigned)base, (unsigned)size, (unsigned)flags);
+  rc = DosSetMem ((void *)base, size, flags);
+  if (rc != 0 && error != (ULONG)-1 && rc != error)
+    {
+      if (rc == 8)
+        otext ("Out of swap space\r\n");
+      else
+        oprintf ("DosSetMem failed, error code = 0x%.8x\r\n", (unsigned)rc);
+      quit (255);
+    }
+  return rc;
+}
+
+
+/* Allocate a block of memory of SIZE bytes from emx.dll's private
+   memory pool.  The address of the block is stored to *MEM.  Return
+   the OS/2 error code. */
+
+ULONG private_alloc (void **mem, ULONG size)
+{
+  ULONG rc;
+  int i;
+  void *obj, *sub;
+
+  rc = ERROR_DOSSUB_NOMEM;
+  for (i = private_objects_count - 1; i >= 0; --i)
+    {
+      rc = DosSubAllocMem (private_objects[i], &sub,
+                           size + sizeof (struct subhdr));
+      if (rc != ERROR_DOSSUB_NOMEM)
+        break;
+    }
+  if (rc == ERROR_DOSSUB_NOMEM && private_objects_count < MAX_PRIVATE_OBJECTS)
+    {
+      rc = DosAllocMem (&obj, PRIVATE_OBJECT_SIZE, PAG_READ | PAG_WRITE);
+      if (rc != 0)
+        return rc;
+      register_obj (obj);
+      rc = DosSubSetMem (obj,
+                         DOSSUB_INIT | DOSSUB_SPARSE_OBJ | DOSSUB_SERIALIZE,
+                         PRIVATE_OBJECT_SIZE);
+      if (rc != 0)
+        return rc;
+      i = private_objects_count++;
+      private_objects[i] = obj;
+      rc = DosSubAllocMem (private_objects[i], &sub,
+                           size + sizeof (struct subhdr));
+    }
+  if (rc != 0)
+    return rc;
+  ((struct subhdr *)sub)->size = size;
+  ((struct subhdr *)sub)->object = private_objects[i];
+  *mem = (void *)((char *)sub + sizeof (struct subhdr));
+  return 0;
+}
+
+
+/* Allocate a block of memory of SIZE bytes from emx.dll's private
+   memory pool.  Return the address of the block.  Abort on error. */
+
+void *checked_private_alloc (ULONG size)
+{
+  void *mem;
+  ULONG rc;
+
+  rc = private_alloc (&mem, size);
+  if (rc != 0)
+    {
+      oprintf ("private_alloc failed, error code = 0x%.8x\r\n", (unsigned)rc);
+      quit (255);
+    }
+  return mem;
+}
+
+
+/* Deallocate a block of memory.  MEM must have been returned by
+   checked_private_alloc() or private_alloc(). */
+
+ULONG private_free (void *mem)
+{
+  struct subhdr *hdr = ((struct subhdr *)mem) - 1;
+  return DosSubFreeMem (hdr->object, (void *)hdr,
+                        hdr->size + sizeof (struct subhdr));
+}
+
+
+/* Initialize the heap of the application.  This function is called
+   from _DLL_InitTerm(). */
+
+void init_heap (void)
+{
+  _fmutex_create (&heap_fmutex, 0);
+}
+
+
+/* Expand the top heap object by INCR bytes.  INCR is a positive
+   number.  Return the previous break address or 0 (error). */
+
+static ULONG expand_heap_obj_by (ULONG incr)
+{
+  ULONG rc, old_brk, new_brk, addr, size, rest;
+
+  old_brk = top_heap_obj->brk;
+  new_brk = old_brk + incr;
+
+  if (new_brk < top_heap_obj->base || new_brk > top_heap_obj->end)
+    return 0;
+
+  addr = old_brk;
+  size = incr;
+  if (addr & 0xfff)
+    {
+      rest = 0x1000 - (addr & 0xfff);
+      if (rest >= size)
+        size = 0;
+      else
+        {
+          size -= rest;
+          addr += rest;
+        }
+    }
+  if (size != 0)
+    {
+      rc = setmem (addr, size, PAG_DEFAULT | PAG_COMMIT, (ULONG)-1);
+      if (rc != 0)
+        return 0;
+    }
+  top_heap_obj->brk = new_brk;
+  return old_brk;
+}
+
+
+/* Shrink the top heap object by DECR bytes.  DECR is a positive
+   number.  Return the previous break address or 0 (error). */
+
+ULONG shrink_heap_obj_by (ULONG decr)
+{
+  ULONG rc, old_brk, new_brk, addr, high;
+
+  old_brk = top_heap_obj->brk;
+  new_brk = old_brk - decr;
+
+  if (new_brk < top_heap_obj->base || new_brk > top_heap_obj->end)
+    return 0;
+
+  addr = (new_brk + 0xfff) & ~0xfff;
+  high = (top_heap_obj->brk + 0xfff) & ~0xfff;
+  if (high > addr)
+    {
+      rc = setmem (addr, high - addr, PAG_DECOMMIT, (ULONG)-1);
+      if (rc != 0)
+        return 0;
+    }
+  top_heap_obj->brk = new_brk;
+  return old_brk;
+}
+
+
+/* Expand the heap by INCR bytes.  INCR is a positive number.  Return
+   the base address of the expansion or 0 (error). */
+
+static ULONG expand_heap_by (ULONG incr, ULONG sbrk_model)
+{
+  unsigned old_obj_count;
+  ULONG base, size;
+
+  old_obj_count = heap_obj_count;
+
+  /* Allocate the first object if not yet done. */
+
+  if (heap_obj_count == 0)
+    {
+      size = heap_obj_size;
+      if (size == 0)
+        {
+          /* Apparently emx_init has not been called.  This happens if
+             emx.dll is used by a DLL which is used by a process which
+             does not use emx.dll.  Use the default heap size of
+             32MB. */
+
+          size = HEAP_OBJ_SIZE;
+        }
+      if (incr > size)
+        size = (incr + 0xffff) & ~0xffff;
+
+      base = (ULONG)allocate_obj_above (size, PAG_READ | PAG_WRITE, 0);
+      if (base == 0)
+        return 0;
+      heap_objs[0].base = base;
+      heap_objs[0].brk = base;
+      heap_objs[0].end = base + size;
+      heap_obj_count = 1;
+      top_heap_obj = &heap_objs[0];
+    }
+
+  /* Now we have at least one heap object.  Check for arithmetic
+     overflow. */
+
+  if (top_heap_obj->brk + incr < top_heap_obj->base)
+    {
+      /* Overflow.  If we've just allocated the first heap object,
+         deallocate it again unless memory must be allocated
+         contiguously. */
+
+      if (old_obj_count == 0 && sbrk_model != _UF_SBRK_CONTIGUOUS)
+        {
+          free_obj ((void *)heap_objs[0].base);
+          heap_obj_count = 0;
+          top_heap_obj = NULL;
+        }
+      return 0;                 /* Failure */
+    }
+
+  /* Check whether we need another heap object.  Allocate one if we
+     need one and are allowed to allocate one.  This should not happen
+     if we just allocated the first one above. */
+
+  if (top_heap_obj->brk + incr > top_heap_obj->end)
+    {
+      /* We need another heap object.  Fail if we are not allowed to
+         allocate non-contiguous memory or if we already have the
+         maximum number of heap objects. */
+
+      if (sbrk_model == _UF_SBRK_CONTIGUOUS || heap_obj_count >= MAX_HEAP_OBJS)
+        return 0;
+
+      /* Allocate at least heap_obj_size (or 32MB if uninitialized)
+         bytes.  The new object must be located above the currently
+         top one. */
+
+      size = heap_obj_size != 0 ? heap_obj_size : HEAP_OBJ_SIZE;
+      if (incr > size)
+        size = (incr + 0xffff) & ~0xffff;
+
+      for (;;)
+        {
+          if (sbrk_model == _UF_SBRK_ARBITRARY)
+            base = (ULONG)allocate_obj_above (size, PAG_READ | PAG_WRITE, 0);
+          else
+            base = (ULONG)allocate_obj_above (size, PAG_READ | PAG_WRITE,
+                                              top_heap_obj->end);
+          if (base != 0)
+            break;
+
+          /* If we're out of virtual address space, halve the size and
+             try again until allocation succeeds.  Of course, don't
+             attempt to allocate less than INCR bytes. */
+
+          size /= 2;
+          if (size < incr)
+            return 0;
+        }
+
+      top_heap_obj = &heap_objs[heap_obj_count++];
+      top_heap_obj->base = base;
+      top_heap_obj->brk = base;
+      top_heap_obj->end = base + size;
+    }
+
+  /* Now top_heap_obj points to an object which has enough space.
+     Commit memory as required.  expand_heap_obj() returns the top
+     object's break address, which is the base address of the
+     expansion as an object might have been added. */
+
+  return expand_heap_obj_by (incr);
+}
+
+
+/* Shrink the heap to the new break address NEW_BRK.  Return the
+   previous break address or 0 (error). */
+
+static ULONG shrink_heap_to (ULONG new_brk)
+{
+  unsigned obj;
+  ULONG old_brk;
+
+  /* Find the heap object containing the new break address.  Fail if
+     there is no such heap object.  Note that the new break address
+     must not be beyond the heap object current break address, that
+     is, we cannot shrink the heap (by deallocating objects) and grow
+     a heap object in one step. */
+
+  for (obj = 0; obj < heap_obj_count; ++obj)
+    if (heap_objs[obj].base <= new_brk
+        && heap_objs[obj].brk >= new_brk)
+      break;
+
+  if (obj >= heap_obj_count)
+    return 0;
+
+  /* We have at least one heap object, OBJ, so this is safe. */
+
+  old_brk = top_heap_obj->brk;
+
+  /* Free objects which are between the new break address and the old
+     one.  Fail if there are such objects and _UF_SBRK_CONTIGUOUS is
+     selected. */
+
+  if (obj != heap_obj_count - 1)
+    {
+      if ((uflags & _UF_SBRK_MODEL) == _UF_SBRK_CONTIGUOUS)
+        return 0;
+      while (heap_obj_count - 1 > obj)
+        {
+          heap_obj_count -= 1;
+          free_obj ((void *)heap_objs[heap_obj_count].base);
+          heap_objs[heap_obj_count].base = 0;
+        }
+      top_heap_obj = &heap_objs[heap_obj_count-1];
+    }
+
+  if (new_brk == top_heap_obj->base)
+    {
+      /* The top object is shrunk to zero bytes, deallocate it and
+         bump NEW_BRK back to the previous object.  If
+         _UF_SBRK_CONTIGUOUS is selected and the (only) object is
+         shrunk to 0 bytes, it will be kept anyway to avoid breaking
+         programs which depend on the object keeping its address:
+
+            p = sbrk (1000);
+            sbrk (-1000);
+            assert (sbrk (1000) == p);
+
+         The assertion should not fail.  However, programs which
+         select _UF_SBRK_MONOTONOUS or _UF_SBRK_ARBITRARY should be
+         prepared for failure of the assertion.  Consider the
+         following code:
+
+            sbrk (1000);
+            p = sbrk (0);
+            sbrk (-1000);
+            brk (p);
+
+         Here, brk() may fail due to deallocation of the top
+         object. */
+
+      if (obj != 0 || (!first_heap_obj_fixed
+                       && (uflags & _UF_SBRK_MODEL) != _UF_SBRK_CONTIGUOUS))
+        {
+          heap_obj_count -= 1;
+          free_obj ((void *)heap_objs[heap_obj_count].base);
+          heap_objs[heap_obj_count].base = 0;
+
+          if (heap_obj_count == 0)
+            top_heap_obj = NULL;
+          else
+            {
+              top_heap_obj = &heap_objs[heap_obj_count-1];
+              new_brk = top_heap_obj->brk;
+            }
+        }
+    }
+
+  /* Now decommit unused pages of the top heap object, if there is
+     one. */
+
+  if (heap_obj_count > 0
+      && shrink_heap_obj_by (top_heap_obj->brk - new_brk) == 0)
+    return 0;
+  return old_brk;
+}
+
+
+/* Shrink the heap by DECR bytes.  DECR is a positive number.  Return
+   the previous break address or 0 (error). */
+
+ULONG shrink_heap_by (ULONG decr, ULONG sbrk_model)
+{
+  if (heap_obj_count == 0)
+    return 0;
+  if (top_heap_obj->brk - decr < top_heap_obj->base)
+    return 0;
+  return shrink_heap_to (top_heap_obj->brk - decr);
+}
+
+
+/* This function implements the __sbrk() system call. */
+
+long do_sbrk (long incr)
+{
+  ULONG base;
+
+  if (_fmutex_request (&heap_fmutex, _FMR_IGNINT) != 0)
+    return -1;
+
+  if (incr >= 0)
+    base = expand_heap_by (incr, uflags & _UF_SBRK_MODEL);
+  else
+    base = shrink_heap_by (-incr, uflags & _UF_SBRK_MODEL);
+
+  if (_fmutex_release (&heap_fmutex) != 0)
+    return -1;
+  return base != 0 ? (long)base : -1;
+}
+
+
+/* This function implements the __brk() system call. */
+
+long do_brk (ULONG brkp)
+{
+  ULONG base;
+
+  if (_fmutex_request (&heap_fmutex, _FMR_IGNINT) != 0)
+    return -1;
+
+  if (heap_obj_count == 0)
+    base = 0;
+  else if (brkp >= top_heap_obj->brk && brkp <= top_heap_obj->end)
+    base = expand_heap_obj_by (brkp - top_heap_obj->brk);
+  else if (brkp >= top_heap_obj->base && brkp < top_heap_obj->brk)
+    base = shrink_heap_obj_by (top_heap_obj->brk - brkp);
+  else
+    base = shrink_heap_to (brkp);
+
+  if (_fmutex_release (&heap_fmutex) != 0)
+    return -1;
+  return base != 0 ? 0 : -1;
+}
Index: trunk/src/emx/src/os2/pm.c
===================================================================
--- trunk/src/emx/src/os2/pm.c	(revision 18)
+++ trunk/src/emx/src/os2/pm.c	(revision 18)
@@ -0,0 +1,102 @@
+/* pm.c -- Presentation Manager stuff
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSMODULEMGR
+#define INCL_DOSSESMGR
+#define INCL_DOSPROCESS
+#define INCL_WINWINDOWMGR
+#include <os2emx.h>
+#include "emxdll.h"
+
+static HMODULE hmod_pmwin;
+static char pm_initialized;
+
+
+static HAB (*p_WinInitialize) (ULONG fsOptions);
+static HMQ (*p_WinCreateMsgQueue) (HAB hab, LONG cmsg);
+static ULONG (*p_WinMessageBox) (HWND hwndParent, HWND hwndOwner, PCSZ pszText,
+    PCSZ pszCaption, ULONG idWindow, ULONG flStyle);
+
+
+#define LOAD_PMWIN(ord,var) \
+    (DosQueryProcAddr (hmod_pmwin, ord, NULL, (PPFN)var) != 0)
+
+int pm_init (void)
+{
+  HAB hab;
+  HMQ hmq;
+  HMODULE hmod_pmwin;
+  char obj[9];
+
+  /* Loading PMWIN.DLL starts the Presentation Manager.  We don't want
+     to do this when running a non-PM program from the OS/2 recovery
+     command line.  Strangely enough, WinInitialize succeeds for
+     non-PM programs run from the OS/2 recovery command line. */
+
+  if (init_pib_ptr->pib_ultype != SSF_TYPE_PM)
+    return FALSE;
+
+  /* Dynamically load PMWIN.DLL.  If references to PMWIN.DLL were made
+     at link time, programs using EMX.DLL could not be used when
+     booting from diskette and with RUN= of config.sys. */
+
+  if (DosLoadModule (obj, sizeof (obj), "PMWIN", &hmod_pmwin) != 0)
+    return FALSE;
+
+  if (LOAD_PMWIN (763, &p_WinInitialize)
+      || LOAD_PMWIN (716, &p_WinCreateMsgQueue)
+      || LOAD_PMWIN (789, &p_WinMessageBox))
+    {
+      DosFreeModule (hmod_pmwin);
+      return FALSE;
+    }
+  pm_initialized = TRUE;
+
+  hab = p_WinInitialize (0);
+  if (hab == NULLHANDLE) return FALSE;
+  hmq = p_WinCreateMsgQueue (hab, 0);
+  return hmq != NULLHANDLE;
+}
+
+
+/* Unload any DLLs loaded by pm_init(). */
+
+void pm_term (void)
+{
+  if (pm_initialized)
+    {
+      pm_initialized = FALSE;
+      DosFreeModule (hmod_pmwin);
+    }
+}
+
+
+void pm_message_box (PCSZ text)
+{
+  if (p_WinMessageBox != NULL)
+    p_WinMessageBox (HWND_DESKTOP, HWND_DESKTOP, text, "emx.dll", 0,
+                     MB_MOVEABLE | MB_OK | MB_ICONHAND);
+}
Index: trunk/src/emx/src/os2/process.c
===================================================================
--- trunk/src/emx/src/os2/process.c	(revision 18)
+++ trunk/src/emx/src/os2/process.c	(revision 18)
@@ -0,0 +1,1818 @@
+/* process.c -- Manage processes
+   Copyright (c) 1993-2000 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSPROCESS
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSSESMGR
+#define INCL_DOSMODULEMGR
+#define INCL_DOSQUEUES
+#define INCL_DOSERRORS
+#define INCL_DOSDEVIOCTL        /* For files.h */
+#include <os2emx.h>
+#include <os2thunk.h>
+#include <emx/syscalls.h>
+#include <sys/signal.h>
+#include <sys/errno.h>
+#include <sys/wait.h>
+#include <sys/process.h>
+#include <sys/ptrace.h>
+#include <sys/uflags.h>
+#include "emxdll.h"
+#include "files.h"
+#include "clib.h"
+
+/* Maximum sizes of various buffers and tables. */
+
+#define MAX_THREADS     1024    /* Number of threads */
+#define MAX_PROCESSES   256     /* Number of child processes */
+#define FORK_REGMEM_MAX 256     /* Number of DLLs supported by fork() */
+#define FORK_REGDLL_MAX 256     /* Number of DLLs supported by fork() */
+
+/* Values for the `status' field of `struct process'. */
+
+#define PS_FREE         0       /* Empty slot */
+#define PS_PROCESS      1       /* Child is a child process */
+#define PS_SESSION      2       /* Child is a session */
+#define PS_ZOMBIE       3       /* Process ended, return code available */
+#define PS_ATTACH       4       /* Attached debuggee */
+
+/* Bits for the `flags' field of `struct process'. */
+
+#define PF_SYNC         0x0001  /* Synchronous child process */
+#define PF_DEBUG        0x0002  /* Child process is being debugged */
+#define PF_WAIT         0x0004  /* wait() status available */
+
+
+/* `process_table' is protected by a Mutex semaphore.  These macros
+   are used for requesting and releasing that semaphore. */
+
+#define LOCK_PROCESS   request_mutex (process_access)
+#define UNLOCK_PROCESS DosReleaseMutexSem (process_access)
+
+
+/* This structure describes a child process. */
+
+struct process
+{
+  ULONG status;                 /* Process status: PS_FREE etc. */
+  ULONG pid;                    /* Process ID */
+  ULONG sid;                    /* Session ID (for PS_SESSION) */
+  ULONG wait_tid;               /* Thread ID for wait() */
+  ULONG wait_ret;               /* Return value for wait() */
+  ULONG flags;                  /* Process flags: PF_SYNC */
+};
+
+/* This structure describes one registered memory area for fork(),
+   such as a DLL data segment. */
+
+struct fork_regmem
+{
+  ULONG start;
+  ULONG end;
+  HMODULE hmod;
+};
+
+/* This structure describes one registered DLL for fork(). */
+
+struct fork_regdll
+{
+  HMODULE hmod;
+};
+
+/* This table keeps track of child processes. */
+
+static struct process process_table[MAX_PROCESSES];
+
+/* For each thread, a pointer to its thread data block is stored in
+   this table indexed by thread IDs. */
+
+thread_data *threads[MAX_THREADS];
+
+/* `process_table' is protected by this Mutex semaphore. */
+
+static HMTX process_access;
+
+/* These event semaphores are posted when a process has been started
+   or has ended, respectively. */
+
+static HEV process_birth;
+static HEV process_death;
+
+/* These variables are true if cwait_thread() or qwait_thread(),
+   respectively, have been started. */
+
+static BYTE cwait_started;
+static BYTE qwait_started;
+
+/* These variables hold the thread IDs for cwait_thread() and
+   qwait_thread(), respectively. */
+
+static ULONG cwait_tid;
+static ULONG qwait_tid;
+
+/* The handle and name of the termination queue read by
+   qwait_thread(). */
+
+static HQUEUE termq_handle;
+static char termq_name[64];
+static char termq_created;
+
+/* Number of zombies. */
+
+int zombie_count;
+
+/* Number of registered memory areas for fork().  This variable must
+   be implicitely initialized to zero. */
+
+static int fork_regmem_count;
+
+/* This variable is made non-zero when `fork_regmem' overflows.  This
+   variable must be implicitely initialized to zero. */
+
+static char fork_regmem_overflow;
+
+/* Table of registered memory areas for fork().  The first
+   `fork_regmem_count' entries are used.  TODO: Use linked list. */
+
+static struct fork_regmem fork_regmem[FORK_REGMEM_MAX];
+
+/* Number of registered DLLs for fork().  This variable must be
+   implicitely initialized to zero. */
+
+static int fork_regdll_count;
+
+/* This variable is made non-zero when `fork_regdll' overflows.  This
+   variable must be implicitely initialized to zero. */
+
+static char fork_regdll_overflow;
+
+/* Table of DLLs for fork().  The first `fork_regdll_count' entries
+   are used.  TODO: Use linked list. */
+
+static struct fork_regdll fork_regdll[FORK_REGDLL_MAX];
+
+/* This variable is non-zero in the parent process during fork()'s
+   DosExecPgm call; it's used by ptrace() to decide whether
+   PTNPROC_FORK should be set or not. */
+
+BYTE ptrace_forking;
+
+/* If `ptrace_forking' is non-zero, the following variable will
+   contain the address at which the two processes will continue/start
+   after the fork.  This is the return address of the system call. */
+
+ULONG ptrace_fork_addr;
+
+
+/* Initialize the process table etc. */
+
+void init_process (void)
+{
+  ULONG i;
+
+  /* Create the semaphores. */
+
+  create_mutex_sem (&process_access);
+  create_event_sem (&process_death, DC_SEM_SHARED);
+  create_event_sem (&process_birth, DC_SEM_SHARED);
+
+  /* There are no child processes. */
+
+  for (i = 0; i < MAX_PROCESSES; ++i)
+    process_table[i].status = PS_FREE;
+  zombie_count = 0;
+}
+
+
+/* Find free process table slot.  Return a pointer to a free process
+   table entry.  If no free slot is found, return NULL.  It is assumed
+   that exclusive access to the process table has been gained. */
+
+static struct process *proc_new (void)
+{
+  ULONG i;
+
+  for (i = 0; i < MAX_PROCESSES; ++i)
+    if (process_table[i].status == PS_FREE)
+      return &process_table[i];
+  return NULL;
+}
+
+
+/* Find process table slot by process ID.  Return a pointer to the
+   process table entry.  If there's no such process in the process
+   table, return NULL.  It is assumed that exclusive access to the
+   process table has been gained. */
+
+static struct process *proc_find (ULONG pid)
+{
+  ULONG i;
+
+  for (i = 0; i < MAX_PROCESSES; ++i)
+    if (process_table[i].pid == pid && process_table[i].status != PS_FREE)
+      return &process_table[i];
+  return NULL;
+}
+
+
+/* Return true if process PID is in the process table. */
+
+int proc_check (int pid)
+{
+  struct process *proc;
+
+  LOCK_PROCESS;
+  proc = proc_find (pid);
+  UNLOCK_PROCESS;
+  return proc != NULL;
+}
+
+
+/* A child has been started; notify cwait_thread(). */
+
+void child_started (void)
+{
+  DosPostEventSem (process_birth);
+}
+
+
+/* Child process ended, post the `process_death' semaphore and raise
+   SIGCLD. */
+
+static void proc_death (int thread1)
+{
+  struct signal_entry *p;
+
+  DosPostEventSem (process_death);
+  p = threads[1]->sig_table + SIGCLD;
+  if (p->handler != SIG_DFL && p->handler != SIG_IGN)
+    {
+      generate_signal (threads[1], SIGCLD);
+      if (get_tid () == 1)
+        deliver_pending_signals (threads[1], NULL, NULL);
+    }
+}
+
+
+/* Add a PS_ATTACH entry to the process table.  Such an entry is used
+   when attaching to a debuggee which is not a child process.  Return
+   errno. */
+
+ULONG proc_add_attach (ULONG pid)
+{
+  struct process *proc;
+
+  LOCK_PROCESS;
+  proc = proc_new ();
+  if (proc != NULL)
+    {
+      proc->status = PS_ATTACH;
+      proc->pid = pid;
+      proc->sid = 0;            /* TODO */
+      proc->flags = PF_DEBUG;
+    }
+  UNLOCK_PROCESS;
+  return (proc == NULL ? EAGAIN : 0);
+}
+
+
+void proc_remove_attach (ULONG pid)
+{
+  struct process *proc;
+
+  LOCK_PROCESS;
+  proc = proc_find (pid);
+  if (proc->status == PS_ATTACH)
+    proc->status = PS_FREE;
+  UNLOCK_PROCESS;
+}
+
+
+/* A child process has ended.  PID is the process ID of the process.
+   If PID is zero, use the session ID SID instead for identifying the
+   process.  RET is the return value for wait().  Update the process
+   table and call proc_death(). */
+
+static void bury (ULONG pid, ULONG sid, ULONG ret)
+{
+  struct process *proc;
+  int i;
+
+  if (pid == 0)
+    {
+      /* Find the process ID for the head process of session SID. */
+
+      LOCK_PROCESS;
+      for (i = 0; i < MAX_PROCESSES; ++i)
+        if (process_table[i].sid == sid
+            && process_table[i].status == PS_SESSION)
+          {
+            pid = process_table[i].pid;
+            break;
+          }
+      UNLOCK_PROCESS;
+    }
+  if (pid != 0)
+    {
+      /* Turn the process into a zombie and call proc_death(). */
+
+      LOCK_PROCESS;
+      proc = proc_find (pid);
+      if (proc == NULL)
+        UNLOCK_PROCESS;
+      else
+        {
+          proc->wait_ret = ret;
+          proc->status = PS_ZOMBIE;
+          ++zombie_count;
+          UNLOCK_PROCESS;
+          proc_death (FALSE);
+        }
+    }
+}
+
+
+/* Exception handler for cwait_thread().  On termination of the
+   thread, cwait_tid will be set to zero. */
+
+static ULONG cwait_exception (EXCEPTIONREPORTRECORD *report,
+                              EXCEPTIONREGISTRATIONRECORD *registration,
+                              CONTEXTRECORD *context,
+                              void *dummy)
+{
+  if (report->fHandlerFlags & (EH_EXIT_UNWIND|EH_UNWINDING))
+    return XCPT_CONTINUE_SEARCH;
+  switch (report->ExceptionNum)
+    {
+    case XCPT_ASYNC_PROCESS_TERMINATE: /* This is the correct one */
+    case XCPT_PROCESS_TERMINATE:       /* OS/2 bug */
+      cwait_tid = 0;
+      break;
+    }
+  return XCPT_CONTINUE_SEARCH;
+}
+
+
+/* This thread handles termination of child processes started with
+   DosExec. */
+
+static void cwait_thread (ULONG arg)
+{
+  RESULTCODES ret_codes;
+  ULONG rc, pid, count, ret, tmp;
+  EXCEPTIONREGISTRATIONRECORD registration;
+
+  registration.prev_structure = NULL;
+  registration.ExceptionHandler = cwait_exception;
+  DosSetExceptionHandler (&registration);
+
+  arg = 0;                      /* keep the compiler happy */
+  for (;;)
+    {
+      DosResetEventSem (process_birth, &count);
+
+      /* Originally, DCWA_PROCESSTREE was used instead of DCW_PROCESS
+         to avoid reporting the death of a forked process that exec's
+         another process.  Now, exec() in a process that has been
+         created by fork() stays alive until the exec'd process
+         terminates, so DCWA_PROCESSTREE is no longer required,
+         avoiding some anomalies. */
+
+      rc = DosWaitChild (DCWA_PROCESS, DCWW_WAIT, &ret_codes, &pid, 0);
+      if (rc == ERROR_WAIT_NO_CHILDREN)
+        DosWaitEventSem (process_birth, 5000);
+      else
+        {
+          ret = ret_codes.codeResult;
+          if (ret > 0xff)
+            ret = 0xff;
+          switch (ret_codes.codeTerminate)
+            {
+            case TC_EXIT:
+              tmp = ret << 8;
+              break;
+            case TC_HARDERROR:
+            case TC_KILLPROCESS:
+              tmp = SIGTERM;
+              break;
+            default:
+              tmp = SIGSEGV;
+              break;
+            }
+          bury (pid, 0, tmp);
+        }
+    }
+}
+
+
+/* Start cwait_thread() if not already done. */
+
+void start_cwait_thread (void)
+{
+  ULONG rc;
+
+  if (!cwait_started)
+    {
+      cwait_started = TRUE;
+      rc = DosCreateThread (&cwait_tid, cwait_thread, 0,
+                            CREATE_READY | STACK_COMMITTED, 0x4000);
+    }
+}
+
+
+/* Exception handler for qwait_thread().  On termination of the
+   thread, qwait_tid will be set to zero. */
+
+static ULONG qwait_exception (EXCEPTIONREPORTRECORD *report,
+                              EXCEPTIONREGISTRATIONRECORD *registration,
+                              CONTEXTRECORD *context,
+                              void *dummy)
+{
+  if (report->fHandlerFlags & (EH_EXIT_UNWIND|EH_UNWINDING))
+    return XCPT_CONTINUE_SEARCH;
+  switch (report->ExceptionNum)
+    {
+    case XCPT_ASYNC_PROCESS_TERMINATE: /* This is the correct one */
+    case XCPT_PROCESS_TERMINATE:       /* OS/2 bug */
+      qwait_tid = 0;
+      break;
+    }
+  return XCPT_CONTINUE_SEARCH;
+}
+
+
+/* This thread handles termination of child processes started with
+   DosStartSession. */
+
+static void qwait_thread (ULONG arg)
+{
+  ULONG rc, len, sid, ret, tmp;
+  REQUESTDATA req;
+  BYTE priority;
+  ULONG *data;
+  EXCEPTIONREGISTRATIONRECORD registration;
+
+  registration.prev_structure = NULL;
+  registration.ExceptionHandler = qwait_exception;
+  DosSetExceptionHandler (&registration);
+
+  arg = 0; data = 0;            /* keep the compiler happy */
+  for (;;)
+    {
+      rc = DosReadQueue (termq_handle, &req, &len, (void **)&data, 0,
+                         DCWW_WAIT, &priority, 0);
+      if (rc == ERROR_QUE_INVALID_HANDLE)
+        DosExit (EXIT_THREAD, 0);
+      if (rc != 0)
+        error (rc, "DosReadQueue");
+      else if (req.ulData == 0)
+        {
+          /* Child session ended. */
+
+          sid = *data & 0xffff;
+          ret = (*data >> 16) & 0xffff;
+          DosFreeMem (data);
+          if (ret > 0xff)
+            ret = 0xff;
+          tmp = ret << 8;
+          bury (0, sid, tmp);
+        }
+      else
+        {
+          /* Child session created (SSF_TRACEOPT_TRACEALL only). */
+
+          DosFreeMem (data);
+        }
+    }
+}
+
+
+/* Start qwait_thread() if not already done. */
+
+static void start_qwait_thread (void)
+{
+  ULONG qn, rc;
+
+  if (!qwait_started)
+    {
+      qwait_started = TRUE;
+      LOCK_COMMON;
+      qn = ++queue_number;
+      UNLOCK_COMMON;
+      sprintf (termq_name, "/queues/emx/termq/%.8x.tqe", (unsigned)qn);
+#if 0
+      prt ("Queue name: ");
+      prt (termq_name);
+      prt ("\r\n");
+#endif
+      rc = DosCreateQueue (&termq_handle, QUE_FIFO | QUE_CONVERT_ADDRESS,
+                           termq_name);
+      if (rc == 0)
+        termq_created = TRUE;
+      else
+        error (rc, "DosCreateQueue");
+      rc = DosCreateThread (&qwait_tid, qwait_thread, 0,
+                            CREATE_READY | STACK_COMMITTED, 0x4000);
+      if (rc != 0) error (rc, "DosCreateThread");
+    }
+}
+
+
+/* This function is called on termination of emx.dll. */
+
+void term_process (void)
+{
+  ULONG i;
+
+  if (termq_created)
+    {
+      termq_created = FALSE;
+      DosCloseQueue (termq_handle);
+    }
+
+  /* Closing termq_handle should terminate qwait_thread().  Give it a
+     chance to terminate. */
+
+  for (i = 0; qwait_tid != 0 && i < 10; ++i)
+    DosSleep (10);
+
+  /* If qwait_thread() is still alive, kill it. */
+
+  if (qwait_tid != 0)
+    DosKillThread (qwait_tid);
+
+  /* Kill cwait_thread() if it is alive. */
+
+  if (cwait_tid != 0)
+    DosKillThread (cwait_tid);
+}
+
+
+/* Set the process status of the debuggee PID to WAIT_RET, to be
+   returned by wait().  Also set the thread ID to be returned by
+   wait() to TID.  If END is true, turn the process into a zombie. */
+
+void debug_set_wait (ULONG pid, ULONG tid, ULONG wait_ret, ULONG end)
+{
+  ULONG i;
+  struct process *p;
+  static struct process *cache;
+
+  LOCK_PROCESS;
+  if (!(cache != NULL
+        && cache->pid == pid
+        && (cache->status == PS_PROCESS || cache->status == PS_SESSION
+            || cache->status == PS_ATTACH)))
+    {
+      p = process_table; cache = NULL;
+      for (i = 0; i < MAX_PROCESSES; ++i, ++p)
+        if (p->pid == pid
+            && (p->status == PS_PROCESS || p->status == PS_SESSION
+                || p->status == PS_ATTACH))
+          {
+            cache = p;
+            break;
+          }
+    }
+  if (cache != NULL)
+    {
+      cache->wait_ret = wait_ret;
+      cache->wait_tid = tid;
+      if (end)
+        {
+          cache->status = PS_ZOMBIE;
+          ++zombie_count;
+        }
+      else
+        cache->flags |= PF_WAIT;
+    }
+  UNLOCK_PROCESS;
+  if (cache != NULL && end)
+    proc_death (TRUE);
+
+}
+
+
+/* Wait for termination of process *PPID.  Update the PID (perhaps
+   including the TID) pointed to by PPID.  Store the termination
+   status (with the return code in bits 8..15, for wait()) to
+   *RET_CODE.  Return 0 on success.  Otherwise, return the errno code
+   (for instance EINTR when interrupted, unless IGNORE_INT is true).
+   If NOHANG is true, wait_for() returns EAGAIN in case it would
+   block. */
+
+static ULONG wait_for (ULONG *ppid, ULONG *ret_code, ULONG nohang,
+                       ULONG ignore_int)
+{
+  ULONG rc, count, i, children;
+  struct process *p;
+
+  for (;;)
+    {
+      DosResetEventSem (process_death, &count);
+
+      /* Note that LOCK_PROCESS ignores interrupts. */
+
+      do
+        {
+          rc = DosRequestMutexSem (process_access, -1);
+        } while (rc == ERROR_SEM_OWNER_DIED
+                 || (rc == ERROR_INTERRUPT && ignore_int));
+      if (rc != 0) return set_error (rc);
+
+      p = process_table; children = 0;
+      for (i = 0; i < MAX_PROCESSES; ++i, ++p)
+        switch (p->status)
+          {
+          case PS_ZOMBIE:
+            if (p->pid == *ppid)
+              {
+                if (!(p->flags & PF_SYNC))
+                  p->status = PS_FREE;
+                --zombie_count;
+                *ret_code = p->wait_ret;
+                UNLOCK_PROCESS;
+                return 0;
+              }
+            break;
+          case PS_FREE:
+            break;
+          default:
+            if (p->pid == *ppid)
+              {
+                if (p->flags & PF_WAIT)
+                  {
+                    p->flags &= ~PF_WAIT;
+                    *ret_code = p->wait_ret;
+                    *ppid = PTRACE_PIDTID (p->pid, p->wait_tid);
+                    UNLOCK_PROCESS;
+                    return 0;
+                  }
+                ++children;
+              }
+            break;
+          }
+      UNLOCK_PROCESS;
+      if (children == 0)
+        return ECHILD;
+      if (nohang)
+        return EAGAIN;
+      rc = DosWaitEventSem (process_death, SEM_INDEFINITE_WAIT);
+      if (rc != 0 && !(rc == ERROR_INTERRUPT && ignore_int))
+        return set_error (rc);
+    }
+}
+
+
+/* Wait for termination of any child process.  Store the termination
+   status (with the return code in bits 8..15, for wait()) to
+   *RET_CODE.  Return 0 on success.  Otherwise, return the errno code
+   (for instance EINTR when interrupted).  If NOHANG is true,
+   wait_any() returns EAGAIN in case it would block. */
+
+static ULONG wait_any (ULONG *ppid, ULONG *ret_code, ULONG nohang)
+{
+  ULONG rc, count, i, children;
+  struct process *p;
+
+  for (;;)
+    {
+      DosResetEventSem (process_death, &count);
+
+      /* Note that LOCK_PROCESS ignores interrupts. */
+
+      do
+        {
+          rc = DosRequestMutexSem (process_access, -1);
+        } while (rc == ERROR_SEM_OWNER_DIED);
+      if (rc != 0) return set_error (rc);
+
+      p = process_table; children = 0;
+      for (i = 0; i < MAX_PROCESSES; ++i, ++p)
+        switch (p->status)
+          {
+          case PS_ZOMBIE:
+            if (!(p->flags & PF_SYNC))
+              p->status = PS_FREE;
+            --zombie_count;
+            *ppid = p->pid;
+            *ret_code = p->wait_ret;
+            UNLOCK_PROCESS;
+            return 0;
+          case PS_FREE:
+            break;
+          default:
+            if (p->flags & PF_WAIT)
+              {
+                p->flags &= ~PF_WAIT;
+                *ppid = PTRACE_PIDTID (p->pid, p->wait_tid);
+                *ret_code = p->wait_ret;
+                UNLOCK_PROCESS;
+                return 0;
+              }
+            ++children;
+            break;
+          }
+      UNLOCK_PROCESS;
+      if (children == 0)
+        return ECHILD;
+      if (nohang)
+        return EAGAIN;
+      rc = DosWaitEventSem (process_death, SEM_INDEFINITE_WAIT);
+      if (rc != 0) return set_error (rc);
+    }
+}
+
+
+/* This function implements the __wait() system call. */
+
+ULONG do_wait (ULONG *ptermstatus, ULONG *errnop)
+{
+  ULONG rc, pid;
+
+  rc = wait_any (&pid, ptermstatus, FALSE);
+  *errnop = rc;
+  return (rc == 0 ? pid : -1);
+}
+
+
+/* This function implements the __waitpid() system call. */
+
+ULONG do_waitpid (ULONG pid, ULONG opt, ULONG *ptermstatus, ULONG *errnop)
+{
+  ULONG rc;
+
+  if (pid == (ULONG)-1)
+    rc = wait_any (&pid, ptermstatus, opt & WNOHANG);
+  else
+    rc = wait_for (&pid, ptermstatus, opt & WNOHANG, FALSE);
+  if (rc == EAGAIN)
+    {
+      *errnop = 0;
+      return 0;
+    }
+  *errnop = rc;
+  return (rc == 0 ? pid : -1);
+}
+
+#define ADDCHR(c) do { \
+  if (arg_buf != NULL) \
+    { \
+      if (size + 1 > arg_buf_size) return -E2BIG; /* Oops */ \
+      arg_buf[size] = (char)c; \
+    } \
+  size += 1; \
+  } while (0)
+
+#define ADDCHRS(c,n) do { \
+  if (arg_buf != NULL) \
+    { \
+      if (size + (n) > arg_buf_size) return -E2BIG; /* Oops */ \
+      memset (arg_buf + size, c, n); \
+    } \
+  size += n; \
+  } while (0)
+
+#define ADDSTR(s,n) do { \
+  if (arg_buf != NULL) \
+    { \
+      if (size + (n) > arg_buf_size) return -E2BIG; /* Oops */ \
+      memcpy (arg_buf + size, s, n); \
+    } \
+  size += n; \
+  } while (0)
+
+/* Build the command line for a child process.  Return the number of
+   bytes required/used for the buffer or -errno.  Well, there's not
+   much point in allocating the buffer dynamically as OS/2 limits the
+   size to 64KB anyway. */
+
+static LONG spawn_args (char *arg_buf, ULONG arg_buf_size,
+                        const char *arg_ptr,
+                        ULONG argc, ULONG mode32, UCHAR session,
+                        const char *prog_name)
+{
+  size_t len, size;
+  const char *src, *s, *base;
+  int i, quote, bs, method;
+
+  base = (const char *)_getname (prog_name);
+  method = 0;
+  if (stricmp (base, "cmd.exe") == 0 || stricmp (base, "4os2.exe") == 0)
+    method = 1;
+  src = arg_ptr;
+  size = 0;
+  if (argc > 0)
+    {
+      ++src;                /* skip flags byte */
+      len = strlen (src) + 1;
+      if (!session)
+        ADDSTR (src, len);
+      src += len;
+    }
+  for (i = 1; i < argc; ++i)
+    {
+      if (i > 1)
+        ADDCHR (' ');
+      ++src;                    /* skip flags byte */
+      quote = FALSE;
+      if (*src == 0)
+        quote = TRUE;
+      else if (opt_quote || (mode32 & P_QUOTE))
+        {
+          if (src[0] == '@' && src[1] != 0)
+            quote = TRUE;
+          else
+            for (s = src; *s != 0; ++s)
+              if (*s == '?' || *s == '*')
+                {
+                  quote = TRUE;
+                  break;
+                }
+        }
+      if (!quote)
+        for (s = src; *s != 0; ++s)
+          if (*s == ' ' || *s == '\t' || (*s == '"' && method == 1))
+            {
+              quote = TRUE;
+              break;
+            }
+      if (quote)
+        ADDCHR ('"');
+      bs = 0;
+      while (*src != 0)
+        {
+          if (*src == '"' && method == 0)
+            {
+              ADDCHRS ('\\', bs+1);
+              bs = 0;
+            }
+          else if (*src == '\\' && method == 0)
+            ++bs;
+          else
+            bs = 0;
+          ADDCHR (*src);
+          ++src;
+        }
+      if (quote)
+        {
+          ADDCHRS ('\\', bs);
+          bs = 0;
+          ADDCHR ('"');
+        }
+      ++src;
+    }
+  ADDCHR (0);
+  if (!session && argc > 0 && (mode32 & P_TILDE))
+    {
+      ADDCHR ('~');
+      src = arg_ptr;
+      for (i = 0; i < argc; ++i)
+        {
+          ++src;                    /* skip flags byte */
+          if (*src == 0 || *src == '~')
+            ADDCHR ('~');
+          len = strlen (src) + 1;
+          ADDSTR (src, len);
+          src += len;
+        }
+    }
+  ADDCHR (0);
+  return size;
+}
+
+
+/* Build environment for child process: Set the `_emx_sig' environment
+   variable to let the child process inherit signal settings.  Store a
+   pointer to the new environment, allocated with private_alloc(), to
+   *DST.  SRC points to the original environment to be passed to the
+   child process.  SRC_SIZE is the size of that environment. */
+
+static ULONG spawn_env (char **dst, const char *src, ULONG src_size)
+{
+  void *pv;
+  char *env;
+  ULONG rc, size;
+  char temp[40];
+  unsigned sigset;
+  int len, i;
+  thread_data *td;
+
+  /* Do some sanity checks to avoid crashing. */
+
+  if (src_size < 1)
+    return EINVAL;
+  if (src[src_size-1] != 0)
+    return EINVAL;
+  if (src_size >= 2 && src[src_size-2] != 0)
+    return EINVAL;
+
+  /* Build the string to be added to the environment.  Let the child
+     process inherit the signal settings of the *current* thread. */
+
+  td = get_thread ();
+  sigset = 0;
+  for (i = 1; i < NSIG; ++i)
+    if (td->sig_table[i].handler == SIG_IGN)
+      sigset |= (1 << i);
+  len = sprintf (temp, "_emx_sig=%.8x:%.8x", (unsigned)my_pid, sigset);
+
+  /* Allocate memory for the new environment. */
+
+  size = src_size + len + 1;
+  rc = private_alloc (&pv, size);
+  if (rc != 0) return set_error (rc);
+  *dst = env = (char *)pv;
+
+  /* Copy the environment, dropping `_emx_sig' if present. */
+
+  while (*src != 0)
+    {
+      if (*src == '_' && strncmp (src, temp, 9) == 0)
+        while (*src++ != 0)
+          ;
+      else
+        {
+          while (*src != 0)
+            *env++ = *src++;
+          *env++ = *src++;
+        }
+    }
+
+  /* Add the new variable. */
+
+  memcpy (env, temp, len + 1);
+  env[len+1] = 0;
+
+  return 0;
+}
+
+
+/* When calling exec() in a fork()ed process, we do not exit after
+   starting the process as our parent (who forked us) cannot retrieve
+   the return code of our child process.  Wait for termination of the
+   child process, passing on signals.  After termination of the child
+   process, return its return code. */
+
+static void spawn_fork_exec (ULONG pid)
+{
+  ULONG wait_ret, i;
+
+#if 0
+  if (get_tid () != 1)
+    {
+      /* TODO: transfer control to the main thread and call
+         spawn_fork_exec() there */
+    }
+#endif
+
+  stop_alarm ();
+
+  /* TODO: stop all user threads */
+
+  fork_exec_pid = pid;
+
+  /* Close all handles but socket handles.  We can't close socket
+     handles as that would create a time window. */
+
+  for (i = 0; i < handle_count; ++i)
+    if ((files[i].flags & (HF_OPEN|HF_SOCKET)) == HF_OPEN)
+      close_handle (i);
+
+  wait_for (&pid, &wait_ret, FALSE, TRUE);
+  quit (wait_ret >> 8);
+}
+
+
+/* This function implements the __spawnve() system call. */
+
+ULONG do_spawn (struct _new_proc *np, ULONG *result)
+{
+  STARTDATA sd;
+  struct process *proc;
+  ULONG rc, pid, sid;
+  RESULTCODES ret_codes;
+  ULONG exec_type;
+  ULONG mode32;
+  UCHAR mode8;
+  long arg_buf_size;
+  char fname[512];
+  char obj_buf[40];
+  BYTE session;
+  PVOID arg_buf;
+  char *env_ptr = NULL;
+
+  /* Kludge alert: Unfortunately, the `mode' member was made only 16
+     bits wide originally.  Bit 15 is used to indicate that the
+     `mode2' member is used, which holds the upper 16 bits of MODE.
+     This allows using emx 0.8 applications with emx 0.9 as emx
+     doesn't look at `mode2' unless bit 15 of `mode' is set.  Of
+     course, this fails if an (old) application program sets bit 15 of
+     MODE. */
+
+  mode32 = np->mode;
+  if (np->mode & 0x8000)
+    mode32 |= np->mode2 << 16;
+
+  mode8 = np->mode & 0xff;
+  switch (mode8)
+    {
+    case P_NOWAIT:
+    case P_WAIT:
+    case P_OVERLAY:
+      session = FALSE;
+      exec_type = EXEC_ASYNCRESULT;
+      break;
+    case P_DETACH:
+      session = FALSE;
+      exec_type = EXEC_BACKGROUND;
+      break;
+    case P_DEBUG:
+      if ((mode32 & P_DEBUGDESC)
+          && (uflags & _UF_PTRACE_MODEL) == _UF_PTRACE_STANDARD)
+        return EINVAL;
+      exec_type = (mode32 & P_DEBUGDESC) ? EXEC_ASYNCRESULTDB : EXEC_TRACE;
+      session = !(debug_same_sess || (mode32 & P_NOSESSION));
+      if (session & (mode32 & P_UNRELATED))
+        return EINVAL;
+      break;
+    case P_SESSION:
+    case P_PM:
+      exec_type = 0;
+      session = TRUE;
+      break;
+    default:
+      return EINVAL;
+    }
+  truncate_name (fname, (char *)np->fname_off);
+  _defext (fname, "exe");
+
+  /* Compute the size of the argument buffer. */
+
+  arg_buf_size = spawn_args (NULL, 0, (const char *)np->arg_off,
+                             np->arg_count, mode32, session, fname);
+  if (arg_buf_size < 0)
+    return -arg_buf_size;       /* errno */
+  if (arg_buf_size > 65536)
+    return E2BIG;
+
+  /* The buffer pointed to by the ArgPointer argument of DosExecPgm
+     must not cross a 64KByte boundary.  Note that objects are aligned
+     on a 64KByte boundary. */
+
+  rc = DosAllocMem (&arg_buf, (ULONG)arg_buf_size,
+                    PAG_READ | PAG_WRITE | PAG_COMMIT);
+  if (rc != 0) return ENOMEM;
+
+  /* Build the argument buffer. */
+
+  arg_buf_size = spawn_args (arg_buf, (ULONG)arg_buf_size,
+                             (const char *)np->arg_off,
+                             np->arg_count, mode32, session, fname);
+  if (arg_buf_size < 0)
+    {
+      DosFreeMem (arg_buf);
+      return -arg_buf_size;     /* errno */
+    }
+
+  rc = spawn_env (&env_ptr, (const char *)np->env_off, np->env_size);
+  if (rc != 0)
+    {
+      DosFreeMem (arg_buf);
+      return rc;
+    }
+  LOCK_PROCESS;
+  proc = proc_new ();
+  if (proc == 0)
+    {
+      UNLOCK_PROCESS;
+      DosFreeMem (arg_buf);
+      private_free (env_ptr);
+      return EAGAIN;
+    }
+  if (session)
+    {
+      if (!(mode32 & P_UNRELATED))
+        start_qwait_thread ();
+      sd.Length = 50;
+      sd.Related = ((mode32 & P_UNRELATED)
+                    ? SSF_RELATED_INDEPENDENT : SSF_RELATED_CHILD);
+      sd.PgmTitle = 0;
+      sd.PgmName = fname;
+      sd.PgmInputs = arg_buf;
+      sd.TermQ = termq_name;
+      sd.Environment = env_ptr;
+      sd.InheritOpt = SSF_INHERTOPT_PARENT;
+      sd.IconFile = 0;
+      sd.PgmHandle = 0;
+      sd.InitXPos = 0;
+      sd.InitYPos = 0;
+      sd.InitXSize = 0;
+      sd.InitYSize = 0;
+      sd.Reserved = 0;
+      sd.ObjectBuffer = 0;
+      sd.ObjectBuffLen = 0;
+      switch (mode32 & 0x0f00)
+        {
+        case P_FULLSCREEN:
+          sd.SessionType = SSF_TYPE_FULLSCREEN;
+          break;
+        case P_WINDOWED:
+          sd.SessionType = SSF_TYPE_WINDOWABLEVIO;
+          break;
+        default:
+          if (mode8 == P_PM)
+            sd.SessionType = SSF_TYPE_PM;
+          else
+            sd.SessionType = SSF_TYPE_DEFAULT;
+          break;
+        }
+      switch (mode32 & 0xf00)
+        {
+        case P_MINIMIZE:
+          sd.PgmControl = SSF_CONTROL_MINIMIZE;
+          break;
+        case P_MAXIMIZE:
+          sd.PgmControl = SSF_CONTROL_MAXIMIZE;
+          break;
+        default:
+          sd.PgmControl = 0;
+          break;
+        }
+      if (mode32 & P_NOCLOSE)
+        sd.PgmControl |= SSF_CONTROL_NOAUTOCLOSE;
+      if (mode8 != P_DEBUG)
+        sd.TraceOpt = SSF_TRACEOPT_NONE;
+      else if (mode32 & P_DEBUGDESC)
+        sd.TraceOpt = SSF_TRACEOPT_TRACEALL;
+      else
+        sd.TraceOpt = SSF_TRACEOPT_TRACE;
+      sd.FgBg = (mode32 & P_BACKGROUND ? SSF_FGBG_BACK : SSF_FGBG_FORE);
+      rc = DosStartSession (&sd, &sid, &pid);
+      DosFreeMem (arg_buf);
+      private_free (env_ptr);
+      if (rc != 0 && rc != ERROR_SMG_START_IN_BACKGROUND)
+        {
+          UNLOCK_PROCESS;
+          return set_error (rc);
+        }
+      if (!(mode32 & P_UNRELATED))
+        {
+          proc->status = PS_SESSION;
+          proc->pid = pid;
+          proc->sid = sid;
+          proc->wait_ret = 0;
+          proc->flags = 0;
+          if (mode8 == P_DEBUG)
+            {
+              proc->flags |= PF_DEBUG | PF_WAIT;
+              proc->wait_ret = 0x7f + (SIGTRAP << 8);
+              proc->wait_tid = 1;
+            }
+        }
+      UNLOCK_PROCESS;
+      if (!(mode32 & P_UNRELATED))
+        child_started ();
+      if (mode8 == P_DEBUG)
+        {
+          rc = spawn_debug (pid, sid);
+          if (rc != 0) return rc;
+        }
+      *result = pid;
+      return 0;
+    }
+  else
+    {
+      kbd_stop ();
+      start_cwait_thread ();
+      rc = DosExecPgm (obj_buf, sizeof (obj_buf),
+                       exec_type, arg_buf, env_ptr,
+                       &ret_codes, fname);
+      DosFreeMem (arg_buf);
+      private_free (env_ptr);
+      if (rc != 0)
+        {
+          UNLOCK_PROCESS;
+          kbd_restart ();
+          return set_error (rc);
+        }
+      UNLOCK_COMMON;
+      pid = ret_codes.codeTerminate;
+      proc->status = PS_PROCESS;
+      proc->pid = pid;
+      proc->sid = 0;
+      proc->wait_ret = 0;
+      proc->flags = 0;
+      if (mode8 == P_WAIT)
+        proc->flags |= PF_SYNC;
+      if (mode8 == P_DEBUG)
+        {
+          proc->flags |= PF_DEBUG | PF_WAIT;
+          proc->wait_ret = 0x7f + (SIGTRAP << 8);
+          proc->wait_tid = 1;
+        }
+      UNLOCK_PROCESS;
+      child_started ();
+      switch (mode8)
+        {
+        case P_DEBUG:
+          rc = spawn_debug (pid, 0);
+          kbd_restart ();
+          if (rc != 0) return rc;
+          *result = pid;
+          return 0;
+        case P_OVERLAY:
+          if (fork_flag)
+            spawn_fork_exec (pid);
+          quit (0);
+        case P_NOWAIT:
+        case P_DETACH:
+          *result = pid;
+          kbd_restart ();
+          return 0;
+        default:
+          rc = wait_for (&pid, result, FALSE, TRUE);
+          *result = (*result >> 8) & 0xff;
+          proc->status = PS_FREE;
+          kbd_restart ();
+          return rc;
+        }
+    }
+}
+
+
+/* Copy the name of the EXE file to BUF.  Copy at most BUFSIZE bytes,
+   including the terminating null character. */
+
+int execname (char *buf, ULONG bufsize)
+{
+  size_t len;
+
+  if (bufsize == 0)
+    return -1;
+
+  if (exe_name[0] == 0)
+    {
+      *buf = 0;
+      return -1;
+    }
+  len = strlen (exe_name);
+  if (len >= bufsize)
+    {
+      *buf = 0;
+      return -1;
+    }
+  memcpy (buf, exe_name, len + 1);
+  return 0;
+}
+
+
+/* Create and initialize thread data block for a new thread.  TID is
+   the thread ID.  Return 0 on success, -1 on failure.  Store the
+   error number to ERRNOP unless ERRNOP is NULL. */
+
+ULONG new_thread (ULONG tid, int *errnop)
+{
+  thread_data *td;
+  ULONG rc;
+  int i;
+
+  if (tid >= MAX_THREADS)
+    {
+      if (errnop != NULL) *errnop = EAGAIN;
+      return -1;
+    }
+
+  /* Silently ignore multiple initializations of the same thread. */
+
+  if (threads[tid] != NULL)
+    return 0;
+
+  rc = private_alloc ((void **)&td, sizeof (thread_data));
+  if (rc != 0)
+    {
+      if (errnop != NULL) *errnop = set_error (rc);
+      return -1;
+    }
+  threads[tid] = td;
+  td->last_sys_errno = 0;       /* No error occured yet */
+  td->prev_sys_errno = 0;       /* No error occured yet */
+  td->sig_blocked = 0;          /* No signals are blocked */
+  td->sig_prev_blocked = 0;     /* Ditto */
+  td->sig_pending = 0;          /* No signals are pending */
+  for (i = 0; i < NSIG; ++i)
+    {
+      td->sig_table[i].handler = SIG_DFL;
+      td->sig_table[i].sa_mask = 0;
+      td->sig_table[i].sa_flags = SA_ACK;
+    }
+  td->find_handle = HDIR_CREATE; /* Handle not open */
+  td->find_next = NULL;
+  td->find_count = 0;
+  if (errnop != NULL) *errnop = 0;
+  return 0;
+}
+
+
+/* Deallocate the thread data block of thread TID.  Return 0 on
+   success, -1 on failure.  Store the error number to *ERRNOP. */
+
+ULONG end_thread (ULONG tid, int *errnop)
+{
+  thread_data *td;
+  ULONG rc;
+
+  if (tid >= MAX_THREADS || threads[tid] == NULL)
+    {
+      *errnop = EINVAL;
+      return -1;
+    }
+  td = threads[tid];
+  if (td->find_handle != HDIR_CREATE)
+    DosFindClose (td->find_handle);
+  rc = private_free (td);
+  threads[tid] = NULL;
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Check if the direct child process PID is alive.  Return FALSE if
+   the child process is not alive. */
+
+static int alive (ULONG pid)
+{
+  ULONG rc;
+
+  rc = DosSetPriority (PRTYS_PROCESS, PRTYC_NOCHANGE, 0, pid);
+  return (rc == 0 ? TRUE : FALSE);
+}
+
+
+/* Register a memory area for fork().  This is used for copying DLL
+   data segments. */
+
+void fork_register_mem (ULONG start, ULONG end, HMODULE hmod)
+{
+  if (fork_regmem_count >= FORK_REGMEM_MAX)
+    fork_regmem_overflow = TRUE;
+  else
+    {
+      fork_regmem[fork_regmem_count].start = start;
+      fork_regmem[fork_regmem_count].end = end;
+      fork_regmem[fork_regmem_count].hmod = hmod;
+      fork_regmem_count += 1;
+    }
+}
+
+
+/* Register a DLL for fork().  This is used for loading DLLs in the
+   child process. */
+
+void fork_register_dll (HMODULE hmod)
+{
+  /* If the module handle is already registered, the DLL was unloaded
+     and another one loaded.  (We don't record unloading of DLLs.)
+     Here, we are only interested in the module handles, no matter
+     what DLL they are associated with. */
+
+  if (fork_dll_registered (hmod))
+    return;
+
+  if (fork_regdll_count >= FORK_REGDLL_MAX)
+    fork_regdll_overflow = TRUE;
+  else
+    {
+      fork_regdll[fork_regdll_count].hmod = hmod;
+      fork_regdll_count += 1;
+    }
+}
+
+/* Return TRUE iff the DLL HMOD is registered. */
+
+int fork_dll_registered (HMODULE hmod)
+{
+  int i;
+
+  for (i = 0; i < fork_regdll_count; ++i)
+    if (fork_regdll[i].hmod == hmod)
+      return TRUE;
+  return FALSE;
+}
+
+
+/* Remove entries for unloaded modules. */
+
+static void fork_reg_cleanup (void)
+{
+  int i, j;
+
+  if (fork_regdll_overflow || fork_regmem_overflow)
+    {
+      /* We cannot recover from overflow.  Just keep the deleted
+         entries. */
+      return;
+    }
+
+  /* Remove deleted entries by moving the remaining entries down.  We
+     keep the order of the entries in an attempt to cope with
+     unloading and reloading modules.  (Actually, the order might be
+     irrelevant, as loading a DLL automatically causes all DLLs it
+     depends on to be loaded.) */
+
+  j = 0;
+  for (i = 0; i < fork_regdll_count; ++i)
+    if (fork_regdll[i].hmod != 0)
+      {
+        if (i != j)
+          fork_regdll[j] = fork_regdll[i];
+        ++j;
+      }
+  fork_regdll_count = j;
+
+  j = 0;
+  for (i = 0; i < fork_regmem_count; ++i)
+    if (fork_regmem[i].hmod != 0)
+      {
+        if (i != j)
+          fork_regmem[j] = fork_regmem[i];
+        ++j;
+      }
+  fork_regmem_count = j;
+}
+
+
+/* Wait for acknowledge from child process. */
+
+ULONG fork_wait (ULONG ack_sem, ULONG pid)
+{
+  ULONG rc;
+
+  for (;;)
+    {
+      rc = DosWaitEventSem (ack_sem, 500);
+      if (rc == ERROR_TIMEOUT)
+        {
+          if (!alive (pid))
+            return ERROR_INVALID_PROCID; /* -> ESRCH */
+        }
+      else if (rc != ERROR_INTERRUPT)
+        return rc;
+    }
+}
+
+
+/* Send a data block to the child process. */
+
+ULONG fork_send (ULONG req_sem, ULONG ack_sem, ULONG pid)
+{
+  ULONG rc, post_count;
+
+  rc = DosResetEventSem (ack_sem, &post_count);
+  if (rc != 0 && rc != ERROR_ALREADY_RESET)
+    return rc;
+  rc = DosPostEventSem (req_sem);
+  if (rc != 0)
+    return rc;
+  return fork_wait (ack_sem, pid);
+}
+
+
+/* Make the child process load a DLL. */
+
+ULONG fork_dll (fork_data *shmem, ULONG req_sem, ULONG ack_sem, ULONG pid,
+                HMODULE hmod)
+{
+  ULONG rc;
+  int i;
+
+  shmem->dll.req_code = FORK_REQ_DLL;
+  shmem->dll.hmod = hmod;
+  rc = DosQueryModuleName (hmod, sizeof (shmem->dll.path), shmem->dll.path);
+  if (rc == 0)
+    {
+      /* The module handle is valid.  Now check if all the registered
+         memory regions are readable.  If the process has unloaded a
+         DLL which is still loaded by another process the module
+         handle will remain valid! */
+
+      for (i = 0; i < fork_regmem_count; ++i)
+        if (fork_regmem[i].hmod == hmod
+            && !verify_memory (fork_regmem[i].start,
+                               fork_regmem[i].end - fork_regmem[i].start))
+          {
+            rc = ERROR_INVALID_HANDLE;
+            break;
+          }
+    }
+
+  if (rc == ERROR_INVALID_HANDLE)
+    {
+      int i;
+
+      /* We should get exactly one match. */
+
+      for (i = 0; i < fork_regdll_count; ++i)
+        if (fork_regdll[i].hmod == hmod)
+          fork_regdll[i].hmod = 0;
+
+      /* We should get 0 through 2 matches. */
+
+      for (i = 0; i < fork_regmem_count; ++i)
+        if (fork_regmem[i].hmod == hmod)
+          fork_regmem[i].hmod = 0;
+
+      return 0;
+    }
+  if (rc != 0)
+    return rc;
+  return fork_send (req_sem, ack_sem, pid);
+}
+
+
+/* Send a block of memory to the child process.  The memory is owned
+   by DLL HMOD (if HMOD is not NULLHANDLE) or by the base process (if
+   HMOD is NULLHANDLE).  This assumes that no DLL has module handle
+   NULLHANDLE. */
+
+ULONG fork_mem (fork_data *shmem, ULONG req_sem, ULONG ack_sem, ULONG pid,
+                ULONG base, ULONG top, HMODULE hmod)
+{
+  ULONG rc, count, chunk;
+
+  count = top - base;
+  while (count != 0)
+    {
+      shmem->mem.req_code = FORK_REQ_MEM;
+      shmem->mem.address = base;
+      shmem->mem.shared = shmem->mem.buf;
+      shmem->mem.hmod = hmod;
+      chunk = FORK_OBJ_SIZE - (sizeof (shmem->mem) - 1);
+      if (count < chunk)
+        chunk = count;
+      shmem->mem.count = chunk;
+      memcpy (shmem->mem.buf, (void *)base, chunk);
+      rc = fork_send (req_sem, ack_sem, pid);
+      if (rc != 0)
+        return rc;
+      base += chunk; count -= chunk;
+    }
+  return 0;
+}
+
+
+/* Implementation of fork().
+
+   The following string is passed in the 3rd argument string:
+
+   ^mmmmmmmm pppppppp
+
+   mmmmmmmm      Base address of shared memory object (hexadecimal)
+   pppppppp      Process ID of parent process
+
+   Note: emx_syscall (in emxdll.asm) pushes and pops all registers,
+   including EBX, ESI, and EDI.  As the stack is copied to the child
+   process, the child process will inherit register variables. */
+
+#define FORK_RSC_PROC    0x01
+#define FORK_RSC_MEM     0x02
+#define FORK_RSC_REQ     0x04
+#define FORK_RSC_ACK     0x08
+#define FORK_RSC_SOCK    0x10
+#define FORK_RSC_FILEIO  0x20
+
+int do_fork (syscall_frame *frame, ULONG *errnop)
+{
+  static char arg_buf[64];      /* Must not cross a 64KByte boundary */
+  char *p;
+  char obj_buf[32];
+  RESULTCODES ret_codes;
+  ULONG rc, req_sem, ack_sem, stk_low, pid, resources, *sp, ip;
+  fork_data *shmem;
+  struct process *pte;
+  thread_data *td;
+  int result, i;
+
+  resources = 0; result = -1;
+  if (heap_obj_count > 1 || fork_regmem_overflow || fork_regdll_overflow
+      || (heap_obj_count != 0 && !first_heap_obj_fixed))
+    {
+      /* Cannot copy more than one heap object and not more than
+         FORK_REGMEM_MAX DLL data segments.  Cannot load more than
+         FORK_REGDLL_MAX DLLs.  Cannot copy a heap object which isn't
+         an object of the EXE file (malloc() in _DLL_InitTerm()!). */
+
+      *errnop = ENOMEM;
+      goto done;
+    }
+  if (layout_flags & L_FLAG_LINK386)
+    {
+      *errnop = EACCES;
+      goto done;
+    }
+  LOCK_PROCESS;
+  resources |= FORK_RSC_PROC;
+  pte = proc_new ();
+  if (pte == NULL)
+    {
+      *errnop = EAGAIN;
+      goto done;
+    }
+  rc = DosAllocSharedMem ((void **)&shmem, NULL, FORK_OBJ_SIZE,
+                          PAG_READ|PAG_WRITE|PAG_COMMIT|OBJ_GETTABLE);
+  if (rc != 0)
+    goto error;
+  resources |= FORK_RSC_MEM;
+  p = arg_buf;
+  *p++ = ' ';                   /* Program name */
+  *p++ = 0;
+  *p++ = ' ';                   /* Command line */
+  *p++ = 0;
+  sprintf (p, "^%.8x %.8x", (unsigned)shmem, (unsigned)my_pid); /* fork */
+  stk_low = (ULONG)alloca (0) & ~0xfff;
+
+  shmem->init.req_code = FORK_REQ_INIT;
+  shmem->init.msize = FORK_OBJ_SIZE;
+  shmem->init.brk = heap_obj_count == 0 ? 0 : heap_objs[0].brk;
+  shmem->init.reg_ebp = (ULONG)frame;
+  shmem->init.umask = umask_bits;
+  shmem->init.umask1 = umask_bits1;
+  shmem->init.uflags = uflags;
+  shmem->init.stack_page = stk_low;
+  shmem->init.stack_base = stack_base;
+
+  rc = create_event_sem (&req_sem, DC_SEM_SHARED);
+  if (rc != 0)
+    goto error;
+  shmem->init.req_sem = req_sem;
+  resources |= FORK_RSC_REQ;
+
+  rc = create_event_sem (&ack_sem, DC_SEM_SHARED);
+  if (rc != 0)
+    goto error;
+  shmem->init.ack_sem = ack_sem;
+  resources |= FORK_RSC_ACK;
+
+  fileio_fork_parent_init ();
+  resources |= FORK_RSC_FILEIO;
+
+  start_cwait_thread ();
+  xf86sup_all_enadup (TRUE);
+
+  /* Compute the return address, for use by ptrace().  We add 4 to the
+     stack pointer to compensate for the PUSHFD of emx_syscall. */
+
+  sp = (ULONG *)(frame->e.esp + 4);
+  ip = frame->e.eip;
+
+  /* Check whether we have been called from __syscall().  That should
+     always be the case, but... We check only the lower 16 bits
+     because we don't know the address of __syscall() in a DLL such as
+     emxlibcs.dll. */
+
+  if ((ip & 0xffff) == 12 + 5)
+    {
+      ++sp;                     /* Remove CALL emx_syscall */
+      ip = *sp++;               /* Get and remove EIP */
+
+      /* IP is now in __fork().  See /emx/src/lib/emx_386/fork.s for
+         details -- note that __fork() does not create a stack frame.
+         Get the function which called __fork(). */
+
+      ip = *sp++;
+    }
+  ptrace_fork_addr = ip;
+
+  /* Create the child process. */
+
+  ptrace_forking = TRUE;
+  rc = DosExecPgm (obj_buf, sizeof (obj_buf), EXEC_ASYNCRESULT,
+                   arg_buf, startup_env, &ret_codes, exe_name);
+  ptrace_forking = FALSE;
+
+  xf86sup_all_enadup (FALSE);
+  if (rc != 0)
+    goto error;
+
+  pid = ret_codes.codeTerminate;
+  pte->status = PS_PROCESS;
+  pte->pid = pid;
+  pte->sid = 0;
+  pte->wait_ret = 0;
+  pte->flags = 0;
+  UNLOCK_PROCESS;
+  resources &= ~FORK_RSC_PROC;
+
+  child_started ();
+  rc = fork_wait (ack_sem, pid);
+  if (rc != 0)
+    goto error;
+
+  rc = fork_mem (shmem, req_sem, ack_sem, pid,
+                 layout->data_base, layout->bss_end, NULLHANDLE);
+  if (rc != 0)
+    goto error;
+  if (heap_obj_count != 0 && heap_objs[0].brk != 0)
+    {
+      rc = fork_mem (shmem, req_sem, ack_sem, pid, heap_objs[0].base,
+                     heap_objs[0].brk, NULLHANDLE);
+      if (rc != 0)
+        goto error;
+    }
+
+  /* Load registered DLLs. */
+
+  if (!(debug_flags & DEBUG_NOFORKDLL))
+    for (i = 0; i < fork_regdll_count; ++i)
+      if (fork_regdll[i].hmod != 0)
+        {
+          rc = fork_dll (shmem, req_sem, ack_sem, pid, fork_regdll[i].hmod);
+          if (rc != 0)
+            goto error;
+        }
+
+  /* Copy registered memory areas (DLL data segments). */
+
+  for (i = 0; i < fork_regmem_count; ++i)
+    if (fork_regmem[i].hmod != 0)
+      {
+        rc = fork_mem (shmem, req_sem, ack_sem, pid,
+                       fork_regmem[i].start, fork_regmem[i].end,
+                       fork_regmem[i].hmod);
+        if (rc != 0)
+          goto error;
+      }
+
+  rc = fork_mem (shmem, req_sem, ack_sem, pid, stk_low, stack_end, NULLHANDLE);
+  if (rc != 0)
+    goto error;
+
+  /* Send the final request to the child process.  The structure
+     contains data which will be kept by the child process in the
+     shared memory object until it can be used.  Therefore, this data
+     must be sent last. */
+
+  shmem->done.req_code = FORK_REQ_DONE;
+  shmem->done.size = sizeof (shmem->done);
+  td = threads[1];              /* Copy signal handlers of thread 1 */
+  memcpy (shmem->done.sig_actions, td->sig_table,
+          sizeof (shmem->done.sig_actions));
+  fileio_fork_parent_fillin (&shmem->done);
+  tcpip_fork_sock (&shmem->done);
+  resources |= FORK_RSC_SOCK;
+  rc = fork_send (req_sem, ack_sem, pid);
+  if (rc != 0)
+    goto error;
+  result = pid;
+  *errnop = 0;
+  goto done;
+
+error:
+  if (resources & FORK_RSC_SOCK)
+    tcpip_undo_fork_sock (&shmem->done);
+  result = -1;
+  *errnop = set_error (rc);
+
+done:
+  if (resources & FORK_RSC_PROC)
+    UNLOCK_PROCESS;
+  if (resources & FORK_RSC_FILEIO)
+    fileio_fork_parent_restore ();
+  if (resources & FORK_RSC_REQ)
+    close_event_sem (req_sem);
+  if (resources & FORK_RSC_ACK)
+    close_event_sem (ack_sem);
+  if (resources & FORK_RSC_MEM)
+    DosFreeMem (shmem);
+  fork_reg_cleanup ();
+  return result;
+}
Index: trunk/src/emx/src/os2/profil.c
===================================================================
--- trunk/src/emx/src/os2/profil.c	(revision 18)
+++ trunk/src/emx/src/os2/profil.c	(revision 18)
@@ -0,0 +1,233 @@
+/* profil.c -- Sampling profiler
+   Copyright (c) 1995-1996 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include "emxdll.h"
+#include "profil.h"
+#include "clib.h"
+
+static enum
+{
+  PS_INIT,
+  PS_FAIL,
+  PS_STOP,
+  PS_RUN
+} profil_state;
+
+static void *profil_buf;
+static unsigned profil_bufsiz;
+static unsigned profil_offset;
+static ULONG (*dosprofile)(ULONG, ULONG, PRFCMD *, PRFRET *);
+
+
+static int xdosprofile (ULONG func, ULONG pid, PRFCMD *cmd, PRFRET *ret)
+{
+  ULONG rc;
+
+  rc = dosprofile (func, pid, cmd, ret);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+static int profil_init (void)
+{
+  char obj[9];
+  HMODULE hmod;
+  ULONG rc;
+
+  profil_state = PS_FAIL;
+  rc = DosLoadModule (obj, sizeof (obj), "DOSCALLS", &hmod);
+  if (rc != 0)
+    return set_error (rc);
+  rc = DosQueryProcAddr (hmod, 377, NULL, (PPFN)&dosprofile);
+  if (rc != 0)
+    return set_error (rc);
+  profil_state = PS_STOP;
+  return 0;
+}
+
+
+static int profil_result (void)
+{
+  PRFRET prof_ret;
+  PRFRET3 *ret3;
+  ULONG ret3_size, rc;
+#ifdef DEBUG
+  PRFRET0 prof_ret0;
+  unsigned shift, i;
+#endif
+  int r;
+
+  if (profil_state != PS_RUN)
+    return set_error (ERROR_PRF_NOT_STARTED);
+  memset (profil_buf, 0, profil_bufsiz);
+  r = xdosprofile (PRF_CM_STOP, my_pid, NULL, NULL);
+  if (r != 0) return r;
+  profil_state = PS_STOP;
+
+#ifdef DEBUG
+  memset (&prof_ret0, 0, sizeof (prof_ret0));
+  prof_ret.us_cmd = PRF_RET_GLOBAL;
+  prof_ret.us_thrdno = 1;
+  prof_ret.us_vaddr = 0;
+  prof_ret.us_bufsz = sizeof (prof_ret0);
+  prof_ret.us_buf = &prof_ret0;
+  r = xdosprofile (PRF_CM_DUMP, my_pid, NULL, &prof_ret);
+  if (r != 0) return r;
+  shift = prof_ret0.r0_shift;
+  oprintf ("r0_shift=%u\r\n", shift);
+#endif
+
+  /* TODO: Overlay data preceding *profil_buff, if posible. */
+
+  ret3_size = profil_bufsiz + sizeof (PRFRET3);
+  rc = DosAllocMem ((PPVOID)&ret3, ret3_size,
+                    PAG_READ | PAG_WRITE | PAG_COMMIT);
+  if (rc != 0)
+    return set_error (rc);
+  memset (ret3, 0, ret3_size);
+
+  memset (&prof_ret, 0, sizeof (prof_ret));
+  prof_ret.us_cmd = PRF_RET_VADETAIL;
+  prof_ret.us_thrdno = 1;
+  prof_ret.us_vaddr = profil_offset;
+  prof_ret.us_bufsz = ret3_size;
+  prof_ret.us_buf = ret3;
+  r = xdosprofile (PRF_CM_DUMP, my_pid, NULL, &prof_ret);
+  if (r != 0)
+    {
+      DosFreeMem (ret3);
+      return r;
+    }
+  memcpy (profil_buf, ret3->r3_cnts, profil_bufsiz);
+#ifdef DEBUG
+  for (i = 0; i < ret3->r3_ncnts; ++i)
+    oprintf ("%#.8x: %u\r\n",
+             profil_offset + (i << shift), ret3->r3_cnts[i]);
+#endif
+  DosFreeMem (ret3);
+  return xdosprofile (PRF_CM_EXIT, my_pid, NULL, NULL);
+}
+
+
+static int profil_start (const struct _profil *p)
+{
+  int r;
+
+  profil_buf = p->buff; profil_bufsiz = p->bufsiz; profil_offset = p->offset;
+  memset (profil_buf, 0, profil_bufsiz);
+  if (profil_state == PS_RUN)
+    {
+      r = xdosprofile (PRF_CM_STOP, my_pid, NULL, NULL);
+      if (r != 0) return r;
+      profil_state = PS_STOP;
+      r = xdosprofile (PRF_CM_CLEAR, my_pid, NULL, NULL);
+      if (r != 0) return r;
+    }
+  if (p->scale == 2)
+    {
+      /* TODO */
+      return set_error (ERROR_INVALID_PARAMETER);
+    }
+  else if (p->scale == 0x10000 || p->scale == 0x8000 || p->scale == 0x4000)
+    {
+      PRFCMD prof_cmd;
+      PRFSLOT prof_slots[1];
+
+      memset (&prof_slots, 0, sizeof (prof_slots));
+      memset (&prof_cmd, 0, sizeof (prof_cmd));
+
+      prof_slots[0].sl_vaddr = profil_offset;
+      prof_slots[0].sl_size = p->bufsiz * (0x10000 / p->scale);
+      prof_slots[0].sl_mode = PRF_SL_PRFVA;
+
+#ifdef DEBUG
+      oprintf ("bufsiz=%#.8x\r\n", profil_bufsiz);
+      oprintf ("scale=%#.8x\r\n", p->scale);
+      oprintf ("sl_vaddr=%#.8x\r\n", prof_slots[0].sl_vaddr);
+      oprintf ("sl_size=%#.8x\r\n", prof_slots[0].sl_size);
+#endif
+
+      prof_cmd.cm_slots = prof_slots;
+      prof_cmd.cm_nslots = 1;
+      prof_cmd.cm_flags = PRF_PROCESS_ST | PRF_VADETAIL;
+      prof_cmd.cm_bufsz = profil_bufsiz;
+      prof_cmd.cm_timval = 1000;
+      prof_cmd.cm_flgbits = NULL;
+      prof_cmd.cm_nflgs = 0;
+
+      r = xdosprofile (PRF_CM_INIT, my_pid, &prof_cmd, NULL);
+      if (r != 0) return r;
+    }
+  r = xdosprofile (PRF_CM_START, my_pid, NULL, NULL);
+  if (r != 0) return r;
+  profil_state = PS_RUN;
+  return 0;
+}
+
+
+int do_profil (const struct _profil *p, int *errnop)
+{
+  int r;
+
+  if (p->cb < sizeof (struct _profil))
+    {
+      *errnop = set_error (ERROR_INVALID_PARAMETER);
+      return -1;
+    }
+
+  if (profil_state == PS_INIT)
+    {
+      r = profil_init ();
+      if (r != 0)
+        {
+          *errnop = r;
+          return -1;
+        }
+    }
+  if (profil_state == PS_FAIL)
+    {
+      *errnop = set_error (ERROR_CALL_NOT_IMPLEMENTED);
+      return -1;
+    }
+
+  if (p->scale == 0 || p->scale == 1)
+    r = profil_result ();
+  else
+    r = profil_start (p);
+  if (r != 0)
+    {
+      *errnop = r;
+      return -1;
+    }
+  *errnop = 0;
+  return 0;
+}
Index: trunk/src/emx/src/os2/profil.h
===================================================================
--- trunk/src/emx/src/os2/profil.h	(revision 18)
+++ trunk/src/emx/src/os2/profil.h	(revision 18)
@@ -0,0 +1,122 @@
+/* profil.h -- written by Holger Veit, donated to the public domain */
+
+typedef ULONG DWORD;
+typedef USHORT WORD;
+
+#define	PRF_CM_INIT	0	/* initialize, must pass pid and profcmd */
+#define	PRF_CM_START	1	/* start profiling (pid) */
+#define	PRF_CM_STOP	2	/* stop profiling (pid) */
+#define	PRF_CM_CLEAR	3	/* clear profile counters (pid) */
+#define PRF_CM_DUMP	4	/* read out profiling data (pid, profret) */
+#define PRF_CM_EXIT	5	/* exit profiling, delete profiling structures */
+
+#pragma pack(1)
+
+typedef struct {
+	DWORD	sl_vaddr;	/* start of VA segment to profile */
+	DWORD	sl_size;	/* length of VA segment */
+	DWORD	sl_mode;	/* !=0 use PRF_VA* flags, */
+				/* =0, simple count */
+#define PRF_SL_SIMPCNT	0
+#define PRF_SL_PRFVA	1
+
+} PRFSLOT;
+
+typedef struct {
+	PRFSLOT	*cm_slots;	/* Virtual address slots */
+	WORD	cm_nslots;	/* # of VA slots < 256 (!) */
+	WORD	cm_flags;	/* command */
+#define PRF_PROCESS_MT	0	/* profile proc+threads */
+#define PRF_PROCESS_ST	1	/* profile proc only */
+#define PRF_KERNEL	2	/* profile kernel */
+
+#define PRF_VADETAIL	0	/* create detailed page counters */
+#define PRF_VAHIT	4	/* create hit table */
+#define PRF_VATOTAL	8	/* create total count for VA only */
+
+#define PRF_FLGBITS	0x40	/* has a flgbits structure (?) */
+#define PRF_WRAP	0x80	/* don't use: if hit table full, wrap */
+				/* there is a bug in kernel, which */
+				/* prevents this from correct working! */
+
+/* status bits, don't ever set these (won't work, not masked, bug!) */
+#define PRFS_RUNNING	0x100	/* profiling is active */
+#define PRFS_THRDS	0x200	/* also profiling threads */
+#define PRFS_HITOVFL	0x800	/* overflow in hit buffer */
+#define PRFS_HEADER	0x1000	/* internally used */
+
+	DWORD	cm_bufsz;	/* reserve # of bytes for buffers */
+				/* e.g. for hit buffer or detailed */
+				/* counters */
+	WORD	cm_timval;	/* timer resolution */
+				/* if 0, use default == 1000 */
+	/* valid if PRF_FLAGBITS set */
+	BYTE*	cm_flgbits;	/* vector of flag bits (?) */
+	BYTE	cm_nflgs;	/* # of flag bits >= 2 if present */
+} PRFCMD;	/* 19 bytes */
+
+typedef struct {
+	DWORD	va_vaddr;	/* virtual address of segment */
+	DWORD	va_size;	/* length of segment */
+	DWORD	va_flags;	/* == 8, va_cnt is valid */
+	DWORD	va_reserved;	/* internally used */
+	DWORD	va_cnt;		/* profile count */
+} PRFVA;
+
+typedef struct {
+	BYTE	us_cmd;		/* command */
+#define PRF_RET_GLOBAL	0	/* return global data */
+				/* set us_thrdno for specific thread */
+				/* us_buf = struct PRFRET0 */
+#define	PRF_RET_VASLOTS	1	/* return VA slot data (PRFRET1) */
+#define PRF_RET_VAHITS	2	/* return hit table (PRFRET2) */
+#define PRF_RET_VADETAIL 3	/* return detailed counters (PRFRET3) */
+				/* specify us_vaddr */
+
+	WORD	us_thrdno;	/* thread requested for cmd=0 */
+	DWORD	us_vaddr;	/* VA for cmd=3*/
+	DWORD	us_bufsz;	/* length of return buffer */
+	VOID	*us_buf;	/* return buffer */
+} PRFRET;	/* 15 bytes */
+
+typedef struct {
+	WORD	r0_flags;	/* profile flags */
+				/* see PRF_* defines */
+	BYTE	r0_shift;	/* shift factor */
+				/* 2^N = length of a segment for */
+				/* detailed counters */
+	DWORD	r0_idle;	/* count if process is idle */
+	DWORD	r0_vm86;	/* count if process is in VM mode */
+	DWORD	r0_kernel;	/* count if process is in kernel */
+	DWORD	r0_shrmem;	/* count if process is in shr mem */
+	DWORD	r0_unknown;	/* count if process is elsewhere */
+	DWORD	r0_nhitbufs;	/* # of dwords in hitbufs */
+	DWORD	r0_hitbufcnt;	/* # of entries in hit table */
+	DWORD	r0_reserved1;	/* internally used */
+	DWORD	r0_reserved2;	/* internally used */
+	WORD	r0_timval;	/* timer resolution */
+	BYTE	r0_errcnt;	/* error count */
+	WORD	r0_nstruc1;	/* # of add structures 1 (?) */
+	WORD	r0_nstruc2;	/* # of add structures 2 (?) */
+} PRFRET0;
+
+typedef struct {
+	BYTE	r1_nslots;	/* # of slots (bug: prevents */
+				/* correct # if #slots >255) */
+	PRFVA	r1_slots[1];	/* slots */
+} PRFRET1;
+
+typedef struct {
+	DWORD	r2_nhits;	/* # of entries in table */
+	DWORD	r2_hits[1];	/* hit table */
+} PRFRET2;
+
+typedef struct {
+	DWORD	r3_size;	/* size of segment */
+	DWORD	r3_ncnts;	/* # of entries in table */
+	DWORD	r3_cnts[1];	/* counters */
+} PRFRET3;
+
+#pragma pack()
+
+ULONG DosProfile (DWORD func, PID pid, PRFCMD *profcmd, PRFRET *profret);
Index: trunk/src/emx/src/os2/ptrace.c
===================================================================
--- trunk/src/emx/src/os2/ptrace.c	(revision 18)
+++ trunk/src/emx/src/os2/ptrace.c	(revision 18)
@@ -0,0 +1,1689 @@
+/* ptrace.c -- Implement ptrace()
+   Copyright (c) 1994-1996 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSPROCESS
+#define INCL_DOSSESMGR
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSMODULEMGR
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include "clib.h"
+#include <sys/signal.h>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+#include "reg.h"
+#include <sys/errno.h>
+#include <sys/uflags.h>
+#include "emxdll.h"
+
+#define DR_SERVER_HEV_CLIENT    0x0001
+#define DR_SERVER_HEV_SERVER    0x0002
+#define DR_CLIENT_HEV_CLIENT    0x0004
+#define DR_CLIENT_HEV_SERVER    0x0008
+#define DR_LIST                 0x0010
+
+#define SHAREMEM_FMT    "/sharemem/emx/ptrace/%.8x.atc"
+
+#define REQ_ATTACH      17
+#define REQ_DOSDEBUG    18
+#define REQ_DETACH      19
+
+#define USEROFF(F) offsetof (struct user, F)
+#define DBGOFF(F) offsetof (uDB_t, F)
+#define CTXOFF(F) offsetof (CONTEXTRECORD, F)
+
+#define PTRACE_REG_COUNT sizeof (ptrace_regs) / sizeof (ptrace_regs[0])
+
+struct reg_table
+{
+  ULONG reg;
+  ULONG user_offset;
+  ULONG dbg_offset;
+  ULONG ctx_offset;
+  BYTE len;
+};
+
+struct co_regs
+{
+  USHORT cw;
+  USHORT unused1;
+  USHORT sw;
+  USHORT unused2;
+  USHORT tw;
+  USHORT unused3;
+  ULONG fip;
+  USHORT fcs;
+  USHORT fop;
+  ULONG foo;
+  USHORT fos;
+  USHORT unused4;
+  BYTE fst[8][10];
+};
+
+enum dbg_type
+{
+  DT_LOCAL,
+  DT_SERVER,
+  DT_CLIENT
+};
+
+struct debuggee
+{
+  struct debuggee *next;        /* Next debuggee */
+  enum dbg_type type;           /* Type of debuggee */
+  ULONG resources;              /* Acquired resources: DR_*. */
+  ULONG pid;                    /* Process ID */
+  ULONG sid;                    /* Session ID */
+  ULONG syscall_addr;           /* Address of CALL _emx_syscall, or 0 */
+  ULONG layout_addr;            /* Address of layout table, or 0 */
+  ULONG signo;                  /* Signal number, or 0 */
+  ULONG context;                /* Address of exception context record, or 0 */
+  ULONG last_cmd;               /* Last command */
+  ULONG regs[19];               /* Current registers */
+  ULONG exc_regs[19];           /* Registers for exception handler */
+  uDB_t dbgbuf;                 /* Buffer for DosDebug, includes registers */
+  struct co_regs dbgco;         /* Floating point status */
+
+  ULONG ptn;                    /* Notification for debugger */
+  ULONG ptn_hmte;               /* For PTN_MODULE_LOAD and PTN_MODULE_FREE */
+  ULONG ptn_tid;                /* For PTN_THREAD_NEW and PTN_THREAD_END */
+  ULONG ptn_pid;                /* For PTN_PROC_NEW */
+  ULONG ptn_flags;              /* For PTN_PROC_NEW */
+  ULONG ptn_fork_addr;          /* For PTN_PROC_NEW */
+  char ptn_name[260];           /* For PTN_PROC_NEW */
+
+  ULONG n_cmd;                  /* run() interrupted by notification: CMD */
+  ULONG n_tbreak;               /* Ditto, TBREAK */
+  ULONG n_signo;                /* Ditto, SIGNO */
+  ULONG n_tid;                  /* Ditto, TID */
+
+  ULONG regs_tid;               /* Registers retrieved for this thread */
+  ULONG server_request;         /* Request for DosDebug server */
+  ULONG server_rc;              /* Return code of DosDebug on server */
+  ULONG server_arg;             /* Argument passed to server */
+  HEV hev_server;               /* Data ready for DosDebug server */
+  HEV hev_client;               /* Data ready for DosDebug client */
+
+  BYTE regs_changed;            /* Registers changed */
+  BYTE fpregs_ok;               /* Floating point registers retrieved */
+  BYTE auto_switch;             /* Automatic session switching enabled */
+  BYTE brk_flag;                /* Break point hit */
+  BYTE more;                    /* Step/run again */
+  BYTE ptn_flag;                /* Notification sent to debugger */
+};
+
+
+/* We keep a linked list of processes being debugged. */
+
+static struct debuggee *dbg_head;
+
+/* Here, we cache the most recently access debuggee. */
+
+static struct debuggee *dbg_cache;
+
+/* Table for converting between user struct offsets, uDB_t offsets,
+   and CONTEXTRECORD offsets.  It also contains the lengths of the
+   members. */
+
+static struct reg_table const ptrace_regs[] =
+{
+  {R_GS,   USEROFF (u_regs[R_GS]),   DBGOFF (GS),     CTXOFF (ctx_SegGs),  2},
+  {R_FS,   USEROFF (u_regs[R_FS]),   DBGOFF (FS),     CTXOFF (ctx_SegFs),  2},
+  {R_ES,   USEROFF (u_regs[R_ES]),   DBGOFF (ES),     CTXOFF (ctx_SegEs),  2},
+  {R_DS,   USEROFF (u_regs[R_DS]),   DBGOFF (DS),     CTXOFF (ctx_SegDs),  2},
+  {R_EDI,  USEROFF (u_regs[R_EDI]),  DBGOFF (EDI),    CTXOFF (ctx_RegEdi), 4},
+  {R_ESI,  USEROFF (u_regs[R_ESI]),  DBGOFF (ESI),    CTXOFF (ctx_RegEsi), 4},
+  {R_EBP,  USEROFF (u_regs[R_EBP]),  DBGOFF (EBP),    CTXOFF (ctx_RegEbp), 4},
+  {R_ESP,  USEROFF (u_regs[R_ESP]),  DBGOFF (ESP),    CTXOFF (ctx_RegEsp), 4},
+  {R_EBX,  USEROFF (u_regs[R_EBX]),  DBGOFF (EBX),    CTXOFF (ctx_RegEbx), 4},
+  {R_EDX,  USEROFF (u_regs[R_EDX]),  DBGOFF (EDX),    CTXOFF (ctx_RegEdx), 4},
+  {R_ECX,  USEROFF (u_regs[R_ECX]),  DBGOFF (ECX),    CTXOFF (ctx_RegEcx), 4},
+  {R_EAX,  USEROFF (u_regs[R_EAX]),  DBGOFF (EAX),    CTXOFF (ctx_RegEax), 4},
+  {R_EIP,  USEROFF (u_regs[R_EIP]),  DBGOFF (EIP),    CTXOFF (ctx_RegEip), 4},
+  {R_CS,   USEROFF (u_regs[R_CS]),   DBGOFF (CS),     CTXOFF (ctx_SegCs),  2},
+  {R_EFL,  USEROFF (u_regs[R_EFL]),  DBGOFF (EFlags), CTXOFF (ctx_EFlags), 4},
+  {R_UESP, USEROFF (u_regs[R_UESP]), DBGOFF (ESP),    CTXOFF (ctx_RegEsp), 4},
+  {R_SS,   USEROFF (u_regs[R_SS]),   DBGOFF (SS),     CTXOFF (ctx_SegSs),  2}
+};
+
+
+/* Prototypes for forward references. */
+
+static ULONG start_debug_descendant (struct debuggee *parent);
+static ULONG start_debug_descendant_2 (struct debuggee *parent,
+    struct debuggee *child);
+static ULONG do_attach (ULONG pid);
+static ULONG do_detach (struct debuggee *d, ULONG addr);
+static ULONG call_server (struct debuggee *d, ULONG request);
+static ULONG free_debuggee (struct debuggee *d, ULONG return_value);
+
+
+static const struct reg_table *user_addr (ULONG addr)
+{
+  int i;
+
+  for (i = 0; i < PTRACE_REG_COUNT; ++i)
+    if (ptrace_regs[i].user_offset == addr)
+      return &ptrace_regs[i];
+  return NULL;
+}
+
+
+static ULONG debug (struct debuggee *d, ULONG cmd)
+{
+  ULONG rc;
+
+  d->dbgbuf.Cmd = cmd;
+  d->dbgbuf.Pid = d->pid;
+  d->last_cmd = cmd;
+  if (d->type == DT_CLIENT)
+    {
+      rc = call_server (d, REQ_DOSDEBUG);
+      if (rc == 0)
+        rc = d->server_rc;
+    }
+  else
+    rc = DosDebug (&d->dbgbuf);
+  return (rc == 0 ? 0 : set_error (rc));
+}
+
+
+static ULONG debug_read_8 (struct debuggee *d, ULONG addr, BYTE *dst)
+{
+  ULONG rc;
+
+  d->dbgbuf.Addr = addr;
+  rc = debug (d, DBG_C_ReadMem);
+  if (rc != 0 || d->dbgbuf.Cmd != DBG_N_Success) return EIO;
+  *dst = (BYTE)d->dbgbuf.Value;
+  return 0;
+}
+
+
+static ULONG debug_read_16 (struct debuggee *d, ULONG addr, USHORT *dst)
+{
+  ULONG rc;
+
+  d->dbgbuf.Addr = addr;
+  rc = debug (d, DBG_C_ReadMem);
+  if (rc != 0 || d->dbgbuf.Cmd != DBG_N_Success) return EIO;
+  *dst = (USHORT)d->dbgbuf.Value;
+  return 0;
+}
+
+
+static ULONG debug_read_32 (struct debuggee *d, ULONG addr, ULONG *dst)
+{
+  ULONG rc, w;
+
+  d->dbgbuf.Addr = addr;
+  rc = debug (d, DBG_C_ReadMem);
+  if (rc != 0 || d->dbgbuf.Cmd != DBG_N_Success) return EIO;
+  w = d->dbgbuf.Value & 0xffff;
+  d->dbgbuf.Addr = addr + 2;
+  rc = debug (d, DBG_C_ReadMem);
+  if (rc != 0 || d->dbgbuf.Cmd != DBG_N_Success) return EIO;
+  w |= (d->dbgbuf.Value & 0xffff) << 16;
+  *dst = w;
+  return 0;
+}
+
+
+static void do_auto_switch (struct debuggee *d)
+{
+  DosSelectSession (d->sid);
+  d->auto_switch = FALSE;
+}
+
+
+static int debug_poke16 (struct debuggee *d, ULONG addr, ULONG value)
+{
+  ULONG rc;
+
+  d->dbgbuf.Addr  = addr;
+  d->dbgbuf.Value = value;
+  rc = debug (d, DBG_C_WriteMem);
+  if (rc == 0 && d->dbgbuf.Cmd != DBG_N_Success)
+    rc = EIO;
+  return rc;
+}
+
+
+/* Write the registers.  TID is the thread ID (which must be
+   non-zero).  Return errno. */
+
+static ULONG write_reg (struct debuggee *d, ULONG tid)
+{
+  ULONG rc, i;
+
+  if (d->regs_tid != tid)
+    return EIO;
+
+  for (i = 0; i < PTRACE_REG_COUNT; ++i)
+    memcpy ((char *)&d->dbgbuf + ptrace_regs[i].dbg_offset,
+            &d->regs[ptrace_regs[i].reg], ptrace_regs[i].len);
+
+  d->dbgbuf.Tid = tid;
+  rc = debug (d, DBG_C_WriteReg);
+  if (rc == 0 && d->dbgbuf.Cmd != DBG_N_Success)
+    rc = EIO;
+  if (rc == 0)
+    d->regs_changed = FALSE;
+  return rc;
+}
+
+
+/* Read the registers.  TID is the thread ID (0 means the active
+   thread).  Return errno. */
+
+static ULONG read_reg (struct debuggee *d, ULONG tid)
+{
+  ULONG rc, i;
+  USHORT us;
+
+  if (d->regs_tid != 0 && d->regs_tid == tid)
+    return 0;
+
+  /* Read registers from a new or a different thread.  Write back the
+     registers to the previous thread if required. */
+
+  if (d->regs_changed)
+    write_reg (d, d->regs_tid);
+
+  memset (d->regs, 0, sizeof (d->regs));
+  memset (d->exc_regs, 0, sizeof (d->exc_regs));
+
+  d->dbgbuf.Tid = tid;
+  rc = debug (d, DBG_C_ReadReg);
+  if (rc == 0 && d->dbgbuf.Cmd != DBG_N_Success)
+    rc = EIO;
+  if (rc != 0) return rc;
+  for (i = 0; i < PTRACE_REG_COUNT; ++i)
+    memcpy (&d->regs[ptrace_regs[i].reg],
+            (char *)&d->dbgbuf + ptrace_regs[i].dbg_offset,
+            ptrace_regs[i].len);
+
+  if (d->context != 0)
+    {
+      /* After an exception, get the registers from the exception
+         context record. */
+
+      memcpy (d->exc_regs, d->regs, sizeof (d->exc_regs));
+      for (i = 0; i < PTRACE_REG_COUNT; ++i)
+        {
+          if (ptrace_regs[i].len == 4)
+            rc = debug_read_32 (d, d->context + ptrace_regs[i].ctx_offset,
+                                &d->regs[ptrace_regs[i].reg]);
+          else
+            {
+              rc = debug_read_16 (d, d->context + ptrace_regs[i].ctx_offset,
+                                  &us);
+              d->regs[ptrace_regs[i].reg] = us;
+            }
+          if (rc != 0) return rc;
+        }
+    }
+  d->regs_tid = d->dbgbuf.Tid;
+  return rc;
+}
+
+
+/* Set a watchpoint.  Return errno. */
+
+static ULONG set_watch (struct debuggee *d, ULONG addr, ULONG len, ULONG type)
+{
+  ULONG rc;
+
+  d->dbgbuf.Addr  = addr;
+  d->dbgbuf.Len   = len;
+  d->dbgbuf.Index = 0;          /* Reserved */
+  d->dbgbuf.Value = type | DBG_W_Local;
+  rc = debug (d, DBG_C_SetWatch);
+  /* TODO: Check notification code? */
+  return rc;
+}
+
+
+static ULONG terminate (struct debuggee *d)
+{
+  ULONG rc;
+
+  d->regs_tid = 0; d->fpregs_ok = FALSE;
+  rc = debug (d, DBG_C_Term);
+  if (rc != 0)
+    return rc;
+  return free_debuggee (d, 0);
+}
+
+
+/* TODO: Have two register sets, see read_reg(). */
+
+static ULONG get_fpstate (struct debuggee *d)
+{
+  ULONG rc, i, flags;
+
+  if (d->context != 0)
+    {
+      /* After an exception, get the floating point state from the
+         exception context record. */
+
+      d->fpregs_ok = FALSE;
+      memset (&d->dbgco, 0, sizeof (d->dbgco));
+
+      rc = debug_read_32 (d, d->context + CTXOFF (ContextFlags), &flags);
+      if (rc != 0) return rc;
+
+      if (!(flags & CONTEXT_FLOATING_POINT))
+        return 0;
+
+      for (i = 0; i < sizeof (struct co_regs); i += 2)
+        {
+          rc = debug_read_16 (d, d->context + CTXOFF (ctx_env) + i,
+                              (USHORT *)((char *)&d->dbgco + i));
+          if (rc != 0) return rc;
+        }
+      d->fpregs_ok = TRUE;
+      return 0;
+    }
+  d->dbgbuf.Tid    = 0;            /* Thread: active thread */
+  d->dbgbuf.Value  = DBG_CO_387;   /* Coprocessor type */
+  d->dbgbuf.Buffer = (ULONG)&d->dbgco;
+  d->dbgbuf.Len    = sizeof (d->dbgco);
+  d->dbgbuf.Index  = 0;            /* Reserved */
+  rc = debug (d, DBG_C_ReadCoRegs);
+  if (rc == 0 && d->dbgbuf.Cmd != DBG_N_Success)
+    rc = EIO;
+  d->fpregs_ok = (rc == 0);
+  return rc;
+}
+
+
+/* Return true if EIP points to a CALL instruction.  Moreover, true is
+   returned if an error occurs (to be on the safe side for
+   automatically switching to the child session). */
+
+static int callp (struct debuggee *d)
+{
+  ULONG eip, rc;
+  BYTE b;
+
+  /* Do not call read_reg() as that would set `d->regs_tid'. */
+
+  d->dbgbuf.Tid = 0;
+  rc = debug (d, DBG_C_ReadReg);
+  if (rc != 0 || d->dbgbuf.Cmd != DBG_N_Success)
+    return TRUE;
+  eip = d->dbgbuf.EIP;
+
+  /* Skip prefixes. */
+
+  do
+    {
+      rc = debug_read_8 (d, eip++, &b);
+      if (rc != 0) return TRUE;
+    } while ((b & 0xe7) == 0x26 /* Segment override prefix */
+             || b == 0x64       /* FS prefix */
+             || b == 0x65       /* GS prefix */
+             || b == 0x66       /* Operand size prefix */
+             || b == 0x67);     /* Address size prefix */
+
+  /* Check for `CALL immediate' instruction. */
+
+  if (b == 0xe8 || b == 0x9a)   /* CALL near label, CALL far label*/
+    return TRUE;
+
+  /* Check for `CALL indirect' instruction. */
+
+  if (b == 0xff)
+    {
+      rc = debug_read_8 (d, eip++, &b);
+      if (rc != 0) return TRUE;
+      /* Note: This was off by one bit in child.asm! */
+      if ((b & 0x38) == 0x10)   /* CALL near reg/mem */
+        return TRUE;
+      if ((b & 0x38) == 0x18)   /* CALL far reg/mem */
+        return TRUE;
+    }
+  return FALSE;
+}
+
+
+#define N_STOP                  (-1)
+#define N_CONTINUE_STOP         (-2)
+#define N_CONTINUE_SEARCH       (-3)
+#define N_CONTINUE_EXECUTION    (-4)
+#define N_RESUME                (-5)
+#define N_NOTIFY                (-6)
+
+
+static void set_wait_cur_thread (struct debuggee *d, ULONG wait_ret)
+{
+  ULONG rc, tid;
+
+  if ((uflags & _UF_PTRACE_MODEL) != _UF_PTRACE_MULTITHREAD)
+    tid = 0;
+  else
+    {
+      d->dbgbuf.Tid = 0;        /* Current thread */
+      rc = debug (d, DBG_C_ReadReg);
+      if (rc != 0 || d->dbgbuf.Cmd != DBG_N_Success)
+        tid = 0;
+      else
+        tid = d->dbgbuf.Tid;
+    }
+  debug_set_wait (d->pid, tid, wait_ret, FALSE);
+}
+
+
+static int debug_signal (struct debuggee *d, int signo, int context_flag)
+{
+  d->more = FALSE;
+  set_wait_cur_thread (d, 0x7f | (signo << 8));
+  if (context_flag)
+    {
+      d->context = d->dbgbuf.Len; /* Address of context buffer */
+      d->signo = signo;
+    }
+  return 0;
+}
+
+
+static int n_exception (struct debuggee *d)
+{
+  int rc;
+  ULONG report, info, w;
+
+  switch (d->dbgbuf.Value)
+    {
+    case DBG_X_PRE_FIRST_CHANCE: /* pre first chance */
+    case DBG_X_STACK_INVALID:   /* invalid stack */
+      /* The exception number is in d->dbgbuf.Buffer. */
+      if (d->dbgbuf.Buffer == XCPT_BREAKPOINT)
+        {
+          d->brk_flag = TRUE; d->more = FALSE;
+          set_wait_cur_thread (d, 0x7f | (SIGTRAP << 8));
+          return N_CONTINUE_STOP;
+        }
+      else if (d->dbgbuf.Buffer == XCPT_SINGLE_STEP)
+        {
+          d->more = FALSE;
+          set_wait_cur_thread (d, 0x7f | (SIGTRAP << 8));
+          return N_CONTINUE_STOP;
+        }
+      break;
+
+    case DBG_X_FIRST_CHANCE:    /* first chance */
+      report = d->dbgbuf.Buffer; /* Address of report buffer */
+      rc = debug_read_32 (d, report + offsetof (EXCEPTIONREPORTRECORD,
+                                                  ExceptionNum), &w);
+      if (rc == 0)
+        switch (w)
+          {
+          case XCPT_GUARD_PAGE_VIOLATION:
+          case XCPT_PROCESS_TERMINATE:
+          case XCPT_ASYNC_PROCESS_TERMINATE:
+            return N_CONTINUE_SEARCH;
+
+          case XCPT_ACCESS_VIOLATION:
+          case XCPT_DATATYPE_MISALIGNMENT:
+            return debug_signal (d, SIGSEGV, TRUE);
+
+          case XCPT_INTEGER_DIVIDE_BY_ZERO:
+          case XCPT_INTEGER_OVERFLOW:
+          case XCPT_ARRAY_BOUNDS_EXCEEDED:
+          case XCPT_FLOAT_DENORMAL_OPERAND:
+          case XCPT_FLOAT_DIVIDE_BY_ZERO:
+          case XCPT_FLOAT_INEXACT_RESULT:
+          case XCPT_FLOAT_INVALID_OPERATION:
+          case XCPT_FLOAT_OVERFLOW:
+          case XCPT_FLOAT_STACK_CHECK:
+          case XCPT_FLOAT_UNDERFLOW:
+            return debug_signal (d, SIGFPE, TRUE);
+
+          case XCPT_ILLEGAL_INSTRUCTION:
+          case XCPT_INVALID_LOCK_SEQUENCE:
+          case XCPT_PRIVILEGED_INSTRUCTION:
+            return debug_signal (d, SIGILL, TRUE);
+
+          case XCPT_SIGNAL:
+            info = offsetof (EXCEPTIONREPORTRECORD, ExceptionInfo) + 0;
+            rc = debug_read_32 (d, report + info, &w);
+            if (rc == 0)
+              switch (w)
+                {
+                case XCPT_SIGNAL_INTR:
+                  return debug_signal (d, SIGINT, TRUE);
+
+                case XCPT_SIGNAL_BREAK:
+                  return debug_signal (d, SIGBREAK, TRUE);
+
+                case XCPT_SIGNAL_KILLPROC:
+                  return debug_signal (d, SIGTERM, TRUE);
+                }
+            break;
+
+          default:
+            return debug_signal (d, SIGSEGV, TRUE);
+          }
+      break;
+
+    case DBG_X_LAST_CHANCE:     /* last chance */
+
+      return N_CONTINUE_SEARCH;
+    }
+
+  return debug_signal (d, SIGSEGV, FALSE);
+}
+
+
+/* Possible notification for the debugger. */
+
+static int notify (struct debuggee *d, int ptn)
+{
+  if ((uflags & _UF_PTRACE_MODEL) == _UF_PTRACE_STANDARD)
+    return N_CONTINUE_STOP;
+  set_wait_cur_thread (d, 0x7f | (SIGPTRACENOTIFY << 8));
+  d->ptn = ptn;
+  d->ptn_flag = TRUE;
+  return N_NOTIFY;
+}
+
+
+/* Handle the current notification and return N_STOP, N_CONTINUE_STOP,
+   N_CONTINUE_SEARCH, N_RESUME, or errno (non-negative). */
+
+static int notification (struct debuggee *d)
+{
+  int rc;
+
+  switch (d->dbgbuf.Cmd)
+    {
+    case DBG_N_Success:
+
+      /* The request was completed successfully.  Run or step again
+         unless `d->more' has been set to FALSE. */
+
+      if (d->more)
+        return N_RESUME;
+
+      /* Running or stepping the debuggee is completed.  Read the
+         registers.  Skip over INT3 if a breakpoint was hit. */
+
+      rc = read_reg (d, 0);
+      if (rc == 0 && d->brk_flag)
+        {
+          /* Skip the INT3 instruction for compatibility with emx.exe
+             and GDB. */
+
+          d->regs[R_EIP] += 1;  /* Skip INT3 */
+          d->regs_changed = TRUE;
+        }
+      return rc;                /* ptrace() successful (usually) */
+
+    case DBG_N_Error:
+
+      /* An error occured. */
+
+#if 0
+      oprintf ("DosDebug (%d) error: %d\r\n",
+               (int)d->last_cmd, (int)d->dbgbuf.Value);
+#endif
+      return set_error (d->dbgbuf.Value);
+
+    case DBG_N_ProcTerm:
+
+      /* Process terminated.  Let wait() return the termination
+         code. */
+
+      debug_set_wait (d->pid, 0, (d->dbgbuf.Value & 0xff) << 8, TRUE);
+      d->more = FALSE;
+      rc = terminate (d);
+      return rc;                /* ptrace() successful (usually) */
+
+    case DBG_N_Exception:
+
+      /* An exception occured. */
+
+      return n_exception (d);
+
+    case DBG_N_ModuleLoad:
+      d->ptn_hmte = d->dbgbuf.Value;
+      return notify (d, PTN_MODULE_LOAD);
+
+    case DBG_N_ModuleFree:
+      d->ptn_hmte = d->dbgbuf.Value;
+      return notify (d, PTN_MODULE_FREE);
+
+    case DBG_N_ThreadCreate:
+      d->ptn_tid = d->dbgbuf.Tid;
+      return notify (d, PTN_THREAD_NEW);
+
+    case DBG_N_ThreadTerm:
+      rc = notify (d, PTN_THREAD_END);
+      if (rc == N_NOTIFY)
+        {
+          d->dbgbuf.Tid = 0;
+          if (debug (d, DBG_C_ReadReg) != 0 || d->dbgbuf.Cmd != DBG_N_Success)
+            rc = EINVAL;
+          else
+            d->ptn_tid = d->dbgbuf.Tid;
+        }
+      return rc;
+
+    case DBG_N_NewProc:
+      rc = notify (d, PTN_PROC_NEW);
+      if (rc == N_NOTIFY)
+        {
+          d->ptn_pid = d->dbgbuf.Value;
+          d->ptn_name[0] = 0;
+          d->ptn_fork_addr = 0;
+          d->ptn_flags = 0;
+          rc = start_debug_descendant (d);
+        }
+      return rc;
+
+    case DBG_N_Watchpoint:
+
+      /* Watchpoint hit.  Watchpoints are currently used only for
+         skipping over the call to emx_syscall when single-stepping.
+         Stop the debuggee and let wait() indicate SIGTRAP. */
+
+      d->more = FALSE;
+      set_wait_cur_thread (d, 0x7f | (SIGTRAP << 8));
+      return N_STOP;
+
+    case DBG_N_AliasFree:
+    default:
+
+      /* These notifications are not expected to occur. */
+
+      oprintf ("Unexpected DosDebug notification: %d\r\n",
+               (int)d->dbgbuf.Cmd);
+      quit (255);
+    }
+}
+
+
+/* Perform a DBG_C_Go or DBG_C_SStep command.  Set a breakpoint at
+   address TBREAK, if non-zero.  Send signal SIGNO, if non-zero. */
+
+static ULONG run (struct debuggee *d, ULONG cmd, ULONG tbreak, ULONG signo,
+                  ULONG tid)
+{
+  ULONG rc;
+  int next;
+
+  d->ptn_flag = FALSE;
+
+  /* For now, we support raising only that signal by which the
+     debuggee has been stopped. */
+
+  if (signo != 0 && signo != d->signo)
+    return EINVAL;
+
+  /* Automatically switch sessions now for DBG_C_Go.  (For
+     DBG_C_SStep, that will be done later, depending on the thread
+     context.) */
+
+  if (d->auto_switch && cmd == DBG_C_Go)
+    do_auto_switch (d);
+
+  /* Set a breakpoint at address TBREAK, if non-zero.  This is used
+     for avoiding stepping into emx.dll (which would confuse GDB). */
+
+  if (tbreak != 0)
+    {
+      rc = set_watch (d, tbreak, 1, DBG_W_Execute);
+      if (rc != 0) return rc;
+    }
+
+  /* If the debuggee has been stopped by an exception, special
+     processing is required now.  Note that DBG_C_Continue has not yet
+     been performed in that case (still in first chance
+     processing). */
+
+  if (d->signo != 0)
+    {
+      if (signo == d->signo)
+        {
+          /* Restore the exception handler context, and call user
+             exception handlers. */
+
+          memcpy (d->regs, d->exc_regs, sizeof (d->regs));
+          next = N_CONTINUE_SEARCH;
+        }
+      else
+        {
+          /* Restore the exception context (retrieved from the
+             exception context record), and do not call user exception
+             handlers. */
+
+          next = N_CONTINUE_EXECUTION;
+        }
+      d->regs_changed = TRUE;   /* Write back registers */
+
+      /* Special processing of exception done (except for the action
+         indicated by `next'. */
+
+      d->context = 0;
+      d->signo = 0;
+    }
+  else
+    next = N_RESUME;
+
+  /* If any registers have been changed, write them to the
+     debuggee. */
+
+  if (d->regs_changed)
+    {
+      rc = write_reg (d, d->regs_tid);
+      if (rc != 0) return rc;
+    }
+
+  d->more = TRUE; d->brk_flag = FALSE;
+  d->regs_tid = 0; d->fpregs_ok = FALSE;
+
+  for (;;)
+    {
+      switch (next)
+        {
+        case N_RESUME:
+          if (d->auto_switch && cmd == DBG_C_SStep && callp (d))
+            do_auto_switch (d);
+          d->dbgbuf.Tid = tid;
+          rc = debug (d, cmd);
+          if (rc != 0) return rc;
+          break;
+
+        case N_STOP:
+          rc = debug (d, DBG_C_Stop);
+          if (rc != 0) return rc;
+          break;
+
+        case N_CONTINUE_STOP:
+        case N_CONTINUE_SEARCH:
+        case N_CONTINUE_EXECUTION:
+
+          d->dbgbuf.Tid = 0;
+          rc = debug (d, DBG_C_ReadReg);
+          if (rc != 0 || d->dbgbuf.Cmd != DBG_N_Success)
+            d->dbgbuf.Tid = 1;
+
+          if (next == N_CONTINUE_SEARCH)
+            d->dbgbuf.Value = XCPT_CONTINUE_SEARCH;
+          else if (next == N_CONTINUE_EXECUTION)
+            d->dbgbuf.Value = XCPT_CONTINUE_EXECUTION;
+          else
+            d->dbgbuf.Value = XCPT_CONTINUE_STOP;
+          rc = debug (d, DBG_C_Continue);
+          if (rc != 0) return rc;
+          break;
+
+        case N_NOTIFY:
+          d->n_cmd = cmd;
+          d->n_tbreak = tbreak;
+          d->n_signo = signo;
+          d->n_tid = tid;
+          return 0;
+
+        default:
+          /* errno value */
+          return (ULONG)next;
+        }
+      next = notification (d);
+    }
+}
+
+
+/* Read a 32-bit word from the layout table of the module, for
+   find_module_layout().  Note that this macro uses local variables of
+   find_module_layout(). */
+
+#define READ_LAYOUT(member,dst) \
+  (debug_read_32 (d, addr_layout + offsetof (layout_table, member), dst) == 0)
+
+
+/* Set the object addresses and sizes in the structure pointed to by
+   PMODULE, if possible. */
+
+static void find_module_layout (struct debuggee *d, struct ptn_module *pmodule)
+{
+  ULONG addr_1, addr_2, addr_layout, flags;
+  ULONG text_base, text_end, data_base, data_end, bss_base, bss_end;
+  BYTE b;
+
+  /* Get the address of the 1st object, which is supposed to be the
+     .text object. */
+
+  d->dbgbuf.Value = 1;
+  d->dbgbuf.MTE = d->ptn_hmte;
+  if (debug (d, DBG_C_NumToAddr) != 0)
+    return;
+  addr_1 = d->dbgbuf.Addr;
+
+  /* Get the address of the 2nd object, which is supposed to be the
+     .data object. */
+
+  d->dbgbuf.Value = 2; /* 2nd object */
+  d->dbgbuf.MTE = d->ptn_hmte;
+  if (debug (d, DBG_C_NumToAddr) != 0)
+    return;
+  addr_2 = d->dbgbuf.Addr;
+
+  /* Check that the .text object starts with the emx startup code.
+     See also spawn_debug(), crt0.s, and dll0.s. */
+
+  if (debug_read_8 (d, addr_1 + 0, &b) != 0
+      || b != 0x68
+      || debug_read_32 (d, addr_1 + 1, &addr_layout) != 0
+      || addr_layout != addr_2
+      || debug_read_8 (d, addr_1 + 5, &b) != 0
+      || b != 0xe8
+      || debug_read_8 (d, addr_1 + 10, &b) != 0
+      || b != 0xeb
+      || debug_read_8 (d, addr_1 + 12, &b) != 0
+      || b != 0xe8)
+    return;
+
+  /* The module seems to be an emx executable or DLL.  Read and check
+     the layout table. */
+
+  if (!READ_LAYOUT (flags, &flags)
+      || (flags >> 24) < 2
+      || !READ_LAYOUT (text_base, &text_base)
+      || !READ_LAYOUT (text_end, &text_end)
+      || text_base > text_end
+      || !READ_LAYOUT (data_base, &data_base)
+      || !READ_LAYOUT (data_end, &data_end)
+      || data_base > data_end
+      || !READ_LAYOUT (bss_base, &bss_base)
+      || !READ_LAYOUT (bss_end, &bss_end)
+      || bss_base > bss_end)
+    return;
+
+  /* Store the object addresses and sizes to the structure provided by
+     the caller of ptrace(). */
+
+  pmodule->text_start = text_base;
+  pmodule->text_size = text_end - text_base;
+  pmodule->data_start = data_base;
+  pmodule->data_size = data_end - data_base;
+  pmodule->bss_start = bss_base;
+  pmodule->bss_size = bss_end - bss_base;
+
+  /* Set PTNMOD_AOUT unless L_FLAG_LINK386 is set. */
+
+  if (!(flags & L_FLAG_LINK386))
+    pmodule->flags |= PTNMOD_AOUT;
+}
+
+
+/* Implement PTRACE_NOTIFICATION. */
+
+static int get_notification (struct debuggee *d, void *data, size_t size,
+                             ULONG *errnop)
+{
+  struct ptn_thread *pthread;
+  struct ptn_module *pmodule;
+  struct ptn_proc *pproc;
+  ULONG rc, flags;
+
+  if (!d->ptn_flag)
+    {
+      *errnop = EINVAL;
+      return -1;
+    }
+  switch (d->ptn)
+    {
+    case PTN_THREAD_NEW:
+    case PTN_THREAD_END:
+      if (data != NULL && size >= sizeof (struct ptn_thread))
+        {
+          pthread = data;
+          pthread->tid = d->ptn_tid;
+        }
+      break;
+
+    case PTN_MODULE_LOAD:
+    case PTN_MODULE_FREE:
+      if (data != NULL && size >= sizeof (struct ptn_module))
+        {
+          pmodule = data;
+          pmodule->hmte = d->ptn_hmte;
+          rc = DosQueryModuleName (d->ptn_hmte, sizeof (pmodule->name),
+                                   pmodule->name);
+          if (rc != 0)
+            pmodule->name[0] = 0;
+          pmodule->text_start = 0; pmodule->text_size = 0;
+          pmodule->data_start = 0; pmodule->data_size = 0;
+          pmodule->bss_start = 0; pmodule->bss_size = 0;
+          pmodule->flags = 0;
+          if (d->ptn == PTN_MODULE_LOAD)
+            find_module_layout (d, pmodule);
+          if (pmodule->name[0] != 0)
+            {
+              rc = DosQueryAppType (pmodule->name, &flags);
+              if (rc == 0 && (flags & FAPPTYP_DLL))
+                pmodule->flags |= PTNMOD_DLL;
+            }
+        }
+      break;
+
+    case PTN_PROC_NEW:
+      if (data != NULL && size >= sizeof (struct ptn_proc))
+        {
+          pproc = data;
+          pproc->pid = d->ptn_pid;
+          pproc->fork_addr = d->ptn_fork_addr;
+          pproc->flags = d->ptn_flags;
+          memcpy (pproc->name, d->ptn_name, sizeof (pproc->name));
+        }
+      break;
+    }
+  *errnop = 0;
+  return d->ptn;
+}
+
+
+/* Handle PTRACE_THAW and PTRACE_FREEEZ. */
+
+static int thaw_freeze (struct debuggee *d, ULONG cmd, ULONG tid,
+                        ULONG *errnop)
+{
+  ULONG rc;
+
+  if ((uflags & _UF_PTRACE_MODEL) != _UF_PTRACE_MULTITHREAD || tid == 0)
+    {
+      *errnop = EINVAL;
+      return -1;
+    }
+
+  d->dbgbuf.Tid = tid;
+  rc = debug (d, cmd);
+  *errnop = rc;
+  return rc == 0 ? 0 : -1;
+}
+
+
+int do_ptrace (ULONG request, ULONG pid, ULONG addr, ULONG data, ULONG *errnop)
+{
+  ULONG rc, w, tid;
+  const struct reg_table *rp;
+  struct debuggee *d;
+
+  switch (request)
+    {
+    case PTRACE_ATTACH:
+      rc = do_attach (pid);
+      *errnop = rc;
+      return (rc == 0 ? 0 : -1);
+    }
+
+  if ((uflags & _UF_PTRACE_MODEL) == _UF_PTRACE_MULTITHREAD)
+    {
+      tid = PTRACE_GETTID (pid);
+      pid = PTRACE_GETPID (pid);
+    }
+  else
+    tid = 1;
+
+  if (pid == 0)
+    {
+      *errnop = ESRCH;
+      return -1;
+    }
+
+  if (dbg_cache != NULL && dbg_cache->pid == pid)
+    d = dbg_cache;
+  else
+    {
+      for (d = dbg_head; d != NULL; d = d->next)
+        if (d->pid == pid)
+          break;
+      if (d == NULL)
+        {
+          *errnop = ESRCH;
+          return -1;
+        }
+      dbg_cache = d;
+    }
+  switch (request)
+    {
+    case PTRACE_EXIT:
+      d->regs_tid = 0; d->fpregs_ok = FALSE;
+      rc = terminate (d);
+      *errnop = rc;
+      if (rc != 0) return -1;
+      debug_set_wait (pid, 0, 0, TRUE);
+      return 0;
+
+    case PTRACE_PEEKTEXT:
+    case PTRACE_PEEKDATA:
+      rc = debug_read_32 (d, addr, &w);
+      *errnop = rc;
+      if (rc != 0) return -1;
+      return w;
+
+    case PTRACE_POKETEXT:
+    case PTRACE_POKEDATA:
+      rc = debug_poke16 (d, addr, (ULONG)data & 0xffff);
+      if (rc == 0)
+        rc = debug_poke16 (d, addr +2, (ULONG)data >> 16);
+      *errnop = rc;
+      return (rc == 0 ? 0 : -1);
+
+    case PTRACE_PEEKUSER:
+      if (addr == USEROFF (u_ar0))
+        w = USEROFF (u_regs) + KERNEL_U_ADDR;
+      else if (addr == USEROFF (u_fpvalid))
+        {
+          if (!d->fpregs_ok)
+            get_fpstate (d);
+          w = (d->fpregs_ok ? 0xff : 0);
+        }
+      else if (addr == USEROFF (u_fpstate.status))
+        w = 0;                  /* ... */
+      else if (addr >= USEROFF (u_fpstate.state)
+               && addr <= USEROFF (u_fpstate.state) + sizeof (d->dbgco) - 4)
+        {
+          if (!d->fpregs_ok)
+            {
+              rc = get_fpstate (d);
+              if (rc != 0)
+                {
+                  *errnop = rc;
+                  return -1;
+                }
+            }
+          memcpy (&w, (char *)&d->dbgco + addr - USEROFF (u_fpstate.state), 4);
+        }
+      else if ((rp = user_addr (addr)) != NULL)
+        {
+          rc = read_reg (d, tid);
+          if (rc != 0)
+            {
+              *errnop = rc;
+              return -1;
+            }
+          w = 0;
+          memcpy (&w, &d->regs[rp->reg], rp->len);
+        }
+      else
+        {
+          *errnop = EINVAL;
+          return -1;
+        }
+      *errnop = 0;
+      return w;
+
+    case PTRACE_POKEUSER:
+      rp = user_addr (addr);
+      if (rp == NULL)
+        rc = EIO;
+      else
+        rc = read_reg (d, tid);
+      if (rc == 0)
+        {
+          d->regs[rp->reg] = 0;
+          memcpy (&d->regs[rp->reg], &data, rp->len);
+          d->regs_changed = TRUE;
+        }
+      *errnop = rc;
+      return (rc == 0 ? 0 : -1);
+
+    case PTRACE_RESUME:
+      rc = run (d, DBG_C_Go, 0, data, tid);
+      *errnop = rc;
+      return (rc == 0 ? 0 : -1);
+
+    case PTRACE_STEP:
+      /* Avoid stepping into emx_syscall. */
+      if (d->syscall_addr != 0 && d->syscall_addr == d->regs[R_EIP])
+        rc = run (d, DBG_C_Go, d->syscall_addr + 5, data, tid);
+      else
+        rc = run (d, DBG_C_SStep, 0, data, tid);
+      *errnop = rc;
+      return (rc == 0 ? 0 : -1);
+
+    case PTRACE_SESSION:
+      if (!debug_same_sess)
+        switch (data)
+          {
+          case 0:               /* Switch to debugger */
+            DosSelectSession (0);
+            d->auto_switch = FALSE;
+            break;
+
+          case 1:               /* Switch to child */
+            DosSelectSession (d->sid);
+            d->auto_switch = FALSE;
+            break;
+
+          case 2:               /* Automatic switch to child */
+            d->auto_switch = TRUE;
+            break;
+
+          default:
+            /* Succeed for undefined values. */
+            break;
+          }
+      *errnop = 0;
+      return 0;
+
+    case PTRACE_NOTIFICATION:
+      return get_notification (d, (void *)addr, (size_t)data, errnop);
+
+    case PTRACE_CONT:
+      if (!d->ptn_flag)
+        {
+          *errnop = EINVAL;
+          return -1;
+        }
+      rc = run (d, d->n_cmd, d->n_tbreak, d->n_signo, d->n_tid);
+      *errnop = rc;
+      return (rc == 0 ? 0 : -1);
+
+    case PTRACE_THAW:
+      return thaw_freeze (d, DBG_C_Resume, tid, errnop);
+
+    case PTRACE_FREEZE:
+      return thaw_freeze (d, DBG_C_Freeze, tid, errnop);
+
+    case PTRACE_DETACH:
+      rc = do_detach (d, addr);
+      *errnop = rc;
+      return (rc == 0 ? 0 : -1);
+
+    case PTRACE_TRACEME:
+    default:
+      *errnop = EINVAL;
+      return -1;
+    }
+}
+
+
+static ULONG free_debuggee (struct debuggee *d, ULONG return_value)
+{
+  struct debuggee **pd;
+
+  if (d->resources & (DR_SERVER_HEV_SERVER | DR_CLIENT_HEV_SERVER))
+    DosCloseEventSem (d->hev_server);
+  if (d->resources & (DR_SERVER_HEV_CLIENT | DR_CLIENT_HEV_CLIENT))
+    DosCloseEventSem (d->hev_client);
+
+  if (d->resources & DR_LIST)
+    {
+      for (pd = &dbg_head; *pd != NULL; pd = &(*pd)->next)
+        if (*pd == d)
+          {
+            *pd = d->next;
+            break;
+          }
+      if (dbg_cache == d)
+        dbg_cache = NULL;
+    }
+
+  DosFreeMem (d);
+  return return_value;
+}
+
+
+/* Return errno. */
+
+static ULONG new_debuggee (struct debuggee **pd, ULONG pid, ULONG sid,
+                           enum dbg_type type)
+{
+  ULONG rc, w;
+  BYTE b;
+  struct debuggee *d;
+  void *mem;
+
+  if (type == DT_CLIENT || type == DT_SERVER)
+    d = *pd;
+  else
+    {
+      rc = DosAllocMem (&mem, sizeof (*d), PAG_COMMIT | PAG_READ | PAG_WRITE);
+      if (rc != 0) return set_error (rc);
+      d = (struct debuggee *)mem;
+      d->resources = 0;
+    }
+
+  d->next = NULL;
+  d->type = type;
+  d->syscall_addr = 0;
+  d->layout_addr = 0;
+  d->fpregs_ok = FALSE;
+  d->regs_tid = 0;
+  d->regs_changed = FALSE;
+  d->context = 0;
+  d->signo = 0;
+  d->ptn = PTN_NONE;
+  d->ptn_flag = FALSE;
+
+  if (type == DT_CLIENT)
+    {
+      rc = call_server (d, REQ_ATTACH);
+      if (rc != 0)
+        return free_debuggee (d, set_error (rc));
+      if (d->server_rc != 0)
+        return free_debuggee (d, d->server_rc);
+    }
+
+  if (type == DT_LOCAL || type == DT_SERVER)
+    {
+      d->pid = pid;
+      d->sid = sid;
+
+      d->dbgbuf.Tid = 0;        /* reserved */
+      d->dbgbuf.Value = DBG_L_386; /* level */
+      rc = debug (d, DBG_C_Connect);
+      if (rc != 0)
+        return free_debuggee (d, rc);
+      if (d->dbgbuf.Cmd != DBG_N_Success)
+        return free_debuggee (d, EINVAL);
+      d->dbgbuf.Tid = 0;        /* Active thread */
+      rc = debug (d, DBG_C_ReadReg);
+      if (rc != 0)
+        return free_debuggee (d, rc);
+      if (d->dbgbuf.Cmd != DBG_N_Success)
+        return free_debuggee (d, EINVAL);
+    }
+  if (debug_read_8 (d, ENTRY_POINT+0, &b) == 0 && b == 0x68     /* PUSH n */
+      && debug_read_8 (d, ENTRY_POINT+5, &b) == 0 && b == 0xe8  /* CALL */
+      && debug_read_8 (d, ENTRY_POINT+10, &b) == 0 && b == 0xeb /* JMP */
+      && debug_read_8 (d, ENTRY_POINT+12, &b) == 0 && b == 0xe8 /* CALL */
+      && debug_read_32 (d, ENTRY_POINT+1, &w) == 0)
+    {
+      d->layout_addr = w;
+      d->syscall_addr = ENTRY_POINT + 12;
+    }
+
+  if (pd != NULL)
+    *pd = d;
+
+  if (type == DT_LOCAL || type == DT_CLIENT)
+    {
+      d->next = dbg_head;
+      dbg_head = d;
+      d->resources |= DR_LIST;
+    }
+  return 0;
+}
+
+
+/* Prepare a child process for debugging.  Return errno. */
+
+ULONG spawn_debug (ULONG pid, ULONG sid)
+{
+  return new_debuggee (NULL, pid, sid, DT_LOCAL);
+}
+
+
+/* Detach from a child process, that is, let it run to the end. */
+
+static void handle_detach (struct debuggee *d)
+{
+  ULONG rc;
+  enum {GO, END, NOTIFICATION} state;
+
+  /* Thaw all threads. */
+
+  d->dbgbuf.Cmd = DBG_C_Resume;
+  d->dbgbuf.Pid = d->pid;
+  d->dbgbuf.Tid = 0;            /* All threads */
+  rc = DosDebug (&d->dbgbuf);
+
+  state = GO;
+  do
+    {
+      if (state == GO)
+        {
+          d->dbgbuf.Cmd = DBG_C_Go;
+          d->dbgbuf.Pid = d->pid;
+          rc = DosDebug (&d->dbgbuf);
+          if (rc != 0) break;
+        }
+
+      switch (d->dbgbuf.Cmd)
+        {
+        case DBG_N_Error:
+          state = END;
+          break;
+
+        case DBG_N_Exception:
+          d->dbgbuf.Cmd = DBG_C_ReadReg;
+          d->dbgbuf.Pid = d->pid;
+          d->dbgbuf.Tid = 0;
+          rc = DosDebug (&d->dbgbuf);
+          if (rc != 0 || d->dbgbuf.Cmd != DBG_N_Success)
+            d->dbgbuf.Tid = 1;
+
+          d->dbgbuf.Cmd = DBG_C_Continue;
+          d->dbgbuf.Value = XCPT_CONTINUE_SEARCH;
+          d->dbgbuf.Pid = d->pid;
+          rc = DosDebug (&d->dbgbuf);
+          state = rc == 0 ? NOTIFICATION : END;
+          break;
+          
+        case DBG_N_ProcTerm:
+          d->dbgbuf.Cmd = DBG_C_Go;
+          d->dbgbuf.Pid = d->pid;
+          rc = DosDebug (&d->dbgbuf);
+          state = END;
+          break;
+
+        default:
+          state = GO;
+          break;
+        }
+    } while (state != END);
+
+  free_debuggee (d, 0);
+  DosExit (EXIT_THREAD, 0);
+}
+
+
+
+static void server_answer (struct debuggee *d)
+{
+  ULONG rc;
+
+  rc = DosPostEventSem (d->hev_client);
+  if (rc != 0)
+    {
+      oprintf ("server_answer: DosPostEventSem failed, rc=%u\r\n", rc);
+      DosExit (EXIT_THREAD, 2);
+    }
+}
+
+
+/* Handle DosDebug requests from a debugger which attached to a child
+   process of one of our debuggees. */
+
+static void debug_descendant_thread (ULONG arg)
+{
+  struct debuggee *d;
+  ULONG rc, post_count, clients;
+
+  /* Raise our priority. */
+
+  rc = DosSetPriority (PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
+
+  d = (struct debuggee *)arg;
+  clients = 0;
+
+  /* Handle requests. */
+
+  for (;;)
+    {
+      rc = DosWaitEventSem (d->hev_server, SEM_INDEFINITE_WAIT);
+      if (rc != 0)
+        {
+          oprintf ("debug_descendant_thread: DosWaitEventSem failed, "
+                   "rc=%u\r\n", rc);
+          return;
+        }
+
+      rc = DosResetEventSem (d->hev_server, &post_count);
+
+      switch (d->server_request)
+        {
+        case REQ_ATTACH:
+          if (clients == 0)
+            {
+              ++clients;
+              d->server_rc = 0;
+            }
+          else
+            d->server_rc = EACCES;
+          server_answer (d);
+          break;
+
+        case REQ_DOSDEBUG:
+          d->server_rc = DosDebug (&d->dbgbuf);
+          server_answer (d);
+          break;
+
+        case REQ_DETACH:
+          d->server_rc = 0;     /* errno*/
+          server_answer (d);
+          --clients;
+          if (d->server_arg == 1)
+            handle_detach (d);
+          break;
+
+        default:
+          oprintf ("debug_descendant_thread: invalid request %u\r\n",
+                   d->server_request);
+          break;
+        }
+    }
+}
+
+
+/* The debuggee PARENT got a new child process.  Enable debugging of
+   the child process for PTRACE_ATTACH.  Return errno or N_NOTIFY. */
+
+static ULONG start_debug_descendant (struct debuggee *parent)
+{
+  char mname[64];
+  struct debuggee *child;
+  void *mem;
+  TID tid;
+  ULONG rc;
+
+  sprintf (mname, SHAREMEM_FMT, (unsigned)parent->ptn_pid);
+  rc = DosAllocSharedMem (&mem, mname, sizeof (*child),
+                          PAG_COMMIT | PAG_READ | PAG_WRITE);
+  if (rc != 0) return set_error (rc);
+  child = (struct debuggee *)mem;
+  child->resources = 0;
+
+  rc = DosCreateEventSem (NULL, &child->hev_server, DC_SEM_SHARED, FALSE);
+  if (rc == 0)
+    {
+      child->resources |= DR_SERVER_HEV_SERVER;
+      rc = DosCreateEventSem (NULL, &child->hev_client, DC_SEM_SHARED, FALSE);
+      if (rc == 0)
+        {
+          child->resources |= DR_SERVER_HEV_CLIENT;
+
+          /* We don't have a session ID.  TODO: qwait_thread() may
+             provide the session ID sooner or later. */
+
+          rc = new_debuggee (&child, parent->ptn_pid, 0, DT_SERVER);
+
+          /* More initializations. */
+
+          if (rc == 0)
+            rc = start_debug_descendant_2 (parent, child);
+
+          /* Create a thread which will handle debugging of the new
+             child process. */
+
+          if (rc == 0)
+            rc = DosCreateThread (&tid, debug_descendant_thread, (ULONG)child,
+                                  CREATE_READY | STACK_COMMITTED, 0x4000);
+        }
+    }
+  if (rc != 0)
+    return free_debuggee (child, set_error (rc));
+
+  return N_NOTIFY;
+}
+
+
+/* Subroutine of the above.  Return OS/2 error code. */
+
+static ULONG start_debug_descendant_2 (struct debuggee *parent,
+                                       struct debuggee *child)
+{
+  ULONG rc, flags, w;
+  BYTE b;
+
+  /* For now assume that the child is in the same session as its
+     parent. (The condition is always true.)  That doesn't hurt
+     because we can't switch sessions anyway (either we'll get error
+     ERROR_SMG_SESSION_NOT_PARENT or ERROR_SMG_SESSION_NOT_FOREGRND,
+     depending on whether the client or server attempts to select the
+     session). */
+
+  if (child->sid == 0)
+    child->sid = parent->sid;
+
+  /* Get module name of the child process. */
+
+  child->dbgbuf.Tid = 0;        /* Current thread */
+  rc = debug (child, DBG_C_ReadReg);
+  if (rc == 0 && child->dbgbuf.Cmd == DBG_N_Success)
+    {
+      rc = DosQueryModuleName (child->dbgbuf.MTE, sizeof (parent->ptn_name),
+                               parent->ptn_name);
+      if (rc != 0)
+        parent->ptn_name[0] = 0;
+    }
+
+  /* Find out whether the child process uses a.out format. */
+
+  if (child->layout_addr != 0
+      && debug_read_32 (child, (child->layout_addr
+                                + offsetof (layout_table, flags)),
+                        &flags) == 0
+      && !(flags & L_FLAG_LINK386))
+    parent->ptn_flags |= PTNPROC_AOUT;
+
+  /* Find out whether the child process has been forked. */
+
+  if (debug_read_8 (parent, (ULONG)&ptrace_forking, &b) == 0 && b)
+    {
+      parent->ptn_flags |= PTNPROC_FORK;
+      if (debug_read_32 (parent, (ULONG)&ptrace_fork_addr, &w) == 0)
+        parent->ptn_fork_addr = w;
+    }
+
+  return 0;
+}
+
+
+/* Return OS/2 error code. */
+
+static ULONG call_server (struct debuggee *d, ULONG request)
+{
+  ULONG rc, count;
+
+  rc = DosResetEventSem (d->hev_client, &count);
+  if (rc != 0 && rc != ERROR_ALREADY_RESET)
+    return rc;
+
+  d->server_request = request;
+  rc = DosPostEventSem (d->hev_server);
+  if (rc != 0) return rc;
+
+  rc = DosWaitEventSem (d->hev_client, SEM_INDEFINITE_WAIT);
+  if (rc != 0) return rc;
+  return 0;
+}
+
+
+/* Return errno. */
+
+static ULONG new_client (struct debuggee **pd, ULONG pid)
+{
+  char mname[64];
+  ULONG rc;
+  void *mem;
+  struct debuggee *d;
+
+  sprintf (mname, SHAREMEM_FMT, (unsigned)pid);
+  rc = DosGetNamedSharedMem (&mem, mname, PAG_READ | PAG_WRITE);
+  if (rc != 0)
+    return ESRCH;
+
+  d = (struct debuggee *)mem;
+
+  /* Assume that at most one process at a time connects to the server
+     for each PID. */
+
+  d->resources &= ~(DR_CLIENT_HEV_CLIENT | DR_CLIENT_HEV_SERVER);
+
+  rc = DosOpenEventSem (NULL, &d->hev_server);
+  if (rc == 0)
+    {
+      d->resources |= DR_CLIENT_HEV_SERVER;
+      rc = DosOpenEventSem (NULL, &d->hev_client);
+      if (rc == 0)
+        d->resources |= DR_CLIENT_HEV_CLIENT;
+    }
+  if (rc != 0)
+    return free_debuggee (d, set_error (rc));
+  *pd = d;
+  return 0;
+}
+
+
+/* Handle PTRACE_ATTACH.  Return errno. */
+
+static ULONG do_attach (ULONG pid)
+{
+  struct debuggee *d;
+  ULONG rc;
+
+  rc = proc_add_attach (pid);
+  if (rc != 0) return rc;
+
+  rc = new_client (&d, pid);
+  if (rc == 0)
+    {
+      rc = new_debuggee (&d, pid, 0, DT_CLIENT);
+      if (rc == 0)
+        debug_set_wait (d->pid, 0, 0x7f | (SIGTRAP << 8), FALSE);
+      if (rc != 0)
+        free_debuggee (d, 0);
+    }
+  if (rc != 0)
+    proc_remove_attach (pid);
+  return rc;
+}
+
+
+/* Handle PTRACE_DETACH.  Return errno. */
+
+static ULONG do_detach (struct debuggee *d, ULONG addr)
+{
+  ULONG rc;
+
+  if (d->type != DT_CLIENT)
+    return EINVAL;
+  if (addr != 0 && addr != 1)
+    return EINVAL;
+  d->server_arg = addr;
+  rc = call_server (d, REQ_DETACH);
+  if (rc != 0)
+    return set_error (rc);
+  else
+    return free_debuggee (d, d->server_rc);
+}
Index: trunk/src/emx/src/os2/reg.h
===================================================================
--- trunk/src/emx/src/os2/reg.h	(revision 18)
+++ trunk/src/emx/src/os2/reg.h	(revision 18)
@@ -0,0 +1,46 @@
+/* reg.h -- Register numbers
+   Copyright (c) 1992-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+/* This header contains the macros of <sys/reg.h> prepended with
+   "R_" to avoid conflicts with the members of uDB_t. */
+
+#define R_GS      0
+#define R_FS      1
+#define R_ES      2
+#define R_DS      3
+#define R_EDI     4
+#define R_ESI     5
+#define R_EBP     6
+#define R_ESP     7
+#define R_EBX     8
+#define R_EDX     9
+#define R_ECX    10
+#define R_EAX    11
+#define R_EIP    14
+#define R_CS     15
+#define R_EFL    16
+#define R_UESP   17
+#define R_SS     18
Index: trunk/src/emx/src/os2/select.c
===================================================================
--- trunk/src/emx/src/os2/select.c	(revision 18)
+++ trunk/src/emx/src/os2/select.c	(revision 18)
@@ -0,0 +1,571 @@
+/* select.c -- Implement select()
+   Copyright (c) 1993-1998 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSDEVIOCTL
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSPROCESS
+#define INCL_DOSMISC
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include <sys/types.h>
+#include <sys/termio.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include "emxdll.h"
+#include "files.h"
+#include "tcpip.h"
+#include "select.h"
+#include "clib.h"
+
+/* Note that select() is not thread-safe for various reasons. */
+
+static HEV npipe_sem;
+static BYTE npipe_sem_open;
+static ULONG mem_size;
+static void *mem;
+
+
+static int select_add_read_npipe (struct select_data *d, int fd)
+{
+  ULONG rc;
+
+  if (!d->sem_npipe_flag)
+    {
+      if (d->sem_count >= d->max_sem)
+        return EINVAL;
+      if (!npipe_sem_open)
+        {
+          if (create_event_sem (&npipe_sem, DC_SEM_SHARED) != 0)
+            return EINVAL;
+          npipe_sem_open = TRUE;
+        }
+      if (reset_event_sem (npipe_sem) != 0)
+        return EINVAL;
+      d->list[d->sem_count].hsemCur = (HSEM)npipe_sem;
+      d->list[d->sem_count].ulUser = 0;
+      ++d->sem_count;
+      d->sem_npipe_flag = TRUE;
+    }
+  rc = DosSetNPipeSem (fd, (HSEM)npipe_sem, 0);
+  if (rc != 0)
+    {
+      error (rc, "DosSetNPipeSem");
+      return EACCES;
+    }
+  return 0;
+}
+
+
+static int select_add_read_con (struct select_data *d, int fd)
+{
+  if (IS_VALID_FILE (fd) && !(GET_FILE (fd)->c_lflag & IDEFAULT)
+      && !d->sem_kbd_flag)
+    {
+      if (d->sem_count >= d->max_sem)
+        return EINVAL;
+      if (reset_event_sem (kbd_sem_new) != 0)
+        return EINVAL;
+      d->list[d->sem_count].hsemCur = (HSEM)kbd_sem_new;
+      d->list[d->sem_count].ulUser = 0;
+      ++d->sem_count;
+      d->sem_kbd_flag = TRUE;
+    }
+  return 0;
+}
+
+
+static int select_add_read_socket (struct select_data *d, int fd)
+{
+  if (!IS_VALID_FILE (fd))
+    return EBADF;
+  d->sockets[d->socket_count] = GET_FILE (fd)->x.socket.handle;
+  d->socketh[d->socket_count] = fd;
+  ++d->socket_count; ++d->socket_nread;
+  return 0;
+}
+
+
+static int select_add_read (struct select_data *d, int fd)
+{
+  ULONG ht;
+
+  if (fd >= handle_count)
+    return EBADF;
+  ht = handle_flags[fd];
+  if (!(ht & HF_OPEN))
+    return EBADF;
+  if (ht & HF_NPIPE)
+    return select_add_read_npipe (d, fd);
+  else if (ht & HF_CON)
+    return select_add_read_con (d, fd);
+  else if (ht & HF_ASYNC)
+    d->async_flag = TRUE;
+  else if (ht & HF_SOCKET)
+    return select_add_read_socket (d, fd);
+  else if (ht & HF_XF86SUP)
+    return xf86sup_select_add_read (d, fd);
+  else
+    {
+      /* Ignore other types of handles */
+    }
+  return 0;
+}
+
+
+static int select_add_write (struct select_data *d, int fd)
+{
+  ULONG ht;
+
+  if (fd >= handle_count)
+    return EBADF;
+  ht = handle_flags[fd];
+  if (!(ht & HF_OPEN))
+    return EBADF;
+  if (ht & HF_ASYNC)
+    d->async_flag = TRUE;
+  else if (ht & HF_SOCKET)
+    {
+      if (!IS_VALID_FILE (fd))
+        return EBADF;
+      d->sockets[d->socket_count] = GET_FILE (fd)->x.socket.handle;
+      d->socketh[d->socket_count] = fd;
+      ++d->socket_count; ++d->socket_nwrite;
+    }
+  else
+    {
+      /* Ignore other types of handles */
+    }
+  return 0;
+}
+
+
+static int select_add_except (struct select_data *d, int fd)
+{
+  ULONG ht;
+
+  if (fd >= handle_count)
+    return EBADF;
+  ht = handle_flags[fd];
+  if (!(ht & HF_OPEN))
+    return EBADF;
+  if (ht & HF_SOCKET)
+    {
+      if (!IS_VALID_FILE (fd))
+        return EBADF;
+      d->sockets[d->socket_count] = GET_FILE (fd)->x.socket.handle;
+      d->socketh[d->socket_count] = fd;
+      ++d->socket_count; ++d->socket_nexcept;
+    }
+  else
+    {
+      /* Ignore other types of handles */
+    }
+  return 0;
+}
+
+
+static int select_init (struct select_data *d, struct _select *args)
+{
+  int fd, e;
+  ULONG rc;
+  struct timeval *tv;
+
+  d->timeout = SEM_INDEFINITE_WAIT;
+  tv = args->timeout;
+  if (tv != NULL)
+    {
+      if (tv->tv_sec < 0 || tv->tv_sec >= 4294967 || tv->tv_usec < 0)
+        return EINVAL;
+      d->timeout = tv->tv_sec * 1000;
+      d->timeout += (tv->tv_usec + 999) / 1000;
+      if (d->timeout != 0)
+        d->start_ms = querysysinfo (QSV_MS_COUNT);
+    }
+  if (args->readfds != NULL)
+    for (fd = 0; fd < args->nfds; ++fd)
+      if (FD_ISSET (fd, args->readfds))
+        {
+          e = select_add_read (d, fd);
+          if (e != 0)
+            return e;
+        }
+  if (args->writefds != NULL)
+    for (fd = 0; fd < args->nfds; ++fd)
+      if (FD_ISSET (fd, args->writefds))
+        {
+          e = select_add_write (d, fd);
+          if (e != 0)
+            return e;
+        }
+  if (args->exceptfds != NULL)
+    for (fd = 0; fd < args->nfds; ++fd)
+      if (FD_ISSET (fd, args->exceptfds))
+        {
+          e = select_add_except (d, fd);
+          if (e != 0)
+            return e;
+        }
+
+  if (d->sem_count >= d->max_sem)
+    return EINVAL;
+  d->list[d->sem_count].hsemCur = (HSEM)signal_sem;
+  d->list[d->sem_count].ulUser = 1;
+  ++d->sem_count;
+  rc = create_muxwait_sem (&d->sem_mux, d->sem_count, d->list, DCMW_WAIT_ANY);
+  if (rc != 0)
+    return EINVAL;
+  d->sem_mux_flag = TRUE;
+  return 0;
+}
+
+
+static void select_check_read (struct select_data *d, int fd)
+{
+  ULONG rc, ht;
+  int dummy_errno;
+
+  ht = handle_flags[fd];
+  if (!(ht & HF_OPEN))
+    return;
+  if (ht & HF_NPIPE)
+    {
+      ULONG buffer, nread, state;
+      AVAILDATA avail;
+
+      rc = DosPeekNPipe (fd, &buffer, 0, &nread, &avail, &state);
+      if (rc != 0)
+        {
+          /* Ignore; TODO? */
+        }
+      else if (avail.cbpipe != 0 || state == NP_STATE_CLOSING)
+        {
+          FD_SET (fd, d->rbits);
+          d->ready_flag = TRUE;
+        }
+    }
+  else if (ht & HF_CON)
+    {
+      /* Note that file descriptors of types unsupported by select()
+         are considered to be always ready. */
+
+      if (!IS_VALID_FILE (fd) || (GET_FILE (fd)->c_lflag & IDEFAULT)
+          || termio_avail (fd) != 0)
+        {
+          FD_SET (fd, d->rbits);
+          d->ready_flag = TRUE;
+        }
+    }
+  else if (ht & HF_ASYNC)
+    {
+      if (async_avail (fd) != 0)
+        {
+          FD_SET (fd, d->rbits);
+          d->ready_flag = TRUE;
+        }
+    }
+  else if (ht & HF_XF86SUP)
+    {
+      if (xf86sup_avail (fd, &dummy_errno) > 0)
+        {
+          FD_SET (fd, d->rbits);
+          d->ready_flag = TRUE;
+        }
+    }
+  else if (ht & HF_SOCKET)
+    {
+      /* Socket handles are handled by tcpip_select_poll(). */
+    }
+  else
+    {
+      /* File descriptors of types unsupported by select() are
+         considered to be always ready. */
+
+      FD_SET (fd, d->rbits);
+      d->ready_flag = TRUE;
+    }
+}
+
+
+static void select_check_write (struct select_data *d, int fd)
+{
+  ULONG ht;
+
+  ht = handle_flags[fd];
+  if (!(ht & HF_OPEN))
+    return;
+
+  if (ht & HF_SOCKET)
+    {
+      /* Socket handles are handled by tcpip_select_poll(). */
+    }
+  else if (ht & HF_ASYNC)
+    {
+      if (async_writable (fd) != 0)
+        {
+          FD_SET (fd, d->wbits);
+          d->ready_flag = TRUE;
+        }
+    }
+  else
+    {
+      /* File descriptors of types unsupported by select() are
+         considered to be always ready. */
+
+      FD_SET (fd, d->wbits);
+      d->ready_flag = TRUE;
+    }
+}
+
+
+/* Poll all handles.  Return 0 or errno. */
+
+static int select_poll (struct select_data *d, struct _select *args)
+{
+  int fd;
+
+  memset (d->rbits, 0, d->nbytes);
+  memset (d->wbits, 0, d->nbytes);
+  memset (d->ebits, 0, d->nbytes);
+
+  /* Reset those event semaphores which can be set without data being
+     ready (false alarms).  This is required because we might want to
+     block after calling select_poll().  Note that the semaphores must
+     be reset before polling to avoid a time window. */
+
+  if (d->sem_npipe_flag && reset_event_sem (npipe_sem) != 0)
+    return EINVAL;
+
+  if (args->readfds != NULL)
+    {
+      for (fd = 0; fd < args->nfds; ++fd)
+        if (FD_ISSET (fd, args->readfds))
+          select_check_read (d, fd);
+    }
+
+  if (args->writefds != NULL)
+    {
+      for (fd = 0; fd < args->nfds; ++fd)
+        if (FD_ISSET (fd, args->writefds))
+          select_check_write (d, fd);
+    }
+
+  if (d->socket_count != 0)
+    {
+      int n, e;
+
+      n = tcpip_select_poll (d, &e);
+      if (n < 0)
+        return e;
+    }
+
+  if (d->ready_flag)
+    {
+      if (args->readfds != NULL)
+        memcpy (args->readfds, d->rbits, d->nbytes);
+      if (args->writefds != NULL)
+        memcpy (args->writefds, d->wbits, d->nbytes);
+      if (args->exceptfds != NULL)
+        memcpy (args->exceptfds, d->ebits, d->nbytes);
+      d->return_value = 0;
+      for (fd = 0; fd < args->nfds; ++fd)
+        if ((args->readfds != NULL && FD_ISSET (fd, args->readfds))
+            || (args->writefds != NULL && FD_ISSET (fd, args->writefds))
+            || (args->exceptfds != NULL && FD_ISSET (fd, args->exceptfds)))
+          d->return_value += 1;
+    }
+  return 0;
+}
+
+
+#define POLL_INTERVAL   10
+
+/* Wait until a semaphore is posted (pipe ready, keyboard data
+   available, signal) or until the timeout elapses, whichever comes
+   first.  Call select_poll() unless a timeout or an error occurs.
+   Return 0 if successful, return errno otherwise. */
+
+static int select_block (struct select_data *d, struct _select *args)
+{
+  ULONG rc, user;
+  ULONG timeout, now, elapsed;
+  int n, e;
+  char poll;
+
+  poll = (char)(d->async_flag || (d->socket_count != 0 && d->timeout != 0));
+  for (;;)
+    {
+      timeout = d->timeout;
+      if (timeout != 0 && timeout != SEM_INDEFINITE_WAIT)
+        {
+          /* This works even if QSV_MS_COUNT wrapped around once since
+             we got d->start_ms, thanks to unsigned arithmetic.  A
+             struct timeval which could make QSV_MS_COUNT wrap around
+             more than once is rejected by select_init(). */
+
+          now = querysysinfo (QSV_MS_COUNT);
+          elapsed = now - d->start_ms;
+          if (timeout < elapsed)
+            timeout = 0;
+          else
+            timeout -= elapsed;
+          if (poll && timeout == 0)
+            return 0;           /* The time is over */
+        }
+      if (!poll)
+        {
+          /* No sockets or async devices involved, we can really
+             block. */
+
+          rc = DosWaitMuxWaitSem (d->sem_mux, timeout, &user);
+          if (rc == ERROR_INTERRUPT || sig_flag)
+            return EINTR;
+          else if (rc == ERROR_TIMEOUT)
+            return 0;
+          else if (rc != 0)
+            {
+              error (rc, "DosWaitMuxWaitSem");
+              return EINVAL;
+            }
+          else
+            {
+              e = select_poll (d, args);
+              if (e != 0 || timeout == 0 || d->ready_flag)
+                return e;
+            }
+        }
+      else
+        {
+          /* Poll sockets. */
+
+          if (d->socket_count != 0)
+            {
+              n = tcpip_select_poll (d, &e);
+              if (n < 0)
+                return e;
+              if (n > 0)
+                return select_poll (d, args);
+            }
+
+          /* Sleep for a few ms, waking up as soon as d->sem_mux is
+             posted.  This way we don't have to poll all the other
+             file descriptors. */
+
+          if (timeout > POLL_INTERVAL || timeout == SEM_INDEFINITE_WAIT)
+            timeout = POLL_INTERVAL;
+          rc = DosWaitMuxWaitSem (d->sem_mux, timeout, &user);
+          if (rc == ERROR_INTERRUPT || sig_flag)
+            return EINTR;
+          else if (rc == 0 || (rc == ERROR_TIMEOUT && d->async_flag))
+            {
+              e = select_poll (d, args);
+              if (e != 0 || timeout == 0 || d->ready_flag)
+                return e;
+            }
+          else if (rc != ERROR_TIMEOUT)
+            {
+              error (rc, "DosWaitMuxWaitSem");
+              return EINVAL;
+            }
+        }
+
+    }
+}
+
+
+static void select_cleanup (struct select_data *d)
+{
+  if (d->sem_mux_flag)
+    close_muxwait_sem (d->sem_mux);
+}
+
+
+int do_select (struct _select *args, int *errnop)
+{
+  struct select_data d;
+  int e;
+  char *a;
+  ULONG size, rc;
+
+  sig_block_start ();
+  d.td = get_thread ();
+  d.sem_npipe_flag = FALSE; d.sem_kbd_flag = FALSE; d.sem_mux_flag = FALSE;
+  d.sem_count = 0; d.ready_flag = FALSE; d.return_value = 0;
+  d.socket_count = 0; d.socket_nread = d.socket_nwrite = d.socket_nexcept = 0;
+  d.async_flag = FALSE;
+  d.nbytes = 4 * ((args->nfds + 31) / 32);
+  d.max_sem = args->nfds + 1;
+  if (d.nbytes < 256 / 8)
+    d.nbytes = 256 / 8;
+  size = (3 * d.nbytes + 3 * args->nfds * sizeof (int)
+          + d.max_sem * sizeof (SEMRECORD));
+  if (size > mem_size)
+    {
+      if (mem != NULL)
+        private_free (mem);
+      mem_size = size;
+      rc = private_alloc (&mem, mem_size);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+    }
+  a = mem;
+  d.rbits = (fd_set *)a; a += d.nbytes;
+  d.wbits = (fd_set *)a; a += d.nbytes;
+  d.ebits = (fd_set *)a; a += d.nbytes;
+  d.sockets = (int *)a; a += args->nfds * sizeof (int);
+  d.socketh = (int *)a; a += args->nfds * sizeof (int);
+  d.sockett = (int *)a; a += args->nfds * sizeof (int);
+  d.list = (SEMRECORD *)a; /* a += d.max_sem * sizeof (SEMRECORD); */
+  e = select_init (&d, args);
+  if (e == 0)
+    {
+      e = select_poll (&d, args);
+      /* Block if no handle is ready and the requested timeout is > 0
+         or indefinite. */
+      if (e == 0 && !d.ready_flag && d.timeout != 0)
+        e = select_block (&d, args);
+    }
+
+  /* If no handles are ready (time-out), we have to clear all sets. */
+
+  if (e == 0 && !d.ready_flag && !(debug_flags & DEBUG_NOFDZERO))
+    {
+      if (args->readfds != NULL)
+        memset (args->readfds, 0, d.nbytes);
+      if (args->writefds != NULL)
+        memset (args->writefds, 0, d.nbytes);
+      if (args->exceptfds != NULL)
+        memset (args->exceptfds, 0, d.nbytes);
+    }
+
+  select_cleanup (&d);
+  sig_block_end ();
+  *errnop = e;
+  return (e == 0 ? d.return_value : -1);
+}
Index: trunk/src/emx/src/os2/select.h
===================================================================
--- trunk/src/emx/src/os2/select.h	(revision 18)
+++ trunk/src/emx/src/os2/select.h	(revision 18)
@@ -0,0 +1,54 @@
+/* select.h -- Header file for select.c
+   Copyright (c) 1993-1998 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+struct select_data
+{
+  SEMRECORD *list;
+  fd_set *rbits;
+  fd_set *wbits;
+  fd_set *ebits;
+  int nbytes;
+  int max_sem;
+  HMUX sem_mux;
+  BYTE sem_npipe_flag;
+  BYTE sem_kbd_flag;
+  BYTE sem_mux_flag;
+  BYTE socket_thread_flag;
+  int sem_count;
+  int ready_flag;
+  int return_value;
+  ULONG timeout;
+  ULONG start_ms;
+  thread_data *td;
+  int socket_count;
+  int socket_nread;
+  int socket_nwrite;
+  int socket_nexcept;
+  int *sockets;
+  int *socketh;
+  int *sockett;
+  int async_flag;
+};
Index: trunk/src/emx/src/os2/signal.c
===================================================================
--- trunk/src/emx/src/os2/signal.c	(revision 18)
+++ trunk/src/emx/src/os2/signal.c	(revision 18)
@@ -0,0 +1,1238 @@
+/* signal.c -- Manage signals and exceptions
+   Copyright (c) 1994-1998 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSPROCESS
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSDATETIME
+#define INCL_DOSMISC
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include "wrapper.h"
+#include <sys/signal.h>
+#include <sys/uflags.h>
+#include <sys/errno.h>
+#include <emx/syscalls.h>
+#include "emxdll.h"
+
+#define SIGF_CORE               0x01
+
+/* TODO: SIGSTOP */
+#define SET_BLOCKED(td,set) ((td)->sig_blocked = (set) & ~_SIGMASK (SIGKILL))
+
+
+/* This structure describes a signal. */
+
+struct signal_descr
+{
+  const char *name;             /* Name of the signal */
+  BYTE dfl_action;              /* Action for SIG_DFL */
+  BYTE fun_action;              /* Action taken after function */
+  BYTE flags;                   /* Flags (SIGF_CORE) */
+};
+
+
+/* Inhibit core dumps. */
+
+BYTE nocore_flag;
+
+/* Don't display harderror popups.  This is done by terminating the
+   process instead of returning XCPT_CONTINUE_SEARCH from the
+   exception handler. */
+
+BYTE no_popup;
+
+/* Event semaphore for temporarily blocked signal. */
+
+HEV signal_sem;
+
+/* This flag is set when a temporarily blocked signal is generated. */
+
+char sig_flag;
+
+/* When exec() is called in a forked process, we pass on signals to
+   the child process until it terminates.  This variable holds the
+   process ID of the child process.  If the value is zero, there is no
+   such child process. */
+
+ULONG fork_exec_pid;
+
+/* Critical sections for signal processing are protected by this Mutex
+   semaphore. */
+
+static HMTX sig_access;
+
+
+/* 16-bit signal handler. */
+
+extern _far16ptr old_sig16_handler;
+extern void (*sig16_handler)(void);
+
+#define ST_TERM   0             /* Terminate process (SIGINT for instance) */
+#define ST_NEXT   1             /* Pass on to next exception handler */
+#define ST_IGNORE 2             /* Ignore exception and continue thread */
+
+
+/* This array contains TRUE for all valid signal numbers. */
+
+char const signal_valid[NSIG] =
+{
+  FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,  /* 0..9 */
+  TRUE,  TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, /* 10..19 */
+  FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE   /* 20..28 */
+};
+
+/* This array contains constant information about the signals: The
+   name of the signal, what to do for SIG_DFL and after calling the
+   signal handler, respectively, and whether to dump core or not. */
+
+static struct signal_descr const signal_info[NSIG] =
+{
+  {"SIG0",     ST_TERM,   ST_TERM,   0},
+  {"SIGHUP",   ST_TERM,   ST_IGNORE, 0},
+  {"SIGINT",   ST_TERM,   ST_IGNORE, 0},
+  {"SIGQUIT",  ST_TERM,   ST_IGNORE, SIGF_CORE},
+  {"SIGILL",   ST_NEXT,   ST_NEXT,   SIGF_CORE},
+  {"SIGTRAP",  ST_NEXT,   ST_NEXT,   SIGF_CORE},
+  {"SIGABRT",  ST_TERM,   ST_TERM,   SIGF_CORE},
+  {"SIGEMT",   ST_TERM,   ST_TERM,   SIGF_CORE},
+  {"SIGFPE",   ST_NEXT,   ST_NEXT,   SIGF_CORE},
+  {"SIGKILL",  ST_TERM,   ST_TERM,   0},
+  {"SIGBUS",   ST_TERM,   ST_TERM,   SIGF_CORE},
+  {"SIGSEGV",  ST_NEXT,   ST_NEXT,   SIGF_CORE},
+  {"SIGSYS",   ST_TERM,   ST_TERM,   SIGF_CORE},
+  {"SIGPIPE",  ST_TERM,   ST_IGNORE, 0},
+  {"SIGALRM",  ST_TERM,   ST_IGNORE, 0},
+  {"SIGTERM",  ST_NEXT,   ST_IGNORE, 0},
+  {"SIGUSR1",  ST_IGNORE, ST_IGNORE, 0},
+  {"SIGUSR2",  ST_IGNORE, ST_IGNORE, 0},
+  {"SIGCLD",   ST_IGNORE, ST_IGNORE, 0},
+  {"SIG19",    ST_TERM,   ST_TERM,   0},
+  {"SIG20",    ST_TERM,   ST_TERM,   0},
+  {"SIGBREAK", ST_TERM,   ST_IGNORE, 0},
+  {"SIG22",    ST_TERM,   ST_TERM,   0},
+  {"SIG23",    ST_TERM,   ST_TERM,   0},
+  {"SIG24",    ST_TERM,   ST_TERM,   0},
+  {"SIG25",    ST_TERM,   ST_TERM,   0},
+  {"SIG26",    ST_TERM,   ST_TERM,   0},
+  {"SIG27",    ST_TERM,   ST_TERM,   0},
+  {"SIGWINCH", ST_IGNORE, ST_IGNORE, 0}
+};
+
+
+/* Prototypes. */
+
+static ULONG kill_emx (int pid, int signo, int tree);
+
+
+/* Display a message when terminating a process due to signal
+   SIGNO. */
+
+static void signal_message (int signo)
+{
+  if (signo == SIGABRT)
+    otext ("\r\nAbnormal program termination\r\n");
+  else
+    oprintf ("\r\nProcess terminated by %s\r\n", signal_info[signo].name);
+}
+
+
+static void sig_lock (void)
+{
+  ULONG count;
+
+  DosEnterMustComplete (&count);
+  request_mutex (sig_access);
+}
+
+
+static void sig_unlock (void)
+{
+  ULONG count;
+
+  DosReleaseMutexSem (sig_access);
+  DosExitMustComplete (&count);
+}
+
+
+/* Acknowledge the signal to OS/2. */
+
+static void acknowledge (int signo)
+{
+  switch (signo)
+    {
+    case SIGINT:
+      DosAcknowledgeSignalException (XCPT_SIGNAL_INTR);
+      break;
+    case SIGTERM:
+      DosAcknowledgeSignalException (XCPT_SIGNAL_KILLPROC);
+      break;
+    case SIGBREAK:
+      DosAcknowledgeSignalException (XCPT_SIGNAL_BREAK);
+      break;
+    }
+}
+
+
+static void acknowledge_mult (ULONG set)
+{
+  if (set & _SIGMASK (SIGINT))
+    acknowledge (SIGINT);
+  if (set & _SIGMASK (SIGBREAK))
+    acknowledge (SIGBREAK);
+  if (set & _SIGMASK (SIGKILL))
+    acknowledge (SIGKILL);
+}
+
+
+/* Generate a signal. */
+
+void generate_signal (thread_data *td, int signo)
+{
+  struct signal_entry *p;
+
+  sig_lock ();
+  p = td->sig_table + signo;
+  if (p->handler != SIG_IGN)
+    {
+      td->sig_pending |= _SIGMASK (signo);
+      if ((td->sig_blocked & ~td->sig_prev_blocked & _SIGMASK (signo))
+          && p->handler != SIG_DFL)
+        {
+          /* Wake up __select() */
+
+          sig_flag = TRUE;
+          DosPostEventSem (signal_sem);
+        }
+      if (td == threads[1] && get_tid () != 1)
+        {
+          /* Interrupt thread 1 and let it examine its set of pending
+             signals. */
+
+          DosFlagProcess (my_pid, FLGP_PID, PFLG_A, 0);
+        }
+    }
+  sig_unlock ();
+}
+
+
+static void regen_sigcld (int lock)
+{
+  if (lock) sig_lock ();
+  if (zombie_count > 0)
+    threads[1]->sig_pending |= _SIGMASK (SIGCLD);
+  if (lock) sig_unlock ();
+}
+
+
+/* Terminate the process.  Optionally do a core dump, taking the
+   registers from the syscall stack frame or the exception context
+   record.  Actually, the process is not terminated by this function
+   if CONTEXT_RECORD is non-NULL and no_popup is false. */
+
+static void sig_terminate (int signo, syscall_frame *frame,
+                           CONTEXTRECORD *context_record)
+{
+  signal_message (signo);
+
+  if (signo == SIGKILL
+      || (!nocore_flag && (signal_info[signo].flags & SIGF_CORE)))
+    {
+      if (frame != NULL)
+        {
+          core_regs_i (frame);
+          core_dump ();
+        }
+      else if (context_record != NULL)
+        {
+          core_regs_e (context_record);
+          core_dump ();
+        }
+    }
+  if (context_record == NULL || no_popup)
+    quit (3);
+}
+
+
+/* Call a signal handler.  This function's stack frame contains four
+   magic words, a pointer to the syscall frame, and a pointer to the
+   context record.  This allows backtracing over invocations of signal
+   handlers. */
+
+static void call_handler2 (ULONG magic1, ULONG magic2, ULONG magic3,
+                           ULONG magic4, syscall_frame *frame,
+                           CONTEXTRECORD *context_record,
+                           void (*handler)(int), int signo)
+{
+  handler (signo);
+}
+
+
+/* Call a signal handler.  This function puts magic words into the
+   stack, see call_handler2(). */
+
+static void call_handler1 (void (*handler)(int), int signo,
+                           syscall_frame *frame, CONTEXTRECORD *context_record)
+{
+  call_handler2 (_SIG_MAGIC1, _SIG_MAGIC2, _SIG_MAGIC3, _SIG_MAGIC4,
+                 frame, context_record, handler, signo);
+}
+
+
+
+/* Deliver a signal.  FRAME points to the system call stack frame,
+   CONTEXT_RECORD points to the exception context record.  This
+   function must be called with sig_lock() in effect; sig_unlock() is
+   called by this function.
+
+   Return ST_TERM, ST_IGNORE, or ST_NEXT. */
+
+static int deliver_signal (thread_data *td, int signo,
+                           syscall_frame *frame,
+                           CONTEXTRECORD *context_record)
+{
+  struct signal_entry *p;
+  void (*handler)(int signo);
+  ULONG mask, old_blocked;
+
+  mask = _SIGMASK (signo);
+  p = td->sig_table + signo;
+
+  td->sig_pending &= ~mask;
+  handler = p->handler;
+
+  if (handler == SIG_IGN)
+    {
+      /* Ignore the signal. */
+
+      sig_unlock ();
+    }
+  else if (handler == SIG_DFL)
+    {
+      /* If the default handler SIG_DFL is installed, check the signal
+         information table to learn whether to ignore the signal or to
+         terminate the process. */
+
+      sig_unlock ();
+      if (signal_info[signo].dfl_action != ST_IGNORE)
+        {
+          sig_terminate (signo, frame, context_record);
+          return signal_info[signo].dfl_action;
+        }
+    }
+  else
+    {
+      /* Call the user-defined signal handler. */
+
+      if (p->sa_flags & SA_SYSV)
+        {
+          p->handler = SIG_DFL;
+          sig_unlock ();
+          call_handler1 (handler, signo, frame, context_record);
+        }
+      else if (p->sa_flags & SA_ACK)
+        {
+          td->sig_blocked |= mask;
+          sig_unlock ();
+          call_handler1 (handler, signo, frame, context_record);
+        }
+      else
+        {
+          old_blocked = td->sig_blocked;
+          SET_BLOCKED (td, td->sig_blocked | mask | p->sa_mask);
+          sig_unlock ();
+          call_handler1 (handler, signo, frame, context_record);
+          td->sig_blocked = old_blocked;
+        }
+      if (signo == SIGCLD && td == threads[1])
+        regen_sigcld (TRUE);
+
+      /* Check the signal information table to learn whether to
+         continue the program or to terminate the process.  This is
+         only done when called from an exception handler. */
+
+      if (context_record != NULL && signal_info[signo].fun_action != ST_IGNORE)
+        {
+          sig_terminate (signo, frame, context_record);
+          return signal_info[signo].fun_action;
+        }
+    }
+  return ST_IGNORE;
+}
+
+
+/* Deliver all pending signals. */
+
+int deliver_pending_signals (thread_data *td, syscall_frame *frame,
+                              CONTEXTRECORD *context_record)
+{
+  int signo, action;
+
+  sig_lock ();
+  while ((td->sig_pending & ~td->sig_blocked) != 0)
+    {
+      for (signo = 1; signo < NSIG; ++signo)
+        if (td->sig_pending & ~td->sig_blocked & _SIGMASK (signo))
+          {
+            action = deliver_signal (td, signo, frame, context_record);
+            if (action != ST_IGNORE)
+              return action;
+            sig_lock ();
+          }
+    }
+  sig_unlock ();
+  return ST_IGNORE;
+}
+
+
+/* This function is called from the 16-bit signal handler to generate
+   signal SIGNO (if SIGNO is non-zero) and to deliver pending
+   signals. */
+
+void raise_from_16 (int signo)
+{
+  if (fork_exec_pid != 0)
+    kill_emx (fork_exec_pid, signo, FALSE);
+  else
+    {
+      if (signo != 0)
+        generate_signal (threads[1], signo);
+      deliver_pending_signals (threads[1], NULL, NULL);
+    }
+}
+
+
+/* Unblock temporarily blocked signals, raise pending signals. */
+
+void sig_block_end (void)
+{
+  thread_data *td;
+
+  td = get_thread ();
+  sig_lock ();
+  td->sig_blocked = td->sig_prev_blocked;
+  td->sig_prev_blocked = 0;
+  sig_unlock ();
+  deliver_pending_signals (td, NULL, NULL);
+}
+
+
+/* Temporarily block signals (for the duration of a system call).
+   From now on, no signals will be raised.  Instead, generated signals
+   will be made pending. */
+
+void sig_block_start (void)
+{
+  thread_data *td;
+
+  td = get_thread ();
+  sig_lock ();
+  sig_flag = FALSE;
+  reset_event_sem (signal_sem); /* select() waits for this semaphore */
+  td->sig_prev_blocked = td->sig_blocked;
+  SET_BLOCKED (td, ~0);
+  sig_unlock ();
+}
+
+
+/* Send a signal to another process (or process tree).  PID is the
+   process ID of the target process and SIGNO is the signal number.
+   Send signal to the process tree starting at PID if tree is true. */
+
+static ULONG kill_emx (int pid, int signo, int tree)
+{
+  return DosFlagProcess (pid, (tree ? FLGP_SUBTREE : FLGP_PID), PFLG_A, signo);
+}
+
+
+void do_raise (int signo, syscall_frame *frame)
+{
+  thread_data *td;
+
+  td = get_thread ();
+  generate_signal (td, signo);
+  deliver_pending_signals (td, frame, NULL);
+}
+
+
+/* This function implements the __kill() system call.  SIGNO is the
+   signal number (or 0 to check whether the target process is alive).
+   PID is the process ID of the target process.  Store the error
+   number (errno) to *ERRNOP.  Return 0 on success, -1 on failure. */
+
+int do_kill (int signo, int pid, syscall_frame *frame, int *errnop)
+{
+  ULONG rc;
+  int org_pid;
+
+  /* Check whether process PID is alive if SIGNO is 0. */
+
+  if (signo == 0)
+    {
+      if (proc_check (pid))
+        {
+          /* The process is alive. */
+
+          *errnop = 0;
+          return 0;
+        }
+
+      /* The process does not exist. */
+
+      *errnop = ESRCH;
+      return -1;
+    }
+
+  /* Fail if SIGNO is not a valid signal number. */
+
+  if (signo < 0 || signo >= NSIG || !signal_valid[signo])
+    {
+      *errnop = EINVAL;
+      return -1;
+    }
+
+  /* Map `kill(getpid(),signo)' to `raise(signo)' to enable core
+     dumps.  Do this only for the main thread as kill() is defined
+     (for emx) to send the signal to the main thread. */
+
+  if (pid == my_pid && get_tid () == 1)
+    {
+      do_raise (signo, frame);
+      *errnop = 0;
+      return 0;
+    }
+
+  /* Save the original process or group ID and turn a group ID (PID is
+     negative) into a process ID. */
+
+  org_pid = pid;
+  if (pid < -1)                 /* Process group? */
+    pid = -pid;                 /* Yes: compute PID from group ID */
+
+  /* SIGKILL is treated specially: Call DosKillProcess. */
+
+  if (signo == SIGKILL)
+    {
+      /* When sending SIGKILL to a process group, first try to kill
+         the process tree.  If this fails, kill only one process.
+         When sending SIGKILL to a single process, kill only that
+         process. */
+
+      if (org_pid < -1)
+        {
+          rc = DosKillProcess (DKP_PROCESSTREE, pid);
+          if (rc != 0)
+            rc = DosKillProcess (DKP_PROCESS, pid);
+        }
+      else
+        rc = DosKillProcess (DKP_PROCESS, pid);
+
+      /* If the process has already been killed but has not yet
+         reacted to the signal, the return code will be
+         ERROR_SIGNAL_PENDING.  Ignore this error. */
+
+      if (rc == 0 || rc == ERROR_SIGNAL_PENDING)
+        {
+          *errnop = 0;
+          return 0;
+        }
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* We can send SIGINT and SIGBREAK to child processes. */
+
+  if ((signo == SIGINT || signo == SIGBREAK) && pid != my_pid)
+    {
+      rc = DosSendSignalException (pid, ((signo == SIGINT)
+                                         ? XCPT_SIGNAL_INTR
+                                         : XCPT_SIGNAL_BREAK));
+      if (rc == 0)
+        {
+          *errnop = 0;
+          return 0;
+        }
+      /* Seems not to be a child process.  Use DosFlagProcess. */
+    }
+
+  /* Send the signal via a 16-bit signal (DosFlagProcess).  This works
+     only for emx programs. */
+
+  if (org_pid < -1)
+    {
+      rc = kill_emx (pid, signo, TRUE);
+      if (rc != 0)
+        rc = kill_emx (pid, signo, FALSE);
+    }
+  else
+    rc = kill_emx (pid, signo, FALSE);
+  if (rc == 0)
+    {
+      *errnop = 0;
+      return 0;
+    }
+  *errnop = set_error (rc);
+  return -1;
+}
+
+
+/* Set a signal handler or acknowledge a signal.  This is the main
+   code for the __signal() system call.  SIGNO is the signal number.
+   HANDLER is SIG_DFL, SIG_IGN, SIG_ACK or the address of the signal
+   handler to be used.  FRAME points to the syscall stack frame in
+   case we have to dump core.  Return the previous (or current for
+   SIG_ACK) signal handler or SIG_ERR on error. */
+
+sigfun *do_signal (ULONG signo, sigfun *handler, syscall_frame *frame)
+{
+  if (handler == SIG_ACK)
+    {
+      thread_data *td;
+      struct signal_entry *p;
+      void (*result)(int signo);
+
+      /* Acknowledge (unblock) the signal. */
+
+      if (signo < 1 || signo >= NSIG || !signal_valid[signo])
+        return SIG_ERR;
+
+      td = get_thread ();
+      p = td->sig_table + signo;
+
+      sig_lock ();
+      if (!(p->sa_flags & SA_ACK))
+        {
+          sig_unlock ();
+          return SIG_ERR;
+        }
+      acknowledge (signo);
+      td->sig_blocked &= ~_SIGMASK (signo);
+      result = p->handler;
+      sig_unlock ();
+      deliver_pending_signals (td, frame, NULL);
+      return handler;
+    }
+  else
+    {
+      struct sigaction isa, osa;
+
+      isa.sa_handler = handler;
+      isa.sa_mask = 0;
+      switch (uflags & _UF_SIG_MODEL)
+        {
+        case _UF_SIG_SYSV:
+          isa.sa_flags = SA_SYSV;
+          break;
+        case _UF_SIG_EMX:
+          isa.sa_flags = SA_ACK;
+          break;
+        default:
+          isa.sa_flags = 0;
+          break;
+        }
+      if (do_sigaction (signo, &isa, &osa) != 0)
+        return SIG_ERR;
+      else
+        return osa.sa_handler;
+    }
+}
+
+
+/* This function implements the __sigaction() system call. */
+
+int do_sigaction (int signo, const struct sigaction *iact,
+                  struct sigaction *oact)
+{
+  thread_data *td;
+  struct signal_entry *p;
+  struct sigaction output;
+
+  /* Check the signal number. */
+
+  if (signo < 1 || signo >= NSIG || !signal_valid[signo])
+    return EINVAL;
+
+  /* Fail if the process tries to set the action for SIGKILL.
+
+     POSIX.1, 3.3.1.3: "The system shall not allow the action for the
+     signals SIGKILL or SIGSTOP to be set to SIG_IGN."
+
+     POSIX.1, 3.3.1.3: "The system shall not allow a process to catch
+     the signals SIGKILL and SIGSTOP."
+
+     POSIX.1, 3.3.4.2: "It is unspecified whether an attempt to set
+     the action for a signal that cannot be caught or ignored to
+     SIG_DFL is ignored or causes an error to be returned with errno
+     set to [EINVAL]." */
+
+  if (signo == SIGKILL && iact != NULL)
+    return EINVAL;
+
+  /* Get a pointer to the thread data block and a pointer to the
+     signal table entry for SIGNO of the current thread. */
+
+  td = get_thread ();
+  p = td->sig_table + signo;
+
+  /* Save the previous action. */
+
+  sig_lock ();
+  output.sa_handler = p->handler;
+  output.sa_mask = p->sa_mask;
+  output.sa_flags = p->sa_flags;
+
+  /* Install new action if IACT is not NULL. */
+
+  if (iact != NULL)
+    {
+      p->handler = iact->sa_handler;
+      p->sa_mask = iact->sa_mask;
+      p->sa_flags = iact->sa_flags;
+
+      if ((p->handler == SIG_DFL && signal_info[signo].dfl_action != ST_IGNORE)
+          || p->handler == SIG_IGN)
+        {
+          /* POSIX.1, 3.3.1.3: "Setting a signal action to SIG_DFL for
+             a signal that is pending, and whose default action is to
+             ignore the signal (for example, SIGCHLD), shall cause the
+             pending signal to be discarded, whether or not it is
+             blocked."
+
+             POSIX.1, 3.3.1.3: "Setting a signal action to SIG_IGN for
+             a signal that is pending shall cause the pending signal
+             to be discarded, whether or not it is blocked." */
+
+          td->sig_pending &= ~_SIGMASK (signo);
+        }
+
+      if ((p->sa_flags & SA_SYSV) && signo == SIGCLD)
+        regen_sigcld (FALSE);
+    }
+
+  /* Store previous action to *OACT if OACT is not NULL.  Do this
+     after reading *IACT because IACT may point to the same set as
+     OACT. */
+
+  if (oact != NULL)
+    *oact = output;
+
+  sig_unlock ();
+  return 0;
+}
+
+
+int do_sigpending (sigset_t *set)
+{
+  thread_data *td;
+
+  td = get_thread ();
+  sig_lock ();
+  *set = td->sig_blocked & td->sig_pending;
+  sig_unlock ();
+  return 0;
+}
+
+
+int do_sigprocmask (int how, const sigset_t *iset, sigset_t *oset,
+                    syscall_frame *frame)
+{
+  thread_data *td;
+  ULONG temp, output;
+
+  td = get_thread ();
+  sig_lock ();
+  output = td->sig_blocked;
+  if (iset != NULL)
+    {
+      switch (how)
+        {
+        case SIG_BLOCK:
+          temp = td->sig_blocked | *iset;
+          break;
+        case SIG_UNBLOCK:
+          temp = td->sig_blocked & ~*iset;
+          break;
+        case SIG_SETMASK:
+          temp = *iset;
+          break;
+        default:
+          sig_unlock ();
+          return EINVAL;
+        }
+      acknowledge_mult (td->sig_blocked & ~temp);
+      SET_BLOCKED (td, temp);
+
+    }
+
+  /* Set *OSET after reading *ISET, because ISET may point to the same
+     set as OSET. */
+
+  if (oset != NULL)
+    *oset = output;
+
+  /* POSIX.1, 3.3.5.2: "If there are any pending unblocked signals
+     after the call to the sigprocmask() function, at least one of
+     those signals shall be delivered before the sigprocmask()
+     function returns." */
+
+  sig_unlock ();
+  deliver_pending_signals (td, frame, NULL);
+  return 0;
+}
+
+
+/* This function implements the __pause() system call.  Wait for the
+   occurance of a signal.  Signals set to SIG_IGN should not make this
+   function return, but they do (for now). */
+
+void do_pause (void)
+{
+  ULONG rc;
+
+  do
+    {
+      rc = DosSleep ((ULONG)(-1));
+    } while (rc == 0);
+}
+
+
+int do_sigsuspend (const sigset_t *mask)
+{
+  ULONG old_blocked;
+  thread_data *td;
+
+  td = get_thread ();
+  sig_lock ();
+  old_blocked = td->sig_blocked;
+  acknowledge_mult (~*mask & td->sig_blocked);
+  SET_BLOCKED (td, *mask);
+  sig_unlock ();
+  do_pause ();
+  td->sig_blocked = old_blocked;
+  return EINTR;
+}
+
+
+/* Raise signal SIGNO from the exception handler. */
+
+ULONG signal_exception (int signo, CONTEXTRECORD *context)
+{
+  thread_data *td;
+  struct signal_entry *p;
+  int action;
+
+  if (fork_exec_pid != 0)
+    {
+      kill_emx (fork_exec_pid, signo, FALSE);
+      acknowledge (signo);
+      return XCPT_CONTINUE_EXECUTION;
+    }
+
+  /* Get a pointer to the thread data block and a pointer to the
+     signal table entry for SIGNO of the current thread. */
+
+  td = get_thread ();
+  p = td->sig_table + signo;
+
+  if (p->handler != SIG_IGN)
+    {
+      generate_signal (td, signo);
+      action = deliver_pending_signals (td, NULL, context);
+      switch (action)
+        {
+        case ST_TERM:
+          quit (3);
+        case ST_NEXT:
+          acknowledge (signo);
+          return XCPT_CONTINUE_SEARCH;
+        default:
+          break;
+        }
+    }
+  acknowledge (signo);
+  return XCPT_CONTINUE_EXECUTION;
+}
+
+
+static ULONG trap (EXCEPTIONREPORTRECORD *report,
+                   CONTEXTRECORD *context,
+                   int signo)
+{
+  struct signal_entry *p;
+  thread_data *td;
+
+  /* Don't try to do anything if the stack is invalid or in a nested
+     exception. */
+
+  if (report->fHandlerFlags & (EH_STACK_INVALID|EH_NESTED_CALL))
+    return XCPT_CONTINUE_SEARCH;
+
+  /* Get a pointer to the thread data block and a pointer to the
+     signal table entry for SIGNO of the current thread. */
+
+  td = get_thread ();
+  p = get_thread ()->sig_table + signo;
+
+  if (p->handler != SIG_IGN)
+    {
+      generate_signal (td, signo);
+
+      /* Deliver the signal even if its blocked. */
+
+      sig_lock ();
+      deliver_signal (td, signo, NULL, context);
+
+      /* Deliver any other pending signals. */
+
+      deliver_pending_signals (td, NULL, context);
+    }
+
+  /* Invoke the next exception handler. */
+
+  return XCPT_CONTINUE_SEARCH;
+}
+
+
+/* Load a heap page from a dumped executable. */
+
+static void load_heap (ULONG addr)
+{
+  ULONG rc, cbread, newpos;
+
+  addr &= ~0xfff;
+  rc = DosSetFilePtr (exe_fhandle, addr - heap_objs[0].base + heap_off,
+                      FILE_BEGIN, &newpos);
+  if (rc == 0)
+    rc = DosRead (exe_fhandle, (void *)addr, 0x1000, &cbread);
+  if (rc != 0)
+    {
+      otext ("\r\nCannot read EXE file\r\n");
+      quit (255);
+    }
+}
+
+
+/* This is the exception handler. */
+
+ULONG exception (EXCEPTIONREPORTRECORD *report,
+                 EXCEPTIONREGISTRATIONRECORD *registration,
+                 CONTEXTRECORD *context, void *dummy)
+{
+  ULONG addr;
+
+  /* Don't trust -- clear the decrement flag. */
+
+  __asm__ ("cld");
+
+  /* Don't do anything when unwinding exception handlers. */
+
+  if (report->fHandlerFlags & (EH_EXIT_UNWIND|EH_UNWINDING))
+    return XCPT_CONTINUE_SEARCH;
+
+  /* The rest of this function depends on the exception number. */
+
+  switch (report->ExceptionNum)
+    {
+    case XCPT_GUARD_PAGE_VIOLATION:
+
+      /* Guard page violation.  This exception is used for loading
+         heap pages from a dumped executable.  Moreover, this is used
+         by old emx programs for expanding the stack.  First, get the
+         address of the page. */
+
+      addr = report->ExceptionInfo[1];
+
+      /* Load a page from the executable if the page is in the heap
+         and we have a dumped executable. */
+
+      if (exe_heap && heap_obj_count >= 1
+          && addr >= heap_objs[0].base && addr < heap_objs[0].brk)
+        {
+          load_heap (addr);
+          return XCPT_CONTINUE_EXECUTION;
+        }
+
+      /* Looks like a guard page created by the application program.
+         Pass the exception to the next exception handler. */
+
+      return XCPT_CONTINUE_SEARCH;
+
+    case XCPT_ACCESS_VIOLATION:
+    case XCPT_DATATYPE_MISALIGNMENT:
+
+      /* Map access violations to SIGSEGV. */
+
+      return trap (report, context, SIGSEGV);
+
+    case XCPT_INTEGER_DIVIDE_BY_ZERO:
+    case XCPT_INTEGER_OVERFLOW:
+    case XCPT_ARRAY_BOUNDS_EXCEEDED:
+    case XCPT_FLOAT_DENORMAL_OPERAND:
+    case XCPT_FLOAT_DIVIDE_BY_ZERO:
+    case XCPT_FLOAT_INEXACT_RESULT:
+    case XCPT_FLOAT_INVALID_OPERATION:
+    case XCPT_FLOAT_OVERFLOW:
+    case XCPT_FLOAT_STACK_CHECK:
+    case XCPT_FLOAT_UNDERFLOW:
+
+      /* Map integer division by zero and floating point exceptions to
+         SIGFPE. */
+
+      return trap (report, context, SIGFPE);
+
+    case XCPT_ILLEGAL_INSTRUCTION:
+    case XCPT_INVALID_LOCK_SEQUENCE:
+    case XCPT_PRIVILEGED_INSTRUCTION:
+
+      /* Map the various exceptions for illegal instructions to
+         SIGILL. */
+
+      return trap (report, context, SIGILL);
+
+    case XCPT_SIGNAL:
+
+      /* Map signal exceptions to SIGINT, SIGTERM or SIGBREAK. */
+
+      if (report->cParameters >= 1)
+        switch (report->ExceptionInfo[0])
+          {
+          case XCPT_SIGNAL_INTR:
+            return signal_exception (SIGINT, context);
+          case XCPT_SIGNAL_KILLPROC:
+            return signal_exception (SIGTERM, context);
+          case XCPT_SIGNAL_BREAK:
+            return signal_exception (SIGBREAK, context);
+          }
+      return XCPT_CONTINUE_SEARCH;
+    }
+
+  /* The exception is not handled by emx.  Pass it to the next
+     exception handler. */
+
+  return XCPT_CONTINUE_SEARCH;
+}
+
+
+/* Install the exception handler for the main thread.  REGISTRATION
+   points to the exception registration record, which must be in the
+   stack (at the `bottom' of the stack). */
+
+void install_except (EXCEPTIONREGISTRATIONRECORD *registration)
+{
+  ULONG rc;
+
+  registration->prev_structure = NULL;
+  registration->ExceptionHandler = exception;
+  rc = DosSetExceptionHandler (registration);
+  if (rc != 0)
+    error (rc, "DosSetExceptionHandler");
+}
+
+
+/* Install the exception handler for another thread.  REGISTRATION
+   points to the exception registration record, which must be in the
+   stack (at the `bottom' of the stack). */
+
+int initthread (EXCEPTIONREGISTRATIONRECORD *registration)
+{
+  ULONG rc;
+
+  registration->prev_structure = NULL;
+  registration->ExceptionHandler = exception;
+  rc = DosSetExceptionHandler (registration);
+  return 0;
+}
+
+
+/* We want to receive signals. */
+
+void receive_signals (void)
+{
+  ULONG times;
+
+  DosSetSignalExceptionFocus (SIG_SETFOCUS, &times);
+}
+
+
+void init_exceptions (void)
+{
+  USHORT old_sig16_action;      /* Dummy (output) */
+
+  sig_flag = FALSE;
+  create_event_sem (&signal_sem, DC_SEM_SHARED);
+  create_mutex_sem (&sig_access);
+  install_except (exc_reg_ptr);
+  init_signal16 ();
+  DosSetSigHandler (_emx_32to16 (&sig16_handler), &old_sig16_handler,
+                    &old_sig16_action, SIGA_ACCEPT, SIG_PFLG_A);
+}
+
+
+/* alarm() */
+
+static BYTE alarm_started;
+static BYTE alarm_set;
+static ULONG alarm_interval;
+static ULONG alarm_time;
+static HTIMER alarm_timer;
+static HEV alarm_sem_timer;
+static TID alarm_tid;
+
+
+/* Exception handler for alarm_thread().  On termination of the
+   thread, alarm_tid will be set to zero. */
+
+static ULONG alarm_exception (EXCEPTIONREPORTRECORD *report,
+                              EXCEPTIONREGISTRATIONRECORD *registration,
+                              CONTEXTRECORD *context,
+                              void *dummy)
+{
+  if (report->fHandlerFlags & (EH_EXIT_UNWIND|EH_UNWINDING))
+    return XCPT_CONTINUE_SEARCH;
+  switch (report->ExceptionNum)
+    {
+    case XCPT_ASYNC_PROCESS_TERMINATE: /* This is the correct one */
+    case XCPT_PROCESS_TERMINATE:       /* OS/2 bug */
+      alarm_tid = 0;
+      break;
+    }
+  return XCPT_CONTINUE_SEARCH;
+}
+
+
+static void alarm_thread (ULONG arg)
+{
+  ULONG rc;
+  EXCEPTIONREGISTRATIONRECORD registration;
+
+  registration.prev_structure = NULL;
+  registration.ExceptionHandler = alarm_exception;
+  DosSetExceptionHandler (&registration);
+
+  for (;;)
+    {
+      rc = DosWaitEventSem (alarm_sem_timer, -1);
+      if (rc == 0)
+        {
+          reset_event_sem (alarm_sem_timer);
+          generate_signal (threads[1], SIGALRM);
+        }
+      else if (rc != ERROR_INTERRUPT)
+        error (rc, "DosWaitEventSem");
+    }
+}
+
+
+void start_alarm (void)
+{
+  ULONG rc;
+
+  if (create_event_sem (&alarm_sem_timer, DC_SEM_SHARED) == 0)
+    {
+      rc = DosCreateThread (&alarm_tid, alarm_thread, 0,
+                            CREATE_READY | STACK_COMMITTED, 0x4000);
+      if (rc != 0)
+        error (rc, "DosCreateThread");
+      else
+        alarm_started = TRUE;
+    }
+}
+
+
+ULONG set_alarm (ULONG value)
+{
+  ULONG rc, rest, result;
+
+  if (!alarm_started)
+    {
+      start_alarm ();
+      if (!alarm_started)
+        return -1;
+    }
+  result = 0;
+  if (alarm_set)
+    {
+      rest = querysysinfo (QSV_TIME_LOW) - alarm_time;
+      if (alarm_interval >= rest)
+        result = alarm_interval - rest;
+      DosStopTimer (alarm_timer);
+      alarm_set = FALSE;
+      reset_event_sem (alarm_sem_timer);
+    }
+  if (value == 0)
+    alarm_interval = 0;
+  else
+    {
+      alarm_set = TRUE;
+      alarm_interval = value;
+      rc = DosAsyncTimer (1000 * value, (HSEM)alarm_sem_timer, &alarm_timer);
+      if (rc != 0)
+        error (rc, "DosAsyncTimer");
+      alarm_time = querysysinfo (QSV_TIME_LOW);
+    }
+  return result;
+}
+
+
+void stop_alarm (void)
+{
+  if (!alarm_started)
+    set_alarm (0);
+}
+
+
+/* Called from DLL termination routine. */
+
+void term_signal (void)
+{
+  if (alarm_tid != 0)
+    DosKillThread (alarm_tid);
+}
+
+
+/* Inherit signal settings from parent process.  These are passed in
+   the `_emx_sig' environment variable, which consists of the PID of
+   the parent process (to ensure that we get the signal settings of
+   our parent process), a colon, and a 32-bit number.  Bit n is set in
+   that number if signal n is to be ignored.  Each number is passed as
+   8 hexadecimal digits. */
+
+void init2_signal (void)
+{
+  PSZ val;
+  ULONG ppid, sigset;
+  int sig;
+
+  if (!(debug_flags & DEBUG_NOINHSIG)
+      && DosScanEnv ("_emx_sig", &val) == 0 && conv_hex8 (val, &ppid)
+      && ppid == init_pib_ptr->pib_ulppid && val[8] == ':'
+      && conv_hex8 (val + 9, &sigset) && val[17] == 0)
+    {
+      for (sig = 1; sig < NSIG; ++sig)
+        if (sigset & (1 << sig))
+          threads[1]->sig_table[sig].handler = SIG_IGN;
+    }
+}
Index: trunk/src/emx/src/os2/syscall.c
===================================================================
--- trunk/src/emx/src/os2/syscall.c	(revision 18)
+++ trunk/src/emx/src/os2/syscall.c	(revision 18)
@@ -0,0 +1,1268 @@
+/* syscall.c -- emx system calls
+   Copyright (c) 1994-1998 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSMISC
+#define INCL_DOSNLS
+#define INCL_DOSPROCESS
+#define INCL_VIO
+#include <os2emx.h>
+#include <sys/signal.h>
+#include <sys/errno.h>
+#include "emxdll.h"
+#include "tcpip.h"
+#include "version.h"
+#include <sys/nls.h>
+#include <sys/timeb.h>
+#include <sys/time.h>
+#include <sys/ulimit.h>
+
+static void bad_spec (syscall_frame *f);
+static ULONG do_syserrno (void);
+static ULONG do_setsyserrno (ULONG errcode);
+static void do_memupr (char *dst, ULONG size);
+static int do_ctype (unsigned char *dst, int *errnop);
+static void do_scrsize (int *dst);
+static ULONG do_read_kbd (ULONG flags);
+static unsigned do_sleep (unsigned sec);
+
+
+void sys_call (syscall_frame *f)
+{
+  int err_no;
+
+  if (debug_flags & DEBUG_SYSCALL)
+    oprintf ("%u: syscall 7f%.2x\r\n", my_pid, (unsigned)f->b.al);
+
+  f->e.eflags &= ~FLAG_C;
+
+  switch (f->b.al)
+    {
+    case 0x00:
+
+      /* __sbrk() */
+
+      f->e.eax = do_sbrk (f->e.edx);
+      break;
+
+    case 0x01:
+
+      /* __brk() */
+
+      f->e.eax = do_brk (f->e.edx);
+      break;
+
+    case 0x02:
+
+      /* __ulimit()
+
+         In:   ECX      Command code (must be UL_GMEMLIM or UL_OBJREST)
+               EDX      New limit (currently ignored)
+
+         Out:  EAX      Return value:
+                          greatest possible break value for UL_GMEMLIM
+                          remaining bytes in current heap object for UL_OBJREST
+               ECX      errno (0 if successful)
+
+         Get greatest possible break value or remaining number of
+         bytes in current heap object. */
+
+      switch (f->e.ecx)
+        {
+        case UL_GMEMLIM:
+          /* Note: As this is the limit for brk(), not for sbrk(), we
+             don't return 512M. */
+          f->e.eax = top_heap_obj != NULL ? top_heap_obj->end : 0;
+          f->e.ecx = 0;
+          break;
+        case UL_OBJREST:
+          f->e.eax = (top_heap_obj != NULL
+                      ? top_heap_obj->end - top_heap_obj->brk : 0);
+          f->e.ecx = 0;
+          break;
+        default:
+          f->e.eax = (ULONG)(-1);
+          f->e.ecx = EINVAL;
+          break;
+        }
+      break;
+
+    case 0x03:
+
+      /* __vmstat() */
+
+      if (f->e.ecx >= 4)
+        ((ULONG *)f->e.ebx)[0] = 0;
+      if (f->e.ecx >= 8)
+        ((ULONG *)f->e.ebx)[1] = 0;
+      break;
+
+    case 0x04:
+
+      /* __umask1() */
+
+      f->e.eax = umask_bits1;
+      umask_bits1 &= ~f->e.edx;
+      break;
+
+    case 0x05:
+
+      /* __getpid() */
+
+      f->e.eax = my_pid;
+      break;
+
+    case 0x06:
+
+      /* __spawnve() */
+
+      err_no = do_spawn ((struct _new_proc *)f->e.edx, &f->e.eax);
+      if (err_no != 0)
+        {
+          f->e.eax = err_no;
+          f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x08:
+
+      /* __ptrace()
+
+         In:   EBX      Request code (see /emx/include/sys/ptrace.h)
+               EDI      Process ID
+               EDX      Address
+               ECX      Data
+
+         Out:  EAX      Result
+               ECX      errno (0 if successful)
+
+         Debugging support */
+
+      f->e.eax = do_ptrace (f->e.ebx, f->e.edi, f->e.edx, f->e.ecx, &f->e.ecx);
+      break;
+
+    case 0x09:
+
+      /* __wait()
+
+         In:   --
+
+         Out:  EAX     Process ID of child process (-1 if no children)
+               ECX     errno
+               EDX     Termination status
+
+         Wait for child process.  There are two cases:
+
+         (1)  when debugging, return the value stored by
+             __ptrace(). Waiting for other processes is not possible
+
+         (2)  examine process table; sit on `process_death'. */
+
+      f->e.eax = do_wait (&f->e.edx, &f->e.ecx);
+      break;
+
+    case 0x0a:
+
+      /* __version()
+
+         In:   --
+
+         Out:  EAX      Version number
+                          Bits 0..7:    version letter ('a'..'z')
+                          Bits 8..15:   minor version number ('0'..'9')
+                          Bits 16..23:  0x2e ('.')
+                          Bits 24..31:  major version number ('0'..'9')
+               EBX      Environment:
+                          Bit 0:        VCPI
+                          Bit 1:        XMS
+                          Bit 2:        VDISK.SYS 3.3
+                          Bit 3:        DESQview
+                          Bit 4:        287
+                          Bit 5:        387
+                          Bit 6:        486      (not implemented)
+                          Bit 7:        DPMI 0.9 (not implemented)
+                          Bit 8:        DPMI 1.0 (not implemented)
+                          Bit 9:        OS/2 2.0
+                          Bit 10:       -t option given
+                          Bits 6..31:   0 (reserved for future expansion)
+               ECX      Revision index
+               EDX      0 (reserved for future expansion)
+
+         Return emx version. */
+
+      f->e.eax = (VERSION[3] | (VERSION[2] << 8)
+                  | (VERSION[1] << 16) | (VERSION[0] << 24));
+      f->e.ebx = 0x0a20;        /* OS/2 2.0, 387, -ac */
+      if (opt_trunc)
+        f->e.ebx |= 0x400;      /* Set -t bit */
+      f->e.ecx = REV_INDEX;
+      f->e.edx = 0;
+      break;
+
+    case 0x0b:
+
+      /* __memavail() */
+
+      f->e.eax = 0;
+      break;
+
+    case 0x0c:
+
+      /* __signal()
+
+         In:   ECX      Signal number
+               EDX      Address of signal handler or SIG_ACK, SIG_DFL, SIG_IGN
+
+         Out:  EAX      Previous value (success) or SIG_ERR (error)
+
+         Set signal handler. */
+
+      f->e.eax = (ULONG)do_signal (f->e.ecx, (sigfun *)f->e.edx, f);
+      break;
+
+    case 0x0d:
+
+      /* __kill()
+
+         In:   ECX      Signal number
+               EDX      Process ID
+
+         Out:  EAX      0 if successful, -1 otherwise
+               ECX      errno
+
+         Send a signal to a process.  If PID is the process ID of this
+         process, send the signal to thread 1.  Under OS/2, a process
+         cannot send a signal to itself using DosSendSignalException:
+         DosRaiseException must be used instead. */
+
+      f->e.eax = do_kill (f->e.ecx, f->e.edx, f, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x0e:
+
+      /* __raise()
+
+         In:   ECX      Signal number
+
+         Out:  EAX      0 if successful, a non-zero value otherwise
+               ECX      errno (0 if successful)
+
+         Raise a signal (in current process). */
+
+      if (f->e.ecx >= NSIG || !signal_valid [f->e.ecx])
+        {
+          f->e.eax = (ULONG)(-1);
+          f->e.ecx = EINVAL;
+        }
+      else
+        {
+          do_raise (f->e.ecx, f);
+          f->e.eax = 0;
+          f->e.ecx = 0;
+        }
+      break;
+
+    case 0x0f:
+
+      /* __uflags()
+
+         In:   ECX      Mask (only bits set to 1 in ECX will be changed)
+               EDX      New values of the bits selected by ECX
+
+         Out:  EAX      Previous set of flags
+               
+         Set user flags. */
+
+      f->e.eax = uflags;
+      uflags = (uflags & ~f->e.ecx) | (f->e.edx & f->e.ecx);
+      break;
+
+    case 0x10:
+
+      /* __unwind()
+
+         Unwind signal handlers for longjmp() -- old version. */
+
+      unwind (exc_reg_ptr, NULL);
+      break;
+
+    case 0x11:
+
+      /* __core() */
+
+      if (layout_flags & L_FLAG_LINK386)
+        {
+          f->e.eax = EACCES;
+          f->e.eflags |= FLAG_C;
+        }
+      else
+        {
+          core_regs_i (f);
+          f->e.eax = core_main (f->e.ebx);
+          if (f->e.eax != 0)
+            f->e.eflags |= FLAG_C;
+        }
+      break;
+
+    case 0x12:
+
+      /* __portaccess() */
+
+      f->e.eax = 0;
+      break;
+
+    case 0x13:
+
+      /* __memaccess () */
+
+      f->e.eax = EACCES;
+      f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x14:
+
+      /* __ioctl2()
+
+         In:   EBX      Handle
+               ECX      Request code
+               EDX      Argument
+
+         Out:  EAX      Return value
+               ECX      errno
+
+         Unix-like termio ioctl(). */
+
+      f->e.eax = do_ioctl2 (f->e.ebx, f->e.ecx, f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x15:
+
+      /* __alarm()
+
+         In:   EDX      Seconds
+
+         Out:  EAX      Time remaining
+
+         Set alarm clock. */
+
+      f->e.eax = set_alarm (f->e.edx);
+      break;
+
+    case 0x17:
+
+      /* __sleep()
+
+         In:   EDX      Seconds
+
+         Out:  EAX      Remaining time if interrupted by signal, or 0
+
+         Suspend process. */
+
+      f->e.eax = do_sleep (f->e.edx);
+      break;
+
+    case 0x18:
+
+      /* __chsize()
+
+         In:   EBX      File handle
+               EDX      File size
+
+         Out:  CY       Error
+               EAX      errno (CY)
+
+         Set file size. */
+
+      f->e.eax = do_chsize (f->e.ebx, f->e.edx);
+      if (f->e.eax != 0)
+        f->e.eflags |= FLAG_C;
+      break;
+
+    case 0x19:
+
+      /* __fcntl()
+
+        In:   EBX       File handle
+              ECX       Request code
+              EDX       Argument
+
+        Out:  EAX       Return value
+              ECX       errno (0 if successful)
+
+        Unix-like file control. */
+
+      f->e.eax = do_fcntl (f->e.ebx, f->e.ecx, f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x1a:
+
+      /* __pipe()
+
+        In:   ECX       Size of pipe
+              EDX       Pointer to storage for two handles (two DWORDs)
+
+        Out:  EAX       0 (success) or -1 (failure)
+              ECX       errno (0 if successful)
+
+        Create unnamed pipe. */
+
+      f->e.ecx = do_pipe ((int *)f->e.edx, f->e.ecx);
+      if (f->e.ecx == 0)
+        f->e.eax = 0;
+      else
+        f->e.eax = (ULONG)(-1);
+      break;
+
+    case 0x1b:
+
+      /* __fsync()
+
+         In:   EBX      File handle
+
+         Out:  EAX      0 (success) or -1 (failure)
+               ECX      errno (0 if successful)
+
+         Update file system. */
+
+      f->e.eax = do_fsync (f->e.ebx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x1c:
+
+      /* __fork()
+
+         Out:  EAX      Process ID or 0 (in new process) or -1 (failure)
+               ECX      errno (0 if successful)
+
+         Duplicate process. */
+
+      f->e.eax = do_fork (f, &f->e.ecx);
+      break;
+
+    case 0x1d:
+
+      /* __scrsize()
+
+         In:   EDX      Pointer to structure
+
+         Out:  --
+
+         Get number of rows and columns. */
+
+      do_scrsize ((int *)f->e.edx);
+      break;
+
+    case 0x1e:
+
+      /* __select()
+
+        In:   EDX       Pointer to structure
+
+        Out:  EAX       0 (timeout), > 0 (ready) or -1 (failure)
+              ECX       errno (0 if successful)
+
+        Synchronous I/O multiplexing. */
+
+      f->e.eax = do_select ((struct _select *)f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x1f:
+
+      /* __syserrno()
+
+        Out:  EAX       Error number
+       
+        Return OS/2 error number for last syscall. */
+
+      f->e.eax = do_syserrno ();
+      break;
+
+    case 0x20:
+
+      /* __stat()
+
+         In:  EDX       Path name
+              EDI       Pointer to structure
+
+         Out: EAX       0 (ok), -1 (error)
+              ECX       errno (0 if successful)
+
+         Get information about a path name. */
+
+      f->e.eax = do_stat ((const char *)f->e.edx, (struct stat *)f->e.edi,
+                          &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x21:
+
+      /* __fstat()
+
+        In:  EBX        File handle
+             EDI        Pointer to structure
+
+        Out: EAX        0 (ok), -1 (error)
+             ECX        errno (0 if successful)
+
+        Get information about an open file. */
+
+      f->e.eax = do_fstat (f->e.ebx, (struct stat *)f->e.edi, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x23:
+
+      /* __filesys()
+
+        In:  EDX        Pointer to drive name
+             EDI        Pointer to output buffer
+             ECX        Size of output buffer
+
+        Out: EAX        0 (ok) or -1 (error)
+             ECX        errno (0 if successful)
+
+        Get name of file-system driver. */
+
+      f->e.eax = do_filesys ((char *)f->e.edi, f->e.ecx,
+                             (const char *)f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x24:
+
+      /* __utimes()
+
+         In:  EDX       Pointer to path name
+              ESI       Pointer to array of structures
+
+         Out: EAX       0 (ok) or -1 (error)
+              ECX       errno (0 if successful)
+
+         Set access and modification time of a file. */
+
+      f->e.eax = do_utimes ((const char *)f->e.edx,
+                            (const struct timeval *)f->e.esi, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x25:
+
+      /* __ftruncate()
+
+         In:   EBX      File handle
+               EDX      File size
+
+         Out:  EAX      0 (ok), -1 (error)
+               ECX      errno (0 if successful)
+
+         Truncate a file. */
+
+      f->e.ecx = do_ftruncate (f->e.ebx, f->e.edx);
+      if (f->e.ecx == 0)
+        f->e.eax = 0;
+      else
+        f->e.eax = (ULONG)(-1);
+      break;
+
+    case 0x26:
+
+      /* __clock()
+
+         Out:  EAX      Timer ticks of CPU time used, low-order 32 bits
+               EDX      High-order 32 bits
+
+         Return CPU time used by this process. */
+
+      {
+        unsigned long long tmp;
+
+        tmp = get_clock (FALSE);
+        f->e.eax = (ULONG)tmp;
+        f->e.edx = (ULONG)(tmp >> 32);
+      }
+      break;
+
+    case 0x27:
+
+      /* __ftime()
+
+         In:   EDX      Pointer to structure
+
+         Get current time. */
+
+      do_ftime ((struct timeb *)f->e.edx);
+      break;
+
+    case 0x28:
+
+      /* __umask()
+
+         In:   EDX      New file permission mask
+
+         Out:  EAX      Previous file permission mask
+
+         Set file permission mask. */
+
+      f->e.eax = umask_bits;
+      umask_bits = f->e.edx;
+      break;
+
+    case 0x29:
+
+      /* __getppid()
+
+         Out: EAX       Parent process ID
+
+         Get parent process ID. */
+
+      f->e.eax = init_pib_ptr->pib_ulppid;
+      break;
+
+    case 0x2a:
+
+      /* __nls_memupr()
+
+         In:  EDX       Pointer to buffer
+              ECX       Size of buffer
+
+         Convert buffer to upper case. */
+
+      do_memupr ((char *)f->e.edx, f->e.ecx);
+      break;
+
+    case 0x2b:
+
+      /* __open()
+
+         In:   EDX      Pointer to file name
+               ECX      Flags
+               EBX      Size
+
+         Out:  EAX      Handle or -1 (failure)
+               ECX      errno (0 if successful)
+
+         Open a file. */
+
+      f->e.eax = sys_open ((const char *)f->e.edx, f->e.ecx, f->e.ebx,
+                           &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x2c:
+
+      /* __newthread()
+
+         In:   EDX      Thread ID
+
+         Out:  EAX      0 (success), -1 (failure)
+               ECX      errno (0 if successful)
+
+         Notify emx of a thread, create thread data block. */
+
+      f->e.eax = new_thread (f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x2d:
+
+      /* __endthread()
+
+         In:   EDX      Thread ID
+
+         Out:  EAX      0 (success), -1 (failure)
+               ECX      errno (0 if successful)
+
+         Notify emx of the end of a thread, deallocate thread data
+         block. */
+
+      f->e.eax = end_thread (f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x2e:
+
+      /* __waitpid()
+
+         In:   EDX      Process ID
+               ECX      Options
+
+         Out:  EAX      Process ID of child process (-1 if no children)
+               ECX      errno
+               EDX      Termination status
+
+         Wait for child process. */
+
+      f->e.eax = do_waitpid (f->e.edx, f->e.ecx, &f->e.edx, &f->e.ecx);
+      break;
+
+    case 0x2f:
+
+      /* __read_kbd()
+
+         In:   EDX      Flags (bit 0: echo, bit 1: wait, bit 2:sig)
+
+         Out:  EAX      Character (or -1)
+
+         Raw keyboard input. */
+
+      f->e.eax = do_read_kbd (f->e.edx);
+      break;
+
+    case 0x30:
+
+      /* __sleep2()
+
+         In:   EDX      Milliseconds
+
+         Out:  EAX      0
+
+         Suspend process. */
+
+      DosSleep (f->e.edx);
+      f->e.eax = 0;
+      break;
+
+    case 0x31:
+
+      /* __unwind2()
+
+         Unwind signal handlers for longjmp(). */
+
+      unwind ((EXCEPTIONREGISTRATIONRECORD *)f->e.edx, NULL);
+      break;
+
+    case 0x32:
+
+      /* __pause()
+
+         Wait for signal. */
+
+      do_pause ();
+      break;
+
+    case 0x33:
+
+      /* __execname()
+
+         In:   EDX      Buffer
+               ECX      Buffer size
+
+         Out:  EAX      0 if successful, -1 otherwise
+
+         Get the name of the executable file. */
+
+      f->e.eax = execname ((char *)f->e.edx, f->e.ecx);
+      break;
+
+    case 0x34:
+
+      /* __initthread()
+
+         In:   EDX      Pointer to EXCEPTIONREGISTRATIONRECORD
+
+         Out:  EAX      0 if successful, -1 otherwise
+
+         Install exception handler in new thread. */
+
+      f->e.eax = initthread ((EXCEPTIONREGISTRATIONRECORD *)f->e.edx);
+      break;
+
+    case 0x35:
+
+      /* __sigaction */
+
+      f->e.ecx = do_sigaction (f->e.ecx, (const struct sigaction *)f->e.edx,
+                               (struct sigaction *)f->e.ebx);
+      if (f->e.ecx == 0)
+        f->e.eax = 0;
+      else
+        f->e.eax = (ULONG)(-1);
+      break;
+
+    case 0x36:
+
+      /* __sigpending */
+
+      f->e.ecx = do_sigpending ((sigset_t *)f->e.edx);
+      if (f->e.ecx == 0)
+        f->e.eax = 0;
+      else
+        f->e.eax = (ULONG)(-1);
+      break;
+
+    case 0x37:
+
+      /* __sigprocmask */
+
+      f->e.ecx = do_sigprocmask (f->e.ecx, (const sigset_t *)f->e.edx,
+                                 (sigset_t *)f->e.ebx, f);
+      if (f->e.ecx == 0)
+        f->e.eax = 0;
+      else
+        f->e.eax = (ULONG)(-1);
+      break;
+
+    case 0x38:
+
+      /* __sigsuspend */
+
+      f->e.ecx = do_sigsuspend ((const sigset_t *)f->e.edx);
+      if (f->e.ecx == 0)
+        f->e.eax = 0;
+      else
+        f->e.eax = (ULONG)(-1);
+      break;
+
+    case 0x39:
+
+      /* __imphandle */
+
+      f->e.eax = do_imphandle (f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x3b:
+
+      /* __getsockhandle */
+
+      f->e.eax = tcpip_getsockhandle (f->e.ebx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x3c:
+
+      /* __socket */
+
+      f->e.eax = tcpip_socket (f->e.ecx, f->e.edx, f->e.ebx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x3d:
+
+      /* __bind */
+
+      f->e.ecx = tcpip_bind (f->e.ebx, (void *)f->e.edx, f->e.ecx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x3e:
+
+      /* __listen */
+
+      f->e.ecx = tcpip_listen (f->e.ebx, f->e.edx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x3f:
+
+      /* __recv */
+
+      f->e.eax = tcpip_recv (f->e.ebx, (void *)f->e.edx, f->e.ecx, f->e.esi,
+                             &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x40:
+
+      /* __send */
+
+      f->e.eax = tcpip_send (f->e.ebx, (const void *)f->e.edx, f->e.ecx,
+                             f->e.esi, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x41:
+
+      /* __accept */
+
+      f->e.eax = tcpip_accept (f->e.ebx, (void *)f->e.edx, (int *)f->e.ecx,
+                               &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x42:
+
+      /* __connect */
+
+      f->e.ecx = tcpip_connect (f->e.ebx, (void *)f->e.edx, f->e.ecx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x43:
+
+      /* __getsockopt */
+
+      f->e.ecx = tcpip_getsockopt (f->e.ebx, f->e.edx, f->e.ecx,
+                                   (void *)f->e.esi, (int *)f->e.edi);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x44:
+
+      /* __setsockopt */
+
+      f->e.ecx = tcpip_setsockopt (f->e.ebx, f->e.edx, f->e.ecx,
+                                   (const void *)f->e.esi, f->e.edi);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x45:
+
+      /* __getsockname */
+
+      f->e.ecx = tcpip_getsockname (f->e.ebx, (void *)f->e.edx,
+                                    (int *)f->e.ecx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x46:
+
+      /* __getpeername */
+
+      f->e.ecx = tcpip_getpeername (f->e.ebx, (void *)f->e.edx,
+                                    (int *)f->e.ecx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x47:
+
+      /* __gethostbyname */
+
+      f->e.ecx = tcpip_gethostbyname ((const char *)f->e.edx,
+                                      (void **)f->e.ebx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x48:
+
+      /* __gethostbyaddr */
+
+      f->e.ecx = tcpip_gethostbyaddr ((const char *)f->e.edx, f->e.ecx,
+                                      f->e.esi, (void **)f->e.ebx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x49:
+
+      /* __getservbyname */
+
+      f->e.eax = tcpip_getservbyname ((const char *)f->e.edx,
+                                      (const char *)f->e.ecx,
+                                      (void **)f->e.ebx);
+      f->e.ecx = 0;
+      break;
+
+    case 0x4a:
+
+      /* __getservbyport */
+
+      f->e.eax = tcpip_getservbyport (f->e.edx, (const char *)f->e.ecx,
+                                      (void **)f->e.ebx);
+      f->e.ecx = 0;
+      break;
+
+    case 0x4b:
+
+      /* __getprotobyname */
+
+      f->e.eax = tcpip_getprotobyname ((const char *)f->e.edx,
+                                       (void **)f->e.ebx);
+      f->e.ecx = 0;
+      break;
+
+    case 0x4c:
+
+      /* __getprotobynumber */
+
+      f->e.eax = tcpip_getprotobynumber (f->e.edx, (void **)f->e.ebx);
+      f->e.ecx = 0;
+      break;
+
+    case 0x4d:
+
+      /* __getnetbyname */
+
+      f->e.eax = tcpip_getnetbyname ((const char *)f->e.edx,
+                                     (void **)f->e.ebx);
+      f->e.ecx = 0;
+      break;
+
+    case 0x4e:
+
+      /* __getnetbyaddr */
+
+      f->e.eax = tcpip_getnetbyaddr (f->e.edx, (void **)f->e.ebx);
+      f->e.ecx = 0;
+      break;
+
+    case 0x4f:
+
+      /* __gethostname */
+
+      f->e.ecx = tcpip_gethostname ((char *)f->e.edx, f->e.ecx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x50:
+
+      /* __gethostid */
+
+      f->e.ecx = tcpip_gethostid ((int *)f->e.ebx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x51:
+
+      /* __shutdown */
+
+      f->e.ecx = tcpip_shutdown (f->e.ebx, f->e.edx);
+      f->e.eax = (ULONG)(f->e.ecx == 0 ? 0 : -1);
+      break;
+
+    case 0x52:
+
+      /* __recvfrom */
+
+      f->e.eax = tcpip_recvfrom ((const struct _recvfrom *)f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x53:
+
+      /* __sendto */
+
+      f->e.eax = tcpip_sendto ((const struct _sendto *)f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x54:
+
+      /* __impsockhandle */
+
+      f->e.eax = tcpip_impsockhandle (f->e.edx, f->e.ecx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x57:
+
+      /* __ttyname()
+
+         In:  EDX       File handle
+              EDI       Pointer to output buffer
+              ECX       Size of output buffer
+
+        Out:  EAX       0 (ok) or -1 (error)
+              ECX       errno (0 if successful)
+
+        Get name of device. */
+
+      f->e.eax = do_ttyname ((char *)f->e.edi, f->e.ecx, f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x58:
+
+      /* __settime()
+
+         In:  EDX       Pointer to struct timeval
+
+         Out: EAX       0 (ok) or -1 (error)
+              ECX       errno (0 if successful)
+
+         Set system time and time zone. */
+
+      f->e.eax = do_settime ((const struct timeval *)f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x59:
+
+      /* __profil()
+
+         In:  EDX       Pointer to struct _profil
+
+         Out: EAX       0 (ok) or -1 (error)
+              ECX       errno (0 if successful)
+
+         Sampling profiler. */
+
+      f->e.eax = do_profil ((const struct _profil *)f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x5a:
+
+      /* __nls_ctype()
+
+         In:  EDX       Pointer to buffer
+
+         Mark DBCS lead bytes. */
+
+      f->e.eax = do_ctype ((unsigned char *)f->e.edx, &err_no);
+      f->e.ecx = err_no;
+      break;
+
+    case 0x5b:
+
+      /* __setsyserrno()
+
+        In:   EDX       New error number
+        Out:  EAX       Old error number
+       
+        Return old OS/2 error number for last syscall. */
+
+      f->e.eax = do_setsyserrno (f->e.edx);
+      break;
+
+    default:
+      if (f->b.al > 0x39)
+        {
+          f->e.eax = (ULONG)(-1);
+          f->e.ecx = ENOSYS;
+        }
+      else
+        bad_spec (f);
+      break;
+    }
+}
+
+
+static void bad_spec (syscall_frame *f)
+{
+  oprintf ("Invalid syscall function code: 7f%.2x\r\n", (unsigned)f->b.al);
+  quit (255);
+}
+
+
+static ULONG do_syserrno (void)
+{
+  thread_data *td;
+
+  td = get_thread ();
+  if (td == NULL)
+    return (ULONG)-1;
+  return td->prev_sys_errno;
+}
+
+
+static ULONG do_setsyserrno (ULONG errcode)
+{
+  thread_data *td;
+
+  td = get_thread ();
+  if (td == NULL)
+    return (ULONG)-1;
+  td->last_sys_errno = errcode;
+  return td->prev_sys_errno;
+}
+
+/* Convert a string to upper case. */
+
+static void do_memupr (char *dst, ULONG size)
+{
+  COUNTRYCODE cc;
+
+  cc.country = 0;
+  cc.codepage = 0;
+  DosMapCase (size, &cc, dst);
+}
+
+
+/* Mark DBCS lead bytes. */
+
+static int do_ctype (unsigned char *dst, int *errnop)
+{
+  ULONG rc;
+  unsigned i;
+
+  rc = get_dbcs_lead ();
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  for (i = 0; i < 256; ++i)
+    if (_nls_is_dbcs_lead (i))
+      dst[i] |= _NLS_DBCS_LEAD;
+    else
+      dst[i] &= ~_NLS_DBCS_LEAD;
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Get the number of rows and columns of the screen. */
+
+static void do_scrsize (int *dst)
+{
+  static VIOMODEINFO vmi;       /* Must not cross a 64K boundary */
+
+  vmi.cb = sizeof (vmi);
+  VioGetMode (&vmi, 0);
+  dst[0] = vmi.col;
+  dst[1] = vmi.row;
+}
+
+
+static ULONG do_read_kbd (ULONG flags)
+{
+  UCHAR c;
+
+  if (kbd_input (&c, !(flags & 4), flags & 1, flags & 2, FALSE))
+    return c;
+  else
+    return (ULONG)-1;
+}
+
+
+static unsigned do_sleep (unsigned sec)
+{
+  if (sec == 0)
+    {
+      DosSleep (0);
+      return 0;
+    }
+  else
+    {
+      ULONG start, stop, elapsed;
+
+      /* TODO: Don't get interrupted by ignored signals (SIG_IGN). */
+
+      start = querysysinfo (QSV_TIME_LOW);
+      if (DosSleep (1000 * sec) == 0)
+        return 0;
+      stop = querysysinfo (QSV_TIME_LOW);
+      elapsed = stop - start;
+      if (sec < elapsed)
+        return 0;
+      return sec - elapsed;
+    }
+}
Index: trunk/src/emx/src/os2/tcpip.c
===================================================================
--- trunk/src/emx/src/os2/tcpip.c	(revision 18)
+++ trunk/src/emx/src/os2/tcpip.c	(revision 18)
@@ -0,0 +1,1608 @@
+/* tcpip.c -- TCP/IP
+   Copyright (c) 1994-2000 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+/* TODO:
+
+  - inheritance of socket handles
+  - add IBM TCP/IP for OS/2 layer (sock_errno() etc.) */
+
+#define INCL_DOSDEVIOCTL
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSMODULEMGR
+#define INCL_DOSPROCESS
+#define INCL_DOSSEMAPHORES
+#include <os2emx.h>
+#include <emx/syscalls.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/so_ioctl.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netdb.h>
+#include "emxdll.h"
+#include "files.h"
+#include "tcpip.h"
+#include "select.h"
+#include "clib.h"
+
+/* Error codes of IBM TCP/IP for OS/2 start at this number. */
+
+#define SOCK_ERRNO_BASE 10000
+
+/* This variable is zero while tcpip_init() has not been called.  A
+   positive value means that initialization of TCP/IP was successful,
+   a negative value means that initialization of TCP/IP failed. */
+
+static int tcpip_initialized;
+
+/* This variable holds the value returned by the most recent call to
+   sock_errno().  In the future, it will be used for providing a
+   sock_errno() system call. */
+
+static int last_sock_errno;
+
+/* Module handles of the two IBM TCP/IP for OS/2 DLLs. */
+
+static HMODULE hmod_so32dll;
+static HMODULE hmod_tcp32dll;
+
+/* List of file handles created by sock_init().  This is used for
+   fork(). */
+
+static ULONG sock_init_count;
+static ULONG sock_init_array[MAXFH_SOCK_INIT];
+
+struct sockaddr;
+
+/* Pointers to entrypoints of the IBM TCP/IP for OS/2 DLLs. */
+
+static int (*tip_accept)(int, struct sockaddr *, int *);
+static void (*tip_addsockettolist)(int);
+static int (*tip_bind)(int, struct sockaddr *, int);
+static int (*tip_connect)(int, struct sockaddr *, int);
+static void * (*tip_gethostbyaddr) (const char *, int, int);
+static void * (*tip_gethostbyname) (const char *);
+static int (*tip_gethostid) (void);
+static int (*tip_gethostname) (char *, int len);
+static void * (*tip_getnetbyaddr) (long);
+static void * (*tip_getnetbyname) (const char *);
+static int (*tip_getpeername) (int, void *, int *);
+static void * (*tip_getprotobyname) (const char *);
+static void * (*tip_getprotobynumber) (int);
+static void * (*tip_getservbyname) (const char *, const char *);
+static void * (*tip_getservbyport) (int, const char *);
+static int (*tip_getsockname) (int, void *, int *);
+static int (*tip_getsockopt) (int, int, int, void *, int *);
+static int (*tip_ioctl)(int, int, void *, int);
+static int (*tip_listen)(int, int);
+static int (*tip_removesocketfromlist)(int);
+static int (*tip_recv)(int, void *, int, int);
+static int (*tip_recvfrom)(int, void *, int, int, struct sockaddr *, int *);
+static int (*tip_select)(int *, int, int, int, long);
+static int (*tip_send)(int, const void *, int, int);
+static int (*tip_sendto)(int, const void *, int, int, const struct sockaddr *,
+    int);
+static int (*tip_setsockopt) (int, int, int, const void *, int);
+static int (*tip_shutdown) (int, int);
+static int (*tip_socket) (int domain, int type, int protocol);
+static int (*tip_sock_errno)(void);
+static int (*tip_sock_init)(void);
+static int (*tip_soclose)(int handle);
+static int *tip_h_errno;
+
+/* These macros are used for getting the addresses of DLL entrypoints. */
+
+#define LOAD(hmod,name,var) (DosQueryProcAddr (hmod, 0, name, (PPFN)var) != 0)
+#define LOAD_SO(name,var)   LOAD (hmod_so32dll, name, var)
+#define LOAD_TCP(name,var)  LOAD (hmod_tcp32dll, name, var)
+
+
+/* Close a socket for this process (the per-process reference count
+   has become zero).  Adjust the global reference count and close the
+   socket if the number of processes using that socket gets zero. */
+
+static int tcpip_close_process (int s)
+{
+  int flag;
+
+  LOCK_COMMON;
+  flag = (sock_proc_count[s] > 0 && --sock_proc_count[s] == 0);
+  UNLOCK_COMMON;
+
+  if (flag)
+    {
+      int rc = tip_soclose (s);
+      if (rc != 0 && (debug_flags & DEBUG_SOCLOSE)
+          && tip_sock_errno () == SOCK_ERRNO_BASE + 38) /* ENOTSOCK */
+        rc = 0;             /* Don't mind socket closed behind our back */
+      return rc;
+    }
+  else
+    {
+      /* Call removesocketfromlist() to prevent SO32DLL.DLL's exit
+         list procedure from closing the socket -- it's still in use
+         by another process which inherited or imported the socket
+         handle. */
+
+      tip_removesocketfromlist (s);
+      return 0;
+    }
+}
+
+
+/* This function is called by the exit list procedure (and by
+   term_tcpip(), which is in turn called by the DLL termination
+   function).  It closes all open sockets.  Calling exit_tcpip() more
+   than once is harmless. */
+
+void exit_tcpip (void)
+{
+  ULONG i;
+
+  if (tcpip_initialized > 0)
+    for (i = 0; i < handle_count; ++i)
+      if ((files[i].flags & (HF_OPEN | HF_SOCKET)) == (HF_OPEN | HF_SOCKET)
+          && files[i].ref_count != 0)
+        {
+          files[i].flags = 0;
+          files[i].ref_count = 0;
+          tcpip_close_process (files[i].x.socket.handle);
+        }
+}
+
+
+void term_tcpip (void)
+{
+  /* Close all sockets in case the exit list procedure has not been
+     called.  This happens if DosFreeModule is used.  Calling
+     exit_tcpip() more than once is benign. */
+
+  exit_tcpip ();
+
+  /* Unload the TCP/IP DLLs. */
+
+  if (tcpip_initialized > 0)
+    {
+      tcpip_initialized = 0;
+      DosFreeModule (hmod_so32dll);
+      DosFreeModule (hmod_tcp32dll);
+    }
+}
+
+
+/* See tcpip_init() for details.  This function is called by
+   tcpip_init() and tcp_init_fork().  See those functions for
+   additional actions to be taken. */
+
+static int tcpip_init2 (void)
+{
+  /* Load the two IBM TCP/IP for SO/2 DLLs. */
+
+  if (load_module ("SO32DLL", &hmod_so32dll) != 0)
+    {
+      tcpip_initialized = -1;
+      return FALSE;
+    }
+  if (load_module ("TCP32DLL", &hmod_tcp32dll) != 0)
+    {
+      DosFreeModule (hmod_so32dll);
+      tcpip_initialized = -1;
+      return FALSE;
+    }
+
+  /* Initialize the pointers to the DLL entrypoints and call
+     sock_init(). */
+
+  if (LOAD_SO ("SOCK_INIT", &tip_sock_init)
+      || LOAD_SO ("SOCK_ERRNO", &tip_sock_errno)
+      || LOAD_SO ("ACCEPT", &tip_accept)
+      || LOAD_SO ("ADDSOCKETTOLIST", &tip_addsockettolist)
+      || LOAD_SO ("BIND", &tip_bind)
+      || LOAD_SO ("CONNECT", &tip_connect)
+      || LOAD_SO ("GETHOSTID", &tip_gethostid)
+      || LOAD_SO ("GETPEERNAME", &tip_getpeername)
+      || LOAD_SO ("GETSOCKNAME", &tip_getsockname)
+      || LOAD_SO ("GETSOCKOPT", &tip_getsockopt)
+      || LOAD_SO ("IOCTL", &tip_ioctl)
+      || LOAD_SO ("LISTEN", &tip_listen)
+      || LOAD_SO ("REMOVESOCKETFROMLIST", &tip_removesocketfromlist)
+      || LOAD_SO ("RECV", &tip_recv)
+      || LOAD_SO ("RECVFROM", &tip_recvfrom)
+      || LOAD_SO ("SELECT", &tip_select)
+      || LOAD_SO ("SEND", &tip_send)
+      || LOAD_SO ("SENDTO", &tip_sendto)
+      || LOAD_SO ("SETSOCKOPT", &tip_setsockopt)
+      || LOAD_SO ("SHUTDOWN", &tip_shutdown)
+      || LOAD_SO ("SOCKET", &tip_socket)
+      || LOAD_SO ("SOCLOSE", &tip_soclose)
+      || LOAD_TCP ("GETHOSTBYADDR", &tip_gethostbyaddr)
+      || LOAD_TCP ("GETHOSTBYNAME", &tip_gethostbyname)
+      || LOAD_TCP ("GETHOSTNAME", &tip_gethostname)
+      || LOAD_TCP ("GETNETBYADDR", &tip_getnetbyaddr)
+      || LOAD_TCP ("GETNETBYNAME", &tip_getnetbyname)
+      || LOAD_TCP ("GETPROTOBYNAME", &tip_getprotobyname)
+      || LOAD_TCP ("GETPROTOBYNUMBER", &tip_getprotobynumber)
+      || LOAD_TCP ("GETSERVBYNAME", &tip_getservbyname)
+      || LOAD_TCP ("GETSERVBYPORT", &tip_getservbyport)
+      || LOAD_TCP ("H_ERRNO", &tip_h_errno)
+      || tip_sock_init () != 0)
+    {
+      DosFreeModule (hmod_so32dll);
+      DosFreeModule (hmod_tcp32dll);
+      tcpip_initialized = -1;
+      return FALSE;
+    }
+
+  /* Success! */
+
+  tcpip_initialized = 1;
+  return TRUE;
+}
+
+
+/* Initialize TCP/IP.  Return FALSE on failure, return TRUE on
+   success.  This function must be called before using any of the
+   above `tip_*' pointers.  Functions which check HF_SOCKET don't have
+   to call tcpip_init() as the HF_SOCKET bit can only be set by a
+   function which calls tcpip_init(). */
+
+static int tcpip_init (void)
+{
+  int result;
+  ULONG count;
+
+  /* If tcpip_init() has already been called, use the result of the
+     first call. */
+
+  if (tcpip_initialized < 0)
+    return FALSE;
+  if (tcpip_initialized > 0)
+    return TRUE;
+
+  /* Ensure that only one thread can enter tcpip_init2().  We can use
+     the `files_access' semaphore for this.
+
+     We should suspend all other threads to prevent them from opening
+     or closing handles while we look for unused handles.
+     Unfortunately, that cannot be done without risking a deadlock.
+     As fork() works with single-thread processes only anyway, we
+     ignore the problem of other threads opening or closing
+     handles. */
+
+  DosEnterMustComplete (&count);
+  LOCK_FILES;
+
+  /* Check tcpip_initialized, in case another thread blocked us in the
+     previous statement. */
+
+  if (tcpip_initialized < 0)
+    result = FALSE;
+  else if (tcpip_initialized > 0)
+    result = TRUE;
+  else
+    {
+      /* Call tcpip_init2(), recording the file handles used by
+         sock_init() for fork(). */
+
+      sock_init_count = find_unused_handles (sock_init_array, MAXFH_SOCK_INIT);
+      result = tcpip_init2 ();
+
+      /* Adjust sock_init_count in case sock_init() creates less than
+         MAXFH_SOCK_INIT handles. */
+
+      if (result)
+        {
+          ULONG temp;
+
+          if (find_unused_handles (&temp, 1) == 1)
+            while (sock_init_count > 0
+                   && sock_init_array[sock_init_count-1] >= temp)
+              --sock_init_count;
+        }
+      else
+        sock_init_count = 0;
+    }
+
+  UNLOCK_FILES;
+  DosExitMustComplete (&count);
+  return result;
+}
+
+
+/* Initialize TCP/IP in a forked process that inherits socket handles
+   from its parent.  As we have only one thread now, we don't have to
+   lock out other threads. */
+
+int tcpip_init_fork (const struct fork_data_done *p)
+{
+#define MAX_FILL 128
+  ULONG unused[MAX_FILL];
+  int i, j, n, fill_count, result;
+
+  /* Copy sock_init_array from the parent process in case this process
+     forks. */
+
+  sock_init_count = p->sock_init_count;
+  memcpy (sock_init_array, p->sock_init_array, sizeof (sock_init_array));
+
+  /* Fill unused handle slots to make sock_init() use the same handles
+     as in the parent process.  Temporarily set `handle_count' as it
+     has not yet been initialized and is used by
+     find_unused_handles(). */
+
+  n = MAX_FILL;
+  if (sock_init_count > 0 && sock_init_array[sock_init_count-1] + 1 < n)
+    n = sock_init_array[sock_init_count-1] + 1;
+  handle_count = n;
+  n = find_unused_handles (unused, n);
+  handle_count = 0;
+
+  i = j = 0; fill_count = 0;
+  while (i < n && j < sock_init_count)
+    if (unused[i] == sock_init_array[j])
+      {
+        /* The slot is unused in this process and in its parent
+           process.  It will be used by sock_init(). */
+
+        ++i; ++j;
+      }
+    else if (unused[i] < sock_init_array[j])
+      {
+        ULONG handle, action;
+
+        /* The file handle is unused in this process, but is used in
+           the parent process.  Fill it.  We could use DosDupHandle if
+           we knew an open file handle.  However, if we inherited
+           socket handles only, there is no such handle. */
+
+        if (DosOpen ("nul", &handle, &action, 0, 0,
+                     OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+                     (OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE
+                      | OPEN_FLAGS_NOINHERIT), NULL) != 0
+            || handle != unused[i])
+          return FALSE;
+
+        /* Remember the file handle, to be able to close it later.  We
+           reuse elements of unused[] which have already been
+           processed. */
+
+        unused[fill_count++] = unused[i];
+        ++i;
+      }
+    else
+      {
+        /* A file handle used by this process is unused in the parent
+           process.  This should not happen and cannot be handled. */
+
+        return FALSE;
+      }
+
+  /* Now initialize TCP/IP.  This calls sock_init(). */
+
+  result = tcpip_init2 ();
+
+  /* Close stuffed file handles. */
+
+  for (i = 0; i < fill_count; ++i)
+    DosClose (unused[i]);
+
+  return result;
+}
+
+
+/* Initialize file tables for inherited socket handles. */
+
+void copy_fork_sock (const struct fork_data_done *p)
+{
+  ULONG i, fd, s;
+
+  for (i = 0; i < p->sock_count; ++i)
+    {
+      fd = p->sock_array[i].f;
+      s = p->sock_array[i].s;
+      close_handle (fd);        /* Clear reference count */
+      alloc_file_description (fd);
+      if (IS_VALID_FILE (fd))
+        {
+          int j = 0;
+          set_handle_flags (fd, HF_OPEN | HF_SOCKET);
+          GET_FILE (fd)->x.socket.handle = s;
+          GET_FILE (fd)->x.socket.fd_flags = 0;
+          while (j < i && p->sock_array[j].s != s)
+            ++j;
+          if (j == i)
+            tip_addsockettolist (s); /* Inform SO32DLL.DLL */
+        }
+      else
+        tcpip_close_process (s);
+    }
+}
+
+
+/* Tell the child process about sockets: Build a list of sockets to be
+   inherited.
+
+   TODO: Closing a socket in another thread while fork() is in
+   progress might result in a socket handle leak.
+
+   FORK_OBJ_SIZE is big enough for MAX_SOCKETS sockets being passed
+   down to the child process. */
+
+void tcpip_fork_sock (struct fork_data_done *p)
+{
+  ULONG i;
+  my_file *f;
+
+  p->sock_init_count = sock_init_count;
+  memcpy (p->sock_init_array, sock_init_array, sizeof (p->sock_init_array));
+  p->sock_count = 0;
+  p->sock_array = (struct fork_sock *)((char *)p + p->size);
+  for (i = 0; i < handle_count; ++i)
+    if (IS_SOCKET (i) && IS_VALID_FILE (i)
+        && p->size + sizeof (struct fork_sock) <= FORK_OBJ_SIZE)
+      {
+        f = GET_FILE (i);
+        p->sock_array[p->sock_count].f = i;
+        p->sock_array[p->sock_count].s = f->x.socket.handle;
+        ++p->sock_count; p->size += sizeof (struct fork_sock);
+        LOCK_COMMON;
+        ++sock_proc_count[f->x.socket.handle];
+        UNLOCK_COMMON;
+      }
+}
+
+
+/* Forking a process failed.  Adjust socket reference counts. */
+
+void tcpip_undo_fork_sock (const struct fork_data_done *p)
+{
+  ULONG i;
+
+  LOCK_COMMON;
+  for (i = 0; i < p->sock_count; ++i)
+    --sock_proc_count[p->sock_array[i].s];
+  UNLOCK_COMMON;
+}
+
+
+/* Use UNDEF for error codes which are supposed to not being
+   returned by IBM TCP/IP for OS/2. */
+
+#define UNDEF   EINVAL
+
+/* This table maps error codes of IBM TCP/IP for OS/2 (offset by
+   SOCK_ERRNO_BASE) to emx errno numbers.  */
+
+static unsigned char const sock_errno_tab[] =
+{
+  UNDEF,                        /* +0 */
+  EPERM,                        /* +1 */
+  UNDEF,                        /* +2 */
+  ESRCH,                        /* +3 */
+  EINTR,                        /* +4 */
+  UNDEF,                        /* +5 */
+  ENXIO,                        /* +6 */
+  UNDEF,                        /* +7 */
+  UNDEF,                        /* +8 */
+  EBADF,                        /* +9 */
+  UNDEF,                        /* +10 */
+  UNDEF,                        /* +11 */
+  UNDEF,                        /* +12 */
+  EACCES,                       /* +13 */
+  EFAULT,                       /* +14 */
+  UNDEF,                        /* +15 */
+  UNDEF,                        /* +16 */
+  UNDEF,                        /* +17 */
+  UNDEF,                        /* +18 */
+  UNDEF,                        /* +19 */
+  UNDEF,                        /* +20 */
+  UNDEF,                        /* +21 */
+  EINVAL,                       /* +22 */
+  UNDEF,                        /* +23 */
+  EMFILE,                       /* +24 */
+  UNDEF,                        /* +25 */
+  UNDEF,                        /* +26 */
+  UNDEF,                        /* +27 */
+  UNDEF,                        /* +28 */
+  UNDEF,                        /* +29 */
+  UNDEF,                        /* +30 */
+  UNDEF,                        /* +31 */
+  EPIPE,                        /* +32 */
+  UNDEF,                        /* +33 */
+  UNDEF,                        /* +34 */
+  EWOULDBLOCK,                  /* +35 */
+  EINPROGRESS,                  /* +36 */
+  EALREADY,                     /* +37 */
+  ENOTSOCK,                     /* +38 */
+  EDESTADDRREQ,                 /* +39 */
+  EMSGSIZE,                     /* +40 */
+  EPROTOTYPE,                   /* +41 */
+  ENOPROTOOPT,                  /* +42 */
+  EPROTONOSUPPORT,              /* +43 */
+  ESOCKTNOSUPPORT,              /* +44 */
+  EOPNOTSUPP,                   /* +45 */
+  EPFNOSUPPORT,                 /* +46 */
+  EAFNOSUPPORT,                 /* +47 */
+  EADDRINUSE,                   /* +48 */
+  EADDRNOTAVAIL,                /* +49 */
+  ENETDOWN,                     /* +50 */
+  ENETUNREACH,                  /* +51 */
+  ENETRESET,                    /* +52 */
+  ECONNABORTED,                 /* +53 */
+  ECONNRESET,                   /* +54 */
+  ENOBUFS,                      /* +55 */
+  EISCONN,                      /* +56 */
+  ENOTCONN,                     /* +57 */
+  ESHUTDOWN,                    /* +58 */
+  ETOOMANYREFS,                 /* +59 */
+  ETIMEDOUT,                    /* +60 */
+  ECONNREFUSED,                 /* +61 */
+  ELOOP,                        /* +62 */
+  ENAMETOOLONG,                 /* +63 */
+  EHOSTDOWN,                    /* +64 */
+  EHOSTUNREACH,                 /* +65 */
+  ENOTEMPTY,                    /* +66 */
+  UNDEF,                        /* +67 */
+  UNDEF,                        /* +68 */
+  UNDEF,                        /* +69 */
+  UNDEF,                        /* +70 */
+  UNDEF,                        /* +71 */
+  UNDEF,                        /* +72 */
+  UNDEF,                        /* +73 */
+  UNDEF,                        /* +74 */
+  UNDEF,                        /* +75 */
+  UNDEF,                        /* +76 */
+  UNDEF,                        /* +77 */
+  UNDEF,                        /* +78 */
+  UNDEF,                        /* +79 */
+  UNDEF,                        /* +80 */
+  UNDEF,                        /* +81 */
+  UNDEF,                        /* +82 */
+  UNDEF,                        /* +83 */
+  UNDEF,                        /* +84 */
+  UNDEF,                        /* +85 */
+  UNDEF,                        /* +86 */
+  UNDEF,                        /* +87 */
+  UNDEF,                        /* +88 */
+  UNDEF,                        /* +89 */
+  UNDEF,                        /* +90 */
+  UNDEF,                        /* +91 */
+  UNDEF,                        /* +92 */
+  UNDEF,                        /* +93 */
+  UNDEF,                        /* +94 */
+  UNDEF,                        /* +95 */
+  UNDEF,                        /* +96 */
+  UNDEF,                        /* +97 */
+  UNDEF,                        /* +98 */
+  UNDEF,                        /* +99 */
+  EIO                           /* +100: SOCEOS2ERR */
+};
+
+
+/* Obtain, translate, and return the error code of the most recent
+   TCP/IP call. */
+
+static int tcpip_errno (void)
+{
+  int e;
+
+  e = tip_sock_errno ();
+  last_sock_errno = e;
+  if (e < SOCK_ERRNO_BASE || e >= SOCK_ERRNO_BASE + sizeof (sock_errno_tab))
+    return EINVAL;
+  return sock_errno_tab[e - SOCK_ERRNO_BASE];
+}
+
+
+/* Fake a low-level file I/O handle for a socket.  Instead of (or in
+   addition to) relocating OS/2 file handles, we might open the "NUL"
+   device to fill the slot used for the faked handle. */
+
+static int tcpip_new_handle (int s, int *errnop)
+{
+  int i;
+
+  /* Check index for sock_proc_count[]. */
+
+  if (s < 0 || s >= MAX_SOCKETS)
+    {
+      tip_soclose (s);
+      *errnop = EMFILE;
+      return -1;
+    }
+
+  /* We might want to prefer handles with high numbers to minimize
+     relocation of file handles; however, we don't know the value of
+     the application's `_nfiles' variable (and nowadays there's no
+     longer a limit). */
+
+  LOCK_FILES;
+  for (i = 0; i < handle_count; ++i)
+    if (!(handle_flags[i] & HF_OPEN))
+      {
+        alloc_file_description (i);
+        if (!IS_VALID_FILE (i))
+          break;
+        set_handle_flags (i, HF_OPEN | HF_SOCKET);
+        GET_FILE (i)->x.socket.handle = s;
+        GET_FILE (i)->x.socket.fd_flags = 0;
+
+        /* Note: By incrementing sock_proc_count[s] after adding the
+           socket to our table of file descriptors, the socket might
+           be closed twice if the process terminates between those two
+           actions.  That's preferable to not closing the socket.  (It
+           can hurt only if another process uses the same socket
+           handle at the same time, which is quite unlikely as IBM
+           TCP/IP reuses socket handles not before about `2048 new
+           sockets later'.)
+
+           As the socket handle is not yet visible to the application
+           program, LOCK_COMMON and UNLOCK_COMMON are not required. */
+
+        sock_proc_count[s] += 1;
+        UNLOCK_FILES;
+        *errnop = 0;
+        return i;
+      }
+  UNLOCK_FILES;
+  tip_soclose (s);
+  *errnop = EMFILE;
+  return -1;
+}
+
+
+/* __socket() */
+
+int tcpip_socket (int domain, int type, int protocol, int *errnop)
+{
+  int s;
+
+  if (!tcpip_init ())
+    {
+      *errnop = ENETDOWN;       /* TODO: last_sock_errno */
+      return -1;
+    }
+
+  s = tip_socket (domain, type, protocol);
+  if (s == -1)
+    {
+      *errnop = tcpip_errno ();
+      return -1;
+    }
+
+  return tcpip_new_handle (s, errnop);
+}
+
+
+/* __getsockhandle() */
+
+int tcpip_getsockhandle (ULONG handle, int *errnop)
+{
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    {
+      *errnop = EBADF;
+      return -1;
+    }
+  *errnop = 0;
+  return GET_FILE (handle)->x.socket.handle;
+}
+
+
+/* __accept() */
+
+int tcpip_accept (ULONG handle, void *addr, int *paddrlen, int *errnop)
+{
+  int s;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    {
+      *errnop = EBADF;          /* TODO: last_sock_errno */
+      return -1;
+    }
+
+  s = tip_accept (GET_FILE (handle)->x.socket.handle, addr, paddrlen);
+  if (s == -1)
+    {
+      *errnop = tcpip_errno ();
+      return -1;
+    }
+
+  return tcpip_new_handle (s, errnop);
+}
+
+
+/* __bind() */
+
+int tcpip_bind (ULONG handle, void *addr, int addrlen)
+{
+  int rc;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    return EBADF;               /* TODO: last_sock_errno */
+
+  rc = tip_bind (GET_FILE (handle)->x.socket.handle, addr, addrlen);
+  if (rc != 0)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __connect() */
+
+int tcpip_connect (ULONG handle, void *addr, int addrlen)
+{
+  int rc;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    return EBADF;               /* TODO: last_sock_errno */
+
+  rc = tip_connect (GET_FILE (handle)->x.socket.handle, addr, addrlen);
+  if (rc != 0)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __listen() */
+
+int tcpip_listen (ULONG handle, int backlog)
+{
+  int rc;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    return EBADF;               /* TODO: last_sock_errno */
+
+  rc = tip_listen (GET_FILE (handle)->x.socket.handle, backlog);
+  if (rc != 0)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __recv() */
+
+int tcpip_recv (ULONG handle, void *buf, int len, unsigned flags, int *errnop)
+{
+  int r;
+
+  if (!IS_SOCKET (handle))
+    {
+      ULONG rc, nread;
+      rc = DosRead (handle, buf, (ULONG)len, &nread);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      *errnop = 0;
+      return (int)nread;
+    }
+
+  if (!IS_VALID_FILE (handle))
+    {
+      *errnop = EBADF;          /* TODO: last_sock_errno */
+      return -1;
+    }
+
+  if (len > 0x7fff) len = 0x7ffc;
+  r = tip_recv (GET_FILE (handle)->x.socket.handle, buf, len, flags);
+  if (r == -1)
+    {
+      *errnop = tcpip_errno ();
+      return -1;
+    }
+  *errnop = 0;
+  last_sock_errno = 0;
+  return r;
+}
+
+
+/* __recvfrom() */
+
+int tcpip_recvfrom (const struct _recvfrom *args, int *errnop)
+{
+  ULONG handle;
+  int r, len;
+
+  handle = args->handle;
+  if (!IS_SOCKET (handle))
+    {
+      ULONG rc, nread;
+      rc = DosRead (handle, args->buf, (ULONG)args->len, &nread);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      *errnop = 0;
+      return (int)nread;
+    }
+
+  if (!IS_VALID_FILE (handle))
+    {
+      *errnop = EBADF;          /* TODO: last_sock_errno */
+      return -1;
+    }
+
+  len = args->len;
+  if (len > 0x7fff) len = 0x7ffc;
+  r = tip_recvfrom (GET_FILE (handle)->x.socket.handle, args->buf, len,
+                    args->flags, args->from, args->pfromlen);
+  if (r == -1)
+    {
+      *errnop = tcpip_errno ();
+      return -1;
+    }
+  *errnop = 0;
+  last_sock_errno = 0;
+  return r;
+}
+
+
+/* __send() */
+
+int tcpip_send (ULONG handle, const void *buf, int len, unsigned flags,
+                int *errnop)
+{
+  int r, n, result, e;
+  const char *p;
+
+  if (!IS_SOCKET (handle))
+    {
+      ULONG rc, nwritten;
+      rc = DosWrite (handle, buf, (ULONG)len, &nwritten);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      *errnop = 0;
+      return (int)nwritten;
+    }
+
+  if (!IS_VALID_FILE (handle))
+    {
+      *errnop = EBADF;          /* TODO: last_sock_errno */
+      return -1;
+    }
+
+  /* TODO: Return EMSGSIZE if appropriate. */
+
+  p = buf; result = 0;
+  while (len > 0)
+    {
+      n = (len > 0x7fff ? 0x7ffc : len);
+      r = tip_send (GET_FILE (handle)->x.socket.handle, p, n, flags);
+      if (r == -1)
+        {
+          e = tcpip_errno ();
+          if (e == EWOULDBLOCK && result != 0)
+            break;
+          *errnop = e;
+          return -1;
+        }
+      result += r;
+      if (r != n) break;
+      p += r; len -= r;
+    }
+
+  *errnop = 0;
+  last_sock_errno = 0;
+  return result;
+}
+
+
+/* __sendto() */
+
+int tcpip_sendto (const struct _sendto *args, int *errnop)
+{
+  ULONG handle;
+  int r, len, n, result, e;
+  const char *p;
+
+  handle = args->handle;
+  if (!IS_SOCKET (handle))
+    {
+      ULONG rc, nwritten;
+      rc = DosWrite (handle, args->buf, (ULONG)args->len, &nwritten);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      *errnop = 0;
+      return (int)nwritten;
+    }
+
+  if (!IS_VALID_FILE (handle))
+    {
+      *errnop = EBADF;          /* TODO: last_sock_errno */
+      return -1;
+    }
+
+  /* TODO: Return EMSGSIZE if appropriate. */
+
+  p = args->buf; result = 0; len = args->len;
+  while (len > 0)
+    {
+      n = (len > 0x7fff ? 0x7ffc : len);
+      r = tip_sendto (GET_FILE (handle)->x.socket.handle, p, n, args->flags,
+                      args->to, args->tolen);
+      if (r == -1)
+        {
+          e = tcpip_errno ();
+          if (e == EWOULDBLOCK && result != 0)
+            break;
+          *errnop = e;
+          return -1;
+        }
+      result += r;
+      if (r != n) break;
+      p += r; len -= r;
+    }
+
+  *errnop = 0;
+  last_sock_errno = 0;
+  return result;
+}
+
+
+/* __close() for a socket handle.  First adjust the local reference
+   count.  If it becomes zero, call tcpip_close_process() to adjust
+   the global reference count and to close the socket if it becomes
+   zero. */
+
+int tcpip_close (ULONG handle)
+{
+  if (!IS_VALID_FILE (handle))
+    return EBADF;
+  if (GET_FILE (handle)->ref_count == 1)
+    {
+      if (tcpip_close_process (GET_FILE (handle)->x.socket.handle) != 0)
+        return tcpip_errno ();
+    }
+  close_handle (handle);
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __dup() for a socket handle.  The target handle has already been
+   closed unless both HANDLE and TARGET are equal. */
+
+int tcpip_dup (ULONG handle, ULONG target, int *errnop)
+{
+  int i;
+
+  if (!IS_VALID_FILE (handle))
+    {
+      *errnop = EBADF;
+      return -1;
+    }
+  if (target == (ULONG)(-1))
+    {
+      LOCK_FILES;
+      for (i = 0; i < handle_count; ++i)
+        if (!(handle_flags[i] & HF_OPEN))
+          {
+            handle_flags[i] = handle_flags[handle];
+            handle_file[i] = handle_file[handle];
+            GET_FILE(handle)->ref_count += 1;
+            UNLOCK_FILES;
+            *errnop = 0;
+            return i;
+          }
+      UNLOCK_FILES;
+      *errnop = EMFILE;
+      return -1;
+    }
+  else if (handle == target)
+    {
+      *errnop = 0;
+      return target;
+    }
+  else if (target >= handle_count)
+    {
+      *errnop = EBADF;
+      return -1;
+    }
+  else
+    {
+      do_close (target);
+      handle_flags[target] = handle_flags[handle];
+      handle_file[target] = handle_file[handle];
+      GET_FILE(handle)->ref_count += 1;
+      *errnop = 0;
+      return target;
+    }
+}
+
+
+/* __read() for a socket handle. */
+
+int tcpip_read (ULONG handle, void *buf, ULONG len, int *errnop)
+{
+  int rc;
+
+  if (len > 0x7fff) len = 0x7ffc;
+  rc = tip_recv (GET_FILE (handle)->x.socket.handle, buf, len, 0);
+  if (rc == -1)
+    {
+      *errnop = tcpip_errno ();
+      return -1;
+    }
+  *errnop = 0;
+  last_sock_errno = 0;
+  return rc;
+}
+
+
+/* __write() for a socket handle. */
+
+int tcpip_write (ULONG handle, const void *buf, ULONG len, int *errnop)
+{
+  int rc, n, result, e;
+  const char *p;
+
+  p = buf; result = 0;
+  while (len > 0)
+    {
+      n = (len > 0x7fff ? 0x7ffc : len);
+      rc = tip_send (GET_FILE (handle)->x.socket.handle, p, n, 0);
+      if (rc == -1)
+        {
+          e = tcpip_errno ();
+          if (e == EWOULDBLOCK && result != 0)
+            break;
+          *errnop = e;
+          return -1;
+        }
+      result += rc;
+      if (rc != n) break;
+      p += rc; len -= rc;
+    }
+  *errnop = 0;
+  last_sock_errno = 0;
+  return result;
+}
+
+
+/* __fstat() for a socket handle. */
+
+int tcpip_fstat (ULONG handle, struct stat *dst, int *errnop)
+{
+  memset (dst, 0, sizeof (struct stat));
+  dst->st_mode = MAKEPERM (S_IREAD|S_IWRITE);
+  dst->st_mode |= S_IFSOCK;
+  dst->st_size = 0;
+  dst->st_dev = 0;
+  dst->st_uid = 0;              /* root */
+  dst->st_gid = 0;              /* root */
+  dst->st_ino = ino_number;
+  if (++ino_number == 0)
+   ino_number = 1;
+  dst->st_rdev = dst->st_dev;
+  dst->st_nlink = 1;
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Call ioctl() of IBM TCP/IP for OS/2. */
+
+static int map_ioctl (ULONG handle, ULONG request, ULONG arg, ULONG datalen,
+                      int *errnop)
+{
+  int rc;
+
+  rc = tip_ioctl (GET_FILE (handle)->x.socket.handle, request,
+                  (void *)arg, datalen);
+  if (rc == -1)
+    {
+      *errnop = tcpip_errno ();
+      return -1;
+    }
+  *errnop = 0;
+  return rc;
+}
+
+
+/* __ioctl() for a socket handle. */
+
+int tcpip_ioctl (ULONG handle, ULONG request, ULONG arg, int *errnop)
+{
+  int rc;
+
+  if (!IS_VALID_FILE (handle))
+    {
+      *errnop = EBADF;
+      return -1;
+    }
+
+  switch (request)
+    {
+    case TCGETA:
+    case TCSETA:
+    case TCSETAF:
+    case TCSETAW:
+    case TCFLSH:
+    case TCSBRK:
+    case TCXONC:
+    case _TCGA:
+    case _TCSANOW:
+    case _TCSADRAIN:
+    case _TCSAFLUSH:
+
+      /* These requests are not yet implemented. */
+
+      *errnop = EINVAL;
+      return -1;
+
+    case FGETHTYPE:
+
+      *(int *)arg = HT_SOCKET;
+      *errnop = 0;
+      return 0;
+
+    case FIONREAD:
+
+      return map_ioctl (handle, _TCPIP_FIONREAD, arg, sizeof (int), errnop);
+
+    case FIOASYNC:
+    case SIOCATMARK:
+
+      return map_ioctl (handle, request, arg, sizeof (int), errnop);
+
+    case SIOCADDRT:
+    case SIOCDELRT:
+
+      return map_ioctl (handle, request, arg, sizeof (struct rtentry), errnop);
+
+    case SIOCDARP:
+    case SIOCGARP:
+    case SIOCSARP:
+
+      return map_ioctl (handle, request, arg, sizeof (struct arpreq), errnop);
+
+    case SIOCGIFADDR:
+    case SIOCGIFBRDADDR:
+    case SIOCGIFDSTADDR:
+    case SIOCGIFFLAGS:
+    case SIOCGIFMETRIC:
+    case SIOCGIFNETMASK:
+    case SIOCSIFADDR:
+    case SIOCSIFBRDADDR:
+    case SIOCSIFDSTADDR:
+    case SIOCSIFFLAGS:
+    case SIOCSIFMETRIC:
+    case SIOCSIFNETMASK:
+
+      return map_ioctl (handle, request, arg, sizeof (struct ifreq), errnop);
+
+    case SIOCGIFCONF:
+
+      return map_ioctl (handle, request, arg, sizeof (struct ifconf), errnop);
+
+    case FIONBIO:
+      rc = map_ioctl (handle, request, arg, sizeof (int), errnop);
+      if (rc == 0)
+        {
+          if (*(int *)arg)
+            handle_flags[handle] |= HF_NDELAY;
+          else
+            handle_flags[handle] &= ~HF_NDELAY;
+        }
+      return rc;
+
+    default:
+      *errnop = EINVAL;
+      return -1;
+    }
+}
+
+
+/* __fcntl() for a socket handle.  This function is called for F_SETFL
+   only, and only if O_NDELAY was changed. */
+
+int tcpip_fcntl (ULONG handle, ULONG request, ULONG arg, int *errnop)
+{
+  int on;
+
+  on = arg & O_NDELAY;
+  return tcpip_ioctl (handle, FIONBIO, (ULONG)&on, errnop);
+}
+
+
+/* __getsockopt() */
+
+int tcpip_getsockopt (ULONG handle, int level, int optname, void *optval,
+                      int *poptlen)
+{
+  int rc;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    return ENOTSOCK;            /* TODO: last_sock_errno */
+
+  rc = tip_getsockopt (GET_FILE (handle)->x.socket.handle, level, optname,
+                       optval, poptlen);
+  if (rc == -1)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __setsockopt() */
+
+int tcpip_setsockopt (ULONG handle, int level, int optname, const void *optval,
+                      int optlen)
+{
+  int rc;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    return ENOTSOCK;            /* TODO: last_sock_errno */
+
+  rc = tip_setsockopt (GET_FILE (handle)->x.socket.handle, level, optname,
+                       optval, optlen);
+  if (rc == -1)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __getsockname() */
+
+int tcpip_getsockname (ULONG handle, void *addr, int *paddrlen)
+{
+  int rc;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    return ENOTSOCK;            /* TODO: last_sock_errno */
+
+  rc = tip_getsockname (GET_FILE (handle)->x.socket.handle, addr, paddrlen);
+  if (rc == -1)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __shutdown() */
+
+int tcpip_shutdown (ULONG handle, int how)
+{
+  int rc;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    return ENOTSOCK;            /* TODO: last_sock_errno */
+
+  rc = tip_shutdown (GET_FILE (handle)->x.socket.handle, how);
+  if (rc != 0)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __getpeername() */
+
+int tcpip_getpeername (ULONG handle, void *addr, int *paddrlen)
+{
+  int rc;
+
+  if (!IS_SOCKET (handle) || !IS_VALID_FILE (handle))
+    return ENOTSOCK;            /* TODO: last_sock_errno */
+
+  rc = tip_getpeername (GET_FILE (handle)->x.socket.handle, addr, paddrlen);
+  if (rc == -1)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __gethostbyname() */
+
+int tcpip_gethostbyname (const char *name, void **dst)
+{
+  void *p;
+
+  if (!tcpip_init ())
+    return NO_RECOVERY;
+
+  p = tip_gethostbyname (name);
+  *dst = p;
+  if (p == NULL)
+    {
+      /* h_errno seems to be always zero.  Bug? */
+
+      if (*tip_h_errno == 0)
+        return NO_RECOVERY;
+      else
+        return *tip_h_errno;
+    }
+  else
+    return 0;
+}
+
+
+/* __gethostbyaddr() */
+
+int tcpip_gethostbyaddr (const char *addr, int len, int type, void **dst)
+{
+  void *p;
+
+  if (!tcpip_init ())
+    return NO_RECOVERY;
+
+  p = tip_gethostbyaddr (addr, len, type);
+  *dst = p;
+  if (p == NULL)
+    {
+      /* h_errno seems to be always zero.  Bug? */
+
+      if (*tip_h_errno == 0)
+        return NO_RECOVERY;
+      else
+        return *tip_h_errno;
+    }
+  else
+    return 0;
+}
+
+
+/* __getservbyname() */
+
+int tcpip_getservbyname (const char *name, const char *proto, void **dst)
+{
+  void *p;
+
+  if (!tcpip_init ())
+    return -1;
+
+  p = tip_getservbyname (name, proto);
+  *dst = p;
+  return (p != NULL ? 0 : -1);
+}
+
+
+/* __getservbyport() */
+
+int tcpip_getservbyport (int port, const char *proto, void **dst)
+{
+  void *p;
+
+  if (!tcpip_init ())
+    return -1;
+
+  p = tip_getservbyport (port, proto);
+  *dst = p;
+  return (p != NULL ? 0 : -1);
+}
+
+
+/* __gethostid() */
+
+int tcpip_gethostid (int *dst)
+{
+  if (!tcpip_init ())
+    return ENETDOWN;
+
+  *dst = tip_gethostid ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __gethostname() */
+
+int tcpip_gethostname (char *name, int len)
+{
+  int rc;
+
+  /* TODO: Get hostname from environment variable if the net is
+     down. */
+
+  if (!tcpip_init ())
+    return ENETDOWN;
+
+  /* If HOSTNAME is not set, IBM's gethostname() simply leaves the
+     buffer alone! */
+
+  *name = 0;
+
+  rc = tip_gethostname (name, len);
+  if (rc != 0)
+    return tcpip_errno ();
+  last_sock_errno = 0;
+  return 0;
+}
+
+
+/* __getprotobyname() */
+
+int tcpip_getprotobyname (const char *name, void **dst)
+{
+  void *p;
+
+  if (!tcpip_init ())
+    return -1;
+
+  p = tip_getprotobyname (name);
+  *dst = p;
+  return (p != NULL ? 0 : -1);
+}
+
+
+/* __getprotobynumber() */
+
+int tcpip_getprotobynumber (int proto, void **dst)
+{
+  void *p;
+
+  if (!tcpip_init ())
+    return -1;
+
+  p = tip_getprotobynumber (proto);
+  *dst = p;
+  return (p != NULL ? 0 : -1);
+}
+
+
+/* __getnetbyname() */
+
+int tcpip_getnetbyname (const char *name, void **dst)
+{
+  void *p;
+
+  if (!tcpip_init ())
+    return -1;
+
+  p = tip_getnetbyname (name);
+  *dst = p;
+  return (p != NULL ? 0 : -1);
+}
+
+
+/* __getnetbyaddr() */
+
+int tcpip_getnetbyaddr (long net, void **dst)
+{
+  void *p;
+
+  if (!tcpip_init ())
+    return -1;
+
+  p = tip_getnetbyaddr (net);
+  *dst = p;
+  return (p != NULL ? 0 : -1);
+}
+
+
+/* __impsockhandle() */
+
+int tcpip_impsockhandle (ULONG handle, ULONG flags, int *errnop)
+{
+  int result, optlen, optval;
+  ULONG i;
+
+  if (!tcpip_init ())
+    {
+      *errnop = ENETDOWN;
+      return -1;
+    }
+
+  if (flags != 0)
+    {
+      *errnop = EINVAL;
+      return -1;
+    }
+
+  /* Check if HANDLE is a known socket handle of this process. */
+
+  LOCK_FILES;
+  for (i = 0; i < handle_count; ++i)
+    if (IS_SOCKET (i) && IS_VALID_FILE (i)
+        && GET_FILE (i)->x.socket.handle == handle)
+      {
+        GET_FILE (i)->ref_count += 1;
+        UNLOCK_FILES;
+        *errnop = 0;
+        return i;
+      }
+
+  /* HANDLE is not a known socket handle of this process.  Check if
+     it's actually a socket handle. */
+
+  optlen = sizeof (optval);
+  if (tip_getsockopt (handle, SOL_SOCKET, SO_TYPE, &optval, &optlen) != 0)
+    {
+      UNLOCK_FILES;
+      *errnop = ENOTSOCK;
+      return -1;
+    }
+
+  /* It's an entirely new socket handle.  Install it in SO32DLL.DLL's
+     tables and in our tables. */
+
+  tip_addsockettolist (handle);
+  result = tcpip_new_handle (handle, errnop);
+  if (result == -1)
+    tip_removesocketfromlist (handle);
+  UNLOCK_FILES;
+  return result;
+}
+
+
+/* Poll socket handles for __select().  Update the bitstrings if a
+   handle is ready. */
+
+int tcpip_select_poll (struct select_data *d, int *errnop)
+{
+  int i, j, n;
+
+  memcpy (d->sockett, d->sockets, d->socket_count * sizeof (int));
+  n = tip_select (d->sockett, d->socket_nread, d->socket_nwrite,
+                  d->socket_nexcept, 0);
+  if (n < 0)
+    {
+      *errnop = tcpip_errno ();
+      return -1;
+    }
+  if (n == 0)
+    return 0;
+  j = 0; n = 0;
+  for (i = 0; i < d->socket_nread; ++i, ++j)
+    if (d->sockett[j] != -1)
+      {
+        FD_SET (d->socketh[j], d->rbits);
+        n = 1;
+      }
+  for (i = 0; i < d->socket_nwrite; ++i, ++j)
+    if (d->sockett[j] != -1)
+      {
+        FD_SET (d->socketh[j], d->wbits);
+        n = 1;
+      }
+  for (i = 0; i < d->socket_nexcept; ++i, ++j)
+    if (d->sockett[j] != -1)
+      {
+        FD_SET (d->socketh[j], d->ebits);
+        n = 1;
+      }
+  *errnop = 0;
+  d->ready_flag = TRUE;
+  return n;
+}
Index: trunk/src/emx/src/os2/tcpip.h
===================================================================
--- trunk/src/emx/src/os2/tcpip.h	(revision 18)
+++ trunk/src/emx/src/os2/tcpip.h	(revision 18)
@@ -0,0 +1,67 @@
+/* tcpip.h -- Interface to tcpip.c
+   Copyright (c) 1994-1996 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+struct select_data;
+struct _recvfrom;
+struct _sendto;
+
+int tcpip_accept (ULONG handle, void *addr, int *paddrlen, int *errnop);
+int tcpip_bind (ULONG handle, void *addr, int addrlen);
+int tcpip_close (ULONG handle);
+int tcpip_connect (ULONG handle, void *addr, int addrlen);
+int tcpip_dup (ULONG handle, ULONG target, int *errnop);
+int tcpip_fcntl (ULONG handle, ULONG request, ULONG arg, int *errnop);
+int tcpip_fstat (ULONG handle, struct stat *dst, int *errnop);
+int tcpip_gethostbyaddr (const char *addr, int len, int type, void **dst);
+int tcpip_gethostbyname (const char *name, void **dst);
+int tcpip_gethostid (int *dst);
+int tcpip_gethostname (char *name, int len);
+int tcpip_getnetbyaddr (long net, void **dst);
+int tcpip_getnetbyname (const char *name, void **dst);
+int tcpip_getpeername (ULONG handle, void *addr, int *paddrlen);
+int tcpip_getprotobyname (const char *name, void **dst);
+int tcpip_getprotobynumber (int proto, void **dst);
+int tcpip_getservbyname (const char *name, const char *proto, void **dst);
+int tcpip_getservbyport (int port, const char *proto, void **dst);
+int tcpip_getsockhandle (ULONG handle, int *errnop);
+int tcpip_getsockname (ULONG handle, void *addr, int *paddrlen);
+int tcpip_getsockopt (ULONG handle, int level, int optname, void *optval,
+    int *poptlen);
+int tcpip_ioctl (ULONG handle, ULONG request, ULONG arg, int *errnop);
+int tcpip_listen (ULONG handle, int backlog);
+int tcpip_read (ULONG handle, void *buf, ULONG len, int *errnop);
+int tcpip_recv (ULONG handle, void *buf, int len, unsigned flags, int *errnop);
+int tcpip_recvfrom (const struct _recvfrom *args, int *errnop);
+int tcpip_select_poll (struct select_data *d, int *errnop);
+int tcpip_send (ULONG handle, const void *buf, int len, unsigned flags,
+    int *errnop);
+int tcpip_sendto (const struct _sendto *args, int *errnop);
+int tcpip_setsockopt (ULONG handle, int level, int optname, const void *optval,
+    int optlen);
+int tcpip_socket (int domain, int type, int protocol, int *errnop);
+int tcpip_shutdown (ULONG handle, int how);
+int tcpip_write (ULONG handle, const void *buf, ULONG len, int *errnop);
+int tcpip_impsockhandle (ULONG handle, ULONG flags, int *errnop);
Index: trunk/src/emx/src/os2/termio.c
===================================================================
--- trunk/src/emx/src/os2/termio.c	(revision 18)
+++ trunk/src/emx/src/os2/termio.c	(revision 18)
@@ -0,0 +1,1335 @@
+/* termio.c -- General terminal interface
+   Copyright (c) 1993-1998 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSPROCESS
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSDEVICES
+#define INCL_DOSDEVIOCTL
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSDATETIME
+#define INCL_DOSERRORS
+#define INCL_KBD
+#include <os2emx.h>
+#include "emxdll.h"
+#include "files.h"
+#include "clib.h"
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/termio.h>         /* SysV */
+#include <sys/ioctl.h>          /* _TCSANOW, _TCSADRAIN, and _TCSAFLUSH */
+#include <termios.h>            /* POSIX.1 */
+#include <sys/signal.h>
+
+#define NULL ((void *)0)
+
+#define KBD_SLEEP       50
+
+
+/* Semaphores. */
+
+HEV kbd_sem_cont;
+HEV kbd_sem_stop;
+HEV kbd_sem_time;
+HMUX kbd_sem_mux;
+HMTX kbd_sem_access;
+HEV kbd_sem_new;
+
+char kbd_started;
+
+static char kbd_buf[1024];
+static unsigned kbd_ptr_in;
+static unsigned kbd_ptr_out;
+static char kbd_kill_flag;
+static char kbd_stop_flag;
+static char kbd_ext_flag;
+static KBDKEYINFO kbd_inp;
+static TID kbd_tid;
+
+static char kbd_idelete;
+static int kbd_cc_intr;
+static int kbd_cc_quit;
+
+
+static void kbd_thread (ULONG arg);
+
+
+/* Start the keyboard thread. */
+
+static void start_keyboard (void)
+{
+  ULONG rc;
+  SEMRECORD semrec[3];
+
+  create_event_sem (&kbd_sem_new, DC_SEM_SHARED);
+  create_event_sem (&kbd_sem_cont, 0);
+  create_event_sem (&kbd_sem_stop, 0);
+  create_event_sem (&kbd_sem_time, DC_SEM_SHARED);
+
+  semrec[0].hsemCur = (HSEM)kbd_sem_new;
+  semrec[0].ulUser  = 0;
+  semrec[1].hsemCur = (HSEM)kbd_sem_time;
+  semrec[1].ulUser  = 1;
+  semrec[2].hsemCur = (HSEM)signal_sem;
+  semrec[2].ulUser  = 2;
+  create_muxwait_sem (&kbd_sem_mux, 3, semrec, DCMW_WAIT_ANY);
+  create_mutex_sem (&kbd_sem_access);
+
+  kbd_ptr_in = kbd_ptr_out = 0;
+
+  rc = DosCreateThread (&kbd_tid, kbd_thread, 0,
+                        CREATE_READY | STACK_COMMITTED, 0x4000);
+  if (rc != 0) error (rc, "DosCreateThread");
+  kbd_started = TRUE;
+}
+
+
+/* Set default values for a termio structure.
+
+   Note that the default values for c_iflag, c_lflag and c_cc differ
+   from Unix. */
+
+void init_termio (ULONG handle)
+{
+  my_file *d;
+
+  if (!IS_VALID_FILE (handle)) return;
+  d = GET_FILE (handle);
+  d->c_iflag = BRKINT | ICRNL | IXON | IXANY;
+  d->c_oflag = 0;
+  d->c_cflag = B9600 | CS8 | CREAD | HUPCL;
+  d->c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | IDEFAULT;
+  d->c_cc[VINTR]  = 0x03;       /* Ctrl-C */
+  d->c_cc[VQUIT]  = 0x1c;       /* Ctrl-\ */
+  d->c_cc[VERASE] = 0x08;       /* Ctrl-H */
+  d->c_cc[VKILL]  = 0x15;       /* Ctrl-U */
+  d->c_cc[VEOF]   = 0x04;       /* Ctrl-D */
+  d->c_cc[VEOL]   = 0;          /* Disabled */
+  d->c_cc[VMIN]   = 6;
+  d->c_cc[VTIME]  = 1;
+  d->c_cc[VSUSP]  = 0;          /* Disabled */
+  d->c_cc[VSTOP]  = 0x13;       /* Ctrl-S */
+  d->c_cc[VSTART] = 0x11;       /* Ctrl-Q */
+  d->tio_escape   = 0;
+  d->tio_buf_count = 0;
+}
+
+
+/* Return the number of characters in the keyboard buffer. */
+
+ULONG kbd_avail (void)
+{
+  ULONG result;
+
+  request_mutex (kbd_sem_access);
+  if (kbd_ptr_in >= kbd_ptr_out)
+    result = kbd_ptr_in - kbd_ptr_out;
+  else
+    result = sizeof (kbd_buf) - (kbd_ptr_out - kbd_ptr_in);
+  DosReleaseMutexSem (kbd_sem_access);
+  return result;
+}
+
+
+/* Put character C into the keyboard buffer.  Return true if
+   successful. */
+
+int kbd_put (UCHAR c)
+{
+  int result;
+  unsigned i;
+
+  request_mutex (kbd_sem_access);
+  i = (kbd_ptr_in + 1) % sizeof (kbd_buf);
+  if (i == kbd_ptr_out)
+    {
+      /* Buffer full. Clear the buffer (like Unix) and return FALSE. */
+
+      kbd_ptr_in = kbd_ptr_out = 0;
+      result = FALSE;
+    }
+  else
+    {
+      kbd_buf[kbd_ptr_in] = c;
+      kbd_ptr_in = i;
+      DosPostEventSem (kbd_sem_new);
+      result = TRUE;
+    }
+  DosReleaseMutexSem (kbd_sem_access);
+  return result;
+}
+
+
+static UCHAR kbd_get (void)
+{
+  UCHAR c;
+
+  if (kbd_ext_flag)
+    {
+      kbd_ext_flag = FALSE;
+      return kbd_inp.chScan;
+    }
+
+  do
+    {
+      KbdCharIn (&kbd_inp, IO_NOWAIT, 0);
+      if (kbd_kill_flag)
+        DosExit (EXIT_THREAD, 0);
+      if (kbd_inp.fbStatus == 0)
+        {
+          if (kbd_stop_flag)
+            {
+              reset_event_sem (kbd_sem_cont);
+              DosPostEventSem (kbd_sem_stop);
+              DosWaitEventSem (kbd_sem_cont, SEM_INDEFINITE_WAIT);
+            }
+          else
+            DosSleep (KBD_SLEEP);
+        }
+    } while (!(kbd_inp.fbStatus & KBDTRF_FINAL_CHAR_IN));
+
+  c = kbd_inp.chChar;
+
+  if (kbd_idelete && kbd_inp.chScan == 14)
+    {
+      /* Swap BS and DEL. */
+
+      if (c == 0x08)
+        return 0x7f;
+      else if (c == 0x7f)
+        return 0x08;
+    }
+
+  /* Return extended codes for Alt-Space and Ctrl-Space. */
+
+  if (c == ' ' && kbd_inp.chScan == 57)
+    {
+      if (kbd_inp.fsState & KBDSTF_ALT)
+        {
+          kbd_inp.chScan = 57;  /* Alt-Space */
+          kbd_ext_flag = TRUE;
+          return 0;
+        }
+      if (kbd_inp.fsState & KBDSTF_CONTROL)
+        {
+          kbd_inp.chScan = 2;   /* Ctrl-Space */
+          kbd_ext_flag = TRUE;
+          return 0;
+        }
+    }
+
+  if (c == 0xe0)
+    {
+      if (!(kbd_inp.fbStatus & KBDTRF_EXTENDED_CODE))
+        return c;
+
+      if (kbd_inp.fsState & (KBDSTF_RIGHTSHIFT | KBDSTF_LEFTSHIFT))
+        {
+          if (kbd_inp.chScan == 82) /* Ins */
+            kbd_inp.chScan = 4; /* Shift-Ins */
+          else if (kbd_inp.chScan == 83) /* Del */
+            kbd_inp.chScan = 5; /* Shift-Del */
+        }
+      kbd_ext_flag = TRUE;
+      return 0;
+    }
+
+  if (c == 0)
+    kbd_ext_flag = TRUE;
+  return c;
+}
+
+
+/* Stuff COUNT characters at SRC into the keyboard buffer.  The first
+   character of SRC will be read first, later.  Return true if
+   successful. */
+
+static int kbd_stuff (const char *src, unsigned count)
+{
+  int result;
+  unsigned i;
+
+  request_mutex (kbd_sem_access);
+  if (count == 0)
+    result = TRUE;
+  else
+    {
+      i = kbd_ptr_out;
+      while (count != 0)
+        {
+          if (i == 0)
+            i = sizeof (kbd_buf) - 1;
+          else
+            --i;
+          if (i == kbd_ptr_in)
+            break;
+          kbd_ptr_out = i;
+          kbd_buf[i] = src[--count];
+        }
+      result = (count == 0);
+    }
+  DosReleaseMutexSem (kbd_sem_access);
+  return result;
+}
+
+
+/* Flush the keyboard buffer. */
+
+static void kbd_flush (my_file *d)
+{
+  if (kbd_started)
+    request_mutex (kbd_sem_access);
+  KbdFlushBuffer (0);
+  kbd_ptr_in = kbd_ptr_out = 0;
+  if (d != NULL)
+    d->tio_buf_count = 0;
+  if (kbd_started)
+    DosReleaseMutexSem (kbd_sem_access);
+}
+
+
+/* Switch the keyboard to binary mode. */
+
+static void kbd_bin_mode (void)
+{
+  static KBDINFO ki;            /* Must not cross a 64K boundary */
+
+  ki.cb           = sizeof (ki);
+  ki.fsMask       = KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE;
+  ki.chTurnAround = (USHORT)'\r';
+  ki.fsInterim    = 0;
+  ki.fsState      = 0;
+  KbdSetStatus (&ki, 0);
+}
+
+
+void kbd_stop (void)
+{
+  static KBDINFO ki;            /* Must not cross a 64K boundary */
+
+  if (kbd_started && !kbd_stop_flag)
+    {
+      reset_event_sem (kbd_sem_stop);
+      kbd_stop_flag = TRUE;
+      DosWaitEventSem (kbd_sem_stop, SEM_INDEFINITE_WAIT);
+
+      ki.cb           = sizeof (ki);
+      ki.fsMask       = KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE;
+      ki.chTurnAround = (USHORT)'\r';
+      ki.fsInterim    = 0;
+      ki.fsState      = 0;
+      KbdSetStatus (&ki, 0);
+    }
+}
+
+
+void kbd_restart (void)
+{
+  if (kbd_started)
+    {
+      kbd_bin_mode ();
+      if (kbd_stop_flag)
+        {
+          kbd_stop_flag = FALSE;
+          DosPostEventSem (kbd_sem_cont);
+        }
+    }
+}
+
+
+/* Exception handler for kbd_thread().  On termination of the thread,
+   kbd_tid will be set to zero. */
+
+static ULONG kbd_exception (EXCEPTIONREPORTRECORD *report,
+                            EXCEPTIONREGISTRATIONRECORD *registration,
+                            CONTEXTRECORD *context,
+                            void *dummy)
+{
+  if (report->fHandlerFlags & (EH_EXIT_UNWIND|EH_UNWINDING))
+    return XCPT_CONTINUE_SEARCH;
+  switch (report->ExceptionNum)
+    {
+    case XCPT_ASYNC_PROCESS_TERMINATE: /* This is the correct one */
+    case XCPT_PROCESS_TERMINATE:       /* OS/2 bug */
+      kbd_tid = 0;
+      break;
+    }
+  return XCPT_CONTINUE_SEARCH;
+}
+
+
+static void kbd_thread (ULONG arg)
+{
+  UCHAR c;
+  EXCEPTIONREGISTRATIONRECORD registration;
+
+  registration.prev_structure = NULL;
+  registration.ExceptionHandler = kbd_exception;
+  DosSetExceptionHandler (&registration);
+
+  kbd_bin_mode ();
+  for (;;)
+    {
+      c = kbd_get ();
+      if (c == 0)
+        {
+          /* Handle scan codes: either store both characters or none. */
+
+          c = kbd_get ();
+          if (kbd_put (0))
+            kbd_put (c);
+          continue;
+        }
+
+      /* Raise signal if ISIG is set and the character matches VINTR
+         or VQUIT. */
+
+      if (kbd_cc_intr != 0 && c == kbd_cc_intr)
+        {
+          generate_signal (threads[1], SIGINT);
+          continue;
+        }
+      else if (kbd_cc_quit != 0 && c == kbd_cc_quit)
+        {
+          generate_signal (threads[1], SIGQUIT);
+          continue;
+        }
+
+      /* Put the character into the keyboard buffer. */
+
+      kbd_put (c);
+    }
+}
+
+
+void term_termio (void)
+{
+  kbd_kill_flag = TRUE;
+  if (kbd_tid != 0)
+    DosKillThread (kbd_tid);
+}
+
+
+#define CHAR_SIG        0x0100
+#define CHAR_NO         0x0101
+#define CHAR_TIME       0x0102
+
+
+/* Read a character from the keyboard.
+
+   If no character is available and WAITP is false, return CHAR_NO.
+   If WAITP is true, wait until a character is available or a signal
+   occurs.  Return CHAR_SIG if interrupted by a signal.  Return
+   CHAR_TIME if timed out.  Otherwise, return the character. */
+
+static unsigned read_keyboard (int waitp)
+{
+  ULONG rc, user;
+  unsigned c;
+  thread_data *td;
+  
+  td = get_thread ();
+  for (;;)
+    {
+      if (sig_flag)
+        return CHAR_SIG;
+      reset_event_sem (kbd_sem_new);
+      request_mutex (kbd_sem_access);
+      if (kbd_ptr_out == kbd_ptr_in)
+        c = CHAR_NO;
+      else
+        {
+          c = kbd_buf[kbd_ptr_out];
+          kbd_ptr_out = (kbd_ptr_out + 1) % sizeof (kbd_buf);
+        }
+      DosReleaseMutexSem (kbd_sem_access);
+      if (c != CHAR_NO || !waitp)
+        return c;
+      rc = DosWaitMuxWaitSem (kbd_sem_mux, SEM_INDEFINITE_WAIT, &user);
+      if (rc == ERROR_INTERRUPT)
+        return CHAR_SIG;
+      if (rc != 0)
+        error (rc, "DosWaitMuxWaitSem");
+      if (user == 1)
+        return CHAR_TIME;
+    }
+}
+
+
+/* Read a character from an asynchronous serial device.
+
+   If no character is available and WAITP is false, return CHAR_NO.
+   If WAITP is true, wait until a character is available or a signal
+   occurs.  Return CHAR_SIG if interrupted by a signal.  Return
+   CHAR_TIME if timed out.  Otherwise, return the character. */
+
+static unsigned read_async (ULONG handle, int waitp)
+{
+  ULONG rc, nread;
+  UCHAR c;
+  thread_data *td;
+
+  td = get_thread ();
+  if (sig_flag)
+    return CHAR_SIG;
+  /* TODO: waitp */
+  /* TODO: time out */
+  rc = DosRead (handle, &c, 1, &nread);
+  if (rc == ERROR_INTERRUPT)
+    return CHAR_SIG;
+  if (rc != 0)
+    return CHAR_NO;
+  return c;
+}
+
+
+ULONG async_avail (ULONG handle)
+{
+  ULONG rc, data_length;
+  RXQUEUE data;
+
+  data_length = sizeof (data);
+  rc = DosDevIOCtl (handle, IOCTL_ASYNC, ASYNC_GETINQUECOUNT,
+                    NULL, 0, NULL,
+                    &data, data_length, &data_length);
+  if (rc != 0)
+    return 0;
+  return data.cch;
+}
+
+
+ULONG async_writable (ULONG handle)
+{
+  ULONG rc, data_length;
+  RXQUEUE data;
+
+  data_length = sizeof (data);
+  rc = DosDevIOCtl (handle, IOCTL_ASYNC, ASYNC_GETOUTQUECOUNT,
+                    NULL, 0, NULL,
+                    &data, data_length, &data_length);
+  if (rc != 0 || data.cch > data.cb)
+    return 0;
+  return data.cb - data.cch;
+}
+
+
+ULONG termio_avail (ULONG handle)
+{
+
+  if (handle_flags[handle] & HF_CON)
+    {
+      if (GET_FILE (handle)->c_lflag & IDEFAULT)
+        return 0;
+      else
+        return kbd_avail ();
+    }
+  else if (handle_flags[handle] & HF_ASYNC)
+    return async_avail (handle);
+  else
+    return 0;
+}
+
+
+static void tr_out (my_file *d, UCHAR c)
+{
+  ULONG cbwritten;
+
+  DosWrite (d->tio_output_handle, &c, 1, &cbwritten);
+}
+
+
+/* Get and preprocess a character for termio input.
+
+   If no character is available and WAITP is false, return CHAR_NO.
+   If WAITP is true, wait until a character is available or a signal
+   occurs.  Return CHAR_SIG if interrupted by a signal.  Return
+   CHAR_TIME if timed out.  Otherwise, return the character. */
+
+static unsigned tr_get (my_file *d, int waitp)
+{
+  unsigned c;
+
+  do
+    {
+      if (d->flags & HF_ASYNC)
+        c = read_async (d->tio_input_handle, waitp);
+      else
+        c = read_keyboard (waitp);
+      if (c & ~0xff)
+        return c;
+      if (d->c_iflag & ISTRIP)
+        c &= 0x7f;
+    } while ((d->c_iflag & IGNCR) && c == '\r');
+
+  if ((d->c_iflag & INLCR) && c == '\n')
+    c = '\r';
+  else if ((d->c_iflag & ICRNL) && c == '\r')
+    c = '\n';
+
+  if ((d->c_iflag & IUCLC) && (c >= 'A' && c <= 'Z'))
+    c += 'a' - 'A';
+
+  return c;
+}
+
+
+static void tr_canon_echo (my_file *d, UCHAR c)
+{
+  if (d->c_lflag & ECHO)
+    {
+      if (c == '\n')
+        {
+          tr_out (d, '\r');
+          tr_out (d, '\n');
+        }
+      else
+        tr_out (d, c);
+    }
+}
+
+
+static void tr_back (my_file *d)
+{
+  ULONG cbwritten;
+
+  --d->tio_buf_count;
+  DosWrite (d->tio_output_handle, "\b \b", 3, &cbwritten);
+}
+
+
+/* Note that this function must not flush the buffer on overflow.
+   Code calling tr_canon_copy() depends on this assumption. */
+
+static void tr_put (my_file *d, UCHAR c)
+{
+  if (d->tio_buf_count < d->tio_buf_size)
+    d->tio_buf[d->tio_buf_count++] = c;
+}
+
+
+static void tr_canon_put (my_file *d, UCHAR c)
+{
+  d->tio_escape = FALSE;
+  tr_put (d, c);
+  tr_canon_echo (d, c);
+}
+
+
+static void tr_canon_esc_put (my_file *d, UCHAR c)
+{
+  tr_out (d, '\b');
+  tr_canon_put (d, c);
+}
+
+
+static int tr_canon_copy (my_file *d, char *dst, unsigned count, int *errnop)
+{
+  unsigned n;
+
+  n = (count < d->tio_buf_count ? count : d->tio_buf_count);
+  memcpy (dst, d->tio_buf + d->tio_buf_idx, n);
+  d->tio_buf_count -= n; d->tio_buf_idx += n;
+  *errnop = 0;
+  return n;
+}
+
+
+static int tr_canon_read (my_file *d, char *dst, unsigned count, int *errnop)
+{
+  unsigned c;
+
+  /* If there's (a remainder of) a line in the buffer, return up to
+     COUNT bytes from the buffer. */
+
+  if (d->tio_buf_count != 0)
+    return tr_canon_copy (d, dst, count, errnop);
+
+  /* Read another line.  If the end of a line (or EOF) is read, call
+     tr_canon_copy() to copy (part of) the line to DST. */
+
+  d->tio_buf_idx = 0;
+  d->tio_escape = FALSE;
+  for (;;)
+    {
+      c = tr_get (d, TRUE);
+      if (c == CHAR_SIG)
+        {
+          /* Interrupted by a signal. */
+
+          termio_flush (d->tio_input_handle);
+          *errnop = EINTR;
+          return -1;
+        }
+      else if (c == 0)
+        {
+          /* We got the 0 character which precedes a scan code.
+             Ignore both characters. */
+
+          c = tr_get (d, TRUE);
+          if (c == CHAR_SIG)
+            {
+              /* Interrupted by a signal. */
+
+              kbd_flush (d);
+              *errnop = EINTR;
+              return -1;
+            }
+        }
+      else if (c == '\n' || c == d->c_cc[VEOL])
+        {
+          /* End of line.  Return the buffered line, which contains at
+             least the end-of-line character. */
+          /* TODO: escape? */
+
+          tr_put (d, c);
+          tr_canon_echo (d, c);
+          return tr_canon_copy (d, dst, count, errnop);
+        }
+      else if (c == d->c_cc[VEOF])
+        {
+          /* End of file.  Return the buffered line. */
+
+          if (d->tio_escape)
+            tr_canon_esc_put (d, c);
+          else if (d->tio_buf_count == 0)
+            {
+              *errnop = 0;
+              return 0;
+            }
+          else
+            return tr_canon_copy (d, dst, count, errnop);
+        }
+      else if (c == d->c_cc[VERASE])
+        {
+          /* Erase character.  Delete one character. */
+
+          if (d->tio_escape)
+            tr_canon_esc_put (d, c);
+          else if (d->tio_buf_count != 0)
+            tr_back (d);
+        }
+      else if (c == d->c_cc[VKILL])
+        {
+          /* Kill character.  Delete all characters typed on this line. */
+
+          if (d->tio_escape)
+            tr_canon_esc_put (d, c);
+          else
+            {
+              d->tio_buf_count = 0;
+              if (d->c_lflag & ECHOK)
+                {
+                  tr_out (d, '\r');
+                  tr_out (d, '\n');
+                }
+            }
+        }
+      else if (d->tio_escape)
+        {
+          d->tio_escape = FALSE;
+          tr_put (d, '\\');
+          tr_put (d, c);
+          tr_canon_echo (d, c);
+        }
+      else if (c == '\\')
+        {
+          d->tio_escape = TRUE;
+          tr_canon_echo (d, c);
+        }
+      else
+        tr_canon_put (d, c);
+    }
+}
+
+
+static int tr_raw_read (my_file *d, char *dst, unsigned count,
+                        int *errnop)
+{
+  int result, timer_flag, vmin, vtime;
+  unsigned c;
+  ULONG rc;
+  HTIMER timer;
+
+  vmin = d->c_cc[VMIN];
+  vtime = d->c_cc[VTIME];
+
+  /* If O_NDELAY is set, rule out all cases where we have to wait. */
+
+  if ((d->flags & HF_NDELAY) && (vmin != 0 || vtime != 0))
+    {
+      ULONG avail;
+
+      avail = termio_avail (d->tio_input_handle);
+      if (avail < count && avail < (vmin != 0 ? vmin : 1))
+        {
+          *errnop = EAGAIN;
+          return -1;
+        }
+    }
+
+  result = 0;
+  timer_flag = FALSE;
+  if (d->flags & HF_CON)
+    reset_event_sem (kbd_sem_time);
+
+  /* Start the timer if VMIN == 0 and VTIME > 0. */
+
+  if (vmin == 0 && vtime != 0 && (d->flags & HF_CON))
+    {
+      rc = DosAsyncTimer ((1000 / 10) * vtime, (HSEM)kbd_sem_time, &timer);
+      if (rc != 0) error (rc, "DosAsyncTimer");
+      timer_flag = TRUE;
+      vmin = 1;
+    }
+
+  /* Read the character until the buffer is empty, enough characters
+     have been read, a signal occurs, or a time out occurs. */
+
+  *errnop = 0;
+  while (count != 0)
+    {
+      c = tr_get (d, result < vmin);
+      if (c == CHAR_NO || c == CHAR_TIME)
+        break;
+
+      if (c == CHAR_SIG)
+        {
+          /* Interrupted by a signal.  Do not flush keyboard buffer.
+             Rather copy the keys back to the keyboard buffer.  If
+             there isn't enough room, flush the keyboard buffer. */
+
+          if (result != 0 && !kbd_stuff (dst - result, result))
+            kbd_flush (d);
+
+          *errnop = EINTR; result = -1;
+          break;
+        }
+
+      /* TODO: Handle 0, scan code pairs. */
+
+      *dst++ = (char)c;
+      ++result; --count;
+      tr_canon_echo (d, c);
+
+      /* Restart timer for VMIN > 0 and VTIME > 0. */
+
+      if (count != 0 && d->c_cc[VMIN] != 0 && vtime != 0
+          && (d->flags & HF_CON))
+        {
+          if (timer_flag)
+            {
+              DosStopTimer (timer);
+              timer_flag = FALSE;
+            }
+          reset_event_sem (kbd_sem_time);
+          rc = DosAsyncTimer ((1000 / 10) * vtime, (HSEM)kbd_sem_time, &timer);
+          if (rc != 0) error (rc, "DosAsyncTimer");
+          timer_flag = TRUE;
+        }
+    }
+  if (timer_flag)
+    {
+      DosStopTimer (timer);
+      /* Reset the semaphore, in case ICANON is activated. */
+      reset_event_sem (kbd_sem_time);
+    }
+  return result;
+}
+
+
+/* Unix-like read() for the terminal.  DST is the destination address,
+   COUNT is the number of bytes to read.  Return the number of bytes
+   read or, on error, -1.  Store the error number to *ERRNOP.
+
+   Currently this function is implemented for the keyboard only. */
+
+int termio_read (ULONG handle, char *dst, unsigned count, int *errnop)
+{
+  int result;
+  my_file *d;
+
+  sig_block_start ();
+
+  /* Update the file description's flag bits with the flag bits of the
+     handle. */
+
+  d = GET_FILE (handle);
+  d->flags = handle_flags[handle];
+  d->tio_input_handle = handle;
+  d->tio_output_handle = (d->flags & HF_CON ? 1 : handle);
+
+  if (count == 0)
+    {
+      *errnop = 0;
+      result = 0;
+    }
+  else if (d->c_lflag & ICANON)
+    result = tr_canon_read (d, dst, count, errnop);
+  else
+    result = tr_raw_read (d, dst, count, errnop);
+  sig_block_end ();
+  return result;
+}
+
+
+void termio_flush (ULONG handle)
+{
+  my_file *d;
+
+  if (IS_VALID_FILE (handle))
+    d = GET_FILE (handle);
+  else
+    d = NULL;
+  if (handle_flags[handle] & HF_CON)
+    kbd_flush (d);
+  else
+    {
+      /* TODO: ASYNC */
+    }
+}
+
+
+static void async_set (ULONG handle, ULONG new_cflag, ULONG new_iflag,
+                       const UCHAR *new_cc)
+{
+  my_file *d;
+  ULONG rc, parm_length;
+  SETEXTBAUDRATE speed;
+  LINECONTROL lctl;
+  DCBINFO dcb;
+
+  d = GET_FILE (handle);
+  if (new_cflag != d->c_cflag)
+    {
+      lctl = d->x.async.lctl;
+      if ((new_cflag & CBAUD) != (d->c_cflag & CBAUD))
+        {
+          speed.ulRate = d->x.async.speed.ulCurrentRate;
+          switch (new_cflag & CBAUD)
+            {
+            case B0:
+              /* TODO: Hang up */
+              break;
+            case B50:
+              speed.ulRate = 50; break;
+            case B75:
+              speed.ulRate = 75; break;
+            case B110:
+              speed.ulRate = 110; break;
+            case B134:
+              speed.ulRate = 134; break;
+            case B150:
+              speed.ulRate = 150; break;
+            case B200:
+              speed.ulRate = 200; break;
+            case B300:
+              speed.ulRate = 300; break;
+            case B600:
+              speed.ulRate = 600; break;
+            case B1200:
+              speed.ulRate = 1200; break;
+            case B1800:
+              speed.ulRate = 1800; break;
+            case B2400:
+              speed.ulRate = 2400; break;
+            case B4800:
+              speed.ulRate = 4800; break;
+            case B9600:
+              speed.ulRate = 9600; break;
+            case B19200:
+              speed.ulRate = 19200; break;
+            case B38400:
+              speed.ulRate = 38400; break;
+            }
+          if (speed.ulRate != d->x.async.speed.ulCurrentRate)
+            {
+              /* Set the bit rate. */
+
+              parm_length = sizeof (speed);
+              rc = DosDevIOCtl (handle, IOCTL_ASYNC, ASYNC_SETEXTBAUDRATE,
+                                &speed, parm_length, &parm_length,
+                                NULL, 0, NULL);
+              d->x.async.speed.ulCurrentRate = speed.ulRate;
+            }
+        }
+
+      /* Character size */
+
+      switch (new_cflag & CSIZE)
+        {
+        case CS5:
+          lctl.bDataBits = 5; break;
+        case CS6:
+          lctl.bDataBits = 6; break;
+        case CS7:
+          lctl.bDataBits = 7; break;
+        case CS8:
+          lctl.bDataBits = 8; break;
+        }
+
+      /* Parity none/odd/even */
+
+      if ((new_cflag & (PARENB|PARODD)) != (d->c_cflag & (PARENB|PARODD)))
+        {
+          if (!(new_cflag & PARENB))
+            lctl.bParity = 0;   /* No parity */
+          else if (new_cflag & PARODD)
+            lctl.bParity = 1;   /* Odd parity */
+          else
+            lctl.bParity = 2;   /* Even parity */
+        }
+
+      /* Stop bits */
+
+      if ((new_cflag & CSTOPB) != (d->c_cflag & CSTOPB))
+        {
+          if (new_cflag & CSTOPB)
+            lctl.bStopBits = 2; /* 2 stop bits */
+          else
+            lctl.bStopBits = 0; /* 1 stop bit */
+        }
+
+      /* Stop bits vs. character size */
+
+      if (lctl.bDataBits == 5 && lctl.bStopBits == 2)
+        lctl.bStopBits = 1;
+      else if (lctl.bDataBits != 5 && lctl.bStopBits == 1)
+        lctl.bStopBits = 2;
+
+      if (memcmp (&lctl, &d->x.async.lctl.bDataBits, sizeof (lctl)) != 0)
+        {
+          /* Set the line characteristics. */
+
+          parm_length = sizeof (lctl);
+          rc = DosDevIOCtl (handle, IOCTL_ASYNC, ASYNC_SETLINECTRL,
+                            &lctl, parm_length, &parm_length,
+                            NULL, 0, NULL);
+          d->x.async.lctl = lctl;
+        }
+    }
+
+  /* Note: There are no VSTOP and VSTART entries in `struct termio'! */
+
+  if (new_iflag != d->c_iflag
+      || new_cc[VMIN] != d->c_cc[VMIN]
+      || new_cc[VTIME] != d->c_cc[VTIME])
+    {
+      dcb = d->x.async.dcb;
+      if ((new_iflag & IXON) != (d->c_iflag & IXON))
+        {
+          if (new_iflag & IXON)
+            dcb.fbFlowReplace |= 1;
+          else
+            dcb.fbFlowReplace &= ~1;
+        }
+      if ((new_iflag & IXOFF) != (d->c_iflag & IXOFF))
+        {
+          if (new_iflag & IXOFF)
+            dcb.fbFlowReplace |= 2;
+          else
+            dcb.fbFlowReplace &= ~2;
+        }
+      if (new_cc[VMIN] != d->c_cc[VMIN]
+          || new_cc[VTIME] != d->c_cc[VTIME])
+        {
+          if (new_cc[VMIN] == 0)
+            {
+              if (new_cc[VTIME] == 0)
+                dcb.fbTimeout = (dcb.fbTimeout & ~6) | 6;
+              else
+                {
+                  dcb.fbTimeout = (dcb.fbTimeout & ~6) | 4;
+                  dcb.usReadTimeout = new_cc[VTIME] * 10 - 1;
+                }
+            }
+          else
+            {
+              dcb.fbTimeout = (dcb.fbTimeout & ~6) | 2;
+              dcb.usReadTimeout = new_cc[VTIME] * 10 - 1;
+            }
+        }
+      if (memcmp (&dcb, &d->x.async.dcb, sizeof (dcb)) != 0)
+        {
+          /* Set the DCB */
+
+          parm_length = sizeof (dcb);
+          rc = DosDevIOCtl (handle, IOCTL_ASYNC, ASYNC_SETDCBINFO,
+                            &dcb, parm_length, &parm_length,
+                            NULL, 0, NULL);
+          d->x.async.dcb = dcb;
+        }
+    }
+}
+
+
+static void termio_set_common (ULONG handle, my_file *d)
+{
+  if (handle_flags[handle] & HF_CON)
+    {
+      kbd_idelete = (d->c_iflag & IDELETE) != 0;
+      if (d->c_lflag & ISIG)
+        {
+          kbd_cc_intr = d->c_cc[VINTR];
+          kbd_cc_quit = d->c_cc[VQUIT];
+        }
+      else
+        kbd_cc_intr = kbd_cc_quit = 0;
+
+      if (d->c_lflag & IDEFAULT)
+        {
+          if (kbd_started)
+            kbd_stop ();
+        }
+      else if (kbd_started)
+        kbd_restart ();
+      else
+        start_keyboard ();
+    }
+}
+
+
+void termio_set (ULONG handle, const struct termio *tio)
+{
+  my_file *d;
+
+  d = GET_FILE (handle);
+  if (!(tio->c_lflag & IDEFAULT) && d->tio_buf == NULL)
+    {
+      d->tio_buf_size = 1024;
+      d->tio_buf = checked_private_alloc (d->tio_buf_size);
+    }
+
+  if (handle_flags[handle] & HF_ASYNC)
+    async_set (handle, tio->c_cflag, tio->c_iflag, tio->c_cc);
+
+  d->c_iflag = tio->c_iflag;
+  d->c_oflag = tio->c_oflag;
+  d->c_cflag = tio->c_cflag;
+  d->c_lflag = tio->c_lflag;
+  memcpy (d->c_cc, tio->c_cc, NCC);
+  d->c_cc[VSUSP]  = 0;          /* Disabled */
+  d->c_cc[VSTOP]  = 0x13;       /* Ctrl-S */
+  d->c_cc[VSTART] = 0x11;       /* Ctrl-Q */
+
+  termio_set_common (handle, d);
+}
+
+
+void termio_get (ULONG handle, struct termio *tio)
+{
+  const my_file *d;
+
+  d = GET_FILE (handle);
+  tio->c_iflag = d->c_iflag;
+  tio->c_oflag = d->c_oflag;
+  tio->c_cflag = d->c_cflag;
+  tio->c_lflag = d->c_lflag;
+  tio->c_line  = 0;
+  memcpy (tio->c_cc, d->c_cc, NCC);
+}
+
+
+void termios_get (ULONG handle, struct termios *tio)
+{
+  const my_file *d;
+
+  d = GET_FILE (handle);
+  tio->c_iflag = d->c_iflag;
+  tio->c_oflag = d->c_oflag;
+  tio->c_cflag = d->c_cflag;
+  tio->c_lflag = d->c_lflag & ~IDEFAULT;
+  memcpy (tio->c_cc, d->c_cc, NCCS);
+}
+
+
+void termios_set (ULONG handle, const struct termios *tio)
+{
+  my_file *d;
+
+  d = GET_FILE (handle);
+  if (d->tio_buf == NULL)
+    {
+      d->tio_buf_size = 1024;
+      d->tio_buf = checked_private_alloc (d->tio_buf_size);
+    }
+
+  if (handle_flags[handle] & HF_ASYNC)
+    async_set (handle, tio->c_cflag, tio->c_iflag, tio->c_cc);
+
+  d->c_iflag = tio->c_iflag;
+  d->c_oflag = tio->c_oflag;
+  d->c_cflag = tio->c_cflag;
+  d->c_lflag = tio->c_lflag & ~IDEFAULT;
+  memcpy (d->c_cc, tio->c_cc, NCCS);
+
+  termio_set_common (handle, d);
+}
+
+
+ULONG query_async (ULONG handle)
+{
+  ULONG rc;
+  ULONG data_length;
+  my_file *d;
+
+  d = GET_FILE (handle);
+
+  /* Retrieve the bit rate. */
+
+  memset (&d->x.async.speed, 0, sizeof (d->x.async.speed));
+  data_length = sizeof (d->x.async.speed);
+  rc = DosDevIOCtl (handle, IOCTL_ASYNC, ASYNC_GETEXTBAUDRATE,
+                    NULL, 0, NULL,
+                    &d->x.async.speed, data_length, &data_length);
+  if (rc != 0) return rc;
+
+  /* Retrieve the line characteristics. */
+
+  memset (&d->x.async.lctl, 0, sizeof (d->x.async.lctl));
+  data_length = sizeof (d->x.async.lctl);
+  rc = DosDevIOCtl (handle, IOCTL_ASYNC, ASYNC_GETLINECTRL,
+                    NULL, 0, NULL,
+                    &d->x.async.lctl, data_length, &data_length);
+  if (rc != 0) return rc;
+
+  /* Retrieve the DCB parameters. */
+
+  memset (&d->x.async.dcb, 0, sizeof (d->x.async.dcb));
+  data_length = sizeof (d->x.async.dcb);
+  rc = DosDevIOCtl (handle, IOCTL_ASYNC, ASYNC_GETDCBINFO,
+                    NULL, 0, NULL,
+                    &d->x.async.dcb, data_length, &data_length);
+  return rc;
+}
+
+
+/* Translate values for termio. */
+
+ULONG translate_async (ULONG handle)
+{
+  ULONG cflag;
+  my_file *d;
+
+  d = GET_FILE (handle);
+  cflag = 0;
+  switch (d->x.async.speed.ulCurrentRate)
+    {
+    case 50: cflag |= B50; break;
+    case 75: cflag |= B75; break;
+    case 110: cflag |= B110; break;
+    case 134: cflag |= B134; break;
+    case 150: cflag |= B150; break;
+    case 200: cflag |= B200; break;
+    case 300: cflag |= B300; break;
+    case 600: cflag |= B600; break;
+    case 1200: cflag |= B1200; break;
+    case 1800: cflag |= B1800; break;
+    case 2400: cflag |= B2400; break;
+    case 4800: cflag |= B4800; break;
+    case 9600: cflag |= B9600; break;
+    case 19200: cflag |= B19200; break;
+    case 38400: cflag |= B38400; break;
+    default: cflag |= B1200; break;
+    }
+
+  switch (d->x.async.lctl.bDataBits)
+    {
+    case 5: cflag |= CS5; break;
+    case 6: cflag |= CS6; break;
+    case 7: cflag |= CS7; break;
+    case 8: cflag |= CS8; break;
+    default: return ERROR_GEN_FAILURE;
+    }
+  switch (d->x.async.lctl.bParity)
+    {
+    case 1: cflag |= PARENB|PARODD; break; /* Odd parity */
+    case 2: cflag |= PARENB;        break; /* Even parity */
+    case 3: break;                         /* Mark parity */
+    case 4: break;                         /* Space parity */
+    default: break;
+    }
+  switch (d->x.async.lctl.bStopBits)
+    {
+    case 0: break;              /* 1 stop bit */
+    case 1: cflag |= CSTOPB;    /* 1.5 stop bits (CS5 only) */
+    case 2: cflag |= CSTOPB;    /* 2 stop bits (all but CS5) */
+    default: break;
+    }
+  cflag |= CREAD;               /* Enable receiver */
+  cflag |= HUPCL;               /* Hang up on last close */
+
+  /* Note: IGNPAR, INPCK, and PARMRK are not supported; parity
+     checking is always enabled and characters with wrong parity are
+     always read. */
+
+  /* TODO: CLOCAL, HUPCL? */
+
+  init_termio (handle);
+  d = GET_FILE (handle);
+  d->c_cflag = cflag;
+  d->c_lflag = IDEFAULT;
+  d->c_cc[VSTOP] = d->x.async.dcb.bXOFFChar;
+  d->c_cc[VSTART] = d->x.async.dcb.bXONChar;
+
+  /* Automatic transmit flow control (XON/XOFF) */
+
+  if (d->x.async.dcb.fbFlowReplace & 1)
+    d->c_iflag |= IXON;
+  else
+    d->c_iflag &= ~IXON;
+
+  /* Automatic receive flow control (XON/XOFF) */
+
+  if (d->x.async.dcb.fbFlowReplace & 2)
+    d->c_iflag |= IXOFF;
+  else
+    d->c_iflag &= ~IXOFF;
+
+  /* Time out processing.  Note that dcb.usReadTimeout contains the
+     number of hundredths of a second, minus 1.  That is, 0 means 0.01
+     seconds. */
+
+  switch (d->x.async.dcb.fbTimeout & 6)
+    {
+    case 2:                     /* Normal */
+      d->c_cc[VMIN] = 255;      /* Approximation to infinity */
+      d->c_cc[VTIME] = (d->x.async.dcb.usReadTimeout > 2550 - 1
+                        ? 255 : (d->x.async.dcb.usReadTimeout + 1 + 9) / 10);
+      break;
+
+    case 4:                     /* Wait for something */
+      d->c_cc[VMIN] = 0;
+      d->c_cc[VTIME] = (d->x.async.dcb.usReadTimeout > 2550 - 1
+                        ? 255 : (d->x.async.dcb.usReadTimeout + 1 + 9) / 10);
+      break;
+
+    case 6:                     /* No-Wait */
+    default:                    /* Should not happen */
+      d->c_cc[VMIN] = 0;
+      d->c_cc[VTIME] = 0;
+      break;
+    }
+  return 0;
+}
Index: trunk/src/emx/src/os2/time.c
===================================================================
--- trunk/src/emx/src/os2/time.c	(revision 18)
+++ trunk/src/emx/src/os2/time.c	(revision 18)
@@ -0,0 +1,245 @@
+/* time.c -- Time and date
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSMISC
+#include <os2emx.h>
+#include "emxdll.h"
+#include <limits.h>
+#include <sys/timeb.h>
+#include <sys/time.h>
+
+
+/* Day number, relative to 01-Jan-1970, of 01-Jan for the years 1970
+   through 2106 */
+
+static ULONG const year_table[] =
+{
+  0, 365, 730, 1096, 1461, 1826, 2191, 2557, 2922, 3287, 3652, 4018,
+  4383, 4748, 5113, 5479, 5844, 6209, 6574, 6940, 7305, 7670, 8035,
+  8401, 8766, 9131, 9496, 9862, 10227, 10592, 10957, 11323, 11688,
+  12053, 12418, 12784, 13149, 13514, 13879, 14245, 14610, 14975,
+  15340, 15706, 16071, 16436, 16801, 17167, 17532, 17897, 18262,
+  18628, 18993, 19358, 19723, 20089, 20454, 20819, 21184, 21550,
+  21915, 22280, 22645, 23011, 23376, 23741, 24106, 24472, 24837,
+  25202, 25567, 25933, 26298, 26663, 27028, 27394, 27759, 28124,
+  28489, 28855, 29220, 29585, 29950, 30316, 30681, 31046, 31411,
+  31777, 32142, 32507, 32872, 33238, 33603, 33968, 34333, 34699,
+  35064, 35429, 35794, 36160, 36525, 36890, 37255, 37621, 37986,
+  38351, 38716, 39082, 39447, 39812, 40177, 40543, 40908, 41273,
+  41638, 42004, 42369, 42734, 43099, 43465, 43830, 44195, 44560,
+  44926, 45291, 45656, 46021, 46387, 46752, 47117, 47482, 47847,
+  48212, 48577, 48942, 49308, 49673, ULONG_MAX
+};
+
+/* Day number, relative to 01-Jan, of day 01 for January through
+   December. */
+
+static ULONG const month_table_non_leap[] = 
+  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, ULONG_MAX};
+
+static ULONG const month_table_leap[] = 
+  {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, ULONG_MAX};
+
+
+/* Convert a my_datetime structure to Unix time format. */
+
+static time_t time2unix (const struct my_datetime *src)
+{
+  ULONG t, y;
+
+  if (src->day < 1 || src->day > 31  || src->month < 1 || src->month > 12
+      || src->year < 1970 || src->year > 2105
+      || src->seconds >= 60 || src->minutes >= 60 || src->hours >= 24)
+    return 0;
+
+  t = src->year * 365 + (src->month - 1) * 31 + src->day;
+  if (src->month <= 2)
+    {
+      /* Jan and Feb. */
+      y = src->year - 1;
+    }
+  else
+    {
+      /* Mar through Dec. */
+      y = src->year;
+      t -= (4 * src->month + 23) / 10;
+    }
+  t += y / 4;
+  t -= (3 * (y / 100 + 1)) / 4;
+  t -= 719528;                  /* 01-Jan-1970 */
+  return ((t * 24 + src->hours) * 60 + src->minutes) * 60 + src->seconds;
+}
+
+
+/* Return 1 if Y is a leap year, return 0 otherwise. */
+
+static int leap_year (ULONG y)
+{
+  if (y % 4 != 0)
+    return 0;
+  else if (y % 100 != 0)
+    return 1;
+  else if (y % 400 != 0)
+    return 0;
+  else
+    return 1;
+}
+
+
+/* Convert a Unix time value to a my_datetime structure. */
+
+void unix2time (struct my_datetime *dst, ULONG t)
+{
+  ULONG lo, hi, i;
+  const ULONG *p;
+
+  dst->seconds = t % 60; t /= 60;
+  dst->minutes = t % 60; t /= 60;
+  dst->hours = t % 24; t /= 24;
+
+  /* Find an i such that year_table[i] <= t < year_table[i+1]. */
+
+  lo = 0; hi = sizeof (year_table) / sizeof (year_table[0]) - 2;
+  for (;;)
+    {
+      i = (lo + hi) / 2;
+      if (year_table[i] > (int)t)
+        hi = i - 1;
+      else if (year_table[i+1] <= (int)t)
+        lo = i + 1;
+      else
+        break;
+    }
+  dst->year = i + 1970;
+  t -= year_table[i];
+
+  p = (leap_year (dst->year) ? month_table_leap : month_table_non_leap);
+  for (i = 0; t >= p[i+1]; ++i)
+    ;
+  dst->month = i + 1;
+  dst->day = t - p[i] + 1;
+}
+
+
+/* Get current time and store it in Unix format to the TIMEB structure
+   pointed to by DST. */
+
+void do_ftime (struct timeb *dst)
+{
+  DATETIME dt;
+  struct my_datetime tmp;
+
+  DosGetDateTime (&dt);
+  tmp.seconds = dt.seconds;
+  tmp.minutes = dt.minutes;
+  tmp.hours = dt.hours;
+  tmp.day = dt.day;
+  tmp.month = dt.month;
+  tmp.year = dt.year;
+  dst->time = time2unix (&tmp);
+  dst->dstflag = 0;
+  dst->millitm = dt.hundredths * 10;
+  dst->timezone = dt.timezone;  /* This will be overridden by ftime() */
+}
+
+
+/* Convert packed time and date to Unix format. */
+
+ULONG packed2unix (FDATE date, FTIME time)
+{
+  struct my_datetime tmp;
+
+  tmp.seconds = time.twosecs * 2;
+  tmp.minutes = time.minutes;
+  tmp.hours   = time.hours;
+  tmp.day     = date.day;
+  tmp.month   = date.month;
+  tmp.year    = date.year + 1980;
+  return time2unix (&tmp);
+}
+
+
+/* Return the number of 1/100 seconds elapsed since the process has
+   been started.
+
+   This function no longer tries to use QSV_TIME_LOW and QSV_TIME_HIGH
+   to increase the time before the return value wraps around.  Now, it
+   will wrap around after 49 days. */
+
+unsigned long long get_clock (int init_flag)
+{
+  ULONG ms;
+  static ULONG clock0_ms;
+
+  ms = querysysinfo (QSV_MS_COUNT);
+  if (init_flag)
+    {
+      clock0_ms = ms;
+      return 0;
+    }
+  else
+    return (ms - clock0_ms) / 10;
+}
+
+
+int do_settime (const struct timeval *tp, int *errnop)
+{
+  DATETIME dt;
+  struct my_datetime mdt;
+  ULONG rc;
+
+  /* Preserve the value of DATETIME.timezone. */
+
+  rc = DosGetDateTime (&dt);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  
+  unix2time (&mdt, tp->tv_sec + tp->tv_usec / 1000000);
+
+  /* Keep dt.timezone! */
+
+  dt.day     = mdt.day;
+  dt.month   = mdt.month;
+  dt.year    = mdt.year;
+  dt.weekday = 0;
+
+  dt.hours   = mdt.hours;
+  dt.minutes = mdt.minutes;
+  dt.seconds = mdt.seconds;
+  dt.hundredths = (tp->tv_usec / 10000) % 100;
+
+  rc = DosSetDateTime (&dt);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  *errnop = 0;
+  return 0;
+}
Index: trunk/src/emx/src/os2/utils.c
===================================================================
--- trunk/src/emx/src/os2/utils.c	(revision 18)
+++ trunk/src/emx/src/os2/utils.c	(revision 18)
@@ -0,0 +1,552 @@
+/* utils.c -- Miscellaneous utility functions
+   Copyright (c) 1994-1998 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#include <stdarg.h>
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSMODULEMGR
+#define INCL_DOSMISC
+#define INCL_DOSNLS
+#define INCL_DOSERRORS
+#include <os2emx.h>
+#include <sys/nls.h>
+#include "emxdll.h"
+#include "clib.h"
+
+#define NULL ((void *)0)
+
+#define MAX_EVENT_SEM   16
+#define MAX_MUTEX_SEM   6
+#define MAX_MUXWAIT_SEM 2
+
+/* Mutex semaphore for protecting data in the COMMON32 segment. */
+
+static char const common_mutex_name[] = "/sem32/emx/common.mtx";
+HMTX common_mutex;
+static BYTE common_open;
+
+/* Table of event semaphores. */
+
+static ULONG event_sem_count;
+static HEV event_sem_table[MAX_EVENT_SEM];
+
+/* Table of Mutex semaphores. */
+
+static ULONG mutex_sem_count;
+static HMTX mutex_sem_table[MAX_MUTEX_SEM];
+
+/* Table of MuxWait semaphores. */
+
+static ULONG muxwait_sem_count;
+static HMUX muxwait_sem_table[MAX_MUXWAIT_SEM];
+
+/* Table identifying DBCS lead bytes.  Note that our local copy of
+   c.lib no longer contains _nls_ctype_tab to avoid linking in
+   _dbcs_init().  This could also have been achieved by initializing
+   this variable; however, initializing any variable would add
+   non-shared pages to emx.dll, slowing down loading when it's already
+   loaded. */
+
+unsigned char _nls_ctype_tab[256];
+
+
+/* Convert a hexadecimal number consisting of 8 digits, for
+   init_fork() and init2_signal().  Return FALSE on failure.  The
+   converted number is stored to *DST.  Only lower-case letters are
+   supported. */
+
+int conv_hex8 (const char *s, ULONG *dst)
+{
+  int i;
+  ULONG n;
+  unsigned char c;
+
+  n = 0;
+  for (i = 0; i < 8; ++i)
+    {
+      c = (unsigned char)*s++;
+      if (c >= '0' && c <= '9')
+        c -= '0';
+      else if (c >= 'a' && c <= 'f')
+        c -= 'a' - 10;
+      else
+        return FALSE;
+      n = (n << 4) | c;
+    }
+  *dst = n;
+  return TRUE;
+}
+
+
+/* Convert the unsigned number X to a hexadecimal string of DIGITS
+   digits at DST. */
+
+static void hexn (char *dst, ULONG x, int digits)
+{
+  int i;
+
+  for (i = digits - 1; i >= 0; --i)
+    {
+      dst[i] = "0123456789abcdef"[x & 0x0f];
+      x >>= 4;
+    }
+}
+
+
+/* Convert the unsigned number X to a decimal string at DST.  Return the
+   number of characters stored to DST. */
+
+static int udecn (char *dst, unsigned x)
+{
+  int i, j;
+  char digits[12];
+
+  i = 0;
+  do
+    {
+      digits[i++] = (char)(x % 10 + '0');
+      x /= 10;
+    } while (x != 0);
+  for (j = 1; j <= i; ++j)
+    *dst++ = digits[i-j];
+  return i;
+}
+
+
+/* Convert the signed number X to a decimal string at DST.  Return the
+   number of characters stored to DST. */
+
+static int decn (char *dst, int x)
+{
+  if (x >= 0)
+    return udecn (dst, (unsigned)x);
+  else
+    {
+      *dst = '-';
+      return udecn (dst+1, (unsigned)(-x)) + 1;
+    }
+}
+
+
+/* Display a string on the error output. */
+
+void otext (const char *msg)
+{
+  ULONG written;
+
+  DosWrite (errout_handle, msg, strlen (msg), &written);
+}
+
+
+/* Handle an unexpected OS/2 error code by beeping and displaying a
+   message which shows the function name (a string pointed to by MSG)
+   and the return code (RC). */
+
+void error (ULONG rc, const char *msg)
+{
+  oprintf ("%s: 0x%.8x ", msg, (unsigned)rc);
+  DosBeep (698, 500);
+}
+
+
+/* Create an unnamed Mutex semaphore and store the handle to *PSEM.
+   Return the OS/2 error code.
+
+   Note: This function is not reentrant! */
+
+ULONG create_mutex_sem (HMTX *psem)
+{
+  ULONG rc;
+
+  /* This should not happen unless someone adds create_mutex_sem()
+     calls without updating MAX_MUTEX_SEM.  Note that do_lock_common()
+     also increments mutex_sem_count. */
+
+  if (mutex_sem_count >= MAX_MUTEX_SEM)
+    {
+      oprintf ("Too many Mutex semaphores\r\n");
+      return ERROR_TOO_MANY_SEMAPHORES;
+    }
+
+  rc = DosCreateMutexSem (NULL, psem, 0, 0);
+  if (rc == 0)
+    mutex_sem_table[mutex_sem_count++] = *psem;
+  else
+    error (rc, "DosCreateMutexSem");
+  return rc;
+}
+
+
+/* Request the Mutex semaphore SEM. */
+
+void request_mutex (HMTX sem)
+{
+  ULONG rc;
+
+  do
+    {
+      rc = DosRequestMutexSem (sem, SEM_INDEFINITE_WAIT);
+    } while (rc == ERROR_SEM_OWNER_DIED || rc == ERROR_INTERRUPT);
+}
+
+
+/* Create an unnamed event semaphore and store the semaphore handle to
+   *PSEM.  Attribute bits (such as DC_SEM_SHARED) are given in
+   ATTR.  Return the OS/2 error code.
+
+   Note: This function is not reentrant! */
+
+ULONG create_event_sem (HEV *psem, ULONG attr)
+{
+  ULONG rc;
+
+  /* This should not happen unless someone adds create_event_sem()
+     calls without updating MAX_EVENT_SEM. */
+
+  if (event_sem_count >= MAX_EVENT_SEM)
+    {
+      oprintf ("Too many event semaphores\r\n");
+      return ERROR_TOO_MANY_SEMAPHORES;
+    }
+
+  rc = DosCreateEventSem (NULL, psem, attr, FALSE);
+  if (rc == 0)
+    event_sem_table[event_sem_count++] = *psem;
+  else
+    error (rc, "DosCreateEventSem");
+  return rc;
+}
+
+
+/* Close an event semaphore.
+
+   Note: This function is not reentrant! */
+
+void close_event_sem (HEV sem)
+{
+  ULONG i;
+
+  for (i = 0; i < event_sem_count; ++i)
+    if (event_sem_table[i] == sem)
+      {
+        event_sem_table[i] = event_sem_table[--event_sem_count];
+        break;
+      }
+  DosCloseEventSem (sem);
+}
+
+
+/* Create an unnamed MuxWait semaphore and store the semaphore handle
+   to *PSEM.  Return the OS/2 error code.
+
+   Note: This function is not reentrant! */
+
+ULONG create_muxwait_sem (HMUX *psem, ULONG count, SEMRECORD *array,
+                          ULONG attr)
+{
+  ULONG rc;
+
+  /* This should not happen unless someone adds create_muxwait_sem()
+     calls without updating MAX_MUXWAIT_SEM. */
+
+  if (muxwait_sem_count >= MAX_MUXWAIT_SEM)
+    {
+      oprintf ("Too many MuxWait semaphores\r\n");
+      return ERROR_TOO_MANY_SEMAPHORES;
+    }
+
+  rc = DosCreateMuxWaitSem (NULL, psem, count, array, attr);
+  if (rc == 0)
+    muxwait_sem_table[muxwait_sem_count++] = *psem;
+  else
+    error (rc, "DosCreateMuxWaitSem");
+  return rc;
+}
+
+
+/* Close an MuxWait semaphore.
+
+   Note: This function is not reentrant! */
+
+void close_muxwait_sem (HMUX sem)
+{
+  ULONG i;
+
+  for (i = 0; i < muxwait_sem_count; ++i)
+    if (muxwait_sem_table[i] == sem)
+      {
+        muxwait_sem_table[i] = muxwait_sem_table[--muxwait_sem_count];
+        break;
+      }
+  DosCloseMuxWaitSem (sem);
+}
+
+
+/* Close all semaphores.  This function is called on termination of
+   emx.dll. */
+
+void term_semaphores (void)
+{
+  while (muxwait_sem_count != 0)
+    DosCloseMuxWaitSem (muxwait_sem_table[--muxwait_sem_count]);
+  while (event_sem_count != 0)
+    DosCloseEventSem (event_sem_table[--event_sem_count]);
+  while (mutex_sem_count != 0)
+    DosCloseMutexSem (mutex_sem_table[--mutex_sem_count]);
+}
+
+
+/* Reset the event semaphore SEM.  It's no error if the semaphore is
+   already reset.  Return the OS/2 error code. */
+
+ULONG reset_event_sem (HEV sem)
+{
+  ULONG rc, post_count;
+
+  rc = DosResetEventSem (sem, &post_count);
+  if (rc == ERROR_ALREADY_RESET)
+    rc = 0;
+  if (rc != 0)
+    error (rc, "DosResetEventSem");
+  return rc;
+}
+
+
+/* Lock the common data area.  This creates or opens the semaphore if
+   not already done. */
+
+void do_lock_common (void)
+{
+  ULONG rc;
+
+  if (!common_open)
+    {
+      common_open = TRUE;
+      rc = DosCreateMutexSem (common_mutex_name, &common_mutex,
+                              DC_SEM_SHARED, 0);
+      if (rc == ERROR_DUPLICATE_NAME)
+        rc = DosOpenMutexSem (common_mutex_name, &common_mutex);
+      if (rc == 0 && mutex_sem_count < MAX_MUTEX_SEM)
+        mutex_sem_table[mutex_sem_count++] = common_mutex;
+        
+    }
+  request_mutex (common_mutex);
+}
+
+
+/* Terminate the process, returning RC. */
+
+void quit (ULONG rc)
+{
+  kbd_stop ();
+  DosExit (EXIT_PROCESS, rc);
+}
+
+
+/* Return the value of a static system variable. */
+
+ULONG querysysinfo (ULONG index)
+{
+  ULONG value;
+
+  DosQuerySysInfo (index, index, &value, sizeof (value));
+  return value;
+}
+
+
+/* This function implements a subset of ANSI vsprintf().  Supported
+   format specifications are %s, %d, %u and %x, with optional
+   precision.  The default precision for %x is currently 8 (no caller
+   depends on this). */
+
+int vsprintf (char *dst, const char *fmt, va_list arg_ptr)
+{
+  char *d;
+  int prec, i;
+  unsigned u;
+  const char *s;
+
+  d = dst;
+  while (*fmt != 0)
+    if (*fmt != '%')
+      *d++ = *fmt++;
+    else if (fmt[1] == '%')
+      *d++ = '%', fmt += 2;
+    else
+      {
+        ++fmt; prec = -1;
+        if (*fmt == '.')
+          {
+            ++fmt; prec = 0;
+            while (*fmt >= '0' && *fmt <= '9')
+              prec = prec * 10 + (*fmt++ - '0');
+          }
+        switch (*fmt)
+          {
+          case 's':
+            s = va_arg (arg_ptr, char *);
+            if (prec == -1) prec = 1 << 30;
+            while (*s != 0 && prec > 0)
+              *d++ = *s++, --prec;
+            break;
+          case 'd':
+            i = va_arg (arg_ptr, int);
+            d += decn (d, i);
+            break;
+          case 'u':
+            u = va_arg (arg_ptr, unsigned);
+            d += udecn (d, u);
+            break;
+          case 'x':
+            u = va_arg (arg_ptr, unsigned);
+            if (prec == -1) prec = 8;
+            hexn (d, u, prec);
+            d += prec;
+            break;
+          }
+        ++fmt;
+      }
+  *d = 0;
+  return d - dst;
+}
+
+
+/* Simple version of sprintf().  See vsprintf() for supported format
+   specifications. */
+
+int sprintf (char *dst, const char *fmt, ...)
+{
+  int result;
+  va_list arg_ptr;
+
+  va_start (arg_ptr, fmt);
+  result = vsprintf (dst, fmt, arg_ptr);
+  va_end (arg_ptr);
+  return result;
+}
+
+
+/* Simple version of printf() with output to error output.  See
+   vsprintf() for supported format specifications. */
+
+void oprintf (const char *fmt, ...)
+{
+  va_list arg_ptr;
+  char buf[1024];
+  int len;
+  ULONG written;
+
+  va_start (arg_ptr, fmt);
+  len = vsprintf (buf, fmt, arg_ptr);
+  DosWrite (errout_handle, buf, len, &written);
+  va_end (arg_ptr);
+}
+
+
+/* Mark in _nls_ctype_tab all DBCS lead bytes with _NLS_DBCS_LEAD.
+   Note that this must be compatible to the C library's
+   _nls_is_dbcs_lead macro.  Return 0 or an OS/2 error code. */
+
+ULONG get_dbcs_lead (void)
+{
+  ULONG rc;
+  COUNTRYCODE cc;
+  BYTE lead[12];
+  unsigned i, j;
+
+  memset (_nls_ctype_tab, 0, 256);
+  cc.country = 0;
+  cc.codepage = 0;
+  rc = DosQueryDBCSEnv (sizeof (lead), &cc, (PCHAR)lead);
+  for (i = 0; i <= sizeof (lead) - 2; i += 2)
+    {
+      if (lead[i+0] == 0 && lead[i+1] == 0)
+        break;
+      for (j = lead[i+0]; j <= lead[i+1]; ++j)
+        _nls_ctype_tab[j] = _NLS_DBCS_LEAD;
+    }
+  return 0;
+}
+
+
+/* This version of stricmp() does not support locales. */
+
+int stricmp (const char *string1, const char *string2)
+{
+  int d;
+
+  for (;;)
+    {
+      d = tolower ((unsigned char)*string1)
+        - tolower ((unsigned char)*string2);
+      if (d != 0 || *string1 == 0 || *string2 == 0)
+        return d;
+      ++string1; ++string2;
+    }
+}
+
+
+/* Load a module.  This is a wrapper for DosLoadModule, saving the
+   coprocessor state.  The initialization code of SO32DLL.DLL and
+   TCP32DLL.DLL set the coprocessor control word to 0x362! */
+
+ULONG load_module (const char *mod_name, HMODULE *phmod)
+{
+  char state[108];
+  char obj[9];
+  ULONG rc;
+
+  __asm__ ("fnsave %0" : "=m"(state));
+  rc = DosLoadModule (obj, sizeof (obj), mod_name, phmod);
+  __asm__ ("frstor %0" : "=m"(state));
+  return rc;
+}
+
+
+/* Return TRUE iff the region of memory starting at START is
+   readable. */
+
+int verify_memory (ULONG start, ULONG size)
+{
+  ULONG rc, cb, flag;
+
+  while (size != 0)
+    {
+      cb = size;
+      rc = DosQueryMem ((PVOID)start, &cb, &flag);
+      if (rc != 0)
+        return FALSE;
+      if (!(flag & (PAG_COMMIT|PAG_SHARED)))
+        return FALSE;
+      if (flag & PAG_FREE)
+        return FALSE;           /* Should not happen */
+      if (!(flag & PAG_READ))
+        return FALSE;
+      if (cb == 0 || cb > size)
+        return FALSE;           /* Should not happen */
+      start += cb; size -= cb;
+    }
+  return TRUE;
+}
Index: trunk/src/emx/src/os2/version.h
===================================================================
--- trunk/src/emx/src/os2/version.h	(revision 18)
+++ trunk/src/emx/src/os2/version.h	(revision 18)
@@ -0,0 +1,28 @@
+/* version.h -- Version number
+   Copyright (c) 1994-2000 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define VERSION         "0.9d"
+#define REV_INDEX       61
Index: trunk/src/emx/src/os2/wrapper.c
===================================================================
--- trunk/src/emx/src/os2/wrapper.c	(revision 18)
+++ trunk/src/emx/src/os2/wrapper.c	(revision 18)
@@ -0,0 +1,58 @@
+/* wrapper.c -- 32-bit wrappers for 16-bit functions
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#include <os2emx.h>
+#include "wrapper.h"
+
+USHORT _THUNK_FUNCTION (Dos16FlagProcess) ();
+
+USHORT DosFlagProcess (PID pid, USHORT fScope, USHORT usFlagNum,
+                       USHORT usFlagArg)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (2+2+2+2);
+           _THUNK_SHORT (pid);
+           _THUNK_SHORT (fScope);
+           _THUNK_SHORT (usFlagNum);
+           _THUNK_SHORT (usFlagArg);
+           _THUNK_CALL (Dos16FlagProcess)));
+}
+
+
+USHORT _THUNK_FUNCTION (Dos16SetSigHandler) ();
+
+USHORT DosSetSigHandler (_far16ptr pfnSigHandler, _far16ptr *ppfnPrev,
+                         PUSHORT pfAction, USHORT fAction, USHORT usSigNum)
+{
+  return ((USHORT)
+          (_THUNK_PROLOG (4+4+4+2+2);
+           _THUNK_FAR16 (pfnSigHandler);
+           _THUNK_FLAT (ppfnPrev);
+           _THUNK_FLAT (pfAction);
+           _THUNK_SHORT (fAction);
+           _THUNK_SHORT (usSigNum);
+           _THUNK_CALL (Dos16SetSigHandler)));
+}
Index: trunk/src/emx/src/os2/wrapper.h
===================================================================
--- trunk/src/emx/src/os2/wrapper.h	(revision 18)
+++ trunk/src/emx/src/os2/wrapper.h	(revision 18)
@@ -0,0 +1,41 @@
+/* wrapper.h -- 32-bit wrappers for 16-bit functions
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#include <os2thunk.h>
+
+#define PFLG_A                  0
+
+#define FLGP_SUBTREE            0
+#define FLGP_PID                1
+
+#define SIG_PFLG_A              5
+
+#define SIGA_ACCEPT             2
+
+USHORT DosFlagProcess (PID pid, USHORT fScope, USHORT usFlagNum,
+    USHORT usFlagArg);
+USHORT DosSetSigHandler (_far16ptr pfnSigHandler, _far16ptr *ppfnPrev,
+    PUSHORT pfAction, USHORT fAction, USHORT usSigNum);
Index: trunk/src/emx/src/os2/xf86sup.c
===================================================================
--- trunk/src/emx/src/os2/xf86sup.c	(revision 18)
+++ trunk/src/emx/src/os2/xf86sup.c	(revision 18)
@@ -0,0 +1,527 @@
+/* xf86sup.c -- Support for Holger Veit's xf86sup device driver
+   Copyright (c) 1995-1996 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define INCL_DOSDEVICES
+#define INCL_DOSDEVIOCTL
+#define INCL_DOSERRORS
+#define INCL_DOSSEMAPHORES
+#include <os2emx.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/so_ioctl.h>
+#include <sys/termio.h>         /* SysV */
+#include <termios.h>            /* POSIX.1 */
+#include "emxdll.h"
+#include "files.h"
+#include "select.h"
+#include "xf86sup.h"
+#include "clib.h"
+
+
+ULONG xf86sup_query (ULONG handle, ULONG *pflags)
+{
+  struct xf86sup_drvid drvid;
+  ULONG rc, data_length;
+  my_file *d;
+
+  memset (&drvid, 0, sizeof (drvid));
+  data_length = sizeof (drvid);
+  rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_DRVID,
+                    NULL, 0, NULL,
+                    &drvid, data_length, &data_length);
+  if (rc != 0) return rc;
+  if (data_length != sizeof (drvid)
+      || drvid.magic != XF86SUP_MAGIC)
+    return ERROR_BAD_DEV_TYPE;
+  switch (drvid.id)
+    {
+    case XF86SUP_ID_PTY:
+    case XF86SUP_ID_TTY:
+    case XF86SUP_ID_CONSOLE:
+    case XF86SUP_ID_PMAP:
+    case XF86SUP_ID_FASTIO:
+    case XF86SUP_ID_PTMS:
+      break;
+    default:
+      return ERROR_BAD_DEV_TYPE;
+    }
+  *pflags = HF_XF86SUP;
+  d = GET_FILE (handle);
+  d->x.xf86sup.id = drvid.id;
+  d->x.xf86sup.sem_open = FALSE;
+  d->x.xf86sup.sem = 0;
+  return 0;
+}
+
+
+int xf86sup_avail (ULONG handle, int *errnop)
+{
+  ULONG rc, data_length, avail;
+
+  data_length = sizeof (avail);
+  rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_FIONREAD,
+                    NULL, 0, NULL,
+                    &avail, data_length, &data_length);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  if (data_length != sizeof (avail))
+    {
+      *errnop = EINVAL;
+      return -1;
+    }
+  *errnop = 0;
+  return (int)avail;
+}
+
+
+/* __fcntl() for a tty or pty handle.  This function is called for
+   F_SETFL only, and only if O_NDELAY was changed. */
+
+
+int xf86sup_fcntl (ULONG handle, ULONG request, ULONG arg, int *errnop)
+{
+  int on;
+
+  on = arg & O_NDELAY;
+  return xf86sup_ioctl (handle, FIONBIO, (ULONG)&on, errnop);
+}
+
+
+
+/* Common code for xf86sup_termio_get() and xf86sup_termios_get().
+   Returns 0 on success, -1 on error.  Always sets *ERRNOP. */
+
+static int xf86sup_tiocgeta (ULONG handle, struct xf86sup_termios *p,
+                             int *errnop)
+{
+  ULONG rc, data_length;
+
+  data_length = sizeof (*p);
+  rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_TIOCGETA,
+                    NULL, 0, NULL,
+                    p, data_length, &data_length);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Handle the TCGETA ioctl.  Returns 0 on success, -1 on error.
+   Always sets *ERRNOP.*/
+
+static int xf86sup_termio_get (ULONG handle, struct termio *p, int *errnop)
+{
+  struct xf86sup_termios xtio;
+
+  if (xf86sup_tiocgeta (handle, &xtio, errnop) != 0)
+    return -1;
+  p->c_iflag = xtio.c_iflag;
+  p->c_oflag = xtio.c_oflag;
+  p->c_cflag = xtio.c_cflag;
+  p->c_lflag = xtio.c_lflag;
+  p->c_line = 0;
+  /* Note that this drops three characters! */
+  memcpy (p->c_cc, xtio.c_cc, NCC);
+  return 0;
+}
+
+
+/* Handle the _TCGA ioctl for tcgetattr().  Returns 0 on success, -1
+   on error.  Always sets *ERRNOP. */
+
+static int xf86sup_termios_get (ULONG handle, struct termios *p, int *errnop)
+{
+  struct xf86sup_termios xtio;
+
+  if (xf86sup_tiocgeta (handle, &xtio, errnop) != 0)
+    return -1;
+  p->c_iflag = xtio.c_iflag;
+  p->c_oflag = xtio.c_oflag;
+  p->c_cflag = xtio.c_cflag;
+  p->c_lflag = xtio.c_lflag;
+  memcpy (p->c_cc, xtio.c_cc, NCCS);
+  return 0;
+}
+
+
+/* Common code for xf86sup_termio_set() and xf86sup_termios_set().
+   Returns 0 on success, -1 on error.  Always sets *ERRNOP. */
+
+static int xf86sup_tiocseta (ULONG handle, struct xf86sup_termios *p,
+                             ULONG request, int *errnop)
+{
+  ULONG rc, data_length;
+
+  data_length = sizeof (*p);
+  rc = DosDevIOCtl (handle, IOCTL_XF86SUP, request,
+                    p, data_length, &data_length,
+                    NULL, 0, NULL);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+  *errnop = 0;
+  return 0;
+}
+
+
+/* Handle the TCSETA, TCSETAF, and TCSETAW ioctls.  Returns 0 on
+   success, -1 on error.  Always sets *ERRNOP. */
+
+static int xf86sup_termio_set (ULONG handle, const struct termio *p,
+                               ULONG request, int *errnop)
+{
+  struct xf86sup_termios xtio;
+
+  /* Get the current settings.  This is required for VSUSP, VSTOP, and
+     VSTART, which are not provided in `struct termio'. */
+
+  if (xf86sup_tiocgeta (handle, &xtio, errnop) != 0)
+    return -1;
+  xtio.c_iflag = p->c_iflag;
+  xtio.c_oflag = p->c_oflag;
+  xtio.c_cflag = p->c_cflag;
+  xtio.c_lflag = p->c_lflag;
+  /* This leaves alone the last three characters! */
+  memcpy (xtio.c_cc, p->c_cc, NCC);
+  return xf86sup_tiocseta (handle, &xtio, request, errnop);
+}
+
+
+/* Handle the _TCSANOW, _TCSADRAIN, and _TCSAFLUSH ioctls for
+   tcsetattr().  Returns 0 on success, -1 on error.  Always sets
+   *ERRNOP. */
+
+static int xf86sup_termios_set (ULONG handle, const struct termios *p,
+                                ULONG request, int *errnop)
+{
+  struct xf86sup_termios xtio;
+
+  memset (&xtio, 0, sizeof (xtio)); /* Clear reserved fields */
+  xtio.c_iflag = p->c_iflag;
+  xtio.c_oflag = p->c_oflag;
+  xtio.c_cflag = p->c_cflag;
+  xtio.c_lflag = p->c_lflag;
+  memcpy (xtio.c_cc, p->c_cc, NCCS);
+  return xf86sup_tiocseta (handle, &xtio, request, errnop);
+}
+
+
+/* __ioct2l() for a tty or pty handle. */
+
+int xf86sup_ioctl (ULONG handle, ULONG request, ULONG arg, int *errnop)
+{
+  int n;
+  ULONG rc, parm_length;
+
+  switch (request)
+    {
+    case FGETHTYPE:
+      *(int *)arg = HT_DEV_OTHER; /* TODO */
+      break;
+
+    case FIONREAD:
+      n = xf86sup_avail (handle, errnop);
+      if (n == -1)
+        return -1;
+      *(int *)arg = n;
+      break;
+
+    case FIONBIO:
+      parm_length = sizeof (int);
+      rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_FIONBIO,
+                        (PVOID)arg, parm_length, &parm_length,
+                        NULL, 0, NULL);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      if (*(int *)arg)
+        handle_flags[handle] |= HF_NDELAY;
+      else
+        handle_flags[handle] &= ~HF_NDELAY;
+      break;
+
+    case TCGETA:
+      return xf86sup_termio_get (handle, (struct termio *)arg, errnop);
+
+    case TCSETA:
+      return xf86sup_termio_set (handle, (const struct termio *)arg,
+                                 XF86SUP_TIOCSETA, errnop);
+
+    case TCSETAF:
+      return xf86sup_termio_set (handle, (const struct termio *)arg,
+                                 XF86SUP_TIOCSETAF, errnop);
+
+    case TCSETAW:
+      return xf86sup_termio_set (handle, (const struct termio *)arg,
+                                 XF86SUP_TIOCSETAW, errnop);
+
+    case TCFLSH:
+      parm_length = sizeof (int);
+      rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_TIOCFLUSH,
+                        &arg, parm_length, &parm_length,
+                        NULL, 0, NULL);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      break;
+
+    case TCSBRK:
+      rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_TIOCDRAIN,
+                        NULL, 0, NULL,
+                        NULL, 0, NULL);
+      if (rc != 0)
+        {
+          *errnop = set_error (rc);
+          return -1;
+        }
+      break;
+
+    case TCXONC:
+      /* Flow control. */
+      break;
+
+    case _TCGA:
+      return xf86sup_termios_get (handle, (struct termios *)arg, errnop);
+
+    case _TCSANOW:
+      return xf86sup_termios_set (handle, (const struct termios *)arg,
+                                  XF86SUP_TIOCSETA, errnop);
+
+    case _TCSADRAIN:
+      return xf86sup_termios_set (handle, (const struct termios *)arg,
+                                  XF86SUP_TIOCSETAW, errnop);
+
+    case _TCSAFLUSH:
+      return xf86sup_termios_set (handle, (const struct termios *)arg,
+                                  XF86SUP_TIOCSETAF, errnop);
+
+    default:
+      *errnop = EINVAL;
+      return -1;
+    }
+
+  /* Function successfully completed. */
+
+  *errnop = 0;
+  return 0;
+}
+
+
+/* __select(): Add a semaphore for a pty, tty, or /dev/console$ handle,
+   to be posted when data becomes ready for reading. */
+
+int xf86sup_select_add_read (struct select_data *d, int fd)
+{
+  HEV sem;
+  my_file *f;
+  int i;
+  ULONG rc, parm_length, data_length, arm_on;
+  struct xf86sup_selreg selreg;
+
+  if (!IS_VALID_FILE (fd))
+    return EBADF;
+
+  f = GET_FILE (fd);
+  if (f->x.xf86sup.id != XF86SUP_ID_PTY && f->x.xf86sup.id != XF86SUP_ID_TTY
+      && f->x.xf86sup.id != XF86SUP_ID_CONSOLE)
+    return 0;                   /* Silently ignore */
+  if (f->x.xf86sup.sem_open)
+    sem = f->x.xf86sup.sem;
+  else
+    {
+      /* Check whether a semaphore is already registered.  As the
+         semaphore handles to be registered are null (invalid) and
+         xf86sup.sys tries to open the new semaphore handles, we'll
+         get ERROR_INVALID_PARAMETER if there are no semaphores
+         registered. */
+
+      selreg.rsel = selreg.xsel = 0;
+      selreg.code = 0;
+      parm_length = sizeof (selreg);
+      data_length = sizeof (selreg);
+      rc = DosDevIOCtl (fd, IOCTL_XF86SUP, XF86SUP_SELREG,
+                        &selreg, parm_length, &parm_length,
+                        &selreg, data_length, &data_length);
+      if (rc == 0 && selreg.rsel != 0)
+        {
+          /* There is a semaphore registered.  Open it. */
+
+          sem = (HEV)selreg.rsel;
+          rc = DosOpenEventSem (NULL, &sem);
+          if (rc != 0) return set_error (rc);
+          f->x.xf86sup.sem = sem;
+          f->x.xf86sup.sem_open = TRUE;
+        }
+      else
+        {
+          /* Create a semaphore which will be registered with
+             xf86sup.sys.  Don't use create_event_sem() as the
+             semaphore will stick forever (and to avoid overflowing
+             the semaphore table). */
+
+          if (DosCreateEventSem (NULL, &sem, DC_SEM_SHARED, FALSE) != 0)
+            return EINVAL;
+
+          /* Register the semaphore with xf86sup.sys.  Unfortunately,
+             xf86sup.sys does not accept null handles, therefore we
+             use the semaphore also for xsel.  TODO: This will cause
+             problems with other processes trying to register two
+             distinct semaphores with this pty/tty pair in the
+             future. */
+
+          selreg.rsel = (ULONG)sem; selreg.xsel = (ULONG)sem;
+          selreg.code = 0;
+          parm_length = sizeof (selreg);
+          data_length = sizeof (selreg);
+          rc = DosDevIOCtl (fd, IOCTL_XF86SUP, XF86SUP_SELREG,
+                            &selreg, parm_length, &parm_length,
+                            &selreg, data_length, &data_length);
+          if (rc != 0)
+            {
+              DosCloseEventSem (sem);
+              return set_error (rc);
+            }
+
+          /* If someone else has registered a semaphore in the
+             meantime, use that semaphore. */
+
+          if (selreg.code & XF86SUP_SEL_READ)
+            {
+              DosCloseEventSem (sem);
+              sem = (HEV)selreg.rsel;
+            }
+          f->x.xf86sup.sem = sem;
+          f->x.xf86sup.sem_open = TRUE;
+        }
+    }
+
+  /* The semaphore handle is now in SEM.  Add the semaphore to the
+     MuxWait list, unless it's already in the list. */
+
+  for (i = 0; i < d->sem_count; ++i)
+    if (d->list[i].hsemCur == (HSEM)sem)
+      break;
+  if (i >= d->sem_count)
+    {
+      /* The semaphore is not yet in the list.  Add it. */
+
+      if (d->sem_count >= d->max_sem)
+        return EINVAL;
+      else
+        {
+          d->list[d->sem_count].hsemCur = (HSEM)sem;
+          d->list[d->sem_count].ulUser = 0;
+          ++d->sem_count;
+        }
+    }
+
+  /* Arm the semaphore.  Arming a semaphore multiple times doesn't
+     hurt as we first arm all semaphores, then poll all handles. */
+
+  parm_length = sizeof (arm_on);
+  arm_on = XF86SUP_SEL_READ;
+  rc = DosDevIOCtl (fd, IOCTL_XF86SUP, XF86SUP_SELARM,
+                    &arm_on, parm_length, &parm_length,
+                    NULL, 0, NULL);
+  if (rc != 0)
+    return set_error (rc);
+  return 0;
+}
+
+
+int xf86sup_ttyname (char *dst, ULONG dst_size, ULONG handle, int *errnop)
+{
+  ULONG rc, parm_length, data_length;
+  char buf[14], *p;
+
+  parm_length = 0;
+  data_length = sizeof (buf);
+  rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_NAME,
+                    NULL, parm_length, &parm_length,
+                    buf, data_length, &data_length);
+  if (rc != 0)
+    {
+      *errnop = set_error (rc);
+      return -1;
+    }
+
+  /* There's no point in handling DBCS characters here. */
+
+  for (p = buf; *p != 0; ++p)
+    if (*p == '\\')
+      *p = '/';
+  return set_ttyname (dst, dst_size, buf, errnop);
+}
+
+
+ULONG xf86sup_uncond_enadup (ULONG handle, ULONG on)
+{
+  ULONG data_length;
+
+  data_length = sizeof (on);
+  return DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_ENADUP,
+                      &on, data_length, &data_length,
+                      NULL, 0, NULL);
+}
+
+
+ULONG xf86sup_maybe_enadup (ULONG handle, ULONG on)
+{
+  if (handle < handle_count
+      && (handle_flags[handle] & (HF_OPEN|HF_XF86SUP))
+      && IS_VALID_FILE (handle)
+      && GET_FILE (handle)->x.xf86sup.id == XF86SUP_ID_PTY)
+    return xf86sup_uncond_enadup (handle, on);
+  else
+    return 0;
+}
+
+
+void xf86sup_all_enadup (ULONG on)
+{
+  ULONG i;
+
+  for (i = 0; i < handle_count; ++i)
+    if ((handle_flags[i] & (HF_OPEN|HF_XF86SUP))
+        && IS_VALID_FILE (i)
+        && GET_FILE (i)->x.xf86sup.id == XF86SUP_ID_PTY)
+      xf86sup_uncond_enadup (i, on);
+}
Index: trunk/src/emx/src/os2/xf86sup.h
===================================================================
--- trunk/src/emx/src/os2/xf86sup.h	(revision 18)
+++ trunk/src/emx/src/os2/xf86sup.h	(revision 18)
@@ -0,0 +1,76 @@
+/* xf86sup.h -- Definitions for Holger Veit's xf86sup device driver
+   Copyright (c) 1995-1996 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+As special exception, emx.dll can be distributed without source code
+unless it has been changed.  If you modify emx.dll, this exception
+no longer applies and you must remove this paragraph from all source
+files for emx.dll.  */
+
+
+#define IOCTL_XF86SUP           0x76
+
+#define XF86SUP_TIOCSETA        0x48
+#define XF86SUP_TIOCSETAW       0x49
+#define XF86SUP_TIOCSETAF       0x4a
+#define XF86SUP_TIOCFLUSH       0x4c
+#define XF86SUP_TIOCDRAIN       0x4e
+#define XF86SUP_ENADUP          0x5a
+#define XF86SUP_NAME            0x60
+#define XF86SUP_DRVID           0x61
+#define XF86SUP_FIONREAD        0x64
+#define XF86SUP_TIOCGETA        0x65
+#define XF86SUP_FIONBIO         0x6a
+#define XF86SUP_SELREG          0x6b
+#define XF86SUP_SELARM          0x6c
+
+#define XF86SUP_MAGIC           0x36384f58
+#define XF86SUP_ID_PTY          1
+#define XF86SUP_ID_TTY          2
+#define XF86SUP_ID_CONSOLE      3
+#define XF86SUP_ID_PMAP         4
+#define XF86SUP_ID_FASTIO       5
+#define XF86SUP_ID_PTMS         6
+
+#define XF86SUP_SEL_READ        0x01
+#define XF86SUP_SEL_EXCEPT      0x02
+
+struct xf86sup_drvid
+{
+  ULONG magic;
+  ULONG id;
+  ULONG version;
+};
+
+struct xf86sup_selreg
+{
+  ULONG	rsel;
+  ULONG	xsel;
+  ULONG	code;
+};
+
+struct xf86sup_termios
+{
+  unsigned short c_iflag;
+  unsigned short c_oflag;
+  unsigned short c_cflag;
+  unsigned short c_lflag;
+  unsigned char  c_cc[NCCS];
+  long           c_reserved[4];
+};
Index: trunk/src/emx/src/pmgdb/COPYING
===================================================================
--- trunk/src/emx/src/pmgdb/COPYING	(revision 18)
+++ trunk/src/emx/src/pmgdb/COPYING	(revision 18)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: trunk/src/emx/src/pmgdb/annotati.cc
===================================================================
--- trunk/src/emx/src/pmgdb/annotati.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/annotati.cc	(revision 18)
@@ -0,0 +1,276 @@
+/* annotati.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <os2.h>
+#include <string.h>
+#include <io.h>
+#include "annotati.h"
+
+
+struct annotation::node
+{
+  node *next;
+  char *str;
+  int len;
+  annotation::code c;
+};
+
+
+annotation::annotation ()
+{
+  buf = NULL; buf_size = 0; buf_in = buf_out = 0;
+  for (int i = 0; i < hash_size; ++i)
+    table[i] = NULL;
+  init (arg_begin, "arg-begin");
+  init (arg_end, "arg-end");
+  init (arg_name_end, "arg-name-end");
+  init (arg_value, "arg-value");
+  init (array_section_begin, "array-section-begin");
+  init (array_section_end, "array-section-end");
+  init (breakpoint, "breakpoint");
+  init (breakpoint_new, "breakpoint-new");
+  init (breakpoints_headers, "breakpoints-headers");
+  init (breakpoints_table, "breakpoints-table");
+  init (breakpoints_table_end, "breakpoints-table-end");
+  init (breakpoints_invalid, "breakpoints-invalid");
+  init (commands, "commands");
+  init (display_begin, "display-begin");
+  init (display_delete, "display-delete");
+  init (display_disable, "display-disable");
+  init (display_enable, "display-enable");
+  init (display_end, "display-end");
+  init (display_expression, "display-expression");
+  init (display_expression_end, "display-expression-end");
+  init (display_format, "display-format");
+  init (display_number_end, "display-number-end");
+  init (display_value, "display-value");
+  init (error_begin, "error-begin");
+  init (error, "error");
+  init (elt, "elt");
+  init (elt_rep, "elt-rep");
+  init (elt_rep_end, "elt-rep-end");
+  init (exec_file, "exec-file");
+  init (exec_file_invalid, "exec-file-invalid");
+  init (exited, "exited");
+  init (field, "field");
+  init (field_begin, "field-begin");
+  init (field_end, "field-end");
+  init (field_name_end, "field-name-end");
+  init (field_value, "field-value");
+  init (frame, "frame");
+  init (frame_args, "frame-args");
+  init (frame_begin, "frame-begin");
+  init (frame_end, "frame-end");
+  init (frame_function_name, "frame-function-name");
+  init (frame_source_begin, "frame-source-begin");
+  init (frame_source_end, "frame-source-end");
+  init (frame_source_file, "frame-source-file");
+  init (frame_source_file_end, "frame-source-file-end");
+  init (frame_source_line, "frame-source-line");
+  init (frames_invalid, "frames-invalid");
+  init (overload_choice, "overload-choice");
+  init (prompt, "prompt");
+  init (prompt_for_continue, "prompt-for-continue");
+  init (pre_commands, "pre-commands");
+  init (pre_overload_choice, "pre-overload-choice");
+  init (pre_prompt, "pre-prompt");
+  init (pre_prompt_for_continue, "pre-prompt-for-continue");
+  init (pre_query, "pre-query");
+  init (post_commands, "post-commands");
+  init (post_overload_choice, "post-overload-choice");
+  init (post_prompt, "post-prompt");
+  init (post_prompt_for_continue, "post-prompt-for-continue");
+  init (post_query, "post-query");
+  init (query, "query");
+  init (quit, "quit");
+  init (record, "record");
+  init (show_value, "show-value");
+  init (show_value_end, "show-value-end");
+  init (starting, "starting");
+  init (stopped, "stopped");
+  init (signalled, "signalled");
+  init (source, "source");
+  init (source_file, "source-file");
+  init (source_location, "source-location");
+  init (source_location_end, "source-location-end");
+  init (signal, "signal");
+  init (signal_handler_caller, "signal-handler-caller");
+  init (signal_name, "signal-name");
+  init (signal_name_end, "signal-name-end");
+  init (signal_string, "signal-string");
+  init (signal_string_end, "signal-string-end");
+  init (thread_add, "thread-add");
+  init (thread_disable, "thread-disable");
+  init (thread_enable, "thread-enable");
+  init (thread_end, "thread-end");
+  init (thread_switch, "thread-switch");
+  init (value_begin, "value-begin");
+  init (value_end, "value-end");
+  init (value_history_begin, "value-history-begin");
+  init (value_history_end, "value-history-end");
+  init (value_history_value, "value-history-value");
+  init (watchpoint, "watchpoint");
+}
+
+
+annotation::~annotation ()
+{
+  node *next;
+  for (int h = 0; h < hash_size; ++h)
+    for (node *p = table[h]; p != NULL; p = next)
+      {
+        next = p->next;
+        delete[] p->str;
+        delete p;
+      }
+  delete[] buf;
+}
+
+
+unsigned annotation::hash (const char *s, int len)
+{
+  unsigned h = 0;
+  for (int i = 0; i < len; ++i)
+    h = (h << 1) ^ (unsigned char)s[i];
+  return h % hash_size;
+}
+
+
+void annotation::init (code c, const char *s)
+{
+  int len = strlen (s);
+  unsigned h = hash (s, len);
+  node *n = new node;
+  n->c = c;
+  n->len = len;
+  n->str = new char[len + 1];
+  memcpy (n->str, s, len + 1);
+  n->next = table[h];
+  table[h] = n;
+}
+
+
+void annotation::start (int in_fd)
+{
+  fd = in_fd;
+}
+
+
+void annotation::parse (const char *s, int len)
+{
+  const char *args = (const char *)memchr (s, ' ', len);
+  int keyword_len = args == NULL ? len : args - s;
+  unsigned h = hash (s, keyword_len);
+  last_code = UNKNOWN; last_args = s; last_args_len = len;
+  const node *n;
+  for (n = table[h]; n != NULL; n = n->next)
+    if (n->len == keyword_len && memcmp (n->str, s, keyword_len) == 0)
+      break;
+  if (n != NULL)
+    {
+      last_code = n->c;
+      if (args != NULL)
+        {
+          last_args = args + 1;
+          last_args_len = len - (keyword_len + 1);
+        }
+      else
+        {
+          last_args = NULL;
+          last_args_len = 0;
+        }
+    }
+}
+
+
+bool annotation::fill ()
+{
+  if (buf_in == buf_out)
+    buf_in = buf_out = 0;
+  if (buf_in == buf_size)
+    {
+      buf_size += 512;
+      char *new_buf = new char [buf_size];
+      memcpy (new_buf, buf, buf_in);
+      delete[] buf;
+      buf = new_buf;
+    }
+  int n = read (fd, buf + buf_in, buf_size - buf_in);
+  if (n <= 0)
+    return false;
+  buf_in += n;
+  return true;
+}
+
+
+annotation::code annotation::get_next ()
+{
+  if (buf_in == buf_out && !fill ())
+    return READ_ERROR;
+  const char *nl;
+  int text_len = 0;
+  for (;;)
+    {
+      const char *start = buf + buf_out + text_len;
+      nl = (const char *)memchr (start, '\n', buf_in - (buf_out + text_len));
+      if (nl == NULL)
+        {
+          text_len = buf_in - buf_out;
+          break;
+        }
+      text_len += (nl - start);
+      int pos = nl - buf;
+
+      if (pos + 1 >= buf_in && !fill ())
+        return READ_ERROR;
+      if (buf[pos+1] != 0x1a)
+        ++text_len;             // Beware of \n\n^Z^Z!
+      else
+        {
+          if (pos + 2 >= buf_in && !fill ())
+            return READ_ERROR;
+          if (buf[pos+2] != 0x1a)
+            ++text_len;         // Beware of \n^Z\n^Z^Z
+          else
+            break;              // Annotation found
+        }
+    }
+
+  if (text_len != 0)
+    {
+      last_code = TEXT;
+      last_text = buf + buf_out; last_text_len = text_len;
+      last_args = NULL; last_args_len = 0;
+      buf_out += text_len;
+      return last_code;
+    }
+
+  while ((nl = (const char *)memchr (buf + buf_out + 3, '\n',
+                                     buf_in - (buf_out + 3))) == NULL)
+    if (!fill ())
+      return READ_ERROR;
+  last_text = buf + buf_out + 3;
+  last_text_len = nl - last_text;
+  parse (last_text, last_text_len);
+  buf[buf_out + 3 + last_text_len] = 0;
+  buf_out = (nl + 1) - buf;
+  return last_code;
+}
Index: trunk/src/emx/src/pmgdb/annotati.h
===================================================================
--- trunk/src/emx/src/pmgdb/annotati.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/annotati.h	(revision 18)
@@ -0,0 +1,154 @@
+/* annotati.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class annotation
+{
+public:
+
+  enum code
+  {
+    UNKNOWN,
+    TEXT,
+    READ_ERROR,
+    arg_begin,
+    arg_end,
+    arg_name_end,
+    arg_value,
+    array_section_begin,
+    array_section_end,
+    breakpoint,
+    breakpoint_new,
+    breakpoints_headers,
+    breakpoints_table,
+    breakpoints_table_end,
+    breakpoints_invalid,
+    commands,
+    display_begin,
+    display_delete,
+    display_disable,
+    display_enable,
+    display_end,
+    display_expression,
+    display_expression_end,
+    display_format,
+    display_number_end,
+    display_value,
+    error_begin,
+    error,
+    elt,
+    elt_rep,
+    elt_rep_end,
+    exec_file,
+    exec_file_invalid,
+    exited,
+    field,
+    field_begin,
+    field_end,
+    field_name_end,
+    field_value,
+    frame,
+    frame_args,
+    frame_begin,
+    frame_end,
+    frame_function_name,
+    frame_source_begin,
+    frame_source_end,
+    frame_source_file,
+    frame_source_file_end,
+    frame_source_line,
+    frames_invalid,
+    overload_choice,
+    prompt,
+    prompt_for_continue,
+    pre_commands,
+    pre_overload_choice,
+    pre_prompt,
+    pre_prompt_for_continue,
+    pre_query,
+    post_commands,
+    post_overload_choice,
+    post_prompt,
+    post_prompt_for_continue,
+    post_query,
+    query,
+    quit,
+    record,
+    show_value,
+    show_value_end,
+    starting,
+    stopped,
+    signalled,
+    source,
+    source_file,
+    source_location,
+    source_location_end,
+    signal,
+    signal_handler_caller,
+    signal_name,
+    signal_name_end,
+    signal_string,
+    signal_string_end,
+    thread_add,
+    thread_disable,
+    thread_enable,
+    thread_end,
+    thread_switch,
+    value_begin,
+    value_end,
+    value_history_begin,
+    value_history_end,
+    value_history_value,
+    watchpoint
+  };
+
+  annotation ();
+  ~annotation ();
+  void start (int fd);
+  code get_next ();
+  code get_code ()        const { return last_code; }
+  const char *get_text () const { return last_text; }
+  int get_text_len ()     const { return last_text_len; }
+  const char *get_args () const { return last_args; }
+  int get_args_len ()     const { return last_args_len; }
+
+private:
+
+  enum
+  {
+    hash_size = 97
+  } constants;
+
+  struct node;
+
+  unsigned hash (const char *s, int len);
+  void init (code c, const char *s);
+  void parse (const char *s, int len);
+  bool fill ();
+
+  int fd;
+  node *table[hash_size];
+  code last_code;
+  const char *last_text, *last_args;
+  int last_args_len, last_text_len;
+  int buf_size;
+  int buf_in, buf_out;
+  char *buf;
+};
Index: trunk/src/emx/src/pmgdb/breakpoi.cc
===================================================================
--- trunk/src/emx/src/pmgdb/breakpoi.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/breakpoi.cc	(revision 18)
@@ -0,0 +1,855 @@
+/* breakpoi.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>              // sprintf()
+#include <stdarg.h>
+#include <string.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "pmgdb.h"
+#include "help.h"
+#include "breakpoi.h"
+#include "srcfiles.h"
+#include "annotati.h"
+#include "capture.h"
+#include "gdbio.h"
+#include "command.h"
+
+breakpoint::breakpoint ()
+{
+  number = 0;
+  type = BPT_UNKNOWN;
+  disposition = BPD_UNKNOWN;
+  enable = false;
+  address = 0;
+  lineno = 0;
+  ignore = 0;
+}
+
+
+breakpoint::breakpoint (const breakpoint &src)
+{
+  copy (src);
+}
+
+
+breakpoint &breakpoint::operator = (const breakpoint &src)
+{
+  copy (src);
+  return *this;
+}
+
+
+// Note: Does not copy next:
+
+void breakpoint::copy (const breakpoint &src)
+{
+  number = src.number;
+  type = src.type;
+  disposition = src.disposition;
+  enable = src.enable;
+  address = src.address;
+  source = src.source;
+  lineno = src.lineno;
+  condition = src.condition;
+  ignore = src.ignore;
+}
+
+
+breakpoint::~breakpoint ()
+{
+}
+
+
+bool breakpoint::operator == (const breakpoint b) const
+{
+  return (number == b.number
+          && type == b.type
+          && disposition == b.disposition
+          && enable == b.enable
+          && address == b.address
+          && lineno == b.lineno
+          && source == b.source
+          && condition == b.condition
+          && ignore == b.ignore);
+}
+
+
+void breakpoint::set_disposition (const char *s)
+{
+  if (s[0] == 'd' && s[1] == 'e') // "del"
+    disposition = BPD_DEL;
+  else if (s[0] == 'd' && s[1] == 'i') // "dis"
+    disposition = BPD_DIS;
+  else if (s[0] == 'k')
+    disposition = BPD_KEEP;     // "keep"
+  else
+    disposition = BPD_UNKNOWN;
+}
+
+
+const char *breakpoint::get_disposition_as_string () const
+{
+  switch (disposition)
+    {
+    case BPD_DEL:
+      return "del";
+    case BPD_DIS:
+      return "dis";
+    case BPD_KEEP:
+      return "keep";
+    default:
+      return "?";
+    }
+}
+
+
+bool breakpoint::set_from_capture (const capture &capt)
+{
+  if (!(capt.bpt_number.is_set ()
+        && capt.bpt_enable.is_set ()
+        && capt.bpt_address.is_set ()
+        && capt.bpt_disposition.is_set ()
+        && capt.bpt_what.is_set ()))
+    return false;
+
+  set_number (capt.bpt_number.get ());
+  set_address (capt.bpt_address.get ());
+  set_enable (capt.bpt_enable.get ());
+  set_disposition (capt.bpt_disposition.get ());
+  if (capt.bpt_condition.is_set ())
+    set_condition (capt.bpt_condition.get ());
+  if (capt.bpt_ignore.is_set ())
+    set_ignore (capt.bpt_ignore.get ());
+  else
+    set_ignore (0);
+
+  const char *p = capt.bpt_what.get ();
+  // "in main at source.c:217 "
+  if (strncmp (p, "in ", 3) == 0)
+    {
+      p += 3;
+      char *end = strstr (p, " at ");
+      if (end == NULL)
+        p = strchr (p, ' ');
+      if (end == NULL)
+        p = end;
+      else
+        p = end + 1;
+    }
+  if (strncmp (p, "at ", 3) == 0)
+    {
+      p += 3;
+      const char *colon = p;
+      while (*colon != 0 && *colon != ':' && *colon != ' ' && *colon != '\n')
+        ++colon;
+      if (*colon == ':')
+        {
+          char *end;
+          long lineno = strtol (colon + 1, &end, 10);
+          if (end != colon + 1
+              && (*end == ' ' || *end == '\n' || *end == 0))
+            {
+              set_lineno ((int)lineno);
+              set_source (p, colon - p);
+            }
+        }
+    }
+  return true;
+}
+
+
+static const struct
+{
+  const char *text;
+  breakpoint::bpd disp;
+} disposition_table[3] =
+  {
+    {"keep", breakpoint::BPD_KEEP},
+    {"dis", breakpoint::BPD_DIS},
+    {"del", breakpoint::BPD_DEL}
+  };
+
+MRESULT breakpoint::breakpoint_msg (HWND hwnd, ULONG msg,
+                                    MPARAM mp1, MPARAM mp2)
+{
+  MRESULT mr;
+  HWND hwndTemp;
+  static char buf[270];         // TODO: query length, see display_window
+  const pm_create *pcreate;
+  const source_files_window *srcs;
+  int i, sel_idx;
+
+  switch (msg)
+    {
+    case WM_INITDLG:
+      pcreate = (const pm_create *)PVOIDFROMMP (mp2);
+      srcs = (const source_files_window *)pcreate->ptr2;
+      dlg_sys_menu (hwnd);
+      WinSetWindowPtr (hwnd, QWL_USER, this);
+      WinSendDlgItemMsg (hwnd, IDC_ENABLE, BM_SETCHECK,
+                         MPFROMSHORT (enable), NULL);
+      hwndTemp = WinWindowFromID (hwnd, IDC_SOURCE);
+      i = 0;
+      for (source_files_window::iterator s(*srcs); s.ok (); s.next ())
+        {
+            WinSendMsg (hwndTemp, LM_INSERTITEM, MPFROMSHORT (i),
+                        MPFROMP ((const char *)s));
+            if (!source.is_null () && strcmp ((const char *)s,
+                                              (const char *)source) == 0)
+              WinSendMsg (hwndTemp, LM_SELECTITEM,
+                          MPFROMSHORT (i), MPFROMSHORT (TRUE));
+            ++i;
+        }
+
+      if (lineno >= 0)
+        {
+          _itoa (lineno, buf, 10);
+          WinSetDlgItemText (hwnd, IDC_LINENO, (PSZ)buf);
+        }
+      if (ignore != 0)
+        {
+          _itoa (ignore, buf, 10);
+          WinSetDlgItemText (hwnd, IDC_IGNORE, (PSZ)buf);
+        }
+      if (!condition.is_null ())
+        WinSetDlgItemText (hwnd, IDC_CONDITION, condition);
+
+      hwndTemp = WinWindowFromID (hwnd, IDC_DISPOSITION);
+      sel_idx = -1;             // Keep the compiler happy
+      for (i = 0; i < 3; ++i)
+        {
+          WinSendMsg (hwndTemp, LM_INSERTITEM, MPFROMSHORT (i),
+                      MPFROMP (disposition_table[i].text));
+          if (disposition_table[i].disp == disposition)
+            sel_idx = i;
+        }
+      WinSendMsg (hwndTemp, LM_SELECTITEM,
+                  MPFROMSHORT (sel_idx), MPFROMSHORT (TRUE));
+      break;
+
+    case WM_COMMAND:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case DID_OK:
+          mr = WinSendDlgItemMsg (hwnd, IDC_ENABLE, BM_QUERYCHECK, NULL, NULL);
+          enable = (bool)SHORT1FROMMR (mr);
+          buf[0] = 0;
+          WinQueryDlgItemText (hwnd, IDC_SOURCE, sizeof (buf), (PSZ)buf);
+          set_source (buf, strlen (buf));
+          buf[0] = 0;
+          WinQueryDlgItemText (hwnd, IDC_LINENO, sizeof (buf), (PSZ)buf);
+          lineno = atoi (buf);
+          buf[0] = 0;
+          WinQueryDlgItemText (hwnd, IDC_IGNORE, sizeof (buf), (PSZ)buf);
+          ignore = atoi (buf);
+          buf[0] = 0;
+          WinQueryDlgItemText (hwnd, IDC_CONDITION, sizeof (buf), (PSZ)buf);
+          if (buf[0] == 0)      // TODO: Ignore white space
+            condition.set_null ();
+          else
+            set_condition (buf);
+          buf[0] = 0;
+          WinQueryDlgItemText (hwnd, IDC_DISPOSITION, sizeof (buf), (PSZ)buf);
+          for (i = 0; i < 3; ++i)
+            if (strcmp (disposition_table[i].text, buf) == 0)
+              disposition = disposition_table[i].disp;
+          WinDismissDlg (hwnd, DID_OK);
+          return 0;
+        }
+      break;
+    }
+  return WinDefDlgProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY dlg_breakpoint (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  breakpoint *p;
+
+  if (msg == WM_INITDLG)
+    p = (breakpoint *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
+  else
+    p = (breakpoint *)WinQueryWindowPtr (hwnd, QWL_USER);
+  return p->breakpoint_msg (hwnd, msg, mp1, mp2);
+}
+
+
+breakpoint_list::breakpoint_list ()
+{
+  list = NULL; end = &list;
+}
+
+
+breakpoint_list::~breakpoint_list ()
+{
+  delete_all ();
+}
+
+
+void breakpoint_list::delete_all ()
+{
+  brkpt_node *next;
+  for (brkpt_node *p = list; p != NULL; p = next)
+    {
+      next = p->next;
+      delete p;
+    }
+  list = NULL; end = &list;
+}
+
+
+void breakpoint_list::add (const breakpoint &bp)
+{
+  brkpt_node *node = new brkpt_node (bp);
+  *end = node; end = &node->next;
+}
+
+
+const breakpoint *breakpoint_list::find (ULONG addr) const
+{
+  for (const brkpt_node *p = list; p != NULL; p = p->next)
+    if (p->address == addr)
+      return p;
+  return NULL;
+}
+
+
+const breakpoint *breakpoint_list::find (const char *fname, int lineno) const
+{
+  for (const brkpt_node *p = list; p != NULL; p = p->next)
+    if (!p->source.is_null () && p->lineno == lineno
+        && _fncmp ((const unsigned char *)p->source,
+                   (const unsigned char *)fname) == 0)
+      return p;
+  return NULL;
+}
+
+
+const breakpoint *breakpoint_list::get (int n) const
+{
+  for (const brkpt_node *p = list; p != NULL; p = p->next)
+    if (n == 0)
+      return p;
+    else
+      --n;
+  return NULL;
+}
+
+
+void breakpoint_list::steal (breakpoint_list &from)
+{
+  list = from.list; end = from.end;
+  from.list = NULL; from.end = &from.list;
+}
+
+
+void breakpoint_list::update (const breakpoint_list &old, command_window *cmd,
+                              update_fun fun)
+{
+  const brkpt_node *o = old.list;
+  const brkpt_node *n = list;
+  int cmp, index = 0;
+  while (o != NULL || n != NULL)
+    {
+      if (o == NULL)
+        cmp = 1;
+      else if (n == NULL)
+        cmp = -1;
+      else if (o->get_number () > n->get_number ())
+        cmp = 1;
+      else if (o->get_number () < n->get_number ())
+        cmp = -1;
+      else
+        cmp = 0;
+
+      // TODO: enabled/disabled
+
+      if (cmp < 0)
+        (cmd->*fun) (index, o, NULL);
+      else if (cmp > 0)
+        (cmd->*fun) (index++, NULL, n);
+      else
+        (cmd->*fun) (index++, o, n);
+
+      if (cmp >= 0)
+        n = n->next;
+      if (cmp <= 0)
+        o = o->next;
+    }
+}
+
+
+bool breakpoint_list::any_enabled () const
+{
+  for (const brkpt_node *p = list; p != NULL; p = p->next)
+    if (p->enable)
+      return true;
+  return false;
+}
+
+
+#define BRK_HEADER_LINES        1
+
+breakpoints_window::breakpoints_window (command_window *in_cmd, gdbio *in_gdb,
+                                        unsigned in_id,
+                                        const char *fontnamesize)
+  : pmtxt (in_cmd->get_app (), in_id, FCF_SHELLPOSITION, NULL, fontnamesize)
+{
+  cmd = in_cmd; gdb = in_gdb;
+  sel_line = -1; exp_number = -1;
+
+  sel_attr = get_default_attr ();
+  set_fg_color (sel_attr, CLR_BLACK);
+  set_bg_color (sel_attr, CLR_PALEGRAY);
+
+  set_title ("pmgdb - Breakpoints");
+  set_keys_help_id (HELP_BRK_KEYS);
+
+  add_all ();
+}
+
+
+breakpoints_window::~breakpoints_window ()
+{
+}
+
+
+void breakpoints_window::add_all ()
+{
+  const breakpoint_list::brkpt_node *p;
+  int line = BRK_HEADER_LINES;
+
+  select_line (-1);
+  delete_all ();
+
+  int x = 0;
+  put (0, x, 4, " No ", true); x += 4;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 5, " Ena ", true); x += 5;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 9, " Address ", true); x += 9;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 8, " Source ", true); x += 8;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 6, " Line ", true); x += 6;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 6, " Disp ", true); x += 6;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 6, " Ign ", true); x += 5;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 5, " Cond", true); x += 5;
+  underline (0, true, true);
+
+  // TODO: iterator
+  for (p = cmd->get_breakpoint_list (); p != NULL; p = p->next)
+    put_bpt (line++, *p);
+  // TODO: Add do_paint argument to pmtxt::delete_all()
+  sync ();
+}
+
+
+void breakpoints_window::update (int index, const breakpoint *old_bpt,
+                                 const breakpoint *new_bpt)
+{
+  int line = index + BRK_HEADER_LINES;
+  if (new_bpt == NULL)
+    {
+      delete_lines (line, 1, true);
+      if (sel_line != -1)
+        {
+          if (line == sel_line)
+            {
+              sel_line = -1;
+              menu_enable (IDM_EDITMENU, false);
+            }
+          else if (line < sel_line)
+            --sel_line;
+        }
+    }
+  else if (old_bpt == NULL)
+    {
+      insert_lines (line, 1, true);
+      put_bpt (line, *new_bpt);
+      if (sel_line != -1)
+        {
+          if (line <= sel_line)
+            ++sel_line;
+        }
+      if (exp_number == new_bpt->get_number ())
+        {
+          exp_number = -1;
+          select_line (line);
+        }
+    }
+  else if (*old_bpt != *new_bpt)
+    {
+      clear_lines (line, 1, true);
+      put_bpt (line, *new_bpt);
+      if (sel_line != -1)
+        {
+          if (line == sel_line)
+            {
+              sel_line = -1;
+              select_line (line);
+              menu_enable (IDM_ENABLE, !new_bpt->get_enable ());
+              menu_enable (IDM_DISABLE, new_bpt->get_enable ());
+            }
+        }
+    }
+}
+
+
+MRESULT breakpoints_window::wm_activate (HWND hwnd, ULONG msg,
+                                         MPARAM mp1, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp1))
+    cmd->associate_help (get_hwndFrame ());
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT breakpoints_window::wm_close (HWND, ULONG, MPARAM, MPARAM)
+{
+  show (false);
+  return 0;
+}
+
+
+MRESULT breakpoints_window::wm_command (HWND hwnd, ULONG msg,
+                                        MPARAM mp1, MPARAM mp2)
+{
+  const breakpoint *bpt;
+
+  switch (SHORT1FROMMP (mp1))
+    {
+    case IDM_DELETE:
+      bpt = cmd->get_breakpoint (sel_line - BRK_HEADER_LINES);
+      if (bpt == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        gdb->send_cmd ("server delete %d", bpt->get_number ());
+      return 0;
+
+    case IDM_ENABLE:
+      bpt = cmd->get_breakpoint (sel_line - BRK_HEADER_LINES);
+      if (bpt == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        send_disposition (bpt->number, bpt->disposition, true);
+      return 0;
+
+    case IDM_DISABLE:
+      bpt = cmd->get_breakpoint (sel_line - BRK_HEADER_LINES);
+      if (bpt == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        send_disposition (bpt->number, bpt->disposition, false);
+      return 0;
+
+    case IDM_BRKPT_LINE:
+      add_line ();
+      return 0;
+
+    case IDM_REFRESH:
+      cmd->get_breakpoints ();
+      return 0;
+
+    case IDM_MODIFY:
+      bpt = cmd->get_breakpoint (sel_line - BRK_HEADER_LINES);
+      if (bpt == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        {
+          breakpoint b = *bpt;
+          if (dialog (&b))
+            {
+              // TODO: bpt might have gone away in the meantime, UWM_STATE!
+              // TODO: check values
+              // TODO: Check type
+              if (b.source != bpt->source || b.lineno != bpt->lineno)
+                {
+                  capture *capt;
+                  capt = gdb->capture_cmd ("server break %s:%d",
+                                           b.get_source (), b.lineno);
+                  if (capt != NULL)
+                    {
+                      if (capt->bpt_number.is_set ())
+                        {
+                          int number = capt->bpt_number.get ();
+                          if (gdb->send_cmd ("server delete %d", bpt->number))
+                            {
+                              send_disposition (number, b.disposition,
+                                                b.enable);
+                              if (!b.condition.is_null ())
+                                gdb->queue_cmd ("server condition %d %s",
+                                                number, b.get_condition ());
+                              if (b.ignore != 0)
+                                gdb->queue_cmd ("server ignore %d %d",
+                                                number, b.ignore);
+                              exp_number = number;
+                            }
+                        }
+                      else if (capt->error.is_set ())
+                        cmd->capture_error (capt);
+                      delete_capture (capt);
+                    }
+                }
+              else
+                {
+                  if (b.disposition != bpt->disposition
+                      || b.enable != bpt->enable)
+                    send_disposition (b.number, b.disposition, b.enable);
+                  if (b.condition != bpt->condition)
+                    gdb->queue_cmd ("server condition %d %s", b.number,
+                                    (b.condition.is_null ()
+                                     ? "" : b.get_condition ()));
+                  if (b.ignore != bpt->ignore)
+                    gdb->queue_cmd ("server ignore %d %d", b.number, b.ignore);
+                }
+            }
+        }
+      return 0;
+
+    default:
+      return cmd->wm_command (hwnd, msg, mp1, mp2);
+    }
+}
+
+
+void breakpoints_window::put_bpt (int line, const breakpoint &bpt)
+{
+  char buf[400];
+  int x = 0, len;
+
+  len = snprintf (buf, sizeof (buf), " %d ", bpt.get_number ());
+  put (line, x, len, buf, true); x += len;
+  put_tab (line, x++, true);
+  put_vrule (line, x++, true);
+
+  len = snprintf (buf, sizeof (buf), " %c ", bpt.get_enable () ? 'y' : 'n');
+  put (line, x, len, buf, true); x += len;
+  put_tab (line, x++, true);
+  put_vrule (line, x++, true);
+
+  len = snprintf (buf, sizeof (buf), " 0x%.8lx ", bpt.get_address ());
+  put (line, x, len, buf, true); x += len;
+  put_tab (line, x++, true);
+  put_vrule (line, x++, true);
+
+  len = snprintf (buf, sizeof (buf), " %s ",
+                  bpt.get_source () != NULL ? bpt.get_source () : "-");
+  put (line, x, len, buf, true); x += len;
+  put_tab (line, x++, true);
+  put_vrule (line, x++, true);
+
+  len = snprintf (buf, sizeof (buf), " %d ", bpt.get_lineno ());
+  put (line, x, len, buf, true); x += len;
+  put_tab (line, x++, true);
+  put_vrule (line, x++, true);
+
+  len = snprintf (buf, sizeof (buf), " %s ",
+                  bpt.get_disposition_as_string ());
+  put (line, x, len, buf, true); x += len;
+  put_tab (line, x++, true);
+  put_vrule (line, x++, true);
+
+  if (bpt.get_ignore () == 0)
+    len = snprintf (buf, sizeof (buf), " - ");
+  else
+    len = snprintf (buf, sizeof (buf), " %d ", bpt.get_ignore ());
+  put (line, x, len, buf, true); x += len;
+  put_tab (line, x++, true);
+  put_vrule (line, x++, true);
+
+  len = snprintf (buf, sizeof (buf), " %s",
+                  bpt.get_condition () != NULL ? bpt.get_condition () : "-");
+  put (line, x, len, buf, true); x += len;
+}
+
+
+void breakpoints_window::select_line (int line, bool toggle)
+{
+  const breakpoint *bpt;
+  if (toggle && line != -1 && line == sel_line)
+    line = -1;
+  if (line == -1)
+    bpt = NULL;
+  else
+    {
+      bpt = cmd->get_breakpoint (line - BRK_HEADER_LINES);
+      if (bpt == NULL) line = -1;
+    }
+  if (line != sel_line)
+    {
+      if (sel_line != -1)
+        {
+          put (sel_line, 0, max_line_len, get_default_attr (), true);
+          set_eol_attr (sel_line, get_default_attr (), true);
+        }
+      if (line != -1)
+        {
+          put (line, 0, max_line_len, sel_attr, true);
+          set_eol_attr (line, sel_attr, true);
+        }
+      sel_line = line;
+    }
+  if (line != -1)
+    {
+      menu_enable (IDM_ENABLE, !bpt->get_enable ());
+      menu_enable (IDM_DISABLE, bpt->get_enable ());
+      show_line (line, 1, 1);
+    }
+  menu_enable (IDM_EDITMENU, line != -1);
+}
+
+
+void breakpoints_window::button_event (int line, int column, int tab,
+                                       int button, int clicks)
+{
+  if (line >= 0 && column >= 0)
+    {
+      if (clicks == 1 && button == 1)
+        {
+          // TODO: Context menu
+          select_line (line, true);
+        }
+      else if (clicks == 2 && button == 1 && tab == 1)
+        {
+          const breakpoint *p = cmd->get_breakpoint (line - BRK_HEADER_LINES);
+          if (p == NULL)
+            WinAlarm (HWND_DESKTOP, WA_ERROR);
+          else
+            {
+              gdb->send_cmd ("server %s %d",
+                             p->get_enable () ? "disable" : "enable",
+                             p->get_number ());
+              select_line (line);
+            }
+        }
+      else if (clicks == 2 && button == 1 && tab >= 3 && tab <= 4)
+        {
+          show_source (line);
+          select_line (line);
+        }
+      else if (clicks == 2)
+        {
+          // TODO: Double clicking on any other field should change that field
+          select_line (line);
+        }
+    }
+  else
+    select_line (-1);
+}
+
+
+void breakpoints_window::show_source (int line)
+{
+  const breakpoint *bpt = cmd->get_breakpoint (line - BRK_HEADER_LINES);
+  if (bpt != NULL && bpt->get_source () != NULL)
+    cmd->show_source (bpt->get_source (), NULL, true, bpt->get_lineno());
+}
+
+
+bool breakpoints_window::dialog (breakpoint *bpt)
+{
+  pm_create create;
+
+  create.cb = sizeof (create);
+  create.ptr = (void *)bpt;
+  create.ptr2 = (void *)cmd->get_srcs ();
+  // TODO: Breakpoint type
+  return WinDlgBox (HWND_DESKTOP, get_hwndClient (), dlg_breakpoint, 0,
+                    IDD_BRKPT_LINE, &create) == DID_OK;
+}
+
+
+void breakpoints_window::add_line (const char *default_source, int line_no)
+{
+  breakpoint temp;
+  // TODO: Breakpoint type
+  temp.set_enable (true);
+  if (default_source != NULL)
+    temp.set_source (default_source, strlen (default_source));
+  temp.set_lineno (line_no);
+  if (dialog (&temp))
+    {
+      select_line (-1);
+      capture *capt;
+      // TODO: Breakpoint type
+      // TODO: Check values
+      capt = gdb->capture_cmd ("server break %s:%d",
+                               temp.get_source (), temp.get_lineno ());
+      if (capt != NULL)
+        {
+          if (capt->bpt_number.is_set ())
+            {
+              int number = capt->bpt_number.get ();
+              send_disposition (number, temp.disposition, temp.enable);
+              if (!temp.condition.is_null ())
+                gdb->queue_cmd ("server condition %d %s", number,
+                                temp.get_condition ());
+              if (temp.ignore != 0)
+                gdb->queue_cmd ("server ignore %d %d", number, temp.ignore);
+              exp_number = number;
+            }
+          else if (capt->error.is_set ())
+            cmd->capture_error (capt);
+        }
+      delete_capture (capt);
+    }
+}
+
+
+void
+breakpoints_window::send_disposition (int number, breakpoint::bpd disposition,
+                                      bool enable)
+{
+  switch (disposition)
+    {
+    case breakpoint::BPD_KEEP:
+      gdb->queue_cmd ("server enable %d", number);
+      break;
+    case breakpoint::BPD_DIS:
+      gdb->queue_cmd ("server enable once %d", number);
+      break;
+    case breakpoint::BPD_DEL:
+      gdb->queue_cmd ("server enable delete %d", number);
+      break;
+    default:
+      break;
+    }
+  if (!enable)
+    gdb->queue_cmd ("server disable %d", number);
+}
Index: trunk/src/emx/src/pmgdb/breakpoi.h
===================================================================
--- trunk/src/emx/src/pmgdb/breakpoi.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/breakpoi.h	(revision 18)
@@ -0,0 +1,195 @@
+/* breakpoi.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class command_window;
+class gdbio;
+class capture;
+class breakpoint_list;
+class breakpoints_window;
+
+class breakpoint
+{
+public:
+
+  enum bpt
+  {
+    BPT_BREAKPOINT,
+    BPT_HW_BREAKPOINT,
+    BPT_UNTIL,
+    BPT_FINISH,
+    BPT_WATCHPOINT,
+    BPT_HW_WATCHPOINT,
+    BPT_READ_WATCHPOINT,
+    BPT_ACC_WATCHPOINT,
+    BPT_LONGJMP,
+    BPT_LONGJMP_RESUME,
+    BPT_STEP_RESUME,
+    BPT_SIGTRAMP,
+    BPT_WATCHPOINT_SCOPE,
+    BPT_CALL_DUMMY,
+    BPT_SHLIB_EVENTS,
+    BPT_UNKNOWN
+  };
+
+  enum bpd
+  {
+    BPD_DEL,
+    BPD_DIS,
+    BPD_KEEP,
+    BPD_UNKNOWN
+  };
+
+  // Constructors and destructors
+  breakpoint ();
+  breakpoint (const breakpoint &bp);
+  ~breakpoint ();
+
+  // Assignment
+  breakpoint &operator = (const breakpoint &src);
+
+  // Setting members
+  void set_number (int v) { number = v; }
+  void set_enable (bool v) { enable = v; }
+  void set_address (ULONG v) { address = v; }
+  void set_source (const char *s, int len) { source.set (s, len); }
+  void set_lineno (int v) { lineno = v; }
+  void set_ignore (int v) { ignore = v; }
+  void set_disposition (const char *s);
+  void set_condition (const char *s) { condition.set (s); }
+  void copy (const breakpoint &src);
+
+  // Querying members
+  int get_number ()         const { return number; }
+  bpt get_type ()           const { return type; }
+  bpd get_disposition ()    const { return disposition; }
+  bool get_enable ()        const { return enable; }
+  ULONG get_address ()      const { return address; }
+  const char *get_source () const { return source; }
+  int get_lineno ()         const { return lineno; }
+  int get_ignore ()         const { return ignore; }
+  const char *get_condition () const { return condition; }
+  const char *get_disposition_as_string () const;
+
+  bool operator == (const breakpoint b) const;
+  bool operator != (const breakpoint b) const { return !operator== (b); }
+
+  bool set_from_capture (const capture &capt);
+
+  // Dialog box
+  MRESULT breakpoint_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+private:
+  int number;
+  bpt type;
+  bpd disposition;
+  bool enable;
+  ULONG address;
+  // TODO: Use numbers for identifying source files
+  fstring source;
+  int lineno;
+  fstring condition;
+  int ignore;
+  // *** Update copy() when adding members!
+  // *** Update eq_brkpt() when adding members!
+
+  // Friends
+  friend breakpoint_list;
+  friend breakpoints_window;
+};
+
+class breakpoint_list
+{
+public:
+
+  typedef void (command_window::*update_fun)(int index,
+                                             const breakpoint *old_bpt,
+                                             const breakpoint *new_bpt);
+
+  // Constructors and destructors
+  breakpoint_list ();
+  ~breakpoint_list ();
+
+  void steal (breakpoint_list &from);
+  void add (const breakpoint &bp);
+  void delete_all ();
+  void update (const breakpoint_list &old, command_window *cmd,
+               update_fun fun);
+  const breakpoint *find (ULONG addr) const;
+  const breakpoint *find (const char *fname, int lineno) const;
+  const breakpoint *get (int n) const;
+  bool any_enabled () const;
+
+private:
+
+  class brkpt_node : public breakpoint
+  {
+  public:
+    brkpt_node (const breakpoint &bp) : breakpoint (bp) { next = NULL; }
+    ~brkpt_node () {}
+    class brkpt_node *next;
+  };
+
+  brkpt_node *list, **end;
+
+  // Friends
+  friend command_window;
+};
+
+
+// Breakpoint list
+class breakpoints_window : public pmtxt
+{
+public:
+
+  typedef pmtxt parent;
+
+  breakpoints_window (command_window *cmd, gdbio *gdb, unsigned id,
+                      const char *fontnamesize);
+  ~breakpoints_window ();
+
+  void add_all ();
+  void update (int index, const breakpoint *old_bpt,
+               const breakpoint *new_bpt);
+  void add_line (const char *default_source = NULL, int line_no = -1);
+
+private:
+  // Override member functions of pmframe
+  MRESULT wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  void button_event (int line, int column, int tab, int button, int clicks);
+
+  // Painting
+  void put_bpt (int line, const breakpoint &bpt);
+  void select_line (int line, bool toggle = false);
+
+  void show_source (int line);
+  bool dialog (breakpoint *bpt);
+  void send_disposition (int number, breakpoint::bpd disposition, bool enable);
+
+  command_window *cmd;
+  gdbio *gdb;
+  pmtxt_attr sel_attr;          // Attribute used for hilighting selection
+  int sel_line;
+
+  // Expected new breakpoint
+  int exp_number;
+};
Index: trunk/src/emx/src/pmgdb/capture.cc
===================================================================
--- trunk/src/emx/src/pmgdb/capture.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/capture.cc	(revision 18)
@@ -0,0 +1,43 @@
+/* capture.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <os2.h>
+#include <string.h>
+#include "capture.h"
+
+
+void capture_string::set (const char *s, size_t len)
+{
+  str = new char[len + 1];
+  memcpy (str, s, len);
+  str[len] = 0;
+}
+
+
+void delete_capture (capture *p)
+{
+  while (p != NULL)
+    {
+      capture *next = p->next;
+      delete p;
+      p = next;
+    }
+}
Index: trunk/src/emx/src/pmgdb/capture.h
===================================================================
--- trunk/src/emx/src/pmgdb/capture.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/capture.h	(revision 18)
@@ -0,0 +1,90 @@
+/* capture.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class capture_string
+{
+public:
+  capture_string () { str = NULL; }
+  ~capture_string () { delete[] str; }
+  void set (const char *s, size_t len);
+  void set (const char *s) { set (s, strlen (s)); }
+  bool is_set () const { return str != NULL; }
+  const char *get () const { return str; }
+private:
+  char *str;
+};
+
+class capture_number
+{
+public:
+  capture_number () { flag = false; }
+  ~capture_number () {}
+  void set (long v) { value = v; flag = true; }
+  bool is_set () const { return flag; }
+  long get () const { return value; }
+private:
+  long value;
+  bool flag;
+};
+
+class capture_bool
+{
+public:
+  capture_bool () { flag = false; }
+  ~capture_bool () {}
+  void set (bool v) { value = v; flag = true; }
+  bool is_set () const { return flag; }
+  bool get () const { return value; }
+private:
+  // TODO: Use three-value enum?
+  bool value;
+  bool flag;
+};
+
+class capture
+{
+public:
+  capture () { next = NULL; }
+  ~capture () {}
+
+  class capture *next;          // TODO: make private, add iterator
+  capture_string source_file;
+  capture_number source_lineno;
+  capture_number source_addr;
+  capture_number bpt_number;
+  capture_string bpt_disposition;
+  capture_bool   bpt_enable;
+  capture_number bpt_address;
+  capture_string bpt_what;
+  capture_string bpt_condition;
+  capture_number bpt_ignore;
+  capture_number disp_number;
+  capture_string disp_format;
+  capture_string disp_expr;
+  capture_string disp_value;
+  capture_bool   disp_enable;
+  capture_string srcs_file;
+  capture_string source_location;
+  capture_string show_value;
+  capture_string error;
+
+  friend void delete_capture (capture *capt);
+};
Index: trunk/src/emx/src/pmgdb/command.cc
===================================================================
--- trunk/src/emx/src/pmgdb/command.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/command.cc	(revision 18)
@@ -0,0 +1,1616 @@
+/* command.cc
+   Copyright (c) 1996, 1998 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <process.h>
+#include <signal.h>
+#include <io.h>
+#include <fcntl.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "pmgdb.h"
+#include "help.h"
+#include "breakpoi.h"
+#include "display.h"
+#include "threads.h"
+#include "register.h"
+#include "source.h"
+#include "srcfiles.h"
+#include "annotati.h"
+#include "capture.h"
+#include "gdbio.h"
+#include "pmdebug.h"
+#include "command.h"
+
+static HWND hwndFatal;
+
+struct command_window::new_source
+{
+  char *short_filename;
+  char *long_filename;
+  int lineno;
+  bool set_focus;
+};
+
+struct command_window::cmd_hist
+{
+  struct cmd_hist *next;
+  struct cmd_hist *prev;
+  fstring cmd;
+};
+
+void command_window_thread (void *arg)
+{
+  ((struct command_window *)arg)->thread ();
+}
+
+
+// Note: This signal handler is called in thread 1, which has a
+// PM message queue.
+
+static void sigchld_handler (int)
+{
+  // TODO: Offer to save settings
+  // TODO: WinMessageBox has a message loop and can therefore cause
+  //       a reentrancy problem
+  WinMessageBox (HWND_DESKTOP, HWND_DESKTOP, (PSZ)"GDB terminated.",
+                 (PSZ)"pmgdb", 0,
+                 MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
+  // TODO: Get and return GDB's termination code
+  exit (0);
+}
+
+
+command_window::command_window (pmapp *in_app, unsigned in_id,
+                                const char *fontnamesize, char **in_argv)
+  : pmtty (in_app, in_id, FCF_TASKLIST, NULL, fontnamesize)
+{
+  SWP swp_cmd, swp_dsp, swp_thr, swp_srcs;
+
+  hwndFatal = get_hwndClient ();
+  _fmutex_checked_create (&mutex, 0);
+
+  swp_srcs.cx = in_app->get_screen_width () / 4;
+  swp_srcs.cy = in_app->get_screen_height () / 4;
+  swp_srcs.x = in_app->get_screen_width () - swp_srcs.cx;
+  swp_srcs.y = in_app->get_screen_height () - swp_srcs.cy;
+
+  swp_cmd.cx = swp_srcs.x;
+  swp_cmd.cy = swp_srcs.cy;
+  swp_cmd.x = 0;
+  swp_cmd.y = swp_srcs.y;
+  WinSetWindowPos (get_hwndFrame (), HWND_DESKTOP, swp_cmd.x, swp_cmd.y,
+                   swp_cmd.cx, swp_cmd.cy, SWP_SIZE | SWP_MOVE);
+
+  WinQueryWindowPos (get_hwndFrame (), &swp_cmd);
+  swp_srcs.x = swp_cmd.x + swp_cmd.cx;
+  swp_srcs.cx = in_app->get_screen_width () - swp_srcs.x;
+
+  swp_thr.x = swp_srcs.x;
+  swp_thr.y = swp_srcs.y - swp_srcs.cy;
+  swp_thr.cx = swp_srcs.cx;
+  swp_thr.cy = swp_srcs.cy;
+
+  swp_dsp.x = 0;
+  swp_dsp.y = swp_thr.y;
+  swp_dsp.cx = swp_cmd.cx;
+  swp_dsp.cy = swp_thr.cy;
+
+  help_ok = help_init (HELP_TABLE, "pmgdb Help", "pmgdb.hlp", HELP_CMD_KEYS);
+  if (!help_ok)
+    {
+      WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
+                     (PSZ)"pmgdb.hlp not found; please set HELP correctly "
+                     "in config.sys.", (PSZ)"pmgdb", 0,
+                     MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
+      help_disable (this);
+    }
+
+  show (true);
+  src_list = NULL; src_menu_id_used = NULL;
+  src_menu_id_count = 0;
+  history = NULL; cur_cmd = NULL;
+  gdb = new gdbio (this);
+  cursor (true);
+
+  argv = NULL; argv_used = 0; argv_size = 0;
+  arg_add ("gdb.exe");
+  arg_add ("--annotate=2");
+  arg_add ("--args");
+  for (int i = 0; in_argv[i] != NULL; ++i)
+    arg_add (in_argv[i]);
+  arg_add (NULL);
+
+  srcs = new source_files_window (this, ID_SOURCE_FILES_WINDOW, &swp_srcs,
+                                  fontnamesize);
+  if (!help_ok) help_disable (srcs);
+  thr = new threads_window (this, gdb, ID_THREADS_WINDOW, &swp_thr,
+                            fontnamesize);
+  if (!help_ok) help_disable (thr);
+  brk = new breakpoints_window (this, gdb, ID_BREAKPOINTS_WINDOW,
+                                fontnamesize);
+  if (!help_ok) help_disable (brk);
+  dsp = new display_window (this, gdb, ID_DISPLAY_WINDOW, &swp_dsp,
+                            fontnamesize);
+  if (!help_ok) help_disable (dsp);
+  reg = new register_window (this, ID_REGISTER_WINDOW, NULL, fontnamesize);
+  if (!help_ok) help_disable (reg);
+
+  notify (GSC_RUNNING | GSC_EXEC_FILE);
+
+  gdb->send_init ();
+  gdb->queue_cmd ("server set height 0");
+
+  struct sigaction sa;
+  sa.sa_handler = sigchld_handler;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGCHLD, &sa, NULL);
+
+  if (_beginthread (command_window_thread, NULL, 0x8000, (void *)this) == -1)
+    abort ();
+}
+
+
+command_window::~command_window ()
+{
+  // TODO: delete cmd_head...
+  pmdbg.exit ();
+  delete brk;
+  delete dsp;
+  delete thr;
+  delete srcs;
+  delete reg;
+  src_node *s, *snext;
+  for (s = src_list; s != NULL; s = snext)
+    {
+      snext = s->next;
+      delete s->src;
+      delete s;
+    }
+  delete[] src_menu_id_used;
+  arg_delete_all ();
+  cmd_hist *h, *hprev;
+  for (h = history; h != NULL; h = hprev)
+    {
+      hprev = h->prev;
+      delete h;
+    }
+
+  // TODO: mutex
+}
+
+
+void command_window::arg_delete_all ()
+{
+  for (int i = 0; argv[i] != NULL; ++i)
+    delete[] argv[i];
+  delete[] argv;
+  argv = NULL; argv_used = 0; argv_size = 0;
+}
+
+
+void command_window::arg_add (const char *str)
+{
+  if (argv_used >= argv_size)
+    {
+      int new_size = argv_size + 16;
+      char **new_argv = new char *[new_size];
+      for (int i = 0; i < argv_size; ++i)
+        new_argv[i] = argv[i];
+      for (int i = argv_size; i < new_size; ++i)
+        new_argv[i] = NULL;
+      delete[] argv;
+      argv = new_argv; argv_size = new_size;
+    }
+
+  char *p;
+  if (str == NULL)
+    p = NULL;
+  else
+    {
+      p = new char[strlen (str) + 1];
+      strcpy (p, str);
+    }
+  argv[argv_used++] = p;
+}
+
+
+void command_window::lock ()
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+}
+
+
+void command_window::unlock ()
+{
+  _fmutex_checked_release (&mutex);
+}
+
+
+void command_window::capture_error (const capture *p)
+{
+  WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
+                 (PSZ)p->error.get (), (PSZ)"pmgdb", 0,
+                 MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
+}
+
+
+void command_window::get_breakpoints ()
+{
+  breakpoint_list old;
+  old.steal (breakpoints);
+  capture *capt = gdb->capture_cmd ("server info breakpoints");
+  if (capt != NULL)
+    {
+      for (capture *p = capt->next; p != NULL; p = p->next)
+        {
+          breakpoint bpt;
+          if (bpt.set_from_capture (*p))
+            breakpoints.add (bpt);
+        }
+      gdb->breakpoints_invalid = false;
+      delete_capture (capt);
+    }
+
+  breakpoints.update (old, this, &brkpt_update);
+
+  // OLD goes out of scope here; that will call delete_all()
+}
+
+
+// Callback function for breakpoint_list::update()
+
+void command_window::brkpt_update (int index, const breakpoint *old_bpt,
+                                   const breakpoint *new_bpt)
+{
+  if (new_bpt == NULL)
+    {
+      // Deletion
+      if (old_bpt->get_source () != NULL)
+        {
+          source_window *src = find_source_short (old_bpt->get_source ());
+          if (src != NULL)
+            src->set_breakpoint (old_bpt->get_lineno (), false, true);
+        }
+    }
+  else if (old_bpt == NULL)
+    {
+      // Insertion
+      if (new_bpt->get_source () != NULL)
+        {
+          source_window *src = find_source_short (new_bpt->get_source ());
+          if (src != NULL)
+            src->set_breakpoint (new_bpt->get_lineno (), true, true);
+        }
+    }
+  else
+    {
+      // Possible update
+      if (old_bpt->get_address () != new_bpt->get_address ())
+        {
+          if (old_bpt->get_source () != NULL)
+            {
+              source_window *src = find_source_short (old_bpt->get_source ());
+              if (src != NULL)
+                src->set_breakpoint (old_bpt->get_lineno (), false, true);
+            }
+          if (new_bpt->get_source () != NULL)
+            {
+              source_window *src = find_source_short (new_bpt->get_source ());
+              if (src != NULL)
+                src->set_breakpoint (new_bpt->get_lineno (), true, true);
+            }
+        }
+    }
+  if (brk != NULL)
+    brk->update (index, old_bpt, new_bpt);
+}
+
+
+void command_window::get_breakpoints (source_window *src, bool paint)
+{
+  const char *name = src->get_short_filename ();
+  // TODO: iterator
+  for (breakpoint_list::brkpt_node *p = breakpoints.list; p != NULL;
+       p = p->next)
+    if (p->get_source () != NULL
+        && _fncmp ((const unsigned char *)p->get_source (),
+                   (const unsigned char *)name) == 0)
+      src->set_breakpoint (p->get_lineno (), true, paint);
+}
+
+
+const breakpoint *command_window::get_breakpoint (int n) const
+{
+  return breakpoints.get (n);
+}
+
+
+source_window *command_window::find_source_short (const char *fname)
+{
+  for (src_node *node = src_list; node != NULL; node = node->next)
+    if (_fncmp ((const unsigned char *)node->src->get_short_filename (),
+                (const unsigned char *)fname) == 0)
+      return node->src;
+  return NULL;
+}
+
+
+source_window *command_window::find_source_long (const char *fname)
+{
+  for (src_node *node = src_list; node != NULL; node = node->next)
+    if (_fncmp ((const unsigned char *)node->src->get_long_filename (),
+                (const unsigned char *)fname) == 0)
+      return node->src;
+  return NULL;
+}
+
+
+// lineno == -1: don't change line if file already loaded;
+//               don't select line for new file
+// Deselect current line in any source window if both filenames are NULL
+
+void command_window::show_source (const char *short_fname,
+                                  const char *long_fname, bool set_focus,
+                                  int lineno)
+{
+  for (const src_node *node = src_list; node != NULL; node = node->next)
+    node->src->show_line (-1);
+  if (short_fname == NULL && long_fname == NULL)
+    return;
+
+  source_window *src = NULL;
+  if (long_fname != NULL)
+    src = find_source_long (long_fname);
+  if (src == NULL && short_fname != NULL)
+    src = find_source_short (short_fname);
+
+  if (src != NULL)
+    {
+      if (lineno != -1)
+        src->show_line (lineno);
+      if (set_focus)
+        src->focus ();
+    }
+  else
+    {
+      new_source ns;
+      ns.short_filename = NULL; ns.long_filename = NULL;
+      if (short_fname != NULL)
+        {
+          // TODO: Use fstring?
+          ns.short_filename = new char [strlen (short_fname) + 1];
+          strcpy (ns.short_filename, short_fname);
+        }
+      if (long_fname != NULL)
+        {
+          ns.long_filename = new char [strlen (long_fname) + 1];
+          strcpy (ns.long_filename, long_fname);
+        }
+      ns.lineno = lineno;
+      ns.set_focus = set_focus;
+      if (same_tid ())
+        show_new_source (&ns);
+      else
+        WinSendMsg (get_hwndClient (), UWM_SOURCE, MPFROMP (&ns), 0);
+    }
+}
+
+
+// FILENAME has been allocated with new char[]!
+
+void command_window::show_new_source (const new_source *ns)
+{
+  unsigned menu_id;
+  MENUITEM mi;
+  char *long_filename = ns->long_filename;
+  char *short_filename = ns->short_filename;
+
+  if (long_filename == NULL || access (long_filename, R_OK) != 0)
+    {
+      char *new_filename = NULL;
+
+      capture *capt = gdb->capture_cmd ("server list %s:1,0",
+                                        (short_filename != NULL
+                                         ? short_filename : long_filename));
+      if (capt != NULL && !capt->error.is_set ())
+        {
+          delete_capture (capt);
+          capt = gdb->capture_cmd ("server info source");
+          if (capt != NULL && capt->source_location.is_set ())
+            {
+              const char *s = capt->source_location.get ();
+              new_filename = new char [strlen (s) + 1];
+              strcpy (new_filename, s);
+            }
+        }
+      delete_capture (capt);
+      delete[] long_filename;
+      if (new_filename == NULL)
+        {
+          delete[] short_filename;
+          return;               // TODO: Message box
+        }
+      long_filename = new_filename;
+    }
+
+  if (short_filename == NULL)
+    {
+      const char *s = _getname (long_filename);
+      short_filename = new char[strlen (s)];
+      strcpy (short_filename, s);
+    }
+  char *p = (char *)memchr (src_menu_id_used, 0, src_menu_id_count);
+  if (p != NULL)
+    menu_id = p - src_menu_id_used;
+  else
+    {
+      int new_count = src_menu_id_count + 32;
+      p = new char[new_count];
+      memcpy (p, src_menu_id_used, src_menu_id_count);
+      memset (p + src_menu_id_count, 0, new_count - src_menu_id_count);
+      delete[] src_menu_id_used;
+      src_menu_id_used = p;
+      menu_id = src_menu_id_count;
+      src_menu_id_count = new_count;
+    }
+  src_menu_id_used[menu_id] = 1;
+  menu_id += IDM_WIN_SRC;
+
+  src_node *new_node = new src_node;
+  new_node->next = NULL;
+  new_node->src = new source_window (get_app (), ID_SOURCE_WINDOW, NULL,
+                                     short_filename, long_filename, this, gdb);
+  if (!help_ok) help_disable (new_node->src);
+  new_node->menu_id = menu_id;
+  new_node->hwndWinMenu = new_node->src->get_hwndMenu_from_id (IDM_WINMENU);
+
+  mi.iPosition = MIT_END;
+  mi.afStyle = MIS_TEXT;
+  mi.afAttribute = 0;
+  mi.hwndSubMenu = NULLHANDLE;
+  mi.hItem = 0;
+  mi.id = new_node->menu_id;
+  const char *new_name = short_filename;
+
+  WinSendMsg (get_hwndMenu_from_id (IDM_WINMENU),
+              MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
+  WinSendMsg (thr->get_hwndMenu_from_id (IDM_WINMENU),
+              MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
+  WinSendMsg (brk->get_hwndMenu_from_id (IDM_WINMENU),
+              MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
+  WinSendMsg (dsp->get_hwndMenu_from_id (IDM_WINMENU),
+              MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
+  WinSendMsg (srcs->get_hwndMenu_from_id (IDM_WINMENU),
+              MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
+
+  for (src_node *pn = src_list; pn != NULL; pn = pn->next)
+    {
+      mi.id = new_node->menu_id;
+      WinSendMsg (pn->hwndWinMenu, MM_INSERTITEM, MPFROMP (&mi),
+                  MPFROMP (new_name));
+      mi.id = pn->menu_id;
+      WinSendMsg (new_node->hwndWinMenu, MM_INSERTITEM, MPFROMP (&mi),
+                  MPFROMP (pn->src->get_short_filename ()));
+    }
+  src_node **patch = &src_list;
+  while (*patch != NULL)
+    patch = &(*patch)->next;
+  *patch = new_node;
+
+  if (ns->lineno != -1)
+    new_node->src->show_line (ns->lineno);
+  if (ns->set_focus)
+    new_node->src->focus ();
+
+  delete[] short_filename;
+  delete[] long_filename;
+}
+
+
+void command_window::delete_source (source_window *src)
+{
+  // TODO: Use Mutex to prevent another thread from accessing src_list and SRC
+  src_node **patch = &src_list;
+  while (*patch != NULL && (*patch)->src != src)
+    patch = &(*patch)->next;
+  if (*patch != NULL)
+    {
+      src_node *p = *patch;
+      *patch = p->next;
+      src_menu_id_used[p->menu_id] = 0;
+      for (src_node *pn = src_list; pn != NULL; pn = pn->next)
+        WinSendMsg (pn->src->get_hwndMenu (), MM_DELETEITEM,
+                    MPFROM2SHORT (p->menu_id, TRUE), 0);
+      WinSendMsg (get_hwndMenu (), MM_DELETEITEM,
+                  MPFROM2SHORT (p->menu_id, TRUE), 0);
+      WinSendMsg (thr->get_hwndMenu (), MM_DELETEITEM,
+                  MPFROM2SHORT (p->menu_id, TRUE), 0);
+      WinSendMsg (brk->get_hwndMenu (), MM_DELETEITEM,
+                  MPFROM2SHORT (p->menu_id, TRUE), 0);
+      WinSendMsg (dsp->get_hwndMenu (), MM_DELETEITEM,
+                  MPFROM2SHORT (p->menu_id, TRUE), 0);
+      WinSendMsg (srcs->get_hwndMenu (), MM_DELETEITEM,
+                  MPFROM2SHORT (p->menu_id, TRUE), 0);
+      delete p;
+    }
+  delete src;
+}
+
+
+bool command_window::open_dialog (char *buf, const char *title,
+                                  const char *fname)
+{
+  FILEDLG fdlg;
+
+  memset (&fdlg, 0, sizeof (fdlg));
+  fdlg.cbSize = sizeof (fdlg);
+  fdlg.fl = FDS_OPEN_DIALOG | FDS_CENTER;
+  fdlg.ulUser = 0;
+  fdlg.lReturn = 0;
+  fdlg.pszTitle = (PSZ)title;
+  fdlg.pszOKButton = (PSZ)"Open";
+  fdlg.pfnDlgProc = NULL;
+  fdlg.pszIType = NULL;
+  fdlg.papszITypeList = NULL;
+  fdlg.pszIDrive = NULL;
+  fdlg.papszIDriveList = NULL;
+  fdlg.hMod = NULLHANDLE;
+  strcpy (fdlg.szFullFile, fname);
+  fdlg.papszFQFilename = NULL;
+  fdlg.ulFQFCount = 0;
+  fdlg.usDlgId = 0;
+  fdlg.x = 0; fdlg.y = 0;
+  fdlg.sEAType = 0;
+  return (WinFileDlg (HWND_DESKTOP, get_hwndClient (), &fdlg)
+          && fdlg.lReturn == DID_OK
+          && _abspath (buf, fdlg.szFullFile, CCHMAXPATH) == 0);
+}
+
+
+void command_window::open_exec ()
+{
+  char aname[CCHMAXPATH];
+  if (open_dialog (aname, "Open program file", "*.exe"))
+    gdb->send_cmd ("server file %s", aname);
+}
+
+
+void command_window::open_core ()
+{
+  char aname[CCHMAXPATH];
+  if (open_dialog (aname, "Open core file", "*"))
+    gdb->send_cmd ("server core-file %s", aname);
+}
+
+
+void command_window::open_source ()
+{
+  char aname[CCHMAXPATH];
+  if (open_dialog (aname, "Open source file", "*"))
+    show_source (NULL, aname, true, -1);
+}
+
+
+void command_window::kill_input ()
+{
+  backspace (input_line.length ());
+  input_line.set (0);
+}
+
+
+void command_window::replace_command (const char *s)
+{
+  kill_input ();
+  input_line.set (s);
+  puts (s);
+}
+
+
+void command_window::exec_command ()
+{
+  if (input_line.length () != 0)
+    {
+      cmd_hist *p = new cmd_hist;
+      p->cmd = input_line;
+      p->prev = history;
+      p->next = NULL;
+      if (history != NULL)
+        history->next = p;
+      history = p;
+    }
+  cur_cmd = NULL;
+
+  input_line.append ("\n", 1);
+  puts ("\n", 1);
+  gdb->send_str ((const char *)input_line, input_line.length ());
+  input_line.set (0);
+}
+
+
+void command_window::from_history (bool next)
+{
+  if (cur_cmd == NULL)
+    {
+      if (history == NULL || next)
+        {
+          WinAlarm (HWND_DESKTOP, WA_ERROR);
+          return;
+        }
+      cur_cmd = history;
+    }
+  else
+    {
+      cmd_hist *p = next ? cur_cmd->next : cur_cmd->prev;
+      if (p == NULL)
+        {
+          WinAlarm (HWND_DESKTOP, WA_ERROR);
+          return;
+        }
+      cur_cmd = p;
+    }
+  replace_command (cur_cmd->cmd);
+}
+
+
+void command_window::key (char c)
+{
+  if (gdb->gdb_prompt != gdbio::GSP_CMD && gdb->gdb_prompt != gdbio::GSP_OTHER)
+    {
+      WinAlarm (HWND_DESKTOP, WA_ERROR);
+      return;
+    }
+  if (c == 8 && input_line.length () > 0)
+    {
+      backspace ();
+      input_line.set (input_line.length () - 1);
+    }
+  else if (c == '\n' || c == '\r')
+    {
+      exec_command ();
+    }
+  else if ((unsigned char)c >= 0x20)
+    {
+      input_line.append (&c, 1);
+      puts ((char *)&c, 1);
+    }
+}
+
+
+HWND command_window::create_hwnd_menu ()
+{
+  return WinCreateWindow (get_hwndClient (), WC_MENU, (PSZ)"",
+                          0, 0, 0, 0, 0,
+                          get_hwndClient (), HWND_TOP, 0,
+                          NULL, NULL);
+}
+
+
+#define MAX_MENU        26
+
+void command_window::completion_menu (HWND hwnd, int start, int count,
+                                      int skip)
+{
+  MENUITEM mi;
+  if (count < MAX_MENU)
+    {
+      mi.iPosition = MIT_END;
+      mi.afStyle = MIS_TEXT;
+      mi.afAttribute = 0;
+      mi.hwndSubMenu = NULLHANDLE;
+      mi.hItem = 0;
+      for (int i = 0; i < count; ++i)
+        {
+          mi.id = IDM_COMPLETIONS + start + i;
+          WinSendMsg (hwnd, MM_INSERTITEM, MPFROMP (&mi),
+                      MPFROMP (completions[start + i] + skip));
+        }
+    }
+  else
+    {
+      int i, j, nsub = 1;
+      for (i = 1; i < count; ++i)
+        if (completions[start+i][skip] != completions[start+i-1][skip])
+          ++nsub;
+      bool initial_char = nsub >= 2 && nsub < MAX_MENU;
+      int number = 1;
+      mi.iPosition = MIT_END;
+      mi.afStyle = MIS_SUBMENU | MIS_TEXT;
+      mi.afAttribute = 0;
+      mi.hItem = 0;
+      mi.id = 0;
+      int subcount, max_subcount = (count + MAX_MENU - 1) / MAX_MENU;
+      char text[20];
+      for (i = 0; i < count; i += subcount)
+        {
+          if (initial_char)
+            {
+              text[0] = completions[start+i][skip];
+              text[1] = 0;
+              for (j = i + 1; j < count; ++j)
+                if (completions[start+j][skip] != completions[start+i][skip])
+                  break;
+              subcount = j - i;
+            }
+          else
+            {
+              _itoa (number++, text, 10);
+              subcount = count - i;
+              if (subcount > max_subcount) subcount = max_subcount;
+            }
+          mi.hwndSubMenu = create_hwnd_menu ();
+          completion_menu (mi.hwndSubMenu, start + i, subcount, skip);
+          WinSendMsg (hwnd, MM_INSERTITEM, MPFROMP (&mi), MPFROMP (text));
+        }
+    }
+}
+
+
+void command_window::complete ()
+{
+  if (gdb->gdb_prompt != gdbio::GSP_CMD && gdb->gdb_prompt != gdbio::GSP_OTHER)
+    {
+      WinAlarm (HWND_DESKTOP, WA_ERROR);
+      return;
+    }
+  // TODO: Don't do this in the PM thread (time!)
+  // TODO: hourglass
+  capture *capt = gdb->capture_cmd ("server complete %s",
+                                    (const char *)input_line);
+  if (capt == NULL)
+    {
+      WinAlarm (HWND_DESKTOP, WA_ERROR);
+      return;
+    }
+  delete_capture (capt);
+  completions = gdb->get_output ();
+  POINTL ptl;
+  if (completions.get_lines () == 1)
+    complete (completions[0]);
+  else if (completions.get_lines () != 0 && get_xy (&ptl))
+    {
+      completions.sort ();
+      int skip = 0;
+      char *blank = strrchr (input_line, ' ');
+      if (blank != NULL)
+        skip = blank + 1 - (const char *)input_line;
+
+      HWND hwndPopup = create_hwnd_menu ();
+      completion_menu (hwndPopup, 0, completions.get_lines (), skip);
+      WinPopupMenu (get_hwndFrame (), get_hwndClient (),
+                    hwndPopup, ptl.x, ptl.y, 0,
+                    (PU_HCONSTRAIN | PU_VCONSTRAIN | PU_NONE
+                     | PU_KEYBOARD | PU_MOUSEBUTTON1));
+    }
+}
+
+
+void command_window::complete (const char *p)
+{
+  if (p != NULL && strncmp (p, input_line, input_line.length ()) == 0)
+    {
+      p += input_line.length ();
+      size_t len = strlen (p);
+      input_line.append (p, len);
+      puts (p, len);
+    }
+}
+
+
+void command_window::font ()
+{
+  if (font_dialog ())
+    {
+      srcs->set_font (*this);
+      thr->set_font (*this);
+      brk->set_font (*this);
+      dsp->set_font (*this);
+      reg->set_font (*this);
+      for (src_node *pn = src_list; pn != NULL; pn = pn->next)
+        pn->src->set_font (*this);
+    }
+}
+
+
+MRESULT command_window::wm_char (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  unsigned fsflags = SHORT1FROMMP (mp1);
+  unsigned usch = SHORT1FROMMP (mp2);
+  unsigned usvk = SHORT2FROMMP (mp2);
+  if (fsflags & KC_KEYUP)
+    return 0;
+  if (fsflags & KC_VIRTUALKEY)
+    {
+      HWND hwndTarget = NULLHANDLE;
+      switch (usvk)
+        {
+        case VK_UP:
+          from_history (false);
+          return 0;
+        case VK_DOWN:
+          from_history (true);
+          return 0;
+        case VK_PAGEUP:
+        case VK_PAGEDOWN:
+          if (SHORT1FROMMP (mp1) & KC_CTRL)
+            hwndTarget = get_hwndHbar ();
+          else
+            hwndTarget = get_hwndVbar ();
+          break;
+        }
+      if (hwndTarget != NULLHANDLE)
+        {
+          if (WinIsWindowEnabled (hwndTarget))
+            WinPostMsg (hwndTarget, msg, mp1, mp2);
+          return 0;
+        }
+    }
+  if (fsflags & KC_CHAR)
+    {
+      key (usch);
+      return 0;
+    }
+  if ((fsflags & (KC_CTRL|KC_VIRTUALKEY)) == KC_CTRL
+      && usch >= 0x40 && usch <= 0x7f)
+    {
+      key (usch & 0x1f);
+      return 0;
+    }
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT command_window::pmdebugmode_msg (HWND hwnd, ULONG msg,
+                                         MPARAM mp1, MPARAM mp2)
+{
+  MRESULT mr;
+
+  switch (msg)
+    {
+    case WM_INITDLG:
+      dlg_sys_menu (hwnd);
+      WinSetWindowPtr (hwnd, QWL_USER, this);
+      WinSendDlgItemMsg (hwnd, IDC_SYNC, BM_SETCHECK,
+                         MPFROMSHORT (pmdbg.get_mode () == pmdebug::sync), 0);
+      break;
+
+    case WM_COMMAND:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case DID_OK:
+          mr = WinSendDlgItemMsg (hwnd, IDC_SYNC, BM_QUERYCHECK, 0, 0);
+          pmdbg.set_mode (SHORT1FROMMR (mr) ? pmdebug::sync : pmdebug::off,
+                          get_hwndClient ());
+          WinDismissDlg (hwnd, 0);
+          return 0;
+        }
+      break;
+    }
+  return WinDefDlgProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY dlg_pmdebugmode (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  command_window *p;
+
+  if (msg == WM_INITDLG)
+    p = (command_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
+  else
+    p = (command_window *)WinQueryWindowPtr (hwnd, QWL_USER);
+  return p->pmdebugmode_msg (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT command_window::startup_msg (HWND hwnd, ULONG msg,
+                                     MPARAM mp1, MPARAM mp2)
+{
+  MRESULT mr;
+  char *s, buf[512];
+
+  switch (msg)
+    {
+    case WM_INITDLG:
+      dlg_sys_menu (hwnd);
+      WinSetWindowPtr (hwnd, QWL_USER, this);
+      WinSendDlgItemMsg (hwnd, IDC_CLOSE_WIN, BM_SETCHECK,
+                         MPFROMSHORT (gdb->get_setshow_boolean ("close")), 0);
+
+      WinSendDlgItemMsg (hwnd, IDC_ARGS, EM_SETTEXTLIMIT,
+                         MPFROMSHORT (128), 0);
+      s = gdb->get_setshow_string ("args");
+      WinSetDlgItemText (hwnd, IDC_ARGS, (PSZ)s);
+      delete[] s;
+      break;
+
+    case WM_COMMAND:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case DID_OK:
+        case IDC_RUN:
+          mr = WinSendDlgItemMsg (hwnd, IDC_CLOSE_WIN, BM_QUERYCHECK, 0, 0);
+          // TODO: Only if changed (handle in caller, using a structure)
+          gdb->set_setshow_boolean ("close", (bool)SHORT1FROMMR (mr));
+
+          WinQueryDlgItemText (hwnd, IDC_ARGS, sizeof (buf), (PSZ)buf);
+          gdb->set_setshow_string ("args", buf);
+          WinDismissDlg (hwnd, SHORT1FROMMP (mp1));
+          return 0;
+        }
+      break;
+    }
+  return WinDefDlgProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY dlg_startup (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  command_window *p;
+
+  if (msg == WM_INITDLG)
+    p = (command_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
+  else
+    p = (command_window *)WinQueryWindowPtr (hwnd, QWL_USER);
+  return p->startup_msg (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY dlg_about (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  switch (msg)
+    {
+    case WM_INITDLG:
+      dlg_sys_menu (hwnd);
+      break;
+    case WM_COMMAND:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case DID_OK:
+          WinDismissDlg (hwnd, TRUE);
+          return 0;
+        }
+      break;
+    }
+  return WinDefDlgProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT command_window::history_msg (HWND hwnd, ULONG msg,
+                                     MPARAM mp1, MPARAM mp2)
+{
+  switch (msg)
+    {
+    case WM_INITDLG:
+      dlg_sys_menu (hwnd);
+      WinSetWindowPtr (hwnd, QWL_USER, this);
+      WinSetDlgItemText (hwnd, IDC_LIST, input_line);
+      for (cmd_hist *p = history; p != NULL; p = p->prev)
+        WinSendDlgItemMsg (hwnd, IDC_LIST, LM_INSERTITEM,
+                           MPFROMSHORT (LIT_END),
+                           MPFROMP ((const char *)p->cmd));
+      break;
+
+    case WM_COMMAND:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case DID_OK:
+          int len = WinQueryDlgItemTextLength (hwnd, IDC_LIST);
+          char *text = (char *)alloca (len + 1);
+          *text = 0;
+          if (WinQueryDlgItemText (hwnd, IDC_LIST, len + 1, (PSZ)text) != 0)
+            {
+              replace_command (text);
+              exec_command ();
+            }
+          WinDismissDlg (hwnd, 0);
+          return 0;
+        }
+      break;
+    }
+  return WinDefDlgProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY dlg_history (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  command_window *p;
+
+  if (msg == WM_INITDLG)
+    p = (command_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
+  else
+    p = (command_window *)WinQueryWindowPtr (hwnd, QWL_USER);
+  return p->history_msg (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT command_window::wm_command (HWND hwnd, ULONG msg,
+                                    MPARAM mp1, MPARAM mp2)
+{
+  pm_create create;
+  unsigned id = SHORT1FROMMP (mp1);
+  switch (id)
+    {
+    case IDM_EXIT:
+      WinPostMsg (get_hwndFrame (), WM_CLOSE, 0, 0);
+      return 0;
+
+    case IDM_OPEN_EXEC:
+      open_exec ();
+      return 0;
+
+    case IDM_OPEN_CORE:
+      open_core ();
+      return 0;
+
+    case IDM_OPEN_SOURCE:
+      open_source ();
+      return 0;
+
+    case IDM_WHERE:
+      where ();
+      return 0;
+
+    case IDM_COMPLETE:
+      complete ();
+      return 0;
+
+    case IDM_HISTORY:
+      create.cb = sizeof (create);
+      create.ptr = (void *)this;
+      WinDlgBox (HWND_DESKTOP, hwnd, dlg_history, 0, IDD_HISTORY,
+                 &create);
+      return 0;
+
+    case IDM_FONT:
+      font ();
+      return 0;
+
+    case IDM_ANNOTATE:
+      gdb->show_annotations = !gdb->show_annotations;
+      menu_check (IDM_ANNOTATE, gdb->show_annotations);
+      return 0;
+
+    case IDM_PMDEBUGMODE:
+      create.cb = sizeof (create);
+      create.ptr = (void *)this;
+      WinDlgBox (HWND_DESKTOP, hwnd, dlg_pmdebugmode, 0, IDD_PMDEBUGMODE,
+                 &create);
+      return 0;
+
+    case IDM_STARTUP:
+      create.cb = sizeof (create);
+      create.ptr = (void *)this;
+      if (WinDlgBox (HWND_DESKTOP, hwnd, dlg_startup, 0, IDD_STARTUP,
+                     &create) == IDC_RUN)
+        {
+          prepare_run ();
+          run_command ();
+        }
+      return 0;
+
+    case IDM_BRKPT_LIST:
+      brk->show (true);
+      brk->focus ();
+      return 0;
+
+    case IDM_BRKPT_LINE:
+      brk->add_line (NULL);
+      return 0;
+
+    case IDM_GO:
+      prepare_run ();
+      if (gdb->gdb_running == gdbio::GSR_NONE)
+        run_command ();
+      else
+        gdb->send_cmd ("server continue");
+      return 0;
+
+    case IDM_RESTART:
+      prepare_run ();
+      run_command ();
+      return 0;
+
+    case IDM_STEPINTO:
+      prepare_run ();
+      gdb->send_cmd ("server step");
+      return 0;
+
+    case IDM_STEPOVER:
+      prepare_run ();
+      gdb->send_cmd ("server next");
+      return 0;
+
+    case IDM_ISTEPINTO:
+      prepare_run ();
+      gdb->send_cmd ("server stepi");
+      return 0;
+
+    case IDM_ISTEPOVER:
+      prepare_run ();
+      gdb->send_cmd ("server nexti");
+      return 0;
+
+    case IDM_FINISH:
+      prepare_run ();
+      gdb->send_cmd ("server finish");
+      return 0;
+
+    case IDM_WIN_CMD:
+      show (true);
+      focus ();
+      return 0;
+
+    case IDM_WIN_BRK:
+      brk->show (true);
+      brk->focus ();
+      return 0;
+
+    case IDM_WIN_THR:
+      thr->show (true);
+      thr->focus ();
+      return 0;
+
+    case IDM_WIN_DSP:
+      dsp->show (true);
+      dsp->focus ();
+      return 0;
+
+    case IDM_WIN_SRCS:
+      srcs->show (true);
+      srcs->focus ();
+      return 0;
+
+    case IDM_WIN_REG:
+      reg->show (true);
+      update_registers ();
+      reg->focus ();
+      return 0;
+
+    case IDM_ABOUT:
+      WinDlgBox (HWND_DESKTOP, hwnd, dlg_about, 0, IDD_ABOUT, NULL);
+      return 0;
+
+    case IDM_TUTORIAL:
+      WinSendMsg (get_hwndHelp (), HM_DISPLAY_HELP,
+                  MPFROMSHORT (HELP_TUTORIAL), MPFROMSHORT (HM_RESOURCEID));
+      return 0;
+
+    case IDM_HELP_HELP:
+      WinSendMsg (get_hwndHelp (), HM_DISPLAY_HELP,
+                  MPFROMSHORT (0), MPFROMSHORT (HM_RESOURCEID));
+      return 0;
+
+    case IDM_HELP_KEYS:
+      WinSendMsg (get_hwndHelp (), HM_KEYS_HELP, 0, 0);
+      return 0;
+
+    case IDM_HELP_INDEX:
+      WinSendMsg (get_hwndHelp (), HM_HELP_INDEX, 0, 0);
+      return 0;
+
+    case IDM_HELP_CONTENTS:
+      WinSendMsg (get_hwndHelp (), HM_HELP_CONTENTS, 0, 0);
+      return 0;
+
+    default:
+      if (id >= IDM_WIN_SRC && id < IDM_WIN_SRC + (unsigned)src_menu_id_count)
+        {
+          src_node *pn = src_list;
+          while (pn != NULL && pn->menu_id != id)
+            pn = pn->next;
+          if (pn != NULL)
+            {
+              pn->src->show (true);
+              pn->src->focus ();
+              return 0;
+            }
+        }
+      else if (id >= IDM_COMPLETIONS
+               && id < IDM_COMPLETIONS + (unsigned)completions.get_lines ())
+        complete (completions[id - IDM_COMPLETIONS]);
+      break;
+    }
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT command_window::wm_activate (HWND hwnd, ULONG msg,
+                                     MPARAM mp1, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp1))
+    associate_help (get_hwndFrame ());
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+bool command_window::wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  unsigned change;
+
+  if (parent::wm_user (hwnd, msg, mp1, mp2))
+    return true;
+  switch (msg)
+    {
+    case UWM_STATE:
+      change = LONGFROMMP (mp1);
+      if (change & GSC_PROMPT)
+        {
+          // TODO: Other menus!
+          menu_enable (IDM_RUNMENU, gdb->is_ready ());
+          if (gdb->is_ready ())
+            {
+              if (gdb->stopped_pending)
+                {
+                  gdb->stopped_pending = false;
+                  capture *frames = gdb->frame_head;
+                  if (frames != NULL)
+                    {
+                      gdb->frame_head = NULL; gdb->frame_cur = NULL;
+                      if (frames->source_file.is_set ())
+                        show_source (NULL, frames->source_file.get (),
+                                     true, frames->source_lineno.get ());
+                      else
+                        show_source (NULL, NULL, false, -1);
+                      delete_capture (frames);
+                    }
+                  else
+                    show_source (NULL, NULL, false, -1);
+                  if (reg->is_visible ())
+                    update_registers ();
+                }
+              capture *displays = gdb->display_head;
+              if (displays != NULL)
+                {
+                  gdb->display_head = NULL; gdb->display_cur = NULL;
+                  for (capture *p = displays; p != NULL; p = p->next)
+                    dsp->update (p->disp_number.get (), p->disp_expr.get (),
+                                 p->disp_format.get (), p->disp_value.get (),
+                                 p->disp_enable.get ());
+                  delete_capture (displays);
+                }
+            }
+        }
+      if (change & GSC_RUNNING)
+        {
+          // TODO: IDM_GO
+          bool running = !gdb->is_nochild ();
+          menu_enable (IDM_STEPOVER, running);
+          menu_enable (IDM_STEPINTO, running);
+          menu_enable (IDM_ISTEPOVER, running);
+          menu_enable (IDM_ISTEPINTO, running);
+          menu_enable (IDM_FINISH, running);
+        }
+      if (change & GSC_BREAKPOINTS)
+        {
+          // TODO: Don't do this in the PM thread (time!)
+          // TODO: This may break if this message is processed while
+          //       we're operating on breakpoints (Edit->Modify!)
+          get_breakpoints ();
+        }
+      if (change & GSC_EXEC_FILE)
+        new_debuggee ();
+      return true;
+
+    case UWM_SOURCE:
+      show_new_source ((const new_source *)PVOIDFROMMP (mp1));
+      return true;
+
+    case UWM_CLOSE_SRC:
+      delete_source ((source_window *)PVOIDFROMMP (mp1));
+      return true;
+
+    case UWM_PMDBG_START:
+      pmdbg.start ();
+      return true;
+
+    case UWM_PMDBG_STOP:
+      pmdbg.stop ();
+      return true;
+
+    case UWM_PMDBG_TERM:
+      pmdbg.term ();
+      return true;
+
+    case UWM_FATAL:
+      WinMessageBox (HWND_DESKTOP, HWND_DESKTOP, (PSZ)PVOIDFROMMP (mp1),
+                     (PSZ)"pmgdb", 0,
+                     MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
+      exit (1);
+
+    default:
+      return false;
+    }
+}
+
+
+MRESULT command_window::wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  if (gdb->gdb_running != gdbio::GSR_NONE)
+    {
+      LONG response
+        = WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
+                         (PSZ)"The program is running -- quit anyway?",
+                         (PSZ)get_name (), 0,
+                         (MB_YESNO | MB_QUERY | MB_DEFBUTTON1 | MB_APPLMODAL
+                          | MB_MOVEABLE));
+      if (response != MBID_YES)
+        return 0;
+    }
+  return parent::wm_close (hwnd, msg, mp1, mp2);
+}
+
+
+void command_window::thread ()
+{
+  int ipipe[2], opipe[2], sin, sout, serr;
+  int pid, from_gdb;
+  pmapp app ("pmgdb");
+  app.no_message_loop ();
+
+  if ((sin = dup (0)) == -1) abort ();
+  if ((sout = dup (1)) == -1) abort ();
+  if ((serr = dup (2)) == -1) abort ();
+
+  if (pipe (ipipe) != 0) abort ();
+  if (pipe (opipe) != 0) abort ();
+  if (fcntl (ipipe[0], F_SETFD, 1) != 0) abort ();
+  if (fcntl (opipe[1], F_SETFD, 1) != 0) abort ();
+
+  from_gdb = ipipe[0];
+  setmode (opipe[1], O_BINARY);
+  gdb->send_init (opipe[1]);
+
+  if (dup2 (opipe[0], 0) != 0) abort ();
+  if (dup2 (ipipe[1], 1) != 1) abort ();
+  if (dup2 (ipipe[1], 2) != 2) abort ();
+
+  close (ipipe[1]);
+  close (opipe[0]);
+
+  // Get the current priority of this thread.
+
+  PPIB ppib;
+  PTIB ptib;
+  DosGetInfoBlocks (&ptib, &ppib);
+  ULONG old_priority = ptib->tib_ptib2->tib2_ulpri;
+
+  // Temporarily change the priority of this thread to let GDB inherit
+  // foreground server priority.  Setting the priority of a process in
+  // another session does not work after starting that session.
+
+  if (DosSetPriority (PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0) != 0)
+    DosBeep (400, 200);
+
+  pid = spawnvp (P_SESSION | P_MINIMIZE | P_BACKGROUND, argv[0], argv);
+
+  // Restore the priority of this thread.  (This won't restore the
+  // priority of any threads started by spawnvp() -- but that doesn't
+  // matter because the thread created by emx.dll for
+  // spawnv(P_SESSION) just waits for termination of our child
+  // sessions.  Having too high a priority for such a thread doesn't
+  // hurt.)
+
+  if (DosSetPriority (PRTYS_THREAD, (old_priority >> 8) & 0xff,
+                      old_priority & 0xff, 0) != 0
+      || DosSetPriority (PRTYS_THREAD, (old_priority >> 8) & 0xff,
+                         old_priority & 0xff, 0) != 0)
+    DosBeep (400, 200);
+
+  dup2 (sin, 0); close (sin);
+  dup2 (sout, 1); close (sout);
+  dup2 (serr, 2); close (serr);
+
+  if (pid == -1)
+    {
+      WinPostMsg (get_hwndClient (), UWM_FATAL,
+                  MPFROMP ("Cannot run gdb.exe."), 0);
+      return;
+    }
+
+  gdb->send_init ();
+  gdb->start (from_gdb);
+  gdb->parse_gdb ();
+}
+
+
+void command_window::handle_output (const char *text, int len)
+{
+  puts (text, len);
+}
+
+
+void command_window::show_annotation (const annotation *ann)
+{
+  pmtxt_attr a = get_attr ();
+  set_attr ();
+  if (ann->get_code () == annotation::UNKNOWN)
+    set_bg_color (CLR_GREEN);
+  else
+    set_fg_color (CLR_DARKGREEN);
+  if (get_column () + ann->get_text_len () + 2 > 80)
+    puts ("{}\n", 3);
+  puts ("{", 1);
+  puts (ann->get_text (), ann->get_text_len ());
+  puts ("}", 1);
+  set_attr (a);
+}
+
+
+void command_window::exec_file (const char *s, int len)
+{
+  lock ();
+  if (s == NULL)
+    debuggee.set_null ();
+  else
+    debuggee.set (s, len);
+  unlock ();
+}
+
+
+void command_window::notify (unsigned change)
+{
+  // Use WinPostMsg instead of WinSendMsg because there may not yet be
+  // a message loop
+  WinPostMsg (get_hwndClient (), UWM_STATE, MPFROMLONG (change), 0);
+  for (src_node *p = src_list; p != NULL; p = p->next)
+    WinPostMsg (p->src->get_hwndClient (), UWM_STATE, MPFROMLONG (change), 0);
+}
+
+
+void command_window::new_debuggee ()
+{
+  srcs->delete_all ();
+  srcs->sync ();
+  lock ();
+  menu_enable (IDM_RESTART, !debuggee.is_null ());
+  menu_enable (IDM_GO, !debuggee.is_null ());
+  if (!debuggee.is_null ())
+    {
+      ULONG flags;
+      if (DosQueryAppType (debuggee, &flags) == 0
+          && (flags & FAPPTYP_EXETYPE) == FAPPTYP_WINDOWAPI)
+        pmdbg.set_mode (pmdebug::sync, get_hwndClient ());
+      const char *temp = _getname (debuggee);
+      unlock ();
+      astring title; title = "pmgdb - ";
+      title.append (temp);
+      set_title (title);
+      bool ok = false;
+      capture *capt = gdb->capture_cmd ("server info sources");
+      if (capt != NULL)
+        {
+          for (capture *c = capt; c != NULL; c = c->next)
+            if (c->srcs_file.is_set ())
+              {
+                srcs->add (c->srcs_file.get ());
+                ok = true;
+              }
+          srcs->done ();
+          delete_capture (capt);
+          capt = gdb->capture_cmd ("server info line main");
+          if (capt != NULL && capt->source_file.is_set ())
+            srcs->select (_getname (capt->source_file.get ()));
+          delete_capture (capt);
+        }
+      if (ok)
+        srcs->show (true);
+    }
+  else
+    {
+      unlock ();
+      set_title ("pmgdb");
+    }
+}
+
+
+void command_window::where ()
+{
+  capture *capt = gdb->capture_cmd ("server info line *$pc");
+  if (capt != NULL && capt->source_file.is_set ())
+    show_source (NULL, capt->source_file.get (), true,
+                 capt->source_lineno.get ());
+  else
+    show_source (NULL, NULL, false, -1);
+  delete_capture (capt);
+}
+
+
+void command_window::update_registers ()
+{
+  capture *capt = gdb->capture_cmd ("server info registers");
+  if (capt != NULL)
+    reg->update (gdb->get_output ());
+  delete_capture (capt);
+}
+
+
+void command_window::help_disable (const pmframe *frame)
+{
+  frame->menu_enable (IDM_HELP_EXT, false, true);
+  frame->menu_enable (IDM_HELP_HELP, false, true);
+  frame->menu_enable (IDM_HELP_KEYS, false, true);
+  frame->menu_enable (IDM_HELP_INDEX, false, true);
+  frame->menu_enable (IDM_HELP_CONTENTS, false, true);
+  frame->menu_enable (IDM_TUTORIAL, false, true);
+}
+
+
+void command_window::associate_help (HWND hwnd)
+{
+  if (get_hwndHelp () != NULLHANDLE)
+    WinAssociateHelpInstance (get_hwndHelp (), hwnd);
+}
+
+
+void command_window::run_command ()
+{
+  if (!breakpoints.any_enabled ())
+    gdb->queue_cmd ("server break main");
+  gdb->queue_cmd ("server run");
+}
+
+
+void command_window::prepare_run ()
+{
+  gdb->prepare_run ();
+  HWND hwndLock = WinQueryFocus (HWND_DESKTOP);
+  if (hwndLock == NULLHANDLE)
+    hwndLock = get_hwndClient ();
+  pmdbg.set_window (hwndLock);
+  pmdbg_start ();
+}
+
+
+void command_window::pmdbg_start ()
+{
+  if (same_tid ())
+    pmdbg.start ();
+  else
+    WinSendMsg (get_hwndClient (), UWM_PMDBG_START, 0, 0);
+}
+
+
+void command_window::pmdbg_stop ()
+{
+  if (same_tid ())
+    pmdbg.stop ();
+  else
+    WinSendMsg (get_hwndClient (), UWM_PMDBG_STOP, 0, 0);
+}
+
+
+void command_window::pmdbg_term ()
+{
+  if (same_tid ())
+    pmdbg.term ();
+  else
+    WinSendMsg (get_hwndClient (), UWM_PMDBG_TERM, 0, 0);
+}
Index: trunk/src/emx/src/pmgdb/command.h
===================================================================
--- trunk/src/emx/src/pmgdb/command.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/command.h	(revision 18)
@@ -0,0 +1,176 @@
+/* command.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class capture;
+class annotation;
+class gdbio;
+class display_window;
+class threads_window;
+class breakpoints_window;
+class breakpoint;
+class source_window;
+class source_files_window;
+class register_window;
+
+
+class command_window : public pmtty
+{
+public:
+  typedef pmtty parent;
+
+  // Contructors and destructors
+  command_window (pmapp *app, unsigned id, const char *fontnamesize,
+                  char **argv);
+  ~command_window ();
+
+  // Querying members
+  const breakpoint_list::brkpt_node *get_breakpoint_list () const
+    { return breakpoints.list; }
+  const breakpoint *get_breakpoint (int n) const;
+  const char *get_debuggee () const { return debuggee; }
+  const source_files_window *get_srcs () const { return srcs; }
+
+  // Override member functions of pmframe
+  MRESULT wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+  // etc.
+  void show_source (const char *short_fname, const char *long_fname,
+                    bool set_focus, int lineno = -1);
+  void capture_error (const capture *p);
+  void run_command ();
+  void prepare_run ();
+  void show_annotation (const annotation *ann);
+  void exec_file (const char *s, int len);
+  void where ();
+  void handle_output (const char *text, int len);
+  void associate_help (HWND hwnd);
+  void update_registers ();
+  void get_breakpoints ();
+
+  // Constants
+
+  enum
+  {
+    GSC_PROMPT      = 0x0001,
+    GSC_RUNNING     = 0x0002,
+    GSC_BREAKPOINTS = 0x0004,
+    GSC_EXEC_FILE   = 0x0008
+  };
+
+private:
+
+  struct new_source;
+
+  void lock ();
+  void unlock ();
+  void key (char c);
+  void kill_input ();
+  void complete ();
+  void complete (const char *p);
+  HWND create_hwnd_menu ();
+  void completion_menu (HWND hwnd, int start, int count, int skip);
+  void from_history (bool next);
+  void replace_command (const char *s);
+  void exec_command ();
+  void font ();
+  void arg_add (const char *str);
+  void arg_delete_all ();
+  void thread ();
+  void notify (unsigned change);
+  void show_new_source (const new_source *ns);
+  void delete_source (source_window *src);
+  bool open_dialog (char *buf, const char *title, const char *fname);
+  void open_exec ();
+  void open_core ();
+  void open_source ();
+  void brkpt_update (int index, const breakpoint *old_bpt,
+                     const breakpoint *new_bpt);
+  void get_breakpoints (source_window *src, bool paint);
+  source_window *find_source_short (const char *fname);
+  source_window *find_source_long (const char *fname);
+  void pmdbg_start ();
+  void pmdbg_stop ();
+  void pmdbg_term ();
+  MRESULT pmdebugmode_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT startup_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT history_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  void new_debuggee ();
+  void help_disable (const pmframe *frame);
+
+  // Override member functions of pmtxt
+  MRESULT wm_char (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  bool wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+  struct src_node               // Perhaps we should use a container class...
+  {
+    struct src_node *next;
+    source_window *src;
+    HWND hwndWinMenu;
+    unsigned menu_id;
+  };
+
+  struct cmd_hist;
+
+  // Data members
+
+  bool exec_file_pending;
+  bool help_ok;
+  char **argv;
+  int argv_used;
+  int argv_size;
+  fstring debuggee;
+
+  _fmutex mutex;                // Hide pmtxt::mutex
+
+  astring input_line;
+  lstring completions;
+  cmd_hist *history;
+  cmd_hist *cur_cmd;
+
+  src_node *src_list;
+  int src_menu_id_count;
+  char *src_menu_id_used;
+
+  breakpoint_list breakpoints;
+
+  breakpoints_window *brk;
+  display_window *dsp;
+  threads_window *thr;
+  source_files_window *srcs;
+  register_window *reg;
+
+  gdbio *gdb;
+
+  // Friends
+  // TODO: Use more friends instead of public members?
+
+  friend source_window;
+  friend gdbio;
+  friend void command_window_thread (void *arg);
+  friend MRESULT EXPENTRY
+    dlg_pmdebugmode (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  friend MRESULT EXPENTRY
+    dlg_startup (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  friend MRESULT EXPENTRY
+    dlg_history (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+};
Index: trunk/src/emx/src/pmgdb/display.cc
===================================================================
--- trunk/src/emx/src/pmgdb/display.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/display.cc	(revision 18)
@@ -0,0 +1,976 @@
+/* display.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>              // sprintf()
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "pmgdb.h"
+#include "help.h"
+#include "breakpoi.h"
+#include "display.h"
+#include "annotati.h"
+#include "capture.h"
+#include "gdbio.h"
+#include "command.h"
+
+
+class dispfmt
+{
+public:
+  dispfmt () { count = 1; format = 0; size = 0; }
+  ~dispfmt () {}
+  void parse (const char *str);
+  void print (char *str) const;
+
+  int count;
+  char format;
+  char size;
+};
+
+
+class display_window::display
+{
+public:
+  display () { enable = true; type = not_set; }
+  display (const display &src);
+  ~display () {}
+  bool is_line (int y) { return line <= y && y < line + line_count; }
+  void set_type (gdbio *gdb);
+  display &operator = (const display &src);
+
+  // Dialog box
+  MRESULT display_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+  vstring expr;
+  vstring format;
+  vstring value;
+  display *next;
+  int number;
+  int line;
+  int line_count;
+  enum
+  {
+    not_set,
+    pointer,
+    other,
+  } type;
+  bool enable;
+};
+
+
+void dispfmt::parse (const char *s)
+{
+  count = 1; size = 0; format = 0;
+  s = strchr (s, '/');
+  s = s != NULL ? s + 1 : "";
+  if (*s >= '0' && *s <= '9')
+    {
+      count = atoi (s);
+      while (*s >= '0' && *s <= '9')
+        ++s;
+    }
+  while (*s != 0)
+    if (*s == 'b' || *s == 'h' || *s == 'w' || *s == 'g')
+      size = *s++;
+    else if (*s >= 'a' && *s <= 'z')
+      format = *s++;
+    else
+      break;
+}
+
+
+void dispfmt::print (char *str) const
+{
+  if (count != 1 || format != 0 || size != 0)
+    {
+      if (count != 1)
+        str += sprintf (str, "/%d", count);
+      else
+        *str++ = '/';
+      if (format != 0)
+        *str++ = format;
+      if (size != 0)
+        *str++ = size;
+    }
+  *str = 0;
+}
+
+
+display_window::display::display (const display &src)
+{
+  expr = src.expr;
+  format = src.format;
+  value = src.value;
+  next = NULL;
+  number = src.number;
+  line = src.line;
+  line_count = src.line_count;
+  enable = src.enable;
+}
+
+
+void display_window::display::set_type (gdbio *gdb)
+{
+  capture *capt;
+  capt = gdb->capture_cmd ("whatis %s", (const char *)expr);
+  if (capt == NULL)
+    return;
+  if (capt->error.is_set ())
+    type = other;
+  else
+    {
+      const char *s = gdb->get_output ();
+      int len = gdb->get_output ().length ();
+      while (len > 0 && s[len-1] == '\n')
+        --len;
+      if (len > 0 && s[len-1] == '*')
+        type = pointer;
+      else
+        type = other;
+    }
+  delete_capture (capt);
+}
+
+
+display_window::display
+&display_window::display::operator = (const display &src)
+{
+  expr = src.expr;
+  format = src.format;
+  value = src.value;
+  next = NULL;
+  number = src.number;
+  line = src.line;
+  line_count = src.line_count;
+  enable = src.enable;
+  type = src.type;
+  return *this;
+}
+
+
+static const struct
+{
+  const char *desc;
+  char chr;
+} formats[] =
+  {
+    {"Default",          0},
+    {"Signed decimal",   'd'},
+    {"Unsigned decimal", 'u'},
+    {"Hexadecimal",      'x'},
+    {"Octal",            'o'},
+    {"Binary",           't'},
+    {"Character",        'c'},
+    {"Address",          'a'},
+    {"Floating point",   'f'},
+    {"String",           's'},
+    {"Instruction",      'i'}
+  };
+
+#define N_FORMATS       (sizeof (formats) / sizeof (formats[0]))
+
+MRESULT display_window::display::display_msg (HWND hwnd, ULONG msg,
+                                              MPARAM mp1, MPARAM mp2)
+{
+  MRESULT mr;
+  HWND hwndTemp;
+  int i;
+  char fmtstr[40];
+
+  switch (msg)
+    {
+    case WM_INITDLG:
+      {
+        dispfmt fmt;
+        dlg_sys_menu (hwnd);
+        WinSetWindowPtr (hwnd, QWL_USER, this);
+        WinSendDlgItemMsg (hwnd, IDC_ENABLE, BM_SETCHECK,
+                           MPFROMSHORT (enable), NULL);
+        WinSendDlgItemMsg (hwnd, IDC_EXPR, EM_SETTEXTLIMIT,
+                           MPFROMSHORT (128), 0);
+        if (!expr.is_null ())
+          WinSetDlgItemText (hwnd, IDC_EXPR, (PCSZ)expr);
+        if (!format.is_null ())
+          fmt.parse (format);
+        hwndTemp = WinWindowFromID (hwnd, IDC_FORMAT);
+        for (i = 0; i < (int)N_FORMATS; ++i)
+          {
+            WinSendMsg (hwndTemp, LM_INSERTITEM, MPFROMSHORT (i),
+                        MPFROMP (formats[i].desc));
+            if (formats[i].chr == fmt.format)
+              WinSendMsg (hwndTemp, LM_SELECTITEM,
+                          MPFROMSHORT (i), MPFROMSHORT (TRUE));
+          }
+        if (fmt.format == 0)
+          WinSendMsg (hwndTemp, LM_SELECTITEM,
+                      MPFROMSHORT (0), MPFROMSHORT (TRUE));
+        WinSendDlgItemMsg (hwnd, IDC_COUNT, SPBM_SETCURRENTVALUE,
+                           MPFROMLONG (fmt.count), 0);
+        WinSendDlgItemMsg (hwnd, IDC_COUNT, SPBM_SETLIMITS,
+                           MPFROMLONG (99), MPFROMLONG (1));
+        break;
+      }
+
+    case WM_CONTROL:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case IDC_FORMAT:
+          mr = WinSendDlgItemMsg (hwnd, IDC_FORMAT, LM_QUERYSELECTION,
+                                  MPFROMSHORT (LIT_FIRST), 0);
+          i = SHORT1FROMMR (mr);
+          bool enable_count = (i != LIT_NONE
+                               && (formats[i].chr == 's'
+                                   || formats[i].chr == 'i'));
+          WinEnableWindow (WinWindowFromID (hwnd, IDC_COUNT), enable_count);
+          break;
+        }
+      return 0;
+
+    case WM_COMMAND:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case DID_OK:
+          {
+            dispfmt fmt;
+            LONG n;
+            mr = WinSendDlgItemMsg (hwnd, IDC_ENABLE, BM_QUERYCHECK, 0, 0);
+            enable = (bool)SHORT1FROMMR (mr);
+            LONG len = WinQueryDlgItemTextLength (hwnd, IDC_EXPR);
+            expr.set (len);
+            WinQueryDlgItemText (hwnd, IDC_EXPR, len + 1, (PSZ)expr.modify ());
+
+            mr = WinSendDlgItemMsg (hwnd, IDC_FORMAT, LM_QUERYSELECTION,
+                                    MPFROMSHORT (LIT_FIRST), 0);
+            i = SHORT1FROMMR (mr);
+            if (i != LIT_NONE && i != 0)
+              {
+                fmt.format = formats[i].chr;
+                if (fmt.format == 's' || fmt.format == 'i')
+                  {
+                    mr = WinSendDlgItemMsg (hwnd, IDC_COUNT, SPBM_QUERYVALUE,
+                                            MPFROMP (&n),
+                                            MPFROM2SHORT (0,
+                                                          SPBQ_ALWAYSUPDATE));
+                    if (SHORT1FROMMR (mr))
+                      fmt.count = n;
+                  }
+                fmt.print (fmtstr);
+                format.set (fmtstr);
+              }
+            else
+              format.set ("");
+            WinDismissDlg (hwnd, DID_OK);
+            return 0;
+          }
+        }
+      break;
+    }
+  return WinDefDlgProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY dlg_display (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  display_window::display *p;
+
+  if (msg == WM_INITDLG)
+    p = (display_window::display *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
+  else
+    p = (display_window::display *)WinQueryWindowPtr (hwnd, QWL_USER);
+  return p->display_msg (hwnd, msg, mp1, mp2);
+}
+
+
+#define DSP_HEADER_LINES        1
+
+display_window::display_window (command_window *in_cmd, gdbio *in_gdb,
+                                unsigned in_id, const SWP *pswp,
+                                const char *fontnamesize)
+  : pmtxt (in_cmd->get_app (), in_id,
+           pswp == NULL ? FCF_SHELLPOSITION : 0, pswp, fontnamesize)
+{
+  cmd = in_cmd; gdb = in_gdb;
+  head = NULL;
+  sel_line = -1;
+  exp_number = -1;
+
+  sel_attr = get_default_attr ();
+  set_fg_color (sel_attr, CLR_BLACK);
+  set_bg_color (sel_attr, CLR_PALEGRAY);
+
+  delete_all_displays (true);   // Update menu, insert header line
+  set_title ("pmgdb - Display");
+  set_keys_help_id (HELP_THR_KEYS);
+}
+
+
+display_window::~display_window ()
+{
+  delete_all_displays (false);
+}
+
+
+void display_window::delete_all_displays (bool init)
+{
+  display *p, *next;
+  for (p = head; p != NULL; p = next)
+    {
+      next = p->next;
+      delete p;
+    }
+  head = NULL;
+  sel_line = -1;
+
+  if (init)
+    {
+      delete_all ();
+      int x = 0;
+      put (0, x, 4, " No ", false); x += 4;
+      put_tab (0, x++, false);
+      put_vrule (0, x++, false);
+      put (0, x, 5, " Ena ", false); x += 5;
+      put_tab (0, x++, false);
+      put_vrule (0, x++, false);
+      put (0, x, 5, " Fmt ", false); x += 5;
+      put_tab (0, x++, false);
+      put_vrule (0, x++, false);
+      put (0, x, 6, " Expr ", false); x += 6;
+      put_tab (0, x++, false);
+      put_vrule (0, x++, false);
+      put (0, x, 6, " Value", false); x += 6;
+      underline (0, true, false);
+      sync ();
+      menu_enable (IDM_ENABLE, false);
+      menu_enable (IDM_DISABLE, false);
+      menu_enable (IDM_MODIFY, false);
+      menu_enable (IDM_DELETE, false);
+      menu_enable (IDM_ENABLE_ALL, false);
+      menu_enable (IDM_DISABLE_ALL, false);
+      menu_enable (IDM_DELETE_ALL, false);
+      menu_enable (IDM_REPMENU, false);
+      menu_enable (IDM_DEREFERENCE, false);
+    }
+}
+
+
+bool display_window::add (HWND hwnd)
+{
+  bool result = false;
+  display temp;
+  pm_create create;
+  create.cb = sizeof (create);
+  create.ptr = (void *)&temp;
+  if (WinDlgBox (HWND_DESKTOP, hwnd, dlg_display, 0, IDD_DISPLAY,
+                 &create) == DID_OK
+      && temp.expr[0] != 0)
+    {
+      select_line (-1);
+      capture *capt;
+      capt = gdb->capture_cmd ("server display %s %s",
+                               (const char *)temp.format,
+                               (const char *)temp.expr);
+      if (capt != NULL && capt->disp_number.is_set ())
+        {
+          int number = capt->disp_number.get ();
+          if (!temp.enable)
+            gdb->send_cmd ("server disable display %d", number);
+          exp_number = number;
+          exp_line = -1;
+          exp_enable = temp.enable;
+          result = true;
+        }
+      delete_capture (capt);
+    }
+  return result;
+}
+
+
+MRESULT display_window::wm_close (HWND, ULONG, MPARAM, MPARAM)
+{
+  show (false);
+  return 0;
+}
+
+
+MRESULT display_window::wm_command (HWND hwnd, ULONG msg,
+                                    MPARAM mp1, MPARAM mp2)
+{
+  display *p;
+
+  switch (SHORT1FROMMP (mp1))
+    {
+    case IDM_ENABLE:
+      p = find_by_line (sel_line);
+      if (p == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        gdb->send_cmd ("server enable display %d", p->number);
+      return 0;
+
+    case IDM_DISABLE:
+      p = find_by_line (sel_line);
+      if (p == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        gdb->send_cmd ("server disable display %d", p->number);
+      return 0;
+
+    case IDM_DELETE:
+      p = find_by_line (sel_line);
+      if (p == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        gdb->send_cmd ("server undisplay %d", p->number);
+      return 0;
+
+    case IDM_ADD:
+      add (hwnd);
+      return 0;
+
+    case IDM_MODIFY:
+      p = find_by_line (sel_line);
+      if (p == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        modify (p);
+      return 0;
+
+    case IDM_ENABLE_ALL:
+      gdb->send_cmd ("server enable display");
+      return 0;
+
+    case IDM_DISABLE_ALL:
+      gdb->send_cmd ("server disable display");
+      return 0;
+
+    case IDM_DELETE_ALL:
+      gdb->send_cmd ("server undisplay");
+      delete_all_displays (true); // GDB doesn't send an annotation!
+      return 0;
+
+    case IDM_REP_DEC_S:
+      change_representation ('d');
+      return 0;
+
+    case IDM_REP_DEC_U:
+      change_representation ('u');
+      return 0;
+
+    case IDM_REP_HEX:
+      change_representation ('x');
+      return 0;
+
+    case IDM_REP_OCT:
+      change_representation ('o');
+      return 0;
+
+    case IDM_REP_BIN:
+      change_representation ('t');
+      return 0;
+
+    case IDM_REP_ADR:
+      change_representation ('a');
+      return 0;
+
+    case IDM_REP_CHR:
+      change_representation ('c');
+      return 0;
+
+    case IDM_REP_FLT:
+      change_representation ('f');
+      return 0;
+
+    case IDM_REP_STR:
+      change_representation ('s');
+      return 0;
+
+    case IDM_REP_INS:
+      change_representation ('i');
+      return 0;
+
+    case IDM_DEREFERENCE:
+      p = find_by_line (sel_line);
+      if (p == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        dereference (p, false);
+      return 0;
+
+    default:
+      return cmd->wm_command (hwnd, msg, mp1, mp2);
+    }
+}
+
+
+bool display_window::wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  if (parent::wm_user (hwnd, msg, mp1, mp2))
+    return true;
+  switch (msg)
+    {
+    case UWM_MENU:
+      // TODO: Cache
+      if (sel_line == -1)
+        {
+          menu_enable (IDM_ENABLE, false);
+          menu_enable (IDM_DISABLE, false);
+          menu_enable (IDM_MODIFY, false);
+          menu_enable (IDM_DELETE, false);
+          menu_enable (IDM_REPMENU, false);
+          menu_enable (IDM_DEREFERENCE, false);
+        }
+      else
+        {
+          const display *p = find_by_line (sel_line);
+          menu_enable (IDM_ENABLE, !p->enable);
+          menu_enable (IDM_DISABLE, p->enable);
+          menu_enable (IDM_MODIFY, true);
+          menu_enable (IDM_DELETE, true);
+          menu_enable (IDM_REPMENU, true);
+          // TODO: null pointer
+          menu_enable (IDM_DEREFERENCE, p->type == display::pointer);
+        }
+      menu_enable (IDM_ENABLE_ALL, head != NULL);
+      menu_enable (IDM_DISABLE_ALL, head != NULL);
+      menu_enable (IDM_DELETE_ALL, head != NULL);
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+
+MRESULT display_window::wm_activate (HWND hwnd, ULONG msg,
+                                     MPARAM mp1, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp1))
+    cmd->associate_help (get_hwndFrame ());
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+void display_window::button_event (int line, int column, int tab, int button,
+                                   int clicks)
+{
+  if (line >= 0 && column >= 0)
+    {
+      // TODO: Context menu
+      if (button == 1 && clicks == 2 && tab == 1)
+        {
+          const display *p = find_by_line (line);
+          if (p == NULL)
+            WinAlarm (HWND_DESKTOP, WA_ERROR);
+          else
+            gdb->send_cmd ("server %s display %d",
+                           p->enable ? "disable" : "enable", p->number);
+        }
+      else if (button == 1 && clicks == 2 && tab >= 2 && tab <= 3)
+        {
+          display *p = find_by_line (line);
+          if (p == NULL)
+            WinAlarm (HWND_DESKTOP, WA_ERROR);
+          else
+            {
+              select_line (line);
+              modify (p);
+            }
+        }
+      else if (button == 1 && clicks == 1)
+        select_line (line, true);
+      else if (button == 1 && clicks == 2)
+        select_line (line);
+    }
+  else
+    select_line (-1);
+}
+
+
+display_window::display *display_window::find_by_number (int number)
+{
+  for (display *p = head; p != NULL; p = p->next)
+    if (p->number == number)
+      return p;
+  return NULL;
+}
+
+
+display_window::display *display_window::find_by_line (int line)
+{
+  for (display *p = head; p != NULL; p = p->next)
+    if (p->is_line (line))
+      return p;
+  return NULL;
+}
+
+
+void display_window::enable (int number)
+{
+  display *p = find_by_number (number);
+  if (p != NULL && !p->enable)
+    {
+      p->enable = true;
+      if (p->line == sel_line)
+        WinPostMsg (get_hwndClient (), UWM_MENU, 0, 0);
+      update (p);
+    }
+}
+
+
+void display_window::disable (int number)
+{
+  display *p = find_by_number (number);
+  if (p != NULL && p->enable)
+    {
+      p->enable = false;
+      if (p->line == sel_line)
+        WinPostMsg (get_hwndClient (), UWM_MENU, 0, 0);
+      update (p);
+    }
+}
+
+
+void display_window::remove (int number)
+{
+  for (display **patch = &head; *patch != NULL; patch = &(*patch)->next)
+    if ((*patch)->number == number)
+      {
+        display *p = *patch;
+        for (display *q = (*patch)->next; q != NULL; q = q->next)
+          q->line -= p->line_count;
+        if (p->line == sel_line)
+          {
+            sel_line = -1;
+            WinPostMsg (get_hwndClient (), UWM_MENU, 0, 0);
+          }
+        delete_lines (p->line, p->line_count, true);
+        *patch = p->next;
+        delete p;
+        return;
+      }
+}
+
+
+void display_window::update (display *p)
+{
+  char buf[400];
+  int x = 0, len, line_count, diff;
+  pmtxt_attr attr;
+
+  if (p->line == sel_line)
+    attr = sel_attr;
+  else
+    attr = get_default_attr ();
+
+  line_count = 1;
+  if (p->enable)
+    for (const char *s = p->value; *s != 0; ++s)
+      if (*s == '\n')
+        ++line_count;
+
+  diff = line_count - p->line_count;
+  if (diff < 0)
+    delete_lines (p->line + line_count, -diff, true);
+  if (diff > 0)
+    insert_lines (p->line + p->line_count, diff, true);
+  if (diff != 0)
+    {
+      for (display *q = p->next; q != NULL; q = q->next)
+        q->line += diff;
+      if (sel_line == p->line)
+        sel_count = line_count;
+      else if (sel_line > p->line)
+        sel_line += diff;
+      p->line_count = line_count;
+    }
+  clear_lines (p->line, line_count, true);
+
+  len = snprintf (buf, sizeof (buf), " %d ", p->number);
+  put (p->line, x, len, buf, attr, true); x += len;
+  put_tab (p->line, x++, attr, true);
+  put_vrule (p->line, x++, attr, true);
+
+  len = snprintf (buf, sizeof (buf), " %c ", p->enable ? 'y' : 'n');
+  put (p->line, x, len, buf, attr, true); x += len;
+  put_tab (p->line, x++, attr, true);
+  put_vrule (p->line, x++, attr, true);
+
+  len = snprintf (buf, sizeof (buf), " %s ", (const char *)p->format);
+  put (p->line, x, len, buf, attr, true); x += len;
+  put_tab (p->line, x++, attr, true);
+  put_vrule (p->line, x++, attr, true);
+
+  len = snprintf (buf, sizeof (buf), " %s ", (const char *)p->expr);
+  put (p->line, x, len, buf, attr, true); x += len;
+  put_tab (p->line, x++, attr, true);
+  put_vrule (p->line, x++, attr, true);
+
+  if (p->line == sel_line)
+    set_eol_attr (p->line, sel_attr, true);
+
+  if (p->enable)
+    {
+      int y = p->line;
+      const char *s = p->value;
+      while (*s != 0)
+        {
+          const char *nl = strchr (s, '\n');
+          len = nl != NULL ? nl - s : strlen (s);
+          if (y != p->line)
+            {
+              if (p->line == sel_line)
+                set_eol_attr (y, sel_attr, true);
+              for (int i = 0; i < 4; ++i)
+                {
+                  put_tab (y, x++, attr, true);
+                  put_vrule (y, x++, attr, true);
+                }
+            }
+          put (y, x++, 1, " ", attr, true);
+          const char *tab;
+          while ((tab = (const char *)memchr (s, '\t', len)) != NULL)
+            {
+              if (tab != s)
+                {
+                  put (y, x, tab - s, s, attr, true);
+                  x += tab - s; len -= tab - s; s = tab;
+                }
+              ++s; --len;       // Skip TAB
+              put (y, x++, 1, " ", attr, true);
+              put_tab (y, x++, attr, true);
+            }
+          if (len != 0)
+            {
+              put (y, x, len, s, attr, true);
+              s += len;
+            }
+          if (*s != 0)
+            {
+              ++s;              // Skip linefeed
+              ++y; x = 0;       // New line
+            }
+        }
+    }
+}
+
+
+void display_window::update (int number, const char *expr, const char *format,
+                             const char *value, bool enable)
+{
+  int undisplay = -1;
+  display *p = find_by_number (number);
+  if (value == NULL) value = "";
+
+  if (p == NULL)
+    {
+      if (exp_number == number && exp_line != -1
+          && (p = find_by_line (exp_line)) != NULL)
+        {
+          // Modifying a display
+          undisplay = p->number;
+          p->line = exp_line;
+        }
+      else
+        {
+          // New display
+          if (head == NULL)
+            {
+              menu_enable (IDM_ENABLE_ALL, true);
+              menu_enable (IDM_DISABLE_ALL, true);
+              menu_enable (IDM_DELETE_ALL, true);
+            }
+
+          display **patch = &head;
+          int line = DSP_HEADER_LINES;
+          while (*patch != NULL)
+            {
+              line += (*patch)->line_count;
+              patch = &(*patch)->next;
+            }
+          p = new display;
+          *patch = p;
+          p->next = NULL;
+          p->line = line;
+          p->line_count = 1;
+          p->enable = true;
+        }
+      p->number = number;
+      p->expr.set (expr);
+      p->format.set (format);
+      p->value.set (value);
+      p->set_type (gdb);
+    }
+  else
+    {
+      if (number != exp_number && strcmp (value, p->value) == 0)
+        return;
+      // TODO: Redraw value only (if only the value changed)
+      p->value.set (value);
+    }
+
+  // Set the state of a new display before GDB knows about and reports
+  // the new state
+  if (number == exp_number)
+    {
+      p->enable = exp_enable;
+      select_line (p->line);
+    }
+  if (!enable)
+    p->enable = false;
+  exp_number = -1;
+  if (undisplay != -1)
+    gdb->send_cmd ("server undisplay %d", undisplay);
+  update (p);
+}
+
+
+void display_window::select_line (int line, bool toggle)
+{
+  const display *p = line == -1 ? (display *)NULL : find_by_line (line);
+  line = p != NULL ? p->line : -1; // Normalize
+  if (toggle && line != -1 && line == sel_line)
+    line = -1;
+  if (line != sel_line)
+    {
+      if (sel_line != -1)
+        for (int i = 0; i < sel_count; ++i)
+          {
+            put (sel_line + i, 0, max_line_len, get_default_attr (), true);
+            set_eol_attr (sel_line + i, get_default_attr (), true);
+          }
+      if (line != -1)
+        {
+          sel_count = p->line_count;
+          for (int i = 0; i < sel_count; ++i)
+            {
+              put (line + i, 0, max_line_len, sel_attr, true);
+              set_eol_attr (line + i, sel_attr, true);
+            }
+        }
+      sel_line = line;
+    }
+  // TODO: Cache
+  if (line != -1)
+    {
+      menu_enable (IDM_ENABLE, !p->enable);
+      menu_enable (IDM_DISABLE, p->enable);
+      menu_enable (IDM_MODIFY, true);
+      menu_enable (IDM_DELETE, true);
+      menu_enable (IDM_REPMENU, true);
+      menu_enable (IDM_DEREFERENCE, p->type == display::pointer);
+      show_line (line, 1, 1);
+    }
+  else
+    {
+      menu_enable (IDM_ENABLE, false);
+      menu_enable (IDM_DISABLE, false);
+      menu_enable (IDM_MODIFY, false);
+      menu_enable (IDM_DELETE, false);
+      menu_enable (IDM_REPMENU, false);
+      menu_enable (IDM_DEREFERENCE, false);
+    }
+}
+
+
+void display_window::modify (const display *p, const char *new_format,
+                             const char *new_expr, bool new_enable, bool add)
+{
+  select_line (-1);
+  if (new_format == NULL)
+    new_format = p->format;
+  if (new_expr == NULL)
+    new_expr = p->expr;
+  capture *capt;
+  capt = gdb->capture_cmd ("server display %s %s", new_format, new_expr);
+  if (capt != NULL && capt->disp_number.is_set ())
+    {
+      int number = capt->disp_number.get ();
+      exp_number = number;
+      exp_enable = new_enable;
+      exp_line = add ? -1 : p->line;
+      if (!new_enable)
+        gdb->send_cmd ("server disable display %d", number);
+    }
+  delete_capture (capt);
+}
+
+
+void display_window::change_representation (char fmtchr)
+{
+  display *p = find_by_line (sel_line);
+  if (p == NULL)
+    {
+      WinAlarm (HWND_DESKTOP, WA_ERROR);
+      return;
+    }
+
+  dispfmt fmt;
+  fmt.parse (p->format);
+
+  if (fmtchr == fmt.format)
+    return;
+  fmt.format = fmtchr;
+  char new_format_buf[20];
+  fmt.print (new_format_buf);
+  modify (p, new_format_buf, NULL, p->enable, false);
+}
+
+
+void display_window::modify (display *p)
+{
+  display temp = *p;
+  pm_create create;
+  create.cb = sizeof (create);
+  create.ptr = (void *)&temp;
+  if (WinDlgBox (HWND_DESKTOP, get_hwndClient (), dlg_display, 0, IDD_DISPLAY,
+                 &create) == DID_OK
+      && temp.expr[0] != 0
+      && (temp.enable != p->enable
+          || strcmp (temp.expr, p->expr) != 0
+          || strcmp (temp.format, p->format) != 0))
+    {
+      if (strcmp (temp.expr, p->expr) == 0
+          && strcmp (temp.format, p->format) == 0)
+        gdb->send_cmd ("server %s display %d",
+                       temp.enable ? "enable" : "disable", p->number);
+      else
+        modify (p, temp.format, temp.expr, temp.enable, false);
+    }
+}
+
+
+void display_window::dereference (display *p, bool add)
+{
+  astring expr;
+  expr = "*(";
+  expr.append (p->expr);
+  expr.append (")");
+  modify (p, "", expr, true, add);
+}
Index: trunk/src/emx/src/pmgdb/display.h
===================================================================
--- trunk/src/emx/src/pmgdb/display.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/display.h	(revision 18)
@@ -0,0 +1,72 @@
+/* display.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class command_window;
+class gdbio;
+
+class display_window : public pmtxt
+{
+public:
+
+  typedef pmtxt parent;
+
+  display_window (command_window *cmd, gdbio *gdb, unsigned id,
+                  const SWP *pswp, const char *fontnamesize);
+  ~display_window ();
+
+  void delete_all_displays (bool init);
+  void update (int number, const char *expr, const char *format,
+               const char *value, bool enable = true);
+  void enable (int number);
+  void disable (int number);
+  void remove (int number);
+  bool add (HWND hwnd);
+
+private:
+  class display;
+
+  // Override member functions of pmframe
+  MRESULT wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  bool wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  void button_event (int line, int column, int tab, int button, int clicks);
+  display *find_by_number (int number);
+  display *find_by_line (int line);
+  void update (display *p);
+  void select_line (int line, bool toggle = false);
+  void modify (const display *p, const char *new_format, const char *new_expr,
+               bool new_enable, bool add);
+  void modify (display *p);
+  void change_representation (char fmtchr);
+  void dereference (display *p, bool add);
+
+  command_window *cmd;
+  gdbio *gdb;
+  display *head;
+  int sel_line, sel_count;
+  pmtxt_attr sel_attr;
+
+  // Expected new display
+  int exp_number;
+  bool exp_enable;
+  int exp_line;
+};
Index: trunk/src/emx/src/pmgdb/gdbio.cc
===================================================================
--- trunk/src/emx/src/pmgdb/gdbio.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/gdbio.cc	(revision 18)
@@ -0,0 +1,898 @@
+/* gdbio.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+#include <stdio.h>              // vsnprintf()
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <io.h>
+#include <sys/ptrace.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "breakpoi.h"
+#include "display.h"
+#include "threads.h"
+#include "annotati.h"
+#include "capture.h"
+#include "gdbio.h"
+#include "pmdebug.h"
+#include "command.h"
+
+
+gdbio::gdbio (command_window *in_cmd)
+{
+  cmd = in_cmd;
+  ignore_prompt = false; ignore_output = false;
+  show_annotations = false;
+  breakpoints_invalid = false; breakpoints_invalid_pending = false;
+  exec_file_pending = false; stopped_pending = false;
+  call_flag = false;
+  capture_head = capture_cur = NULL;
+  display_head = display_cur = NULL;
+  frame_head = frame_cur = NULL;
+  gdb_prompt = GSP_NOTREADY;
+  gdb_running = GSR_NONE;
+  cmd_head = NULL; cmd_add = &cmd_head;
+  to_gdb = -1;
+  _fmutex_checked_create (&mutex_cmd_queue, 0);
+  if (DosCreateEventSem (NULL, &hev_done, 0, FALSE) != 0)
+    abort ();
+}
+
+
+gdbio::~gdbio ()
+{
+}
+
+
+void gdbio::lock_cmd_queue ()
+{
+  _fmutex_checked_request (&mutex_cmd_queue, _FMR_IGNINT);
+}
+
+
+void gdbio::unlock_cmd_queue ()
+{
+  _fmutex_checked_release (&mutex_cmd_queue);
+}
+
+
+void gdbio::reset_hev_done ()
+{
+  ULONG post_count;
+  ULONG rc = DosResetEventSem (hev_done, &post_count);
+  if (rc != 0 && rc != ERROR_ALREADY_RESET) abort ();
+}
+
+
+void gdbio::post_hev_done ()
+{
+  ULONG rc = DosPostEventSem (hev_done);
+  if (rc != 0) abort ();
+}
+
+
+void gdbio::wait_hev_done ()
+{
+  ULONG rc;
+
+  do
+    {
+      rc = DosWaitEventSem (hev_done, SEM_INDEFINITE_WAIT);
+    } while (rc == ERROR_INTERRUPT);
+  if (rc != 0) abort ();
+}
+
+
+void gdbio::fetch ()
+{
+  if (get_next () == READ_ERROR)
+    {
+      // TODO: Message box?
+      DosExit (EXIT_THREAD, 0);
+    }
+  if (show_annotations && get_code () != TEXT)
+    cmd->show_annotation (this);
+}
+
+
+void gdbio::handle_output (const char *text, int len)
+{
+  if (!ignore_output)
+    {
+      cmd->handle_output (text, len);
+      ignore_prompt = false;
+    }
+}
+
+
+void gdbio::copy_text (bool to_screen, bool to_field)
+{
+  if (to_field)
+    field_init ();
+  for (;;)
+    {
+      fetch ();
+      if (get_code () != TEXT)
+        break;
+      if (to_field)
+        field.append (get_text (), get_text_len ());
+      if (to_screen)
+        handle_output (get_text (), get_text_len ());
+    }
+}
+
+
+void gdbio::parse_gdb ()
+{
+  char *end;
+  long n;
+  int pid;
+
+  fetch ();
+  for (;;)
+    {
+      switch (get_code ())
+        {
+        case TEXT:
+          handle_output (get_text (), get_text_len ());
+          // TODO: not always needed, add arg to capture_cmd()
+          if (capture_head != NULL)
+            output.append (get_text (), get_text_len ());
+          fetch ();
+          break;
+
+        case breakpoint_new:
+          // Note: add to head!
+          // TODO: strtol()
+          if (capture_head != NULL)
+            capture_head->bpt_number.set (atoi (get_args ()));
+          fetch ();
+          break;
+
+        case breakpoints_table:
+          parse_breakpoints_table ();
+          break;
+
+        case annotation::breakpoints_invalid:
+          breakpoints_invalid = true;
+          breakpoints_invalid_pending = true;
+          fetch ();
+          break;
+
+        case display_begin:
+          parse_display_begin ();
+          break;
+
+        case display_delete:
+          if (cmd->dsp != NULL)
+            cmd->dsp->remove (atoi (get_args ()));
+          fetch ();
+          break;
+
+        case display_disable:
+          if (cmd->dsp != NULL)
+            cmd->dsp->disable (atoi (get_args ()));
+          fetch ();
+          break;
+
+        case display_enable:
+          if (cmd->dsp != NULL)
+            cmd->dsp->enable (atoi (get_args ()));
+          fetch ();
+          break;
+
+        case error_begin:
+          parse_error_begin ();
+          break;
+
+        case error:
+          cmd->set_fg_color ();
+          fetch ();
+          break;
+
+        case exec_file:
+          exec_file_pending = true;
+          cmd->exec_file (get_args (), get_args_len ());
+          fetch ();
+          break;
+
+        case exec_file_invalid:
+          cmd->exec_file (NULL, 0);
+          fetch ();
+          break;
+
+        case exited:
+          gdb_running = GSR_NONE;
+          cmd->pmdbg_term ();
+          cmd->notify (command_window::GSC_RUNNING);
+          fetch ();
+          break;
+
+        case frame_begin:
+          parse_frame_begin ();
+          break;
+
+        case pre_commands:
+        case pre_overload_choice:
+        case pre_prompt:
+        case pre_prompt_for_continue:
+        case pre_query:
+          parse_pre_prompt ();
+          break;
+
+        case show_value:
+          copy_text (true, capture_head != NULL);
+          if (get_code () == show_value_end)
+            {
+              if (capture_head != NULL)
+                capture_head->show_value.set (field, field.length ());
+              fetch ();
+            }
+          break;
+
+        case starting:
+          gdb_running = GSR_RUNNING;
+          // TODO: This may be too late
+          cmd->pmdbg_start ();
+          cmd->notify (command_window::GSC_RUNNING);
+          fetch ();
+          break;
+
+        case stopped:
+          if (gdb_running == GSR_RUNNING)
+            {
+              gdb_running = GSR_STOPPED;
+              cmd->pmdbg_stop ();
+            }
+          stopped_pending = true;
+          cmd->notify (command_window::GSC_RUNNING);
+          fetch ();
+          break;
+
+        case signalled:
+          gdb_running = GSR_NONE;
+          cmd->pmdbg_term ();
+          cmd->notify (command_window::GSC_RUNNING);
+          fetch ();
+          break;
+
+        case source:
+          parse_source ();
+          fetch ();
+          break;
+
+        case source_file:
+          if (capture_cur != NULL)
+            {
+              if (capture_cur->srcs_file.is_set ())
+                {
+                  capture_cur->next = new capture;
+                  capture_cur = capture_cur->next;
+                }
+              capture_cur->srcs_file.set (get_args ());
+            }
+          fetch ();
+          break;
+
+        case source_location:
+          parse_source_location ();
+          break;
+
+        case thread_add:
+          n = strtol (get_args (), &end, 10);
+          if (*end == ' ')
+            {
+              pid = atoi (end);
+              if (PTRACE_GETTID (pid) == 1)
+                pmdbg.set_pid (PTRACE_GETPID (pid));
+              cmd->thr->add ((int)n, pid);
+            }
+          fetch ();
+          break;
+
+        case thread_disable:
+          cmd->thr->disable (atoi (get_args ()));
+          fetch ();
+          break;
+
+        case thread_enable:
+          cmd->thr->enable (atoi (get_args ()));
+          fetch ();
+          break;
+
+        case thread_end:
+          cmd->thr->remove (atoi (get_args ()));
+          fetch ();
+          break;
+
+        case thread_switch:
+          cmd->thr->select (atoi (get_args ()));
+          fetch ();
+          break;
+
+        default:
+          fetch ();
+          break;
+        }
+    }
+}
+
+
+// Handle `source FILENAME;LINE;CHARACTER;MIDDLE;ADDR' annotation
+
+#define SOURCE_SEP      ';'
+
+// TODO: `info line' typed by user must not update source window!
+void gdbio::parse_source ()
+{
+  const char *args = get_args ();
+  const char *p;
+  char *filename, *end;
+  long lineno, addr;
+  int len;
+
+  // FILENAME
+  p = strchr (args, SOURCE_SEP);
+  if (p == NULL) return;
+  len = p - args;
+  filename = (char *)alloca (len + 1);
+  memcpy (filename, args, len);
+  filename[len] = 0;
+
+  // LINE
+  lineno = strtol (p + 1, &end, 10);
+  if (lineno <= 0 || *end != SOURCE_SEP) return;
+
+  // CHARACTER
+  p = strchr (end + 1, SOURCE_SEP);
+  if (p == NULL) return;
+
+  // MIDDLE
+  p = strchr (p + 1, SOURCE_SEP);
+  if (p == NULL) return;
+
+  // ADDR
+  addr = strtol (p + 1, &end, 16);
+  if (end == p + 1 || *end != 0) return;
+
+  capture *capt;
+  if (capture_head != NULL)
+    capt = capture_head;
+  else
+    {
+      if (frame_head == NULL)
+        frame_head = frame_cur = new capture;
+      capt = frame_head;
+    }
+  capt->source_file.set (filename, len);
+  capt->source_lineno.set (lineno);
+  capt->source_addr.set (addr);
+}
+
+
+void gdbio::parse_breakpoints_table ()
+{
+  long n = -1;                  // Keep the compiler happy
+  char *end;
+
+  fetch ();
+  if (capture_head == NULL)
+    return;
+  while (get_code () == record)
+    {
+      capture_cur->next = new capture;
+      capture_cur = capture_cur->next;
+      fetch ();
+      while (get_code () == annotation::field)
+        {
+          int number = atoi (get_args ());
+          copy_text (true, true);
+          switch (number)
+            {
+            case 0:
+              // NUMBER: "1  "
+              capture_cur->bpt_number.set (atoi (field));
+              break;
+            case 1:
+              // TYPE: "breakpoint  "
+              break;
+            case 2:
+              // DISPOSITION: "keep "
+              field.remove_trailing (' ');
+              capture_cur->bpt_disposition.set (field, field.length ());
+              break;
+            case 3:
+              // ENABLE: "y  "
+              capture_cur->bpt_enable.set (field[0] == 'y');
+              break;
+            case 4:
+              // ADDRESS: "0x100b2 "
+              // TODO: This field is language-dependent
+              n = strtol (field, &end, 16);
+              if (end != (const char *)field && (*end == ' ' || *end == 0))
+                capture_cur->bpt_address.set (n);
+              break;
+            case 5:
+              // WHAT: "in main at source.c:217"
+              capture_cur->bpt_what.set (field, field.length ());
+              break;
+            case 6:
+              // FRAME: TODO
+              break;
+            case 7:
+              // CONDITION: "\tstop only if i >= 2\n"
+              field.remove_trailing ('\n');
+              if (strncmp (field, "\tstop only if ", 14) == 0)
+                capture_cur->bpt_condition.set ((const char *)field + 14,
+                                                field.length () - 14);
+              break;
+            case 8:
+              // IGNORE-COUNT: "\tignore next X hits\n"
+              if (strncmp (field, "\tignore next ", 13) == 0
+                  && (n = strtol ((const char *)field + 13, &end, 10)) >= 1)
+                capture_cur->bpt_ignore.set (n);
+              break;
+            case 9:
+              // COMMANDS: TODO
+              break;
+            }
+        }
+    }
+  if (get_code () == breakpoints_table_end)
+    fetch ();
+}
+
+
+void gdbio::parse_display_begin ()
+{
+  bool to_screen = frame_head == NULL;
+  capture *capt = new capture;
+  if (display_cur == NULL)
+    display_head = capt;
+  else
+    display_cur->next = capt;
+  display_cur = capt;
+
+  // display-begin NUMBER display-number-end
+  copy_text (to_screen, true);
+  if (get_code () != display_number_end)
+    return;
+  char *end;
+  long n = strtol (field, &end, 10);
+  if (end == (const char *)field || *end != 0)
+    return;
+  display_cur->disp_number.set (n);
+  // For adding displays, see IDM_ADD of display_window
+  if (capture_head != NULL)
+    capture_head->disp_number.set (n);
+
+  // NUMBER-SEPARATOR display-format FORMAT display-expression
+  copy_text (to_screen, false);
+  if (get_code () != display_format)
+    return;
+  copy_text (to_screen, true);
+  if (get_code () != display_expression)
+    return;
+  field.remove_trailing (' ');
+  display_cur->disp_format.set (field, field.length ());
+
+  // EXPRESSION display-expression-end
+  copy_text (to_screen, true);
+  if (get_code () == error_begin)
+    {
+      display_cur->disp_expr.set ("*ERROR*");
+      display_cur->disp_value.set ("");
+      parse_error_begin ();
+      display_cur->disp_enable.set (false);
+      return;
+    }
+  if (get_code () != display_expression_end)
+    return;
+  display_cur->disp_expr.set (field, field.length ());
+
+  // EXPRESSION-SEPARATOR display-value VALUE display-end
+  copy_text (to_screen, false);
+  if (get_code () != display_value)
+    return;
+  parse_value (to_screen, true);
+  if (get_code () != display_end)
+    return;
+  field.remove_trailing ('\n');
+  display_cur->disp_value.set (field, field.length ());
+  display_cur->disp_enable.set (true);
+  fetch ();
+}
+
+
+void gdbio::parse_value (bool to_screen, bool to_field)
+{
+  if (to_field)
+    field_init ();
+  bool more = true;
+  while (more)
+    {
+      fetch ();
+      switch (get_code ())
+        {
+        case TEXT:
+          if (to_field)
+            field.append (get_text (), get_text_len ());
+          if (to_screen)
+            handle_output (get_text (), get_text_len ());
+          break;
+        case array_section_begin:
+        case array_section_end:
+        case elt:
+        case elt_rep:
+        case elt_rep_end:
+        case field_begin:
+        case field_name_end:
+        case field_value:
+        case field_end:
+          break;
+        default:
+          more = false;
+          break;
+        }
+    }
+}
+
+
+void gdbio::parse_error_begin ()
+{
+  cmd->set_fg_color (CLR_RED);
+  copy_text (true, capture_head != NULL);
+  if (get_code () == quit || get_code () == error)
+    {
+      if (capture_head != NULL)
+        {
+          field.remove_trailing ('\n');
+          capture_head->error.set (field, field.length ());
+        }
+      fetch ();
+    }
+  cmd->set_fg_color ();
+}
+
+
+void gdbio::parse_source_location ()
+{
+  copy_text (true, capture_head != NULL);
+  if (get_code () == source_location_end)
+    {
+      if (capture_head != NULL)
+        capture_head->source_location.set (field, field.length ());
+      fetch ();
+    }
+}
+
+
+void gdbio::parse_frame_begin ()
+{
+  capture *capt = new capture;
+  if (frame_cur == NULL)
+    frame_head = capt;
+  else
+    frame_cur->next = capt;
+  frame_cur = capt;
+  // TODO: parse
+  fetch ();
+}
+
+
+void gdbio::parse_pre_prompt ()
+{
+  cmd->set_fg_color (CLR_BLUE);
+  copy_text (!ignore_prompt, false);
+  switch (get_code ())
+    {
+    case commands:
+    case overload_choice:
+    case prompt_for_continue:
+    case query:
+      if (gdb_prompt != GSP_OTHER)
+        {
+          gdb_prompt = GSP_OTHER;
+          cmd->set_fg_color (CLR_DARKBLUE);
+          cmd->notify (command_window::GSC_PROMPT);
+        }
+      break;
+
+    case prompt:
+      if (cmd_head != NULL)
+        {
+          lock_cmd_queue ();
+          cmd_queue *q = cmd_head;
+          cmd_head = cmd_head->next;
+          if (cmd_head == NULL)
+            cmd_add = &cmd_head;
+          unlock_cmd_queue ();
+          ignore_prompt = true;
+          send_str (q->cmd, strlen (q->cmd));
+          delete q;
+        }
+      else
+        {
+          gdb_prompt = GSP_CMD;
+          ignore_prompt = false;
+          unsigned change = command_window::GSC_PROMPT;
+          cmd->set_fg_color (CLR_DARKBLUE);
+          if (call_flag)
+            {
+              // Note that this is done before posting UWM_STATE, so
+              // that, say, a new display number can be picked up
+              // before updating the displays
+              post_hev_done ();
+            }
+          if (breakpoints_invalid_pending)
+            {
+              breakpoints_invalid_pending = false;
+              change |= command_window::GSC_BREAKPOINTS;
+            }
+          if (exec_file_pending)
+            {
+              exec_file_pending = false;
+              change |= command_window::GSC_EXEC_FILE;
+            }
+          cmd->notify (change);
+        }
+      break;
+
+    default:
+      cmd->set_fg_color ();
+      ignore_prompt = false;
+      return;
+    }
+
+  // input
+  copy_text (true, false);
+  switch (get_code ())
+    {
+    case post_commands:
+    case post_overload_choice:
+    case post_prompt:
+    case post_prompt_for_continue:
+    case post_query:
+      gdb_prompt = GSP_NONE;
+      cmd->set_fg_color ();
+      cmd->notify (command_window::GSC_PROMPT);
+      fetch ();
+      break;
+
+    default:
+      cmd->set_fg_color ();
+      break;
+    }
+}
+
+
+void gdbio::prepare_run ()
+{
+  if (frame_head != NULL)
+    {
+      delete_capture (frame_head);
+      frame_head = NULL; frame_cur = NULL;
+    }
+}
+
+
+static void sigpipe_handler (int)
+{
+}
+
+
+void gdbio::send_init (int fd)
+{
+  to_gdb = fd;
+}
+
+
+void gdbio::send_init ()
+{
+  struct sigaction sa;
+
+  sa.sa_handler = sigpipe_handler;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGPIPE, &sa, NULL);
+}
+
+
+void gdbio::send_str (const char *str, int len)
+{
+  write (to_gdb, str, len);
+}
+
+
+void gdbio::send_vfmt (const char *fmt, va_list args)
+{
+  char buf[512];
+
+  int len = vsnprintf (buf, sizeof (buf) - 1, fmt, args);
+  if (len >= (int)sizeof (buf) - 1)
+    abort ();
+  buf[len] = '\n';
+  buf[len+1] = 0;
+  send_str (buf, len + 1);
+}
+
+
+bool gdbio::send_cmd (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  if (!is_ready () || cmd_head != NULL)
+    {
+      DosBeep (400, 200);
+      return false;
+    }
+  gdb_prompt = GSP_NOTREADY;
+  ignore_prompt = true;
+  va_start (arg_ptr, fmt);
+  send_vfmt (fmt, arg_ptr);
+  va_end (arg_ptr);
+  return true;
+}
+
+
+void gdbio::queue_cmd (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  char buf[512];
+  va_start (arg_ptr, fmt);
+  int len = vsnprintf (buf, sizeof (buf) - 1, fmt, arg_ptr);
+  va_end (arg_ptr);
+  if (len >= (int)sizeof (buf) - 1)
+    abort ();
+  buf[len] = '\n';
+  buf[len+1] = 0;
+
+  lock_cmd_queue ();
+  if (is_ready () && cmd_head == NULL)
+    {
+      gdb_prompt = GSP_NOTREADY;
+      unlock_cmd_queue ();
+      ignore_prompt = true;
+      send_str (buf, len + 1);
+    }
+  else
+    {
+      cmd_queue *q = new cmd_queue;
+      q->cmd.set (buf, len + 1);
+      q->next = NULL;
+      *cmd_add = q; cmd_add = &q->next;
+      unlock_cmd_queue ();
+    }
+}
+
+
+bool gdbio::call_cmd (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  // TODO: mutex
+  if (!is_ready () || cmd_head != NULL)
+    return false;
+
+  gdb_prompt = GSP_NOTREADY;
+  ignore_prompt = true; ignore_output = true; call_flag = true;
+  output.set (0);
+  reset_hev_done ();
+  va_start (arg_ptr, fmt);
+  send_vfmt (fmt, arg_ptr);
+  va_end (arg_ptr);
+  wait_hev_done ();
+  ignore_output = false; call_flag = false;
+  return true;
+}
+
+
+capture * gdbio::capture_cmd (const char *fmt, ...)
+{
+  va_list arg_ptr;
+
+  // TODO: mutex
+  if (!is_ready () || capture_head != NULL || cmd_head != NULL)
+    return NULL;
+
+  gdb_prompt = GSP_NOTREADY;
+  ignore_prompt = true; ignore_output = true; call_flag = true;
+  capture_head = capture_cur = new capture;
+  output.set (0);
+  reset_hev_done ();
+  va_start (arg_ptr, fmt);
+  send_vfmt (fmt, arg_ptr);
+  va_end (arg_ptr);
+  wait_hev_done ();
+  capture *tmp = capture_head;
+  capture_head = capture_cur = NULL;
+  ignore_output = false; call_flag = false;
+  return tmp;
+}
+
+
+ULONG gdbio::address_of_line (const char *fname, int lineno)
+{
+  capture *capt = capture_cmd ("server info line %s:%d", fname, lineno);
+  if (capt == NULL)
+    return 0;
+  ULONG addr = 0;
+  if (capt->source_addr.is_set ())
+    addr = (ULONG)capt->source_addr.get ();
+  delete_capture (capt);
+  return addr;
+}
+
+
+bool gdbio::get_setshow_boolean (const char *name)
+{
+  capture *capt = capture_cmd ("server show %s", name);
+  if (capt == NULL)
+    return false;
+  bool result = (capt->show_value.is_set ()
+                 && strcmp (capt->show_value.get (), "on") == 0);
+  delete_capture (capt);
+  return result;
+}
+
+
+void gdbio::set_setshow_boolean (const char *name, bool value)
+{
+  queue_cmd ("server set %s %s", name, value ? "on" : "off");
+}
+
+
+char *gdbio::get_setshow_string (const char *name)
+{
+  capture *capt = capture_cmd ("server show %s", name);
+  if (capt == NULL)
+    return NULL;
+  char *result = NULL;
+  if (capt->show_value.is_set ())
+    {
+      const char *s = capt->show_value.get ();
+      size_t len = strlen (s);
+      if (len >= 2 && s[0] == '"' && s[len-1] == '"')
+        {
+          ++s; len -= 2;
+        }
+      result = new char[len + 1];
+      memcpy (result, s, len);
+      result[len] = 0;
+    }
+  delete_capture (capt);
+  return result;
+}
+
+
+void gdbio::set_setshow_string (const char *name, const char *value)
+{
+  queue_cmd ("server set %s %s", name, value);
+}
Index: trunk/src/emx/src/pmgdb/gdbio.h
===================================================================
--- trunk/src/emx/src/pmgdb/gdbio.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/gdbio.h	(revision 18)
@@ -0,0 +1,116 @@
+/* gdbio.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class command_window;
+class capture;
+
+class gdbio : annotation
+{
+public:
+
+  // Types
+
+  enum gsp
+  {
+    GSP_CMD,
+    GSP_OTHER,
+    GSP_NONE,
+    GSP_NOTREADY
+  };
+
+  enum gsr
+  {
+    GSR_RUNNING,
+    GSR_STOPPED,
+    GSR_NONE
+  };
+
+  gdbio (command_window *cmd);
+  ~gdbio ();
+
+  void parse_gdb ();
+  const astring &get_output () const { return output; }
+  bool is_nochild () const { return gdb_running == GSR_NONE; }
+  bool is_ready () const { return gdb_prompt == GSP_CMD; }
+  void prepare_run ();
+  void send_init (int fd);
+  void send_init ();
+  bool send_cmd (const char *fmt, ...);
+  void queue_cmd (const char *fmt, ...);
+  bool call_cmd (const char *fmt, ...);
+  capture *capture_cmd (const char *fmt, ...);
+  ULONG address_of_line (const char *fname, int lineno);
+  bool get_setshow_boolean (const char *name);
+  void set_setshow_boolean (const char *name, bool value);
+  char *get_setshow_string (const char *name);
+  void set_setshow_string (const char *name, const char *value);
+
+private:
+  void parse_breakpoints_table ();
+  void parse_display_begin ();
+  void parse_error_begin ();
+  void parse_source ();
+  void parse_source_location ();
+  void parse_frame_begin ();
+  void parse_pre_prompt ();
+  void parse_value (bool to_screen, bool to_field);
+  void fetch ();
+  void handle_output (const char *text, int len);
+  void copy_text (bool to_screen, bool to_field);
+  void field_init () { field.set (0); }
+  void send_str (const char *str, int len);
+  void send_vfmt (const char *fmt, va_list args);
+  void lock_cmd_queue ();
+  void unlock_cmd_queue ();
+  void reset_hev_done ();
+  void post_hev_done ();
+  void wait_hev_done ();
+
+  struct cmd_queue
+  {
+    struct cmd_queue *next;
+    fstring cmd;
+  };
+
+  command_window *cmd;
+  capture *capture_head, *capture_cur;
+  capture *frame_head, *frame_cur;
+  capture *display_head, *display_cur;
+  astring field;
+  astring output;
+  bool ignore_prompt;
+  bool ignore_output;
+  bool show_annotations;
+  bool breakpoints_invalid;
+  bool breakpoints_invalid_pending;
+  bool exec_file_pending;
+  bool stopped_pending;
+  bool call_flag;
+  gsp gdb_prompt;
+  gsr gdb_running;
+
+  _fmutex mutex_cmd_queue;
+  HEV hev_done;
+  int to_gdb;
+  cmd_queue *cmd_head, **cmd_add;
+
+  friend command_window;
+};
Index: trunk/src/emx/src/pmgdb/help.h
===================================================================
--- trunk/src/emx/src/pmgdb/help.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/help.h	(revision 18)
@@ -0,0 +1,138 @@
+/* help.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define HELP_GENERAL            1
+#define HELP_CMD_WINDOW         2
+#define HELP_CMD_KEYS           3
+#define HELP_SRC_WINDOW         4
+#define HELP_SRC_KEYS           5
+#define HELP_SRCS_WINDOW        6
+#define HELP_SRCS_KEYS          7
+#define HELP_BRK_WINDOW         8
+#define HELP_BRK_KEYS           9
+#define HELP_DSP_WINDOW        10
+#define HELP_DSP_KEYS          11
+#define HELP_THR_WINDOW        12
+#define HELP_THR_KEYS          13
+#define HELP_REG_WINDOW        14
+#define HELP_REG_KEYS          15
+#define HELP_TUTORIAL         100
+
+#define HPM_CMD_FILEMENU     1000
+#define HPM_CMD_OPEN_EXEC    1001
+#define HPM_CMD_OPEN_CORE    1002
+#define HPM_OPEN_SOURCE      1003
+#define HPM_CMD_STARTUP      1004
+#define HPM_RESTART          1005
+#define HPM_WHERE            1006
+#define HPM_EXIT             1007
+#define HPM_CMD_RUNMENU      1008
+#define HPM_GO               1009
+#define HPM_STEPOVER         1010
+#define HPM_STEPINTO         1011
+#define HPM_FINISH           1012
+#define HPM_ISTEPOVER        1013
+#define HPM_ISTEPINTO        1014
+#define HPM_CMD_BRKPTMENU    1015
+#define HPM_BRKPT_LINE       1016
+#define HPM_BRKPT_LIST       1017
+#define HPM_CMD_OPTIONSMENU  1018
+#define HPM_PMDEBUGMODE      1019
+#define HPM_CMD_ANNOTATE     1020
+#define HPM_CMD_WINMENU      1021
+#define HPM_WIN_BRK          1022
+#define HPM_WIN_CMD          1023
+#define HPM_WIN_DSP          1024
+#define HPM_WIN_THR          1025
+#define HPM_WIN_SRCS         1026
+#define HPM_CMD_HELPMENU     1027
+#define HPM_HELP_HELP        1028
+#define HPM_HELP_EXT         1029
+#define HPM_HELP_KEYS        1030
+#define HPM_HELP_INDEX       1031
+#define HPM_CMD_ABOUT        1032
+#define HPM_SRC_FILEMENU     1033
+#define HPM_SRC_GOTO         1034
+#define HPM_SRC_RUNMENU      1035
+#define HPM_SRC_UNTIL        1036
+#define HPM_SRC_JUMP         1037
+#define HPM_SRC_BRKPTMENU    1038
+#define HPM_SRC_DSPMENU      1039
+#define HPM_SRC_DSP_SHOW     1041
+#define HPM_SRC_OPTIONSMENU  1042
+#define HPM_SRC_WINMENU      1043
+#define HPM_SRC_HELPMENU     1044
+#define HPM_SRCS_FILEMENU    1045
+#define HPM_SRCS_WINMENU     1046
+#define HPM_SRCS_HELPMENU    1047
+#define HPM_HELP_CONTENTS    1048
+#define HPM_BRK_FILEMENU     1049
+#define HPM_BRK_EDITMENU     1050
+#define HPM_BRK_MODIFY       1051
+#define HPM_BRK_ENABLE       1052
+#define HPM_BRK_DISABLE      1053
+#define HPM_BRK_DELETE       1054
+#define HPM_BRK_BRKPTMENU    1055
+#define HPM_BRK_WINMENU      1056
+#define HPM_BRK_HELPMENU     1057
+#define HPM_DSP_FILEMENU     1058
+#define HPM_DSP_EDITMENU     1059
+#define HPM_DSP_WINMENU      1060
+#define HPM_DSP_HELPMENU     1061
+#define HPM_DSP_ADD          1062
+#define HPM_DSP_MODIFY       1063
+#define HPM_DSP_ENABLE       1064
+#define HPM_DSP_DISABLE      1065
+#define HPM_DSP_DELETE       1066
+#define HPM_DSP_FORMAT       1067
+#define HPM_DSP_DEREFERENCE  1068
+#define HPM_DSP_ENABLE_ALL   1069
+#define HPM_DSP_DISABLE_ALL  1070
+#define HPM_DSP_DELETE_ALL   1071
+#define HPM_THR_FILEMENU     1072
+#define HPM_THR_EDITMENU     1073
+#define HPM_THR_WINMENU      1074
+#define HPM_THR_ENABLE       1075
+#define HPM_THR_DISABLE      1076
+#define HPM_THR_SWITCH       1077
+#define HPM_SRC_VIEWMENU     1078
+#define HPM_SRC_FIND         1079
+#define HPM_SRC_FINDNEXT     1080
+#define HPM_SRC_FINDPREV     1081
+#define HPM_CMD_EDITMENU     1082
+#define HPM_CMD_COMPLETE     1083
+#define HPM_CMD_HISTORY      1084
+#define HPM_CMD_FONT         1085
+#define HPM_REG_FILEMENU     1086
+#define HPM_REG_WINMENU      1087
+#define HPM_WIN_REG          1088
+#define HPM_REG_VIEWMENU     1089
+#define HPM_REG_REFRESH      1090
+#define HPM_BRK_REFRESH      1091
+#define HPM_TUTORIAL         1092
+
+#define HPD_PMDEBUGMODE      2000
+#define HPD_BRKPT_LINE       2001
+#define HPD_STARTUP          2002
+#define HPD_DISPLAY          2003
+#define HPD_GOTO             2004
+#define HPD_FIND             2006
+#define HPD_HISTORY          2007
Index: trunk/src/emx/src/pmgdb/makefile
===================================================================
--- trunk/src/emx/src/pmgdb/makefile	(revision 18)
+++ trunk/src/emx/src/pmgdb/makefile	(revision 18)
@@ -0,0 +1,114 @@
+#
+# /emx/src/pmgdb/makefile
+#
+# Copyright (c) 1996 Eberhard Mattes
+#
+# This file is part of pmgdb.
+#
+# pmgdb is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# pmgdb is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with pmgdb; see the file COPYING.  If not, write to the
+# the Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+BIN=\emx\bin\ #
+HELP=\emx\help\ #
+CC=gcc -g -O2 -Zmt -Wall
+
+OBJ=pmgdb.o pmtty.o pmtxt.o pmframe.o source.o srcfiles.o command.o \
+		breakpoi.o display.o threads.o register.o annotati.o \
+		capture.o gdbio.o pmdebug.o pmapp.o string.o
+
+default: $(BIN)pmgdb.exe $(HELP)pmgdb.hlp
+
+$(BIN)pmgdb.exe:	$(OBJ) pmgdb.def pmgdb.res
+	$(CC) -o pmgdb $(OBJ) pmgdb.def -Zsmall-conv
+	emxbind -b -s -o$(BIN)pmgdb.exe -rpmgdb.res -dpmgdb.def pmgdb
+
+pmgdb.o:	pmgdb.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h source.h command.h pmgdb.h
+	$(CC) -c pmgdb.cc
+
+command.o:	command.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h display.h threads.h register.h source.h srcfiles.h \
+		annotati.h capture.h gdbio.h command.h pmdebug.h pmgdb.h help.h
+	$(CC) -c command.cc
+
+source.o:	source.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h display.h source.h annotati.h capture.h \
+		gdbio.h command.h pmgdb.h help.h
+	$(CC) -c source.cc
+
+srcfiles.o:	srcfiles.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h srcfiles.h command.h pmgdb.h help.h
+	$(CC) -c srcfiles.cc
+
+breakpoi.o:	breakpoi.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h srcfiles.h annotati.h capture.h gdbio.h command.h \
+		pmgdb.h help.h
+	$(CC) -c breakpoi.cc
+
+display.o:	display.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h display.h annotati.h capture.h gdbio.h command.h \
+		pmgdb.h help.h
+	$(CC) -c display.cc
+
+threads.o:	threads.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h threads.h annotati.h gdbio.h command.h \
+		pmgdb.h help.h
+	$(CC) -c threads.cc
+
+register.o:	register.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h register.h pmgdb.h help.h
+	$(CC) -c register.cc
+
+annotati.o:	annotati.cc annotati.h
+	$(CC) -c annotati.cc
+
+capture.o:	capture.cc capture.h
+	$(CC) -c capture.cc
+
+gdbio.o:	gdbio.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h \
+		breakpoi.h display.h threads.h annotati.h capture.h \
+		gdbio.h pmdebug.h command.h
+	$(CC) -c gdbio.cc
+
+pmdebug.o:	pmdebug.cc pmdebug.h
+	$(CC) -c pmdebug.cc
+
+pmtty.o:	pmtty.cc string.h pmapp.h pmframe.h pmtxt.h pmtty.h
+	$(CC) -c pmtty.cc
+
+pmtxt.o:	pmtxt.cc string.h pmapp.h pmframe.h pmtxt.h
+	$(CC) -c pmtxt.cc
+
+pmframe.o:	pmframe.cc string.h pmapp.h pmframe.h
+	$(CC) -c pmframe.cc
+
+pmapp.o:	pmapp.cc string.h pmapp.h
+	$(CC) -c pmapp.cc
+
+string.o:	string.cc string.h
+	$(CC) -c string.cc
+
+pmgdb.res:        pmgdb.rc pmgdb.h help.h
+	rc -r pmgdb.rc
+
+$(HELP)pmgdb.hlp:	pmgdb.ipp pmgdb.h
+	ipfcprep pmgdb.ipp pmgdb.ipf
+	ipfc pmgdb.ipf
+	del pmgdb.ipf
+	cp pmgdb.hlp $(HELP)pmgdb.hlp
+
+clean:
+	-rm -f *.o *.exe *.res *.hlp pmgdb.ipf core pmgdb
Index: trunk/src/emx/src/pmgdb/pmapp.cc
===================================================================
--- trunk/src/emx/src/pmgdb/pmapp.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmapp.cc	(revision 18)
@@ -0,0 +1,154 @@
+/* pmapp.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include "string.h"
+#include "pmapp.h"
+
+
+pmapp::pmapp (const char *in_name)
+{
+  name = in_name;
+  hab = WinInitialize (0);
+  hmq = WinCreateMsgQueue (hab, 0);
+  WinQueryWindowPos (HWND_DESKTOP, &swpScreen);
+}
+
+
+pmapp::~pmapp ()
+{
+  WinDestroyMsgQueue (hmq);
+  WinTerminate (hab);
+}
+
+
+void pmapp::no_message_loop () const
+{
+  WinCancelShutdown (hmq, TRUE);
+}
+
+
+void pmapp::message_loop () const
+{
+  QMSG qmsg;
+
+  while (WinGetMsg (hab, &qmsg, 0, 0, 0))
+    WinDispatchMsg (hab, &qmsg);
+}
+
+
+void pmapp::win_error () const
+{
+  // TODO: Make thread-safe
+  static char buf[] = "WinGetLastError: 0x????????";
+
+  ERRORID eid = WinGetLastError (hab);
+  unsigned err = ERRORIDERROR (eid);
+  _ltoa ((long)err, strchr (buf, 'x') + 1, 16);
+  if (WinMessageBox (HWND_DESKTOP, HWND_DESKTOP, (PSZ)buf, (PCSZ)name, 0,
+                     MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION) == MBID_ERROR)
+    DosBeep (440, 500);
+}
+
+
+/* Remove all unwanted items from the system menu of a dialog box, as
+   required by SAA CUA '89. */
+
+void dlg_sys_menu (HWND hwnd)
+{
+  HWND hwndSysMenu;
+  MENUITEM mi;
+  MRESULT mr;
+  int i, n, id;
+
+  /* Get the window handle of the system menu. */
+
+  hwndSysMenu = WinWindowFromID (hwnd, FID_SYSMENU);
+  if (hwndSysMenu == NULLHANDLE)
+    return;
+
+  /* Well, actually the system menu proper is a submenu of the menu we
+     just got. */
+
+  mr = WinSendMsg (hwndSysMenu, MM_QUERYITEM,
+                   MPFROM2SHORT (SC_SYSMENU, FALSE), (MPARAM)&mi);
+  if (!SHORT1FROMMR (mr))
+    return;
+  hwndSysMenu = mi.hwndSubMenu;
+  if (hwndSysMenu == NULLHANDLE)
+    return;
+
+  /* Delete all the unwanted menu items. */
+
+  WinSendMsg (hwndSysMenu, MM_DELETEITEM,
+              MPFROM2SHORT (SC_MINIMIZE, FALSE), 0);
+  WinSendMsg (hwndSysMenu, MM_DELETEITEM,
+              MPFROM2SHORT (SC_MAXIMIZE, FALSE), 0);
+  WinSendMsg (hwndSysMenu, MM_DELETEITEM,
+              MPFROM2SHORT (SC_SIZE, FALSE), 0);
+  WinSendMsg (hwndSysMenu, MM_DELETEITEM,
+              MPFROM2SHORT (SC_RESTORE, FALSE), 0);
+  WinSendMsg (hwndSysMenu, MM_DELETEITEM,
+              MPFROM2SHORT (SC_TASKMANAGER, FALSE), 0);
+  WinSendMsg (hwndSysMenu, MM_DELETEITEM,
+              MPFROM2SHORT (SC_HIDE, FALSE), 0);
+
+  /* Deleting menu items may leave two or more successive separator
+     lines.  Now we remove all the separator lines.  */
+
+redo:
+
+  /* Get the number of menu items. */
+
+  mr = WinSendMsg (hwndSysMenu, MM_QUERYITEMCOUNT, 0, 0);
+  n = SHORT1FROMMR (mr);
+
+  /* Find the first one which is a separator line. */
+
+  for (i = 0; i < n; ++i)
+    {
+      mr = WinSendMsg (hwndSysMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT (i), 0);
+      id = SHORT1FROMMR (mr);
+      if (id != MID_ERROR)
+        {
+          mr = WinSendMsg (hwndSysMenu, MM_QUERYITEM,
+                           MPFROM2SHORT (id, FALSE), (MPARAM)&mi);
+          if (SHORT1FROMMR (mr) && (mi.afStyle & MIS_SEPARATOR))
+            {
+              /* We found a separator line.  Delete that menu item. */
+
+              WinSendMsg (hwndSysMenu, MM_DELETEITEM,
+                          MPFROM2SHORT (id, FALSE), 0);
+
+              /* Restart the loop as the menu items have been
+                 renumbered. */
+
+              goto redo;
+            }
+        }
+    }
+
+  /* Now there's no separator line left. */
+}
Index: trunk/src/emx/src/pmgdb/pmapp.h
===================================================================
--- trunk/src/emx/src/pmgdb/pmapp.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmapp.h	(revision 18)
@@ -0,0 +1,50 @@
+/* pmapp.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class pmapp
+{
+public:
+  pmapp (const char *name);
+  ~pmapp ();
+  void win_error () const;
+  void no_message_loop () const;
+  void message_loop () const;
+  HAB get_hab () const { return hab; }
+  const char *get_name () const { return name; }
+  int get_screen_width () const { return swpScreen.cx; }
+  int get_screen_height () const { return swpScreen.cy; }
+
+private:
+  HAB hab;
+  HMQ hmq;
+  SWP swpScreen;
+  fstring name;
+};
+
+
+struct pm_create
+{
+  USHORT cb;
+  void *ptr;
+  void *ptr2;
+};
+
+void dlg_sys_menu (HWND hwnd);
Index: trunk/src/emx/src/pmgdb/pmdebug.cc
===================================================================
--- trunk/src/emx/src/pmgdb/pmdebug.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmdebug.cc	(revision 18)
@@ -0,0 +1,123 @@
+/* pmdebug.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pmdebug.h"
+
+
+pmdebug pmdbg;
+
+
+static VOID APIENTRY pmdebug_exitlist (ULONG)
+{
+  pmdbg.exit ();
+  DosExitList (EXLST_EXIT, NULL);
+}
+
+
+pmdebug::pmdebug ()
+{
+  cur_mode = off; locked = false; pid = 0; hwndLock = NULLHANDLE;
+}
+
+
+pmdebug::~pmdebug ()
+{
+  exit ();
+}
+
+
+void pmdebug::exit ()
+{
+  if (cur_mode == sync && locked)
+    {
+      // TODO: Destroy all windows of the debuggee (pid)
+      // TODO: Kill debuggee (important!)
+      WinLockInput (NULLHANDLE, FALSE);
+      locked = false;
+    }
+  set_mode (off, NULLHANDLE);
+}
+
+
+void pmdebug::set_mode (mode new_mode, HWND hwnd, int in_pid)
+{
+  if (new_mode == cur_mode)
+    return;
+  if (cur_mode == sync && locked)
+    {
+      WinLockInput (NULLHANDLE, FALSE);
+      locked = false;
+    }
+  if (new_mode == sync)
+    DosExitList (EXLST_ADD | (0 << 8), pmdebug_exitlist);
+  else if (cur_mode == sync)
+    DosExitList (EXLST_REMOVE, pmdebug_exitlist);
+  cur_mode = new_mode;
+  pid = in_pid; hwndLock = hwnd;
+}
+
+
+void pmdebug::start ()
+{
+  switch (cur_mode)
+    {
+    case sync:
+      if (locked)
+        WinLockInput (NULLHANDLE, FALSE);
+      locked = false;
+      break;
+    default:
+      break;
+    }
+}
+
+
+void pmdebug::stop ()
+{
+  switch (cur_mode)
+    {
+    case sync:
+      if (!locked)
+        {
+          locked = true;
+          WinLockInput (NULLHANDLE, FALSE);
+          WinLockInput (NULLHANDLE, WLI_NOBUTTONUP);
+          WinSetSysModalWindow (HWND_DESKTOP, hwndLock);
+          WinSetFocus (HWND_DESKTOP, hwndLock);
+          WinSetSysModalWindow (HWND_DESKTOP, NULLHANDLE);
+        }
+      break;
+    default:
+      break;
+    }
+}
+
+
+void pmdebug::term ()
+{
+  pid = 0;
+  start ();
+}
Index: trunk/src/emx/src/pmgdb/pmdebug.h
===================================================================
--- trunk/src/emx/src/pmgdb/pmdebug.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmdebug.h	(revision 18)
@@ -0,0 +1,49 @@
+/* pmdebug.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+// Important: All member functions of pmdebug must be called in a
+// thread that has a message queue.  Moreover, thread 1 must have
+// a message queue (DosExitList!)
+
+class pmdebug
+{
+public:
+  enum mode { off, sync, async };
+
+  pmdebug ();
+  ~pmdebug ();
+  void set_mode (mode new_mode, HWND hwnd, int pid = 0);
+  mode get_mode () const { return cur_mode; }
+  void start ();                // About to start debuggee
+  void stop ();                 // Debuggee stopped
+  void term ();                 // Debuggee terminated
+  void set_pid (int in_pid) { pid = in_pid; }
+  void set_window (HWND hwnd) { hwndLock = hwnd; }
+  void exit ();
+
+private:
+  mode cur_mode;
+  bool locked;
+  HWND hwndLock;
+  int pid;
+};
+
+extern pmdebug pmdbg;
Index: trunk/src/emx/src/pmgdb/pmframe.cc
===================================================================
--- trunk/src/emx/src/pmgdb/pmframe.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmframe.cc	(revision 18)
@@ -0,0 +1,375 @@
+/* pmframe.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+
+// TODO
+static pmframe *pmframe_init_kludge;
+
+pmframe::pmframe (pmapp *in_app)
+{
+  app = in_app;
+  minimized = false;
+  hwndHelp = NULLHANDLE;
+  keys_help_id = 0;
+  tid = _gettid ();
+}
+
+
+void pmframe::create (const char *classname, unsigned id, ULONG frame_flags,
+                      const SWP *pswp)
+{
+  WinRegisterClass (app->get_hab (), (PSZ)classname, pmframe_client_msg,
+                    CS_SIZEREDRAW, sizeof (pmframe *));
+
+  frame_flags |= (FCF_TITLEBAR      | FCF_SYSMENU |
+                  FCF_SIZEBORDER    | FCF_MINMAX  |
+                  FCF_MENU          | FCF_ACCELTABLE |
+                  FCF_VERTSCROLL    | FCF_HORZSCROLL);
+
+  pmframe_init_kludge = this;
+  if (WinCreateStdWindow (HWND_DESKTOP, 0,
+                          &frame_flags, (PSZ)classname,
+                          NULL, 0L, 0, id, NULL) == NULLHANDLE)
+    {
+      win_error ();
+      abort ();
+    }
+  old_frame_msg = WinSubclassWindow (hwndFrame, pmframe_frame_msg);
+  if (pswp != NULL)
+    WinSetWindowPos (hwndFrame, HWND_DESKTOP, pswp->x, pswp->y,
+                     pswp->cx, pswp->cy, SWP_MOVE | SWP_SIZE);
+}
+
+
+pmframe::~pmframe ()
+{
+  WinDestroyWindow (hwndFrame);
+}
+
+
+void pmframe::set_title (const char *title)
+{
+  WinSetWindowText (hwndFrame, (PCSZ)title);
+}
+
+
+void pmframe::repaint (RECTL *prcl)
+{
+  WinInvalidateRect (hwndClient, prcl, FALSE);
+}
+
+
+repaint (RECTL *prcl = NULL);
+
+
+MRESULT pmframe::wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmframe::wm_button (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmframe::wm_char (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmframe::wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmframe::wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmframe::wm_create (HWND, ULONG, MPARAM, MPARAM)
+{
+  return FALSE;
+}
+
+
+MRESULT pmframe::wm_hscroll (HWND, ULONG, MPARAM, MPARAM)
+{
+  return 0;
+}
+
+
+MRESULT pmframe::wm_presparamchanged (HWND, ULONG, MPARAM, MPARAM)
+{
+  return 0;
+}
+
+
+MRESULT pmframe::wm_setfocus (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmframe::wm_size (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmframe::wm_timer (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+bool pmframe::wm_user (HWND, ULONG, MPARAM, MPARAM)
+{
+  return false;
+}
+
+
+MRESULT pmframe::wm_vscroll (HWND, ULONG, MPARAM, MPARAM)
+{
+  return 0;
+}
+
+
+MRESULT pmframe::client_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  PSWP pswp;
+
+  switch (msg)
+    {
+    case WM_ACTIVATE:
+      return wm_activate (hwnd, msg, mp1, mp2);
+
+    case WM_BUTTON1DOWN:
+    case WM_BUTTON2DOWN:
+    case WM_BUTTON3DOWN:
+    case WM_BUTTON1CLICK:
+    case WM_BUTTON2CLICK:
+    case WM_BUTTON3CLICK:
+    case WM_BUTTON1DBLCLK:
+    case WM_BUTTON2DBLCLK:
+    case WM_BUTTON3DBLCLK:
+      return wm_button (hwnd, msg, mp1, mp2);
+
+    case WM_CHAR:
+      return wm_char (hwnd, msg, mp1, mp2);
+
+    case WM_CLOSE:
+      return wm_close (hwnd, msg, mp1, mp2);
+
+    case WM_COMMAND:
+      return wm_command (hwnd, msg, mp1, mp2);
+
+    case WM_CREATE:
+      hwndClient = hwnd;
+      hwndFrame = WinQueryWindow (hwnd, QW_PARENT);
+      hwndMenu = WinWindowFromID (hwndFrame, FID_MENU);
+
+      WinSetWindowPtr (hwndClient, QWL_USER, this);
+      WinSetWindowPtr (hwndFrame, QWL_USER, this);
+      return wm_create (hwnd, msg, mp1, mp2);
+
+    case WM_DESTROY:
+      if (hwndHelp != NULLHANDLE)
+        {
+          WinAssociateHelpInstance (NULLHANDLE, hwndFrame);
+          WinDestroyHelpInstance (hwndHelp);
+        }
+      return 0;
+
+    case WM_HSCROLL:
+      return wm_hscroll (hwnd, msg, mp1, mp2);
+
+    case WM_MINMAXFRAME:
+      pswp = (PSWP)mp1;
+      if (pswp->fl & SWP_MINIMIZE)
+        minimized = true;
+      else if (pswp->fl & (SWP_RESTORE | SWP_MAXIMIZE))
+        minimized = false;
+      return FALSE;
+
+    case WM_PAINT:
+      return wm_paint (hwnd, msg, mp1, mp2);
+
+    case WM_PRESPARAMCHANGED:
+      return wm_presparamchanged (hwnd, msg, mp1, mp2);
+
+    case WM_SETFOCUS:
+      return wm_setfocus (hwnd, msg, mp1, mp2);
+
+    case WM_SIZE:
+      return wm_size (hwnd, msg, mp1, mp2);
+
+    case WM_TIMER:
+      return wm_timer (hwnd, msg, mp1, mp2);
+
+    case WM_VSCROLL:
+      return wm_vscroll (hwnd, msg, mp1, mp2);
+
+    case HM_QUERY_KEYS_HELP:
+      return (MRESULT)keys_help_id;
+
+    default:
+      if (msg >= WM_USER)
+        {
+          wm_user (hwnd, msg, mp1, mp2);
+          return FALSE;
+        }
+      else
+        return WinDefWindowProc (hwnd, msg, mp1, mp2);
+    }
+}
+
+
+MRESULT pmframe::wm_querytrackinfo (HWND hwnd, ULONG msg, MPARAM mp1,
+                                    MPARAM mp2)
+{
+  return old_frame_msg (hwnd, msg, mp1, mp2);
+}
+
+
+
+
+MRESULT pmframe::frame_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  switch (msg)
+    {
+    case WM_QUERYTRACKINFO:
+      return wm_querytrackinfo (hwnd, msg, mp1, mp2);
+    }
+  return old_frame_msg (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY
+pmframe_client_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  if (msg == WM_CREATE)
+    return pmframe_init_kludge->client_msg (hwnd, msg, mp1, mp2);
+  else
+    {
+      pmframe *p = (pmframe *)WinQueryWindowPtr (hwnd, QWL_USER);
+      return p->client_msg (hwnd, msg, mp1, mp2);
+    }
+}
+
+
+MRESULT EXPENTRY
+pmframe_frame_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  pmframe *p = (pmframe *)WinQueryWindowPtr (hwnd, QWL_USER);
+  return p->frame_msg (hwnd, msg, mp1, mp2);
+}
+
+
+void pmframe::focus () const
+{
+  WinSetActiveWindow (HWND_DESKTOP, hwndFrame);
+}
+
+
+void pmframe::top () const
+{
+  WinSetWindowPos (hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
+}
+
+
+void pmframe::show (bool visible) const
+{
+  if (visible)
+    WinSetWindowPos (hwndFrame, HWND_TOP, 0, 0, 0, 0, SWP_SHOW | SWP_RESTORE);
+  else
+    WinShowWindow (hwndFrame, FALSE);
+}
+
+
+void pmframe::menu_check (unsigned idm, bool on) const
+{
+  if (!WinSendMsg (hwndMenu, MM_SETITEMATTR,
+                   MPFROM2SHORT (idm, TRUE),
+                   MPFROM2SHORT (MIA_CHECKED, (on ? MIA_CHECKED : 0))))
+    WinAlarm (HWND_DESKTOP, WA_ERROR);
+}
+
+
+void pmframe::menu_enable (unsigned idm, bool on, bool silent) const
+{
+  if (!WinSendMsg (hwndMenu, MM_SETITEMATTR,
+                   MPFROM2SHORT (idm, TRUE),
+                   MPFROM2SHORT (MIA_DISABLED, (on ? 0 : MIA_DISABLED)))
+      && !silent)
+    WinAlarm (HWND_DESKTOP, WA_ERROR);
+}
+
+
+HWND pmframe::get_hwndMenu_from_id (unsigned idm) const
+{
+  MENUITEM mi;
+  MRESULT mr = WinSendMsg (hwndMenu, MM_QUERYITEM,
+                           MPFROM2SHORT (idm, FALSE), (MPARAM)&mi);
+  return SHORT1FROMMR (mr) ? mi.hwndSubMenu : NULLHANDLE;
+}
+
+
+bool pmframe::is_visible () const
+{
+  return !minimized && WinIsWindowVisible (hwndClient);
+}
+
+
+bool pmframe::help_init (unsigned help_table_id, const char *title,
+                         const char *file, unsigned in_keys_help_id)
+{
+  HELPINIT helpinit;
+  memset (&helpinit, 0, sizeof (helpinit));
+  helpinit.cb = sizeof (helpinit);
+  helpinit.pszTutorialName = NULL;
+  helpinit.phtHelpTable = (PHELPTABLE)MAKELONG (help_table_id, 0xFFFF);
+  helpinit.hmodHelpTableModule = 0;
+  helpinit.hmodAccelActionBarModule = 0;
+  helpinit.idActionBar = 0;
+  helpinit.pszHelpWindowTitle = (PSZ)title;
+  helpinit.fShowPanelId = CMIC_HIDE_PANEL_ID;
+  helpinit.pszHelpLibraryName = (PSZ)file;
+  hwndHelp = WinCreateHelpInstance (get_hab (), &helpinit);
+  if (hwndHelp != NULLHANDLE)
+    if (!WinAssociateHelpInstance (hwndHelp, hwndFrame))
+      hwndHelp = NULLHANDLE;
+  keys_help_id = in_keys_help_id;
+  return hwndHelp != NULLHANDLE;
+}
Index: trunk/src/emx/src/pmgdb/pmframe.h
===================================================================
--- trunk/src/emx/src/pmgdb/pmframe.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmframe.h	(revision 18)
@@ -0,0 +1,106 @@
+/* pmframe.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+// A frame window
+
+class pmframe
+{
+public:
+
+  // Constructors and destructors, initialization
+  pmframe (pmapp *app);
+  virtual ~pmframe ();
+  void create (const char *classname, unsigned id, ULONG frame_flags,
+               const SWP *pswp);
+
+  // Querying private members
+  HWND get_hwndMenu ()       const { return hwndMenu; }
+  HWND get_hwndClient ()     const { return hwndClient; }
+  HWND get_hwndFrame ()      const { return hwndFrame; }
+  HWND get_hwndHelp ()       const { return hwndHelp; }
+  pmapp *get_app ()          const { return app; }
+  HAB get_hab ()             const { return app->get_hab (); }
+  const char *get_name ()    const { return app->get_name (); }
+  PFNWP get_old_frame_msg () const { return old_frame_msg; }
+  bool get_minimized ()      const { return minimized; }
+
+  // Painting
+  void repaint (RECTL *prcl = NULL);
+
+  // Miscellanea
+  void set_title (const char *title);
+  void win_error () const { app->win_error (); }
+  void focus () const;
+  void top () const;
+  void show (bool visible) const;
+  void menu_check (unsigned idm, bool on) const;
+  void menu_enable (unsigned idm, bool on, bool silent = false) const;
+  bool same_tid () const { return tid == _gettid (); }
+  HWND get_hwndMenu_from_id (unsigned idm) const;
+  bool is_visible () const;
+
+protected:
+
+  // Messages
+  virtual MRESULT wm_paint (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) = 0;
+  virtual MRESULT wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_button (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_char (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_create (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_hscroll (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_presparamchanged (HWND hwnd, ULONG msg, MPARAM mp1,
+                                       MPARAM mp2);
+  virtual MRESULT wm_querytrackinfo (HWND hwnd, ULONG msg, MPARAM mp1,
+                                     MPARAM mp2);
+  virtual MRESULT wm_setfocus (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_size (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_timer (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual bool wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual MRESULT wm_vscroll (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+  bool help_init (unsigned help_table_id, const char *title, const char *file,
+                  unsigned keys_help_id);
+  void set_keys_help_id (unsigned id) { keys_help_id = id; }
+
+private:
+
+  MRESULT client_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT frame_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+  friend MRESULT EXPENTRY
+    pmframe_client_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  friend MRESULT EXPENTRY
+    pmframe_frame_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+  // Data members
+
+  pmapp *app;
+  HWND hwndFrame;
+  HWND hwndClient;
+  HWND hwndMenu;
+  HWND hwndHelp;
+  int tid;
+  unsigned keys_help_id;
+  PFNWP old_frame_msg;
+  bool minimized;
+};
Index: trunk/src/emx/src/pmgdb/pmgdb.cc
===================================================================
--- trunk/src/emx/src/pmgdb/pmgdb.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmgdb.cc	(revision 18)
@@ -0,0 +1,45 @@
+/* pmgdb.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "pmgdb.h"
+#include "breakpoi.h"
+#include "source.h"
+#include "command.h"
+
+int main (int, char *argv[])
+{
+  pmapp *app = new pmapp ("pmgdb");
+  command_window *cmd = new command_window (app, ID_COMMAND_WINDOW,
+                                            "8.Courier", argv + 1);
+  app->message_loop ();
+  delete cmd;
+  delete app;
+  return 0;
+}
Index: trunk/src/emx/src/pmgdb/pmgdb.def
===================================================================
--- trunk/src/emx/src/pmgdb/pmgdb.def	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmgdb.def	(revision 18)
@@ -0,0 +1,23 @@
+; pmgdb.def
+;
+; Copyright (c) 1996 Eberhard Mattes
+;
+; This file is part of pmgdb.
+;
+; pmgdb is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2, or (at your option)
+; any later version.
+;
+; pmgdb is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with pmgdb; see the file COPYING.  If not, write to the
+; the Free Software Foundation, 59 Temple Place - Suite 330,
+; Boston, MA 02111-1307, USA.
+;
+NAME PMGDB WINDOWAPI
+STACKSIZE 0x8000
Index: trunk/src/emx/src/pmgdb/pmgdb.h
===================================================================
--- trunk/src/emx/src/pmgdb/pmgdb.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmgdb.h	(revision 18)
@@ -0,0 +1,140 @@
+/* pmgdb.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define ID_COMMAND_WINDOW       1
+#define ID_SOURCE_WINDOW        2
+#define ID_BREAKPOINTS_WINDOW   3
+#define ID_DISPLAY_WINDOW       4
+#define ID_THREADS_WINDOW       5
+#define ID_SOURCE_FILES_WINDOW  6
+#define ID_REGISTER_WINDOW      7
+
+#define IDM_FILEMENU    1000
+#define IDM_EXIT        1001
+#define IDM_OPEN_EXEC   1003
+#define IDM_OPEN_CORE   1004
+#define IDM_OPEN_SOURCE 1005
+#define IDM_STARTUP     1006
+#define IDM_WHERE       1007
+#define IDM_RESTART     1009
+#define IDM_RUNMENU     1100
+#define IDM_GO          1101
+#define IDM_STEPINTO    1102
+#define IDM_STEPOVER    1103
+#define IDM_ISTEPINTO   1104
+#define IDM_ISTEPOVER   1105
+#define IDM_JUMP        1106
+#define IDM_UNTIL       1107
+#define IDM_FINISH      1108
+#define IDM_BRKPTMENU   1200
+#define IDM_BRKPT_LIST  1201
+#define IDM_BRKPT_LINE  1202
+#define IDM_OPTIONSMENU 1300
+#define IDM_PMDEBUGMODE 1301
+#define IDM_ANNOTATE    1302
+#define IDM_FONT        1303
+#define IDM_EDITMENU    1400
+#define IDM_ENABLE      1401
+#define IDM_DISABLE     1402
+#define IDM_MODIFY      1403
+#define IDM_DELETE      1404
+#define IDM_ENABLE_ALL  1405
+#define IDM_DISABLE_ALL 1406
+#define IDM_DELETE_ALL  1407
+#define IDM_SWITCH      1408
+#define IDM_ADD         1409
+#define IDM_DEREFERENCE 1410
+#define IDM_COMPLETE    1411
+#define IDM_HISTORY     1412
+#define IDM_WINMENU     1500
+#define IDM_WIN_CMD     1501
+#define IDM_WIN_THR     1502
+#define IDM_WIN_BRK     1503
+#define IDM_WIN_DSP     1504
+#define IDM_WIN_SRCS    1505
+#define IDM_WIN_REG     1506
+#define IDM_REPMENU     1600
+#define IDM_REP_DEC_S   1601
+#define IDM_REP_DEC_U   1602
+#define IDM_REP_HEX     1603
+#define IDM_REP_OCT     1604
+#define IDM_REP_BIN     1605
+#define IDM_REP_CHR     1606
+#define IDM_REP_ADR     1607
+#define IDM_REP_FLT     1608
+#define IDM_REP_STR     1609
+#define IDM_REP_INS     1610
+#define IDM_DSPMENU     1700
+#define IDM_DSP_SHOW    1701
+#define IDM_DSP_ADD     1702
+#define IDM_HELPMENU    1800
+#define IDM_HELP_EXT    1801
+#define IDM_HELP_KEYS   1802
+#define IDM_HELP_INDEX  1803
+#define IDM_HELP_CONTENTS 1804
+#define IDM_HELP_HELP   1805
+#define IDM_ABOUT       1806
+#define IDM_TUTORIAL    1807
+#define IDM_VIEWMENU    1900
+#define IDM_GOTO        1901
+#define IDM_FIND        1902
+#define IDM_FINDNEXT    1903
+#define IDM_FINDPREV    1904
+#define IDM_REFRESH     1905
+#define IDM_WIN_SRC     2000    // ...and following IDs
+#define IDM_COMPLETIONS 3000    // ...and following IDs
+
+#define IDD_PMDEBUGMODE 1000
+#define IDD_BRKPT_LINE  1001
+#define IDD_STARTUP     1002
+#define IDD_DISPLAY     1003
+#define IDD_GOTO        1004
+#define IDD_ABOUT       1005
+#define IDD_FIND        1006
+#define IDD_HISTORY     1007
+
+#define IDC_HELP        1000
+#define IDC_SYNC        1001
+#define IDC_ENABLE      1002
+#define IDC_CLOSE_WIN   1003
+#define IDC_ARGS        1004
+#define IDC_EXPR        1005
+#define IDC_FORMAT      1006
+#define IDC_COUNT       1007
+#define IDC_SOURCE      1008
+#define IDC_LINENO      1009
+#define IDC_RUN         1010
+#define IDC_CONDITION   1011
+#define IDC_DISPOSITION 1012
+#define IDC_STRING      1013
+#define IDC_LIST        1014
+#define IDC_IGNORE      1015
+
+#define UWM_STATE               (WM_USER+0)
+#define UWM_SOURCE              (WM_USER+1)
+#define UWM_CLOSE_SRC           (WM_USER+2)
+#define UWM_PMDBG_START         (WM_USER+3)
+#define UWM_PMDBG_STOP          (WM_USER+4)
+#define UWM_PMDBG_TERM          (WM_USER+5)
+#define UWM_MENU                (WM_USER+6)
+#define UWM_FATAL               (WM_USER+7)
+
+#define HELP_TABLE              1
Index: trunk/src/emx/src/pmgdb/pmgdb.ipp
===================================================================
--- trunk/src/emx/src/pmgdb/pmgdb.ipp	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmgdb.ipp	(revision 18)
@@ -0,0 +1,2008 @@
+.* pmgdb.ipp
+.*
+.* Copyright (c) 1996 Eberhard Mattes
+.*
+.* This file is part of pmgdb.
+.*
+.* pmgdb is free software; you can redistribute it and/or modify it
+.* under the terms of the GNU General Public License as published by
+.* the Free Software Foundation; either version 2, or (at your option)
+.* any later version.
+.*
+.* pmgdb is distributed in the hope that it will be useful,
+.* but WITHOUT ANY WARRANTY; without even the implied warranty of
+.* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+.* GNU General Public License for more details.
+.*
+.* You should have received a copy of the GNU General Public License
+.* along with pmgdb; see the file COPYING.  If not, write to the
+.* the Free Software Foundation, 59 Temple Place - Suite 330,
+.* Boston, MA 02111-1307, USA.
+.*
+:userdoc.
+:prolog.
+:docprof toc=1234.
+:title.Help for pmgdb
+:eprolog.
+:body.
+
+.imd help.h
+
+.nameit symbol=tt text=':font facename=Courier size=16x9.'
+.nameit symbol=ett text=':font facename=default size=0x0.'
+
+.************************************************************************
+.* General help, nothing selected
+.************************************************************************
+:h1 res=&HELP_GENERAL..About pmgdb
+:i1 id='pmgdb'.pmgdb
+:lm margin=1.
+:p.
+:hp2.pmgdb:ehp2. is a Presentation Manager frontend for GDB, the
+GNU debugger.
+:p.
+To start :hp2.pmgdb:ehp2. from the command line, type
+:lm margin=5.:xmp.pmgdb app.exe arg1 arg2:exmp.:lm margin=1.
+:p.
+where &tt.app.exe&ett. is the application
+to be debugged and &tt.arg1&ett. and &tt.arg2&ett. are command
+line arguments for that application.
+:p.
+Alternatively, you can select the application to debug and provide
+command line arguments with :hp2.pmgdb:ehp2.'s menus.
+:p.
+In addition to a :link reftype=hd res=&HELP_TUTORIAL..tutorial:elink.,
+help is available on the following topics&colon.
+:p.
+:ul.
+:li.:link reftype=hd res=&HELP_CMD_WINDOW..The command window:elink.
+:li.:link reftype=hd res=&HELP_SRC_WINDOW..Source windows:elink.
+:li.:link reftype=hd res=&HELP_SRCS_WINDOW..Source files window:elink.
+:li.:link reftype=hd res=&HELP_BRK_WINDOW..Breakpoints window:elink.
+:li.:link reftype=hd res=&HELP_DSP_WINDOW..Display window:elink.
+:li.:link reftype=hd res=&HELP_THR_WINDOW..Threads window:elink.
+:li.:link reftype=hd res=&HELP_REG_WINDOW..Register window:elink.
+:eul.
+
+.************************************************************************
+.* Command window
+.************************************************************************
+:h1 res=&HELP_CMD_WINDOW..Help for command window
+:i1 id='cmd'.pmgdb command window
+:lm margin=1.
+:p.
+The command window of :hp2.pmgdb:ehp2. shows GDB's output. You can
+type GDB commands in the command window. Select
+:link reftype=hd res=&HPM_CMD_HISTORY..History:elink. from the
+:link reftype=hd res=&HPM_CMD_FILEMENU..File:elink. menu to
+edit the command. If you close the command
+window, :hp2.pmgdb:ehp2. will be terminated.
+:p.
+In addition to a :link reftype=hd res=&HELP_TUTORIAL..tutorial:elink.,
+help is available on the following topics&colon.
+:p.
+:ul.
+:li.:link reftype=hd res=&HPM_CMD_FILEMENU..File menu:elink.
+:li.:link reftype=hd res=&HPM_CMD_EDITMENU..Edit menu:elink.
+:li.:link reftype=hd res=&HPM_CMD_RUNMENU..Run menu:elink.
+:li.:link reftype=hd res=&HPM_CMD_BRKPTMENU..Breakpoints menu:elink.
+:li.:link reftype=hd res=&HPM_CMD_OPTIONSMENU..Options menu:elink.
+:li.:link reftype=hd res=&HPM_CMD_WINMENU..Windows menu:elink.
+:li.:link reftype=hd res=&HPM_CMD_HELPMENU..Help menu:elink.
+:li.:link reftype=hd res=&HELP_CMD_KEYS..Keys in the command window:elink.
+:eul.
+
+.************************************************************************
+.* File
+.************************************************************************
+:h2 res=&HPM_CMD_FILEMENU..Help for File
+:i2 refid='cmd'.File menu
+:i1 id='cmd.file'.File menu choices (command window)
+:lm margin=1.
+:p.
+The File menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_CMD_OPEN_EXEC..Open program file:elink.
+:pd.Open a program file.
+:pt.:link reftype=hd res=&HPM_CMD_OPEN_CORE..Open core file:elink.
+:pd.Open a core dump file.
+:pt.:link reftype=hd res=&HPM_OPEN_SOURCE..Open a source file:elink.
+:pd.Open a source file.
+:pt.:link reftype=hd res=&HPM_CMD_STARTUP..Startup:elink.
+:pd.Set command line arguments and other startup options.
+:pt.:link reftype=hd res=&HPM_RESTART..Restart:elink.
+:pd.Restart the program.
+:pt.:link reftype=hd res=&HPM_WHERE..Where:elink.
+:pd.Show current location of execution.
+:pt.:link reftype=hd res=&HPM_EXIT..Exit:elink.
+:pd.Terminate :hp2.pmgdb:ehp2..
+:eparml.
+
+.************************************************************************
+.* Open program file
+.************************************************************************
+:h3 res=&HPM_CMD_OPEN_EXEC..Help for Open program file
+:i2 refid='cmd.file'.Open program file
+:i2 refid='pmgdb'.Open program file
+:i2 refid='pmgdb'.Program file
+:lm margin=1.
+:p.
+Use this choice to open a program file, that is, to specify the program
+to be debugged (debuggee).
+
+.************************************************************************
+.* Open core file
+.************************************************************************
+:h3 res=&HPM_CMD_OPEN_CORE..Help for Open core file
+:i2 refid='cmd.file'.Open core file
+:i2 refid='pmgdb'.Open core file
+:i2 refid='pmgdb'.core file
+:lm margin=1.
+:p.
+Use this choice to open a core dump file.
+
+.************************************************************************
+.* Open source file
+.************************************************************************
+:h3 res=&HPM_OPEN_SOURCE..Help for Open source file
+:i2 refid='cmd.file'.Open source file
+:i2 refid='pmgdb'.Open source file
+:i2 refid='pmgdb'.Source file
+:lm margin=1.
+:p.
+Use this choice to open a source file.  If the source file is already
+loaded, the window for that source file will be displayed.  Otherwise,
+the source file will be loaded and displayed in a new window.
+
+.************************************************************************
+.* Startup
+.************************************************************************
+:h3 res=&HPM_CMD_STARTUP..Help for Startup
+:i2 refid='cmd.file'.Startup
+:i2 refid='pmgdb'.Startup
+:i2 refid='pmgdb'.Command line arguments for debuggee
+:lm margin=1.
+:p.
+Use this choice to specify startup options. 
+This choice opens the
+:link reftype=hd res=&HPD_STARTUP..Startup:elink. dialog box.
+You can enter the command line options and select whether the
+VIO window of the debuggee should be closed after termination of the
+debuggee.
+
+.************************************************************************
+.* Restart
+.************************************************************************
+:h3 res=&HPM_RESTART..Help for Restart
+:i2 refid='cmd.file'.Restart
+:i2 refid='pmgdb'.Restart
+:lm margin=1.
+:p.
+Use this choice to restart the debuggee.  If the debuggee is running,
+it will be stopped and restarted.  If the debuggee is not running, it
+will be started.  The debugger keeps any breakpoints.  If no
+breakpoints are set (or all breakpoints are disabled), a breakpoint
+will be set on &tt.main&ett.
+
+.************************************************************************
+.* Where
+.************************************************************************
+:h3 res=&HPM_WHERE..Help for Where
+:i2 refid='cmd.file'.Where
+:i2 refid='pmgdb'.Where
+:lm margin=1.
+:p.
+Use this choice to show the current location of execution.  If source
+code is available for that location, the appropriate source file will
+be displayed with the current line highlighted.
+
+.************************************************************************
+.* Exit
+.************************************************************************
+:h3 res=&HPM_EXIT..Help for Exit
+:i2 refid='cmd.file'.Exit
+:i2 refid='pmgdb'.Exit
+:lm margin=1.
+:p.
+Use this choice to terminate :hp2.pmgdb:ehp2..  If a debuggee is running,
+it will be terminated.  :hp2.GDB:ehp2. will also be terminated.
+
+.************************************************************************
+.* Edit
+.************************************************************************
+:h2 res=&HPM_CMD_EDITMENU..Help for Edit
+:i2 refid='cmd'.Edit menu
+:i1 id='cmd.edit'.Edit menu choices (command window)
+:lm margin=1.
+:p.
+The Edit menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_CMD_COMPLETE..Complete:elink.
+:pd.Command completion.
+:pt.:link reftype=hd res=&HPM_CMD_HISTORY..History:elink.
+:pd.Select, edit, and repeat a previously issued command.
+:eparml.
+
+.************************************************************************
+.* Complete
+.************************************************************************
+:h3 res=&HPM_CMD_COMPLETE..Help for Complete
+:i2 refid='cmd.edit'.Complete
+:i2 refid='pmgdb'.Complete
+:lm margin=1.
+:p.
+Use this choice to complete the command typed in the command window.
+If there is more than one possible completion, a popup window will
+show all available completions.  Select one of those choices to
+complete the command.
+
+.************************************************************************
+.* History
+.************************************************************************
+:h3 res=&HPM_CMD_HISTORY..Help for History
+:i2 refid='cmd.edit'.History
+:i2 refid='pmgdb'.History
+:lm margin=1.
+:p.
+Use this choice to select and edit a command from a list of all previously
+issued commands or to edit the current command.  This choice opens the
+:link reftype=hd res=&HPD_HISTORY..History:elink. dialog box.
+
+.************************************************************************
+.* Run
+.************************************************************************
+:h2 res=&HPM_CMD_RUNMENU..Help for Run
+:i2 refid='pmgdb'.Run menu (command window)
+:i1 id='cmd.run'.Run menu choices
+:lm margin=1.
+:p.
+The Run menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_GO..Go:elink.
+:pd.Continue (or start) program.
+:pt.:link reftype=hd res=&HPM_STEPOVER..Step over:elink.
+:pd.Step program, proceeding through subroutine calls.
+:pt.:link reftype=hd res=&HPM_STEPINTO..Step into:elink.
+:pd.Step program until it reaches a different source line.
+:pt.:link reftype=hd res=&HPM_FINISH..Finish:elink.
+:pd.Execute until selected stack frame returns.
+:pt.:link reftype=hd res=&HPM_ISTEPOVER..Insn step over:elink.
+:pd.Step one instruction, proceeding through subroutine calls.
+:pt.:link reftype=hd res=&HPM_ISTEPINTO..Insn step into:elink.
+:pd.Step one instruction.
+:eparml.
+
+.************************************************************************
+.* Go
+.************************************************************************
+:h3 res=&HPM_GO..Help for Go
+:i2 refid='cmd.run'.Go
+:i2 refid='pmgdb'.Go
+:i2 refid='pmgdb'.Continue program
+:i2 refid='pmgdb'.Start program
+:lm margin=1.
+:p.
+Use this choice to let the program run until a breakpoint is hit or a
+signal occurs.  If the program has not yet been started, it will be
+started and a breakpoint will be set on &tt.main&ett.  if no
+breakpoints are set (or all breakpoints are disabled).
+
+.************************************************************************
+.* Step over
+.************************************************************************
+:h3 res=&HPM_STEPOVER..Help for Step over
+:i2 refid='cmd.run'.Step over
+:i2 refid='pmgdb'.Step over
+:lm margin=1.
+:p.
+Use this choice to step the program, proceeding through subroutine calls.
+Subroutine calls are treated as one instruction.  If there are no subroutine
+calls, this choice is equivalent to
+:link reftype=hd res=&HPM_STEPINTO..Step into:elink..
+
+.************************************************************************
+.* Step into
+.************************************************************************
+:h3 res=&HPM_STEPINTO..Help for Step into
+:i2 refid='cmd.run'.Step into
+:i2 refid='pmgdb'.Step into
+:lm margin=1.
+:p.
+Use this choice to step the program until it reaches a different source
+line.  See also
+:link reftype=hd res=&HPM_STEPOVER..Step over:elink..
+
+.************************************************************************
+.* Finish
+.************************************************************************
+:h3 res=&HPM_FINISH..Help for Finish
+:i2 refid='cmd.run'.Finish
+:i2 refid='pmgdb'.Finish
+:lm margin=1.
+:p.
+Use this choice to execute the program until the selected stack frame
+returns.  That is, this choice finishes a subroutine call, stopping
+at the location from which the subroutine was called.  The returned value
+is printed in the command window.
+
+.************************************************************************
+.* Insn step over
+.************************************************************************
+:h3 res=&HPM_ISTEPOVER..Help for Insn step over
+:i2 refid='cmd.run'.Insn step over
+:i2 refid='pmgdb'.Insn step over
+:lm margin=1.
+:p.
+Use this choice to step one instruction of the program. Subroutine
+calls are treated as one instruction. If the instruction is not
+a subroutine call, this choice is equivalent to
+:link reftype=hd res=&HPM_ISTEPINTO..Insn step into:elink..
+
+.************************************************************************
+.* Insn step into
+.************************************************************************
+:h3 res=&HPM_ISTEPINTO..Help for Insn step into
+:i2 refid='cmd.run'.Insn step into
+:i2 refid='pmgdb'.Insn step into
+:lm margin=1.
+:p.
+Use this choice to step one instruction of the program.  See also
+:link reftype=hd res=&HPM_ISTEPOVER..Insn step over:elink..
+
+.************************************************************************
+.* Breakpoints
+.************************************************************************
+:h2 res=&HPM_CMD_BRKPTMENU..Help for Breakpoints
+:i2 refid='cmd'.Breakpoints menu
+:i1 id='cmd.brkpt'.Breakpoints menu choices (command window)
+:lm margin=1.
+:p.
+The Breakpoints menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_BRKPT_LINE..On line:elink.
+:pd.Set a breakpoint on a line.
+:pt.:link reftype=hd res=&HPM_BRKPT_LIST..List:elink.
+:pd.Open the breakpoints window.
+:eparml.
+
+.************************************************************************
+.* On line
+.************************************************************************
+:h3 res=&HPM_BRKPT_LINE..Help for On line
+:i2 refid='cmd.brkpt'.On line
+:i2 refid='pmgdb'.On line
+:i2 refid='pmgdb'.Breakpoint, on line
+:lm margin=1.
+:p.
+Use this choice to set a breakpoint on a line of the source code.
+This choice opens the
+:link reftype=hd res=&HPD_BRKPT_LINE..Line Breakpoint:elink. dialog box.
+:p.
+You can also set or clear a breakpoint by double clicking with the
+first mouse button on the line number in a source window.
+
+.************************************************************************
+.* List
+.************************************************************************
+:h3 res=&HPM_BRKPT_LIST..Help for List
+:i2 refid='cmd.brkpt'.List
+:i2 refid='pmgdb'.List
+:i2 refid='pmgdb'.Breakpoint, list
+:lm margin=1.
+:p.
+Use this choice to open the breakpoints window which shows all the
+breakpoints.
+
+.************************************************************************
+.* Options
+.************************************************************************
+:h2 res=&HPM_CMD_OPTIONSMENU..Help for Options
+:i2 refid='cmd'.Options menu
+:i1 id='cmd.options'.Options menu choices
+:lm margin=1.
+:p.
+The Options menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_PMDEBUGMODE..PM debugging mode:elink.
+:pd.Select the mode for debugging PM applications.
+:pt.:link reftype=hd res=&HPM_CMD_ANNOTATE..Annotate:elink.
+:pd.Print annotations.
+:pt.:link reftype=hd res=&HPM_CMD_FONT..Font:elink.
+:pd.Select font.
+:eparml.
+
+.************************************************************************
+.* PM debugging mode
+.************************************************************************
+:h3 res=&HPM_PMDEBUGMODE..Help for PM debugging mode
+:i2 refid='cmd.options'.PM debugging mode
+:i2 refid='pmgdb'.PM debugging mode
+:lm margin=1.
+:p.
+Use this choice to select the mode for debugging PM applications.
+Synchronous mode should be selected before starting a Presentation
+Manager application, otherwise the Presentation Manager will hang,
+requiring a reboot to recover.  In Synchronous mode, only windows of
+:hp2.pmgdb:ehp2. and of the program being debugged can be made active;
+all other windows cannot be used.
+:hp2.pmgdb:ehp2. attempts to set Synchronous mode automatically when
+a PM program is loaded.  This choice opens the
+:link reftype=hd res=&HPD_PMDEBUGMODE..PM debugging mode:elink. dialog box.
+
+.************************************************************************
+.* Annotate
+.************************************************************************
+:h3 res=&HPM_CMD_ANNOTATE..Help for Annotate
+:i2 refid='cmd.options'.Annotate
+:i2 refid='pmgdb'.Annotate
+:lm margin=1.
+:p.
+Use this choice to turn on printing of GDB's annotations.  This us
+used for debugging :hp2.pmgdb:ehp2..
+
+.************************************************************************
+.* Font
+.************************************************************************
+:h3 res=&HPM_CMD_FONT..Help for Font
+:i2 refid='cmd.options'.Font
+:i2 refid='pmgdb'.Font
+:lm margin=1.
+:p.
+Use this choice to select a font for all windows of :hp2.pmgdb:ehp2..
+You can change the font of a single window by dragging a font from the
+Font Palette and dropping it on a :hp2.pmgdb:ehp2. window.
+
+.************************************************************************
+.* Windows
+.************************************************************************
+:h2 res=&HPM_CMD_WINMENU..Help for Windows
+:i2 refid='cmd'.Windows menu
+:i1 id='cmd.win'.Windows menu choices
+:lm margin=1.
+:p.
+The Windows menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_WIN_SRCS..Source files:elink.
+:pd.Show the source files window.
+:pt.:link reftype=hd res=&HPM_WIN_BRK..Breakpoints:elink.
+:pd.Show the breakpoints window.
+:pt.:link reftype=hd res=&HPM_WIN_DSP..Display:elink.
+:pd.Show the display window.
+:pt.:link reftype=hd res=&HPM_WIN_THR..Threads:elink.
+:pd.Show the threads window.
+:pt.:link reftype=hd res=&HPM_WIN_REG..Register:elink.
+:pd.Show the register window.
+:eparml.
+
+.************************************************************************
+.* Source files
+.************************************************************************
+:h3 res=&HPM_WIN_SRCS..Help for Source files
+:i2 refid='cmd.win'.Source files
+:i2 refid='pmgdb'.Source files
+:lm margin=1.
+:p.
+Use this choice to show the source files window.
+
+.************************************************************************
+.* Breakpoints
+.************************************************************************
+:h3 res=&HPM_WIN_BRK..Help for Breakpoints
+:i2 refid='cmd.win'.Breakpoints
+:i2 refid='pmgdb'.Breakpoints
+:lm margin=1.
+:p.
+Use this choice to show the breakpoints window.
+
+.************************************************************************
+.* Display
+.************************************************************************
+:h3 res=&HPM_WIN_DSP..Help for Display
+:i2 refid='cmd.win'.Display
+:i2 refid='pmgdb'.Display
+:lm margin=1.
+:p.
+Use this choice to show the display window.
+
+.************************************************************************
+.* Threads
+.************************************************************************
+:h3 res=&HPM_WIN_THR..Help for Threads
+:i2 refid='cmd.win'.Threads
+:i2 refid='pmgdb'.Threads
+:lm margin=1.
+:p.
+Use this choice to show the threads window.
+
+.************************************************************************
+.* Register
+.************************************************************************
+:h3 res=&HPM_WIN_REG..Help for Register
+:i2 refid='cmd.win'.Register
+:i2 refid='pmgdb'.Register
+:lm margin=1.
+:p.
+Use this choice to show the register window.
+
+.************************************************************************
+.* Help
+.************************************************************************
+:h2 res=&HPM_CMD_HELPMENU..Help for Help
+:i2 refid='cmd'.Help menu
+:i1 id='cmd.help'.Help menu choices
+:lm margin=1.
+:p.
+The Help menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_HELP_HELP..Help for help:elink.
+:pd.Display help for help.
+:pt.:link reftype=hd res=&HPM_HELP_EXT..Extended help:elink.
+:pd.Display extended help.
+:pt.:link reftype=hd res=&HPM_HELP_KEYS..Keys help:elink.
+:pd.Display help about keys.
+:pt.:link reftype=hd res=&HPM_HELP_INDEX..Help index:elink.
+:pd.Display the help index.
+:pt.:link reftype=hd res=&HPM_HELP_CONTENTS..Help index:elink.
+:pd.Display the help contents.
+:pt.:link reftype=hd res=&HPM_TUTORIAL..Tutorial:elink.
+:pd.Display tutorial.
+:pt.:link reftype=hd res=&HPM_CMD_ABOUT..About:elink.
+:pd.Display copyright information.
+:eparml.
+
+.************************************************************************
+.* Help for Help
+.************************************************************************
+:h3 res=&HPM_HELP_HELP..Help for Help
+:i2 refid='cmd.help'.Help for Help
+:lm margin=1.
+:p.
+Use this choice to get online help for help.
+
+.************************************************************************
+.* Extended help
+.************************************************************************
+:h3 res=&HPM_HELP_EXT..Help for Extended help
+:i2 refid='cmd.help'.Extended help
+:lm margin=1.
+:p.
+Use this choice to get online help
+for :hp2.pmgdb:ehp2.. You can also press the :hp2.F1:ehp2. key
+to get online help.
+
+.************************************************************************
+.* Keys help
+.************************************************************************
+:h3 res=&HPM_HELP_KEYS..Help for Keys help
+:i2 refid='cmd.help'.Keys help
+:lm margin=1.
+:p.
+Use this choice to get online help for :hp2.pmgdb:ehp2. keys.
+
+.************************************************************************
+.* Help index
+.************************************************************************
+:h3 res=&HPM_HELP_INDEX..Help for Help index
+:i2 refid='cmd.help'.Help for Help index
+:lm margin=1.
+:p.
+Use this choice to display the help index.
+
+.************************************************************************
+.* Help contents
+.************************************************************************
+:h3 res=&HPM_HELP_CONTENTS..Help for Help contents
+:i2 refid='cmd.help'.Help for Help contents
+:lm margin=1.
+:p.
+Use this choice to display the table of contents for online help.
+
+.************************************************************************
+.* Tutorial
+.************************************************************************
+:h3 res=&HPM_TUTORIAL..Help for Tutorial
+:i2 refid='cmd.help'.Tutorial
+:lm margin=1.
+:p.
+Use this choice to display the :hp2.pmgdb:ehp2.
+:link reftype=hd res=&HELP_TUTORIAL..tutorial:elink..
+
+.************************************************************************
+.* About
+.************************************************************************
+:h3 res=&HPM_CMD_ABOUT..Help for About
+:i2 refid='cmd.help'.About
+:i2 refid='pmgdb'.Author
+:i2 refid='pmgdb'.Copyright
+:lm margin=1.
+:p.
+Use this choice to display copyright information
+about :hp2.pmgdb:ehp2..
+
+.************************************************************************
+.* Keys help (command window)
+.************************************************************************
+:h1 res=&HELP_CMD_KEYS..Keys help (command window)
+:i1 id='cmd.keys'.Keys (command window)
+:lm margin=1.
+:p.
+You can use the following keys in the command window&colon.
+:dl tsize=20 compact.
+:dt.Backspace:dd.Delete one character to the left.
+:dt.Up arrow:dd.Fetch the previous command from the command history.
+:dt.Down arrow:dd.Fetch the next command from the command history.
+:dt.Page Up:dd.Scroll down by one window.
+:dt.Page Down:dd.Scroll up by one window.
+:dt.Ctrl+Page Up:dd.Scroll down right by one window.
+:dt.Ctrl+Page Down:dd.Scroll left by one window.
+:edl.
+:p.
+Accelerator keys are missed out in the list above.
+
+.************************************************************************
+.* Source window
+.************************************************************************
+:h1 res=&HELP_SRC_WINDOW..Help for source window
+:i1 id='src'.pmgdb source window
+:lm margin=1.
+:p.
+The source windows of :hp2.pmgdb:ehp2. show the source code of the
+application being debugged.  There may be multiple source windows,
+one for each source file.  Closing a source window doesn't terminate
+:hp2.pmgdb:ehp2..
+:p.
+Help is available on the following topics&colon.
+:p.
+:ul.
+:li.:link reftype=hd res=&HPM_SRC_FILEMENU..File menu:elink.
+:li.:link reftype=hd res=&HPM_SRC_VIEWMENU..View menu:elink.
+:li.:link reftype=hd res=&HPM_SRC_RUNMENU..Run menu:elink.
+:li.:link reftype=hd res=&HPM_SRC_BRKPTMENU..Breakpoints menu:elink.
+:li.:link reftype=hd res=&HPM_SRC_DSPMENU..Display menu:elink.
+:li.:link reftype=hd res=&HPM_SRC_OPTIONSMENU..Options menu:elink.
+:li.:link reftype=hd res=&HPM_SRC_WINMENU..Windows menu:elink.
+:li.:link reftype=hd res=&HPM_SRC_HELPMENU..Help menu:elink.
+:li.:link reftype=hd res=&HELP_SRC_KEYS..Keys in a source window:elink.
+:eul.
+
+.************************************************************************
+.* File
+.************************************************************************
+:h2 res=&HPM_SRC_FILEMENU..Help for File
+:i2 refid='src'.File menu
+:i1 id='src.file'.File menu choices (source window)
+:lm margin=1.
+:p.
+The File menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_OPEN_SOURCE..Open a source file:elink.
+:pd.Open a source file.
+:pt.:link reftype=hd res=&HPM_RESTART..Restart:elink.
+:pd.Restart the program.
+:pt.:link reftype=hd res=&HPM_WHERE..Where:elink.
+:pd.Show current location of execution.
+:pt.:link reftype=hd res=&HPM_EXIT..Exit:elink.
+:pd.Terminate :hp2.pmgdb:ehp2..
+:eparml.
+
+.************************************************************************
+.* View
+.************************************************************************
+:h2 res=&HPM_SRC_VIEWMENU..Help for View
+:i2 refid='src'.View menu
+:i1 id='src.view'.View menu choices (source window)
+:lm margin=1.
+:p.
+The View menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_SRC_FIND..Find:elink.
+:pd.Search for a regular expression.
+:pt.:link reftype=hd res=&HPM_SRC_FINDNEXT..Find next:elink.
+:pd.Search for next occurrence.
+:pt.:link reftype=hd res=&HPM_SRC_FINDPREV..Find previous:elink.
+:pd.Search for previous occurrence.
+:pt.:link reftype=hd res=&HPM_SRC_GOTO..Go to line:elink.
+:pd.Show a line specified by line number.
+:eparml.
+
+.************************************************************************
+.* Find
+.************************************************************************
+:h3 res=&HPM_SRC_FIND..Help for Find
+:i2 refid='src.view'.Find
+:i2 refid='pmgdb'.Find
+:lm margin=1.
+:p.
+Use this choice to search the source file for a regular expression.
+This choice opens the
+:link reftype=hd res=&HPD_FIND..Find:elink. dialog box.
+The search starts at the beginning of the file.
+See also :link reftype=hd res=&HPM_SRC_FINDNEXT..Find next:elink.
+and :link reftype=hd res=&HPM_SRC_FINDPREV..Find previous:elink..
+
+.************************************************************************
+.* Find next
+.************************************************************************
+:h3 res=&HPM_SRC_FINDNEXT..Help for Find next
+:i2 refid='src.view'.Find next
+:i2 refid='pmgdb'.Find next
+:lm margin=1.
+:p.
+Use this choice to search for the next occurrence of a regular expression.
+The search continues from the line following the line containing the
+previously found match.
+See also :link reftype=hd res=&HPM_SRC_FIND..Find:elink.
+and :link reftype=hd res=&HPM_SRC_FINDPREV..Find previous:elink..
+
+.************************************************************************
+.* Find previous
+.************************************************************************
+:h3 res=&HPM_SRC_FINDPREV..Help for Find previous
+:i2 refid='src.view'.Find previous
+:i2 refid='pmgdb'.Find previous
+:lm margin=1.
+:p.
+Use this choice to search for the previous occurrence of a regular expression.
+The search continues from the line preceding the line containing the
+previously found match.
+See also :link reftype=hd res=&HPM_SRC_FIND..Find:elink.
+and :link reftype=hd res=&HPM_SRC_FINDNEXT..Find next:elink..
+
+.************************************************************************
+.* Go to line
+.************************************************************************
+:h3 res=&HPM_SRC_GOTO..Help for Go to line
+:i2 refid='src.view'.Go to line
+:i2 refid='pmgdb'.Go to line
+:lm margin=1.
+:p.
+Use this choice to show a line of the current source file
+specified by line number.  This choice opens the
+:link reftype=hd res=&HPD_GOTO..Go to line:elink. dialog box.
+
+.************************************************************************
+.* Run
+.************************************************************************
+:h2 res=&HPM_SRC_RUNMENU..Help for Run
+:i2 refid='pmgdb'.Run menu (source window)
+:i1 id='src.run'.Run menu choices
+:lm margin=1.
+:p.
+The Run menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_GO..Go:elink.
+:pd.Continue (or start) program.
+:pt.:link reftype=hd res=&HPM_STEPOVER..Step over:elink.
+:pd.Step program, proceeding through subroutine calls.
+:pt.:link reftype=hd res=&HPM_STEPINTO..Step into:elink.
+:pd.Step program until it reaches a different source line.
+:pt.:link reftype=hd res=&HPM_FINISH..Finish:elink.
+:pd.Execute until selected stack frame returns.
+:pt.:link reftype=hd res=&HPM_ISTEPOVER..Insn step over:elink.
+:pd.Step one instruction, proceeding through subroutine calls.
+:pt.:link reftype=hd res=&HPM_ISTEPINTO..Insn step into:elink.
+:pd.Step one instruction.
+:pt.:link reftype=hd res=&HPM_SRC_UNTIL..Until:elink.
+:pd.Execute until the program reaches the selected line.
+:pt.:link reftype=hd res=&HPM_SRC_JUMP..Jump:elink.
+:pd.Jump to the selected line.
+:eparml.
+
+.************************************************************************
+.* Until
+.************************************************************************
+:h3 res=&HPM_SRC_UNTIL..Help for Until
+:i2 refid='src.run'.Until
+:i2 refid='pmgdb'.Until
+:lm margin=1.
+:p.
+Use this choice to let the program run until it reaches the selected line.
+Click with the first mouse button on a line number in a source window to
+select a line.
+
+.************************************************************************
+.* Jump
+.************************************************************************
+:h3 res=&HPM_SRC_JUMP..Help for Jump
+:i2 refid='src.run'.Jump
+:i2 refid='pmgdb'.Jump
+:lm margin=1.
+:p.
+Use this choice to jump to the selected line.  Execution will continue
+from that line.  Click with the first mouse button on a line number in
+a source window to select a line.
+
+.************************************************************************
+.* Breakpoints
+.************************************************************************
+:h2 res=&HPM_SRC_BRKPTMENU..Help for Breakpoints
+:i2 refid='src'.Breakpoints menu
+:i1 id='src.brkpt'.Breakpoints menu choices (source window)
+:lm margin=1.
+:p.
+The Breakpoints menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_BRKPT_LINE..On line:elink.
+:pd.Set a breakpoint on a line.
+:pt.:link reftype=hd res=&HPM_BRKPT_LIST..List:elink.
+:pd.Open the breakpoints window.
+:eparml.
+
+.************************************************************************
+.* Display
+.************************************************************************
+:h2 res=&HPM_SRC_DSPMENU..Help for Display
+:i2 refid='src'.Display menu
+:i1 id='src.dsp'.Display menu choices
+:lm margin=1.
+:p.
+The Display menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_DSP_ADD..Add:elink.
+:pd.Add a display.
+:pt.:link reftype=hd res=&HPM_SRC_DSP_SHOW..Show:elink.
+:pd.Show the display window.
+:eparml.
+
+.************************************************************************
+.* Show
+.************************************************************************
+:h3 res=&HPM_SRC_DSP_SHOW..Help for Show
+:i2 refid='src.dsp'.Show
+:i2 refid='pmgdb'.Show
+:lm margin=1.
+:p.
+Use this choice to show the display window.
+
+.************************************************************************
+.* Options
+.************************************************************************
+:h2 res=&HPM_SRC_OPTIONSMENU..Help for Options
+:i2 refid='src'.Options menu
+:i1 id='src.options'.Options menu choices
+:lm margin=1.
+:p.
+The Options menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_PMDEBUGMODE..PM debugging mode:elink.
+:pd.Select the mode for debugging PM applications.
+:eparml.
+
+.************************************************************************
+.* Windows
+.************************************************************************
+:h2 res=&HPM_SRC_WINMENU..Help for Windows
+:i2 refid='src'.Windows menu
+:i1 id='src.win'.Windows menu choices (source window)
+:lm margin=1.
+:p.
+The Windows menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_WIN_CMD..Command:elink.
+:pd.Show the command window.
+:pt.:link reftype=hd res=&HPM_WIN_SRCS..Source files:elink.
+:pd.Show the source files window.
+:pt.:link reftype=hd res=&HPM_WIN_BRK..Breakpoints:elink.
+:pd.Show the breakpoints window.
+:pt.:link reftype=hd res=&HPM_WIN_DSP..Display:elink.
+:pd.Show the display window.
+:pt.:link reftype=hd res=&HPM_WIN_THR..Threads:elink.
+:pd.Show the threads window.
+:pt.:link reftype=hd res=&HPM_WIN_REG..Register:elink.
+:pd.Show the register window.
+:eparml.
+
+.************************************************************************
+.* Command
+.************************************************************************
+:h3 res=&HPM_WIN_CMD..Help for Command
+:i2 refid='src.win'.Command
+:i2 refid='pmgdb'.Command
+:lm margin=1.
+:p.
+Use this choice to show the command window.
+
+.************************************************************************
+.* Help
+.************************************************************************
+:h2 res=&HPM_SRC_HELPMENU..Help for Help
+:i2 refid='src'.Help menu
+:i1 id='src.help'.Help menu choices
+:lm margin=1.
+:p.
+The Help menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_HELP_HELP..Help for help:elink.
+:pd.Display help for help.
+:pt.:link reftype=hd res=&HPM_HELP_EXT..Extended help:elink.
+:pd.Display extended help.
+:pt.:link reftype=hd res=&HPM_HELP_KEYS..Keys help:elink.
+:pd.Display help about keys.
+:pt.:link reftype=hd res=&HPM_HELP_INDEX..Help index:elink.
+:pd.Display the help index.
+:pt.:link reftype=hd res=&HPM_HELP_CONTENTS..Help index:elink.
+:pd.Display the help contents.
+:eparml.
+
+.************************************************************************
+.* Keys help (source window)
+.************************************************************************
+:h1 res=&HELP_SRC_KEYS..Keys help (source window)
+:i1 id='src.keys'.Keys (source window)
+:lm margin=1.
+:p.
+You can use the following keys in a source window&colon.
+:dl tsize=20 compact.
+:dt.Up arrow:dd.Scroll down by one line.
+:dt.Down arrow:dd.Scroll up by one line.
+:dt.Page Up:dd.Scroll down by one window.
+:dt.Page Down:dd.Scroll up by one window.
+:dt.Left:dd.Scroll left by one character (average character width).
+:dt.Right:dd.Scroll right by one character (average character width).
+:dt.Ctrl+Page Up:dd.Scroll down right by one window.
+:dt.Ctrl+Page Down:dd.Scroll left by one window.
+:edl.
+:p.
+Accelerator keys are missed out in the list above.
+
+.************************************************************************
+.* Source files window
+.************************************************************************
+:h1 res=&HELP_SRCS_WINDOW..Help for source files window
+:i1 id='srcs'.pmgdb source files window
+:lm margin=1.
+:p.
+The source files window of :hp2.pmgdb:ehp2. lists the names of
+all source files for modules compiled with debugging enabled.
+Double clicking with the first mouse button on a file name will show
+an existing source window or open a new source window for that file.
+Closing the source files window doesn't terminate :hp2.pmgdb:ehp2..
+:p.
+Help is available on the following topics&colon.
+:p.
+:ul.
+:li.:link reftype=hd res=&HPM_SRCS_FILEMENU..File menu:elink.
+:li.:link reftype=hd res=&HPM_SRCS_WINMENU..Windows menu:elink.
+:li.:link reftype=hd res=&HPM_SRCS_HELPMENU..Help menu:elink.
+:li.:link reftype=hd res=&HELP_SRCS_KEYS..Keys in the source files
+window:elink.
+:eul.
+
+.************************************************************************
+.* File
+.************************************************************************
+:h2 res=&HPM_SRCS_FILEMENU..Help for File
+:i2 refid='srcs'.File menu
+:i1 id='srcs.file'.File menu choices (source files window)
+:lm margin=1.
+:p.
+The File menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_EXIT..Exit:elink.
+:pd.Terminate :hp2.pmgdb:ehp2..
+:eparml.
+
+.************************************************************************
+.* Windows
+.************************************************************************
+:h2 res=&HPM_SRCS_WINMENU..Help for Windows
+:i2 refid='srcs'.Windows menu
+:i1 id='srcs.win'.Windows menu choices (source files window)
+:lm margin=1.
+:p.
+The Windows menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_WIN_CMD..Command:elink.
+:pd.Show the command window.
+:pt.:link reftype=hd res=&HPM_WIN_BRK..Breakpoints:elink.
+:pd.Show the breakpoints window.
+:pt.:link reftype=hd res=&HPM_WIN_DSP..Display:elink.
+:pd.Show the display window.
+:pt.:link reftype=hd res=&HPM_WIN_THR..Threads:elink.
+:pd.Show the threads window.
+:pt.:link reftype=hd res=&HPM_WIN_REG..Register:elink.
+:pd.Show the register window.
+:eparml.
+
+.************************************************************************
+.* Help
+.************************************************************************
+:h2 res=&HPM_SRCS_HELPMENU..Help for Help
+:i2 refid='srcs'.Help menu
+:i1 id='srcs.help'.Help menu choices
+:lm margin=1.
+:p.
+The Help menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_HELP_HELP..Help for help:elink.
+:pd.Display help for help.
+:pt.:link reftype=hd res=&HPM_HELP_EXT..Extended help:elink.
+:pd.Display extended help.
+:pt.:link reftype=hd res=&HPM_HELP_KEYS..Keys help:elink.
+:pd.Display help about keys.
+:pt.:link reftype=hd res=&HPM_HELP_INDEX..Help index:elink.
+:pd.Display the help index.
+:pt.:link reftype=hd res=&HPM_HELP_CONTENTS..Help index:elink.
+:pd.Display the help contents.
+:eparml.
+
+.************************************************************************
+.* Keys help (source files window)
+.************************************************************************
+:h1 res=&HELP_SRCS_KEYS..Keys help (source files window)
+:i1 id='srcs.keys'.Keys (source files window)
+:lm margin=1.
+:p.
+You can use the following keys in the source files window&colon.
+:dl tsize=20 compact.
+:edl.
+:p.
+Accelerator keys are missed out in the list above.
+
+.************************************************************************
+.* Breakpoints window
+.************************************************************************
+:h1 res=&HELP_BRK_WINDOW..Help for breakpoints window
+:i1 id='brk'.pmgdb breakpoints window
+:lm margin=1.
+:p.
+The breakpoints window of :hp2.pmgdb:ehp2. shows all the breakpoints.
+For each breakpoint, the following values are displayed&colon.
+:dl tsize=12 compact.
+:dt.No:dd.The number of the breakpoint as maintained by GDB.  Modifying
+a breakpoint may change its number
+:dt.Ena:dd.y if the breakpoint is enabled, n if the breakpoint is disabled
+:dt.Address:dd.Address of the breakpoint
+:dt.Source:dd.Source file for the breakpoint address
+:dt.Line:dd.Line number for the breakpoint address
+:dt.Disp:dd.Disposition of the breakpoint: `keep' means that the breakpoint
+remains enabled when hit, `dis' means that the breakpoint will be disabled
+when hit, `del' means that the breakpoint will be deleted when hit.
+:dt.Ign:dd.Ignore count.  The breakpoint will be ignored this many
+times.
+:dt.Cond:dd.Condition.  This expression is evaluated whenever the
+breakpoint is hit; the breakpoint breaks only if the expression is true.
+:edl.
+:p.
+You can toggle the enabled state of a breakpoint by double clicking
+with the first mouse button on the value in the `Ena' column.  You can
+view the source code at the breakpoint by double clicking on the value
+in the `Source' or `Line' column.
+Closing the breakpoints window doesn't terminate :hp2.pmgdb:ehp2..
+:p.
+Help is available on the following topics&colon.
+:p.
+:ul.
+:li.:link reftype=hd res=&HPM_BRK_FILEMENU..File menu:elink.
+:li.:link reftype=hd res=&HPM_BRK_EDITMENU..Edit menu:elink.
+:li.:link reftype=hd res=&HPM_BRK_BRKPTMENU..Breakpoints menu:elink.
+:li.:link reftype=hd res=&HPM_BRK_WINMENU..Windows menu:elink.
+:li.:link reftype=hd res=&HPM_BRK_HELPMENU..Help menu:elink.
+:li.:link reftype=hd res=&HELP_BRK_KEYS..Keys in the breakpoints window:elink.
+:eul.
+
+.************************************************************************
+.* File
+.************************************************************************
+:h2 res=&HPM_BRK_FILEMENU..Help for File
+:i2 refid='brk'.File menu
+:i1 id='brk.file'.File menu choices (breakpoints window)
+:lm margin=1.
+:p.
+The File menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_EXIT..Exit:elink.
+:pd.Terminate :hp2.pmgdb:ehp2..
+:eparml.
+
+.************************************************************************
+.* Edit
+.************************************************************************
+:h2 res=&HPM_BRK_EDITMENU..Help for Edit
+:i2 refid='brk'.Edit menu
+:i1 id='brk.edit'.Edit menu choices (breakpoints window)
+:lm margin=1.
+:p.
+The Edit menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_BRK_MODIFY..Modify:elink.
+:pd.Modify the selected breakpoint.
+:pt.:link reftype=hd res=&HPM_BRK_ENABLE..Enable:elink.
+:pd.Enable the selected breakpoint.
+:pt.:link reftype=hd res=&HPM_BRK_DISABLE..Disable:elink.
+:pd.Disable the selected breakpoint.
+:pt.:link reftype=hd res=&HPM_BRK_DELETE..Delete:elink.
+:pd.Delete the selected breakpoint.
+:eparml.
+
+.************************************************************************
+.* Modify
+.************************************************************************
+:h3 res=&HPM_BRK_MODIFY..Help for Modify
+:i2 refid='brk.edit'.Modify
+:i2 refid='pmgdb'.Modify breakpoint
+:lm margin=1.
+:p.
+Use this choice to modify the selected breakpoint.  Click with the
+first mouse button select a breakpoint.
+
+.************************************************************************
+.* Enable
+.************************************************************************
+:h3 res=&HPM_BRK_ENABLE..Help for Enable
+:i2 refid='brk.edit'.Enable
+:i2 refid='pmgdb'.Enable
+:lm margin=1.
+:p.
+Use this choice to enable the selected breakpoint.  Click with the
+first mouse button select a breakpoint.
+
+.************************************************************************
+.* Disable
+.************************************************************************
+:h3 res=&HPM_BRK_DISABLE..Help for Disable
+:i2 refid='brk.edit'.Disable
+:i2 refid='pmgdb'.Disable breakpoint
+:lm margin=1.
+:p.
+Use this choice to disable the selected breakpoint.  Click with the
+first mouse button select a breakpoint.
+
+.************************************************************************
+.* Delete
+.************************************************************************
+:h3 res=&HPM_BRK_DELETE..Help for Delete
+:i2 refid='brk.edit'.Delete
+:i2 refid='pmgdb'.Delete breakpoint
+:lm margin=1.
+:p.
+Use this choice to delete the selected breakpoint.  Click with the
+first mouse button select a breakpoint.
+
+.************************************************************************
+.* Breakpoints
+.************************************************************************
+:h2 res=&HPM_BRK_BRKPTMENU..Help for Breakpoints
+:i2 refid='brk'.Breakpoints menu
+:i1 id='brk.brkpt'.Breakpoints menu choices (breakpoints window)
+:lm margin=1.
+:p.
+The Breakpoints menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_BRKPT_LINE..On line:elink.
+:pd.Set a breakpoint on a line.
+:pt.:link reftype=hd res=&HPM_BRK_REFRESH..Refresh:elink.
+:pd.Refresh the window contents.
+:eparml.
+
+.************************************************************************
+.* Refresh
+.************************************************************************
+:h3 res=&HPM_BRK_REFRESH..Help for Refresh
+:i2 refid='brk.brkpt'.Refresh
+:i2 refid='pmgdb'.Refresh (breakpoints window)
+:lm margin=1.
+:p.
+Use this choice to refresh the contents of the breakpoints window.
+Due to shortcomings in GDB, :hp2.pmgdb:ehp2. does not always automatically
+update the breakpoints window to reflect changes of the breakpoints.
+For instance, the ignore count is not updated when the debuggee stops.
+
+.************************************************************************
+.* Windows
+.************************************************************************
+:h2 res=&HPM_BRK_WINMENU..Help for Windows
+:i2 refid='brk'.Windows menu
+:i1 id='brk.win'.Windows menu choices (breakpoints window)
+:lm margin=1.
+:p.
+The Windows menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_WIN_CMD..Command:elink.
+:pd.Show the command window.
+:pt.:link reftype=hd res=&HPM_WIN_SRCS..Source files:elink.
+:pd.Show the source files window.
+:pt.:link reftype=hd res=&HPM_WIN_DSP..Display:elink.
+:pd.Show the display window.
+:pt.:link reftype=hd res=&HPM_WIN_THR..Threads:elink.
+:pd.Show the threads window.
+:pt.:link reftype=hd res=&HPM_WIN_REG..Register:elink.
+:pd.Show the register window.
+:eparml.
+
+.************************************************************************
+.* Help
+.************************************************************************
+:h2 res=&HPM_BRK_HELPMENU..Help for Help
+:i2 refid='brk'.Help menu
+:i1 id='brk.help'.Help menu choices
+:lm margin=1.
+:p.
+The Help menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_HELP_HELP..Help for help:elink.
+:pd.Display help for help.
+:pt.:link reftype=hd res=&HPM_HELP_EXT..Extended help:elink.
+:pd.Display extended help.
+:pt.:link reftype=hd res=&HPM_HELP_KEYS..Keys help:elink.
+:pd.Display help about keys.
+:pt.:link reftype=hd res=&HPM_HELP_INDEX..Help index:elink.
+:pd.Display the help index.
+:pt.:link reftype=hd res=&HPM_HELP_CONTENTS..Help index:elink.
+:pd.Display the help contents.
+:eparml.
+
+.************************************************************************
+.* Keys help (breakpoints window)
+.************************************************************************
+:h1 res=&HELP_BRK_KEYS..Keys help (breakpoints window)
+:i1 id='brk.keys'.Keys (breakpoints window)
+:lm margin=1.
+:p.
+You can use the following keys in the breakpoints window&colon.
+:dl tsize=20 compact.
+:edl.
+:p.
+Accelerator keys are missed out in the list above.
+
+.************************************************************************
+.* Display window
+.************************************************************************
+:h1 res=&HELP_DSP_WINDOW..Help for display window
+:i1 id='dsp'.pmgdb display window
+:lm margin=1.
+:p.
+The display window of :hp2.pmgdb:ehp2. shows all the displays.
+For each display, the following values are displayed&colon.
+:dl tsize=12 compact.
+:dt.No:dd.The number of the display as maintained by GDB.  Modifying
+a display may change its number
+:dt.Ena:dd.y if the display is enabled, n if the display is disabled
+:dt.Fmt:dd.Format to be used for displaying the value
+:dt.Expr:dd.Expression to be evaluated
+:dt.Value:dd.Value of the expression (if the display is enabled)
+:edl.
+:p.
+You can toggle the enabled state of a display by double clicking
+with the first mouse button on the value in the `Ena' column.  You can
+modify a display by double clicking on the value
+in the `Fmt' or `Expr' column.
+Closing the display window doesn't terminate :hp2.pmgdb:ehp2..
+:p.
+Help is available on the following topics&colon.
+:p.
+:ul.
+:li.:link reftype=hd res=&HPM_DSP_FILEMENU..File menu:elink.
+:li.:link reftype=hd res=&HPM_DSP_EDITMENU..Edit menu:elink.
+:li.:link reftype=hd res=&HPM_DSP_WINMENU..Windows menu:elink.
+:li.:link reftype=hd res=&HPM_DSP_HELPMENU..Help menu:elink.
+:li.:link reftype=hd res=&HELP_DSP_KEYS..Keys in the display window:elink.
+:eul.
+
+.************************************************************************
+.* File
+.************************************************************************
+:h2 res=&HPM_DSP_FILEMENU..Help for File
+:i2 refid='dsp'.File menu
+:i1 id='dsp.file'.File menu choices (display window)
+:lm margin=1.
+:p.
+The File menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_EXIT..Exit:elink.
+:pd.Terminate :hp2.pmgdb:ehp2..
+:eparml.
+
+.************************************************************************
+.* Edit
+.************************************************************************
+:h2 res=&HPM_DSP_EDITMENU..Help for Edit
+:i2 refid='dsp'.Edit menu
+:i1 id='dsp.edit'.Edit menu choices (display window)
+:lm margin=1.
+:p.
+The Edit menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_DSP_ADD..Add:elink.
+:pd.Add a display.
+:pt.:link reftype=hd res=&HPM_DSP_MODIFY..Modify:elink.
+:pd.Modify the selected display.
+:pt.:link reftype=hd res=&HPM_DSP_ENABLE..Enable:elink.
+:pd.Enable the selected display.
+:pt.:link reftype=hd res=&HPM_DSP_DISABLE..Disable:elink.
+:pd.Disable the selected display.
+:pt.:link reftype=hd res=&HPM_DSP_FORMAT..Format:elink.
+:pd.Change format for selected display.
+:pt.:link reftype=hd res=&HPM_DSP_DELETE..Delete:elink.
+:pd.Delete the selected display.
+:pt.:link reftype=hd res=&HPM_DSP_DEREFERENCE..Dereference:elink.
+:pd.Display the value pointed to by a pointer.
+:pt.:link reftype=hd res=&HPM_DSP_ENABLE_ALL..Enable all:elink.
+:pd.Enable all displays.
+:pt.:link reftype=hd res=&HPM_DSP_DISABLE_ALL..Disable all:elink.
+:pd.Disable all displays.
+:pt.:link reftype=hd res=&HPM_DSP_DELETE_ALL..Delete all:elink.
+:pd.Delete all displays.
+:eparml.
+
+.************************************************************************
+.* Add
+.************************************************************************
+:h3 res=&HPM_DSP_ADD..Help for Add
+:i2 refid='dsp.dsp'.Add
+:i2 refid='pmgdb'.Add display
+:lm margin=1.
+:p.
+Use this choice to add a display.  This choice opens the
+:link reftype=hd res=&HPD_DISPLAY..Display:elink. dialog box.
+You can also double click with the first mouse button on a variable
+in a source window to add it to the display window.
+
+.************************************************************************
+.* Modify
+.************************************************************************
+:h3 res=&HPM_DSP_MODIFY..Help for Modify
+:i2 refid='dsp.edit'.Modify
+:i2 refid='pmgdb'.Modify display
+:lm margin=1.
+:p.
+Use this choice to modify the selected display.  This choice opens the
+:link reftype=hd res=&HPD_DISPLAY..Display:elink. dialog box.  Click with the
+first mouse button select a display.
+
+.************************************************************************
+.* Enable
+.************************************************************************
+:h3 res=&HPM_DSP_ENABLE..Help for Enable
+:i2 refid='dsp.edit'.Enable
+:i2 refid='pmgdb'.Enable display
+:lm margin=1.
+:p.
+Use this choice to enable the selected display.  Click with the
+first mouse button select a display.
+
+.************************************************************************
+.* Disable
+.************************************************************************
+:h3 res=&HPM_DSP_DISABLE..Help for Disable
+:i2 refid='dsp.edit'.Disable
+:i2 refid='pmgdb'.Disable display
+:lm margin=1.
+:p.
+Use this choice to disable the selected display.  Click with the
+first mouse button select a display.
+
+.************************************************************************
+.* Format
+.************************************************************************
+:h3 res=&HPM_DSP_FORMAT..Help for Format
+:i2 refid='dsp.edit'.Format
+:i2 refid='pmgdb'.Format
+:lm margin=1.
+:p.
+Use this choice to change the format of the selected display.  Click with the
+first mouse button select a display.
+
+.************************************************************************
+.* Delete
+.************************************************************************
+:h3 res=&HPM_DSP_DELETE..Help for Delete
+:i2 refid='dsp.edit'.Delete
+:i2 refid='pmgdb'.Delete display
+:lm margin=1.
+:p.
+Use this choice to delete the selected display.  Click with the
+first mouse button select a display.
+
+.************************************************************************
+.* Dereference
+.************************************************************************
+:h3 res=&HPM_DSP_DEREFERENCE..Help for Dereference
+:i2 refid='dsp.edit'.Dereference
+:i2 refid='pmgdb'.Dereference
+:lm margin=1.
+:p.
+Use this choice to replace the selected display with one which shows
+the object pointed to by the display's value.  This can be done only
+if the selected display shows a pointer.  Click with the first mouse
+button select a display.
+:note.The value is dereferenced in the current context, not in the
+context which was active when the display was created.
+
+.************************************************************************
+.* Enable all
+.************************************************************************
+:h3 res=&HPM_DSP_ENABLE_ALL..Help for Enable all
+:i2 refid='dsp.edit'.Enable all
+:i2 refid='pmgdb'.Enable all
+:lm margin=1.
+:p.
+Use this choice to enable all displays.
+
+.************************************************************************
+.* Disable all
+.************************************************************************
+:h3 res=&HPM_DSP_DISABLE_ALL..Help for Disable all
+:i2 refid='dsp.edit'.Disable all
+:i2 refid='pmgdb'.Disable all
+:lm margin=1.
+:p.
+Use this choice to disable all displays.
+
+.************************************************************************
+.* Delete all
+.************************************************************************
+:h3 res=&HPM_DSP_DELETE_ALL..Help for Delete all
+:i2 refid='dsp.edit'.Delete all
+:i2 refid='pmgdb'.Delete all
+:lm margin=1.
+:p.
+Use this choice to delete all displays.
+
+.************************************************************************
+.* Windows
+.************************************************************************
+:h2 res=&HPM_DSP_WINMENU..Help for Windows
+:i2 refid='dsp'.Windows menu
+:i1 id='dsp.win'.Windows menu choices (display window)
+:lm margin=1.
+:p.
+The Windows menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_WIN_CMD..Command:elink.
+:pd.Show the command window.
+:pt.:link reftype=hd res=&HPM_WIN_SRCS..Source files:elink.
+:pd.Show the source files window.
+:pt.:link reftype=hd res=&HPM_WIN_BRK..Breakpoints:elink.
+:pd.Show the breakpoints window.
+:pt.:link reftype=hd res=&HPM_WIN_THR..Threads:elink.
+:pd.Show the threads window.
+:pt.:link reftype=hd res=&HPM_WIN_REG..Register:elink.
+:pd.Show the register window.
+:eparml.
+
+.************************************************************************
+.* Help
+.************************************************************************
+:h2 res=&HPM_DSP_HELPMENU..Help for Help
+:i2 refid='dsp'.Help menu
+:i1 id='dsp.help'.Help menu choices
+:lm margin=1.
+:p.
+The Help menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_HELP_HELP..Help for help:elink.
+:pd.Display help for help.
+:pt.:link reftype=hd res=&HPM_HELP_EXT..Extended help:elink.
+:pd.Display extended help.
+:pt.:link reftype=hd res=&HPM_HELP_KEYS..Keys help:elink.
+:pd.Display help about keys.
+:pt.:link reftype=hd res=&HPM_HELP_INDEX..Help index:elink.
+:pd.Display the help index.
+:pt.:link reftype=hd res=&HPM_HELP_CONTENTS..Help index:elink.
+:pd.Display the help contents.
+:eparml.
+
+.************************************************************************
+.* Keys help (display window)
+.************************************************************************
+:h1 res=&HELP_DSP_KEYS..Keys help (display window)
+:i1 id='dsp.keys'.Keys (display window)
+:lm margin=1.
+:p.
+You can use the following keys in the display window&colon.
+:dl tsize=20 compact.
+:edl.
+:p.
+Accelerator keys are missed out in the list above.
+
+.************************************************************************
+.* Threads window
+.************************************************************************
+:h1 res=&HELP_THR_WINDOW..Help for threads window
+:i1 id='thr'.pmgdb threads window
+:lm margin=1.
+:p.
+The threads window of :hp2.pmgdb:ehp2. shows all threads.
+For each thread, the following values are displayed&colon.
+:dl tsize=12 compact.
+:dt.TID:dd.The thread ID
+:dt.Ena:dd.y if the thread is enabled, n if the thread is disabled
+:edl.
+:p.
+You can toggle the enabled state of a thread by double clicking
+with the first mouse button on the value in the `Ena' column.
+Closing the threads window doesn't terminate :hp2.pmgdb:ehp2..
+:p.
+Help is available on the following topics&colon.
+:p.
+:ul.
+:li.:link reftype=hd res=&HPM_THR_FILEMENU..File menu:elink.
+:li.:link reftype=hd res=&HPM_THR_EDITMENU..Edit menu:elink.
+:li.:link reftype=hd res=&HPM_THR_WINMENU..Windows menu:elink.
+:li.:link reftype=hd res=&HELP_THR_KEYS..Keys in the threads window:elink.
+:eul.
+
+.************************************************************************
+.* File
+.************************************************************************
+:h2 res=&HPM_THR_FILEMENU..Help for File
+:i2 refid='thr'.File menu
+:i1 id='thr.file'.File menu choices (threads window)
+:lm margin=1.
+:p.
+The File menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_EXIT..Exit:elink.
+:pd.Terminate :hp2.pmgdb:ehp2..
+:eparml.
+
+.************************************************************************
+.* Edit
+.************************************************************************
+:h2 res=&HPM_THR_EDITMENU..Help for Edit
+:i2 refid='thr'.Edit menu
+:i1 id='thr.edit'.Edit menu choices (threads window)
+:lm margin=1.
+:p.
+The Edit menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_THR_ENABLE..Enable (thaw):elink.
+:pd.Enable (thaw) the selected thread.
+:pt.:link reftype=hd res=&HPM_THR_DISABLE..Disable (freeze):elink.
+:pd.Disable (freeze) the selected thread.
+:pt.:link reftype=hd res=&HPM_THR_SWITCH..Switch to:elink.
+:pd.Switch to the selected thread.
+:eparml.
+
+.************************************************************************
+.* Enable
+.************************************************************************
+:h3 res=&HPM_THR_ENABLE..Help for Enable
+:i2 refid='thr.edit'.Enable
+:i2 refid='pmgdb'.Enable thread
+:lm margin=1.
+:p.
+Use this choice to enable the selected thread.  Click with the
+first mouse button select a thread.
+
+.************************************************************************
+.* Disable
+.************************************************************************
+:h3 res=&HPM_THR_DISABLE..Help for Disable
+:i2 refid='thr.edit'.Disable
+:i2 refid='pmgdb'.Disable thread
+:lm margin=1.
+:p.
+Use this choice to disable the selected thread.  Click with the
+first mouse button select a thread.
+
+.************************************************************************
+.* Switch to
+.************************************************************************
+:h3 res=&HPM_THR_SWITCH..Help for Switch to
+:i2 refid='thr.edit'.Switch to
+:i2 refid='pmgdb'.Switch to thread
+:lm margin=1.
+:p.
+Use this choice to switch to the selected thread.  Click with the
+first mouse button select a thread.  You can also switch to a thread
+by double clicking on the thread ID (TID).
+
+.************************************************************************
+.* Windows
+.************************************************************************
+:h2 res=&HPM_THR_WINMENU..Help for Windows
+:i2 refid='thr'.Windows menu
+:i1 id='thr.win'.Windows menu choices (threads window)
+:lm margin=1.
+:p.
+The Windows menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_WIN_CMD..Command:elink.
+:pd.Show the command window.
+:pt.:link reftype=hd res=&HPM_WIN_SRCS..Source files:elink.
+:pd.Show the source files window.
+:pt.:link reftype=hd res=&HPM_WIN_BRK..Breakpoints:elink.
+:pd.Show the breakpoints window.
+:pt.:link reftype=hd res=&HPM_WIN_DSP..Display:elink.
+:pd.Show the display window.
+:pt.:link reftype=hd res=&HPM_WIN_REG..Register:elink.
+:pd.Show the register window.
+:eparml.
+
+.************************************************************************
+.* Keys help (threads window)
+.************************************************************************
+:h1 res=&HELP_THR_KEYS..Keys help (threads window)
+:i1 id='thr.keys'.Keys (threads window)
+:lm margin=1.
+:p.
+You can use the following keys in the threads window&colon.
+:dl tsize=20 compact.
+:edl.
+:p.
+Accelerator keys are missed out in the list above.
+
+.************************************************************************
+.* Register window
+.************************************************************************
+:h1 res=&HELP_REG_WINDOW..Help for register window
+:i1 id='reg'.pmgdb register window
+:lm margin=1.
+:p.
+The register window of :hp2.pmgdb:ehp2. shows the values of the
+CPU registers. Closing the register window doesn't terminate
+:hp2.pmgdb:ehp2..
+:p.
+Help is available on the following topics&colon.
+:p.
+:ul.
+:li.:link reftype=hd res=&HPM_REG_FILEMENU..File menu:elink.
+:li.:link reftype=hd res=&HPM_REG_VIEWMENU..View menu:elink.
+:li.:link reftype=hd res=&HPM_REG_WINMENU..Windows menu:elink.
+:li.:link reftype=hd res=&HELP_REG_KEYS..Keys in the register window:elink.
+:eul.
+
+.************************************************************************
+.* File
+.************************************************************************
+:h2 res=&HPM_REG_FILEMENU..Help for File
+:i2 refid='reg'.File menu
+:i1 id='reg.file'.File menu choices (register window)
+:lm margin=1.
+:p.
+The File menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_EXIT..Exit:elink.
+:pd.Terminate :hp2.pmgdb:ehp2..
+:eparml.
+
+.************************************************************************
+.* View
+.************************************************************************
+:h2 res=&HPM_REG_VIEWMENU..Help for View
+:i2 refid='reg'.View menu
+:i1 id='reg.view'.View menu choices (register window)
+:lm margin=1.
+:p.
+The View menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_REG_REFRESH..Refresh:elink.
+:pd.Refresh the window contents.
+:eparml.
+
+.************************************************************************
+.* Refresh
+.************************************************************************
+:h3 res=&HPM_REG_REFRESH..Help for Refresh
+:i2 refid='reg.view'.Refresh
+:i2 refid='pmgdb'.Refresh (register window)
+:lm margin=1.
+:p.
+Use this choice to refresh the contents of the register window.
+:hp2.pmgdb:ehp2. does not automatically update the register window
+to reflect modifications of the register values done with GDB commands.
+
+.************************************************************************
+.* Windows
+.************************************************************************
+:h2 res=&HPM_REG_WINMENU..Help for Windows
+:i2 refid='reg'.Windows menu
+:i1 id='reg.win'.Windows menu choices (register window)
+:lm margin=1.
+:p.
+The Windows menu contains the following choices&colon.
+:parml compact.
+:pt.:link reftype=hd res=&HPM_WIN_CMD..Command:elink.
+:pd.Show the command window.
+:pt.:link reftype=hd res=&HPM_WIN_SRCS..Source files:elink.
+:pd.Show the source files window.
+:pt.:link reftype=hd res=&HPM_WIN_BRK..Breakpoints:elink.
+:pd.Show the breakpoints window.
+:pt.:link reftype=hd res=&HPM_WIN_DSP..Display:elink.
+:pd.Show the display window.
+:pt.:link reftype=hd res=&HPM_WIN_THR..Threads:elink.
+:pd.Show the threads window.
+:eparml.
+
+.************************************************************************
+.* Keys help (register window)
+.************************************************************************
+:h1 res=&HELP_REG_KEYS..Keys help (register window)
+:i1 id='reg.keys'.Keys (register window)
+:lm margin=1.
+:p.
+You can use the following keys in the register window&colon.
+:dl tsize=20 compact.
+:edl.
+:p.
+Accelerator keys are missed out in the list above.
+
+.************************************************************************
+.* PM debugging mode
+.************************************************************************
+:h1 res=&HPD_PMDEBUGMODE..Help for PM debugging mode dialog box
+:i2 refid='pmgdb'.PM debugging mode dialog box
+:lm margin=1.
+:p.
+Select the :hp8.Synchronous mode:ehp8. checkbox to enable
+Synchronous mode.  Synchronous mode is required for debugging PM
+applications and must be selected before starting a PM application,
+otherwise the Presentation Manager will hang, requiring a reboot to
+recover.  In Synchronous mode, only windows of :hp2.pmgdb:ehp2. and
+of the program being debugged can be made active; all other windows
+cannot be used.  :hp2.pmgdb:ehp2. attempts to set Synchronous mode
+automatically when a PM program is loaded.
+
+.************************************************************************
+.* Line breakpoint
+.************************************************************************
+:h1 res=&HPD_BRKPT_LINE..Help for Line Breakpoint dialog box
+:i2 refid='pmgdb'.Line Breakpoint dialog box
+:lm margin=1.
+:p.
+This dialog box is used for adding or modifying a line breakpoint.
+A line breakpoint is a breakpoint in a source line of the program.
+:p.
+Enter the name of the source file and the line number in that source file
+in the :hp8.Source file:ehp8. and :hp8.Line:ehp8. fields, respectively.
+:p.
+A non-zero :hp8.Ignore count:ehp8. causes the breakpoint to not stop
+the program until it has been reached this many times.  If this
+field is empty or contains zero, the program is stopped the first time
+it reaches the breakpoint.  Each time a breakpoint is reached, the ignore
+count is decremented by one (unless it's already zero); if the ignore
+count becomes zero (or was zero before), the breakpoint stops the program.
+:p.
+You can enter an expression in the :hp8.Condition:ehp8. field; that
+expression will be evaluated each time the breakpoint is hit (unless
+its ignore count is still non-zero); if it evaluates to false, the
+breakpoint is ignored.  That is, the breakpoint stops the program only
+if the expression evaluates to true at the time the breakpoint is hit.
+See the :hp2.GDB:ehp2. manual for details on expressions.
+:p.
+Breakpoints can be disabled by unchecking the :hp8.Enable:ehp8.
+checkbox.  Disabled breakpoints are ignored.  Instead of deleting
+breakpoints which you may need again later, you should disable them.
+:p.
+In the :hp8.Disposition:ehp8. field, you can select what to do with a
+breakpoint when it stops the program&colon.
+:dl tsize=20 compact.
+:dt.&tt.del&ett.:dd.delete the breakpoint
+:dt.&tt.dis&ett.:dd.disable the breakpoint
+:dt.&tt.keep&ett.:dd.keep the breakpoint (default)
+:edl.
+:p.
+This can be used to define temporary breakpoints.
+
+.************************************************************************
+.* Startup
+.************************************************************************
+:h1 res=&HPD_STARTUP..Help for Startup dialog box
+:i2 refid='pmgdb'.Startup dialog box
+:lm margin=1.
+:p.
+This dialog box is used for setting startup options.
+You can enter command line arguments for the debuggee
+in the :hp8.Arguments:ehp8. field.
+:p.
+By default, the VIO window of the debuggee stays open after termination
+of the debuggee, so that you can view the debuggee's output.  You
+have to close that window manually.  If :hp8.Close window after exit:ehp8.
+is checked, the VIO window will be closed automatically on termination
+of the debuggee.
+:p.
+Use the :hp8.OK:ehp8. button to accept the settings, use the
+:hp8.Run:ehp8. button to accept the settings and start the program.
+If no breakpoints are set (or all breakpoints are disabled), a
+breakpoint will be set on &tt.main&ett. if the :hp8.Run:ehp8. button
+is selected.
+
+.************************************************************************
+.* Display
+.************************************************************************
+:h1 res=&HPD_DISPLAY..Help for Display dialog box
+:i2 refid='pmgdb'.Display dialog box
+:lm margin=1.
+:p.
+This dialog box is used to add or modify a display.
+:p.
+Enter the expression to be displayed in the :hp8.Expression:ehp8.
+field.  See the :hp2.GDB:ehp2. manual for details on expressions.
+:p.
+Select a display format in the :hp8.Format:ehp8. field.
+:p.
+For some formats, the number of items to be displayed can be entered
+in the :hp8.Count:ehp8. field.
+:p.
+Displays can be disabled by unchecking the :hp8.Enable:ehp8.
+checkbox.  The values of disabled displays are not displayed.
+Instead of deleting displays which you may need again later, you should
+disable them.
+
+.************************************************************************
+.* Go to line
+.************************************************************************
+:h1 res=&HPD_GOTO..Help for Go to line dialog box
+:i2 refid='pmgdb'.Go to line dialog box
+:lm margin=1.
+:p.
+Enter a line number in the :hp8.Line:ehp8. field.
+
+.************************************************************************
+.* Find
+.************************************************************************
+:h1 res=&HPD_FIND..Help for Find dialog box
+:i2 refid='pmgdb'.Find dialog box
+:lm margin=1.
+:p.
+Enter the regular expression to be searched for in the :hp8.Regexp:ehp8.
+field.
+
+.************************************************************************
+.* History
+.************************************************************************
+:h1 res=&HPD_HISTORY..Help for History dialog box
+:i2 refid='pmgdb'.History dialog box
+:lm margin=1.
+:p.
+In this dialog box, you can select and/or edit one of the commands
+previously entered.
+
+.************************************************************************
+.* Tutorial
+.************************************************************************
+:h1 res=&HELP_TUTORIAL..pmgdb tutorial
+:i2 refid='pmgdb'.Tutorial
+:i1 id='tut'.Tutorial
+:lm margin=1.
+:p.
+:ol.
+:li.If not already done, compile the &tt.sieve&ett. sample program
+for debugging&colon.
+:cgraphic.
+cd \emx\samples
+gcc -g sieve.c:ecgraphic.
+:li.Start :hp2.pmgdb:ehp2. in the directory containing the source code
+of the program to debug (debuggee).  Specify the program and its command
+line arguments on the command line of :hp2.pmgdb:ehp2.&colon.
+:cgraphic.
+cd \emx\samples
+pmgdb sieve 100
+:ecgraphic.
+:p.
+That is, just prepend &tt.pmgdb&ett. to the command line.
+:li.:hp2.pmgdb:ehp2. will come up with two windows&colon.
+the :link reftype=hd res=&HELP_CMD_WINDOW..command window:elink.,
+titled `&tt.pmgdb - sieve&ett.', and the 
+:link reftype=hd res=&HELP_SRCS_WINDOW..Source files window:elink..
+The command window shows :hp2.GDB:ehp2.'s welcome message and the
+:hp2.GDB:ehp2. prompt.  The Source Files window lists all the source
+files of the debuggee.  For this sample session, that's just
+&tt.sieve.c&ett..  The source file which contains the &tt.main&ett.
+function is highlighted (grey background).  You can view a source
+file by double clicking on a file name in the Source files window
+(click on the file name, not on the blank space after the file name).
+However we don't need to do this now.
+:li.Run the program by selecting :link reftype=hd res=&HPM_GO..Go:elink.
+from the :link reftype=hd res=&HPM_CMD_RUNMENU..Run menu:elink..
+Note that the command window shows that a breakpoint has been hit&colon.
+:cgraphic.
+Breakpoint 1, main (argc=2, argv=0x282ffcc) at sieve.c&colon.76
+:ecgraphic.
+:p.
+That breakpoint has been set automatically by :hp2.pmgdb:ehp2..
+Moreover, a
+:link reftype=hd res=&HELP_SRC_WINDOW..Source window:elink.
+has popped up.  The first executable line of the &tt.main&ett. function
+has black background.  The line where the debuggee has been stopped
+is marked this way.  Moreover, the line number has a red background; this
+means that a breakpoint is set on that line.
+:li.Now let's set a breakpoint on the &tt.isqrt&ett. function.
+Either type
+:cgraphic.
+b isqrt
+:ecgraphic.
+:p.
+in the command window or double click on the line number of line 45
+(the first executable line of the function).
+Let the program continue execution.  (Remember?  Go...)
+:li.While stepping through &tt.isqrt&ett. we want to watch the
+values of the variables &tt.l&ett., &tt.r&ett., and &tt.x&ett.
+in :hp2.pmgdb:ehp2.'s
+:link reftype=hd res=&HELP_DSP_WINDOW..Display window:elink..
+This is done by double clicking on any instance of &tt.l&ett.,
+&tt.r&ett., and &tt.x&ett. in the source code (:hp2.GDB:ehp2. uses
+dynamic scoping, that is, it uses those variables which are visible at
+the time the display is defined.  Other debuggers use static scoping,
+that is, they use the source code context in which the display
+is defined.)  The Display window should become visible automatically.
+Move and/or resize the windows so that you can see both the Display
+window and the source window.  The two most important columns of
+the Display window are :hp8.Expr:ehp8. (the expression being displayed,
+for instance, a variable) and :hp8.Value:ehp8. (the value of the
+expression).  Note that the Display window
+shows garbage for the &tt.l&ett. and &tt.r&ett. variables.  This
+is because these variables have not yet been initialized, so they
+indeed contain garbage.
+:li.Now let's execute some lines of C code (single step).
+There are two operations for stepping lines of source code&colon.
+:link reftype=hd res=&HPM_STEPOVER..Step over:elink.
+and :link reftype=hd res=&HPM_STEPINTO..Step into:elink.,
+both available in the
+:link reftype=hd res=&HPM_CMD_RUNMENU..Run menu:elink..
+The first one does not step into function calls, treating function
+calls as one statement.  The second one does step into function calls.
+As &tt.isqrt&ett. does not call any functions, there's no difference
+between the two here.  Step over five lines of source code by hitting
+the &tt.o&ett. key or &tt.i&ett. key five times while the source window
+has the focus.  Note how the values of &tt.l&ett. and &tt.r&ett. become valid.
+:li.In addition to the three variables, we want to watch the value
+of the expression `&tt.m*m&ett.'.  Select
+:link reftype=hd res=&HPM_DSP_ADD..Add:elink. from the
+:link reftype=hd res=&HPM_SRC_DSPMENU..Display menu:elink.
+and type `&tt.m*m&ett.' in the :hp8.Expression:ehp8. field
+of the dialog box and hit Return or click the :hp8.OK:ehp8. button.
+Note that the expression and its value have been added to the Display
+window.  You can also add displays by using :hp2.GDB:ehp2.'s &tt.display&ett.
+command&colon.
+:cgraphic.
+disp m*m
+:ecgraphic.
+:p.
+Continue stepping some (say, 20) source lines and watch the Display window.
+:li.To let &tt.isqrt&ett. run to its end and stop at the place where
+it has been called, select
+:link reftype=hd res=&HPM_FINISH..Finish:elink. from the
+:link reftype=hd res=&HPM_CMD_RUNMENU..Run menu:elink.
+or hit the &tt.f&ett. key.  The return value is displayed in
+the command window.  Note that the program is stopped in
+the line containing the call to &tt.isqrt&ett., not on the line after.
+This is because there's still some code of that line not yet executed.
+As examining &tt.sqrt_size&ett. shows, the return value of &tt.isqrt&ett.
+has not yet been assigned to that variable.  If you don't want to
+clutter the Display window with values which you want to examine only
+once, use :hp2.GDB:ehp2.'s &tt.print&ett. command in the
+command window&colon.
+:cgraphic.
+p sqrt_size
+:ecgraphic.
+:p.
+Hit the &tt.o&ett. key to execute the rest of the code of that line.
+:li.Now we want to trace through the code of &tt.main&ett. which
+prints the result.  That code starts at line 113.  This time, we
+don't set a breakpoint.  Instead, select line 113 by clicking once
+on the line number of that line.  (You can scroll to an arbitrary line by
+selecting :link reftype=hd res=&HPM_SRC_GOTO..Go to line:elink.
+from the :link reftype=hd res=&HPM_SRC_VIEWMENU..View menu:elink.
+and typing the line number.)  Then, either select
+:link reftype=hd res=&HPM_SRC_UNTIL..Until:elink. from the
+:link reftype=hd res=&HPM_CMD_RUNMENU..Run menu:elink.
+or hit the &tt.u&ett. key.  This operations works by setting
+a temporary breakpoint, which will vanish after completion of
+the operation.  Therefore, the line number does not have a red
+background.  This time, we do not want to step into functions
+(such as &tt.printf&ett.), therefore use the &tt.o&ett. key
+to step over the lines.  If you're tired, hit the &tt.g&ett. key.
+After stepping the last line, :hp2.GDB:ehp2. will say
+:cgraphic.
+Program exited normally.
+:ecgraphic.
+:p.
+in the command window.  Note that the window in which &tt.sieve.exe&ett.
+was running won't go away automatically; the title changed
+to
+:cgraphic.
+Completed&colon. sieve.exe
+:ecgraphic.
+:p.
+and you have to close it manually.  The application window will
+be closed automatically if you select :hp8.Close window after exit:ehp8..
+in the dialog box popped up by selecting 
+:link reftype=hd res=&HPM_CMD_STARTUP..Startup:elink.
+from the :link reftype=hd res=&HPM_CMD_FILEMENU..File menu:elink.
+before starting the program.
+:eol.
+
+:euserdoc.
Index: trunk/src/emx/src/pmgdb/pmgdb.rc
===================================================================
--- trunk/src/emx/src/pmgdb/pmgdb.rc	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmgdb.rc	(revision 18)
@@ -0,0 +1,751 @@
+/* pmgdb.rc
+   Copyright (c) 1996-1998 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <os2.h>
+#include "pmgdb.h"
+#include "help.h"
+
+MENU ID_COMMAND_WINDOW
+BEGIN
+    SUBMENU "~File",                       IDM_FILEMENU
+    BEGIN
+        MENUITEM "Open ~program file...",  IDM_OPEN_EXEC
+        MENUITEM "Open ~core file...",     IDM_OPEN_CORE
+        MENUITEM "Open ~source file...",   IDM_OPEN_SOURCE
+        MENUITEM "S~tartup...",            IDM_STARTUP
+        MENUITEM "~Restart",               IDM_RESTART
+        MENUITEM "~Where",                 IDM_WHERE
+        MENUITEM "E~xit\tF3",              IDM_EXIT
+    END
+    SUBMENU "~Edit",                       IDM_EDITMENU
+    BEGIN
+        MENUITEM "~Complete\tTab",         IDM_COMPLETE
+        MENUITEM "~History...\tLeft",      IDM_HISTORY
+    END
+    SUBMENU "~Run",                        IDM_RUNMENU, , MIA_DISABLED
+    BEGIN
+        MENUITEM "~Go\tCtrl+G",            IDM_GO
+        MENUITEM "Step ~over\tCtrl+O",     IDM_STEPOVER
+        MENUITEM "Step ~into\tCtrl+I",     IDM_STEPINTO
+        MENUITEM "~Finish\tCtrl+F",        IDM_FINISH
+        MENUITEM SEPARATOR
+        MENUITEM "Insn step over",         IDM_ISTEPOVER
+        MENUITEM "Insn step into",         IDM_ISTEPINTO
+    END
+    SUBMENU "~Breakpoints",                IDM_BRKPTMENU
+    BEGIN
+        MENUITEM "On ~line...",            IDM_BRKPT_LINE
+        MENUITEM SEPARATOR
+        MENUITEM "L~ist",                  IDM_BRKPT_LIST
+    END
+    SUBMENU "~Options",                    IDM_OPTIONSMENU
+    BEGIN
+        MENUITEM "~PM debugging mode...",  IDM_PMDEBUGMODE
+        MENUITEM "~Annotate",              IDM_ANNOTATE
+        MENUITEM "~Font...",               IDM_FONT
+    END
+    SUBMENU "~Windows",                    IDM_WINMENU
+    BEGIN
+        MENUITEM "~Source files",          IDM_WIN_SRCS
+        MENUITEM "~Breakpoints",           IDM_WIN_BRK
+        MENUITEM "~Display",               IDM_WIN_DSP
+        MENUITEM "~Threads",               IDM_WIN_THR
+        MENUITEM "~Register",              IDM_WIN_REG
+    END
+    SUBMENU "~Help",                       IDM_HELPMENU
+    BEGIN
+        MENUITEM "~Help for help",         IDM_HELP_HELP
+        MENUITEM "~Extended help",         IDM_HELP_EXT, MIS_HELP
+        MENUITEM "~Keys help",             IDM_HELP_KEYS,
+        MENUITEM "Help ~index",            IDM_HELP_INDEX
+        MENUITEM "Help ~contents",         IDM_HELP_CONTENTS
+        MENUITEM SEPARATOR
+        MENUITEM "~Tutorial",              IDM_TUTORIAL
+        MENUITEM SEPARATOR
+        MENUITEM "~About...",              IDM_ABOUT
+    END
+END
+
+ACCELTABLE ID_COMMAND_WINDOW
+BEGIN
+  VK_F3,   IDM_EXIT,      VIRTUALKEY
+  VK_TAB,  IDM_COMPLETE,  VIRTUALKEY
+  VK_LEFT, IDM_HISTORY,   VIRTUALKEY
+  "f",     IDM_FINISH,    CHAR, CONTROL
+  "g",     IDM_GO,        CHAR, CONTROL
+  "i",     IDM_STEPINTO,  CHAR, CONTROL
+  "o",     IDM_STEPOVER,  CHAR, CONTROL
+END
+
+
+MENU ID_SOURCE_WINDOW
+BEGIN
+    SUBMENU "~File",                       IDM_FILEMENU
+    BEGIN
+        MENUITEM "~Open source file...",   IDM_OPEN_SOURCE
+        MENUITEM "~Restart",               IDM_RESTART
+        MENUITEM "~Where",                 IDM_WHERE
+        MENUITEM "E~xit\tF3",              IDM_EXIT
+    END
+    SUBMENU "~View",                       IDM_VIEWMENU
+    BEGIN
+        MENUITEM "~Find...\tCtrl+F",       IDM_FIND
+        MENUITEM "Find ~next\tCtrl+N",     IDM_FINDNEXT
+        MENUITEM "Find ~previous\tCtrl+P", IDM_FINDPREV
+        MENUITEM SEPARATOR
+        MENUITEM "~Go to line...",         IDM_GOTO
+    END
+    SUBMENU "~Run",                        IDM_RUNMENU, , MIA_DISABLED
+    BEGIN
+        MENUITEM "~Go\tG",                 IDM_GO
+        MENUITEM "Step ~over\tO",          IDM_STEPOVER
+        MENUITEM "Step ~into\tI",          IDM_STEPINTO
+        MENUITEM "~Finish\tF",             IDM_FINISH
+        MENUITEM "~Until\tU",              IDM_UNTIL
+        MENUITEM "~Jump\tJ",               IDM_JUMP
+        MENUITEM SEPARATOR
+        MENUITEM "Insn step over",         IDM_ISTEPOVER
+        MENUITEM "Insn step into",         IDM_ISTEPINTO
+    END
+    SUBMENU "~Breakpoints",                IDM_BRKPTMENU
+    BEGIN
+        MENUITEM "On ~line...",            IDM_BRKPT_LINE
+        MENUITEM SEPARATOR
+        MENUITEM "L~ist",                  IDM_BRKPT_LIST
+    END
+    SUBMENU "~Display",                    IDM_DSPMENU
+    BEGIN
+        MENUITEM "Add...\tCtrl+D",         IDM_DSP_ADD
+        MENUITEM SEPARATOR
+        MENUITEM "~Show",                  IDM_DSP_SHOW
+    END
+    SUBMENU "~Options",                    IDM_OPTIONSMENU
+    BEGIN
+        MENUITEM "~PM debugging mode...",  IDM_PMDEBUGMODE
+    END
+    SUBMENU "~Windows",                    IDM_WINMENU
+    BEGIN
+        MENUITEM "~Command",               IDM_WIN_CMD
+        MENUITEM "~Source files",          IDM_WIN_SRCS
+        MENUITEM "~Breakpoints",           IDM_WIN_BRK
+        MENUITEM "~Display",               IDM_WIN_DSP
+        MENUITEM "~Threads",               IDM_WIN_THR
+        MENUITEM "~Register",              IDM_WIN_REG
+    END
+    SUBMENU "~Help",                       IDM_HELPMENU
+    BEGIN
+        MENUITEM "~Help for help",         IDM_HELP_HELP
+        MENUITEM "~Extended help",         IDM_HELP_EXT, MIS_HELP
+        MENUITEM "~Keys help",             IDM_HELP_KEYS,
+        MENUITEM "Help ~index",            IDM_HELP_INDEX
+        MENUITEM "Help ~contents",         IDM_HELP_CONTENTS
+    END
+END
+
+
+ACCELTABLE ID_SOURCE_WINDOW
+BEGIN
+  VK_F3,  IDM_EXIT,      VIRTUALKEY
+  "f",    IDM_FINISH,    CHAR
+  "g",    IDM_GO,        CHAR
+  "i",    IDM_STEPINTO,  CHAR
+  "j",    IDM_JUMP,      CHAR
+  "o",    IDM_STEPOVER,  CHAR
+  "u",    IDM_UNTIL,     CHAR
+  "d",    IDM_DSP_ADD,   CHAR, CONTROL
+  "f",    IDM_FIND,      CHAR, CONTROL  /* TODO: IDM_FIND vs. IDM_FINISH */
+  "g",    IDM_GO,        CHAR, CONTROL
+  "i",    IDM_STEPINTO,  CHAR, CONTROL
+  "n",    IDM_FINDNEXT,  CHAR, CONTROL
+  "o",    IDM_STEPOVER,  CHAR, CONTROL
+  "p",    IDM_FINDPREV,  CHAR, CONTROL
+END
+
+
+MENU ID_BREAKPOINTS_WINDOW
+BEGIN
+    SUBMENU "~File",                       IDM_FILEMENU
+    BEGIN
+        MENUITEM "E~xit\tF3",              IDM_EXIT
+    END
+    SUBMENU "~Edit",                       IDM_EDITMENU
+    BEGIN
+        MENUITEM "~Modify...",             IDM_MODIFY
+        MENUITEM "~Enable",                IDM_ENABLE
+        MENUITEM "~Disable",               IDM_DISABLE
+        MENUITEM SEPARATOR
+        MENUITEM "De~lete\tDel",           IDM_DELETE
+    END
+    SUBMENU "~Breakpoints",                IDM_BRKPTMENU
+    BEGIN
+        MENUITEM "On ~line...",            IDM_BRKPT_LINE
+        MENUITEM SEPARATOR
+        MENUITEM "~Refresh",               IDM_REFRESH
+    END
+    SUBMENU "~Windows",                    IDM_WINMENU
+    BEGIN
+        MENUITEM "~Command",               IDM_WIN_CMD
+        MENUITEM "~Source files",          IDM_WIN_SRCS
+        MENUITEM "~Display",               IDM_WIN_DSP
+        MENUITEM "~Threads",               IDM_WIN_THR
+        MENUITEM "~Register",              IDM_WIN_REG
+    END
+    SUBMENU "~Help",                       IDM_HELPMENU
+    BEGIN
+        MENUITEM "~Help for help",         IDM_HELP_HELP
+        MENUITEM "~Extended help",         IDM_HELP_EXT, MIS_HELP
+        MENUITEM "~Keys help",             IDM_HELP_KEYS,
+        MENUITEM "Help ~index",            IDM_HELP_INDEX
+        MENUITEM "Help ~contents",         IDM_HELP_CONTENTS
+    END
+END
+
+
+ACCELTABLE ID_BREAKPOINTS_WINDOW
+BEGIN
+  VK_F3,     IDM_EXIT,      VIRTUALKEY
+  VK_DELETE, IDM_DELETE,    VIRTUALKEY
+END
+
+
+MENU ID_DISPLAY_WINDOW
+BEGIN
+    SUBMENU "~File",                       IDM_FILEMENU
+    BEGIN
+        MENUITEM "E~xit\tF3",              IDM_EXIT
+    END
+    SUBMENU "~Edit",                       IDM_EDITMENU
+    BEGIN
+        MENUITEM "~Add...",                IDM_ADD
+        MENUITEM SEPARATOR
+        MENUITEM "~Modify...",             IDM_MODIFY
+        MENUITEM "~Enable",                IDM_ENABLE
+        MENUITEM "~Disable",               IDM_DISABLE
+        SUBMENU "~Format",                 IDM_REPMENU
+        BEGIN                              
+            MENUITEM "~Signed decimal",    IDM_REP_DEC_S
+            MENUITEM "~Unsigned decimal",  IDM_REP_DEC_U
+            MENUITEM "~Hexadecimal",       IDM_REP_HEX
+            MENUITEM "~Octal",             IDM_REP_OCT
+            MENUITEM "~Binary",            IDM_REP_BIN
+            MENUITEM "~Character",         IDM_REP_CHR
+            MENUITEM "~Address",           IDM_REP_ADR
+            MENUITEM "~Floating point",    IDM_REP_FLT
+            MENUITEM "St~ring",            IDM_REP_STR
+            MENUITEM "~Instruction",       IDM_REP_INS
+        END
+        MENUITEM "De~lete\tDel",           IDM_DELETE
+        MENUITEM SEPARATOR
+        MENUITEM "Dereference",            IDM_DEREFERENCE
+        MENUITEM SEPARATOR
+        MENUITEM "Enable all",             IDM_ENABLE_ALL
+        MENUITEM "Disable all",            IDM_DISABLE_ALL
+        MENUITEM "Delete all",             IDM_DELETE_ALL
+    END
+    SUBMENU "~Windows",                    IDM_WINMENU
+    BEGIN
+        MENUITEM "~Command",               IDM_WIN_CMD
+        MENUITEM "~Source files",          IDM_WIN_SRCS
+        MENUITEM "~Breakpoints",           IDM_WIN_BRK
+        MENUITEM "~Threads",               IDM_WIN_THR
+        MENUITEM "~Register",              IDM_WIN_REG
+    END
+    SUBMENU "~Help",                       IDM_HELPMENU
+    BEGIN
+        MENUITEM "~Help for help",         IDM_HELP_HELP
+        MENUITEM "~Extended help",         IDM_HELP_EXT, MIS_HELP
+        MENUITEM "~Keys help",             IDM_HELP_KEYS,
+        MENUITEM "Help ~index",            IDM_HELP_INDEX
+        MENUITEM "Help ~contents",         IDM_HELP_CONTENTS
+    END
+END
+
+
+ACCELTABLE ID_DISPLAY_WINDOW
+BEGIN
+  VK_F3,     IDM_EXIT,      VIRTUALKEY
+  VK_DELETE, IDM_DELETE,    VIRTUALKEY
+END
+
+
+MENU ID_THREADS_WINDOW
+BEGIN
+    SUBMENU "~File",                       IDM_FILEMENU
+    BEGIN
+        MENUITEM "E~xit\tF3",              IDM_EXIT
+    END
+    SUBMENU "~Edit",                       IDM_EDITMENU
+    BEGIN
+        MENUITEM "~Enable (thaw)",         IDM_ENABLE
+        MENUITEM "~Disable (freeze)",      IDM_DISABLE
+        MENUITEM "~Switch to",             IDM_SWITCH
+    END
+    SUBMENU "~Windows",                    IDM_WINMENU
+    BEGIN
+        MENUITEM "~Command",               IDM_WIN_CMD
+        MENUITEM "~Source files",          IDM_WIN_SRCS
+        MENUITEM "~Breakpoints",           IDM_WIN_BRK
+        MENUITEM "~Display",               IDM_WIN_DSP
+        MENUITEM "~Register",              IDM_WIN_REG
+    END
+END
+
+
+ACCELTABLE ID_THREADS_WINDOW
+BEGIN
+  VK_F3,  IDM_EXIT,      VIRTUALKEY
+END
+
+
+MENU ID_SOURCE_FILES_WINDOW
+BEGIN
+    SUBMENU "~File",                       IDM_FILEMENU
+    BEGIN
+        MENUITEM "E~xit\tF3",              IDM_EXIT
+    END
+    SUBMENU "~Windows",                    IDM_WINMENU
+    BEGIN
+        MENUITEM "~Command",               IDM_WIN_CMD
+        MENUITEM "~Breakpoints",           IDM_WIN_BRK
+        MENUITEM "~Display",               IDM_WIN_DSP
+        MENUITEM "~Threads",               IDM_WIN_THR
+        MENUITEM "~Register",              IDM_WIN_REG
+    END
+    SUBMENU "~Help",                       IDM_HELPMENU
+    BEGIN
+        MENUITEM "~Help for help",         IDM_HELP_HELP
+        MENUITEM "~Extended help",         IDM_HELP_EXT, MIS_HELP
+        MENUITEM "~Keys help",             IDM_HELP_KEYS,
+        MENUITEM "Help ~index",            IDM_HELP_INDEX
+        MENUITEM "Help ~contents",         IDM_HELP_CONTENTS
+    END
+END
+
+
+ACCELTABLE ID_SOURCE_FILES_WINDOW
+BEGIN
+  VK_F3,  IDM_EXIT,      VIRTUALKEY
+END
+
+
+MENU ID_REGISTER_WINDOW
+BEGIN
+    SUBMENU "~File",                       IDM_FILEMENU
+    BEGIN
+        MENUITEM "E~xit\tF3",              IDM_EXIT
+    END
+    SUBMENU "~View",                       IDM_VIEWMENU
+    BEGIN
+        MENUITEM "~Refresh",               IDM_REFRESH
+    END
+    SUBMENU "~Windows",                    IDM_WINMENU
+    BEGIN
+        MENUITEM "~Command",               IDM_WIN_CMD
+        MENUITEM "~Source files",          IDM_WIN_SRCS
+        MENUITEM "~Breakpoints",           IDM_WIN_BRK
+        MENUITEM "~Display",               IDM_WIN_DSP
+        MENUITEM "~Threads",               IDM_WIN_THR
+    END
+END
+
+
+ACCELTABLE ID_REGISTER_WINDOW
+BEGIN
+  VK_F3,  IDM_EXIT,      VIRTUALKEY
+END
+
+
+DLGTEMPLATE IDD_PMDEBUGMODE
+BEGIN
+    DIALOG "PM debugging mode", IDD_PMDEBUGMODE, 32, 32, 240, 68, , FCF_TITLEBAR | FCF_SYSMENU
+    BEGIN
+        CONTROL  "~Synchronous mode",    IDC_SYNC,  10,  30, 100, 12, WC_BUTTON, WS_VISIBLE | BS_AUTOCHECKBOX | WS_TABSTOP | WS_GROUP
+        DEFPUSHBUTTON "~OK",               DID_OK,  10,   8,  40, 16, WS_TABSTOP | WS_GROUP
+        CONTROL       "Cancel",        DID_CANCEL,  60,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP
+        CONTROL       "Help",            IDC_HELP, 110,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | BS_HELP | BS_NOPOINTERFOCUS
+    END
+END
+
+
+DLGTEMPLATE IDD_BRKPT_LINE
+BEGIN
+    DIALOG "Line Breakpoint", IDD_BRKPT_LINE, 32, 32, 230, 120, , FCF_TITLEBAR | FCF_SYSMENU
+    BEGIN
+        CONTROL "Location",                     0,   4,  80, 222, 34, WC_STATIC, WS_VISIBLE | SS_GROUPBOX | DT_MNEMONIC
+        CONTROL "~Source file:",                0,  10,  96,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                    IDC_SOURCE,  68,  52,  72, 53, WC_COMBOBOX, WS_VISIBLE | CBS_DROPDOWN | WS_TABSTOP | WS_GROUP
+        CONTROL "~Line:",                       0,  10,  84,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                    IDC_LINENO,  70,  84,  40,  8, WC_ENTRYFIELD, WS_VISIBLE | ES_AUTOSCROLL | ES_MARGIN | WS_TABSTOP | WS_GROUP
+        CONTROL "Options",                      0,   4,  30, 222, 48, WC_STATIC, WS_VISIBLE | SS_GROUPBOX | DT_MNEMONIC
+        CONTROL "~Ignore count:",               0,  10,  60,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                    IDC_IGNORE,  70,  60,  40,  8, WC_ENTRYFIELD, WS_VISIBLE | ES_AUTOSCROLL | ES_MARGIN | WS_TABSTOP | WS_GROUP
+        CONTROL "~Condition:",                  0,  10,  46,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                 IDC_CONDITION,  70,  46, 148,  8, WC_ENTRYFIELD, WS_VISIBLE | ES_AUTOSCROLL | ES_MARGIN | WS_TABSTOP | WS_GROUP
+        CONTROL  "~Enable",            IDC_ENABLE,  10,  32, 100, 12, WC_BUTTON, WS_VISIBLE | BS_AUTOCHECKBOX | WS_TABSTOP | WS_GROUP
+        CONTROL "~Disposition:",                0, 120,  34,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",               IDC_DISPOSITION, 178, -10,  40, 53, WC_COMBOBOX, WS_VISIBLE | CBS_DROPDOWNLIST | WS_TABSTOP | WS_GROUP
+        DEFPUSHBUTTON "~OK",               DID_OK,  10,   8,  40, 16, WS_TABSTOP | WS_GROUP
+        CONTROL       "Cancel",        DID_CANCEL,  60,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP
+        CONTROL       "Help",            IDC_HELP, 110,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | BS_HELP | BS_NOPOINTERFOCUS
+    END
+END
+
+
+DLGTEMPLATE IDD_STARTUP
+BEGIN
+    DIALOG "Startup", IDD_STARTUP, 32, 32, 240, 68, , FCF_TITLEBAR | FCF_SYSMENU
+    BEGIN
+        CONTROL "~Arguments:",                           0,  10,  44,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                               IDC_ARGS,  70,  44, 160,  8, WC_ENTRYFIELD, WS_VISIBLE | ES_AUTOSCROLL | ES_MARGIN | WS_TABSTOP | WS_GROUP
+        CONTROL  "~Close window after exit", IDC_CLOSE_WIN,  10,  30, 200, 12, WC_BUTTON, WS_VISIBLE | BS_AUTOCHECKBOX | WS_TABSTOP | WS_GROUP
+        DEFPUSHBUTTON "~OK",                        DID_OK,  10,   8,  40, 16, WS_TABSTOP | WS_GROUP
+        CONTROL       "~Run",                      IDC_RUN,  60,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP
+        CONTROL       "Cancel",                 DID_CANCEL, 110,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP
+        CONTROL       "Help",                     IDC_HELP, 160,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | BS_HELP | BS_NOPOINTERFOCUS
+    END
+END
+
+
+DLGTEMPLATE IDD_DISPLAY
+BEGIN
+    DIALOG "Display", IDD_DISPLAY, 32, 32, 240, 88, , FCF_TITLEBAR | FCF_SYSMENU
+    BEGIN
+        CONTROL "E~xpression:",                          0,  10,  68,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                               IDC_EXPR,  70,  68, 160,  8, WC_ENTRYFIELD, WS_VISIBLE | ES_AUTOSCROLL | ES_MARGIN | WS_TABSTOP | WS_GROUP
+        CONTROL "~Format:",                              0,  10,  56,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                             IDC_FORMAT,  68,  12,  72, 53, WC_COMBOBOX, WS_VISIBLE | CBS_DROPDOWNLIST | WS_TABSTOP | WS_GROUP
+        CONTROL "~Count:",                               0,  10,  44,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                              IDC_COUNT,  68,  43,  40,  8, WC_SPINBUTTON, WS_VISIBLE | SPBS_MASTER | SPBS_NUMERICONLY | SPBS_JUSTRIGHT | SPBS_FASTSPIN | WS_TABSTOP | WS_GROUP
+        CONTROL  "~Enable",                     IDC_ENABLE,  10,  30, 200, 12, WC_BUTTON, WS_VISIBLE | BS_AUTOCHECKBOX | WS_TABSTOP | WS_GROUP
+        DEFPUSHBUTTON "~OK",                        DID_OK,  10,   8,  40, 16, WS_TABSTOP | WS_GROUP
+        CONTROL       "Cancel",                 DID_CANCEL,  60,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP
+        CONTROL       "Help",                     IDC_HELP, 110,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | BS_HELP | BS_NOPOINTERFOCUS
+    END
+END
+
+
+DLGTEMPLATE IDD_GOTO
+BEGIN
+    DIALOG "Go to line", IDD_GOTO, 32, 32, 240, 56, , FCF_TITLEBAR | FCF_SYSMENU
+    BEGIN
+        CONTROL "~Line:",                       0,  10,  30,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                    IDC_LINENO,  70,  30,  40,  8, WC_ENTRYFIELD, WS_VISIBLE | ES_AUTOSCROLL | ES_MARGIN | WS_TABSTOP | WS_GROUP
+        DEFPUSHBUTTON "~OK",               DID_OK,  10,   8,  40, 16, WS_TABSTOP | WS_GROUP
+        CONTROL       "Cancel",        DID_CANCEL,  60,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP
+        CONTROL       "Help",            IDC_HELP, 110,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | BS_HELP | BS_NOPOINTERFOCUS
+    END
+END
+
+
+DLGTEMPLATE IDD_FIND
+BEGIN
+    DIALOG "Find", IDD_FIND, 32, 32, 240, 56, , FCF_TITLEBAR | FCF_SYSMENU
+    BEGIN
+        CONTROL "~Regexp:",                     0,  10,  30,  60,  8, WC_STATIC, WS_VISIBLE | SS_TEXT | DT_LEFT | DT_MNEMONIC
+        CONTROL "",                    IDC_STRING,  70,  30,  40,  8, WC_ENTRYFIELD, WS_VISIBLE | ES_AUTOSCROLL | ES_MARGIN | WS_TABSTOP | WS_GROUP
+        DEFPUSHBUTTON "~OK",               DID_OK,  10,   8,  40, 16, WS_TABSTOP | WS_GROUP
+        CONTROL       "Cancel",        DID_CANCEL,  60,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP
+        CONTROL       "Help",            IDC_HELP, 110,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | BS_HELP | BS_NOPOINTERFOCUS
+    END
+END
+
+
+DLGTEMPLATE IDD_ABOUT
+BEGIN
+    DIALOG "About pmgdb", IDD_ABOUT, 32, 32, 240, 140, , FCF_TITLEBAR | FCF_SYSMENU
+    BEGIN
+        CTEXT   "pmgdb 0.9d",                                                    0, 10, 116, 220, 8
+        CTEXT   "Copyright (C) 1996-1998"                                        0, 10,  88, 220, 8
+        CTEXT   "by Eberhard Mattes"                                             0, 10,  80, 220, 8
+        LTEXT   "pmgdb comes with ABSOLUTELY NO WARRANTY. For details see file"  0, 10,  60, 220, 8
+        PRESPARAMS PP_FONTNAMESIZE, "8.Helv"
+        LTEXT   "`COPYING' that should have come with this program."             0, 10,  52, 220, 8
+        PRESPARAMS PP_FONTNAMESIZE, "8.Helv"
+        LTEXT   "pmgdb is free software, and you are welcome to redistribute it" 0, 10,  44, 220, 8
+        PRESPARAMS PP_FONTNAMESIZE, "8.Helv"
+        LTEXT   "under certain conditions. See the file `COPYING' for details."  0, 10,  36, 220, 8
+        PRESPARAMS PP_FONTNAMESIZE, "8.Helv"
+        DEFPUSHBUTTON "~OK",               DID_OK,  10,   8,  40, 16, WS_TABSTOP | WS_GROUP
+        CONTROL       "Help",            IDC_HELP,  60,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | BS_HELP | BS_NOPOINTERFOCUS
+    END
+END
+
+
+DLGTEMPLATE IDD_HISTORY
+BEGIN
+    DIALOG "Command history", IDD_HISTORY, 32, 32, 240, 100, , FCF_TITLEBAR | FCF_SYSMENU
+    BEGIN
+        CONTROL "",                      IDC_LIST,  10,  30, 220, 64, WC_COMBOBOX, WS_VISIBLE | CBS_SIMPLE | WS_TABSTOP | WS_GROUP
+        DEFPUSHBUTTON "~OK",               DID_OK,  10,   8,  40, 16, WS_TABSTOP | WS_GROUP
+        CONTROL       "Cancel",        DID_CANCEL,  60,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP
+        CONTROL       "Help",            IDC_HELP, 110,   8,  40, 16, WC_BUTTON, WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | BS_HELP | BS_NOPOINTERFOCUS
+    END
+END
+
+
+HELPSUBTABLE ID_COMMAND_WINDOW
+BEGIN
+  HELPSUBITEM IDM_FILEMENU,     HPM_CMD_FILEMENU
+  HELPSUBITEM IDM_OPEN_EXEC,    HPM_CMD_OPEN_EXEC
+  HELPSUBITEM IDM_OPEN_CORE,    HPM_CMD_OPEN_CORE
+  HELPSUBITEM IDM_OPEN_SOURCE,  HPM_OPEN_SOURCE
+  HELPSUBITEM IDM_STARTUP,      HPM_CMD_STARTUP
+  HELPSUBITEM IDM_RESTART,      HPM_RESTART
+  HELPSUBITEM IDM_WHERE,        HPM_WHERE
+  HELPSUBITEM IDM_EXIT,         HPM_EXIT
+  HELPSUBITEM IDM_EDITMENU,     HPM_CMD_EDITMENU
+  HELPSUBITEM IDM_COMPLETE,     HPM_CMD_COMPLETE
+  HELPSUBITEM IDM_HISTORY,      HPM_CMD_HISTORY
+  HELPSUBITEM IDM_RUNMENU,      HPM_CMD_RUNMENU
+  HELPSUBITEM IDM_GO,           HPM_GO
+  HELPSUBITEM IDM_STEPOVER,     HPM_STEPOVER
+  HELPSUBITEM IDM_STEPINTO,     HPM_STEPINTO
+  HELPSUBITEM IDM_FINISH,       HPM_FINISH
+  HELPSUBITEM IDM_ISTEPOVER,    HPM_ISTEPOVER
+  HELPSUBITEM IDM_ISTEPINTO,    HPM_ISTEPINTO
+  HELPSUBITEM IDM_BRKPTMENU,    HPM_CMD_BRKPTMENU
+  HELPSUBITEM IDM_BRKPT_LINE,   HPM_BRKPT_LINE
+  HELPSUBITEM IDM_BRKPT_LIST,   HPM_BRKPT_LIST
+  HELPSUBITEM IDM_OPTIONSMENU,  HPM_CMD_OPTIONSMENU
+  HELPSUBITEM IDM_PMDEBUGMODE,  HPM_PMDEBUGMODE
+  HELPSUBITEM IDM_ANNOTATE,     HPM_CMD_ANNOTATE
+  HELPSUBITEM IDM_FONT,         HPM_CMD_FONT
+  HELPSUBITEM IDM_WINMENU,      HPM_CMD_WINMENU
+  HELPSUBITEM IDM_WIN_BRK,      HPM_WIN_BRK
+  HELPSUBITEM IDM_WIN_DSP,      HPM_WIN_DSP
+  HELPSUBITEM IDM_WIN_SRCS,     HPM_WIN_SRCS
+  HELPSUBITEM IDM_WIN_THR,      HPM_WIN_THR
+  HELPSUBITEM IDM_WIN_REG,      HPM_WIN_REG
+  HELPSUBITEM IDM_HELPMENU,     HPM_CMD_HELPMENU
+  HELPSUBITEM IDM_HELP_HELP,    HPM_HELP_HELP
+  HELPSUBITEM IDM_HELP_EXT,     HPM_HELP_EXT
+  HELPSUBITEM IDM_HELP_KEYS,    HPM_HELP_KEYS
+  HELPSUBITEM IDM_HELP_INDEX,   HPM_HELP_INDEX
+  HELPSUBITEM IDM_HELP_CONTENTS, HPM_HELP_CONTENTS
+  HELPSUBITEM IDM_ABOUT,        HPM_CMD_ABOUT
+END
+
+HELPSUBTABLE ID_SOURCE_WINDOW
+BEGIN
+  HELPSUBITEM IDM_FILEMENU,     HPM_SRC_FILEMENU
+  HELPSUBITEM IDM_OPEN_SOURCE,  HPM_OPEN_SOURCE
+  HELPSUBITEM IDM_RESTART,      HPM_RESTART
+  HELPSUBITEM IDM_WHERE,        HPM_WHERE
+  HELPSUBITEM IDM_EXIT,         HPM_EXIT
+  HELPSUBITEM IDM_VIEWMENU,     HPM_SRC_VIEWMENU
+  HELPSUBITEM IDM_FIND,         HPM_SRC_FIND
+  HELPSUBITEM IDM_FINDNEXT,     HPM_SRC_FINDNEXT
+  HELPSUBITEM IDM_FINDPREV,     HPM_SRC_FINDPREV
+  HELPSUBITEM IDM_GOTO,         HPM_SRC_GOTO
+  HELPSUBITEM IDM_RUNMENU,      HPM_SRC_RUNMENU
+  HELPSUBITEM IDM_STEPOVER,     HPM_STEPOVER
+  HELPSUBITEM IDM_STEPINTO,     HPM_STEPINTO
+  HELPSUBITEM IDM_FINISH,       HPM_FINISH
+  HELPSUBITEM IDM_ISTEPOVER,    HPM_ISTEPOVER
+  HELPSUBITEM IDM_ISTEPINTO,    HPM_ISTEPINTO
+  HELPSUBITEM IDM_UNTIL,        HPM_SRC_UNTIL
+  HELPSUBITEM IDM_JUMP,         HPM_SRC_JUMP
+  HELPSUBITEM IDM_BRKPTMENU,    HPM_SRC_BRKPTMENU
+  HELPSUBITEM IDM_BRKPT_LINE,   HPM_BRKPT_LINE
+  HELPSUBITEM IDM_BRKPT_LIST,   HPM_BRKPT_LIST
+  HELPSUBITEM IDM_DSPMENU,      HPM_SRC_DSPMENU
+  HELPSUBITEM IDM_DSP_ADD,      HPM_DSP_ADD
+  HELPSUBITEM IDM_DSP_SHOW,     HPM_SRC_DSP_SHOW
+  HELPSUBITEM IDM_OPTIONSMENU,  HPM_SRC_OPTIONSMENU
+  HELPSUBITEM IDM_PMDEBUGMODE,  HPM_PMDEBUGMODE
+  HELPSUBITEM IDM_WINMENU,      HPM_SRC_WINMENU
+  HELPSUBITEM IDM_WIN_BRK,      HPM_WIN_BRK
+  HELPSUBITEM IDM_WIN_CMD,      HPM_WIN_CMD
+  HELPSUBITEM IDM_WIN_DSP,      HPM_WIN_DSP
+  HELPSUBITEM IDM_WIN_SRCS,     HPM_WIN_SRCS
+  HELPSUBITEM IDM_WIN_THR,      HPM_WIN_THR
+  HELPSUBITEM IDM_WIN_REG,      HPM_WIN_REG
+  HELPSUBITEM IDM_HELPMENU,     HPM_SRC_HELPMENU
+  HELPSUBITEM IDM_HELP_HELP,    HPM_HELP_HELP
+  HELPSUBITEM IDM_HELP_EXT,     HPM_HELP_EXT
+  HELPSUBITEM IDM_HELP_KEYS,    HPM_HELP_KEYS
+  HELPSUBITEM IDM_HELP_INDEX,   HPM_HELP_INDEX
+  HELPSUBITEM IDM_HELP_CONTENTS, HPM_HELP_CONTENTS
+END
+
+HELPSUBTABLE ID_SOURCE_FILES_WINDOW
+BEGIN
+  HELPSUBITEM IDM_FILEMENU,     HPM_SRCS_FILEMENU
+  HELPSUBITEM IDM_EXIT,         HPM_EXIT
+  HELPSUBITEM IDM_WINMENU,      HPM_SRCS_WINMENU
+  HELPSUBITEM IDM_WIN_BRK,      HPM_WIN_BRK
+  HELPSUBITEM IDM_WIN_CMD,      HPM_WIN_CMD
+  HELPSUBITEM IDM_WIN_DSP,      HPM_WIN_DSP
+  HELPSUBITEM IDM_WIN_THR,      HPM_WIN_THR
+  HELPSUBITEM IDM_WIN_REG,      HPM_WIN_REG
+  HELPSUBITEM IDM_HELPMENU,     HPM_SRCS_HELPMENU
+  HELPSUBITEM IDM_HELP_HELP,    HPM_HELP_HELP
+  HELPSUBITEM IDM_HELP_EXT,     HPM_HELP_EXT
+  HELPSUBITEM IDM_HELP_KEYS,    HPM_HELP_KEYS
+  HELPSUBITEM IDM_HELP_INDEX,   HPM_HELP_INDEX
+  HELPSUBITEM IDM_HELP_CONTENTS, HPM_HELP_CONTENTS
+END
+
+HELPSUBTABLE ID_BREAKPOINTS_WINDOW
+BEGIN
+  HELPSUBITEM IDM_FILEMENU,     HPM_BRK_FILEMENU
+  HELPSUBITEM IDM_EXIT,         HPM_EXIT
+  HELPSUBITEM IDM_EDITMENU,     HPM_BRK_EDITMENU
+  HELPSUBITEM IDM_MODIFY,       HPM_BRK_MODIFY
+  HELPSUBITEM IDM_ENABLE,       HPM_BRK_ENABLE
+  HELPSUBITEM IDM_DISABLE,      HPM_BRK_DISABLE
+  HELPSUBITEM IDM_DELETE,       HPM_BRK_DELETE
+  HELPSUBITEM IDM_BRKPTMENU,    HPM_BRK_BRKPTMENU
+  HELPSUBITEM IDM_BRKPT_LINE,   HPM_BRKPT_LINE
+  HELPSUBITEM IDM_REFRESH,      HPM_BRK_REFRESH
+  HELPSUBITEM IDM_WINMENU,      HPM_BRK_WINMENU
+  HELPSUBITEM IDM_WIN_CMD,      HPM_WIN_CMD
+  HELPSUBITEM IDM_WIN_DSP,      HPM_WIN_DSP
+  HELPSUBITEM IDM_WIN_SRCS,     HPM_WIN_SRCS
+  HELPSUBITEM IDM_WIN_THR,      HPM_WIN_THR
+  HELPSUBITEM IDM_WIN_REG,      HPM_WIN_REG
+  HELPSUBITEM IDM_HELPMENU,     HPM_BRK_HELPMENU
+  HELPSUBITEM IDM_HELP_HELP,    HPM_HELP_HELP
+  HELPSUBITEM IDM_HELP_EXT,     HPM_HELP_EXT
+  HELPSUBITEM IDM_HELP_KEYS,    HPM_HELP_KEYS
+  HELPSUBITEM IDM_HELP_INDEX,   HPM_HELP_INDEX
+  HELPSUBITEM IDM_HELP_CONTENTS, HPM_HELP_CONTENTS
+END
+
+HELPSUBTABLE ID_DISPLAY_WINDOW
+BEGIN
+  HELPSUBITEM IDM_FILEMENU,     HPM_DSP_FILEMENU
+  HELPSUBITEM IDM_EXIT,         HPM_EXIT
+  HELPSUBITEM IDM_EDITMENU,     HPM_DSP_EDITMENU
+  HELPSUBITEM IDM_ADD,          HPM_DSP_ADD
+  HELPSUBITEM IDM_MODIFY,       HPM_DSP_MODIFY
+  HELPSUBITEM IDM_ENABLE,       HPM_DSP_ENABLE
+  HELPSUBITEM IDM_DISABLE,      HPM_DSP_DISABLE
+  HELPSUBITEM IDM_REPMENU,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_DEC_S,    HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_DEC_U,    HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_HEX,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_OCT,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_BIN,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_CHR,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_ADR,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_FLT,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_STR,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_REP_INS,      HPM_DSP_FORMAT
+  HELPSUBITEM IDM_DELETE,       HPM_DSP_DELETE
+  HELPSUBITEM IDM_DEREFERENCE,  HPM_DSP_DEREFERENCE
+  HELPSUBITEM IDM_ENABLE_ALL,   HPM_DSP_ENABLE_ALL
+  HELPSUBITEM IDM_DISABLE_ALL,  HPM_DSP_DISABLE_ALL
+  HELPSUBITEM IDM_DELETE_ALL,   HPM_DSP_DELETE_ALL
+  HELPSUBITEM IDM_WINMENU,      HPM_DSP_WINMENU
+  HELPSUBITEM IDM_WIN_CMD,      HPM_WIN_CMD
+  HELPSUBITEM IDM_WIN_BRK,      HPM_WIN_BRK
+  HELPSUBITEM IDM_WIN_SRCS,     HPM_WIN_SRCS
+  HELPSUBITEM IDM_WIN_THR,      HPM_WIN_THR
+  HELPSUBITEM IDM_WIN_REG,      HPM_WIN_REG
+  HELPSUBITEM IDM_HELPMENU,     HPM_DSP_HELPMENU
+  HELPSUBITEM IDM_HELP_HELP,    HPM_HELP_HELP
+  HELPSUBITEM IDM_HELP_EXT,     HPM_HELP_EXT
+  HELPSUBITEM IDM_HELP_KEYS,    HPM_HELP_KEYS
+  HELPSUBITEM IDM_HELP_INDEX,   HPM_HELP_INDEX
+  HELPSUBITEM IDM_HELP_CONTENTS, HPM_HELP_CONTENTS
+END
+
+HELPSUBTABLE ID_THREADS_WINDOW
+BEGIN
+  HELPSUBITEM IDM_FILEMENU,     HPM_THR_FILEMENU
+  HELPSUBITEM IDM_EXIT,         HPM_EXIT
+  HELPSUBITEM IDM_EDITMENU,     HPM_THR_EDITMENU
+  HELPSUBITEM IDM_ENABLE,       HPM_THR_ENABLE
+  HELPSUBITEM IDM_DISABLE,      HPM_THR_DISABLE
+  HELPSUBITEM IDM_SWITCH,       HPM_THR_SWITCH
+  HELPSUBITEM IDM_WINMENU,      HPM_THR_WINMENU
+  HELPSUBITEM IDM_WIN_CMD,      HPM_WIN_CMD
+  HELPSUBITEM IDM_WIN_BRK,      HPM_WIN_BRK
+  HELPSUBITEM IDM_WIN_SRCS,     HPM_WIN_SRCS
+  HELPSUBITEM IDM_WIN_DSP,      HPM_WIN_DSP
+  HELPSUBITEM IDM_WIN_REG,      HPM_WIN_REG
+END
+
+HELPSUBTABLE ID_REGISTER_WINDOW
+BEGIN
+  HELPSUBITEM IDM_FILEMENU,     HPM_REG_FILEMENU
+  HELPSUBITEM IDM_EXIT,         HPM_EXIT
+  HELPSUBITEM IDM_VIEWMENU,     HPM_REG_VIEWMENU
+  HELPSUBITEM IDM_REFRESH,      HPM_REG_REFRESH
+  HELPSUBITEM IDM_WINMENU,      HPM_REG_WINMENU
+  HELPSUBITEM IDM_WIN_CMD,      HPM_WIN_CMD
+  HELPSUBITEM IDM_WIN_BRK,      HPM_WIN_BRK
+  HELPSUBITEM IDM_WIN_SRCS,     HPM_WIN_SRCS
+  HELPSUBITEM IDM_WIN_DSP,      HPM_WIN_DSP
+  HELPSUBITEM IDM_WIN_THR,      HPM_WIN_THR
+END
+
+HELPSUBTABLE IDD_PMDEBUGMODE
+BEGIN
+END
+
+HELPSUBTABLE IDD_BRKPT_LINE
+BEGIN
+END
+
+HELPSUBTABLE IDD_STARTUP
+BEGIN
+END
+
+HELPSUBTABLE IDD_DISPLAY
+BEGIN
+END
+
+HELPSUBTABLE IDD_GOTO
+BEGIN
+END
+
+HELPSUBTABLE IDD_ABOUT
+BEGIN
+END
+
+HELPSUBTABLE IDD_FIND
+BEGIN
+END
+
+HELPSUBTABLE IDD_HISTORY
+BEGIN
+END
+
+HELPTABLE HELP_TABLE
+BEGIN
+    HELPITEM ID_COMMAND_WINDOW,      ID_COMMAND_WINDOW,      HELP_CMD_WINDOW
+    HELPITEM ID_SOURCE_WINDOW,       ID_SOURCE_WINDOW,       HELP_SRC_WINDOW
+    HELPITEM ID_SOURCE_FILES_WINDOW, ID_SOURCE_FILES_WINDOW, HELP_SRCS_WINDOW
+    HELPITEM ID_BREAKPOINTS_WINDOW,  ID_BREAKPOINTS_WINDOW,  HELP_BRK_WINDOW
+    HELPITEM ID_DISPLAY_WINDOW,      ID_DISPLAY_WINDOW,      HELP_DSP_WINDOW
+    HELPITEM ID_THREADS_WINDOW,      ID_THREADS_WINDOW,      HELP_THR_WINDOW
+    HELPITEM ID_REGISTER_WINDOW,     ID_REGISTER_WINDOW,     HELP_REG_WINDOW
+    HELPITEM IDD_PMDEBUGMODE,        IDD_PMDEBUGMODE,        HPD_PMDEBUGMODE
+    HELPITEM IDD_BRKPT_LINE,         IDD_BRKPT_LINE,         HPD_BRKPT_LINE
+    HELPITEM IDD_STARTUP,            IDD_STARTUP,            HPD_STARTUP
+    HELPITEM IDD_DISPLAY,            IDD_DISPLAY,            HPD_DISPLAY
+    HELPITEM IDD_GOTO,               IDD_GOTO,               HPD_GOTO
+    HELPITEM IDD_ABOUT,              IDD_ABOUT,              HELP_GENERAL
+    HELPITEM IDD_FIND,               IDD_FIND,               HPD_FIND
+    HELPITEM IDD_HISTORY,            IDD_HISTORY,            HPD_HISTORY
+END
Index: trunk/src/emx/src/pmgdb/pmtty.cc
===================================================================
--- trunk/src/emx/src/pmgdb/pmtty.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmtty.cc	(revision 18)
@@ -0,0 +1,291 @@
+/* pmtty.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+// TODO: jump to end on input
+
+#define INCL_DOS
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+
+
+#define IDT_CURSOR      1
+
+pmtty::pmtty (pmapp *in_app, unsigned in_id, ULONG frame_flags,
+              const SWP *pswp, const char *fontnamesize)
+  : pmtxt (in_app, in_id, frame_flags, pswp, fontnamesize)
+{
+  x = 0; y = 0;
+  line_width = max_line_len;
+  cursor_enabled = false; cursor_painted = false; cursor_hidden = 0;
+  sel_attr = get_default_attr ();
+  create_hpsCursor ();
+  cursor_width = (int)WinQuerySysValue (HWND_DESKTOP, SV_CXBORDER);
+}
+
+
+pmtty::~pmtty ()
+{
+}
+
+
+void pmtty::set_line_width (int width)
+{
+  if (width > max_line_len)
+    width = max_line_len;
+  if (x >= width)
+    puts ("\n", 1);
+  line_width = width;
+}
+
+
+void pmtty::create_hpsCursor ()
+{
+  hpsCursor = WinGetPS (get_hwndClient ());
+  set_font (hpsCursor);
+}
+
+
+
+// Roll our own cursor because a cursor created with WinCreateCursor
+// can be hidden and destroyed only by the thread which created it.
+
+void pmtty::paint_cursor ()
+{
+  POINTL ptl;
+
+  if (get_bbox_pos (hpsCursor, &ptl, y, x))
+    {
+      // TODO: Nicer cursor (WinDrawPointer?)
+      rclCursor.xLeft = ptl.x;
+      rclCursor.xRight = rclCursor.xLeft + cursor_width;
+      rclCursor.yBottom = ptl.y;
+      rclCursor.yTop = rclCursor.yBottom + get_cyChar ();
+      WinInvertRect (hpsCursor, &rclCursor);
+      cursor_painted = true;
+    }
+}
+
+
+void pmtty::remove_cursor ()
+{
+  WinInvertRect (hpsCursor, &rclCursor);
+  cursor_painted = false;
+}
+
+
+inline void pmtty::cursor_on ()
+{
+  if (--cursor_hidden == 0 && cursor_enabled && !cursor_painted
+      && WinQueryFocus (HWND_DESKTOP) == get_hwndClient ())
+    paint_cursor ();
+}
+
+
+inline void pmtty::cursor_off ()
+{
+  if (++cursor_hidden == 1 && cursor_enabled && cursor_painted)
+    remove_cursor ();
+}
+
+
+void pmtty::puts1 (const char *s, size_t len)
+{
+  while (x + (int)len >= line_width)
+    {
+      size_t n = line_width - x;
+      put (y, x, n, s, sel_attr, true);
+      x = 0; ++y;
+      s += n; len -= n;
+    }
+  if (len != 0)
+    {
+      put (y, x, len, s, sel_attr, true);
+      x += len;
+    }
+}
+
+
+void pmtty::puts (const char *s, size_t len)
+{
+  if (len == 0)
+    return;
+  cursor_off ();
+  while (len != 0)
+    {
+      size_t i;
+      for (i = 0; i < len; ++i)
+        if (s[i] == '\n' || s[i] == '\t')
+          break;
+      if (i >= len)
+        {
+          puts1 (s, len);
+          break;
+        }
+      if (i != 0)
+        puts1 (s, i);
+      if (s[i] == '\t')
+        {
+          int tab_width = (x | 7) + 1 - x;
+          puts1 ("        ", tab_width);
+        }
+      else
+        {
+          x = 0; ++y;
+        }
+      len -= i + 1; s += i + 1;
+    }
+  if (x == 0)
+    put (y, x, 0, "", sel_attr, true);
+  // TODO: Optionally scroll horizontally/vertically to make cursor visible
+  cursor_on ();
+}
+
+
+class pmtty_const_str
+{
+public:
+  char *str;
+  pmtty_const_str (char c, size_t len)
+  {
+    str = new char[len + 1];
+    memset (str, c, len);
+    str[len] = 0;
+  }
+};
+
+
+static pmtty_const_str spaces (' ', pmtxt::max_line_len);
+
+void pmtty::backspace (int n)
+{
+  if (n > x)
+    n = x;
+  if (n > 0)
+    {
+      x -= n;
+      cursor_off ();
+      put (y, x, n, spaces.str, sel_attr, true);
+      cursor_on ();
+    }
+}
+
+
+void pmtty::cursor (bool on)
+{
+  if (on && !cursor_enabled)
+    {
+      cursor_enabled = true;
+      if (cursor_hidden == 0
+          && WinQueryFocus (HWND_DESKTOP) == get_hwndClient ())
+        paint_cursor ();
+      // TODO: Restart timer when SV_CURSORRATE is changed
+      WinStartTimer (get_hab (), get_hwndClient (), IDT_CURSOR,
+                     WinQuerySysValue (HWND_DESKTOP, SV_CURSORRATE));
+    }
+  else if (!on && cursor_enabled)
+    {
+      WinStopTimer (get_hab(), get_hwndClient (), IDT_CURSOR);
+      cursor_enabled = false;
+      if (cursor_painted)
+        remove_cursor ();
+    }
+}
+
+
+MRESULT pmtty::wm_setfocus (HWND, ULONG, MPARAM, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp2))
+    {
+      if (cursor_enabled && cursor_hidden == 0 && !cursor_painted)
+        paint_cursor ();
+    }
+  else
+    {
+      if (cursor_painted)
+        remove_cursor ();
+    }
+  return 0;
+}
+
+
+MRESULT pmtty::wm_timer (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp1) == IDT_CURSOR)
+    {
+      if (cursor_painted)
+        remove_cursor ();
+      else if (cursor_enabled && cursor_hidden == 0
+               && WinQueryFocus (HWND_DESKTOP) == get_hwndClient ())
+        paint_cursor ();
+      return FALSE;
+    }
+  else
+    return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmtty::wm_presparamchanged (HWND hwnd, ULONG msg,
+                                    MPARAM mp1, MPARAM mp2)
+{
+  parent::wm_presparamchanged (hwnd, msg, mp1, mp2);
+  if (LONGFROMMP (mp1) == PP_FONTNAMESIZE && !get_initializing_font ())
+    {
+      WinReleasePS (hpsCursor);
+      create_hpsCursor ();
+    }
+  return 0;
+}
+
+
+void pmtty::font_changed ()
+{
+  set_font (hpsCursor);
+}
+
+
+void pmtty::painting (bool start)
+{
+  if (start)
+    cursor_off ();
+  else
+    cursor_on ();
+}
+
+
+void pmtty::delete_all ()
+{
+  cursor_off ();
+  x = 0; y = 0;
+  parent::delete_all ();
+}
+
+
+bool pmtty::get_xy (POINTL *ptl)
+{
+  return get_bbox_pos (hpsCursor, ptl, y, x);
+}
Index: trunk/src/emx/src/pmgdb/pmtty.h
===================================================================
--- trunk/src/emx/src/pmgdb/pmtty.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmtty.h	(revision 18)
@@ -0,0 +1,83 @@
+/* pmtty.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+// A frame window showing scrollable text; with tty-like output and cursor
+
+class pmtty : public pmtxt
+{
+public:
+  typedef pmtxt parent;
+
+  // Constructors and destructors, initialization
+  pmtty (pmapp *app, unsigned id, ULONG frame_flags, const SWP *pswp,
+         const char *fontnamesize = 0);
+  ~pmtty ();
+  void delete_all ();
+
+  // Painting
+  void puts (const char *s, size_t len);
+  void puts (const char *s) { puts (s, strlen (s)); }
+  void backspace (int n = 1);
+  void cursor (bool on);
+
+  // Attributes
+  void set_fg_color (COLOR color) { pmtxt::set_fg_color (sel_attr, color); }
+  void set_fg_color () { pmtxt::set_fg_color (sel_attr); }
+
+  void set_bg_color (COLOR color) { pmtxt::set_bg_color (sel_attr, color); }
+  void set_bg_color () { pmtxt::set_bg_color (sel_attr); }
+
+  const struct pmtxt_attr &get_attr () const {return sel_attr;}
+  void set_attr (const struct pmtxt_attr &a) {sel_attr = a;}
+  void set_attr () {sel_attr = get_default_attr ();}
+
+  void set_line_width (int width);
+  int get_line () const { return y; }
+  int get_column () const { return x; }
+  bool get_xy (POINTL *ptl);
+
+private:
+  int x, y;
+  bool cursor_enabled;          // True iff cursor enabled with cursor()
+  bool cursor_painted;          // True iff cursor painted
+  int cursor_hidden;            // Positive iff cursor temporarily hidden
+  pmtxt_attr sel_attr;
+  int line_width;
+  int cursor_width;
+  HPS hpsCursor;
+  RECTL rclCursor;
+
+  // Override member functions of pmframe
+  MRESULT wm_setfocus (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_timer (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_presparamchanged (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+  // Override member functions of pmtxt
+  void painting (bool start);
+  void font_changed ();
+
+  void create_hpsCursor ();
+  void cursor_on ();
+  void cursor_off ();
+  void paint_cursor ();
+  void remove_cursor ();
+  void puts1 (const char *s, size_t len);
+};
Index: trunk/src/emx/src/pmgdb/pmtxt.cc
===================================================================
--- trunk/src/emx/src/pmgdb/pmtxt.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmtxt.cc	(revision 18)
@@ -0,0 +1,2006 @@
+/* pmtxt.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_WIN
+#define INCL_GPI
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+
+#define UWM_PMTHREAD            (WM_USER+200)
+
+#define PMTHREAD_SBAR_X         0x01
+#define PMTHREAD_SBAR_Y         0x02
+
+
+#define LF_UNDERLINE            0x01
+
+#define EOL_COLUMN      (pmtxt::max_line_len + 1)
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+struct pmtxt_line_attr
+{
+  // TODO: x
+  struct pmtxt_line_attr *next;
+  int column;
+  pmtxt::element el;
+  pmtxt_attr attr;
+};
+
+struct pmtxt_line
+{
+  char *str;
+  pmtxt_line_attr *attr;
+  int len, alloc;
+  // TODO: Add flag bits (HAS_TABS, OUTPUT_PENDING, ...)
+  unsigned char flags;
+};
+
+
+pmtxt::pmtxt (pmapp *in_app, unsigned in_id, ULONG frame_flags,
+              const SWP *pswp, const char *fontnamesize)
+  : pmframe (in_app)
+{
+  _fmutex_checked_create (&mutex, 0);
+
+  track = true;
+  default_font = true;
+  init_fontnamesize = fontnamesize;
+  initializing_font = false;
+
+  aptl_line = new POINTL[max_line_len+1];
+
+  pmthread_pending = 0;
+  x_off = 0; y_off = 0;
+  x_pos = 0; max_x_pos = 0;
+  output_stopped = false; output_pending = false;
+  cache_line = -1;
+
+  lines_used = 0; lines_alloc = 0;
+  lines_vector = NULL;
+
+  tab_x = NULL; tab_count = 0; tab_x_size = 0;
+  tab_repaint = false;
+
+  default_attr.fg_color = CLR_BLACK;
+  default_attr.bg_color = CLR_WHITE;
+
+  create ("pmtxt.client", in_id, frame_flags, pswp);
+}
+
+
+pmtxt::~pmtxt ()
+{
+  delete_all ();
+  delete[] aptl_line;
+  delete[] tab_x;
+  // TODO: mutex
+}
+
+
+void pmtxt::delete_all ()
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+
+  output_pending = lines_used != 0;
+
+  for (int i = 0; i < lines_alloc; ++i)
+    free_line (i);
+  delete[] lines_vector;
+
+  x_off = 0; y_off = 0;
+  x_pos = 0; max_x_pos = 0;
+  cache_line = -1;
+
+  lines_used = 0; lines_alloc = 0;
+  lines_vector = NULL;
+
+  tab_count = 0;
+
+  unlock ();
+}
+
+
+void pmtxt::free_line (int line)
+{
+  delete[] lines_vector[line].str;
+  delete_attr (lines_vector[line].attr);
+}
+
+
+void pmtxt::init_line (int line)
+{
+  lines_vector[line].str = NULL;
+  lines_vector[line].attr = NULL;
+  lines_vector[line].len = 0;
+  lines_vector[line].alloc = 0;
+  lines_vector[line].flags = 0;
+}
+
+
+void pmtxt::delete_attr (pmtxt_line_attr *a)
+{
+  pmtxt_line_attr *next;
+
+  while (a != NULL)
+    {
+      next = a->next;
+      delete a;
+      a = next;
+    }
+}
+
+
+void pmtxt::more_lines (int new_count)
+{
+  int n = new_count < 1024 ? new_count + 128 : new_count + 1024;
+  pmtxt_line *new_vec = new pmtxt_line[n];
+  for (int i = 0; i < lines_alloc; ++i)
+    new_vec[i] = lines_vector[i];
+  delete[] lines_vector;
+  lines_vector = new_vec;
+  for (int i = lines_alloc; i < n; ++i)
+    init_line (i);
+  lines_alloc = n;
+}
+
+
+static inline void query_hps_attr (HPS hps, pmtxt_attr &cache)
+{
+  cache.fg_color = GpiQueryColor (hps);
+  cache.bg_color = GpiQueryBackColor (hps);
+}
+
+
+static inline void set_hps_attr (HPS hps, pmtxt_attr &cache,
+                                 const pmtxt_attr &attr)
+{
+  if (attr.fg_color != cache.fg_color)
+    {
+      GpiSetColor (hps, attr.fg_color);
+      cache.fg_color = attr.fg_color;
+    }
+  if (attr.bg_color != cache.bg_color)
+    {
+      GpiSetBackColor (hps, attr.bg_color);
+      cache.bg_color = attr.bg_color;
+    }
+}
+
+
+static inline bool eq_attr (const pmtxt_attr &a1, const pmtxt_attr &a2)
+{
+  return (a1.fg_color == a2.fg_color
+          && a1.bg_color == a2.bg_color);
+}
+
+
+MRESULT pmtxt::wm_create (HWND hwnd, ULONG, MPARAM, MPARAM)
+{
+  hwndHbar = WinWindowFromID (get_hwndFrame (), FID_HORZSCROLL);
+  hwndVbar = WinWindowFromID (get_hwndFrame (), FID_VERTSCROLL);
+
+  // Set the initial font
+
+  if (init_fontnamesize)
+    {
+      initializing_font = true;
+      WinSetPresParam (hwnd, PP_FONTNAMESIZE, strlen (init_fontnamesize) + 1,
+                       (PVOID)init_fontnamesize);
+      initializing_font = false;
+    }
+
+  // Create a presentation space handle for asynchronous painting (and
+  // for retrieving the font metrics).
+
+  create_hpsClient ();
+
+  // Get the default line (rule) width
+  // TODO: Does this really yield the width in pixels?
+  LINEBUNDLE lbundle;
+  if (GpiQueryAttrs (hpsClient, PRIM_LINE, LBB_WIDTH, &lbundle)
+      == GPI_ALTERROR)
+    rule_width = 1;
+  else
+    rule_width = FIXEDINT (lbundle.fxWidth);
+
+  // Retrieve the current attributes of hpsClient.
+
+  query_hps_attr (hpsClient, hpsClient_attr);
+
+  return FALSE;
+}
+
+
+// Retrieve the font metrics of the default font.
+
+void pmtxt::get_fontmetrics ()
+{
+  FONTMETRICS fm;
+  GpiQueryFontMetrics (hpsClient, (LONG)sizeof (fm), &fm);
+  cxChar = (int)fm.lMaxCharInc;
+  cyChar = (int)fm.lMaxBaselineExt;
+  cyDesc = (int)fm.lMaxDescender;
+
+  fixed_pitch = (fm.fsType & FM_TYPE_FIXED);
+}
+
+
+void pmtxt::create_hpsClient ()
+{
+  hpsClient = WinGetPS (get_hwndClient ());
+  setup_ps (hpsClient);
+  get_fontmetrics ();
+}
+
+
+void pmtxt::setup_ps (HPS hps)
+{
+  GpiSetBackMix (hps, BM_OVERPAINT);
+  set_font (hps);
+}
+
+
+void pmtxt::set_font (HPS hps)
+{
+  if (!default_font)
+    {
+      GpiCreateLogFont (hps, NULL, 1, &fattrs);
+      GpiSetCharSet (hps, 1);
+    }
+}
+
+
+void pmtxt::set_font (const pmtxt &s)
+{
+  SIZEF charbox;
+  char fontnamesize[FACESIZE+10];
+
+  // TODO: dropped font (and don't forget to update the constructor
+  // of source_window which depends on the current behavior)
+  if (!s.default_font && GpiQueryCharBox (s.hpsClient, &charbox))
+    {
+      _fmutex_checked_request (&mutex, _FMR_IGNINT);
+      fattrs = s.fattrs;
+      default_font = false;
+      GpiCreateLogFont (hpsClient, NULL, 1, &fattrs);
+      GpiSetCharSet (hpsClient, 1);
+      GpiSetCharBox (hpsClient, &charbox);
+      get_fontmetrics ();
+      cache_line = -1;
+      unlock ();
+      clear_tabs ();
+      change_size ();
+      font_changed ();
+      repaint ();
+    }
+  else if (s.default_font
+           && WinQueryPresParam (s.get_hwndClient(), PP_FONTNAMESIZE, 0,
+                                 NULL, sizeof (fontnamesize), fontnamesize,
+                                 0) != 0)
+    WinSetPresParam (get_hwndClient (), PP_FONTNAMESIZE,
+                     strlen (fontnamesize) + 1, fontnamesize);
+}
+
+
+MRESULT pmtxt::wm_paint (HWND hwnd, ULONG, MPARAM, MPARAM)
+{
+  pmtxt_attr hps_attr;
+
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  HPS hps = WinBeginPaint (hwnd, NULLHANDLE, NULL);
+  setup_ps (hps);
+  query_hps_attr (hps, hps_attr);
+  painting (true);
+  GpiErase (hps);
+
+  // TODO: examine update region to find lines to be displayed
+
+  int line = y_off;
+
+  // Compute the number of lines to display
+  int count = window_lines;
+  if (count > lines_used - line)
+    count = lines_used - line;
+
+  tab_repaint = false;
+  for (int i = 0; i < count; ++i)
+    paint (hps, hps_attr, line++, 0, false);
+  painting (false);
+  WinEndPaint (hps);
+  if (tab_repaint)
+    repaint ();
+  else
+    pmthread_pending |= PMTHREAD_SBAR_X | PMTHREAD_SBAR_Y;
+  unlock ();
+  return 0;
+}
+
+
+// Side effect: tab_repaint
+
+void pmtxt::paint (HPS hps, pmtxt_attr &cur_attr, int line, int column,
+                   bool paint_eol)
+{
+  int end;
+  POINTL ptl;
+
+  if (!get_bbox_pos (hps, &ptl, line, column))
+    return;
+  if (ptl.y < 0 || ptl.y >= cyClient)
+    return;
+  ptl.y += cyDesc;
+
+  const pmtxt_line *pline = &lines_vector[line];
+  char *p = pline->str + column;
+
+  if (pline->attr == NULL)
+    {
+      // Optimization
+      set_hps_attr (hps, cur_attr, default_attr);
+      GpiCharStringAt (hps, &ptl, pline->len - column, (PCH)p);
+      if (paint_eol)
+        {
+          // TODO
+          pmtxt_line_attr la;
+          la.el = E_FILL;
+          la.attr = default_attr;
+          paint (hps, cur_attr, &la, (char *)NULL, -1);
+        }
+    }
+  else
+    {
+      tab_index = 0;
+      const pmtxt_line_attr *a = pline->attr;
+      while (a->column < column)
+        {
+          if (a->next == NULL || a->next->column > column)
+            break;
+          if (a->el == E_TAB && a->next != NULL
+              && a->next->column != EOL_COLUMN)
+            tab_index += a->next->column - a->column;
+          a = a->next;
+        }
+
+      if (column < a->column)
+        {
+          set_hps_attr (hps, cur_attr, default_attr);
+          end = a->column == EOL_COLUMN ? pline->len : a->column;
+          GpiCharStringAt (hps, &ptl, end - column, (PCH)p);
+          p += end - column;
+          column = end;
+        }
+      else
+        GpiMove (hps, &ptl);
+
+      while (a != NULL && a->column != EOL_COLUMN)
+        {
+          if (a->next == NULL || a->next->column == EOL_COLUMN)
+            end = pline->len;
+          else
+            end = a->next->column;
+          if (column < end)
+            paint (hps, cur_attr, a, p, end - column);
+          p += end - column; column = end;
+          a = a->next;
+        }
+      // TODO: Don't always clear to the end of the line (we need
+      // to remember the previous max x
+      if (a != NULL)            // a->column == EOL_COLUMN
+        paint (hps, cur_attr, a, p, -1);
+      else if (paint_eol)
+        {
+          // TODO
+          pmtxt_line_attr la;
+          la.el = E_FILL;
+          la.attr = default_attr;
+          paint (hps, cur_attr, &la, (char *)NULL, -1);
+        }
+    }
+
+  POINTL ptl_end;
+  GpiQueryCurrentPosition (hps, &ptl_end);
+  int x = (ptl_end.x - (-x_off * cxChar) + cxChar - 1) / cxChar;
+  if (x > max_x_pos)
+    max_x_pos = x;
+
+  if (pline->flags & LF_UNDERLINE)
+    {
+      RECTL rcli;
+      rcli.xLeft = 0; rcli.xRight = cxClient;
+      rcli.yBottom = ptl.y - cyDesc;
+      rcli.yTop = rcli.yBottom + 1;
+      WinFillRect (hps, &rcli, default_attr.fg_color);
+    }
+}
+
+
+void pmtxt::paint (HPS hps, pmtxt_attr &cur_attr, const pmtxt_line_attr *pla,
+                   const char *p, int len)
+{
+  POINTL ptl;
+  RECTL rcli;
+  int x, add, i;
+
+  switch (pla->el)
+    {
+    case E_FILL:
+      // TODO: Use GpiBox
+      GpiQueryCurrentPosition (hps, &ptl);
+      rcli.xLeft = ptl.x;
+      // TODO: Width specified in string (pixels)
+      rcli.xRight = len == -1 ? cxClient : rcli.xLeft + len * cxChar;
+      rcli.yBottom = ptl.y - cyDesc;
+      rcli.yTop = rcli.yBottom + cyChar;
+      WinFillRect (hps, &rcli, pla->attr.bg_color);
+      if (len != -1)
+        {
+          ptl.x = rcli.xRight;
+          GpiMove (hps, &ptl);
+        }
+      break;
+
+    case E_TEXT:
+      set_hps_attr (hps, cur_attr, pla->attr);
+      GpiCharString (hps, len, (PCH)p);
+      break;
+
+    case E_VRULE:
+      // TODO: Use GpiBox
+      GpiQueryCurrentPosition (hps, &ptl);
+      rcli.xLeft = ptl.x;
+      rcli.xRight = rcli.xLeft + rule_width;
+      rcli.yBottom = ptl.y - cyDesc;
+      rcli.yTop = rcli.yBottom + cyChar;
+      // Note: CLR_DEFAULT does not work (background vs. foreground)
+      WinFillRect (hps, &rcli, pla->attr.fg_color);
+      ptl.x += rule_width;
+      GpiMove (hps, &ptl);
+      break;
+
+    case E_TAB:
+      // TODO: Use GpiBox
+      GpiQueryCurrentPosition (hps, &ptl);
+      x = ptl.x + x_off * cxChar; add = 0;
+      while (len != 0)
+        {
+          if (x > tab_x[tab_index])
+            {
+              tab_repaint = true;
+              add += x - tab_x[tab_index];
+              for (i = tab_index; i < tab_count; ++i)
+                tab_x[i] += add;
+            }
+          x = tab_x[tab_index];
+          ++tab_index; --len;
+        }
+
+      rcli.xLeft = ptl.x;
+      rcli.xRight = x - x_off * cxChar;
+      rcli.yBottom = ptl.y - cyDesc;
+      rcli.yTop = rcli.yBottom + cyChar;
+      WinFillRect (hps, &rcli, pla->attr.bg_color);
+      ptl.x = rcli.xRight;
+      GpiMove (hps, &ptl);
+      break;
+
+    default:
+      break;
+    }
+}
+
+
+void pmtxt::sync ()
+{
+  if (output_pending)
+    repaint ();
+}
+
+
+// TODO: Cache current scrollbar status to avoid WinSendMsg if nothing changed
+
+static void check_size (int new_value, int target, HWND sbar, int *off)
+{
+  int m = target - new_value;
+  if (m > 0)
+    {
+      WinEnableWindow (sbar, TRUE);
+      if (*off > m)
+        *off = m;
+      WinSendMsg (sbar, SBM_SETSCROLLBAR,
+                  MPFROMSHORT (*off), MPFROM2SHORT (0, MAX (0, (SHORT)m)));
+      WinSendMsg (sbar, SBM_SETTHUMBSIZE,
+                  MPFROM2SHORT ((USHORT)new_value, (USHORT)target), 0);
+    }
+  else
+    {
+      WinEnableWindow (sbar, FALSE);
+      *off = 0;
+    }
+}
+
+
+void pmtxt::check_x_size ()
+{
+  if (output_stopped)
+    pmthread_pending |= PMTHREAD_SBAR_X;
+  else if (same_tid ())
+    {
+      // Note that check_y_size() might be called recursively because
+      // check_size() calls WinSendMsg
+      unsigned rc = _fmutex_request (&mutex, _FMR_IGNINT | _FMR_NOWAIT);
+      if (rc != 0)
+        {
+          pmthread_pending |= PMTHREAD_SBAR_X;
+          // Avoid time window
+          rc = _fmutex_request (&mutex, _FMR_IGNINT | _FMR_NOWAIT);
+        }
+      if (rc == 0)
+        {
+          check_size (window_columns, max_x_pos, hwndHbar, &x_off);
+          unlock ();
+        }
+    }
+  else
+    pmthread_request (PMTHREAD_SBAR_X);
+}
+
+
+void pmtxt::check_y_size ()
+{
+  if (output_stopped)
+    pmthread_pending |= PMTHREAD_SBAR_Y;
+  else if (same_tid ())
+    {
+      // Note that check_y_size() might be called recursively because
+      // check_size() calls WinSendMsg
+      unsigned rc = _fmutex_request (&mutex, _FMR_IGNINT | _FMR_NOWAIT);
+      if (rc != 0)
+        {
+          pmthread_pending |= PMTHREAD_SBAR_Y;
+          // Avoid time window
+          rc = _fmutex_request (&mutex, _FMR_IGNINT | _FMR_NOWAIT);
+        }
+      if (rc == 0)
+        {
+          check_size (window_lines, lines_used, hwndVbar, &y_off);
+          unlock ();
+        }
+    }
+  else
+    pmthread_request (PMTHREAD_SBAR_Y);
+}
+
+
+void pmtxt::painting (bool)
+{
+}
+
+
+void pmtxt::button_event (int, int, int, int, int)
+{
+}
+
+
+MRESULT pmtxt::button_event (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2,
+                             int button, int clicks)
+{
+  if (WinQueryFocus (HWND_DESKTOP) == hwnd)
+    {
+      int line, column, tab;
+      _fmutex_checked_request (&mutex, _FMR_IGNINT);
+      line_column_from_x_y (hpsClient, &line, &column, &tab,
+                            (USHORT)SHORT1FROMMP (mp1),
+                            (USHORT)SHORT2FROMMP (mp1));
+      unlock ();
+      button_event (line, column, tab, button, clicks);
+      return (MRESULT)TRUE;
+    }
+
+  // Continue processing -- make window active.
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT pmtxt::wm_size (HWND, ULONG, MPARAM, MPARAM mp2)
+{
+  cxClient = SHORT1FROMMP (mp2);
+  cyClient = SHORT2FROMMP (mp2);
+  change_size ();
+  return 0;
+}
+
+
+void pmtxt::change_size ()
+{
+  window_lines = (int)(cyClient / cyChar);
+  window_columns = (int)(cxClient / cxChar);
+  if (cyClient != window_lines * cyChar && !get_minimized ())
+    {
+      // I don't like calling WinSetWindowPos from WM_SIZE processing;
+      // however, there seems to be no other way which works with
+      // FCF_SHELLPOSITION (WM_ADJUSTWINDOWPOS does not work)
+      SWP swp;
+      WinQueryWindowPos (get_hwndClient (), &swp);
+      POINTL ptl;
+      ptl.x = swp.x;
+      ptl.y = swp.y + cyClient;
+      WinMapWindowPoints (get_hwndFrame (), HWND_DESKTOP, &ptl, 1);
+      RECTL rcl;
+      rcl.xLeft = ptl.x;
+      rcl.xRight = rcl.xLeft + cxClient;
+      rcl.yTop = ptl.y;
+      rcl.yBottom = rcl.yTop - window_lines * cyChar;
+      WinCalcFrameRect (get_hwndFrame (), &rcl, FALSE);
+      // This causes recursion on WM_SIZE
+      WinSetWindowPos (get_hwndFrame (), HWND_TOP, rcl.xLeft, rcl.yBottom,
+                       rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom,
+                       SWP_SIZE | SWP_MOVE);
+    }
+  check_x_size ();
+  check_y_size ();
+}
+
+
+MRESULT pmtxt::wm_button (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  switch (msg)
+    {
+    case WM_BUTTON1DOWN:
+      return button_event (hwnd, msg, mp1, mp2, 1, 0);
+
+    case WM_BUTTON2DOWN:
+      return button_event (hwnd, msg, mp1, mp2, 2, 0);
+
+    case WM_BUTTON3DOWN:
+      return button_event (hwnd, msg, mp1, mp2, 3, 0);
+
+    case WM_BUTTON1CLICK:
+      return button_event (hwnd, msg, mp1, mp2, 1, 1);
+
+    case WM_BUTTON2CLICK:
+      return button_event (hwnd, msg, mp1, mp2, 2, 1);
+
+    case WM_BUTTON3CLICK:
+      return button_event (hwnd, msg, mp1, mp2, 3, 1);
+
+    case WM_BUTTON1DBLCLK:
+      return button_event (hwnd, msg, mp1, mp2, 1, 2);
+
+    case WM_BUTTON2DBLCLK:
+      return button_event (hwnd, msg, mp1, mp2, 2, 2);
+
+    case WM_BUTTON3DBLCLK:
+      return button_event (hwnd, msg, mp1, mp2, 3, 2);
+    }
+  return 0;
+}
+
+
+MRESULT pmtxt::wm_vscroll (HWND, ULONG, MPARAM, MPARAM mp2)
+{
+  int n, m, diff;
+
+  m = lines_used - window_lines;
+  switch (SHORT2FROMMP (mp2))
+    {
+    case SB_LINEUP:
+      n = y_off - 1; break;
+    case SB_LINEDOWN:
+      n = y_off + 1; break;
+    case SB_PAGEUP:
+      n = y_off - window_lines; break;
+    case SB_PAGEDOWN:
+      n = y_off + window_lines; break;
+    case SB_SLIDERTRACK:
+      disable_output ();
+      if (!track)
+        return 0;
+      n = SHORT1FROMMP (mp2);
+      break;
+    case SB_SLIDERPOSITION:
+      enable_output ();
+      n = SHORT1FROMMP (mp2);
+      break;
+    default:
+      return 0;
+    }
+  if (n > m) n = m;
+  if (n < 0) n = 0;
+  diff = n - y_off;
+  if (diff > 0)
+    {
+      y_off = n;
+      scroll_up (diff, true);
+    }
+  else if (diff < 0)
+    {
+      y_off = n;
+      scroll_down (-diff);
+    }
+  if (SHORT2FROMMP (mp2) != SB_SLIDERTRACK)
+    WinSendMsg (hwndVbar, SBM_SETSCROLLBAR, MPFROMSHORT (y_off),
+                MPFROM2SHORT (0, (SHORT)m));
+  return 0;
+}
+
+
+MRESULT pmtxt::wm_hscroll (HWND, ULONG, MPARAM, MPARAM mp2)
+{
+  int n, m;
+
+  m = max_x_pos - window_columns;
+  switch (SHORT2FROMMP (mp2))
+    {
+    case SB_LINELEFT:
+      n = x_off - 1; break;
+    case SB_LINERIGHT:
+      n = x_off + 1; break;
+    case SB_PAGELEFT:
+      n = x_off - window_columns; break;
+    case SB_PAGERIGHT:
+      n = x_off + window_columns; break;
+    case SB_SLIDERTRACK:
+      disable_output ();
+      if (!track)
+        return 0;
+      n = SHORT1FROMMP (mp2);
+      break;
+    case SB_SLIDERPOSITION:
+      enable_output ();
+      n = SHORT1FROMMP (mp2);
+      break;
+    default:
+      return 0;
+    }
+  if (n > m) n = m;
+  if (n < 0) n = 0;
+  if (n != x_off)
+    {
+      // TODO: use GpiBitBlt
+      x_pos += (x_off - n) * cxChar;
+      x_off = n;
+      repaint ();
+    }
+  if (SHORT2FROMMP (mp2) != SB_SLIDERTRACK)
+    WinSendMsg (hwndHbar, SBM_SETSCROLLBAR, MPFROMSHORT (x_off),
+                MPFROM2SHORT (0, (SHORT)m));
+  return 0;
+}
+
+
+MRESULT pmtxt::wm_presparamchanged (HWND hwnd, ULONG msg,
+                                    MPARAM mp1, MPARAM mp2)
+{
+  parent::wm_presparamchanged (hwnd, msg, mp1, mp2);
+  if (LONGFROMMP (mp1) == PP_FONTNAMESIZE && !initializing_font)
+    {
+      _fmutex_checked_request (&mutex, _FMR_IGNINT);
+      default_font = true;
+      WinReleasePS (hpsClient);
+      create_hpsClient ();
+      query_hps_attr (hpsClient, hpsClient_attr);
+      cache_line = -1;
+      unlock ();
+      clear_tabs ();
+      change_size ();
+      repaint ();
+    }
+  return 0;
+}
+
+
+void pmtxt::font_changed ()
+{
+}
+
+
+bool pmtxt::font_dialog ()
+{
+  FONTMETRICS fm;
+  FONTDLG fd;
+  UCHAR family_name[FACESIZE+1];
+  LONG pel_per_inch;
+  SIZEF charbox;
+
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  HDC hdc = GpiQueryDevice (hpsClient);
+  bool ok = (GpiQueryFontMetrics (hpsClient, (LONG)sizeof (fm), &fm)
+             && DevQueryCaps (hdc, CAPS_VERTICAL_FONT_RES, 1, &pel_per_inch)
+             && GpiQueryCharBox (hpsClient, &charbox)
+             && pel_per_inch != 0);
+  unlock ();
+  if (!ok)
+    {
+      WinAlarm (HWND_DESKTOP, WA_ERROR);
+      return false;
+    }
+
+  memcpy (family_name, fm.szFamilyname, FACESIZE);
+  family_name[FACESIZE] = 0;
+
+  memset (&fd, 0, sizeof (fd));
+  fd.cbSize = sizeof (fd);
+  fd.hpsScreen = hpsClient;
+  fd.hpsPrinter = NULLHANDLE;
+  fd.pszTitle = (PSZ)"Font";
+  fd.pszPreview = NULL;
+  fd.pszPtSizeList = NULL;
+  fd.pfnDlgProc = NULL;
+  fd.pszFamilyname = family_name;
+  if (fixed_pitch)
+    fd.fxPointSize = MAKEFIXED (fm.sNominalPointSize, 0) / 10;
+  else
+    fd.fxPointSize = (72 * charbox.cy + pel_per_inch / 2) / pel_per_inch;
+  fd.fl = (FNTS_HELPBUTTON | FNTS_RESETBUTTON | FNTS_CENTER
+           | FNTS_INITFROMFATTRS);
+  fd.flFlags = 0;
+  fd.flType = fm.fsType;
+  fd.flTypeMask = 0;
+  fd.flStyle = 0;
+  fd.flStyleMask = 0;
+  fd.clrFore = CLR_BLACK;
+  fd.clrBack = CLR_WHITE;
+  fd.ulUser = 0;
+  fd.lEmHeight = fm.lEmHeight;
+  fd.lXHeight = fm.lXHeight;
+  fd.lExternalLeading = fm.lExternalLeading;
+  fd.fAttrs.usRecordLength = sizeof (FATTRS);
+  fd.fAttrs.fsSelection = fm.fsSelection;
+  fd.fAttrs.lMatch = fm.lMatch;
+  memcpy (fd.fAttrs.szFacename, fm.szFacename, FACESIZE);
+  fd.fAttrs.idRegistry = fm.idRegistry;
+  fd.fAttrs.usCodePage = fm.usCodePage;
+  fd.fAttrs.lMaxBaselineExt = fm.lMaxBaselineExt;
+  fd.fAttrs.lAveCharWidth = fm.lAveCharWidth;
+  fd.fAttrs.fsType = fm.fsType;
+  fd.fAttrs.fsFontUse = 0;      // TODO?
+  fd.sNominalPointSize = fm.sNominalPointSize;
+  fd.usWeight = fm.usWeightClass;
+  fd.usWidth = fm.usWidthClass;
+  fd.usFamilyBufLen = FACESIZE;
+  if (WinFontDlg (HWND_DESKTOP, get_hwndClient (), &fd) == NULLHANDLE)
+    WinAlarm (HWND_DESKTOP, WA_ERROR);
+  else if (fd.lReturn == DID_OK)
+    {
+      fd.fAttrs.fsFontUse = FATTR_FONTUSE_NOMIX;
+      charbox.cx = charbox.cy = (fd.fxPointSize * pel_per_inch + 72/2)  / 72;
+      _fmutex_checked_request (&mutex, _FMR_IGNINT);
+      if (GpiCreateLogFont (hpsClient, NULL, 1, &fd.fAttrs) != FONT_MATCH
+          || !GpiSetCharSet (hpsClient, 1)
+          || !GpiSetCharBox (hpsClient, &charbox))
+        {
+          unlock ();
+          WinAlarm (HWND_DESKTOP, WA_ERROR);
+        }
+      else
+        {
+          fattrs = fd.fAttrs;
+          default_font = false;
+          get_fontmetrics ();
+          cache_line = -1;
+          unlock ();
+          clear_tabs ();
+          change_size ();
+          font_changed ();
+          repaint ();
+          return true;
+        }
+    }
+  return false;
+}
+
+
+void pmtxt::unlock ()
+{
+  _fmutex_checked_release (&mutex);
+  pmthread_perform ();
+}
+
+
+void pmtxt::pmthread_request (unsigned char bits)
+{
+  if (bits & ~pmthread_pending)
+    {
+      pmthread_pending |= bits;
+      WinPostMsg (get_hwndClient (), UWM_PMTHREAD, 0, 0);
+    }
+}
+
+
+void pmtxt::pmthread_perform ()
+{
+  if (same_tid ())
+    {
+      // TODO: Atomic
+      unsigned char x = pmthread_pending;
+      pmthread_pending = 0;
+      if (x & PMTHREAD_SBAR_X)
+        check_x_size ();
+      if (x & PMTHREAD_SBAR_Y)
+        check_y_size ();
+    }
+  else if (pmthread_pending != 0)
+    WinPostMsg (get_hwndClient (), UWM_PMTHREAD, 0, 0);
+}
+
+
+bool pmtxt::wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  if (parent::wm_user (hwnd, msg, mp1, mp2))
+    return true;
+  switch (msg)
+    {
+    case UWM_PMTHREAD:
+      pmthread_perform ();
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+
+// Fill-in TRACKINFO structure for resizing or moving a window.
+// This function is called from the frame window procedure.
+
+MRESULT pmtxt::wm_querytrackinfo (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  // First call the normal frame window procedure to set up the
+  // structure.
+
+  MRESULT mr = get_old_frame_msg () (hwnd, msg, mp1, mp2);
+
+  // If we're resizing the window, set the grid.
+
+  USHORT fs = SHORT1FROMMP (mp1);
+  if (((fs & TF_MOVE) != TF_MOVE)
+      && ((fs & TF_MOVE) || (fs & TF_SETPOINTERPOS))
+      && cxChar != 0 && cyChar != 0)
+    {
+      PTRACKINFO pti = (PTRACKINFO)mp2;
+      pti->fs |= TF_GRID;
+      if (fixed_pitch)
+        pti->cxGrid = pti->cxKeyboard = cxChar;
+      else
+        pti->cxGrid = pti->cxKeyboard = 1;
+      pti->cyGrid = pti->cyKeyboard = cyChar;
+    }
+  return mr;
+}
+
+
+void pmtxt::delete_lines (int line, int count, bool do_paint)
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  if (line >= 0 && line < lines_used && count >= 1)
+    {
+      if (line + count > lines_used)
+        count = lines_used - line;
+      if (cache_line >= line)
+        cache_line = -1;
+      int i;
+      for (i = 0; i < count; ++i)
+        free_line (line + i);
+      for (i = line; i < lines_used - count; ++i)
+        lines_vector[i] = lines_vector[i+count];
+      for (i = lines_used - count; i < lines_used; ++i)
+        init_line (i);
+      lines_used -= count;
+      int first = line - y_off;
+      if (first < 0) first = 0;
+      if (y_off > lines_used - window_lines)
+        {
+          y_off = lines_used - window_lines;
+          if (y_off < 0)
+            y_off = 0;
+          // TODO: Use GpiBitBlt?
+          if (do_paint && !output_stopped)
+            repaint ();
+          else
+            output_pending = true;
+        }
+      else if (first < window_lines)
+        {
+          if (!(do_paint && !output_stopped))
+            output_pending = true;
+          else if (first + count >= window_lines)
+            {
+              // No scrolling, just overwrite the last line(s)
+              // Clear first because paint() does nothing for lines
+              // beyond the current end of lines_vector[]
+              int n = window_lines - first;
+              RECTL rcli;
+              rcli.xLeft = 0; rcli.xRight = cxClient;
+              rcli.yBottom = 0; rcli.yTop = n * cyChar;
+              painting (true);
+              WinFillRect (hpsClient, &rcli, CLR_BACKGROUND);
+
+              // Repaint the last line(s)
+              for (i = 0; i < n; ++i)
+                paint (hpsClient, hpsClient_attr,
+                       window_lines - n + i + y_off, 0, false);
+              painting (false);
+            }
+          else
+            {
+              RECTL rcli, rcl, rcl_update, rcl_dummy;
+              rcli.xLeft = 0; rcli.xRight = cxClient;
+              rcli.yBottom = 0; rcli.yTop = cyClient - first * cyChar;
+              rcl.xLeft = rcli.xLeft; rcl.xRight = rcli.xRight - 1;
+              rcl.yBottom = rcli.yBottom; rcl.yTop = rcli.yTop - 1;
+              if (!output_pending
+                  && GpiRectVisible (hpsClient, &rcl) == RVIS_VISIBLE
+                  && (!WinQueryUpdateRect (get_hwndClient (), &rcl_update)
+                      || !WinIntersectRect (get_hab (), &rcl_dummy,
+                                            &rcl_update, &rcli)))
+                {
+                  // Scroll
+                  POINTL aptl[3];
+                  aptl[0].x = 0; aptl[0].y = count * cyChar;
+                  aptl[1].x = cxClient; aptl[1].y = cyClient - first * cyChar;
+                  aptl[2].x = 0; aptl[2].y = 0;
+                  painting (true);
+                  GpiBitBlt (hpsClient, hpsClient, 3, aptl, ROP_SRCCOPY,
+                             BBO_IGNORE);
+
+                  // Clear the last line(s)
+                  rcli.xLeft = 0; rcli.xRight = cxClient;
+                  rcli.yBottom = 0; rcli.yTop = count * cyChar;
+                  WinFillRect (hpsClient, &rcli, CLR_BACKGROUND);
+
+                  // Repaint the last line(s)
+                  for (i = 0; i < count; ++i)
+                    paint (hpsClient, hpsClient_attr,
+                           window_lines - count + i + y_off, 0, false);
+
+                  painting (false);
+                }
+              else
+                {
+                  // TODO: Don't have to repaint all the lines
+                  repaint ();
+                }
+            }
+        }
+    }
+  unlock ();
+  check_y_size ();
+}
+
+
+void pmtxt::insert_lines (int line, int count, bool do_paint)
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  if (line >= 0 && line <= lines_used && count >= 1)
+    {
+      if (lines_used + count > lines_alloc)
+        more_lines (lines_used + count);
+      if (cache_line >= line)
+        cache_line = -1;
+      if (line == lines_used)
+        lines_used += count;
+      else
+        {
+          int i;
+          for (i = 0; i < count; ++i)
+            free_line (lines_used + i);
+          for (i = lines_used - 1; i >= line; --i)
+            lines_vector[i+count] = lines_vector[i];
+          for (i = 0; i < count; ++i)
+            init_line (line + i);
+          lines_used += count;
+
+          int first = line - y_off;
+          if (first < 0) first = 0;
+          if (first < window_lines)
+            {
+              if (!(do_paint && !output_stopped))
+                output_pending = true;
+              else if (first + count >= window_lines)
+                {
+                  // No scrolling, just clear the inserted line(s)
+                  int n = window_lines - first;
+                  RECTL rcli;
+                  rcli.xLeft = 0; rcli.xRight = cxClient;
+                  rcli.yBottom = 0; rcli.yTop = n * cyChar;
+                  painting (true);
+                  WinFillRect (hpsClient, &rcli, CLR_BACKGROUND);
+                  painting (false);
+                }
+              else
+                {
+                  RECTL rcli, rcl, rcl_update, rcl_dummy;
+                  rcli.xLeft = 0; rcli.xRight = cxClient;
+                  rcli.yBottom = 0; rcli.yTop = cyClient - first * cyChar;
+                  rcl.xLeft = rcli.xLeft; rcl.xRight = rcli.xRight - 1;
+                  rcl.yBottom = rcli.yBottom; rcl.yTop = rcli.yTop - 1;
+                  if (!output_pending
+                      && GpiRectVisible (hpsClient, &rcl) == RVIS_VISIBLE
+                      && (!WinQueryUpdateRect (get_hwndClient (), &rcl_update)
+                          || !WinIntersectRect (get_hab (), &rcl_dummy,
+                                                &rcl_update, &rcli)))
+                    {
+                      // Scroll
+                      POINTL aptl[3];
+                      aptl[0].x = 0; aptl[0].y = 0;
+                      aptl[1].x = cxClient;
+                      aptl[1].y = (window_lines - first - count) * cyChar;
+                      aptl[2].x = 0; aptl[2].y = count * cyChar;
+                      painting (true);
+                      GpiBitBlt (hpsClient, hpsClient, 3, aptl, ROP_SRCCOPY,
+                                 BBO_IGNORE);
+
+                      // Clear the inserted line(s)
+                      rcli.xLeft = 0; rcli.xRight = cxClient;
+                      rcli.yTop = cyClient - first * cyChar;
+                      rcli.yBottom = rcl.yTop - count * cyChar;
+                      WinFillRect (hpsClient, &rcli, CLR_BACKGROUND);
+                      painting (false);
+                    }
+                  else
+                    {
+                      // TODO: Don't have to repaint all the lines
+                      repaint ();
+                    }
+                }
+            }
+        }
+    }
+  unlock ();
+  check_y_size ();
+}
+
+
+void pmtxt::clear_lines (int line, int count, bool do_paint)
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  if (line >= 0 && line < lines_used && count >= 1)
+    {
+      if (line + count > lines_used)
+        count = lines_used - line;
+      if (cache_line >= line && cache_line < line + count)
+        cache_line = -1;
+      for (int i = 0; i < count; ++i)
+        {
+          lines_vector[line + i].len = 0;
+          delete_attr (lines_vector[line + i].attr);
+          lines_vector[line + i].attr = NULL;
+        }
+
+      int first = line - y_off;
+      if (first < window_lines && first + count > 0)
+        {
+          if (first < 0)
+            {
+              count += first;
+              first = 0;
+            }
+          if (first + count > window_lines)
+            count = window_lines - first;
+          if (do_paint && !output_stopped)
+            {
+              RECTL rcli;
+              rcli.xLeft = 0; rcli.xRight = cxClient;
+              rcli.yTop =  cyClient - first * cyChar;
+              rcli.yBottom = rcli.yTop - count * cyChar;
+              painting (true);
+              WinFillRect (hpsClient, &rcli, CLR_BACKGROUND);
+              painting (false);
+            }
+          else
+            output_pending = true;
+        }
+    }
+  unlock ();
+}
+
+
+void pmtxt::truncate_line (int line, int count, bool do_paint)
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  if (line >= 0 && line < lines_used)
+    {
+      pmtxt_line *pline = &lines_vector[line];
+      if (pline->len > count)
+        {
+          pmtxt_line_attr **pa = &pline->attr;
+          while (*pa != NULL && (*pa)->column <= count)
+            pa = &(*pa)->next;
+          pmtxt_line_attr *a = *pa, *next;
+          while (a != NULL && a->column != EOL_COLUMN)
+            {
+              next = a->next;
+              delete a;
+              a = next;
+            }
+          *pa = a;
+          pline->len = count;
+          if (cache_line == line && cache_column > count)
+            cache_line = -1;
+          if (do_paint)
+            paint (hpsClient, hpsClient_attr, line, count, true);
+        }
+    }
+  unlock ();
+}
+
+
+// Return true iff the caller is responsible for painting the area
+// becoming free
+
+bool pmtxt::scroll_up (int n, bool do_paint)
+{
+  RECTL rcl, rcli, rcl_update, rcl_dummy;
+
+  if (n >= window_lines || output_pending)
+    {
+      if (!do_paint)
+        cache_line = -1;
+      repaint ();
+      output_pending = false;
+      return false;
+    }
+  rcli.xLeft = 0; rcli.xRight = cxClient;
+  rcli.yBottom = 0; rcli.yTop = cyClient - n * cyChar;
+  rcl.xLeft = 0; rcl.xRight = cxClient - 1;
+  rcl.yBottom = 0; rcl.yTop = cyClient - n * cyChar - 1;
+  if (GpiRectVisible (hpsClient, &rcl) == RVIS_VISIBLE
+      && (!WinQueryUpdateRect (get_hwndClient (), &rcl_update)
+          || !WinIntersectRect (get_hab (), &rcl_dummy, &rcl_update, &rcli)))
+    {
+      // Source rectangle completely visible and not to be updated; scroll!
+      POINTL aptl[3];
+      aptl[0].x = 0; aptl[0].y = n * cyChar;
+      aptl[1].x = cxClient; aptl[1].y = cyClient;
+      aptl[2].x = 0; aptl[2].y = 0;
+      painting (true);
+      GpiBitBlt (hpsClient, hpsClient, 3, aptl, ROP_SRCCOPY, BBO_IGNORE);
+      rcli.xLeft = 0; rcli.xRight = cxClient;
+      rcli.yBottom = 0; rcli.yTop = n * cyChar;
+      if (do_paint)
+        {
+          painting (false);
+          repaint (&rcli);
+          return false;
+        }
+      else
+        {
+          WinFillRect (hpsClient, &rcli, CLR_BACKGROUND);
+          painting (false);
+          return true;
+        }
+    }
+  else
+    {
+      if (!do_paint)
+        cache_line = -1;
+      repaint ();
+      return false;
+    }
+}
+
+
+void pmtxt::scroll_down (int n)
+{
+  RECTL rcl, rcli, rcl_update, rcl_dummy;
+
+  if (n >= window_lines || output_pending)
+    {
+      repaint ();
+      output_pending = false;
+      return;
+    }
+  rcli.xLeft = 0; rcli.xRight = cxClient;
+  rcli.yBottom = n * cyChar; rcli.yTop = cyClient;
+  rcl.xLeft = 0; rcl.xRight = cxClient - 1;
+  rcl.yBottom = n * cyChar; rcl.yTop = cyClient - 1;
+  if (GpiRectVisible (hpsClient, &rcl) == RVIS_VISIBLE
+      && (!WinQueryUpdateRect (get_hwndClient (), &rcl_update)
+          || !WinIntersectRect (get_hab (), &rcl_dummy, &rcl_update, &rcli)))
+    {
+      // Source rectangle completely visible and not to be updated; scroll!
+      POINTL aptl[3];
+      aptl[0].x = 0; aptl[0].y = 0;
+      aptl[1].x = cxClient; aptl[1].y = cyClient - n * cyChar;
+      aptl[2].x = 0; aptl[2].y = n * cyChar;
+      painting (true);
+      GpiBitBlt (hpsClient, hpsClient, 3, aptl, ROP_SRCCOPY, BBO_IGNORE);
+      painting (false);
+      rcli.xLeft = 0; rcli.xRight = cxClient;
+      rcli.yTop = cyClient; rcli.yBottom = cyClient - n * cyChar;
+      repaint (&rcli);
+    }
+  else
+    repaint ();
+}
+
+
+void pmtxt::disable_output ()
+{
+  output_stopped = true;
+}
+
+
+void pmtxt::enable_output ()
+{
+  output_stopped = false;
+  if (output_pending)
+    {
+      output_pending = false;
+      repaint ();
+    }
+}
+
+
+void pmtxt::show_line (int line, int threshold, int overshoot)
+{
+  int n;
+
+  if (overshoot < threshold)
+    overshoot = threshold;
+  if (line - threshold < y_off)
+    {
+      line = line >= overshoot ? line - overshoot : 0;
+      n = y_off - line;
+      y_off = line;
+      scroll_down (n);
+      check_y_size ();
+    }
+  else if (line + threshold >= y_off + window_lines)
+    {
+      line = line + overshoot < lines_used ? line + overshoot : lines_used - 1;
+      n = line - (y_off + window_lines - 1);
+      y_off = line - (window_lines - 1);
+      scroll_up (n, true);
+      check_y_size ();
+    }
+}
+
+
+// TODO: E_TEXT only
+int pmtxt::get_char (int line, int column)
+{
+  if (line < 0 || line >= lines_used || column < 0)
+    return -1;
+  if (column >= lines_vector[line].len)
+    return -1;
+  return (unsigned char)lines_vector[line].str[column];
+}
+
+
+// TODO: E_TEXT only
+bool pmtxt::get_string (int line, int column, char *str, size_t count)
+{
+  if (line < 0 || line >= lines_used || column < 0)
+    return false;
+  if (column >= lines_vector[line].len)
+    count = 0;
+  else if (column + (int)count > lines_vector[line].len)
+    count = lines_vector[line].len - column;
+  memcpy (str, lines_vector[line].str + column, count);
+  str[count] = 0;
+  return true;
+}
+
+
+void pmtxt::clear_tabs ()
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  for (int i = 0; i < tab_count;++i)
+    tab_x[i] = 0;
+  unlock ();
+}
+
+
+bool pmtxt::get_bbox_pos (HPS hps, POINTL *pptl, int line, int column)
+{
+  if (line >= lines_used)
+    return false;
+
+  int x = -1;
+  int line_len = lines_vector[line].len;
+
+  if (column == 0)
+    x = 0;
+  else if (line == cache_line && column == cache_column)
+    x = cache_x;
+
+  if (column > line_len)
+    return false;
+
+  if (x == -1)
+    {
+      POINTL ptl; ptl.x = 0; ptl.y = 0;
+      char *p = lines_vector[line].str;
+      const pmtxt_line_attr *a = lines_vector[line].attr;
+
+      // TODO: Use extra PS when adding fonts
+      // TODO: Start at cache_column if possible
+
+      if (a == NULL || column <= a->column)
+        {
+          if (fixed_pitch)
+            x = ptl.x + column * cxChar;
+          else
+            {
+              GpiQueryCharStringPosAt (hps, &ptl, 0, column, (PCH)p,
+                                       NULL, aptl_line);
+              x = aptl_line[column].x;
+            }
+        }
+      else
+        {
+          int cur_column = 0, t = 0, end, len;
+          x = 0;
+
+          if (a->column != 0)
+            {
+              if (fixed_pitch)
+                x += a->column * cxChar;
+              else
+                {
+                  GpiQueryCharStringPosAt (hps, &ptl, 0, a->column,
+                                           (PCH)p, NULL, aptl_line);
+                  x += aptl_line[a->column].x;
+                }
+              cur_column = a->column;
+            }
+
+          while (a != NULL && cur_column != column)
+            {
+              // TODO: Don't skip past font changes
+              while (a->next != NULL && a->next->el == a->el)
+                {
+                  if (a->el == E_TAB && a->next->column != EOL_COLUMN)
+                    t += a->next->column - a->column;
+                  a = a->next;
+                }
+
+              if (a->column == EOL_COLUMN || a->next == NULL)
+                end = line_len;
+              else
+                end = a->next->column;
+              if (column < end)
+                len = column - cur_column;
+              else
+                len = end - cur_column;
+              switch (a->el)
+                {
+                case E_TEXT:
+                  if (fixed_pitch)
+                    x += len * cxChar;
+                  else
+                    {
+                      GpiQueryCharStringPosAt (hps, &ptl, 0, len,
+                                               (PCH)p + cur_column, NULL,
+                                               aptl_line);
+                      x += aptl_line[len].x;
+                    }
+                  break;
+                case E_FILL:
+                  // TODO: Width specified in string (pixels)
+                  x += len * cxChar;
+                  break;
+                case E_VRULE:
+                  x += rule_width;
+                  break;
+                case E_TAB:
+                  t += len;
+                  x = tab_x[t-1];
+                  break;
+                default:
+                  break;
+                }
+              a = a->next;
+              cur_column += len;
+            }
+        }
+      cache_line = line; cache_column = column; cache_x = x;
+    }
+  pptl->x = x - x_off * cxChar;
+  pptl->y = cyClient - cyChar * (line + 1 - y_off);
+  return true;
+}
+
+
+// This is the reverse of get_bbox_pos()
+// TODO: Use cache
+
+void pmtxt::line_column_from_x_y (HPS hps, int *out_line, int *out_column,
+                                  int *out_tab, int x, int y)
+{
+  int line = (cyClient - 1 - y) / cyChar + y_off;
+  if (line >= 0 && line < lines_used)
+    {
+      *out_line = line;
+      pmtxt_line *pline = &lines_vector[line];
+      POINTL ptl;
+      ptl.x = -x_off * cxChar; ptl.y = 0;
+      if (x >= ptl.x)
+        {
+          const pmtxt_line_attr *a = pline->attr;
+          pmtxt_line_attr temp;
+          if (a == NULL || a->column > 0)
+            {
+              temp.el = E_TEXT;
+              temp.next = (pmtxt_line_attr *)a; // Remove `const'
+              temp.column = 0;
+              a = &temp;
+            }
+          int tab_index = 0;
+          while (a != NULL && a->column != EOL_COLUMN)
+            {
+              int len;
+              if (a->next != NULL && a->next->column != EOL_COLUMN)
+                len = a->next->column - a->column;
+              else
+                len = pline->len - a->column;
+              if (a->el == E_TEXT)
+                {
+                  if (fixed_pitch)
+                    {
+                      if (x < ptl.x + len * cxChar)
+                        {
+                          *out_column = a->column + (x - ptl.x) / cxChar;
+                          *out_tab = tab_index;
+                          return;
+                        }
+                      ptl.x += len * cxChar;
+                    }
+                  else
+                    {
+                      GpiQueryCharStringPosAt (hps, &ptl, 0, len,
+                                               (PCH)pline->str + a->column,
+                                               NULL, aptl_line);
+                      for (int i = 0; i < len; ++i)
+                        if (x < aptl_line[i+1].x)
+                          {
+                            *out_column = a->column + i;
+                            *out_tab = tab_index;
+                            return;
+                          }
+                      ptl.x = aptl_line[len].x;
+                    }
+                }
+              else if (a->el == E_VRULE)
+                {
+                  if (x < ptl.x + rule_width)
+                    {
+                      *out_column = a->column;
+                      *out_tab = tab_index;
+                      return;
+                    }
+                  ptl.x += rule_width;
+                }
+              else if (a->el == E_FILL)
+                {
+                  if (x < ptl.x + len * cxChar)
+                    {
+                      *out_column = a->column + (x - ptl.x) / cxChar;
+                      *out_tab = tab_index;
+                      return;
+                    }
+                  ptl.x += len * cxChar;
+                }
+              else if (a->el == E_TAB)
+                {
+                  if (x < tab_x[tab_index])
+                    {
+                      *out_column = a->column;
+                      *out_tab = tab_index;
+                      return;
+                    }
+                  ptl.x = tab_x[tab_index++] - x_off * cxChar;
+                }
+              a = a->next;
+            }
+        }
+    }
+  else
+    *out_line = -1; 
+  *out_column = -1;
+  *out_tab = -1;
+}
+
+
+// 
+// Add text
+//
+// Note that this function is not a no-op with LEN==0: it may add
+// an empty line at the end, for the cursor.
+
+void pmtxt::put (int line, int column, size_t len, const char *s,
+                 const pmtxt_attr &attr, element el, bool do_paint)
+{
+  int lines_added;
+
+  if (line < 0 || column < 0)
+    return;
+
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+
+  if (line >= lines_alloc)
+    more_lines (line + 1);
+
+  pmtxt_line *pline = &lines_vector[line];
+  int tlen = pline->len;
+
+  if (column > tlen)
+    {
+      unlock ();
+      return;
+    }
+
+  if (line >= lines_used)
+    {
+      lines_added = line + 1 - lines_used;
+      lines_used = line + 1;
+    }
+  else
+    lines_added = 0;
+
+  if (column + (int)len > max_line_len)
+    {
+      len = max_line_len - column;
+      if (len == 0)
+        {
+          unlock ();
+          return;
+        }
+    }
+  if (column + (int)len > pline->alloc)
+    {
+      int new_alloc = ((column + len + 39) / 40) * 40;
+      char *t = new char[new_alloc];
+      memcpy (t, pline->str, tlen);
+      delete[] pline->str;
+      pline->alloc = new_alloc;
+      pline->str = t;
+    }
+
+  char *target = pline->str;
+
+  memcpy (target + column, s, len);
+
+  if (len != 0)
+    {
+      if (column + (int)len > tlen)
+        pline->len = column + len;
+      change_attr (pline, column, column + (int)len, attr, el);
+      if (line == cache_line && column < cache_column)
+        cache_line = -1;
+    }
+
+  if (do_paint && !output_stopped)
+    {
+      if (lines_added != 0 && lines_used > window_lines)
+        {
+          if (y_off + lines_added == lines_used - window_lines)
+            {
+              y_off += lines_added;
+              bool paint_after_scroll = scroll_up (lines_added, false);
+              check_y_size ();
+              if (!paint_after_scroll)
+                {
+                  unlock ();
+                  return;
+                }
+            }
+          else
+            check_y_size ();
+        }
+
+      if (len != 0)
+        {
+          tab_repaint = false;
+          // TODO: Set do_paint to true only if required
+          painting (true);
+          paint (hpsClient, hpsClient_attr, line, column, true);
+          painting (false);
+          if (tab_repaint)
+            repaint ();
+        }
+    }
+  else
+    {
+      if (output_stopped && (lines_added || len != 0))
+        output_pending = true;
+    }
+
+  unlock ();
+}
+
+
+//
+// Change attributes of existing text
+//
+void pmtxt::put (int line, int column, size_t len, const pmtxt_attr &attr,
+                 bool do_paint)
+{
+  if (line < 0 || line >= lines_used || column < 0)
+    return;
+
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+
+  pmtxt_line *pline = &lines_vector[line];
+  int tlen = pline->len;
+  if (column + (int)len > tlen)
+    {
+      if (column >= tlen)
+        len = 0;
+      else
+        len = tlen - column;
+    }
+  if (len == 0)
+    {
+      unlock ();
+      return;
+    }
+
+  change_attr (pline, column, column + (int)len, attr, E_KEEP);
+
+  // TODO: Invalidate cache if font width changed
+
+  if (do_paint && !output_stopped)
+    {
+      tab_repaint = false;
+      painting (true);
+      paint (hpsClient, hpsClient_attr, line, column, true);
+      painting (false);
+      if (tab_repaint)
+        repaint ();
+    }
+  else
+    {
+      if (output_stopped)
+        output_pending = true;
+    }
+
+  unlock ();
+}
+
+
+void pmtxt::set_eol_attr (int line, const pmtxt_attr &attr, bool do_paint)
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  if (line >= 0 && line < lines_used)
+    {
+      pmtxt_line_attr **ppa;
+      for (ppa = &lines_vector[line].attr; *ppa != NULL; ppa = &(*ppa)->next)
+        if ((*ppa)->column == EOL_COLUMN)
+          break;
+      bool change = false;
+      if (*ppa == NULL)
+        {
+          if (!eq_attr (attr, default_attr))
+            {
+              pmtxt_line_attr *a = new pmtxt_line_attr;
+              a->next = NULL;
+              a->column = EOL_COLUMN;
+              a->el = E_FILL;
+              a->attr = attr;
+              *ppa = a;
+              change = true;
+            }
+        }
+      else
+        {
+          if (eq_attr (attr, default_attr))
+            {
+              pmtxt_line_attr *a = *ppa;
+              *ppa = NULL;
+              delete a;
+              change = true;
+            }
+          else if (!eq_attr (attr, (*ppa)->attr))
+            {
+              (*ppa)->attr = attr;
+              change = true;
+            }
+        }
+      if (change)
+        {
+          if (do_paint && !output_stopped)
+            {
+              POINTL ptl;
+              RECTL rcli;
+              if (!get_bbox_pos (hpsClient, &ptl, line,
+                                 lines_vector[line].len))
+                abort ();
+              rcli.xLeft = ptl.x; rcli.xRight = cxClient;
+              rcli.yBottom = ptl.y; rcli.yTop = ptl.y + cyChar;
+              painting (true);
+              WinFillRect (hpsClient, &rcli, attr.bg_color);
+              painting (false);
+            }
+          else
+            output_pending = true;
+        }
+    }
+  unlock ();
+}
+
+
+// TODO: underline off, underline to end of line, underline to width of window
+// TODO: attribute
+void pmtxt::underline (int line, bool on, bool do_paint)
+{
+  _fmutex_checked_request (&mutex, _FMR_IGNINT);
+  if (line >= 0 && line < lines_used
+      && (bool)(lines_vector[line].flags & LF_UNDERLINE) != on)
+    {
+      if (on)
+        lines_vector[line].flags |= LF_UNDERLINE;
+      else
+        lines_vector[line].flags &= ~LF_UNDERLINE;
+      if (do_paint && !output_stopped)
+        {
+          painting (true);
+          paint (hpsClient, hpsClient_attr, line, 0, true);
+          painting (false);
+        }
+    }
+  unlock ();
+}
+
+
+struct change_data
+{
+  pmtxt_line_attr **add;
+  pmtxt_line_attr *last;
+  pmtxt_attr cur_attr;
+  pmtxt::element cur_el;
+};
+
+
+void change_at (change_data &c, pmtxt_line_attr *a, int column,
+                const pmtxt_attr &attr, pmtxt::element el)
+{
+  if (column != EOL_COLUMN && eq_attr (attr, c.cur_attr) && el == c.cur_el)
+    {
+      if (a != NULL)
+        delete a;
+    }
+  else if (c.last != NULL && c.last->column == column)
+    {
+      c.last->attr = attr;
+      c.last->el = el;
+      c.cur_attr = attr;
+      c.cur_el = el;
+      if (a != NULL)
+        delete a;
+    }
+  else
+    {
+      if (a == NULL)
+        a = new pmtxt_line_attr;
+      a->next = NULL;
+      a->column = column;
+      a->attr = attr;
+      a->el = el;
+      c.cur_attr = attr;
+      c.cur_el = el;
+      c.last = a;
+      *c.add = a;
+      c.add = &a->next;
+    }
+}
+
+
+// TODO: Optimize to avoid copying/writing
+
+void pmtxt::change_attr (pmtxt_line *p, int start, int end,
+                         const pmtxt_attr &new_attr, element new_el)
+{
+  pmtxt_line_attr *new_list, *a, *next;
+  pmtxt_attr prev_attr;
+  element prev_el;
+  change_data c;
+
+  new_list = NULL;
+  c.add = &new_list;
+  c.last = NULL;
+  c.cur_attr = default_attr;
+  c.cur_el = E_TEXT;
+
+  a = p->attr;
+  while (a != NULL && a->column < start)
+    {
+      next = a->next;
+      change_at (c, a, a->column, a->attr, a->el);
+      a = next;
+    }
+
+  prev_attr = c.cur_attr; prev_el = c.cur_el;
+  if (a == NULL)
+    change_at (c, NULL, start, new_attr,
+               new_el != E_KEEP ? new_el : c.cur_el);
+  else if (new_el == E_KEEP)
+    {
+      change_at (c, NULL, start, new_attr, c.cur_el);
+      while (a != NULL && a->column < end)
+        {
+          next = a->next;
+          change_at (c, a, a->column, new_attr, a->el);
+          a = next;
+        }
+    }
+  else
+    {
+      if (a->column == start)
+        {
+          prev_attr = a->attr; prev_el = a->el;
+          next = a->next;
+          change_at (c, a, start, new_attr, new_el);
+          a = next;
+        }
+      else
+        {
+          // TODO: if a->column < end, we can reuse the node
+          change_at (c, NULL, start, new_attr, new_el);
+        }
+      while (a != NULL && a->column < end)
+        {
+          next = a->next;
+          prev_attr = a->attr; prev_el = a->el;
+          delete a;
+          a = next;
+        }
+    }
+
+  if (a == NULL || a->column != end)
+    change_at (c, NULL, end, prev_attr, prev_el);
+
+  while (a != NULL)
+    {
+      next = a->next;
+      change_at (c, a, a->column, a->attr, a->el);
+      a = next;
+    }
+
+  p->attr = new_list;
+
+  int t = 0, i;
+   for (a = p->attr; a != NULL; a = a->next)
+    ++t;
+  if (t > tab_x_size)
+    {
+      tab_x_size = t + 16;
+      int *new_x = new int[tab_x_size];
+      for (i = 0; i < tab_count; ++i)
+        new_x[i] = tab_x[i];
+      delete[] tab_x;
+      tab_x = new_x;
+    }
+  if (t > tab_count)
+    {
+      for (i = tab_count; i < t; ++i)
+        tab_x[i] = 0;
+      tab_count = t;
+    }
+}
Index: trunk/src/emx/src/pmgdb/pmtxt.h
===================================================================
--- trunk/src/emx/src/pmgdb/pmtxt.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/pmtxt.h	(revision 18)
@@ -0,0 +1,234 @@
+/* pmtxt.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+
+struct pmtxt_line;
+struct pmtxt_line_attr;
+
+struct pmtxt_attr
+{
+  COLOR fg_color;
+  COLOR bg_color;
+};
+
+
+// A frame window showing scrollable text
+
+class pmtxt : public pmframe
+{
+public:
+
+  typedef pmframe parent;
+
+  // Constructors and destructors, initialization
+  pmtxt (pmapp *app, unsigned id, ULONG frame_flags, const SWP *pswp,
+         const char *fontnamesize = 0);
+  virtual ~pmtxt ();
+  virtual void delete_all ();
+
+  // Painting
+  void put (int line, int column, size_t len, const char *s,
+            const pmtxt_attr &attr, bool do_paint)
+    { put (line, column, len, s, attr, E_TEXT, do_paint); }
+  void put (int line, int column, size_t len, const char *s, bool do_paint)
+    { put (line, column, len, s, default_attr, E_TEXT, do_paint); }
+  void put_vrule (int line, int column, const pmtxt_attr &attr, bool do_paint)
+    { put (line, column, 1, "", attr, E_VRULE, do_paint); }
+  void put_vrule (int line, int column, bool do_paint)
+    { put_vrule (line, column, default_attr, do_paint); }
+  void put_tab (int line, int column, const pmtxt_attr &attr, bool do_paint)
+    { put (line, column, 1, " ", attr, E_TAB, do_paint); }
+  void put_tab (int line, int column, bool do_paint)
+    { put_tab (line, column, default_attr, do_paint); }
+  void underline (int line, bool on, bool do_paint);
+  void sync ();
+  void show_line (int line, int threshold = 0, int overshoot = 0);
+  void delete_lines (int line, int count, bool do_paint);
+  void insert_lines (int line, int count, bool do_paint);
+  void clear_lines (int line, int count, bool do_paint);
+  void truncate_line (int line, int count, bool do_paint);
+
+  // Attributes
+  void set_fg_color (pmtxt_attr &attr, COLOR color)
+    { attr.fg_color = color; }
+  void set_fg_color (pmtxt_attr &attr)
+    { attr.fg_color = default_attr.fg_color; }
+  COLOR get_fg_color (pmtxt_attr const &attr) const
+    { return attr.fg_color; }
+
+  void set_bg_color (pmtxt_attr &attr, COLOR color)
+    { attr.bg_color = color; }
+  void set_bg_color (pmtxt_attr &attr)
+    { attr.bg_color = default_attr.bg_color; }
+  COLOR get_bg_color (pmtxt_attr const &attr) const
+    { return attr.bg_color; }
+
+  const pmtxt_attr &get_default_attr () const { return default_attr; }
+
+  void put (int line, int column, size_t len, const pmtxt_attr &attr,
+            bool do_paint);
+  void set_eol_attr (int line, const pmtxt_attr &attr, bool do_paint);
+  void clear_tabs ();
+  void set_font (const pmtxt &s);
+
+  // Querying window contents
+  int get_char (int line, int column);
+  bool get_string (int line, int column, char *str, size_t count);
+  int get_window_lines () const { return window_lines; }
+
+  // Constants
+
+  enum
+  {
+    max_line_len = 512          // See GpiCharString
+  };
+
+protected:
+
+  // Types
+
+  enum element
+  {
+    E_KEEP,
+    E_TEXT,
+    E_VRULE,
+    E_FILL,
+    E_TAB
+  };
+
+  // Messages
+  MRESULT wm_button (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_create (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_hscroll (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_presparamchanged (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_querytrackinfo (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_size (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_vscroll (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual bool wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  virtual void button_event (int line, int column, int tab, int button,
+                             int clicks);
+
+  // Painting
+  bool get_bbox_pos (HPS hps, POINTL *pptl, int line, int column);
+  void put (int line, int column, size_t len, const char *s,
+            const pmtxt_attr &attr, element el, bool do_paint);
+
+  // Notifications for derived classes
+  virtual void painting (bool start);
+  virtual void font_changed ();
+
+  // Querying members
+  int get_cyChar () const { return cyChar; }
+  int get_cyDesc () const { return cyDesc; }
+  int get_cxChar () const { return cxChar; }
+  HWND get_hwndHbar () const { return hwndHbar; }
+  HWND get_hwndVbar () const { return hwndVbar; }
+  bool get_initializing_font () const { return initializing_font; }
+
+  bool font_dialog ();
+  void set_font (HPS hps);
+
+  // Data members
+
+  bool output_stopped;
+  bool output_pending;
+
+private:
+
+  // Messages
+  MRESULT wm_paint (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT button_event (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2,
+                        int button, int clicks);
+
+  // Painting
+  bool scroll_up (int n, bool do_paint);
+  void scroll_down (int n);
+  void check_x_size ();
+  void check_y_size ();
+  void disable_output ();
+  void enable_output ();
+  void change_attr (pmtxt_line *p, int start, int end,
+                    const pmtxt_attr &new_attr, element new_el);
+  void setup_ps (HPS hps);
+  void create_hpsClient ();
+  void get_fontmetrics ();
+  void change_size ();
+  void paint (HPS hps, pmtxt_attr &cur_attr, int line, int column,
+              bool paint_eol);
+  void paint (HPS hps, pmtxt_attr &cur_attr, const pmtxt_line_attr *pla,
+              const char *p, int len);
+
+  void unlock ();
+  void more_lines (int new_count);
+  void free_line (int line);
+  void init_line (int line);
+  void delete_attr (pmtxt_line_attr *a);
+  void pmthread_perform ();
+  void pmthread_request (unsigned char bits);
+  void line_column_from_x_y (HPS hps, int *line, int *column, int *tab,
+                             int x, int y);
+
+  // Data members
+
+  HWND hwndVbar;
+  HWND hwndHbar;
+  HPS hpsClient;
+  LONG cxClient;
+  LONG cyClient;
+  int cxChar;
+  int cyChar;
+  int cyDesc;
+  int rule_width;
+  int window_lines, window_columns;
+  bool track;
+  int x_off, y_off;
+  int x_pos, max_x_pos;
+  int lines_used;
+  int lines_alloc;
+  pmtxt_line *lines_vector;
+  _fmutex mutex;
+  unsigned char pmthread_pending;
+
+  // TABs
+  int tab_count;                // Number of active TABs
+  int tab_x_size;               // Size of following array
+  int *tab_x;                   // X coordinates of TABs
+  bool tab_repaint;             // X coordinate of a TAB changed, repaint!
+  int tab_index;                // Current TAB index (temporary)
+
+  pmtxt_attr default_attr;      // In effect at start of each line
+  pmtxt_attr hpsClient_attr;    // Current attributes of hpsClient
+
+  int cache_line;               // Input
+  int cache_column;             // Input
+  int cache_x;                  // Output
+
+  bool fixed_pitch;
+
+  POINTL *aptl_line;
+
+  FATTRS fattrs;
+  bool default_font;
+  const char *init_fontnamesize;
+  bool initializing_font;
+};
Index: trunk/src/emx/src/pmgdb/register.cc
===================================================================
--- trunk/src/emx/src/pmgdb/register.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/register.cc	(revision 18)
@@ -0,0 +1,154 @@
+/* register.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "pmgdb.h"
+#include "help.h"
+#include "breakpoi.h"
+#include "register.h"
+#include "command.h"
+
+
+register_window::register_window (command_window *in_cmd, unsigned in_id,
+                                  const SWP *pswp, const char *fontnamesize)
+  : pmtxt (in_cmd->get_app (), in_id,
+           pswp == NULL ? FCF_SHELLPOSITION : 0, pswp, fontnamesize)
+{
+  cmd = in_cmd;
+
+  int x = 0;
+  put (0, x, 6, " Reg ", true); x += 6;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 5, " Hex ", true); x += 5;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 5, " Dec ", true); x += 5;
+  underline (0, true, true);
+
+  set_title ("pmgdb - Registers");
+  set_keys_help_id (HELP_REG_KEYS);
+}
+
+
+register_window::~register_window ()
+{
+}
+
+
+MRESULT register_window::wm_close (HWND, ULONG, MPARAM, MPARAM)
+{
+  show (false);
+  return 0;
+}
+
+
+MRESULT register_window::wm_command (HWND hwnd, ULONG msg,
+                                     MPARAM mp1, MPARAM mp2)
+{
+  switch (SHORT1FROMMP (mp1))
+    {
+    case IDM_REFRESH:
+      cmd->update_registers ();
+      return 0;
+    }
+  return cmd->wm_command (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT register_window::wm_activate (HWND hwnd, ULONG msg,
+                                          MPARAM mp1, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp1))
+    cmd->associate_help (get_hwndFrame ());
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+#define WHITE(c) ((c) == ' ' || (c) == '\t')
+
+void register_window::update (const char *s)
+{
+  char buf[20];
+  buf[0] = ' ';
+  int line = 1;
+  while (*s != 0)
+    {
+      int len = 0;
+      while (s[len] != 0 && !WHITE (s[len]))
+        ++len;
+      if (!WHITE (s[len]))
+        break;
+      int x = 0;
+      memcpy (buf + 1, s, len);
+      buf[len+1] = ' ';
+      put (line, x, len + 2, buf, true); x += len + 2;
+      put_tab (line, x++, true);
+      put_vrule (line, x++, true);
+      s += len;
+      while (WHITE (*s))
+        ++s;
+      if (*s++ != '0' || *s++ != 'x')
+        break;
+      len = 0;
+      while (s[len] != 0 && !WHITE (s[len]))
+        ++len;
+      if (!WHITE (s[len]) || len > 8)
+        break;
+      memset (buf + 1, '0', 7);
+      memcpy (buf + 1 + 8 - len, s, len);
+      buf[9] = ' ';
+      put (line, x, 10, buf, true); x += 10;
+      put_tab (line, x++, true);
+      put_vrule (line, x++, true);
+      s += len;
+      while (WHITE (*s))
+        ++s;
+      len = 0;
+      while (s[len] != 0 && s[len] != '\n')
+        ++len;
+      if (s[len] != '\n')
+        break;
+      if (s[0] == '0' && s[1] == 'x')
+        {
+          long n = strtol (s + 2, NULL, 16);
+          int len2 = strlen (_ltoa (n, buf + 1, 10));
+          put (line, x, len2 + 1, buf, true); x += len2 + 1;
+        }
+      else
+        {
+          memcpy (buf + 1, s, len);
+          put (line, x, len + 1, buf, true); x += len + 1;
+        }
+      truncate_line (line, x, true);
+      ++line;
+      s += len + 1;
+    }
+}
Index: trunk/src/emx/src/pmgdb/register.h
===================================================================
--- trunk/src/emx/src/pmgdb/register.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/register.h	(revision 18)
@@ -0,0 +1,43 @@
+/* register.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class command_window;
+
+class register_window : public pmtxt
+{
+public:
+
+  typedef pmtxt parent;
+
+  // Constructors and destructors
+  register_window (command_window *cmd, unsigned id, const SWP *pswp,
+                   const char *fontnamesize);
+  ~register_window ();
+  void update (const char *s);
+
+private:
+  // Override member functions of pmframe
+  MRESULT wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+  command_window *cmd;
+};
Index: trunk/src/emx/src/pmgdb/source.cc
===================================================================
--- trunk/src/emx/src/pmgdb/source.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/source.cc	(revision 18)
@@ -0,0 +1,610 @@
+/* source.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_WIN
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <fcntl.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "pmgdb.h"
+#include "help.h"
+#include "breakpoi.h"
+#include "source.h"
+#include "display.h"
+#include "annotati.h"
+#include "capture.h"
+#include "gdbio.h"
+#include "command.h"
+
+#define LINENO_WIDTH    6
+#define SOURCE_COLUMN   (LINENO_WIDTH + 4)
+
+source_window::source_window (pmapp *in_app, unsigned in_id,
+                              const char *fontnamesize,
+                              const char *short_fname, const char *long_fname,
+                              command_window *in_cmd, gdbio *in_gdb)
+  : pmtxt (in_app, in_id, FCF_SHELLPOSITION, NULL, fontnamesize)
+{
+  cmd = in_cmd; gdb = in_gdb;
+  short_filename = short_fname;
+  long_filename = long_fname;
+
+  astring title;
+  title = "pmgdb - ";
+  title.append (short_filename);
+  set_title (title);
+
+  set_keys_help_id (HELP_SRC_KEYS);
+
+  hilite_attr = get_default_attr ();
+  set_fg_color (hilite_attr, CLR_WHITE);
+  set_bg_color (hilite_attr, CLR_BLACK);
+
+  sel_attr = get_default_attr ();
+  set_fg_color (sel_attr, CLR_BLACK);
+  set_bg_color (sel_attr, CLR_PALEGRAY);
+
+  bpt_attr = get_default_attr ();
+  set_fg_color (bpt_attr, CLR_WHITE);
+  set_bg_color (bpt_attr, CLR_RED);
+
+  sel_bpt_attr = get_default_attr ();
+  set_fg_color (sel_bpt_attr, CLR_WHITE);
+  set_bg_color (sel_bpt_attr, CLR_PINK);
+
+  // Initialize menu
+  WinPostMsg (get_hwndClient (), UWM_STATE, MPFROMLONG (~0), 0);
+
+  load ();
+  set_font (*cmd);
+  show (true);
+}
+
+
+source_window::~source_window ()
+{
+}
+
+
+void source_window::load ()
+{
+  char buf[max_line_len+2];     // Line read from source file
+  char pfx[10];                 // Line number
+  int c;
+
+  delete_all ();
+  cur_lineno = -1; sel_lineno = -1;
+  exp_lineno = -1; find_string = "";
+  menu_enable (IDM_FINDNEXT, false);
+  menu_enable (IDM_FINDPREV, false);
+
+  FILE *f = fopen (long_filename, "r");
+  if (f == NULL)
+    {
+      // TODO: Use GDB's value of `set directory'
+      // TODO: Dialog box, asking for file name
+      strcpy (buf, "Cannot open file");
+      put (0, 0, strlen (buf), buf, true);
+    }
+  else
+    {
+      int y = 0;
+      while (fgets (buf, sizeof (buf), f) != NULL)
+        {
+          size_t len = strlen (buf);
+          if (len > 0 && buf[len-1] == '\n')
+            --len;
+          else
+            {
+              // Line too long, skip rest
+              do
+                {
+                  c = fgetc (f);
+                } while (c != EOF && c != '\n');
+            }
+
+          // Insert line number
+          int pfx_len = sprintf (pfx, "%*d    ", LINENO_WIDTH, y + 1);
+          put (y, 0, pfx_len, pfx, false);
+          put_tab (y, LINENO_WIDTH + 1, false);
+          put_vrule (y, LINENO_WIDTH + 2, false);
+
+          // Insert source line
+          char *tab = (char *)memchr (buf, '\t', len);
+          if (tab == NULL)
+            put (y, SOURCE_COLUMN, len, buf, false);
+          else
+            {
+              // Expand TABs
+              int x = 0;
+              size_t i = 0;
+              while (tab != NULL)
+                {
+                  size_t copy = tab - (buf + i);
+                  if (copy != 0)
+                    {
+                      put (y, SOURCE_COLUMN + x, copy, buf + i, false);
+                      i += copy; x += copy;
+                    }
+                  int tab_width = (x | 7) + 1 - x;
+                  put (y, SOURCE_COLUMN + x, tab_width, "        ", false);
+                  ++i; x += tab_width;
+                  tab = (char *)memchr (buf + i, '\t', len - i);
+                }
+              if (i < len)
+                put (y, SOURCE_COLUMN + x, len - i, buf + i, false);
+            }
+          ++y;
+        }
+      // TODO: ferror()
+      fclose (f);
+    }
+  cmd->get_breakpoints (this, false);
+}
+
+
+void source_window::show_line (int lineno)
+{
+  if (lineno != cur_lineno)
+    {
+      if (cur_lineno != -1)
+        {
+          put (cur_lineno - 1, SOURCE_COLUMN - 1, max_line_len,
+               get_default_attr (), true);
+          set_eol_attr (cur_lineno - 1, get_default_attr (), true);
+        }
+      if (lineno != -1)
+        {
+          put (lineno - 1, SOURCE_COLUMN - 1, max_line_len, hilite_attr, true);
+          set_eol_attr (lineno - 1, hilite_attr, true);
+        }
+      cur_lineno = lineno;
+      if (lineno == exp_lineno)
+        exp_lineno = -1;
+    }
+  if (lineno != -1)
+    parent::show_line (lineno - 1, 1, get_window_lines () * 2 / 3);
+}
+
+
+void source_window::select_line (int lineno)
+{
+  if (lineno != sel_lineno)
+    {
+      if (sel_lineno != -1)
+        {
+          const breakpoint *bpt
+            = cmd->breakpoints.find (short_filename, sel_lineno);
+          put (sel_lineno - 1, 0, LINENO_WIDTH + 2,
+               bpt != NULL ? bpt_attr : get_default_attr (), true);
+        }
+      if (lineno != -1)
+        {
+          const breakpoint *bpt
+            = cmd->breakpoints.find (short_filename, lineno);
+          put (lineno - 1, 0, LINENO_WIDTH + 2,
+               bpt != NULL ? sel_bpt_attr : sel_attr, true);
+        }
+      sel_lineno = lineno;
+    }
+}
+
+
+ULONG source_window::selected_addr ()
+{
+  if (sel_lineno == -1)
+    return 0;
+  return gdb->address_of_line (short_filename, sel_lineno);
+}
+
+
+MRESULT source_window::goto_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  char buf[80];
+
+  switch (msg)
+    {
+    case WM_INITDLG:
+      dlg_sys_menu (hwnd);
+      WinSetWindowPtr (hwnd, QWL_USER, this);
+      break;
+
+    case WM_COMMAND:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case DID_OK:
+          WinQueryDlgItemText (hwnd, IDC_LINENO, sizeof (buf), (PSZ)buf);
+          int lineno = atoi (buf);
+          if (lineno > 0)
+            parent::show_line (lineno - 1, 1, get_window_lines () / 2);
+          WinDismissDlg (hwnd, DID_OK);
+          return 0;
+        }
+      break;
+    }
+  return WinDefDlgProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY dlg_goto (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  source_window *p;
+
+  if (msg == WM_INITDLG)
+    p = (source_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
+  else
+    p = (source_window *)WinQueryWindowPtr (hwnd, QWL_USER);
+  return p->goto_msg (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT source_window::find_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  char buf[200];
+
+  switch (msg)
+    {
+    case WM_INITDLG:
+      dlg_sys_menu (hwnd);
+      WinSendDlgItemMsg (hwnd, IDC_STRING, EM_SETTEXTLIMIT,
+                         MPFROMSHORT (sizeof (buf) - 1), 0);
+      WinSetDlgItemText (hwnd, IDC_STRING, (PCSZ)find_string);
+      WinSetWindowPtr (hwnd, QWL_USER, this);
+      break;
+
+    case WM_COMMAND:
+      switch (SHORT1FROMMP (mp1))
+        {
+        case DID_OK:
+          WinQueryDlgItemText (hwnd, IDC_STRING, sizeof (buf), (PSZ)buf);
+          if (buf[0] != 0)
+            {
+              find_string = buf;
+              WinDismissDlg (hwnd, DID_OK);
+            }
+          else
+            WinDismissDlg (hwnd, DID_CANCEL);
+          return 0;
+        }
+      break;
+    }
+  return WinDefDlgProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT EXPENTRY dlg_find (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  source_window *p;
+
+  if (msg == WM_INITDLG)
+    p = (source_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
+  else
+    p = (source_window *)WinQueryWindowPtr (hwnd, QWL_USER);
+  return p->find_msg (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT source_window::wm_activate (HWND hwnd, ULONG msg,
+                                    MPARAM mp1, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp1))
+    cmd->associate_help (get_hwndFrame ());
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT source_window::wm_char (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  if ((SHORT1FROMMP (mp1) & (KC_VIRTUALKEY|KC_KEYUP)) == KC_VIRTUALKEY)
+    {
+      HWND hwndTarget = NULLHANDLE;
+      switch (SHORT2FROMMP (mp2))
+        {
+        case VK_UP:
+        case VK_DOWN:
+          hwndTarget = get_hwndVbar ();
+          break;
+
+        case VK_PAGEUP:
+        case VK_PAGEDOWN:
+          if (SHORT1FROMMP (mp1) & KC_CTRL)
+            hwndTarget = get_hwndHbar ();
+          else
+            hwndTarget = get_hwndVbar ();
+          break;
+
+        case VK_LEFT:
+        case VK_RIGHT:
+          hwndTarget = get_hwndHbar ();
+          break;
+        }
+      if (hwndTarget != NULLHANDLE && WinIsWindowEnabled (hwndTarget))
+        WinPostMsg (hwndTarget, msg, mp1, mp2);
+    }
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT source_window::wm_command (HWND hwnd, ULONG msg,
+                                   MPARAM mp1, MPARAM mp2)
+{
+  ULONG addr;
+  pm_create create;
+
+  switch (SHORT1FROMMP (mp1))
+    {
+    case IDM_GOTO:
+      create.cb = sizeof (create);
+      create.ptr = (void *)this;
+      WinDlgBox (HWND_DESKTOP, get_hwndClient (), dlg_goto, 0, IDD_GOTO,
+                 &create);
+      return 0;
+
+    case IDM_FIND:
+      create.cb = sizeof (create);
+      create.ptr = (void *)this;
+      if (WinDlgBox (HWND_DESKTOP, get_hwndClient (), dlg_find, 0, IDD_FIND,
+                     &create) == DID_OK)
+        find (true, true);
+      return 0;
+
+    case IDM_FINDNEXT:
+      find (false, true);
+      return 0;
+
+    case IDM_FINDPREV:
+      find (false, false);
+      return 0;
+
+    case IDM_JUMP:
+      // TODO: Don't do this in the PM thread (time!)
+      addr = selected_addr ();
+      if (addr == 0 || !gdb->call_cmd ("server set var $pc=0x%lx", addr))
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        cmd->where ();
+      return 0;
+
+    case IDM_UNTIL:
+      // TODO: Don't do this in the PM thread (time!)
+      addr = selected_addr ();
+      if (addr == 0)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        {
+          gdb->prepare_run ();
+          gdb->send_cmd ("server until *0x%lx", addr);
+        }
+      return 0;
+
+    case IDM_DSP_SHOW:
+      cmd->dsp->show (true);
+      return 0;
+
+    case IDM_DSP_ADD:
+      if (cmd->dsp->add (hwnd))
+        cmd->dsp->show (true);
+      return 0;
+
+    case IDM_BRKPT_LINE:
+      cmd->brk->add_line (short_filename, sel_lineno);
+      return 0;
+
+    default:
+      return cmd->wm_command (hwnd, msg, mp1, mp2);
+    }
+}
+
+
+bool source_window::wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  unsigned change;
+
+  if (parent::wm_user (hwnd, msg, mp1, mp2))
+    return true;
+  switch (msg)
+    {
+    case UWM_STATE:
+      change = LONGFROMMP (mp1);
+      if (change & command_window::GSC_PROMPT)
+        menu_enable (IDM_RUNMENU, gdb->is_ready ());
+      if (change & command_window::GSC_RUNNING)
+        {
+          if (gdb->is_nochild ())
+            show_line (-1);
+          // TODO: IDM_GO
+          bool running = !gdb->is_nochild ();
+          menu_enable (IDM_STEPOVER, running);
+          menu_enable (IDM_STEPINTO, running);
+          menu_enable (IDM_ISTEPOVER, running);
+          menu_enable (IDM_ISTEPINTO, running);
+          // TODO:
+          menu_enable (IDM_UNTIL, running);
+          menu_enable (IDM_JUMP, running);
+          menu_enable (IDM_FINISH, running);
+        }
+      if (change & command_window::GSC_EXEC_FILE)
+        {
+          menu_enable (IDM_RESTART, cmd->get_debuggee () != NULL);
+          menu_enable (IDM_GO, cmd->get_debuggee () != NULL);
+        }
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+
+MRESULT source_window::wm_close (HWND, ULONG, MPARAM, MPARAM)
+{
+  WinPostMsg (cmd->get_hwndClient (), UWM_CLOSE_SRC, MPFROMP (this), 0);
+  return 0;
+}
+
+
+static bool is_symbol (int c)
+{
+  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
+}
+
+
+void source_window::button1_lineno (int line, int clicks)
+{
+  int lineno = line + 1;
+  if (clicks == 0)
+    {
+      if (lineno == sel_lineno)
+        select_line (-1);
+      else
+        select_line (lineno);
+    }
+  else if (clicks == 2)
+    {
+      const breakpoint *brk
+        = cmd->breakpoints.find (short_filename, lineno);
+      // TODO: enabled/disabled
+      if (brk != NULL)
+        gdb->send_cmd ("server delete %d", brk->get_number ());
+      else
+        gdb->send_cmd ("server break %s:%d",
+                       (const char *)short_filename, lineno);
+    }
+}
+
+
+void source_window::button1_source (int line, int column, int clicks)
+{
+  if (clicks == 2)
+    {
+      if (exp_lineno != -1)
+        {
+          put (exp_lineno - 1, exp_column, exp_len,
+               exp_lineno == cur_lineno ? hilite_attr : get_default_attr (),
+               true);
+          exp_lineno = -1;
+        }
+      if (is_symbol (get_char (line, column)))
+        {
+          int start = column;
+          while (start > 0)
+            {
+              int c = get_char (line, start - 1);
+              if (is_symbol (c))
+                --start;
+              // TODO: blanks
+              else if (c == '.'
+                       && is_symbol (get_char (line, start - 2)))
+                start -= 2;
+              // TODO: blanks
+              else if (c == '>'
+                       && get_char (line, start - 2) == '-'
+                       && is_symbol (get_char (line, start - 3)))
+                start -= 3;
+              else
+                break;
+            }
+          int end = column + 1;
+          for (;;)
+            {
+              int c = get_char (line, end);
+              if (is_symbol (c) || (c >= '0' && c <= '9'))
+                ++end;
+              else
+                break;
+            }
+          char *buf = (char *)alloca (end - start + 1);
+          if (get_string (line, start, buf, end - start))
+            {
+              exp_lineno = line + 1;
+              exp_column = start; exp_len = end - start;
+              put (line, start, exp_len, sel_attr, true);
+              // TODO: Context (class, function, ...)
+              gdb->send_cmd ("server display %s", buf);
+              cmd->dsp->show (true);
+            }
+        }
+    }
+}
+
+
+void source_window::button_event (int line, int column, int, int button,
+                                  int clicks)
+{
+  if (line >= 0 && column >= 0 && button == 1)
+    {
+      // TODO: Context menu (run editor, set/edit breakpoint, ...)
+      if (column < LINENO_WIDTH + 2)
+        button1_lineno (line, clicks);
+      else if (column >= SOURCE_COLUMN - 1)
+        button1_source (line, column, clicks);
+    }
+}
+
+
+void source_window::set_breakpoint (int lineno, bool set, bool paint)
+{
+  put (lineno - 1, 0, LINENO_WIDTH + 2,
+       set ? bpt_attr : lineno == sel_lineno ? sel_attr : get_default_attr (),
+       paint);
+}
+
+
+// TODO: Don't do this in the PM thread
+
+void source_window::find (bool start, bool forward)
+{
+  capture *capt = gdb->capture_cmd ("server list %s:%d,1",
+                                    (const char *)short_filename,
+                                    start ? 1 : find_lineno);
+  delete_capture (capt);
+  capt = gdb->capture_cmd ("server %s %s",
+                           forward ? "search" : "reverse-search",
+                           (const char *)find_string);
+  long n;
+  if (capt != NULL && (n = strtol (gdb->get_output (), NULL, 10)) >= 1)
+    {
+      find_lineno = (int)n;
+      select_line ((int)n);
+      parent::show_line (n - 1, 1, get_window_lines () / 2);
+      menu_enable (IDM_FINDNEXT, true);
+      menu_enable (IDM_FINDPREV, !start);
+    }
+  else
+    {
+      WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
+                     (PSZ)"Not found.", (PSZ)"pmgdb", 0,
+                     MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
+      if (forward || start)
+        menu_enable (IDM_FINDNEXT, false);
+      if (!forward || start)
+        menu_enable (IDM_FINDPREV, false);
+    }
+  delete_capture (capt);
+}
Index: trunk/src/emx/src/pmgdb/source.h
===================================================================
--- trunk/src/emx/src/pmgdb/source.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/source.h	(revision 18)
@@ -0,0 +1,81 @@
+/* source.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class command_window;
+class gdbio;
+
+class source_window : public pmtxt
+{
+public:
+
+  typedef pmtxt parent;
+
+  // Constructors and destructors
+  source_window (pmapp *app, unsigned id, const char *fontnamesize,
+                 const char *short_fname, const char *long_fname,
+                 command_window *cmd, gdbio *gdb);
+  ~source_window ();
+
+  // Painting
+  void show_line (int lineno);
+  void select_line (int lineno);
+  ULONG selected_addr ();
+  void set_breakpoint (int lineno, bool set, bool paint);
+
+  // Querying members
+  const char *get_short_filename () const { return short_filename; }
+  const char *get_long_filename () const { return long_filename; }
+
+  // Dialog box
+  MRESULT goto_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT find_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+
+private:
+  void load ();
+  void button1_lineno (int line, int clicks);
+  void button1_source (int line, int column, int clicks);
+  void find (bool start, bool forward);
+
+  // Override member functions of pmframe
+  bool wm_user (HWND, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_char (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  void button_event (int line, int column, int tab, int button, int clicks);
+
+  command_window *cmd;
+  gdbio *gdb;
+  fstring short_filename;       // File name of source file (symtab)
+  fstring long_filename;        // Path name of source file
+  int cur_lineno;               // Current line# (1-based) or -1
+  int sel_lineno;               // Selected line# (1-based) or -1
+  pmtxt_attr hilite_attr;       // Attribute used for hilighting current line
+  pmtxt_attr sel_attr;          // Attribute used for hilighting selection
+  pmtxt_attr bpt_attr;          // Attribute used for breakpoints
+  pmtxt_attr sel_bpt_attr;      // Select and breakpoint
+
+  int exp_lineno, exp_column;
+  size_t exp_len;
+
+  int find_lineno;
+  vstring find_string;
+};
Index: trunk/src/emx/src/pmgdb/srcfiles.cc
===================================================================
--- trunk/src/emx/src/pmgdb/srcfiles.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/srcfiles.cc	(revision 18)
@@ -0,0 +1,219 @@
+/* srcfiles.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_DOS
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "pmgdb.h"
+#include "help.h"
+#include "breakpoi.h"
+#include "srcfiles.h"
+#include "command.h"
+
+
+source_files_window::source_files_window (command_window *in_cmd,
+                                          unsigned in_id, const SWP *pswp,
+                                          const char *fontnamesize)
+  : pmtxt (in_cmd->get_app (), in_id,
+           pswp == NULL ? FCF_SHELLPOSITION : 0, pswp, fontnamesize)
+{
+  cmd = in_cmd;
+  head = NULL;
+  lines = 0; sel_line = -1;
+  set_title ("pmgdb - Source Files");
+  set_keys_help_id (HELP_SRCS_KEYS);
+
+  sel_attr = get_default_attr ();
+  set_fg_color (sel_attr, CLR_BLACK);
+  set_bg_color (sel_attr, CLR_PALEGRAY);
+}
+
+
+source_files_window::~source_files_window ()
+{
+  delete_all ();
+}
+
+
+MRESULT source_files_window::wm_close (HWND, ULONG, MPARAM, MPARAM)
+{
+  show (false);
+  return 0;
+}
+
+
+MRESULT source_files_window::wm_command (HWND hwnd, ULONG msg,
+                                         MPARAM mp1, MPARAM mp2)
+{
+  return cmd->wm_command (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT source_files_window::wm_activate (HWND hwnd, ULONG msg,
+                                          MPARAM mp1, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp1))
+    cmd->associate_help (get_hwndFrame ());
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+void source_files_window::button_event (int line, int column, int, int button,
+                                        int clicks)
+{
+  if (line >= 0 && column >= 0)
+    {
+      // TODO: Context menu
+      if (button == 1 && clicks == 1)
+        select_line (line, true);
+      else if (button == 1 && clicks == 2)
+        {
+          const srcs_node *p = find_by_line (line);
+          if (p == NULL)
+            WinAlarm (HWND_DESKTOP, WA_ERROR);
+          else
+            cmd->show_source (p->fname, NULL, true);
+          select_line (line);
+        }
+      else
+        select_line (-1);
+    }
+  else
+    select_line (-1);
+}
+
+
+source_files_window::srcs_node *source_files_window::find_by_line (int line)
+{
+  for (srcs_node *p = head; p != NULL; p = p->next)
+    if (line == 0)
+      return p;
+    else
+      --line;
+  return NULL;
+}
+
+
+void source_files_window::add (const char *fname)
+{
+  srcs_node *p = new srcs_node;
+  p->next = head;
+  p->fname = fname;
+  head = p;
+  ++lines;
+}
+
+
+static int compare (const void *p1, const void *p2)
+{
+  const source_files_window::srcs_node *n1
+    = *((source_files_window::srcs_node **)p1);
+  const source_files_window::srcs_node *n2
+    = *((source_files_window::srcs_node **)p2);
+  return _fncmp ((const unsigned char *)_getname (n1->fname),
+                 (const unsigned char *)_getname (n2->fname));
+}
+
+
+void source_files_window::done ()
+{
+  int i;
+  srcs_node *p;
+
+  if (lines > 1)
+    {
+      srcs_node **vector = new srcs_node *[lines];
+      i = 0;
+      for (p = head; p != NULL; p = p->next)
+        vector[i++] = p;
+      qsort (vector, lines, sizeof (*vector), compare);
+      srcs_node **patch = &head;
+      for (i = 0; i < lines; ++i)
+        {
+          *patch = vector[i];
+          patch = &(*patch)->next;
+        }
+      *patch = NULL;
+      delete[] vector;
+    }
+  for (i = 0, p = head; p != NULL; p = p->next, ++i)
+    {
+      put (i, 0, 1, " ", true);
+      put (i, 1, strlen (p->fname), p->fname, true);
+    }
+}
+
+
+void source_files_window::delete_all ()
+{
+  parent::delete_all ();
+  srcs_node *p, *next;
+  for (p = head; p != NULL; p = next)
+    {
+      next = p->next;
+      delete p;
+    }
+  head = NULL;
+  lines = 0; sel_line = -1;
+}
+
+
+void source_files_window::select (const char *fname)
+{
+  int line = 0;
+  for (srcs_node *p = head; p != NULL; p = p->next, ++line)
+    if (strcmp (p->fname, fname) == 0)
+      {
+        select_line (line);
+        return;
+      }
+  select_line (-1);
+}
+
+
+void source_files_window::select_line (int line, bool toggle)
+{
+  if (toggle && line != -1 && line == sel_line)
+    line = -1;
+  if (line != sel_line)
+    {
+      if (sel_line != -1)
+        {
+          put (sel_line, 0, max_line_len, get_default_attr (), true);
+          set_eol_attr (sel_line, get_default_attr (), true);
+        }
+      if (line != -1)
+        {
+          put (line, 0, max_line_len, sel_attr, true);
+          set_eol_attr (line, sel_attr, true);
+        }
+      sel_line = line;
+    }
+  if (line != -1)
+    show_line (line, 0, 0);
+}
Index: trunk/src/emx/src/pmgdb/srcfiles.h
===================================================================
--- trunk/src/emx/src/pmgdb/srcfiles.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/srcfiles.h	(revision 18)
@@ -0,0 +1,77 @@
+/* srcfiles.h -*- C++ -*-
+   Copyright (c) 1996-1998 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class command_window;
+
+class source_files_window : public pmtxt
+{
+public:
+
+  typedef pmtxt parent;
+  struct srcs_node;
+
+  // Constructors and destructors
+  source_files_window (command_window *cmd, unsigned id, const SWP *pswp,
+                       const char *fontnamesize);
+  ~source_files_window ();
+  void add (const char *fname);
+  void done ();
+  void delete_all ();
+  void select (const char *fname);
+
+  class iterator
+  {
+  public:
+    iterator (const source_files_window &s) { cur = s.head; }
+    ~iterator () {}
+    bool ok () { return cur != NULL; }
+    void next () { cur = cur->next; }
+    operator const char * () { return cur->fname; }
+
+  private:
+    const srcs_node *cur;
+  };
+
+private:
+
+  // Override member functions of pmframe
+  MRESULT wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  void button_event (int line, int column, int tab, int button, int clicks);
+
+  srcs_node *find_by_line (int line);
+  void select_line (int line, bool toggle = false);
+
+  command_window *cmd;
+  srcs_node *head;
+  int lines;
+  int sel_line;
+  pmtxt_attr sel_attr;
+
+  struct srcs_node
+  {
+    struct srcs_node *next;
+    fstring fname;
+  };
+
+  friend class iterator;
+};
Index: trunk/src/emx/src/pmgdb/string.cc
===================================================================
--- trunk/src/emx/src/pmgdb/string.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/string.cc	(revision 18)
@@ -0,0 +1,262 @@
+/* string.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "string.h"
+
+
+bool bstring::operator == (const bstring &b) const
+{
+  if (str == NULL && b.str == NULL)
+    return true;
+  if (str == NULL || b.str == NULL)
+    return false;
+  return strcmp (str, b.str) == 0;
+}
+
+
+void vstring::set (const char *s, int len)
+{
+  if (len >= alloc)
+    set (len);
+  memcpy (str, s, len);
+  str[len] = 0;
+}
+
+
+void vstring::set (int len)
+{
+  if (len >= alloc)
+    {
+      alloc = len + 1;
+      alloc = ((alloc + 31) / 32) * 32;
+      char *temp = new char[alloc];
+      if (str != NULL)
+        {
+          strcpy (temp, str);
+          delete[] str;
+        }
+      else
+        *temp = 0;
+      str = temp;
+    }
+  str[len] = 0;
+}
+
+
+void vstring::set_null ()
+{
+  delete[] str;
+  str = NULL;
+  alloc = 0;
+}
+
+
+vstring &vstring::operator = (const vstring &src)
+{
+  if (src.str == NULL)
+    set_null ();
+  else
+    set (src.str);
+  return *this;
+}
+
+
+void fstring::set (const char *s, int len)
+{
+  delete[] str;
+  str = new char[len + 1];
+  memcpy (str, s, len);
+  str[len] = 0;
+}
+
+
+// Note: Does not keep the contents of the string
+
+void fstring::set (int len)
+{
+  delete[] str;
+  str = new char[len + 1];
+  *str = 0;
+}
+
+
+void fstring::set_null ()
+{
+  delete[] str;
+  str = NULL;
+}
+
+
+fstring &fstring::operator = (const fstring &src)
+{
+  if (src.str == NULL)
+    set_null ();
+  else
+    set (src.str);
+  return *this;
+}
+
+
+void astring::append (const char *s, int len)
+{
+  if (cur_len + len  >= alloc)
+    set (cur_len + len);
+  memcpy (str + cur_len, s, len);
+  cur_len += len;
+  str[cur_len] = 0;
+}
+
+
+astring &astring::operator = (const astring &src)
+{
+  if (src.str == NULL)
+    set_null ();
+  else
+    {
+      // TODO: no need to copy old string
+      parent::set (src.str);
+      cur_len = src.cur_len;
+    }
+  return *this;
+}
+
+
+void astring::remove_trailing (char c)
+{
+  while (cur_len > 0 && str[cur_len-1] == c)
+    --cur_len;
+  str[cur_len] = 0;
+}
+
+
+lstring::lstring (const char *s)
+{
+  str = NULL; vec = NULL;
+  set (s);
+}
+
+
+lstring::lstring (const bstring &s)
+{
+  str = NULL; vec = NULL;
+  set ((const char *)s);
+}
+
+
+lstring::lstring (const lstring &s)
+{
+  str = NULL; vec = NULL;
+  assign (s);
+}
+
+
+lstring::~lstring ()
+{
+  delete[] str;
+  delete[] vec;
+}
+
+
+lstring &lstring::operator = (const lstring &s)
+{
+  assign (s);
+  return *this;
+}
+
+
+void lstring::assign (const lstring &s)
+{
+  delete[] str;
+  delete[] vec;
+  str_len = s.str_len;
+  str = new char[str_len+1];
+  memcpy (str, s.str, str_len+1);
+  n = s.n;
+  vec = new const char *[n];
+  const char *p = str;
+  for (int i = 0; i < n; ++i)
+    {
+      vec[i] = p;
+      p += strlen (p) + 1;
+    }
+}
+
+
+void lstring::set (const char *s, size_t len)
+{
+  delete[] str;
+  delete[] vec;
+  str_len = len;
+  str = new char[len+1];
+  memcpy (str, s, len+1);
+  n = _memcount (str, '\n', len);
+  if (len != 0 && str[len-1] != '\n')
+    ++n;
+  vec = new const char *[n];
+  char *p = str;
+  int i = 0;
+  while (len != 0)
+    {
+      vec[i++] = p;
+      char *end = (char *)memchr (p, '\n', len);
+      if (end == NULL)
+        break;
+      *end = 0;
+      len -= (end + 1 - p);
+      p = end + 1;
+    }
+  if (i != n)
+    abort ();
+}
+
+
+static int (*lstring_compare_strings)(const char *, const char *);
+
+
+static int default_compare (const char *s1, const char *s2)
+{
+  return strcmp (s1, s2);
+}
+
+
+extern "C"
+{
+  static int lstring_compare (const void *p1, const void *p2)
+    {
+      return lstring_compare_strings (*(const char **)p1, *(const char **)p2);
+    }
+}
+
+void lstring::sort ()
+{
+  sort (default_compare);
+}
+
+
+// This is not thread-safe!
+
+void lstring::sort (int (*compare)(const char *, const char *))
+{
+  lstring_compare_strings = compare;
+  qsort (vec, n, sizeof (*vec), lstring_compare);
+}
Index: trunk/src/emx/src/pmgdb/string.h
===================================================================
--- trunk/src/emx/src/pmgdb/string.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/string.h	(revision 18)
@@ -0,0 +1,128 @@
+/* string.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class bstring
+{
+public:
+  bstring () { str = NULL; }
+  virtual ~bstring () { delete[] str; }
+  char * modify () { return str; }
+  virtual void set (const char *s, int len) = 0;
+  virtual void set (int len) = 0;
+  virtual void set_null () = 0;
+  bool is_null () const { return str == NULL; }
+  int length () const { return strlen (str); }
+  void set (const char *s) { set (s, strlen (s)); }
+  operator const char * () const { return str; }
+  operator const unsigned char * () const { return (unsigned char *)str; }
+  const char operator [] (int index) const { return str[index]; }
+  bool operator == (const bstring &b) const;
+  bool operator != (const bstring &b) const { return !operator== (b); }
+
+protected:
+  char *str;
+};
+
+// A vstring is expected to be modified quite often
+
+class vstring : public bstring
+{
+public:
+  vstring () { alloc = 0; }
+  ~vstring () {}
+  void set (const char *s) { bstring::set (s); }
+  void set (const char *s, int len);
+  void set (int len);
+  void set_null ();
+  vstring &operator = (const char *s) { set (s); return *this; }
+  vstring &operator = (const vstring &src);
+
+protected:
+  int alloc;
+};
+
+// An fstring is expected to be set only once
+
+class fstring : public bstring
+{
+public:
+  fstring () {}
+  ~fstring () {}
+  void set (const char *s) { bstring::set (s); }
+  void set (const char *s, int len);
+  void set (int len);
+  void set_null ();
+  fstring &operator = (const char *s) { set (s); return *this; }
+  fstring &operator = (const fstring &src);
+};
+
+
+// An astring is expected to be appended to
+
+class astring : public vstring
+{
+private:
+  typedef vstring parent;
+public:
+  astring () { cur_len = 0; }
+  ~astring () {}
+  void set (const char *s) { bstring::set (s); }
+  void set (const char *s, int len) { parent::set (s, len); cur_len = len; }
+  void set (int len) { parent::set (len); if (len < cur_len) cur_len = len; }
+  void set_null () { parent::set_null (); cur_len = 0; }
+  void append (const char *s, int len);
+  void append (const char *s) { append (s, strlen (s)); }
+  vstring &operator = (const char *s) { set (s); return *this; }
+  astring &operator = (const astring &src);
+  int length () const { return cur_len; }
+  void remove_trailing (char c);
+
+private:
+  int cur_len;
+};
+
+
+// String consisting of lines
+
+class lstring
+{
+public:
+  lstring () { str = NULL; vec = NULL; n = 0; }
+  lstring (const char *s);
+  lstring (const bstring &s);
+  lstring (const lstring &s);
+  ~lstring ();
+  lstring &operator = (const lstring &s);
+  void set (const char *s, size_t len);
+  void set (const char *s) { set (s, strlen (s)); }
+  int get_lines () const { return n; }
+  const char *operator [] (int index) const
+    { return (index >= 0 && index < n) ? vec[index] : NULL; }
+  void sort (int (*compare) (const char *, const char *));
+  void sort ();
+
+private:
+  void assign (const lstring &s);
+  char *str;
+  const char **vec;
+  int n;
+  size_t str_len;
+};
Index: trunk/src/emx/src/pmgdb/threads.cc
===================================================================
--- trunk/src/emx/src/pmgdb/threads.cc	(revision 18)
+++ trunk/src/emx/src/pmgdb/threads.cc	(revision 18)
@@ -0,0 +1,392 @@
+/* threads.cc
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#define INCL_WIN
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>              // sprintf()
+#include <stdarg.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include "string.h"
+#include "pmapp.h"
+#include "pmframe.h"
+#include "pmtxt.h"
+#include "pmtty.h"
+#include "pmgdb.h"
+#include "help.h"
+#include "breakpoi.h"
+#include "threads.h"
+#include "annotati.h"
+#include "gdbio.h"
+#include "command.h"
+
+
+class threads_window::thread
+{
+public:
+  thread () {}
+  ~thread () {}
+
+  thread *next;
+  int number;
+  int pid;
+  int line;
+  bool enable;
+};
+
+#define THR_HEADER_LINES        1
+
+threads_window::threads_window (command_window *in_cmd, gdbio *in_gdb,
+                                unsigned in_id, const SWP *pswp,
+                                const char *fontnamesize)
+  : pmtxt (in_cmd->get_app (), in_id,
+           pswp == NULL ? FCF_SHELLPOSITION : 0, pswp, fontnamesize)
+{
+  cmd = in_cmd; gdb = in_gdb;
+  head = NULL;
+  cur_line = -1; sel_line = -1;
+
+  sel_attr = get_default_attr ();
+  set_fg_color (sel_attr, CLR_BLACK);
+  set_bg_color (sel_attr, CLR_PALEGRAY);
+
+  hilite_attr = get_default_attr ();
+  set_fg_color (hilite_attr, CLR_WHITE);
+  set_bg_color (hilite_attr, CLR_BLACK);
+
+  sel_hilite_attr = get_default_attr ();
+  set_fg_color (sel_hilite_attr, CLR_WHITE);
+  set_bg_color (sel_hilite_attr, CLR_DARKGRAY);
+
+  menu_enable (IDM_EDITMENU, false);
+
+  int x = 0;
+  put (0, x, 6, " TID ", true); x += 6;
+  put_tab (0, x++, true);
+  put_vrule (0, x++, true);
+  put (0, x, 5, " Ena ", true); x += 5;
+  underline (0, true, true);
+
+  set_title ("pmgdb - Threads");
+  set_keys_help_id (HELP_THR_KEYS);
+}
+
+
+threads_window::~threads_window ()
+{
+  thread *p, *next;
+  for (p = head; p != NULL; p = next)
+    {
+      next = p->next;
+      delete p;
+    }
+}
+
+
+MRESULT threads_window::wm_activate (HWND hwnd, ULONG msg,
+                                     MPARAM mp1, MPARAM mp2)
+{
+  if (SHORT1FROMMP (mp1))
+    cmd->associate_help (get_hwndFrame ());
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+MRESULT threads_window::wm_close (HWND, ULONG, MPARAM, MPARAM)
+{
+  show (false);
+  return 0;
+}
+
+
+MRESULT threads_window::wm_command (HWND hwnd, ULONG msg,
+                                    MPARAM mp1, MPARAM mp2)
+{
+  const thread *p;
+
+  switch (SHORT1FROMMP (mp1))
+    {
+    case IDM_ENABLE:
+      p = find_by_line (sel_line);
+      if (p == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        gdb->send_cmd ("server thread enable %d", p->number);
+      break;
+
+    case IDM_DISABLE:
+      p = find_by_line (sel_line);
+      if (p == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        gdb->send_cmd ("server thread disable %d", p->number);
+      break;
+
+    case IDM_SWITCH:
+      p = find_by_line (sel_line);
+      if (p == NULL)
+        WinAlarm (HWND_DESKTOP, WA_ERROR);
+      else
+        gdb->send_cmd ("server thread %d", p->number);
+      break;
+
+    default:
+      return cmd->wm_command (hwnd, msg, mp1, mp2);
+    }
+  return WinDefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+
+bool threads_window::wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  if (parent::wm_user (hwnd, msg, mp1, mp2))
+    return true;
+  switch (msg)
+    {
+    case UWM_MENU:
+      if (sel_line == -1)
+        menu_enable (IDM_EDITMENU, false);
+      else
+        {
+          const thread *p = find_by_line (sel_line);
+          menu_enable (IDM_ENABLE, !p->enable);
+          menu_enable (IDM_DISABLE, p->enable);
+        }
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+
+void threads_window::button_event (int line, int column, int tab, int button,
+                                   int clicks)
+{
+  if (line >= 0 && column >= 0)
+    {
+      // TODO: Context menu
+      if (button == 1 && clicks == 1)
+        select_line (line, true);
+      else if (button == 1 && clicks == 2 && tab == 1)
+        {
+          const thread *p = find_by_line (line);
+          if (p == NULL)
+            WinAlarm (HWND_DESKTOP, WA_ERROR);
+          else
+            gdb->send_cmd ("server thread %s %d",
+                           p->enable ? "disable" : "enable", p->number);
+        }
+      else if (button == 1 && clicks == 2)
+        {
+          const thread *p = find_by_line (line);
+          if (p == NULL)
+            WinAlarm (HWND_DESKTOP, WA_ERROR);
+          else
+            {
+              gdb->call_cmd ("server thread %d", p->number);
+              cmd->where ();
+            }
+        }
+    }
+  else
+    select_line (-1);
+}
+
+
+threads_window::thread *threads_window::find_by_number (int number)
+{
+  for (thread *p = head; p != NULL; p = p->next)
+    if (p->number == number)
+      return p;
+  return NULL;
+}
+
+
+threads_window::thread *threads_window::find_by_line (int line)
+{
+  for (thread *p = head; p != NULL; p = p->next)
+    if (p->line == line)
+      return p;
+  return NULL;
+}
+
+
+void threads_window::add (int number, int pid)
+{
+  thread *p = find_by_number (number);
+  if (p == NULL)
+    {
+      int line = THR_HEADER_LINES;
+      thread **patch = &head;
+      while (*patch != NULL && (*patch)->pid < pid)
+        {
+          patch = &(*patch)->next;
+          ++line;
+        }
+      p = new thread;
+      p->next = *patch;
+      *patch = p;
+      p->number = number;
+      p->pid = pid;
+      p->line = line;
+      p->enable = true;
+      for (thread *q = p->next; q != NULL; q = q->next)
+        ++q->line;
+      insert_lines (p->line, 1, true);
+      if (cur_line != -1 && p->line <= cur_line)
+        ++cur_line;
+      if (sel_line != -1 && p->line <= sel_line)
+        ++sel_line;
+      update (p);
+    }
+}
+
+
+void threads_window::enable (int number)
+{
+  thread *p = find_by_number (number);
+  if (p != NULL && !p->enable)
+    {
+      p->enable = true;
+      if (p->line == sel_line)
+        WinPostMsg (get_hwndClient (), UWM_MENU, 0, 0);
+      update (p);
+    }
+}
+
+
+void threads_window::disable (int number)
+{
+  thread *p = find_by_number (number);
+  if (p != NULL && p->enable)
+    {
+      p->enable = false;
+      if (p->line == sel_line)
+        WinPostMsg (get_hwndClient (), UWM_MENU, 0, 0);
+      update (p);
+    }
+}
+
+
+void threads_window::remove (int pid)
+{
+  for (thread **patch = &head; *patch != NULL; patch = &(*patch)->next)
+    if ((*patch)->pid == pid)
+      {
+        for (thread *p = (*patch)->next; p != NULL; p = p->next)
+          --p->line;
+        thread *p = *patch;
+        delete_lines (p->line, 1, true);
+        *patch = p->next;
+        if (cur_line != -1 && p->line == cur_line)
+          cur_line = -1;
+        if (sel_line != -1 && p->line == sel_line)
+          {
+            sel_line = -1;
+            WinPostMsg (get_hwndClient (), UWM_MENU, 0, 0);
+          }
+        delete p;
+        return;
+      }
+}
+
+
+void threads_window::select (int number)
+{
+  thread *p = find_by_number (number);
+  if (p != NULL)
+    current_line (p->line);
+}
+
+
+void threads_window::update (const thread *p)
+{
+  char buf[400];
+  int x = 0, len;
+  pmtxt_attr attr;
+
+  if (p->line == cur_line && p->line == sel_line)
+    attr = sel_hilite_attr;
+  else if (p->line == cur_line)
+    attr = hilite_attr;
+  else if (p->line == sel_line)
+    attr = sel_attr;
+  else
+    attr = get_default_attr ();
+
+  clear_lines (p->line, 1, true);
+  len = snprintf (buf, sizeof (buf), " %d ", PTRACE_GETTID (p->pid));
+  put (p->line, x, len, buf, attr, true); x += len;
+  put_tab (p->line, x++, attr, true);
+  put_vrule (p->line, x++, attr, true);
+
+  len = snprintf (buf, sizeof (buf), " %c ", p->enable ? 'y' : 'n');
+  put (p->line, x, len, buf, attr, true); x += len;
+}
+
+
+void threads_window::current_line (int line)
+{
+  if (line != cur_line)
+    {
+      if (cur_line != -1)
+        put (cur_line, 0, max_line_len,
+             cur_line == sel_line ? sel_attr : get_default_attr (), true);
+      if (line != -1)
+        put (line, 0, max_line_len,
+             line == sel_line ? sel_hilite_attr : hilite_attr, true);
+      cur_line = line;
+    }
+}
+
+
+void threads_window::select_line (int line, bool toggle)
+{
+  const thread *p;
+  if (toggle && line != -1 && line == sel_line)
+    line = -1;
+  if (line == -1)
+    p = NULL;
+  else
+    {
+      p = find_by_line (line);
+      if (p == NULL) line = -1;
+    }
+  if (line != sel_line)
+    {
+      if (sel_line != -1)
+        put (sel_line, 0, max_line_len,
+             sel_line == cur_line ? hilite_attr : get_default_attr (), true);
+      if (line != -1)
+        put (line, 0, max_line_len,
+             line == cur_line ? sel_hilite_attr : sel_attr, true);
+      sel_line = line;
+    }
+  if (line != -1)
+    {
+      menu_enable (IDM_ENABLE, !p->enable);
+      menu_enable (IDM_DISABLE, p->enable);
+      show_line (line, 0, 0);
+    }
+  menu_enable (IDM_EDITMENU, line != -1);
+}
Index: trunk/src/emx/src/pmgdb/threads.h
===================================================================
--- trunk/src/emx/src/pmgdb/threads.h	(revision 18)
+++ trunk/src/emx/src/pmgdb/threads.h	(revision 18)
@@ -0,0 +1,65 @@
+/* threads.h -*- C++ -*-
+   Copyright (c) 1996 Eberhard Mattes
+
+This file is part of pmgdb.
+
+pmgdb is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+pmgdb is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pmgdb; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+class command_window;
+class gdbio;
+
+class threads_window : public pmtxt
+{
+public:
+
+  typedef pmtxt parent;
+
+  threads_window (command_window *cmd, gdbio *gdb, unsigned id,
+                  const SWP *pswp, const char *fontnamesize);
+  ~threads_window ();
+
+  void add (int number, int pid);
+  void select (int number);
+  void enable (int number);
+  void disable (int number);
+  void remove (int tid);
+
+private:
+  class thread;
+
+  // Override member functions of pmframe
+  MRESULT wm_activate (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  MRESULT wm_command (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  bool wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+  void button_event (int line, int column, int tab, int button, int clicks);
+
+  thread *find_by_number (int number);
+  thread *find_by_line (int line);
+  void update (const thread *p);
+  void current_line (int line);
+  void select_line (int line, bool toggle = false);
+
+  command_window *cmd;
+  gdbio *gdb;
+  thread *head;
+  pmtxt_attr sel_attr;          // Selected thread
+  pmtxt_attr hilite_attr;       // Current thread
+  pmtxt_attr sel_hilite_attr;   // Selected & current thread
+  int cur_line;                 // Line of current thread
+  int sel_line;                 // Line of selected thread
+};
Index: trunk/src/emx/src/regexp/COPYRIGH
===================================================================
--- trunk/src/emx/src/regexp/COPYRIGH	(revision 18)
+++ trunk/src/emx/src/regexp/COPYRIGH	(revision 18)
@@ -0,0 +1,22 @@
+This entire subtree is copyright the University of Toronto.
+The following copyright notice applies to all files found here.  None of
+these files contain AT&T proprietary source code.
+_____________________________________________________________________________
+
+	Copyright (c) 1986 by University of Toronto.
+	Written by Henry Spencer.  Not derived from licensed software.
+
+	Permission is granted to anyone to use this software for any
+	purpose on any computer system, and to redistribute it freely,
+	subject to the following restrictions:
+
+	1. The author is not responsible for the consequences of use of
+		this software, no matter how awful, even if they arise
+		from defects in it.
+
+	2. The origin of this software must not be misrepresented, either
+		by explicit claim or by omission.
+
+	3. Altered versions must be plainly marked as such, and must not
+		be misrepresented as being the original software.
+
Index: trunk/src/emx/src/regexp/README
===================================================================
--- trunk/src/emx/src/regexp/README	(revision 18)
+++ trunk/src/emx/src/regexp/README	(revision 18)
@@ -0,0 +1,84 @@
+This is a nearly-public-domain reimplementation of the V8 regexp(3) package.
+It gives C programs the ability to use egrep-style regular expressions, and
+does it in a much cleaner fashion than the analogous routines in SysV.
+
+	Copyright (c) 1986 by University of Toronto.
+	Written by Henry Spencer.  Not derived from licensed software.
+
+	Permission is granted to anyone to use this software for any
+	purpose on any computer system, and to redistribute it freely,
+	subject to the following restrictions:
+
+	1. The author is not responsible for the consequences of use of
+		this software, no matter how awful, even if they arise
+		from defects in it.
+
+	2. The origin of this software must not be misrepresented, either
+		by explicit claim or by omission.
+
+	3. Altered versions must be plainly marked as such, and must not
+		be misrepresented as being the original software.
+
+Barring a couple of small items in the BUGS list, this implementation is
+believed 100% compatible with V8.  It should even be binary-compatible,
+sort of, since the only fields in a "struct regexp" that other people have
+any business touching are declared in exactly the same way at the same
+location in the struct (the beginning).
+
+This implementation is *NOT* AT&T/Bell code, and is not derived from licensed
+software.  Even though U of T is a V8 licensee.  This software is based on
+a V8 manual page sent to me by Dennis Ritchie (the manual page enclosed
+here is a complete rewrite and hence is not covered by AT&T copyright).
+The software was nearly complete at the time of arrival of our V8 tape.
+I haven't even looked at V8 yet, although a friend elsewhere at U of T has
+been kind enough to run a few test programs using the V8 regexp(3) to resolve
+a few fine points.  I admit to some familiarity with regular-expression
+implementations of the past, but the only one that this code traces any
+ancestry to is the one published in Kernighan & Plauger (from which this
+one draws ideas but not code).
+
+Simplistically:  put this stuff into a source directory, copy regexp.h into
+/usr/include, inspect Makefile for compilation options that need changing
+to suit your local environment, and then do "make r".  This compiles the
+regexp(3) functions, compiles a test program, and runs a large set of
+regression tests.  If there are no complaints, then put regexp.o, regsub.o,
+and regerror.o into your C library, and regexp.3 into your manual-pages
+directory.
+
+Note that if you don't put regexp.h into /usr/include *before* compiling,
+you'll have to add "-I." to CFLAGS before compiling.
+
+The files are:
+
+Makefile	instructions to make everything
+regexp.3	manual page
+regexp.h	header file, for /usr/include
+regexp.c	source for regcomp() and regexec()
+regsub.c	source for regsub()
+regerror.c	source for default regerror()
+regmagic.h	internal header file
+try.c		source for test program
+timer.c		source for timing program
+tests		test list for try and timer
+
+This implementation uses nondeterministic automata rather than the
+deterministic ones found in some other implementations, which makes it
+simpler, smaller, and faster at compiling regular expressions, but slower
+at executing them.  In theory, anyway.  This implementation does employ
+some special-case optimizations to make the simpler cases (which do make
+up the bulk of regular expressions actually used) run quickly.  In general,
+if you want blazing speed you're in the wrong place.  Replacing the insides
+of egrep with this stuff is probably a mistake; if you want your own egrep
+you're going to have to do a lot more work.  But if you want to use regular
+expressions a little bit in something else, you're in luck.  Note that many
+existing text editors use nondeterministic regular-expression implementations,
+so you're in good company.
+
+This stuff should be pretty portable, given appropriate option settings.
+If your chars have less than 8 bits, you're going to have to change the
+internal representation of the automaton, although knowledge of the details
+of this is fairly localized.  There are no "reserved" char values except for
+NUL, and no special significance is attached to the top bit of chars.
+The string(3) functions are used a fair bit, on the grounds that they are
+probably faster than coding the operations in line.  Some attempts at code
+tuning have been made, but this is invariably a bit machine-specific.
Index: trunk/src/emx/src/regexp/makefile
===================================================================
--- trunk/src/emx/src/regexp/makefile	(revision 18)
+++ trunk/src/emx/src/regexp/makefile	(revision 18)
@@ -0,0 +1,17 @@
+#
+# make file (written by Eberhard Mattes) for regexp (written by Henry Spencer)
+#
+default: regexp.a
+
+CC=	gcc
+CFLAGS= -O2 -I.
+
+.c.o:
+	$(CC) -c $(CFLAGS) $<
+
+OBJS=regexp.o regsub.o regerror.o
+
+regexp.a: $(OBJS)
+	-del regexp.a
+	ar r regexp.a $(OBJS)
+	ar s regexp.a
Index: trunk/src/emx/src/regexp/regerror.c
===================================================================
--- trunk/src/emx/src/regexp/regerror.c	(revision 18)
+++ trunk/src/emx/src/regexp/regerror.c	(revision 18)
@@ -0,0 +1,18 @@
+#include <regexp.h>
+#include <stdio.h>
+
+void
+regerror(s)
+const char *s;
+{
+#ifdef ERRAVAIL
+	error("regexp: %s", s);
+#else
+/*
+	fprintf(stderr, "regexp(3): %s\n", s);
+	exit(1);
+*/
+	return;	  /* let std. egrep handle errors */
+#endif
+	/* NOTREACHED */
+}
Index: trunk/src/emx/src/regexp/regexp.3
===================================================================
--- trunk/src/emx/src/regexp/regexp.3	(revision 18)
+++ trunk/src/emx/src/regexp/regexp.3	(revision 18)
@@ -0,0 +1,315 @@
+.\" Copyright 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)regexp.3	5.2 (Berkeley) 4/20/91
+.\"
+.Dd April 20, 1991
+.Dt REGEXP 3
+.Os
+.Sh NAME
+.Nm regcomp ,
+.Nm regexec ,
+.Nm regsub ,
+.Nm regerror
+.Nd regular expression handlers
+.Sh SYNOPSIS
+.Fd #include <regexp.h>
+.Ft regexp *
+.Fn regcomp "const char *exp"
+.Ft int
+.Fn regexec "const regexp *prog" "const char *string"
+.Ft void
+.Fn regsub "const regexp *prog" "const char *source" "char *dest"
+.Sh DESCRIPTION
+The
+.Fn regcomp ,
+.Fn regexec ,
+.Fn regsub ,
+and
+.Fn regerror
+functions
+implement
+.Xr egrep 1 Ns -style
+regular expressions and supporting facilities.
+.Pp
+The
+.Fn regcomp
+function
+compiles a regular expression into a structure of type
+.Xr regexp ,
+and returns a pointer to it.
+The space has been allocated using
+.Xr malloc 3
+and may be released by
+.Xr free .
+.Pp
+The
+.Fn regexec
+function
+matches a
+.Dv NUL Ns -terminated
+.Fa string
+against the compiled regular expression
+in
+.Fa prog .
+It returns 1 for success and 0 for failure, and adjusts the contents of
+.Fa prog Ns 's
+.Em startp
+and
+.Em endp
+(see below) accordingly.
+.Pp
+The members of a
+.Xr regexp
+structure include at least the following (not necessarily in order):
+.Bd -literal -offset indent
+char *startp[NSUBEXP];
+char *endp[NSUBEXP];
+.Ed
+.Pp
+where
+.Dv NSUBEXP
+is defined (as 10) in the header file.
+Once a successful
+.Fn regexec
+has been done using the
+.Fn regexp ,
+each
+.Em startp Ns - Em endp
+pair describes one substring
+within the
+.Fa string ,
+with the
+.Em startp
+pointing to the first character of the substring and
+the
+.Em endp
+pointing to the first character following the substring.
+The 0th substring is the substring of
+.Fa string
+that matched the whole
+regular expression.
+The others are those substrings that matched parenthesized expressions
+within the regular expression, with parenthesized expressions numbered
+in left-to-right order of their opening parentheses.
+.Pp
+The
+.Fn regsub
+function
+copies
+.Fa source
+to
+.Fa dest ,
+making substitutions according to the
+most recent
+.Fn regexec
+performed using
+.Fa prog .
+Each instance of `&' in
+.Fa source
+is replaced by the substring
+indicated by
+.Em startp Ns Bq
+and
+.Em endp Ns Bq .
+Each instance of
+.Sq \e Ns Em n ,
+where
+.Em n
+is a digit, is replaced by
+the substring indicated by
+.Em startp Ns Bq Em n
+and
+.Em endp Ns Bq Em n .
+To get a literal `&' or
+.Sq \e Ns Em n
+into
+.Fa dest ,
+prefix it with `\e';
+to get a literal `\e' preceding `&' or
+.Sq \e Ns Em n ,
+prefix it with
+another `\e'.
+.Pp
+The
+.Fn regerror
+function
+is called whenever an error is detected in
+.Fn regcomp ,
+.Fn regexec ,
+or
+.Fn regsub .
+The default
+.Fn regerror
+writes the string
+.Fa msg ,
+with a suitable indicator of origin,
+on the standard
+error output
+and invokes
+.Xr exit 2 .
+The
+.Fn regerror
+function
+can be replaced by the user if other actions are desirable.
+.Sh REGULAR EXPRESSION SYNTAX
+A regular expression is zero or more
+.Em branches ,
+separated by `|'.
+It matches anything that matches one of the branches.
+.Pp
+A branch is zero or more
+.Em pieces ,
+concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.Pp
+A piece is an
+.Em atom
+possibly followed by `*', `+', or `?'.
+An atom followed by `*' matches a sequence of 0 or more matches of the atom.
+An atom followed by `+' matches a sequence of 1 or more matches of the atom.
+An atom followed by `?' matches a match of the atom, or the null string.
+.Pp
+An atom is a regular expression in parentheses (matching a match for the
+regular expression), a
+.Em range
+(see below), `.'
+(matching any single character), `^' (matching the null string at the
+beginning of the input string), `$' (matching the null string at the
+end of the input string), a `\e' followed by a single character (matching
+that character), or a single character with no other significance
+(matching that character).
+.Pp
+A
+.Em range
+is a sequence of characters enclosed in `[]'.
+It normally matches any single character from the sequence.
+If the sequence begins with `^',
+it matches any single character
+.Em not
+from the rest of the sequence.
+If two characters in the sequence are separated by `\-', this is shorthand
+for the full list of
+.Tn ASCII
+characters between them
+(e.g. `[0-9]' matches any decimal digit).
+To include a literal `]' in the sequence, make it the first character
+(following a possible `^').
+To include a literal `\-', make it the first or last character.
+.Sh AMBIGUITY
+If a regular expression could match two different parts of the input string,
+it will match the one which begins earliest.
+If both begin in the same place but match different lengths, or match
+the same length in different ways, life gets messier, as follows.
+.Pp
+In general, the possibilities in a list of branches are considered in
+left-to-right order, the possibilities for `*', `+', and `?' are
+considered longest-first, nested constructs are considered from the
+outermost in, and concatenated constructs are considered leftmost-first.
+The match that will be chosen is the one that uses the earliest
+possibility in the first choice that has to be made.
+If there is more than one choice, the next will be made in the same manner
+(earliest possibility) subject to the decision on the first choice.
+And so forth.
+.Pp
+For example,
+.Sq Li (ab|a)b*c
+could match
+`abc' in one of two ways.
+The first choice is between `ab' and `a'; since `ab' is earlier, and does
+lead to a successful overall match, it is chosen.
+Since the `b' is already spoken for,
+the `b*' must match its last possibility\(emthe empty string\(emsince
+it must respect the earlier choice.
+.Pp
+In the particular case where no `|'s are present and there is only one
+`*', `+', or `?', the net effect is that the longest possible
+match will be chosen.
+So
+.Sq Li ab* ,
+presented with `xabbbby', will match `abbbb'.
+Note that if
+.Sq Li ab* ,
+is tried against `xabyabbbz', it
+will match `ab' just after `x', due to the begins-earliest rule.
+(In effect, the decision on where to start the match is the first choice
+to be made, hence subsequent choices must respect it even if this leads them
+to less-preferred alternatives.)
+.Sh RETURN VALUES
+The
+.Fn regcomp
+function
+returns
+.Dv NULL
+for a failure
+.Pf ( Fn regerror
+permitting),
+where failures are syntax errors, exceeding implementation limits,
+or applying `+' or `*' to a possibly-null operand.
+.Sh SEE ALSO
+.Xr ed 1 ,
+.Xr ex 1 ,
+.Xr expr 1 ,
+.Xr egrep 1 ,
+.Xr fgrep 1 ,
+.Xr grep 1 ,
+.Xr regex 3
+.Sh HISTORY
+Both code and manual page for
+.Fn regcomp ,
+.Fn regexec ,
+.Fn regsub ,
+and
+.Fn regerror
+were written at the University of Toronto
+and appeared in
+.Bx 4.3 tahoe .
+They are intended to be compatible with the Bell V8
+.Xr regexp 3 ,
+but are not derived from Bell code.
+.Sh BUGS
+Empty branches and empty regular expressions are not portable to V8.
+.Pp
+The restriction against
+applying `*' or `+' to a possibly-null operand is an artifact of the
+simplistic implementation.
+.Pp
+Does not support
+.Xr egrep Ns 's
+newline-separated branches;
+neither does the V8
+.Xr regexp 3 ,
+though.
+.Pp
+Due to emphasis on
+compactness and simplicity,
+it's not strikingly fast.
+It does give special attention to handling simple cases quickly.
Index: trunk/src/emx/src/regexp/regexp.c
===================================================================
--- trunk/src/emx/src/regexp/regexp.c	(revision 18)
+++ trunk/src/emx/src/regexp/regexp.c	(revision 18)
@@ -0,0 +1,1320 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ *** THIS IS AN ALTERED VERSION.  It was altered by John Gilmore,
+ *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to |
+ *** to assist in implementing egrep.
+ *** THIS IS AN ALTERED VERSION.  It was altered by John Gilmore,
+ *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching
+ *** as in BSD grep and ex.
+ *** THIS IS AN ALTERED VERSION.  It was altered by John Gilmore,
+ *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \.
+ *** THIS IS AN ALTERED VERSION.  It was altered by James A. Woods,
+ *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions.  Serious changes in
+ * regular-expression syntax might require a total rethink.
+ */
+#include <regexp.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "regmagic.h"
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases.  They are:
+ *
+ * regstart	char that must begin a match; '\0' if none obvious
+ * reganch	is the match anchored (at beginning-of-line only)?
+ * regmust	string (pointer into program) that match must include, or NULL
+ * regmlen	length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot.  Regmust permits fast rejection
+ * of lines that cannot possibly match.  The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup).  Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program".  This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology).  Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives.  (Here we
+ * have one of the subtle syntax dependencies:  an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.)  The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM.  In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure:  the tail of the branch connects
+ * to the thing following the set of BRANCHes.)  The opcodes are:
+ */
+
+/* definition	number	opnd?	meaning */
+#define	END	0	/* no	End of program. */
+#define	BOL	1	/* no	Match "" at beginning of line. */
+#define	EOL	2	/* no	Match "" at end of line. */
+#define	ANY	3	/* no	Match any one character. */
+#define	ANYOF	4	/* str	Match any character in this string. */
+#define	ANYBUT	5	/* str	Match any character not in this string. */
+#define	BRANCH	6	/* node	Match this alternative, or the next... */
+#define	BACK	7	/* no	Match "", "next" ptr points backward. */
+#define	EXACTLY	8	/* str	Match this string. */
+#define	NOTHING	9	/* no	Match empty string. */
+#define	STAR	10	/* node	Match this (simple) thing 0 or more times. */
+#define	PLUS	11	/* node	Match this (simple) thing 1 or more times. */
+#define	WORDA	12	/* no	Match "" at wordchar, where prev is nonword */
+#define	WORDZ	13	/* no	Match "" at nonwordchar, where prev is word */
+#define	OPEN	20	/* no	Mark this point in input as start of #n. */
+			/*	OPEN+1 is number 1, etc. */
+#define	CLOSE	30	/* no	Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH	The set of branches constituting a single choice are hooked
+ *		together with their "next" pointers, since precedence prevents
+ *		anything being concatenated to any individual branch.  The
+ *		"next" pointer of the last BRANCH in a choice points to the
+ *		thing following the whole choice.  This is also where the
+ *		final "next" pointer of each individual branch points; each
+ *		branch starts with the operand node of a BRANCH node.
+ *
+ * BACK		Normal "next" pointers all implicitly point forward; BACK
+ *		exists to make loop structures possible.
+ *
+ * STAR,PLUS	'?', and complex '*' and '+', are implemented as circular
+ *		BRANCH structures using BACK.  Simple cases (one character
+ *		per match) are implemented with STAR and PLUS for speed
+ *		and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE	...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first.  The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node.  (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define	OP(p)	(*(p))
+#define	NEXT(p)	(((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define	OPERAND(p)	((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+#define	FAIL(m)	{ regerror(m); return(NULL); }
+#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?')
+
+/*
+ * Flags to be passed up and down.
+ */
+#define	HASWIDTH	01	/* Known never to match null string. */
+#define	SIMPLE		02	/* Simple enough to be STAR/PLUS operand. */
+#define	SPSTART		04	/* Starts with * or +. */
+#define	WORST		0	/* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+static char *regparse;		/* Input-scan pointer. */
+static int regnpar;		/* () count. */
+static char regdummy;
+static char *regcode;		/* Code-emit pointer; &regdummy = don't. */
+static long regsize;		/* Code size. */
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define	STATIC	static
+#endif
+STATIC char *reg();
+STATIC char *regbranch();
+STATIC char *regpiece();
+STATIC char *regatom();
+STATIC char *regnode();
+STATIC char *regnext();
+STATIC void regc();
+STATIC void reginsert();
+STATIC void regtail();
+STATIC void regoptail();
+#ifdef STRCSPN
+STATIC int strcspn();
+#endif
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code.  So we cheat:  we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it.  (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp(exp)
+const char *exp;
+{
+	register regexp *r;
+	register char *scan;
+	register char *longest;
+	register int len;
+	int flags;
+
+	if (exp == NULL)
+		FAIL("NULL argument");
+
+	/* First pass: determine size, legality. */
+#ifdef notdef
+	if (exp[0] == '.' && exp[1] == '*') exp += 2;  /* aid grep */
+#endif
+	regparse = (char *)exp;
+	regnpar = 1;
+	regsize = 0L;
+	regcode = &regdummy;
+	regc(MAGIC);
+	if (reg(0, &flags) == NULL)
+		return(NULL);
+
+	/* Small enough for pointer-storage convention? */
+	if (regsize >= 32767L)		/* Probably could be 65535L. */
+		FAIL("regexp too big");
+
+	/* Allocate space. */
+	r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
+	if (r == NULL)
+		FAIL("out of space");
+
+	/* Second pass: emit code. */
+	regparse = (char *)exp;
+	regnpar = 1;
+	regcode = r->program;
+	regc(MAGIC);
+	if (reg(0, &flags) == NULL)
+		return(NULL);
+
+	/* Dig out information for optimizations. */
+	r->regstart = '\0';	/* Worst-case defaults. */
+	r->reganch = 0;
+	r->regmust = NULL;
+	r->regmlen = 0;
+	scan = r->program+1;			/* First BRANCH. */
+	if (OP(regnext(scan)) == END) {		/* Only one top-level choice. */
+		scan = OPERAND(scan);
+
+		/* Starting-point info. */
+		if (OP(scan) == EXACTLY)
+			r->regstart = *OPERAND(scan);
+		else if (OP(scan) == BOL)
+			r->reganch++;
+
+		/*
+		 * If there's something expensive in the r.e., find the
+		 * longest literal string that must appear and make it the
+		 * regmust.  Resolve ties in favor of later strings, since
+		 * the regstart check works with the beginning of the r.e.
+		 * and avoiding duplication strengthens checking.  Not a
+		 * strong reason, but sufficient in the absence of others.
+		 */
+		if (flags&SPSTART) {
+			longest = NULL;
+			len = 0;
+			for (; scan != NULL; scan = regnext(scan))
+				if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+					longest = OPERAND(scan);
+					len = strlen(OPERAND(scan));
+				}
+			r->regmust = longest;
+			r->regmlen = len;
+		}
+	}
+
+	return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *
+reg(paren, flagp)
+int paren;			/* Parenthesized? */
+int *flagp;
+{
+	register char *ret;
+	register char *br;
+	register char *ender;
+	register int parno;
+	int flags;
+
+	*flagp = HASWIDTH;	/* Tentatively. */
+
+	/* Make an OPEN node, if parenthesized. */
+	if (paren) {
+		if (regnpar >= NSUBEXP)
+			FAIL("too many ()");
+		parno = regnpar;
+		regnpar++;
+		ret = regnode(OPEN+parno);
+	} else
+		ret = NULL;
+
+	/* Pick up the branches, linking them together. */
+	br = regbranch(&flags);
+	if (br == NULL)
+		return(NULL);
+	if (ret != NULL)
+		regtail(ret, br);	/* OPEN -> first. */
+	else
+		ret = br;
+	if (!(flags&HASWIDTH))
+		*flagp &= ~HASWIDTH;
+	*flagp |= flags&SPSTART;
+	while (*regparse == '|' || *regparse == '\n') {
+		regparse++;
+		br = regbranch(&flags);
+		if (br == NULL)
+			return(NULL);
+		regtail(ret, br);	/* BRANCH -> BRANCH. */
+		if (!(flags&HASWIDTH))
+			*flagp &= ~HASWIDTH;
+		*flagp |= flags&SPSTART;
+	}
+
+	/* Make a closing node, and hook it on the end. */
+	ender = regnode((paren) ? CLOSE+parno : END);	
+	regtail(ret, ender);
+
+	/* Hook the tails of the branches to the closing node. */
+	for (br = ret; br != NULL; br = regnext(br))
+		regoptail(br, ender);
+
+	/* Check for proper termination. */
+	if (paren && *regparse++ != ')') {
+		FAIL("unmatched ()");
+	} else if (!paren && *regparse != '\0') {
+		if (*regparse == ')') {
+			FAIL("unmatched ()");
+		} else
+			FAIL("junk on end");	/* "Can't happen". */
+		/* NOTREACHED */
+	}
+
+	return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *
+regbranch(flagp)
+int *flagp;
+{
+	register char *ret;
+	register char *chain;
+	register char *latest;
+	int flags;
+
+	*flagp = WORST;		/* Tentatively. */
+
+	ret = regnode(BRANCH);
+	chain = NULL;
+	while (*regparse != '\0' && *regparse != ')' &&
+	       *regparse != '\n' && *regparse != '|') {
+		latest = regpiece(&flags);
+		if (latest == NULL)
+			return(NULL);
+		*flagp |= flags&HASWIDTH;
+		if (chain == NULL)	/* First piece. */
+			*flagp |= flags&SPSTART;
+		else
+			regtail(chain, latest);
+		chain = latest;
+	}
+	if (chain == NULL)	/* Loop ran zero times. */
+		(void) regnode(NOTHING);
+
+	return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized:  they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *
+regpiece(flagp)
+int *flagp;
+{
+	register char *ret;
+	register char op;
+	register char *next;
+	int flags;
+
+	ret = regatom(&flags);
+	if (ret == NULL)
+		return(NULL);
+
+	op = *regparse;
+	if (!ISMULT(op)) {
+		*flagp = flags;
+		return(ret);
+	}
+
+	if (!(flags&HASWIDTH) && op != '?')
+		FAIL("*+ operand could be empty");
+	*flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+	if (op == '*' && (flags&SIMPLE))
+		reginsert(STAR, ret);
+	else if (op == '*') {
+		/* Emit x* as (x&|), where & means "self". */
+		reginsert(BRANCH, ret);			/* Either x */
+		regoptail(ret, regnode(BACK));		/* and loop */
+		regoptail(ret, ret);			/* back */
+		regtail(ret, regnode(BRANCH));		/* or */
+		regtail(ret, regnode(NOTHING));		/* null. */
+	} else if (op == '+' && (flags&SIMPLE))
+		reginsert(PLUS, ret);
+	else if (op == '+') {
+		/* Emit x+ as x(&|), where & means "self". */
+		next = regnode(BRANCH);			/* Either */
+		regtail(ret, next);
+		regtail(regnode(BACK), ret);		/* loop back */
+		regtail(next, regnode(BRANCH));		/* or */
+		regtail(ret, regnode(NOTHING));		/* null. */
+	} else if (op == '?') {
+		/* Emit x? as (x|) */
+		reginsert(BRANCH, ret);			/* Either x */
+		regtail(ret, regnode(BRANCH));		/* or */
+		next = regnode(NOTHING);		/* null. */
+		regtail(ret, next);
+		regoptail(ret, next);
+	}
+	regparse++;
+	if (ISMULT(*regparse))
+		FAIL("nested *?+");
+
+	return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization:  gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run.  Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *
+regatom(flagp)
+int *flagp;
+{
+	register char *ret;
+	int flags;
+
+	*flagp = WORST;		/* Tentatively. */
+
+	switch (*regparse++) {
+	/* FIXME: these chars only have meaning at beg/end of pat? */
+	case '^':
+		ret = regnode(BOL);
+		break;
+	case '$':
+		ret = regnode(EOL);
+		break;
+	case '.':
+		ret = regnode(ANY);
+		*flagp |= HASWIDTH|SIMPLE;
+		break;
+	case '[': {
+			register int class;
+			register int classend;
+
+			if (*regparse == '^') {	/* Complement of range. */
+				ret = regnode(ANYBUT);
+				regparse++;
+			} else
+				ret = regnode(ANYOF);
+			if (*regparse == ']' || *regparse == '-')
+				regc(*regparse++);
+			while (*regparse != '\0' && *regparse != ']') {
+				if (*regparse == '-') {
+					regparse++;
+					if (*regparse == ']' || *regparse == '\0')
+						regc('-');
+					else {
+						class = UCHARAT(regparse-2)+1;
+						classend = UCHARAT(regparse);
+						if (class > classend+1)
+							FAIL("invalid [] range");
+						for (; class <= classend; class++)
+							regc(class);
+						regparse++;
+					}
+				} else
+					regc(*regparse++);
+			}
+			regc('\0');
+			if (*regparse != ']')
+				FAIL("unmatched []");
+			regparse++;
+			*flagp |= HASWIDTH|SIMPLE;
+		}
+		break;
+	case '(':
+		ret = reg(1, &flags);
+		if (ret == NULL)
+			return(NULL);
+		*flagp |= flags&(HASWIDTH|SPSTART);
+		break;
+	case '\0':
+	case '|':
+	case '\n':
+	case ')':
+		FAIL("internal urp");	/* Supposed to be caught earlier. */
+		break;
+	case '?':
+	case '+':
+	case '*':
+		FAIL("?+* follows nothing");
+		break;
+	case '\\':
+		switch (*regparse++) {
+		case '\0':
+			FAIL("trailing \\");
+			break;
+		case '<':
+			ret = regnode(WORDA);
+			break;
+		case '>':
+			ret = regnode(WORDZ);
+			break;
+		/* FIXME: Someday handle \1, \2, ... */
+		default:
+			/* Handle general quoted chars in exact-match routine */
+			goto de_fault;
+		}
+		break;
+	de_fault:
+	default:
+		/*
+		 * Encode a string of characters to be matched exactly.
+		 *
+		 * This is a bit tricky due to quoted chars and due to
+		 * '*', '+', and '?' taking the SINGLE char previous
+		 * as their operand.
+		 *
+		 * On entry, the char at regparse[-1] is going to go
+		 * into the string, no matter what it is.  (It could be
+		 * following a \ if we are entered from the '\' case.)
+		 * 
+		 * Basic idea is to pick up a good char in  ch  and
+		 * examine the next char.  If it's *+? then we twiddle.
+		 * If it's \ then we frozzle.  If it's other magic char
+		 * we push  ch  and terminate the string.  If none of the
+		 * above, we push  ch  on the string and go around again.
+		 *
+		 *  regprev  is used to remember where "the current char"
+		 * starts in the string, if due to a *+? we need to back
+		 * up and put the current char in a separate, 1-char, string.
+		 * When  regprev  is NULL,  ch  is the only char in the
+		 * string; this is used in *+? handling, and in setting
+		 * flags |= SIMPLE at the end.
+		 */
+		{
+			char *regprev;
+			register char ch;
+
+			regparse--;			/* Look at cur char */
+			ret = regnode(EXACTLY);
+			for ( regprev = 0 ; ; ) {
+				ch = *regparse++;	/* Get current char */
+				switch (*regparse) {	/* look at next one */
+
+				default:
+					regc(ch);	/* Add cur to string */
+					break;
+
+				case '.': case '[': case '(':
+				case ')': case '|': case '\n':
+				case '$': case '^':
+				case '\0':
+				/* FIXME, $ and ^ should not always be magic */
+				magic:
+					regc(ch);	/* dump cur char */
+					goto done;	/* and we are done */
+
+				case '?': case '+': case '*':
+					if (!regprev) 	/* If just ch in str, */
+						goto magic;	/* use it */
+					/* End mult-char string one early */
+					regparse = regprev; /* Back up parse */
+					goto done;
+
+				case '\\':
+					regc(ch);	/* Cur char OK */
+					switch (regparse[1]){ /* Look after \ */
+					case '\0':
+					case '<':
+					case '>':
+					/* FIXME: Someday handle \1, \2, ... */
+						goto done; /* Not quoted */
+					default:
+						/* Backup point is \, scan							 * point is after it. */
+						regprev = regparse;
+						regparse++; 
+						continue;	/* NOT break; */
+					}
+				}
+				regprev = regparse;	/* Set backup point */
+			}
+		done:
+			regc('\0');
+			*flagp |= HASWIDTH;
+			if (!regprev)		/* One char? */
+				*flagp |= SIMPLE;
+		}
+		break;
+	}
+
+	return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char *			/* Location. */
+regnode(op)
+char op;
+{
+	register char *ret;
+	register char *ptr;
+
+	ret = regcode;
+	if (ret == &regdummy) {
+		regsize += 3;
+		return(ret);
+	}
+
+	ptr = ret;
+	*ptr++ = op;
+	*ptr++ = '\0';		/* Null "next" pointer. */
+	*ptr++ = '\0';
+	regcode = ptr;
+
+	return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc(b)
+char b;
+{
+	if (regcode != &regdummy)
+		*regcode++ = b;
+	else
+		regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(op, opnd)
+char op;
+char *opnd;
+{
+	register char *src;
+	register char *dst;
+	register char *place;
+
+	if (regcode == &regdummy) {
+		regsize += 3;
+		return;
+	}
+
+	src = regcode;
+	regcode += 3;
+	dst = regcode;
+	while (src > opnd)
+		*--dst = *--src;
+
+	place = opnd;		/* Op node, where operand used to be. */
+	*place++ = op;
+	*place++ = '\0';
+	*place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(p, val)
+char *p;
+char *val;
+{
+	register char *scan;
+	register char *temp;
+	register int offset;
+
+	if (p == &regdummy)
+		return;
+
+	/* Find last node. */
+	scan = p;
+	for (;;) {
+		temp = regnext(scan);
+		if (temp == NULL)
+			break;
+		scan = temp;
+	}
+
+	if (OP(scan) == BACK)
+		offset = scan - val;
+	else
+		offset = val - scan;
+	*(scan+1) = (offset>>8)&0377;
+	*(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void
+regoptail(p, val)
+char *p;
+char *val;
+{
+	/* "Operandless" and "op != BRANCH" are synonymous in practice. */
+	if (p == NULL || p == &regdummy || OP(p) != BRANCH)
+		return;
+	regtail(OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+/*
+ * Global work variables for regexec().
+ */
+static char *reginput;		/* String-input pointer. */
+static char *regbol;		/* Beginning of input, for ^ check. */
+static char **regstartp;	/* Pointer to startp array. */
+static char **regendp;		/* Ditto for endp. */
+
+/*
+ * Forwards.
+ */
+STATIC int regtry();
+STATIC int regmatch();
+STATIC int regrepeat();
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop();
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(prog, string)
+register const regexp *prog;
+register const char *string;
+{
+	register char *s;
+	extern char *strchr();
+
+	/* Be paranoid... */
+	if (prog == NULL || string == NULL) {
+		regerror("NULL parameter");
+		return(0);
+	}
+
+	/* Check validity of program. */
+	if (UCHARAT(prog->program) != MAGIC) {
+		regerror("corrupted program");
+		return(0);
+	}
+
+	/* If there is a "must appear" string, look for it. */
+	if (prog->regmust != NULL) {
+		s = (char *)string;
+		while ((s = strchr(s, prog->regmust[0])) != NULL) {
+			if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+				break;	/* Found it. */
+			s++;
+		}
+		if (s == NULL)	/* Not present. */
+			return(0);
+	}
+
+	/* Mark beginning of line for ^ . */
+	regbol = (char *)string;
+
+	/* Simplest case:  anchored match need be tried only once. */
+	if (prog->reganch)
+		return(regtry(prog, string));
+
+	/* Messy cases:  unanchored match. */
+	s = (char *)string;
+	if (prog->regstart != '\0')
+		/* We know what char it must start with. */
+		while ((s = strchr(s, prog->regstart)) != NULL) {
+			if (regtry(prog, s))
+				return(1);
+			s++;
+		}
+	else
+		/* We don't -- general case. */
+		do {
+			if (regtry(prog, s))
+				return(1);
+		} while (*s++ != '\0');
+
+	/* Failure. */
+	return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+static int			/* 0 failure, 1 success */
+regtry(prog, string)
+regexp *prog;
+char *string;
+{
+	register int i;
+	register char **sp;
+	register char **ep;
+
+	reginput = string;
+	regstartp = prog->startp;
+	regendp = prog->endp;
+
+	sp = prog->startp;
+	ep = prog->endp;
+	for (i = NSUBEXP; i > 0; i--) {
+		*sp++ = NULL;
+		*ep++ = NULL;
+	}
+	if (regmatch(prog->program + 1)) {
+		prog->startp[0] = string;
+		prog->endp[0] = reginput;
+		return(1);
+	} else
+		return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple:  check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly.  In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int			/* 0 failure, 1 success */
+regmatch(prog)
+char *prog;
+{
+	register char *scan;	/* Current node. */
+	char *next;		/* Next node. */
+	extern char *strchr();
+
+	scan = prog;
+#ifdef DEBUG
+	if (scan != NULL && regnarrate)
+		fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+	while (scan != NULL) {
+#ifdef DEBUG
+		if (regnarrate)
+			fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+		next = regnext(scan);
+
+		switch (OP(scan)) {
+		case BOL:
+			if (reginput != regbol)
+				return(0);
+			break;
+		case EOL:
+			if (*reginput != '\0')
+				return(0);
+			break;
+		case WORDA:
+			/* Must be looking at a letter, digit, or _ */
+			if ((!isalnum(*reginput)) && *reginput != '_')
+				return(0);
+			/* Prev must be BOL or nonword */
+			if (reginput > regbol &&
+			    (isalnum(reginput[-1]) || reginput[-1] == '_'))
+				return(0);
+			break;
+		case WORDZ:
+			/* Must be looking at non letter, digit, or _ */
+			if (isalnum(*reginput) || *reginput == '_')
+				return(0);
+			/* We don't care what the previous char was */
+			break;
+		case ANY:
+			if (*reginput == '\0')
+				return(0);
+			reginput++;
+			break;
+		case EXACTLY: {
+				register int len;
+				register char *opnd;
+
+				opnd = OPERAND(scan);
+				/* Inline the first character, for speed. */
+				if (*opnd != *reginput)
+					return(0);
+				len = strlen(opnd);
+				if (len > 1 && strncmp(opnd, reginput, len) != 0)
+					return(0);
+				reginput += len;
+			}
+			break;
+		case ANYOF:
+ 			if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
+				return(0);
+			reginput++;
+			break;
+		case ANYBUT:
+ 			if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
+				return(0);
+			reginput++;
+			break;
+		case NOTHING:
+			break;
+		case BACK:
+			break;
+		case OPEN+1:
+		case OPEN+2:
+		case OPEN+3:
+		case OPEN+4:
+		case OPEN+5:
+		case OPEN+6:
+		case OPEN+7:
+		case OPEN+8:
+		case OPEN+9: {
+				register int no;
+				register char *save;
+
+				no = OP(scan) - OPEN;
+				save = reginput;
+
+				if (regmatch(next)) {
+					/*
+					 * Don't set startp if some later
+					 * invocation of the same parentheses
+					 * already has.
+					 */
+					if (regstartp[no] == NULL)
+						regstartp[no] = save;
+					return(1);
+				} else
+					return(0);
+			}
+			break;
+		case CLOSE+1:
+		case CLOSE+2:
+		case CLOSE+3:
+		case CLOSE+4:
+		case CLOSE+5:
+		case CLOSE+6:
+		case CLOSE+7:
+		case CLOSE+8:
+		case CLOSE+9: {
+				register int no;
+				register char *save;
+
+				no = OP(scan) - CLOSE;
+				save = reginput;
+
+				if (regmatch(next)) {
+					/*
+					 * Don't set endp if some later
+					 * invocation of the same parentheses
+					 * already has.
+					 */
+					if (regendp[no] == NULL)
+						regendp[no] = save;
+					return(1);
+				} else
+					return(0);
+			}
+			break;
+		case BRANCH: {
+				register char *save;
+
+				if (OP(next) != BRANCH)		/* No choice. */
+					next = OPERAND(scan);	/* Avoid recursion. */
+				else {
+					do {
+						save = reginput;
+						if (regmatch(OPERAND(scan)))
+							return(1);
+						reginput = save;
+						scan = regnext(scan);
+					} while (scan != NULL && OP(scan) == BRANCH);
+					return(0);
+					/* NOTREACHED */
+				}
+			}
+			break;
+		case STAR:
+		case PLUS: {
+				register char nextch;
+				register int no;
+				register char *save;
+				register int min;
+
+				/*
+				 * Lookahead to avoid useless match attempts
+				 * when we know what character comes next.
+				 */
+				nextch = '\0';
+				if (OP(next) == EXACTLY)
+					nextch = *OPERAND(next);
+				min = (OP(scan) == STAR) ? 0 : 1;
+				save = reginput;
+				no = regrepeat(OPERAND(scan));
+				while (no >= min) {
+					/* If it could work, try it. */
+					if (nextch == '\0' || *reginput == nextch)
+						if (regmatch(next))
+							return(1);
+					/* Couldn't or didn't -- back up. */
+					no--;
+					reginput = save + no;
+				}
+				return(0);
+			}
+			break;
+		case END:
+			return(1);	/* Success! */
+			break;
+		default:
+			regerror("memory corruption");
+			return(0);
+			break;
+		}
+
+		scan = next;
+	}
+
+	/*
+	 * We get here only if there's trouble -- normally "case END" is
+	 * the terminating point.
+	 */
+	regerror("corrupted pointers");
+	return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat(p)
+char *p;
+{
+	register int count = 0;
+	register char *scan;
+	register char *opnd;
+
+	scan = reginput;
+	opnd = OPERAND(p);
+	switch (OP(p)) {
+	case ANY:
+		count = strlen(scan);
+		scan += count;
+		break;
+	case EXACTLY:
+		while (*opnd == *scan) {
+			count++;
+			scan++;
+		}
+		break;
+	case ANYOF:
+		while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+			count++;
+			scan++;
+		}
+		break;
+	case ANYBUT:
+		while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+			count++;
+			scan++;
+		}
+		break;
+	default:		/* Oh dear.  Called inappropriately. */
+		regerror("internal foulup");
+		count = 0;	/* Best compromise. */
+		break;
+	}
+	reginput = scan;
+
+	return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char *
+regnext(p)
+register char *p;
+{
+	register int offset;
+
+	if (p == &regdummy)
+		return(NULL);
+
+	offset = NEXT(p);
+	if (offset == 0)
+		return(NULL);
+
+	if (OP(p) == BACK)
+		return(p-offset);
+	else
+		return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump(r)
+regexp *r;
+{
+	register char *s;
+	register char op = EXACTLY;	/* Arbitrary non-END op. */
+	register char *next;
+	extern char *strchr();
+
+
+	s = r->program + 1;
+	while (op != END) {	/* While that wasn't END last time... */
+		op = OP(s);
+		printf("%2d%s", s-r->program, regprop(s));	/* Where, what. */
+		next = regnext(s);
+		if (next == NULL)		/* Next ptr. */
+			printf("(0)");
+		else 
+			printf("(%d)", (s-r->program)+(next-s));
+		s += 3;
+		if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+			/* Literal string, where present. */
+			while (*s != '\0') {
+				putchar(*s);
+				s++;
+			}
+			s++;
+		}
+		putchar('\n');
+	}
+
+	/* Header fields of interest. */
+	if (r->regstart != '\0')
+		printf("start `%c' ", r->regstart);
+	if (r->reganch)
+		printf("anchored ");
+	if (r->regmust != NULL)
+		printf("must have \"%s\"", r->regmust);
+	printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop(op)
+char *op;
+{
+	register char *p;
+	static char buf[50];
+
+	(void) strcpy(buf, ":");
+
+	switch (OP(op)) {
+	case BOL:
+		p = "BOL";
+		break;
+	case EOL:
+		p = "EOL";
+		break;
+	case ANY:
+		p = "ANY";
+		break;
+	case ANYOF:
+		p = "ANYOF";
+		break;
+	case ANYBUT:
+		p = "ANYBUT";
+		break;
+	case BRANCH:
+		p = "BRANCH";
+		break;
+	case EXACTLY:
+		p = "EXACTLY";
+		break;
+	case NOTHING:
+		p = "NOTHING";
+		break;
+	case BACK:
+		p = "BACK";
+		break;
+	case END:
+		p = "END";
+		break;
+	case OPEN+1:
+	case OPEN+2:
+	case OPEN+3:
+	case OPEN+4:
+	case OPEN+5:
+	case OPEN+6:
+	case OPEN+7:
+	case OPEN+8:
+	case OPEN+9:
+		sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
+		p = NULL;
+		break;
+	case CLOSE+1:
+	case CLOSE+2:
+	case CLOSE+3:
+	case CLOSE+4:
+	case CLOSE+5:
+	case CLOSE+6:
+	case CLOSE+7:
+	case CLOSE+8:
+	case CLOSE+9:
+		sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+		p = NULL;
+		break;
+	case STAR:
+		p = "STAR";
+		break;
+	case PLUS:
+		p = "PLUS";
+		break;
+	case WORDA:
+		p = "WORDA";
+		break;
+	case WORDZ:
+		p = "WORDZ";
+		break;
+	default:
+		regerror("corrupted opcode");
+		break;
+	}
+	if (p != NULL)
+		(void) strcat(buf, p);
+	return(buf);
+}
+#endif
+
+/*
+ * The following is provided for those people who do not have strcspn() in
+ * their C libraries.  They should get off their butts and do something
+ * about it; at least one public-domain implementation of those (highly
+ * useful) string routines has been published on Usenet.
+ */
+#ifdef STRCSPN
+/*
+ * strcspn - find length of initial segment of s1 consisting entirely
+ * of characters not from s2
+ */
+
+static int
+strcspn(s1, s2)
+char *s1;
+char *s2;
+{
+	register char *scan1;
+	register char *scan2;
+	register int count;
+
+	count = 0;
+	for (scan1 = s1; *scan1 != '\0'; scan1++) {
+		for (scan2 = s2; *scan2 != '\0';)	/* ++ moved down. */
+			if (*scan1 == *scan2++)
+				return(count);
+		count++;
+	}
+	return(count);
+}
+#endif
Index: trunk/src/emx/src/regexp/regexp.h
===================================================================
--- trunk/src/emx/src/regexp/regexp.h	(revision 18)
+++ trunk/src/emx/src/regexp/regexp.h	(revision 18)
@@ -0,0 +1,21 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#define NSUBEXP  10
+typedef struct regexp {
+	char *startp[NSUBEXP];
+	char *endp[NSUBEXP];
+	char regstart;		/* Internal use only. */
+	char reganch;		/* Internal use only. */
+	char *regmust;		/* Internal use only. */
+	int regmlen;		/* Internal use only. */
+	char program[1];	/* Unwarranted chumminess with compiler. */
+} regexp;
+
+extern regexp *regcomp();
+extern int regexec();
+extern void regsub();
+extern void regerror();
Index: trunk/src/emx/src/regexp/regmagic.h
===================================================================
--- trunk/src/emx/src/regexp/regmagic.h	(revision 18)
+++ trunk/src/emx/src/regexp/regmagic.h	(revision 18)
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define	MAGIC	0234
Index: trunk/src/emx/src/regexp/regsub.c
===================================================================
--- trunk/src/emx/src/regexp/regsub.c	(revision 18)
+++ trunk/src/emx/src/regexp/regsub.c	(revision 18)
@@ -0,0 +1,81 @@
+/*
+ * regsub
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ */
+#include <regexp.h>
+#include <stdio.h>
+#include <string.h>
+#include "regmagic.h"
+
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+/*
+ - regsub - perform substitutions after a regexp match
+ */
+void
+regsub(prog, source, dest)
+const regexp *prog;
+const char *source;
+char *dest;
+{
+	register char *src;
+	register char *dst;
+	register char c;
+	register int no;
+	register int len;
+	extern char *strncpy();
+
+	if (prog == NULL || source == NULL || dest == NULL) {
+		regerror("NULL parm to regsub");
+		return;
+	}
+	if (UCHARAT(prog->program) != MAGIC) {
+		regerror("damaged regexp fed to regsub");
+		return;
+	}
+
+	src = (char *)source;
+	dst = dest;
+	while ((c = *src++) != '\0') {
+		if (c == '&')
+			no = 0;
+		else if (c == '\\' && '0' <= *src && *src <= '9')
+			no = *src++ - '0';
+		else
+			no = -1;
+ 		if (no < 0) {	/* Ordinary character. */
+ 			if (c == '\\' && (*src == '\\' || *src == '&'))
+ 				c = *src++;
+ 			*dst++ = c;
+ 		} else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+			len = prog->endp[no] - prog->startp[no];
+			(void) strncpy(dst, prog->startp[no], len);
+			dst += len;
+			if (len != 0 && *(dst-1) == '\0') {	/* strncpy hit NUL. */
+				regerror("damaged match string");
+				return;
+			}
+		}
+	}
+	*dst++ = '\0';
+}
Index: trunk/src/emx/src/utils/makefile
===================================================================
--- trunk/src/emx/src/utils/makefile	(revision 18)
+++ trunk/src/emx/src/utils/makefile	(revision 18)
@@ -0,0 +1,56 @@
+#
+# /emx/src/utils/makefile
+#
+# Copyright (c) 1994-1996 by Eberhard Mattes
+#
+# This file is part of emx.
+#
+# emx is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# emx is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with emx; see the file COPYING.  If not, write to the
+# Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+.SUFFIXES: .c .o
+
+BIN=\emx\bin\ #
+
+CC=gcc
+CFLAGS=-O -Wall -I../include
+LFLAGS=-s -Zsmall-conv
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+default:	all
+all:		updt touch
+updt:		$(BIN)updt.exe
+touch:		$(BIN)touch.exe
+
+updt.o: updt.c
+touch.o: touch.c
+
+$(BIN)touch.exe: touch.o
+	gcc $(LFLAGS) -o $(BIN)touch.exe touch.o
+
+$(BIN)updt.exe: updt.o
+	gcc $(LFLAGS) -o $(BIN)updt.exe updt.o
+
+clean:
+	-del *.o
+
+realclean: clean
+	-del $(BIN)touch.exe
+	-del $(BIN)updt.exe
+
+# End of /emx/src/utils/makefile
Index: trunk/src/emx/src/utils/touch.c
===================================================================
--- trunk/src/emx/src/utils/touch.c	(revision 18)
+++ trunk/src/emx/src/utils/touch.c	(revision 18)
@@ -0,0 +1,113 @@
+/* touch.c -- Update the time stamp of files
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <sys/types.h>
+#include <sys/utime.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <io.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#define FALSE 0
+#define TRUE  1
+
+static void usage (void)
+{
+  fputs ("Usage: touch [-c] [-r <ref_file>] <files>\n\n"
+         "Options:\n"
+         "  -c             Don't create files\n"
+         "  -r <ref_file>  Use time and date of <ref_file>\n", stderr);
+  exit (1);
+}
+
+
+int main (int argc, char *argv[])
+{
+  int c, i, h, rc;
+  int dont_create;
+  const char *ref_fname;
+  struct utimbuf *ut;
+  char *s;
+
+  _response (&argc, &argv);
+  _wildcard (&argc, &argv);
+  if (argc < 2)
+    usage ();
+  dont_create = FALSE; ref_fname = NULL; opterr = FALSE;
+  while ((c = getopt (argc, argv, "cr:")) != -1)
+    switch (c)
+      {
+      case 'c':
+        dont_create = TRUE;
+        break;
+      case 'r':
+        ref_fname = optarg;
+        break;
+      default:
+        usage ();
+      }
+  if (optind >= argc)
+    usage ();
+
+  if (ref_fname == NULL)
+    ut = NULL;
+  else
+    {
+      struct stat st;
+      static struct utimbuf ut_ref;
+
+      if (stat (ref_fname, &st) != 0)
+        {
+          perror (ref_fname);
+          exit (1);
+        }
+      ut_ref.actime = st.st_atime;
+      ut_ref.modtime = st.st_mtime;
+      ut = &ut_ref;
+    }
+
+  rc = 0;
+  for (i = optind; i < argc; ++i)
+    {
+      s = argv[i];
+      if (utime (s, ut) != 0 && !dont_create)
+        {
+          h = open (s, O_CREAT|O_EXCL|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
+          if (h < 0)
+            {
+              perror (s);
+              rc = 1;
+            }
+          else
+            {
+              close (h);
+              if (ut != NULL && utime (s, ut) != 0)
+                {
+                  perror (s);
+                  rc = 1;
+                }
+            }
+        }
+    }
+  return rc;
+}
Index: trunk/src/emx/src/utils/updt.c
===================================================================
--- trunk/src/emx/src/utils/updt.c	(revision 18)
+++ trunk/src/emx/src/utils/updt.c	(revision 18)
@@ -0,0 +1,152 @@
+/* updt.c -- Copy a file if required
+   Copyright (c) 1994-1995 by Eberhard Mattes
+
+This file is part of emx.
+
+emx is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+emx is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with emx; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define FALSE 0
+#define TRUE  1
+
+int main (int argc, char *argv[]);
+static void usage (void);
+
+static void usage (void)
+{
+  fputs ("Usage: updt [-t] [-v] <source_file> <target_file>\n", stderr);
+  exit (1);
+}
+
+
+int main (int argc, char *argv[])
+{
+  FILE *source_file, *target_file;
+  char *source_fname, *target_fname;
+  struct stat source_stat, target_stat;
+  int c1, c2, c, opt_t, opt_v;
+
+  opt_t = FALSE; opt_v = FALSE;
+  while ((c = getopt (argc, argv, "tv")) != EOF)
+    {
+      switch (c)
+        {
+        case 't':
+          opt_t = TRUE;
+          break;
+        case 'v':
+          opt_v = TRUE;
+          break;
+        default:
+          usage();
+        }
+    }
+  if (argc - optind != 2)
+    usage ();
+  source_fname = argv[optind+0];
+  target_fname = argv[optind+1];
+  source_file = fopen (source_fname, "rb");
+  if (source_file == NULL)
+    {
+      fprintf (stderr, "updt: cannot open source file `%s'\n", source_fname);
+      return 1;
+    }
+  target_file = fopen (target_fname, "rb");
+  if (target_file != NULL)
+    {
+      if (opt_t)
+        {
+          if (stat (source_fname, &source_stat) != 0)
+            {
+              fprintf (stderr, "updt: cannot access `%s'\n", source_fname);
+              return 1;
+            }
+          if (stat (target_fname, &target_stat) != 0)
+            {
+              fprintf (stderr, "updt: cannot access `%s'\n", target_fname);
+              return 1;
+            }
+          if (target_stat.st_mtime >= source_stat.st_mtime)
+            {
+              if (opt_v)
+                fputs ("updt: source not newer than target "
+                       "-- not copying\n", stderr);
+              return 0;
+            }
+          if (opt_v)
+            fputs ("updt: source newer than target "
+                   "-- copying\n", stderr);
+        }
+      else
+        {
+          for (;;)
+            {
+              c1 = getc (source_file);
+              c2 = getc (target_file);
+              if (c1 != c2 || c1 == EOF)
+                break;
+            }
+          if (c1 == EOF && c2 == EOF && !ferror (source_file) &&
+              !ferror (target_file))
+            {
+              if (opt_v)
+                fputs ("updt: files match -- not copying\n", stderr);
+              return 0;
+            }
+          if (opt_v)
+            fputs ("updt: files don't match -- copying\n", stderr);
+        }
+      (void)fclose (target_file);
+    }
+  else if (opt_v)
+    fputs ("updt: target does not exist -- copying\n", stderr);
+  rewind (source_file);
+  target_file = fopen (target_fname, "wb");
+  if (target_file == NULL)
+    {
+      fprintf (stderr, "updt: cannot open target file `%s'\n", target_fname);
+      return 1;
+    }
+  for (;;)
+    {
+      c1 = getc (source_file);
+      if (c1 == EOF)
+        break;
+      if (putc (c1, target_file) == EOF)
+        break;
+    }
+  if (ferror (source_file) || fclose (source_file) != 0)
+    {
+      fprintf (stderr, "updt: cannot read source file `%s'\n", source_fname);
+      return 1;
+    }
+  if (ferror (target_file) || fflush (target_file) != 0 ||
+      fclose (target_file) != 0)
+    {
+      fprintf (stderr, "updt: cannot write target file `%s'\n",
+               target_fname);
+      return 1;
+    }
+  return 0;
+}
